# -*- coding: utf-8 -*- """ IRC Bot Plugins: Join, Part, Nickname, Message, Topic, Invite, Voice, Kick, Ban, Op, and Mute Management This module provides multiple IRC bot plugins: 1. `JoinPlugin`: Handles joining specific channels. 2. `PartPlugin`: Handles leaving specific channels. 3. `NickPlugin`: Handles changing the bot's nickname. 4. `MessagePlugin`: Handles sending messages. 5. `TopicPlugin`: Handles changing the channel topic. 6. `InvitePlugin`: Handles inviting users to a channel. 7. `VoicePlugin`: Handles granting and revoking voice (+v) privileges. 8. `KickPlugin`: Handles kicking users from the channel. 9. `BanPlugin`: Handles banning and unbanning users. 10. `OpPlugin`: Handles granting and removing operator privileges. 11. `MutePlugin`: Handles muting and unmuting users. All commands require **admin** permissions. Features: - Join and leave specific channels. - Change the bot's nickname. - Send messages to users or channels. - Change the channel topic. - Invite users to channels. - Voice a single user or all users in a channel. - Devoice a single user or all users. - Kick users with optional reasons. - Ban and unban users. - Grant and remove operator privileges. - Mute and unmute users. Author: Zodiac (Modified for verbose logging by bot.log) """ import asyncio import irc3 from irc3.plugins.command import command @irc3.plugin class JoinPlugin: """A plugin to join specific IRC channels.""" def __init__(self, bot): """ Initialize the JoinPlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def join(self, mask, target, args): """ Join a specific channel. Usage: %%join """ channel = args.get('') if channel: self.bot.log.info("Request to join channel %s", channel) await self.join_channel(channel) async def join_channel(self, channel): """ Join a specific channel. Args: channel (str): The IRC channel to join. """ self.bot.log.info("Joining channel %s", channel) self.bot.send(f'JOIN {channel}') @irc3.plugin class PartPlugin: """A plugin to leave specific IRC channels.""" def __init__(self, bot): """ Initialize the PartPlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def part(self, mask, target, args): """ Leave a specific channel. Usage: %%part """ channel = args.get('') if channel: self.bot.log.info("Request to leave channel %s", channel) await self.part_channel(channel) async def part_channel(self, channel): """ Leave a specific channel. Args: channel (str): The IRC channel to leave. """ self.bot.log.info("Leaving channel %s", channel) self.bot.send(f'PART {channel}') @irc3.plugin class NickPlugin: """A plugin to change the bot's nickname.""" def __init__(self, bot): """ Initialize the NickPlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def nick(self, mask, target, args): """ Change the bot's nickname. Usage: %%nick """ newnick = args.get('') if newnick: self.bot.log.info("Request to change nickname to %s", newnick) await self.change_nick(newnick) async def change_nick(self, newnick): """ Change the bot's nickname. Args: newnick (str): The new nickname for the bot. """ self.bot.log.info("Changing nickname to %s", newnick) self.bot.send(f'NICK {newnick}') @irc3.plugin class MessagePlugin: """A plugin to send messages to users or channels.""" def __init__(self, bot): """ Initialize the MessagePlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def msg(self, mask, target, args): """ Send a message to a user or channel. Usage: %%msg """ msg_target = args.get('') message = args.get('') if msg_target and message: self.bot.log.info("Request to send message to %s: %s", msg_target, message) await self.send_message(msg_target, message) async def send_message(self, msg_target, message): """ Send a message to a user or channel. Args: msg_target (str): The target user or channel. message (str): The message to send. """ self.bot.log.info("Sending message to %s: %s", msg_target, message) self.bot.send(f'PRIVMSG {msg_target} :{message}') @irc3.plugin class TopicPlugin: """A plugin to change the topic of an IRC channel.""" def __init__(self, bot): """ Initialize the TopicPlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def topic(self, mask, target, args): """ Change the topic of a channel. Usage: %%topic """ newtopic = args.get('') if newtopic: self.bot.log.info("Request to change topic to %s in %s", newtopic, target) await self.change_topic(target, newtopic) async def change_topic(self, target, newtopic): """ Change the topic of a channel. Args: target (str): The IRC channel. newtopic (str): The new topic for the channel. """ self.bot.log.info("Changing topic in channel %s to %s", target, newtopic) self.bot.send(f'TOPIC {target} :{newtopic}') @irc3.plugin class InvitePlugin: """A plugin to invite users to an IRC channel.""" def __init__(self, bot): """ Initialize the InvitePlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def invite(self, mask, target, args): """ Invite a user to a channel. Usage: %%invite """ nick = args.get('') channel = args.get('') if nick and channel: self.bot.log.info("Request to invite %s to channel %s", nick, channel) await self.invite_user(nick, channel) async def invite_user(self, nick, channel): """ Invite a user to a channel. Args: nick (str): The nickname of the user. channel (str): The IRC channel. """ self.bot.log.info("Inviting user %s to channel %s", nick, channel) self.bot.send(f'INVITE {nick} {channel}') @irc3.plugin class VoicePlugin: """A plugin to manage voice (+v) privileges in an IRC channel.""" def __init__(self, bot): """ Initialize the VoicePlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def voice(self, mask, target, args): """ Grant voice to a specific user or all users in the channel. Usage: %%voice [] """ nick = args.get('') if nick: self.bot.log.info("Request to grant voice to %s in %s", nick, target) await self.give_voice(target, nick) else: self.bot.log.info("Request to grant voice to all users in %s", target) await self.give_voice_all(target) @command(permission='admin') async def devoice(self, mask, target, args): """ Remove voice from a specific user or all users in the channel. Usage: %%devoice [] """ nick = args.get('') if nick: self.bot.log.info("Request to remove voice from %s in %s", nick, target) await self.remove_voice(target, nick) else: self.bot.log.info("Request to remove voice from all users in %s", target) await self.remove_voice_all(target) async def give_voice(self, target, nick): """ Grant voice to a specific user. Args: target (str): The IRC channel. nick (str): The nickname of the user. """ self.bot.log.info("Granting voice to user %s in channel %s", nick, target) self.bot.send(f'MODE {target} +v {nick}') async def remove_voice(self, target, nick): """ Remove voice from a specific user. Args: target (str): The IRC channel. nick (str): The nickname of the user. """ self.bot.log.info("Removing voice from user %s in channel %s", nick, target) self.bot.send(f'MODE {target} -v {nick}') async def give_voice_all(self, target): """ Grant voice to all users in the channel who do not already have voice or op privileges. Args: target (str): The IRC channel. """ self.bot.log.info("Granting voice to all non-voiced users in channel %s", target) result = await self.bot.async_cmds.names(target) for user in result['names']: nick = user.get('nick') modes = user.get('modes', '') # Check if the user already has op or voice based on the modes field. if modes.endswith('@') or modes.endswith('+'): continue self.bot.log.info("Granting voice to user %s", nick) self.bot.send(f'MODE {target} +v {nick}') await asyncio.sleep(0.07) # Prevent server flooding async def remove_voice_all(self, target): """ Remove voice from all users in the channel who currently have voice privileges. Args: target (str): The IRC channel. """ self.bot.log.info("Removing voice from all voiced users in channel %s", target) result = await self.bot.async_cmds.names(target) for user in result['names']: nick = user.get('nick') modes = user.get('modes', '') # Remove voice only if the user has a voice prefix (and not op) if modes.endswith('+'): self.bot.log.info("Removing voice from user %s", nick) self.bot.send(f'MODE {target} -v {nick}') await asyncio.sleep(0.07) # Prevent server flooding @irc3.plugin class KickPlugin: """A plugin to kick users from an IRC channel.""" def __init__(self, bot): """ Initialize the KickPlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def kick(self, mask, target, args): """ Kick a specific user from the channel with an optional reason. Usage: %%kick [] """ nick = args.get('') reason = args.get('') or 'Kicked by admin' if nick: self.bot.log.info("Request to kick user %s from channel %s for reason: %s", nick, target, reason) await self.kick_user(target, nick, reason) async def kick_user(self, target, nick, reason): """ Kick a user from the channel using ChanServ. Args: target (str): The IRC channel. nick (str): The nickname of the user. reason (str): The reason for kicking the user. """ self.bot.log.info("Kicking user %s from channel %s", nick, target) self.bot.send(f'PRIVMSG ChanServ :KICK {target} {nick} {reason}') @irc3.plugin class BanPlugin: """A plugin to ban and unban users in an IRC channel.""" def __init__(self, bot): """ Initialize the BanPlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def ban(self, mask, target, args): """ Ban a specific user from the channel. Usage: %%ban """ nick = args.get('') if nick: self.bot.log.info("Request to ban user %s from channel %s", nick, target) await self.ban_user(target, nick) @command(permission='admin') async def unban(self, mask, target, args): """ Unban a specific user from the channel. Usage: %%unban """ nick = args.get('') if nick: self.bot.log.info("Request to unban user %s from channel %s", nick, target) await self.unban_user(target, nick) async def ban_user(self, target, nick): """ Ban a specific user from the channel. Args: target (str): The IRC channel. nick (str): The nickname of the user. """ self.bot.log.info("Banning user %s in channel %s", nick, target) self.bot.send(f'MODE {target} +b {nick}') async def unban_user(self, target, nick): """ Unban a specific user from the channel. Args: target (str): The IRC channel. nick (str): The nickname of the user. """ self.bot.log.info("Unbanning user %s in channel %s", nick, target) self.bot.send(f'MODE {target} -b {nick}') @irc3.plugin class OpPlugin: """A plugin to grant and remove operator privileges in an IRC channel.""" def __init__(self, bot): """ Initialize the OpPlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def op(self, mask, target, args): """ Grant operator privileges to a specific user. Usage: %%op """ nick = args.get('') if nick: self.bot.log.info("Request to grant operator privileges to %s in %s", nick, target) await self.give_op(target, nick) @command(permission='admin') async def deop(self, mask, target, args): """ Remove operator privileges from a specific user. Usage: %%deop """ nick = args.get('') if nick: self.bot.log.info("Request to remove operator privileges from %s in %s", nick, target) await self.remove_op(target, nick) async def give_op(self, target, nick): """ Grant operator privileges to a specific user. Args: target (str): The IRC channel. nick (str): The nickname of the user. """ self.bot.log.info("Granting operator privileges to user %s in channel %s", nick, target) self.bot.send(f'MODE {target} +o {nick}') async def remove_op(self, target, nick): """ Remove operator privileges from a specific user. Args: target (str): The IRC channel. nick (str): The nickname of the user. """ self.bot.log.info("Removing operator privileges from user %s in channel %s", nick, target) self.bot.send(f'MODE {target} -o {nick}') @irc3.plugin class MutePlugin: """A plugin to mute and unmute users in an IRC channel.""" def __init__(self, bot): """ Initialize the MutePlugin. Args: bot (irc3.IrcBot): The IRC bot instance. """ self.bot = bot @command(permission='admin') async def mute(self, mask, target, args): """ Mute a specific user in the channel. Usage: %%mute """ nick = args.get('') if nick: self.bot.log.info("Request to mute user %s in channel %s", nick, target) await self.mute_user(target, nick) @command(permission='admin') async def unmute(self, mask, target, args): """ Unmute a specific user in the channel. Usage: %%unmute """ nick = args.get('') if nick: self.bot.log.info("Request to unmute user %s in channel %s", nick, target) await self.unmute_user(target, nick) async def mute_user(self, target, nick): """ Mute a specific user in the channel. Args: target (str): The IRC channel. nick (str): The nickname of the user. """ self.bot.log.info("Muting user %s in channel %s", nick, target) self.bot.send(f'MODE {target} +q {nick}') async def unmute_user(self, target, nick): """ Unmute a specific user in the channel. Args: target (str): The IRC channel. nick (str): The nickname of the user. """ self.bot.log.info("Unmuting user %s in channel %s", nick, target) self.bot.send(f'MODE {target} -q {nick}')