async def badwords_output_sieve(client, server, command, args, kwargs): """Is for stopping the bot saying bad words in channel.""" if command == 'PRIVMSG': kickwords = db.get_cell(client.bot.dbs[server], 'channels', 'kickwords', 'channel', args[0])[0][0] banwords = db.get_cell(client.bot.dbs[server], 'channels', 'banwords', 'channel', args[0])[0][0] message = args[1] if kickwords: if ' ' in kickwords: kickwords = kickwords.split() else: kickwords = [kickwords] for word in kickwords: if word in message: message = message.replace(word, '[censored]').strip() if banwords: if ' ' in banwords: banwords = banwords.split() else: banwords = [banwords] for word in banwords: word = ' '.join(word.split(':')[0:-1]) if word in message: message = message.replace(word, '[censored]').strip() args = (args[0], message) return command, args, kwargs
async def flood_input_sieve(client, data): #Is for handling users who are flooding in the channel. conn = client.bot.dbs[data.server] isadmin = await user.is_admin(client, conn, data.nickname, data.mask) if await user.is_gadmin(client, data.server, data.mask): return data if isadmin or not data.target: return data if data.target[0] != '#': return data db.add_column(conn, 'channels', 'msgflood') db.add_column(conn, 'channels', 'cmdflood') prefix = db.get_cell(conn, 'channels', 'commandprefix', 'channel', data.target)[0][0] msgflood = db.get_cell(conn, 'channels', 'msgflood', 'channel', data.target)[0][0] cmdflood = db.get_cell(conn, 'channels', 'cmdflood', 'channel', data.target)[0][0] if msgflood: msgflood = msgflood.split() asyncio.create_task(_detect_flood(client, data, msgflood, 'msg')) if cmdflood and data.command and prefix: if data.command[0] == prefix: if cmdflood: cmdflood = cmdflood.split() asyncio.create_task( _detect_flood(client, data, cmdflood, 'cmd')) return data
async def _update_user(self, user: str, mask: str) -> None: """ Is used to update the users db information when they speak. Runs before sieves so ignored users are in the db. If user not in db, adds them, otherwise update nick, or mask if needed. """ if user == self.nickname: return conn: Connection = self.bot.dbs[self.server_tag] db_mask: DBResult = db.get_cell(conn, 'users', 'mask', 'nick', user) db_nick: DBResult = db.get_cell(conn, 'users', 'nick', 'mask', mask) if not db_mask or not db_nick: db.add_user(conn, user, mask) return else: same_mask = (db_mask[0][0] == mask) same_nick = (db_nick[0][0] == user) # if mask changed if not same_mask and same_nick: db.set_cell(conn, 'users', 'mask', mask, 'nick', user) # if nick changed if same_mask and not same_nick: db.set_cell(conn, 'users', 'nick', user, 'mask', mask)
async def c_badwords(client, data): """ .badwords <list/kick/ban> [add/del] [word] -- List or add kick and ban words, for ban words do word:seconds or it will default to 1 minute. """ kickwords = db.get_cell(client.bot.dbs[data.server], 'channels', 'kickwords', 'channel', data.target) banwords = db.get_cell(client.bot.dbs[data.server], 'channels', 'banwords', 'channel', data.target) if ' ' in data.message: message = data.message.split(' ') else: message = [data.message] tooshort = (len(message) < 3 and message[0] != 'list') if message[0] not in ['list', 'ban', 'kick'] or tooshort: doc = ' '.join(c_badwords.__doc__.split()) asyncio.create_task(client.notice(data.nickname, f'{doc}')) return if message[0] == 'list': if not kickwords or not kickwords[0][0]: asyncio.create_task( client.notice(data.nickname, 'No words in kick list.')) else: asyncio.create_task( client.notice(data.nickname, f'Kickwords: {kickwords[0][0]}.')) if not banwords or not banwords[0][0]: asyncio.create_task( client.notice(data.nickname, 'No words in ban list.')) else: asyncio.create_task( client.notice(data.nickname, f'Banwords: {banwords[0][0]}.')) return if message[1] == 'add': if message[0] == 'ban': await _add_words(client, data, client.bot.dbs[data.server], banwords, message[2:], True) else: await _add_words(client, data, client.bot.dbs[data.server], kickwords, message[2:]) elif message[1] == 'del': if message[0] == 'ban': await _del_words(client, data, client.bot.dbs[data.server], banwords, message[2:], ban=True) else: await _del_words(client, data, client.bot.dbs[data.server], kickwords, message[2:]) else: doc = ' '.join(c_badwords.__doc__.split()) asyncio.create_task(client.notice(data.nickname, f'{doc}'))
async def c_admins(client, data): """ .admins [list/add/del] [user/mask] -- Lists, adds or deletes users or masks from admins. """ message = data.split_message conn = client.bot.dbs[data.server] admins = await botu.make_list( db.get_cell(conn, 'channels', 'admins', 'channel', data.target)[0][0]) if len(message) > 1: masks = await user.parse_masks(client, conn, ' '.join(message[1:])) if message[0] == 'del': for mask in masks: asyncio.create_task( botu.del_from_channels(client, data, conn, 'admins', mask, admins, f'Removing {mask} from admins.', f'{mask} is not an admin.')) elif message[0] == 'add': for mask in masks: asyncio.create_task( botu.add_to_channels(client, data, conn, 'admins', mask, admins, f'Adding {mask} to admins.', f'{mask} is already an admin.')) elif message[0] == 'list': if admins: asyncio.create_task( client.notice(data.nickname, f'Admins are: {", ".join(admins)}')) else: asyncio.create_task( client.notice(data.nickname, 'There are no admins.')) return
async def _get_prefix(self, target: str) -> str: """ Is used to get or set the channel command prefix. Returns default for private messages. If channel has prefix set to non valid prefix, set it to default. """ default_prefix: str try: default_prefix = self.bot.config['servers'][self.server_tag].get( 'command_prefix', '.') except AttributeError: default_prefix = '.' conn: Connection = self.bot.dbs[self.server_tag] prefix: Optional[str] if target[0] == '#': db_prefix: DBResult = db.get_cell(conn, 'channels', 'commandprefix', 'channel', target) if not db_prefix: prefix = default_prefix db.add_channel(conn, target, prefix) else: prefix = db_prefix[0][0] valid_prefixes: Union[str, List[str]] = self.bot.config.get( 'valid_command_prefixes', '.') if not prefix or prefix not in valid_prefixes: prefix = default_prefix db.set_cell(conn, 'channels', 'commandprefix', prefix, 'channel', target) else: prefix = default_prefix return prefix
def _get_user_attribute(conn, attr_name, username): attr = db.get_cell(conn, 'users', attr_name, 'nick', username) if attr[0][0] is None or attr[0][0] == '': print('returning error str') return f'No {attr_name} found for {username}.' else: return attr[0][0]
async def g_set(client, data): """ .set <table> <matchcol> <value> <setcol> <value> -- Changes values in the database, and lists valid tables and columns when arguments ommited. """ bot = client.bot conn = bot.dbs[data.server] if not data.message: doc = ' '.join(g_set.__doc__.split()) asyncio.create_task(client.notice(data.nickname, f'{doc}')) asyncio.create_task(_list_tables(client, data, conn)) return message = data.split_message table = message[0] columns = await _list_columns(None, data, conn, table) table_exists = db.get_table(conn, table) if isinstance(table_exists, OperationalError): asyncio.create_task(_list_tables(client, data, conn)) return if len(message) == 1: asyncio.create_task(_list_columns(client, data, conn, table)) return match_col = message[1] if match_col not in columns: asyncio.create_task(_list_columns(client, data, conn, table)) return match_value = await _get_match_value(client, data, message) if not match_value: return row_exists = db.get_cell(conn, table, match_col, match_col, match_value) if not row_exists: asyncio.create_task( client.notice(data.nickname, f'{match_value} is not in that table.')) return set_column = await _get_set_column(client, data, conn, message, table, columns) if not set_column: return value = ' '.join(message[4:]) if not value: asyncio.create_task( client.notice(data.nickname, 'Need a value to add.')) else: conn = client.bot.dbs[data.server] asyncio.create_task( client.notice(data.nickname, f'Setting {set_column} to {value}.')) db.set_cell(conn, table, set_column, value, match_col, match_value)
async def c_un_ignore(client, data): """ .unignore/.ignore <list/user/mask> -- Unignores or ignores a list of users, or lists ignored users. """ conn = client.bot.dbs[data.server] message = data.message.replace(',', ' ') masks = await _parse_masks(client, data, conn, message) if not len(masks) and message.split(' ')[0] != 'list': doc = ' '.join(c_un_ignore.__doc__.split()) asyncio.create_task(client.notice(data.nickname, f'{doc}')) asyncio.create_task( client.notice(data.nickname, f'No valid users or masks.')) return ignored = db.get_cell(conn, 'channels', 'ignored', 'channel', data.target)[0][0] if not ignored: ignored = '' if message.split(' ')[0] == 'list': if len(ignored) > 0: asyncio.create_task( client.notice(data.nickname, f'Ignored users: {ignored}')) else: asyncio.create_task( client.notice(data.nickname, f'No users ignored.')) return for mask in masks: if data.command == 'unignore': if mask in ignored: asyncio.create_task( client.notice(data.nickname, f'{mask} is unignored in {data.target}.')) ignored = ignored.replace(mask, '').strip() else: asyncio.create_task( client.notice(data.nickname, f'{mask} is not ignored in {data.target}.')) return elif data.command == 'ignore': if mask in ignored: asyncio.create_task( client.notice( data.nickname, f'{mask} is already ignored in {data.target}.')) return else: asyncio.create_task( client.notice(data.nickname, f'ignoring {mask} in {data.target}.')) ignored += mask + ' ' db.set_cell(conn, 'channels', 'ignored', ignored, 'channel', data.target)
def _get_user_location(conn, location_column, username): location = db.get_cell(conn, 'users', location_column, 'nick', username) #print( location[0][0] ); try: if location[0][0] is None or len(location[0][0]) == 0: return None except: return None return location[0][0]
async def is_ignored(client: Any, conn: Connection, target: str, mask: str) -> bool: """Is used to check if a mask is ignored in a channel.""" db.add_column(conn, 'channels', 'ignored') ignores = db.get_cell(conn, 'channels', 'ignored', 'channel', target) if ignores: nignores: Optional[str] = ignores[0][0] if nignores: if mask in nignores: return True return False
async def is_admin(client: Any, conn: Connection, nick: str, mask: str) -> bool: """Is used to check if a mask is an admin in the channel.""" db.add_column(conn, 'channels', 'admins') admins = db.get_cell(conn, 'channels', 'admins', 'channel', nick) if admins: nadmins: Optional[str] = admins[0][0] if nadmins: if mask in nadmins.split(): return True return False
async def badwords(client, data): """Is an event for kicking or banning users using bad words.""" if data.target[0] != '#': return if await user.is_admin(client, client.bot.dbs[data.server], data.nickname, data.mask): return if await user.is_gadmin(client, data.server, data.mask): return kickwords = db.get_cell(client.bot.dbs[data.server], 'channels', 'kickwords', 'channel', data.target) banwords = db.get_cell(client.bot.dbs[data.server], 'channels', 'banwords', 'channel', data.target) if kickwords: kickwords = kickwords[0][0] for word in kickwords.split(): if word in data.message: asyncio.create_task( client.kick( data.target, data.nickname, reason=(f'You\'re not allowed to say {word}.'))) if banwords: banwords = banwords[0][0] for word in banwords.split(): word, ban_time, *_ = word.split(':') ban_time = int(ban_time) if word in data.message: asyncio.create_task( client.kickban( data.target, data.nickname, reason=( f'You\'re not allowed to say {word}, banned for' f' {ban_time} seconds.'))) asyncio.create_task( timeu.asyncsched(ban_time, client.unban, (data.target, data.nickname)))
async def c_ban_unban(client, data): """.ban [add/del/list] [user] [timer]/.kickban [add/del] [user] [reason] [timer]/.unban [user] -- Ban/kickban/unban the user. User can be banned for [timer]. .unban automatically removes from ban list.""" message = data.split_message conn = client.bot.dbs[data.server] bans = await botu.make_list( db.get_cell(conn, 'channels', 'ban', 'channel', data.target)[0][0]) if data.command == 'unban': asyncio.create_task(client.unban(data.target, message[0])) asyncio.create_task( botu.del_from_channels(client, data, conn, 'ban', message[0], bans, f'Removing {message[0]} from bans.', f'{message[0]} is not in the ban list.')) return try: timer = int(message[-1]) message = message[:-1] except ValueError: timer = 0 if message[0] == 'del': message = message[1:] asyncio.create_task( botu.del_from_channels(client, data, conn, 'ban', message[0], bans, f'Removing {message[0]} from bans.', f'{message[0]} is not in the ban list.')) elif message[0] == 'add': message = message[1:] asyncio.create_task( botu.add_to_channels(client, data, conn, 'ban', message[0], bans, f'Adding {message[0]} to the bans.', f'{message[0]} is already in the ban list.')) elif message[0] == 'list': asyncio.create_task( client.notice(data.nickname, 'bans are: ' + ', '.join(bans))) return if data.command == 'ban': asyncio.create_task(client.ban(data.target, message[0])) if data.command == 'kickban': asyncio.create_task( client.kickban( data.target, message[0], reason=' '.join(message).replace(message[0], 'Git Rekt'))) if timer: asyncio.create_task( timeu.asyncsched(timer, client.unban, (data.target, message[0])))
async def get_mask(client: Any, conn: Connection, nick: str) -> str: """Is used to combine user information into a mask.""" user: Dict[str, str] try: user = client.users[nick] except KeyError: db_user = db.get_cell(conn, 'users', 'mask', 'nick', nick) if db_user: return db_user[0][0] else: return '' mask: str = f'{user["nickname"]}!{user["username"]}@{user["hostname"]}' return mask
def _get_user_intro(conn, intro_name, username, join): intro = db.get_cell(conn, 'users', intro_name, 'nick', username) intro_msg = intro[0][0] if join: """Checking intro through JOIN""" if intro_msg is not None: return intro_msg return None elif not join: """Checking intro through PRIVMSG""" if intro_msg is None: return f'No {intro_name} saved for {username}.' return username + ": " + intro_msg
async def badwords_input_sieve(client, data): """Is used to return block inputs from users using bad words.""" admin = await user.is_admin(client, client.bot.dbs[data.server], data.nickname, data.mask) gadmin = await user.is_gadmin(client, data.server, data.mask) db.add_column(client.bot.dbs[data.server], 'channels', 'kickwords') db.add_column(client.bot.dbs[data.server], 'channels', 'banwords') if not data.target or data.target[0] != '#' or gadmin or admin: return data db_prefix = db.get_cell(client.bot.dbs[data.server], 'channels', 'commandprefix', 'channel', data.target)[0][0] if data.command[0] != db_prefix: return data kickwords = db.get_cell(client.bot.dbs[data.server], 'channels', 'kickwords', 'channel', data.target) banwords = db.get_cell(client.bot.dbs[data.server], 'channels', 'banwords', 'channel', data.target) if kickwords: kickwords = kickwords[0][0] for word in kickwords.split(' '): if word in data.message: asyncio.create_task( client.notice(data.nickname, (f'I cannot say {word} in' f'{data.target}'))) if banwords: banwords = banwords[0][0] for word in banwords.split(' '): word = ' '.join(word.split(':')[0:-1]) if word in data.message: asyncio.create_task( client.notice(data.nickname, (f'I cannot say {word} in' f'{data.target}'))) return data
async def chan_join(client, data): """Is called on channel join.""" conn = client.bot.dbs[data.server] if data.nickname in client.users: ops = await botu.make_list( db.get_cell(conn, 'channels', 'op', 'channel', data.target)[0][0]) hops = await botu.make_list( db.get_cell(conn, 'channels', 'hop', 'channel', data.target)[0][0]) vops = await botu.make_list( db.get_cell(conn, 'channels', 'vop', 'channel', data.target)[0][0]) bans = await botu.make_list( db.get_cell(conn, 'channels', 'ban', 'channel', data.target)[0][0]) if data.mask in ops: asyncio.create_task( client.rawmsg('MODE', data.target, '+o', f'{data.nickname}')) elif data.mask in hops: asyncio.create_task( client.rawmsg('MODE', data.target, '+h', f'{data.nickname}')) elif data.mask in vops: asyncio.create_task( client.rawmsg('MODE', data.target, '+v', f'{data.nickname}')) if data.mask in bans: asyncio.create_task(client.ban(data.target, data.nickname))
async def c_enable_disable(client, data): """ .enable/.disable <list/commands/events/sieves> -- Lists, enables or disables commands, events and sieves. """ event_vals = list(client.bot.plugs['event'].values()) events = [func[0].__name__ for func in (event for event in event_vals)] commands = list(client.bot.plugs['command']) sieves = list(client.bot.plugs['sieve']) nodisable = client.bot.config['servers'][data.server]['no_disable'] conn = client.bot.dbs[data.server] disabled = await botu.make_list( db.get_cell(conn, 'channels', 'disabled', 'channel', data.target)[0][0]) message = data.split_message if message[0] == 'list': asyncio.create_task( botu.cmd_event_sieve_lists(client, data, disabled, nodisable, sieves, events, commands)) return for plugin in message: plugin = plugin.lower().strip() if await botu.is_cmd_event_sieve(plugin, data, sieves, events, commands): asyncio.create_task( client.notice(data.nickname, f'{plugin} is not a sieve, command or event.')) elif data.command == 'enable': asyncio.create_task( botu.del_from_channels(client, data, conn, 'disabled', plugin, disabled, f'Enabling {plugin}', f'{plugin} is not disabled')) elif data.command == 'disable': if plugin in nodisable: asyncio.create_task( client.notice(data.nickname, f'You cannot disable {plugin}.')) else: asyncio.create_task( botu.add_to_channels(client, data, conn, 'disabled', plugin, disabled, f'Disabling {plugin}', f'{plugin} is already disabled.'))
async def c_op(client, data): """.deop <users>/.op [add/del/list] [users] -- Ops/deops users and can add/del to autoop list. Same for hop and vop.""" message = data.split_message conn = client.bot.dbs[data.server] if data.command[0:2] == 'de': asyncio.create_task( botu.usermodes(client, data.target, data.command, message)) return dbmasks = await botu.make_list( db.get_cell(conn, 'channels', data.command, 'channel', data.target)[0][0]) if message[0] == 'list': if dbmasks: asyncio.create_task( client.notice(data.nickname, f'{data.command}s are: {" ".join(dbmasks)}.')) else: asyncio.create_task( client.notice(data.nickname, f'There are no {data.command}s.')) return message = message[1:] masks = await user.parse_masks(client, conn, ' '.join(message)) for mask in masks: if message[0] == 'add': asyncio.create_task( botu.add_to_channels( client, data, conn, data.command, mask, dbmasks, f'Adding {mask} to {data.command} list.', f'{mask} is already auto-{data.command}ed.')) elif message[0] == 'del': asyncio.create_task( botu.del_from_channels( client, data, conn, data.command, mask, dbmasks, f'Removing {mask} from {data.command} list.', f'{mask} is not auto-{data.command}ed.')) asyncio.create_task( botu.usermodes(client, data.target, data.command, message))
async def c_flood(client, data): """ .flood [list/cmd/msg] [messages/disable] [second] [kick/ban/warn] -- List, disable, or change the max messages per second or commands per second. The bot can kick, ban(which also kicks), or warn flooding users. """ conn = client.bot.dbs[data.server] msgflood = db.get_cell(conn, 'channels', 'msgflood', 'channel', data.target)[0][0] cmdflood = db.get_cell(conn, 'channels', 'cmdflood', 'channel', data.target)[0][0] if ' ' in data.message: message = data.message.split(' ') else: message = [data.message] if message[0] == 'list': if msgflood not in (None, ''): asyncio.create_task( client.notice(data.nickname, f'Message flood: {msgflood}.')) else: asyncio.create_task( client.notice(data.nickname, f'No message flood set.')) if cmdflood not in (None, ''): asyncio.create_task( client.notice(data.nickname, f'Command flood: {cmdflood}.')) else: asyncio.create_task( client.notice(data.nickname, f'No command flood set.')) return secs = await _secs_or_help(client, data, message) if not secs: return if message[0] == 'msg': if message[1] == 'disable': asyncio.create_task( client.notice(data.nickname, 'Disabling message flood.')) db.set_cell(conn, 'channels', 'msgflood', '', 'channel', data.target) else: asyncio.create_task( client.notice( data.nickname, f'Changing message flood to {message[1]} {secs}' f'{message[3]}.')) db.set_cell(conn, 'channels', 'msgflood', f'{message[1]} {secs} {message[3]}', 'channel', data.target) if message[0] == 'cmd': if message[1] == 'disable': asyncio.create_task( client.notice(data.nickname, 'Disabling command flood.')) db.set_cell(conn, 'channels', 'cmdflood', '', 'channel', data.target) else: asyncio.create_task( client.notice( data.nickname, f'Changing command flood to {message[1]} {secs}' f'{message[3]}.')) db.set_cell(conn, 'channels', 'cmdflood', f'{message[1]} {secs} {message[3]}', 'channel', data.target)
async def is_user(client: Any, conn: Connection, nick: str) -> bool: """Is used to determain if a user is in db or user dict.""" db_user = db.get_cell(conn, 'users', 'mask', 'nick', nick) if nick not in client.users and not db_user: return False return True