From dbc3f9e6a833814e98a2a5b6ec0f7e53b9f0e518 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Wed, 2 Oct 2019 11:27:07 -0400 Subject: [PATCH 01/23] channel changes --- sopel_modules/SpiceBot/Channels.py | 268 ++++++++++++------ sopel_modules/SpiceBot/Prerun.py | 2 +- .../SpiceBot_Core_Commands/Channels.py | 33 +-- .../SpiceBot_Core_Commands/Messaging.py | 2 +- .../SpiceBot_Core_Processing/Channels.py | 22 +- .../StartupMonologue.py | 4 +- 6 files changed, 212 insertions(+), 119 deletions(-) diff --git a/sopel_modules/SpiceBot/Channels.py b/sopel_modules/SpiceBot/Channels.py index 160cd25..01cb762 100644 --- a/sopel_modules/SpiceBot/Channels.py +++ b/sopel_modules/SpiceBot/Channels.py @@ -12,7 +12,6 @@ import threading from .Config import config as botconfig from .Database import db as botdb -from .Users import users as botusers class SpiceBot_Channels_MainSection(StaticSection): @@ -21,19 +20,30 @@ class SpiceBot_Channels_MainSection(StaticSection): operadmin = ValidatedAttribute('operadmin', default=False) chanignore = ListAttribute('chanignore') +# replace process lock with uuid list system + class BotChannels(): """This Logs all channels known to the server""" def __init__(self): + + # bot config setup self.setup_channels() - self.who_reqs = {} + + # Locking self.lock = threading.Lock() self.channel_lock = False - self.channels = [] - self.dict = { - "list": {}, - "InitialProcess": False - } + + # list of channels + self.chandict = {} + + # list of uuids to process + self.server_recieved = [] + + # initial process + self.InitialProcess = False + + self.who_reqs = {} def __getattr__(self, name): ''' will only get called for undefined attributes ''' @@ -43,22 +53,51 @@ class BotChannels(): else: raise Exception('Channel dict does not contain a function or key ' + str(name.lower())) - def get_channel_users(self, channel, idtype="nick"): + def total_channels(self): + totalcount = len(list(self.chandict.keys())) + return totalcount - if channel.lower() not in list(self.dict["list"].keys()): - raise Exception('Channel ' + str(channel.lower()) + " does not seem to be on this server") - if 'users' not in list(self.dict["list"][channel.lower()].keys()) or not self.check_channel_bot(channel): - raise Exception('Channel ' + str(channel.lower()) + " does not seem to be a channel the bot is in") + def total_bot_channels(self): + totalcount = 0 + for channel in list(self.chandict.keys()): + if self.chandict[channel]["joined"]: + totalcount += 1 + return totalcount - nick_ids = self.dict["list"][channel.lower()]['users'] - if idtype.upper() == "ID": - return nick_ids + def chanlist(self): + return list(self.chandict.keys()) + + def chanlist_bot(self): + chanlist_return = [] + for channel in list(self.chandict.keys()): + if self.chandict[channel]["joined"]: + chanlist_return.append(channel) + return chanlist_return + + def ischannel(self, channel): + + # channel names case-sensitivity should never be an issue + channel = str(channel).lower() + + if channel in list(self.chandict.keys()): + return True else: - nick_list = [] - for nick_id in nick_ids: - nickname = botusers.ID(nick_id) - nick_list.append(nickname) - return nick_list + return False + + def get_channel_users(self, channel): + + # channel names case-sensitivity should never be an issue + channel = str(channel).lower() + + # channel not on server + if channel not in list(self.chandict.keys()): + raise Exception('Channel ' + str(channel) + " does not seem to be on this server") + + # bot is not in channel + if not self.chandict[channel]["joined"]: + raise Exception('Channel ' + str(channel) + " does not seem to be a channel the bot is in") + + return self.chandict[channel]["users"] def setup_channels(self): botconfig.define_section("SpiceBot_Channels", SpiceBot_Channels_MainSection, validate=False) @@ -70,81 +109,120 @@ class BotChannels(): self.channel_lock = True def channel_list_recieve_input(self, trigger): - self.lock.acquire() + + # parse info channel, _, topic = trigger.args[1:] - if channel.lower() not in list(self.dict['list'].keys()): - self.dict['list'][channel.lower()] = dict() - self.dict['list'][channel.lower()]['name'] = channel - self.dict['list'][channel.lower()]['topic'] = self.topic_compile(topic) + + # check channel existance + if channel not in list(self.chandict.keys()): + self.channeldict_append(channel) + + self.lock.acquire() + + # get proper name of channel + self.chandict[channel.lower()]['name'] = channel + self.chandict[channel.lower()]['topic'] = self.topic_compile(topic) self.channel_lock = True self.lock.release() def channel_list_recieve_finish(self): self.lock.acquire() - if not self.dict['InitialProcess']: - self.dict['InitialProcess'] = True - self.lock.release() + if not self.InitialProcess: + self.InitialProcess = True self.channel_lock = False + self.lock.release() def topic_compile(self, topic): actual_topic = re.compile(r'^\[\+[a-zA-Z]+\] (.*)') topic = re.sub(actual_topic, r'\1', topic) + if topic.isspace(): + topic = None return topic - def add_channel(self, channel): + def channeldict_append(self, channel): + + # channel names case-sensitivity should never be an issue channel = str(channel).lower() + + # create basic components of the channel dict self.lock.acquire() - if channel not in self.channels: - self.channels.append(channel) + if channel not in list(self.chandict.keys()): + self.chandict[channel] = { + "name": channel, + "topic": None, + "joined": False, + "reason": "appended", + "users": [], + } self.lock.release() - def remove_channel(self, channel): + def add_channel(self, channel, reason=None): + + # channel names case-sensitivity should never be an issue channel = str(channel).lower() + + # check channel existance + if channel not in list(self.chandict.keys()): + self.channeldict_append(channel) + self.lock.acquire() - if channel in self.channels: - self.channels.remove(channel) + if reason != "check": + self.chandict[channel]["joined"] = True + self.chandict[channel]["reason"] = reason + self.lock.release() + + def remove_channel(self, channel, reason=None): + + # channel names case-sensitivity should never be an issue + channel = str(channel).lower() + + # check channel existance + if channel not in list(self.chandict.keys()): + self.channeldict_append(channel) + + self.lock.acquire() + if reason != "check": + self.chandict[channel]["joined"] = False + self.chandict[channel]["reason"] = reason self.lock.release() def bot_part_empty(self, bot): """Don't stay in empty channels""" - ignorepartlist = [] + ignorepartlist = [] # TODO add bot.config channels to ignore if bot.config.core.logging_channel: ignorepartlist.append(bot.config.core.logging_channel) for channel in list(bot.channels.keys()): - if len(list(bot.channels[channel].privileges.keys())) == 1 and channel not in ignorepartlist and channel.startswith("#"): - bot.part(channel, "Leaving Empty Channel") - if channel.lower() in self.dict['list']: - self.lock.acquire() - del self.dict['list'][channel.lower()] - self.lock.release() - self.remove_channel(channel) + if channel.startswith("#") and channel not in ignorepartlist: + if len(list(bot.channels[channel].privileges.keys())) == 1: + bot.part(channel, "Leaving Empty Channel") + if channel.lower() in list(self.chandict.keys()): + self.lock.acquire() + self.chandict[channel]["joined"] = False + self.chandict[channel]["reason"] = "empty_chan_part" + self.lock.release() + self.remove_channel(channel) def join_all_channels(self, bot): if botconfig.SpiceBot_Channels.joinall: - for channel in list(self.dict['list'].keys()): - if channel.startswith("#"): - if channel not in list(bot.channels.keys()) and channel not in botconfig.SpiceBot_Channels.chanignore: - bot.write(('JOIN', bot.nick, self.dict['list'][channel]['name'])) - if channel not in list(bot.channels.keys()) and botconfig.SpiceBot_Channels.operadmin: - bot.write(('SAJOIN', bot.nick, self.dict['list'][channel]['name'])) + for channel in list(self.chandict.keys()): + if channel.startswith("#") and channel not in botconfig.SpiceBot_Channels.chanignore: + if channel.lower() not in [chan.lower() for chan in list(bot.channels.keys())]: + self.bot_join(bot, channel) + if channel.lower() not in [chan.lower() for chan in list(bot.channels.keys())]: + self.bot_sajoin(bot, channel) - if channel in list(bot.channels.keys()): - self.add_channel(channel) + def bot_join(self, bot, channel): + bot.write(('JOIN', bot.nick, channel)) - def chanadmin_all_channels(self, bot): + def bot_sajoin(self, bot, channel): + if botconfig.SpiceBot_Channels.operadmin: + bot.write(('SAJOIN', bot.nick, channel)) + + def chanadmin_channel(self, bot, channel): # Chan ADMIN +a - for channel in list(bot.channels.keys()): - if channel.startswith("#"): - self.add_channel(channel) - if channel not in botconfig.SpiceBot_Channels.chanignore: - if botconfig.SpiceBot_Channels.operadmin: - if not bot.channels[channel].privileges[bot.nick] < sopel.module.ADMIN: - bot.write(('SAMODE', channel, "+a", bot.nick)) - else: - bot.part(channel) - - if channel not in list(bot.channels.keys()): - self.remove_channel(channel) + if botconfig.SpiceBot_Channels.operadmin: + if not bot.channels[channel].privileges[bot.nick] < sopel.module.ADMIN: + bot.write(('SAMODE', channel, "+a", bot.nick)) def whois_ident(self, nick): nick = Identifier(nick) @@ -152,43 +230,48 @@ class BotChannels(): return nick_id def add_to_channel(self, channel, nick, nick_id=None): + + # channel names case-sensitivity should never be an issue channel = str(channel).lower() + + # Verify Channel is in list + if channel not in list(self.chandict.keys()): + self.add_channel(channel, "error_handling") + self.lock.acquire() if not nick_id: nick_id = self.whois_ident(nick) - if channel.lower() not in list(self.dict['list'].keys()): - self.dict['list'][channel.lower()] = dict() - if 'users' not in self.dict['list'][channel.lower()]: - self.dict['list'][channel.lower()]['users'] = [] - if int(nick_id) not in self.dict['list'][channel.lower()]['users']: - self.dict['list'][channel.lower()]['users'].append(int(nick_id)) - if channel.lower() not in self.channels: - self.channels.append(channel.lower()) + if int(nick_id) not in self.chandict[channel]["users"]: + self.chandict[channel]["users"].append(int(nick_id)) self.lock.release() def remove_from_channel(self, channel, nick, nick_id=None): + + # channel names case-sensitivity should never be an issue channel = str(channel).lower() + + # Verify Channel is in list + if channel not in list(self.chandict.keys()): + self.add_channel(channel, "error_handling") + self.lock.acquire() if not nick_id: nick_id = self.whois_ident(nick) - if channel.lower() not in list(self.dict['list'].keys()): - self.dict['list'][channel.lower()] = dict() - if 'users' not in self.dict['list'][channel.lower()]: - self.dict['list'][channel.lower()]['users'] = [] - if int(nick_id) in self.dict['list'][channel.lower()]['users']: - self.dict['list'][channel.lower()]['users'].remove(int(nick_id)) + if int(nick_id) in self.chandict[channel.lower()]['users']: + self.chandict[channel.lower()]['users'].remove(int(nick_id)) self.lock.release() def remove_all_from_channel(self, channel): + + # channel names case-sensitivity should never be an issue channel = str(channel).lower() + + # Verify Channel is in list + if channel not in list(self.chandict.keys()): + self.add_channel(channel, "error_handling") + self.lock.acquire() - if channel.lower() not in list(self.dict['list'].keys()): - self.dict['list'][channel.lower()] = dict() - if 'users' not in self.dict['list'][channel.lower()]: - self.dict['list'][channel.lower()]['users'] = [] - self.dict['list'][channel.lower()]['users'] = [] - if channel.lower() in self.channels: - self.channels.remove(channel.lower()) + self.chandict[channel.lower()]['users'] = [] self.lock.release() def channel_scan(self, bot): @@ -199,6 +282,7 @@ class BotChannels(): def join(self, bot, trigger): # bot block if trigger.nick == bot.nick: + self.chanadmin_channel(bot, trigger.sender) for user in list(bot.channels[trigger.sender].privileges.keys()): self.add_to_channel(trigger.sender, user) return @@ -211,6 +295,10 @@ class BotChannels(): # bot block if trigger.nick == bot.nick: self.remove_all_from_channel(trigger.sender) + self.lock.acquire() + self.chandict[trigger.sender]["joined"] = False + self.chandict[trigger.sender]["reason"] = "quit" + self.lock.release() return # Identify nick_id = self.whois_ident(trigger.nick) @@ -221,6 +309,10 @@ class BotChannels(): # bot block if trigger.nick == bot.nick: self.remove_all_from_channel(trigger.sender) + self.lock.acquire() + self.chandict[trigger.sender]["joined"] = False + self.chandict[trigger.sender]["reason"] = "bot_part" + self.lock.release() return # Identify nick_id = self.whois_ident(trigger.nick) @@ -232,6 +324,10 @@ class BotChannels(): # bot block if targetnick == bot.nick: self.remove_all_from_channel(trigger.sender) + self.lock.acquire() + self.chandict[trigger.sender]["joined"] = False + self.chandict[trigger.sender]["reason"] = "kicked" + self.lock.release() return # Identify nick_id = self.whois_ident(targetnick) @@ -287,9 +383,9 @@ class BotChannels(): self.add_to_channel(channel, nick) def check_channel_bot(self, channel, allchan=False): - if str(channel).lower() in self.channels: + if str(channel).lower() in self.chanlist_bot(): return True - elif allchan and str(channel).lower() in list(self.dict['list'].keys()): + elif allchan and str(channel).lower() in self.chanlist(): return True else: return False diff --git a/sopel_modules/SpiceBot/Prerun.py b/sopel_modules/SpiceBot/Prerun.py index 7a5e5c7..305c443 100644 --- a/sopel_modules/SpiceBot/Prerun.py +++ b/sopel_modules/SpiceBot/Prerun.py @@ -212,7 +212,7 @@ def verify_user(bot, trigger): def verify_channel(trigger): - botchannels.add_channel(trigger.sender) + botchannels.add_channel(trigger.sender, "check") # Identify nick_id = botchannels.whois_ident(trigger.nick) # Verify nick is in the channel list diff --git a/sopel_modules/SpiceBot_Core_Commands/Channels.py b/sopel_modules/SpiceBot_Core_Commands/Channels.py index 83cd269..ccd3d9b 100644 --- a/sopel_modules/SpiceBot_Core_Commands/Channels.py +++ b/sopel_modules/SpiceBot_Core_Commands/Channels.py @@ -22,23 +22,23 @@ def nickname_comand_channels(bot, trigger, botcom): botcom.dict['args'] = spicemanip(botcom.dict['args'], '2+', 'list') if commandused == 'list': - botcount = len(list(bot.channels.keys())) - servercount = len(list(SpiceBot.channels.dict['list'].keys())) + botcount = SpiceBot.channels.total_bot_channels() + servercount = SpiceBot.channels.total_channels() displayval = "I am in " + str(botcount) + " of " + str(servercount) + " channel(s) available on this server." - chanlist = spicemanip(list(bot.channels.keys()), 'andlist') + chanlist = spicemanip(SpiceBot.channels.chanlist_bot(), 'andlist') bot.osd([displayval, "You can find me in " + chanlist]) return elif commandused == 'total': - botcount = len(list(bot.channels.keys())) - servercount = len(list(SpiceBot.channels.dict['list'].keys())) + botcount = SpiceBot.channels.total_bot_channels() + servercount = SpiceBot.channels.total_channels() bot.osd("I am in " + str(botcount) + " of " + str(servercount) + " channel(s) available on this server.") return elif commandused == 'random': - channel = spicemanip(SpiceBot.channels.dict['list'], 'random') - topic = SpiceBot.channels.dict['list'][channel]['topic'] - msg = ["Random channel for you: {}.".format(SpiceBot.channels.dict['list'][channel]['name'])] + channel = spicemanip(list(SpiceBot.channels.chandict), 'random') + topic = SpiceBot.channels.chandict[channel]['topic'] + msg = ["Random channel for you: {}.".format(SpiceBot.channels.chandict[channel]['name'])] if topic and not topic.isspace(): msg.append("The topic is: {}".format(topic)) else: @@ -47,7 +47,7 @@ def nickname_comand_channels(bot, trigger, botcom): return elif commandused == 'update': - if not trigger.admin: + if not trigger.admin: # TODO SpiceBot.messagelog.messagelog_error(botcom.dict["log_id"], "You do not have permission to update the channel listing.") return SpiceBot.channels.bot_part_empty(bot) @@ -56,7 +56,7 @@ def nickname_comand_channels(bot, trigger, botcom): while SpiceBot.channels.channel_lock: pass SpiceBot.channels.join_all_channels(bot) - foundchannelcount = len(list(SpiceBot.channels.dict['list'].keys())) + foundchannelcount = len(list(SpiceBot.channels.chandict.keys())) bot.osd("[SpiceBot_Channels]", "Channel listing finished!", str(foundchannelcount) + " channel(s) found.") SpiceBot.channels.bot_part_empty(bot) return @@ -66,12 +66,13 @@ def nickname_comand_channels(bot, trigger, botcom): SpiceBot.messagelog.messagelog_error(botcom.dict["log_id"], "Channel name input missing.") return channel = spicemanip(botcom.dict['args'], 1) - if not SpiceBot.inlist(channel.lower(), list(SpiceBot.channels.dict['list'].keys())): + if not SpiceBot.inlist(channel.lower(), list(SpiceBot.channels.chandict.keys())): SpiceBot.messagelog.messagelog_error(botcom.dict["log_id"], "Channel name {} not valid.".format(channel)) return - topic = SpiceBot.channels.dict['list'][channel.lower()]['topic'] - channel = SpiceBot.channels.dict['list'][channel.lower()]['name'] - bot.osd("Topic for {}: {}".format(channel, topic)) + channel = str(channel).lower() + topic = SpiceBot.channels.chandict[channel]['topic'] + channelname = SpiceBot.channels.chandict[channel]['name'] + bot.osd("Topic for {}: {}".format(channelname, topic)) return if commandused.upper() in ['OP', 'HOP', 'VOICE', 'OWNER', 'ADMIN']: @@ -83,7 +84,7 @@ def nickname_comand_channels(bot, trigger, botcom): channel = trigger.sender else: channel = spicemanip(botcom.dict['args'], 1) - if not SpiceBot.inlist(channel.lower(), list(SpiceBot.channels.dict['list'].keys())): + if not SpiceBot.inlist(channel.lower(), list(SpiceBot.channels.chandict.keys())): SpiceBot.messagelog.messagelog_error(botcom.dict["log_id"], "Channel name {} not valid.".format(channel)) return if not SpiceBot.inlist(channel.lower(), list(bot.channels.keys())): @@ -103,7 +104,7 @@ def nickname_comand_channels(bot, trigger, botcom): # Users List if commandused == 'users': channel = spicemanip(botcom.dict['args'], 1) - if not SpiceBot.inlist(channel.lower(), list(SpiceBot.channels.dict['list'].keys())): + if not SpiceBot.inlist(channel.lower(), list(SpiceBot.channels.chandict.keys())): SpiceBot.messagelog.messagelog_error(botcom.dict["log_id"], "Channel name {} not valid.".format(channel)) return if not SpiceBot.inlist(channel.lower(), list(bot.channels.keys())): diff --git a/sopel_modules/SpiceBot_Core_Commands/Messaging.py b/sopel_modules/SpiceBot_Core_Commands/Messaging.py index 29e59a6..f89783b 100644 --- a/sopel_modules/SpiceBot_Core_Commands/Messaging.py +++ b/sopel_modules/SpiceBot_Core_Commands/Messaging.py @@ -42,7 +42,7 @@ def bot_command_process(bot, trigger, botcom): target = spicemanip(botcom.dict['args'], 1) if (target not in ['allchans', 'allnicks'] - and not SpiceBot.inlist(target.lower(), list(SpiceBot.channels.dict['list'].keys())) + and not SpiceBot.channels.ischannel(target) and not SpiceBot.inlist(target.lower(), bot.users)): SpiceBot.messagelog.messagelog_error(botcom.dict["log_id"], "Channel/nick name {} not valid.".format(target)) return diff --git a/sopel_modules/SpiceBot_Core_Processing/Channels.py b/sopel_modules/SpiceBot_Core_Processing/Channels.py index c82ec7e..c8f4dd6 100644 --- a/sopel_modules/SpiceBot_Core_Processing/Channels.py +++ b/sopel_modules/SpiceBot_Core_Processing/Channels.py @@ -31,21 +31,17 @@ def request_channels_list_initial(bot, trigger): starttime = time.time() # wait 60 seconds for initial population of information - while not SpiceBot.channels.dict['InitialProcess']: + while not SpiceBot.channels.InitialProcess: if time.time() - starttime >= 60: SpiceBot.logs.log('SpiceBot_Channels', "Initial Channel list populating Timed Out") - SpiceBot.channels.dict['InitialProcess'] = True + SpiceBot.channels.InitialProcess = True else: pass - foundchannelcount = len(list(SpiceBot.channels.dict['list'].keys())) + foundchannelcount = SpiceBot.channels.total_channels() SpiceBot.logs.log('SpiceBot_Channels', "Channel listing finished! " + str(foundchannelcount) + " channel(s) found.") SpiceBot.channels.join_all_channels(bot) - SpiceBot.channels.chanadmin_all_channels(bot) - - if "*" in SpiceBot.channels.dict['list'].keys(): - del SpiceBot.channels.dict['list']["*"] SpiceBot.channels.bot_part_empty(bot) SpiceBot.events.trigger(bot, SpiceBot.events.BOT_CHANNELS, "SpiceBot_Channels") @@ -76,13 +72,17 @@ def trigger_channel_list_recurring(bot, trigger): time.sleep(1800) SpiceBot.channels.bot_part_empty(bot) - oldlist = list(SpiceBot.channels.dict['list'].keys()) + oldlist = SpiceBot.channels.chanlist() SpiceBot.channels.channel_list_request(bot) while SpiceBot.channels.channel_lock: pass - newlist = [item.lower() for item in oldlist if item.lower() not in list(SpiceBot.channels.dict['list'].keys())] + currentlist = SpiceBot.channels.chanlist() + newlist = [] + for channel in currentlist: + if channel not in oldlist: + newlist.append(channel) if "*" in newlist: newlist.remove("*") if len(newlist) and SpiceBot.config.SpiceBot_Channels.announcenew: @@ -90,10 +90,6 @@ def trigger_channel_list_recurring(bot, trigger): SpiceBot.channels.join_all_channels(bot) - SpiceBot.channels.chanadmin_all_channels(bot) - - if "*" in list(SpiceBot.channels.dict['list'].keys()): - del SpiceBot.channels.dict['list']["*"] SpiceBot.channels.bot_part_empty(bot) diff --git a/sopel_modules/SpiceBot_Core_Processing/StartupMonologue.py b/sopel_modules/SpiceBot_Core_Processing/StartupMonologue.py index 2e50bdb..61fb9d9 100644 --- a/sopel_modules/SpiceBot_Core_Processing/StartupMonologue.py +++ b/sopel_modules/SpiceBot_Core_Processing/StartupMonologue.py @@ -30,8 +30,8 @@ def bot_startup_monologue_sopel_version(bot, trigger): @sopel.module.event(SpiceBot.events.BOT_CHANNELS) @sopel.module.rule('.*') def bot_startup_monologue_channels(bot, trigger): - botcount = len(list(bot.channels.keys())) - servercount = len(list(SpiceBot.channels.dict['list'].keys())) + botcount = SpiceBot.channels.total_bot_channels() + servercount = SpiceBot.channels.total_channels() displayval = "I am in " + str(botcount) + " of " + str(servercount) + " channel(s) available on this server." SpiceBot.startupmonologue.dict["channels"] = displayval SpiceBot.logs.log('SpiceBot_StartupMonologue', displayval) From 1c8ea3ac5b628ef97e017186ed87a7b3fcbd175c Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Wed, 2 Oct 2019 11:36:36 -0400 Subject: [PATCH 02/23] remove getattr --- sopel_modules/SpiceBot/Channels.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sopel_modules/SpiceBot/Channels.py b/sopel_modules/SpiceBot/Channels.py index 01cb762..b5fe764 100644 --- a/sopel_modules/SpiceBot/Channels.py +++ b/sopel_modules/SpiceBot/Channels.py @@ -45,14 +45,6 @@ class BotChannels(): self.who_reqs = {} - def __getattr__(self, name): - ''' will only get called for undefined attributes ''' - """We will try to find a dict value, or return None""" - if name.lower() in list(self.dict.keys()): - return self.dict[str(name).lower()] - else: - raise Exception('Channel dict does not contain a function or key ' + str(name.lower())) - def total_channels(self): totalcount = len(list(self.chandict.keys())) return totalcount From 98d957f0604480f8fdb9b34eb240fbfe26c84bac Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Wed, 2 Oct 2019 11:37:13 -0400 Subject: [PATCH 03/23] news file --- sopel_modules/SpiceBot_Configs/SpiceBot_Release_Notes/Core.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/sopel_modules/SpiceBot_Configs/SpiceBot_Release_Notes/Core.txt b/sopel_modules/SpiceBot_Configs/SpiceBot_Release_Notes/Core.txt index 641d73a..c7ae173 100644 --- a/sopel_modules/SpiceBot_Configs/SpiceBot_Release_Notes/Core.txt +++ b/sopel_modules/SpiceBot_Configs/SpiceBot_Release_Notes/Core.txt @@ -1,2 +1,3 @@ First release of Release Notes OSD updated to more accurately reflect IRC 512 byte limit +Channel Class cleaned up From 2762462162a28a86fc58479078a2c7621fe3b453 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Wed, 2 Oct 2019 11:49:39 -0400 Subject: [PATCH 04/23] whois forget on nick change --- sopel_modules/SpiceBot/Users.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sopel_modules/SpiceBot/Users.py b/sopel_modules/SpiceBot/Users.py index 4ccf102..5918747 100644 --- a/sopel_modules/SpiceBot/Users.py +++ b/sopel_modules/SpiceBot/Users.py @@ -267,6 +267,7 @@ class BotUsers(): def nick(self, bot, trigger): oldnick = trigger.nick old_nick_id = self.whois_ident(oldnick) + self.whois_identify_forget(old_nick_id) newnick = Identifier(trigger) if oldnick == bot.nick or newnick == bot.nick: return @@ -283,11 +284,11 @@ class BotUsers(): # mark user as online self.mark_user_online(old_nick_id) # alias the nick - try: - botdb.alias_nick(oldnick, newnick) - except Exception as e: - old_nick_id = e - return + # try: + # botdb.alias_nick(oldnick, newnick) + # except Exception as e: + # old_nick_id = e + # return def mode(self, bot, trigger): return From 31afc3fc48efd4897345f988af0a1b0ec264a0a1 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Wed, 2 Oct 2019 11:58:49 -0400 Subject: [PATCH 05/23] consolidate user ID system --- sopel_modules/SpiceBot/AI.py | 9 +++++---- sopel_modules/SpiceBot/Channels.py | 3 ++- sopel_modules/SpiceBot/Users.py | 11 ++++++++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/sopel_modules/SpiceBot/AI.py b/sopel_modules/SpiceBot/AI.py index dd6da2d..b2f9212 100644 --- a/sopel_modules/SpiceBot/AI.py +++ b/sopel_modules/SpiceBot/AI.py @@ -14,6 +14,7 @@ import aiml from .Database import db as botdb from .Config import config as botconfig from .Read import read as botread +from .Users import users as botusers from sopel_modules.spicemanip import spicemanip @@ -116,7 +117,7 @@ class SpiceBot_AI(): def on_message(self, bot, trigger, message): nick = Identifier(trigger.nick) - nick_id = botdb.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, create=True) self.check_user_import(nick, nick_id) message = self.bot_message_precipher(bot, trigger, message) @@ -207,13 +208,13 @@ class SpiceBot_AI(): def getPredicate(self, predicate, nick, nick_id=None): if not nick_id: nick = Identifier(nick) - nick_id = botdb.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, create=True) self.aiml_kernel.getPredicate(predicate, nick_id) def check_user_import(self, nick, nick_id=None): if not nick_id: nick = Identifier(nick) - nick_id = botdb.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, create=True) if nick_id not in list(self.dict["sessioncache"].keys()): self.dict["sessioncache"][nick_id] = botdb.get_nick_value(nick, 'botai') or {} for predicate in list(self.dict["sessioncache"][nick_id].keys()): @@ -228,7 +229,7 @@ class SpiceBot_AI(): def save_nick_session(self, nick, nick_id=None): if not nick_id: nick = Identifier(nick) - nick_id = botdb.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, create=True) sessionData = self.aiml_kernel.getSessionData(nick_id) botdb.set_nick_value(nick, 'botai', sessionData) diff --git a/sopel_modules/SpiceBot/Channels.py b/sopel_modules/SpiceBot/Channels.py index b5fe764..6562b17 100644 --- a/sopel_modules/SpiceBot/Channels.py +++ b/sopel_modules/SpiceBot/Channels.py @@ -12,6 +12,7 @@ import threading from .Config import config as botconfig from .Database import db as botdb +from .Users import users as botusers class SpiceBot_Channels_MainSection(StaticSection): @@ -218,7 +219,7 @@ class BotChannels(): def whois_ident(self, nick): nick = Identifier(nick) - nick_id = botdb.db.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, create=True) return nick_id def add_to_channel(self, channel, nick, nick_id=None): diff --git a/sopel_modules/SpiceBot/Users.py b/sopel_modules/SpiceBot/Users.py index 5918747..34b2de8 100644 --- a/sopel_modules/SpiceBot/Users.py +++ b/sopel_modules/SpiceBot/Users.py @@ -65,10 +65,19 @@ class BotUsers(): nick_id = self.whois_ident(nickinput) return int(nick_id) + def get_nick_id(self, nick, usercreate=True): + try: + nick_id = botdb.db.get_nick_id(nick, create=usercreate) + except Exception as e: + nick_id = e + nick_id = None + return None + return nick_id + def whois_ident(self, nick, usercreate=True): nick = Identifier(nick) try: - nick_id = botdb.db.get_nick_id(nick, create=usercreate) + nick_id = self.get_nick_id(nick, create=usercreate) except Exception as e: nick_id = e nick_id = None From 64a9737e387b80e37ff56ceb08d186245e1b793a Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Wed, 2 Oct 2019 12:02:23 -0400 Subject: [PATCH 06/23] fix --- sopel_modules/SpiceBot/AI.py | 8 ++++---- sopel_modules/SpiceBot/Channels.py | 2 +- sopel_modules/SpiceBot/Users.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sopel_modules/SpiceBot/AI.py b/sopel_modules/SpiceBot/AI.py index b2f9212..3e6b6a2 100644 --- a/sopel_modules/SpiceBot/AI.py +++ b/sopel_modules/SpiceBot/AI.py @@ -117,7 +117,7 @@ class SpiceBot_AI(): def on_message(self, bot, trigger, message): nick = Identifier(trigger.nick) - nick_id = botusers.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, True) self.check_user_import(nick, nick_id) message = self.bot_message_precipher(bot, trigger, message) @@ -208,13 +208,13 @@ class SpiceBot_AI(): def getPredicate(self, predicate, nick, nick_id=None): if not nick_id: nick = Identifier(nick) - nick_id = botusers.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, True) self.aiml_kernel.getPredicate(predicate, nick_id) def check_user_import(self, nick, nick_id=None): if not nick_id: nick = Identifier(nick) - nick_id = botusers.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, True) if nick_id not in list(self.dict["sessioncache"].keys()): self.dict["sessioncache"][nick_id] = botdb.get_nick_value(nick, 'botai') or {} for predicate in list(self.dict["sessioncache"][nick_id].keys()): @@ -229,7 +229,7 @@ class SpiceBot_AI(): def save_nick_session(self, nick, nick_id=None): if not nick_id: nick = Identifier(nick) - nick_id = botusers.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, True) sessionData = self.aiml_kernel.getSessionData(nick_id) botdb.set_nick_value(nick, 'botai', sessionData) diff --git a/sopel_modules/SpiceBot/Channels.py b/sopel_modules/SpiceBot/Channels.py index 6562b17..5c0f187 100644 --- a/sopel_modules/SpiceBot/Channels.py +++ b/sopel_modules/SpiceBot/Channels.py @@ -219,7 +219,7 @@ class BotChannels(): def whois_ident(self, nick): nick = Identifier(nick) - nick_id = botusers.get_nick_id(nick, create=True) + nick_id = botusers.get_nick_id(nick, True) return nick_id def add_to_channel(self, channel, nick, nick_id=None): diff --git a/sopel_modules/SpiceBot/Users.py b/sopel_modules/SpiceBot/Users.py index 34b2de8..1f8008a 100644 --- a/sopel_modules/SpiceBot/Users.py +++ b/sopel_modules/SpiceBot/Users.py @@ -77,7 +77,7 @@ class BotUsers(): def whois_ident(self, nick, usercreate=True): nick = Identifier(nick) try: - nick_id = self.get_nick_id(nick, create=usercreate) + nick_id = self.get_nick_id(nick, usercreate) except Exception as e: nick_id = e nick_id = None From 731dca8858f8df15234f4ad1d36207e0a333217a Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Wed, 2 Oct 2019 14:16:36 -0400 Subject: [PATCH 07/23] patch --- sopel_modules/SpiceBot/Channels.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sopel_modules/SpiceBot/Channels.py b/sopel_modules/SpiceBot/Channels.py index 5c0f187..76429a2 100644 --- a/sopel_modules/SpiceBot/Channels.py +++ b/sopel_modules/SpiceBot/Channels.py @@ -159,8 +159,8 @@ class BotChannels(): self.channeldict_append(channel) self.lock.acquire() + self.chandict[channel]["joined"] = True if reason != "check": - self.chandict[channel]["joined"] = True self.chandict[channel]["reason"] = reason self.lock.release() @@ -174,8 +174,8 @@ class BotChannels(): self.channeldict_append(channel) self.lock.acquire() + self.chandict[channel]["joined"] = False if reason != "check": - self.chandict[channel]["joined"] = False self.chandict[channel]["reason"] = reason self.lock.release() @@ -352,7 +352,7 @@ class BotChannels(): if not channels: return channel = Identifier(channels.group(1)) - self.add_channel(channel) + self.add_channel(channel, " check") mapping = {'+': sopel.module.VOICE, '%': sopel.module.HALFOP, From cf69d2c345e332299fe0c33c44ceaf859fab11de Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:09:04 -0400 Subject: [PATCH 08/23] test --- .../SpiceBot_Core_Tools/HTTP_Codes.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py new file mode 100644 index 0000000..011a7c2 --- /dev/null +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -0,0 +1,56 @@ +# coding=utf8 +from __future__ import unicode_literals, absolute_import, division, print_function + +# sopel imports +import sopel.module + +from sopel_modules.spicemanip import spicemanip + +import sopel_modules.SpiceBot as SpiceBot + +import re +import requests +import bleach +from lxml import etree + +api_url = 'https://httpstatuses.com/%s' + + +@SpiceBot.prerun('module') +@sopel.module.commands('httpcode') +def bot_command_http_codes(bot, trigger, botcom): + + query = spicemanip(botcom.dict["args"], 1) or None + if not query: + return bot.osd("You must provide a HTTP status code to look up.") + result = fetch_result(query) + + bot.osd(["[HTTP code search for " + str(query) + "]", result]) + + +def fetch_result(query): + + if not re.match('^[1-5]\d{2}$', query): + return "Invalid HTTP status code: %s" % query + url = api_url % query + try: + r = requests.get(url=url, timeout=(10.0, 4.0)) + except requests.exceptions.ConnectTimeout: + return "Connection timed out." + except requests.exceptions.ConnectionError: + return "Couldn't connect to server." + except requests.exceptions.ReadTimeout: + return "Server took too long to send data." + if r.status_code == 404: + return "Unknown HTTP status code: %s" % query + try: + r.raise_for_status() + except requests.exceptions.HTTPError as e: + return "HTTP error: " + e.message + + page = etree.HTML(r.content) + title = bleach.clean(etree.tostring(page.xpath('/html/body/article/h1[1]')[0]), tags=[], strip=True) + summary = bleach.clean( + re.sub('.*?<\/a>', '', etree.tostring(page.xpath('/html/body/article/p[1]')[0])), tags=[], + strip=True) + return "{title}: {summary} — {link}".format(title=title, summary=summary, link=url) From dc4cd287d1c50cf1fc5eb740508380f5e3f37fa5 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:11:34 -0400 Subject: [PATCH 09/23] test --- sopel_modules/SpiceBot_Core_Tools/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sopel_modules/SpiceBot_Core_Tools/__init__.py b/sopel_modules/SpiceBot_Core_Tools/__init__.py index b8a59da..04c0f61 100644 --- a/sopel_modules/SpiceBot_Core_Tools/__init__.py +++ b/sopel_modules/SpiceBot_Core_Tools/__init__.py @@ -6,6 +6,7 @@ from .Gif import * from .Sherlock import * from .Reddit import * from .Search import * +from .HTTP_Codes import * __author__ = 'Sam Zick' __email__ = 'sam@deathbybandaid.net' From 86b8a0f4bc2aa94f69a66587c42d82c20e4c99be Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:14:01 -0400 Subject: [PATCH 10/23] test --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index 011a7c2..3f7df34 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -23,6 +23,7 @@ def bot_command_http_codes(bot, trigger, botcom): query = spicemanip(botcom.dict["args"], 1) or None if not query: return bot.osd("You must provide a HTTP status code to look up.") + bot.say(str(query)) result = fetch_result(query) bot.osd(["[HTTP code search for " + str(query) + "]", result]) From 26719216caf2f1c6ed7ab8d17c81060665b8e7a0 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:15:30 -0400 Subject: [PATCH 11/23] test --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index 3f7df34..ec85faa 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -23,8 +23,7 @@ def bot_command_http_codes(bot, trigger, botcom): query = spicemanip(botcom.dict["args"], 1) or None if not query: return bot.osd("You must provide a HTTP status code to look up.") - bot.say(str(query)) - result = fetch_result(query) + result = fetch_result(str(query)) bot.osd(["[HTTP code search for " + str(query) + "]", result]) From 6482487f9d5433c7efd3256a774f1f3210c34b80 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:17:25 -0400 Subject: [PATCH 12/23] test --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index ec85faa..928ce78 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -13,7 +13,7 @@ import requests import bleach from lxml import etree -api_url = 'https://httpstatuses.com/%s' +api_url = 'https://httpstatuses.com/' @SpiceBot.prerun('module') @@ -32,7 +32,7 @@ def fetch_result(query): if not re.match('^[1-5]\d{2}$', query): return "Invalid HTTP status code: %s" % query - url = api_url % query + url = api_url + query try: r = requests.get(url=url, timeout=(10.0, 4.0)) except requests.exceptions.ConnectTimeout: From 5ebdad391ba8fa7e5610b65d3ff6d92b7659cb48 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:22:50 -0400 Subject: [PATCH 13/23] test --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index 928ce78..3167846 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -47,6 +47,7 @@ def fetch_result(query): r.raise_for_status() except requests.exceptions.HTTPError as e: return "HTTP error: " + e.message + return "testing" page = etree.HTML(r.content) title = bleach.clean(etree.tostring(page.xpath('/html/body/article/h1[1]')[0]), tags=[], strip=True) From 6413ddf14892435d58d92a8fbc56ae0c3efd706d Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:31:27 -0400 Subject: [PATCH 14/23] test --- .../SpiceBot_Core_Tools/HTTP_Codes.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index 3167846..4ca3d79 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -13,6 +13,8 @@ import requests import bleach from lxml import etree +from lxml import html + api_url = 'https://httpstatuses.com/' @@ -49,6 +51,25 @@ def fetch_result(query): return "HTTP error: " + e.message return "testing" + tree = html.fromstring(r.content) + + try: + title = tree.xpath(('/html/body/article/p[1]')[0]) + # if isinstance(title, list): + # title = title[0] + # title = str(title) + # for r in (("u'", ""), ("['", ""), ("[", ""), ("']", ""), ("\\n", ""), ("\\t", "")): + # title = title.replace(*r) + # title = unicode_string_cleanup(title) + except Exception as e: + title = None + if title: + return title + else: + return "An Error Occured" + + return + page = etree.HTML(r.content) title = bleach.clean(etree.tostring(page.xpath('/html/body/article/h1[1]')[0]), tags=[], strip=True) summary = bleach.clean( From f8d0e8ac144c7a57d472e2d13433a2fbf90a270e Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:32:47 -0400 Subject: [PATCH 15/23] test --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index 4ca3d79..fb2eb90 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -49,7 +49,6 @@ def fetch_result(query): r.raise_for_status() except requests.exceptions.HTTPError as e: return "HTTP error: " + e.message - return "testing" tree = html.fromstring(r.content) From f23df8a74781370b06590012d1c16772980345e2 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:38:42 -0400 Subject: [PATCH 16/23] test --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index fb2eb90..65e4210 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -16,6 +16,7 @@ from lxml import etree from lxml import html api_url = 'https://httpstatuses.com/' +basic_xpath = "/html/body/article/h1[1]/text()" @SpiceBot.prerun('module') @@ -52,8 +53,11 @@ def fetch_result(query): tree = html.fromstring(r.content) + title = tree.xpath((basic_xpath)) + return str(title) + try: - title = tree.xpath(('/html/body/article/p[1]')[0]) + title = tree.xpath((basic_xpath)) # if isinstance(title, list): # title = title[0] # title = str(title) @@ -63,15 +67,6 @@ def fetch_result(query): except Exception as e: title = None if title: - return title + return str(title) else: return "An Error Occured" - - return - - page = etree.HTML(r.content) - title = bleach.clean(etree.tostring(page.xpath('/html/body/article/h1[1]')[0]), tags=[], strip=True) - summary = bleach.clean( - re.sub('.*?<\/a>', '', etree.tostring(page.xpath('/html/body/article/p[1]')[0])), tags=[], - strip=True) - return "{title}: {summary} — {link}".format(title=title, summary=summary, link=url) From aaf74c418c2edc4e7a8dafb9b3440a2609ccc0fe Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:40:35 -0400 Subject: [PATCH 17/23] test --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index 65e4210..d9e72c2 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -53,13 +53,10 @@ def fetch_result(query): tree = html.fromstring(r.content) - title = tree.xpath((basic_xpath)) - return str(title) - try: title = tree.xpath((basic_xpath)) - # if isinstance(title, list): - # title = title[0] + if isinstance(title, list): + title = title[0] # title = str(title) # for r in (("u'", ""), ("['", ""), ("[", ""), ("']", ""), ("\\n", ""), ("\\t", "")): # title = title.replace(*r) From 1aa68fe21aab6b970496a1c76571ce5d74386daa Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:41:08 -0400 Subject: [PATCH 18/23] remove imports --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index d9e72c2..de15aba 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -10,9 +10,6 @@ import sopel_modules.SpiceBot as SpiceBot import re import requests -import bleach -from lxml import etree - from lxml import html api_url = 'https://httpstatuses.com/' From 17789c120a1b4473a00f59043ac7bb5bcc5682e9 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 09:47:23 -0400 Subject: [PATCH 19/23] test --- .../SpiceBot_Core_Tools/HTTP_Codes.py | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index de15aba..7911264 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -14,22 +14,22 @@ from lxml import html api_url = 'https://httpstatuses.com/' basic_xpath = "/html/body/article/h1[1]/text()" +explain_xpath = "/html/body/article/p[1]/text()" @SpiceBot.prerun('module') @sopel.module.commands('httpcode') def bot_command_http_codes(bot, trigger, botcom): - query = spicemanip(botcom.dict["args"], 1) or None if not query: return bot.osd("You must provide a HTTP status code to look up.") + message = ["[HTTP code search for " + str(query) + "]"] result = fetch_result(str(query)) - - bot.osd(["[HTTP code search for " + str(query) + "]", result]) + message.extend(result) + bot.osd(message) def fetch_result(query): - if not re.match('^[1-5]\d{2}$', query): return "Invalid HTTP status code: %s" % query url = api_url + query @@ -49,18 +49,26 @@ def fetch_result(query): return "HTTP error: " + e.message tree = html.fromstring(r.content) - + dispmsg = [] try: title = tree.xpath((basic_xpath)) if isinstance(title, list): title = title[0] - # title = str(title) - # for r in (("u'", ""), ("['", ""), ("[", ""), ("']", ""), ("\\n", ""), ("\\t", "")): - # title = title.replace(*r) - # title = unicode_string_cleanup(title) except Exception as e: title = None if title: - return str(title) - else: - return "An Error Occured" + dispmsg.append(str(title)) + + try: + explanation = tree.xpath((explain_xpath)) + if isinstance(explanation, list): + explanation = explanation[0] + except Exception as e: + explanation = None + if explanation: + dispmsg.append(str(explanation)) + + if not len(dispmsg): + dispmsg.append("An Error Occured Finding This Information") + + return dispmsg From 584f56e6968b1f67fde213e27c5328f3a25ab0f6 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 10:04:40 -0400 Subject: [PATCH 20/23] test --- sopel_modules/SpiceBot/HTTP_Codes.py | 80 +++++++++++++++++++ sopel_modules/SpiceBot/Version.py | 2 +- sopel_modules/SpiceBot/__init__.py | 1 + .../SpiceBot_Release_Notes/HTTP_Codes.txt | 2 + .../SpiceBot_Core_Tools/HTTP_Codes.py | 4 +- 5 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 sopel_modules/SpiceBot/HTTP_Codes.py create mode 100644 sopel_modules/SpiceBot_Configs/SpiceBot_Release_Notes/HTTP_Codes.txt diff --git a/sopel_modules/SpiceBot/HTTP_Codes.py b/sopel_modules/SpiceBot/HTTP_Codes.py new file mode 100644 index 0000000..69cfd0f --- /dev/null +++ b/sopel_modules/SpiceBot/HTTP_Codes.py @@ -0,0 +1,80 @@ +# coding=utf8 +from __future__ import unicode_literals, absolute_import, division, print_function +""" +This is the SpiceBot HTTP Codes system. +""" + +import re +import requests +from lxml import html + + +class Bothttpcodes(): + + def __init__(self): + self.api_url = 'https://httpstatuses.com/' + self.basic_xpath = "/html/body/article/h1[1]/text()" + self.explain_xpath = "/html/body/article/p[1]/text()" + + def fetch_result(self, query): + returndict = { + "basic": "", + "explanation": "", + } + if not re.match('^[1-5]\d{2}$', query): + returndict["basic"] = "Invalid HTTP status code:" + returndict["explanation"] = str(query) + return returndict + + url = self.api_url + query + try: + r = requests.get(url=url, timeout=(10.0, 4.0)) + except requests.exceptions.ConnectTimeout: + returndict["basic"] = "Connection timed out." + return returndict + except requests.exceptions.ConnectionError: + returndict["basic"] = "Couldn't connect to server." + return returndict + except requests.exceptions.ReadTimeout: + returndict["basic"] = "Server took too long to send data." + return returndict + if r.status_code == 404: + returndict["basic"] = "Unknown HTTP status code:" + returndict["explanation"] = str(query) + return returndict + try: + r.raise_for_status() + except requests.exceptions.HTTPError as e: + returndict["basic"] = "HTTP error:" + returndict["explanation"] = str(e.message) + return returndict + + tree = html.fromstring(r.content) + try: + title = tree.xpath((self.basic_xpath)) + if isinstance(title, list): + title = title[0] + except Exception as e: + title = None + if title: + returndict["basic"] = str(title) + else: + returndict["basic"] = "An Error Occured:" + returndict["explanation"] = "Xpath for basic yeilded no information" + return returndict + + try: + explanation = tree.xpath((self.explain_xpath)) + if isinstance(explanation, list): + explanation = explanation[0] + except Exception as e: + explanation = None + if explanation: + returndict["explanation"] = str(explanation) + else: + returndict["explanation"] = "Xpath for explanation yeilded no information" + + return returndict + + +httpcodes = Bothttpcodes() diff --git a/sopel_modules/SpiceBot/Version.py b/sopel_modules/SpiceBot/Version.py index ad308de..a6c4a0b 100644 --- a/sopel_modules/SpiceBot/Version.py +++ b/sopel_modules/SpiceBot/Version.py @@ -1,7 +1,7 @@ # coding=utf8 from __future__ import unicode_literals, absolute_import, division, print_function """ -This is the SpiceBot Update system. +This is the SpiceBot Version system. """ import sopel diff --git a/sopel_modules/SpiceBot/__init__.py b/sopel_modules/SpiceBot/__init__.py index 90f1629..556fa86 100644 --- a/sopel_modules/SpiceBot/__init__.py +++ b/sopel_modules/SpiceBot/__init__.py @@ -40,6 +40,7 @@ from .Translate import * from .Version import * from .RegNicks import * from .ReleaseNotes import * +from .HTTP_Codes import * __author__ = 'Sam Zick' diff --git a/sopel_modules/SpiceBot_Configs/SpiceBot_Release_Notes/HTTP_Codes.txt b/sopel_modules/SpiceBot_Configs/SpiceBot_Release_Notes/HTTP_Codes.txt new file mode 100644 index 0000000..c6ba1d6 --- /dev/null +++ b/sopel_modules/SpiceBot_Configs/SpiceBot_Release_Notes/HTTP_Codes.txt @@ -0,0 +1,2 @@ +Added Tool to check HTTP code meanings, accessible via `.httpcodes` command +Migrated Functionality into a SpiceBot class for other tools to use diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index 7911264..0db2c58 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -24,8 +24,8 @@ def bot_command_http_codes(bot, trigger, botcom): if not query: return bot.osd("You must provide a HTTP status code to look up.") message = ["[HTTP code search for " + str(query) + "]"] - result = fetch_result(str(query)) - message.extend(result) + result = SpiceBot.httpcodes.fetch_result(str(query)) + message.append([result["basic"], result["explanation"]]) bot.osd(message) From 1a09a7e7b17369680d9337ce057883c22841deb6 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 10:07:42 -0400 Subject: [PATCH 21/23] test --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index 0db2c58..8ecfc7d 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -25,6 +25,8 @@ def bot_command_http_codes(bot, trigger, botcom): return bot.osd("You must provide a HTTP status code to look up.") message = ["[HTTP code search for " + str(query) + "]"] result = SpiceBot.httpcodes.fetch_result(str(query)) + bot.say(result["basic"]) + bot.say(result["explanation"]) message.append([result["basic"], result["explanation"]]) bot.osd(message) From 3b524842704e48d2ed39c348523884776b45cee6 Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 10:08:55 -0400 Subject: [PATCH 22/23] test --- sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index 8ecfc7d..d4cb625 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -25,9 +25,7 @@ def bot_command_http_codes(bot, trigger, botcom): return bot.osd("You must provide a HTTP status code to look up.") message = ["[HTTP code search for " + str(query) + "]"] result = SpiceBot.httpcodes.fetch_result(str(query)) - bot.say(result["basic"]) - bot.say(result["explanation"]) - message.append([result["basic"], result["explanation"]]) + message.extend([result["basic"], result["explanation"]]) bot.osd(message) From c85a0fc473e96be197a6a59c1b6efc16c9e58faf Mon Sep 17 00:00:00 2001 From: deathbybandaid Date: Fri, 4 Oct 2019 10:10:21 -0400 Subject: [PATCH 23/23] remove old code --- .../SpiceBot_Core_Tools/HTTP_Codes.py | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py index d4cb625..7279ada 100644 --- a/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py +++ b/sopel_modules/SpiceBot_Core_Tools/HTTP_Codes.py @@ -8,14 +8,6 @@ from sopel_modules.spicemanip import spicemanip import sopel_modules.SpiceBot as SpiceBot -import re -import requests -from lxml import html - -api_url = 'https://httpstatuses.com/' -basic_xpath = "/html/body/article/h1[1]/text()" -explain_xpath = "/html/body/article/p[1]/text()" - @SpiceBot.prerun('module') @sopel.module.commands('httpcode') @@ -27,48 +19,3 @@ def bot_command_http_codes(bot, trigger, botcom): result = SpiceBot.httpcodes.fetch_result(str(query)) message.extend([result["basic"], result["explanation"]]) bot.osd(message) - - -def fetch_result(query): - if not re.match('^[1-5]\d{2}$', query): - return "Invalid HTTP status code: %s" % query - url = api_url + query - try: - r = requests.get(url=url, timeout=(10.0, 4.0)) - except requests.exceptions.ConnectTimeout: - return "Connection timed out." - except requests.exceptions.ConnectionError: - return "Couldn't connect to server." - except requests.exceptions.ReadTimeout: - return "Server took too long to send data." - if r.status_code == 404: - return "Unknown HTTP status code: %s" % query - try: - r.raise_for_status() - except requests.exceptions.HTTPError as e: - return "HTTP error: " + e.message - - tree = html.fromstring(r.content) - dispmsg = [] - try: - title = tree.xpath((basic_xpath)) - if isinstance(title, list): - title = title[0] - except Exception as e: - title = None - if title: - dispmsg.append(str(title)) - - try: - explanation = tree.xpath((explain_xpath)) - if isinstance(explanation, list): - explanation = explanation[0] - except Exception as e: - explanation = None - if explanation: - dispmsg.append(str(explanation)) - - if not len(dispmsg): - dispmsg.append("An Error Occured Finding This Information") - - return dispmsg