Merge pull request #41 from deathbybandaid/development

Development
This commit is contained in:
Deathbybandaid 2019-05-20 09:00:01 -04:00 committed by GitHub
commit b0ad4cd2ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 2167 additions and 808 deletions

View File

@ -20,7 +20,8 @@ rm dev-requirements.txt
wget https://raw.githubusercontent.com/SpiceBot/SpiceBot/development/Installation%20Files/requirements.txt wget https://raw.githubusercontent.com/SpiceBot/SpiceBot/development/Installation%20Files/requirements.txt
pip3 install -r requirements.txt pip3 install -r requirements.txt
rm requirements.txt rm requirements.txt
pip3 install sopel # pip3 install sopel
pip3 install --upgrade --force-reinstall git+https://github.com/sopel-irc/sopel@master
mkdir /usr/local/lib/python3.6/dist-packages/sopel/modules/stock mkdir /usr/local/lib/python3.6/dist-packages/sopel/modules/stock
mv /usr/local/lib/python3.6/dist-packages/sopel/modules/* /usr/local/lib/python3.6/dist-packages/sopel/modules/stock/ mv /usr/local/lib/python3.6/dist-packages/sopel/modules/* /usr/local/lib/python3.6/dist-packages/sopel/modules/stock/

View File

@ -0,0 +1,77 @@
# coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function
"""
This is the SpiceBot Logs system.
This Class stores logs in an easy to access manner
"""
import sopel
import re
class BotChannels():
"""This Logs all channels known to the server"""
def __init__(self):
self.channel_lock = False
self.SpiceBot_Channels = {
"list": {},
"InitialProcess": False
}
def channel_list_request(self, bot):
bot.write(['LIST'])
def channel_list_recieve_start(self):
self.channel_lock = True
def channel_list_recieve_input(self, trigger):
channel, _, topic = trigger.args[1:]
if channel.lower() not in self.SpiceBot_Channels['list'].keys():
self.SpiceBot_Channels['list'][channel.lower()] = dict()
self.SpiceBot_Channels['list'][channel.lower()]['name'] = channel
self.SpiceBot_Channels['list'][channel.lower()]['topic'] = self.topic_compile(topic)
self.channel_lock = True
def channel_list_recieve_finish(self):
if not self.SpiceBot_Channels['InitialProcess']:
self.SpiceBot_Channels['InitialProcess'] = True
self.channel_lock = False
def topic_compile(self, topic):
actual_topic = re.compile(r'^\[\+[a-zA-Z]+\] (.*)')
topic = re.sub(actual_topic, r'\1', topic)
return topic
def bot_part_empty(self, bot):
"""Don't stay in empty channels"""
ignorepartlist = []
if bot.config.core.logging_channel:
ignorepartlist.append(bot.config.core.logging_channel)
for channel in bot.channels.keys():
if len(bot.channels[channel].privileges.keys()) == 1 and channel not in ignorepartlist and channel.startswith("#"):
bot.part(channel, "Leaving Empty Channel")
if channel.lower() in botchannels.SpiceBot_Channels['list']:
del botchannels.SpiceBot_Channels['list'][channel.lower()]
def join_all_channels(self, bot):
if bot.config.SpiceBot_Channels.joinall:
for channel in botchannels.SpiceBot_Channels['list'].keys():
if channel.startswith("#"):
if channel not in bot.channels.keys() and channel not in bot.config.SpiceBot_Channels.chanignore:
bot.write(('JOIN', bot.nick, botchannels.SpiceBot_Channels['list'][channel]['name']))
if channel not in bot.channels.keys() and bot.config.SpiceBot_Channels.operadmin:
bot.write(('SAJOIN', bot.nick, botchannels.SpiceBot_Channels['list'][channel]['name']))
def chanadmin_all_channels(self, bot):
# Chan ADMIN +a
for channel in bot.channels.keys():
if channel.startswith("#"):
if channel not in bot.config.SpiceBot_Channels.chanignore:
if bot.config.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)
botchannels = BotChannels()

View File

@ -0,0 +1,129 @@
# coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function
"""
This is the SpiceBot events system.
We utilize the Sopel code for event numbers and
self-trigger the bot into performing actions
"""
import sopel
import functools
class BotEvents(object):
"""A dynamic listing of all the notable Bot numeric events.
Events will be assigned a 4-digit number above 1000.
This allows you to do, ``@module.event(botevents.BOT_WELCOME)````
Triggers handled by this module will be processed immediately.
Others will be placed into a queue.
Triggers will be logged by ID and content
"""
def __init__(self):
self.RPL_WELCOME = '001' # This is a defined IRC event
self.BOT_WELCOME = '1001'
self.BOT_READY = '1002'
self.BOT_CONNECTED = '1003'
self.BOT_LOADED = '1004'
self.BOT_RECONNECTED = '1005'
self.defaultevents = [self.BOT_WELCOME, self.BOT_READY, self.BOT_CONNECTED, self.BOT_LOADED, self.BOT_RECONNECTED]
self.SpiceBot_Events = {
"assigned_IDs": {1000: "Default", 1001: "BOT_WELCOME", 1002: "BOT_READY", 1003: "BOT_CONNECTED", 1004: "BOT_LOADED", 1005: "BOT_RECONNECTED"},
"triggers_recieved": {},
"trigger_queue": [],
"startup_required": [self.BOT_WELCOME, self.BOT_READY, self.BOT_CONNECTED],
"RPL_WELCOME_Count": 0
}
def __getattr__(self, name):
''' will only get called for undefined attributes '''
eventnumber = max(list(self.SpiceBot_Events["assigned_IDs"].keys())) + 1
self.SpiceBot_Events["assigned_IDs"][eventnumber] = str(name)
setattr(self, name, str(eventnumber))
return str(eventnumber)
def trigger(self, bot, number, message="SpiceBot_Events"):
pretriggerdict = {"number": str(number), "message": message}
if number in self.defaultevents:
self.dispatch(bot, pretriggerdict)
else:
self.SpiceBot_Events["trigger_queue"].append(pretriggerdict)
def dispatch(self, bot, pretriggerdict):
number = pretriggerdict["number"]
message = pretriggerdict["message"]
pretrigger = sopel.trigger.PreTrigger(
bot.nick,
":SpiceBot_Events " + str(number) + " " + str(bot.nick) + " :" + message
)
bot.dispatch(pretrigger)
self.recieved({"number": number, "message": message})
def recieved(self, trigger):
if isinstance(trigger, dict):
eventnumber = str(trigger["number"])
message = str(trigger["message"])
else:
eventnumber = str(trigger.event)
message = trigger.args[1]
if eventnumber not in self.SpiceBot_Events["triggers_recieved"]:
self.SpiceBot_Events["triggers_recieved"][eventnumber] = []
self.SpiceBot_Events["triggers_recieved"][eventnumber].append(message)
def check(self, checklist):
if not isinstance(checklist, list):
checklist = [str(checklist)]
for number in checklist:
if str(number) not in self.SpiceBot_Events["triggers_recieved"].keys():
return False
return True
def startup_add(self, startlist):
if not isinstance(startlist, list):
startlist = [str(startlist)]
self.SpiceBot_Events["startup_required"].extend(startlist)
def startup_check(self):
for number in self.SpiceBot_Events["startup_required"]:
if str(number) not in self.SpiceBot_Events["triggers_recieved"].keys():
return False
return True
def startup_debug(self):
not_done = []
for number in self.SpiceBot_Events["startup_required"]:
if str(number) not in self.SpiceBot_Events["triggers_recieved"].keys():
not_done.append(int(number))
reference_not_done = []
for item in not_done:
reference_not_done.append(str(self.SpiceBot_Events["assigned_IDs"][item]))
return reference_not_done
def check_ready(self, checklist):
def actual_decorator(function):
@functools.wraps(function)
def _nop(*args, **kwargs):
while not self.check(checklist):
pass
return function(*args, **kwargs)
return _nop
return actual_decorator
def startup_check_ready(self):
def actual_decorator(function):
@functools.wraps(function)
def _nop(*args, **kwargs):
while not self.startup_check():
pass
return function(*args, **kwargs)
return _nop
return actual_decorator
botevents = BotEvents()

View File

@ -0,0 +1,106 @@
# coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function
"""
This is the SpiceBot Logs system.
This Class stores logs in an easy to access manner
"""
import sopel
import os
import spicemanip
class botlogs():
"""This Is a contained source of log information"""
def __init__(self):
self.SpiceBot_Logs = {
"list": {"Sopel_systemd": [], "Sopel_stdio": []},
"queue": []
}
self.sopel_config = {
"logging_channel": True
}
def log(self, logtype, logentry, stdio=False):
logtitle = "[" + logtype + "]"
logmessage = logtitle + " " + logentry
if self.sopel_config["logging_channel"]:
self.SpiceBot_Logs["queue"].append(logmessage)
if stdio:
sopel.tools.stderr(logmessage)
if logtype not in self.SpiceBot_Logs["list"].keys():
self.SpiceBot_Logs["list"][logtype] = []
self.SpiceBot_Logs["list"][logtype].append(logentry)
def get_logs(self):
return []
def stdio_logs_fetch(self, bot):
stdio_ignore = []
for logtype in botlogs.SpiceBot_Logs["list"].keys():
stdio_ignore.append("[" + logtype + "]")
logfile = os.path.os.path.join(bot.config.core.logdir, 'stdio.log')
try:
log_file_lines = []
log_file = open(logfile, 'r')
lines = log_file.readlines()
for line in lines:
log_file_lines.append(line)
log_file.close()
currentline, linenumindex = 0, []
for line in log_file_lines:
if line.startswith("Welcome to Sopel. Loading modules..."):
linenumindex.append(currentline)
currentline += 1
last_start = max(linenumindex)
filelines = log_file_lines[last_start:]
except Exception as e:
debuglines = e
filelines = []
debuglines = []
loadedmodules = []
for line in filelines:
if line.startswith("Loaded:"):
loadedmodules.append(str(line).split("Loaded:")[-1])
else:
if not line.startswith(tuple(stdio_ignore)) and not line.isspace():
debuglines.append(str(line))
loadedmodules = "Loaded: " + spicemanip.main(loadedmodules, 'andlist')
debuglines.insert(1, loadedmodules)
return debuglines
def systemd_logs_fetch(self, bot):
servicepid = self.get_running_pid(bot)
debuglines = []
for line in os.popen(str("sudo journalctl _PID=" + str(servicepid))).read().split('\n'):
line = str(line).split(str(os.uname()[1] + " "))[-1]
lineparts = str(line).split(": ")
del lineparts[0]
line = spicemanip.main(lineparts, 0)
if not line.isspace():
debuglines.append(str(line))
return debuglines
def get_running_pid(self, bot):
try:
filename = "/run/sopel/sopel-" + str(bot.nick) + ".pid"
with open(filename, 'r') as pid_file:
pidnum = int(pid_file.read())
except Exception as e:
pidnum = e
pidnum = str(os.popen("systemctl show " + str(bot.nick) + " --property=MainPID").read()).split("=")[-1]
return pidnum
botlogs = botlogs()

View File

@ -0,0 +1,15 @@
# coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function
"""
These are the core SpiceBot Classes
This module contains references only for other modules to utilize.
"""
from .Logs import *
from .Events import *
from .Channels import *
__author__ = 'Sam Zick'
__email__ = 'sam@deathbybandaid.net'
__version__ = '0.1.1'

View File

@ -7,15 +7,13 @@ import sopel.module
import spicemanip import spicemanip
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, googlesearch, bot_privs, inlist, inlist_match, similar_list from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, googlesearch, bot_privs, inlist, inlist_match, similar_list
from sopel_modules.SpiceBot_Events.System import bot_events_check, botevents from sopel_modules.SpiceBot.Events import botevents
@botevents.check_ready([botevents.BOT_LOADED, botevents.BOT_COMMANDSQUERY])
@sopel.module.nickname_commands('(.*)') @sopel.module.nickname_commands('(.*)')
def bot_command_nick(bot, trigger): def bot_command_nick(bot, trigger):
while not bot_events_check(bot, [botevents.BOT_LOADED, botevents.BOT_COMMANDSQUERY]):
pass
triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'nickname_command') triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'nickname_command')
if not triggercommand: if not triggercommand:

View File

@ -0,0 +1,18 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
import spicemanip
@sopel.module.rule(r'(?i)(really),? $nickname\?')
def bot_command_really(bot, trigger):
really = spicemanip.main(["Yes, really.", "Really really"], "random")
bot.reply(really)
@sopel.module.rule('$nickname really\?')
def bot_command_really_b(bot, trigger):
bot_command_really(bot, trigger)

View File

@ -0,0 +1,13 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
import spicemanip
@sopel.module.rule(r'(?i)(welcome back),? $nickname\?')
def bot_command_really(bot, trigger):
reply = spicemanip.main(['Thank you', 'thanks'], "random")
bot.reply(reply)

View File

@ -10,6 +10,8 @@ from .AI_Lazy import *
from .AI_InsultHandler import * from .AI_InsultHandler import *
from .AI_Ping import * from .AI_Ping import *
from .AI_Love import * from .AI_Love import *
from .AI_Really import *
from .AI_Welcomeback import *
__author__ = 'Sam Zick' __author__ = 'Sam Zick'
__email__ = 'sam@deathbybandaid.net' __email__ = 'sam@deathbybandaid.net'

View File

@ -1,129 +0,0 @@
#!/usr/bin/env python
# coding=utf-8
from __future__ import unicode_literals, absolute_import, print_function, division
# sopel imports
import sopel.module
from sopel.config.types import StaticSection, ValidatedAttribute, ListAttribute
from sopel_modules.SpiceBot_Events.System import bot_events_startup_register, bot_events_recieved, bot_events_trigger, botevents
from sopel_modules.SpiceBot_SBTools import (
join_all_channels, chanadmin_all_channels, channel_list_current,
bot_logging
)
import spicemanip
import time
class SpiceBot_Channels_MainSection(StaticSection):
announcenew = ValidatedAttribute('announcenew', default=False)
joinall = ValidatedAttribute('joinall', default=False)
operadmin = ValidatedAttribute('operadmin', default=False)
chanignore = ListAttribute('chanignore')
def configure(config):
config.define_section("SpiceBot_Channels", SpiceBot_Channels_MainSection, validate=False)
config.SpiceBot_Channels.configure_setting('announcenew', 'SpiceBot_Channels Announce New Channels')
config.SpiceBot_Channels.configure_setting('announcenew', 'SpiceBot_Channels JOIN New Channels')
config.SpiceBot_Channels.configure_setting('announcenew', 'SpiceBot_Channels OPER ADMIN MODE')
config.SpiceBot_Channels.configure_setting('chanignore', 'SpiceBot_Channels Ignore JOIN for channels')
def setup(bot):
bot_logging(bot, 'SpiceBot_Channels', "Starting setup procedure")
bot_events_startup_register(bot, [botevents.BOT_CHANNELS])
bot.config.define_section("SpiceBot_Channels", SpiceBot_Channels_MainSection, validate=False)
if "SpiceBot_Channels" not in bot.memory:
bot.memory["SpiceBot_Channels"] = {"channels": {}, "InitialProcess": False, "ProcessLock": False}
def shutdown(bot):
if "SpiceBot_Channels" in bot.memory:
del bot.memory["SpiceBot_Channels"]
@sopel.module.event(botevents.BOT_CONNECTED)
@sopel.module.rule('.*')
def trigger_channel_list_initial(bot, trigger):
bot_events_recieved(bot, trigger.event)
# Unkickable
bot.write(('SAMODE', bot.nick, '+q'))
bot_part_empty(bot)
bot.write(['LIST'])
bot.memory['SpiceBot_Channels']['ProcessLock'] = True
bot_logging(bot, 'SpiceBot_Channels', "Initial Channel list populating")
starttime = time.time()
while not bot.memory['SpiceBot_Channels']['InitialProcess']:
timesince = time.time() - starttime
if timesince < 60:
pass
else:
bot_logging(bot, 'SpiceBot_Channels', "Initial Channel list populating Timed Out")
bot.memory['SpiceBot_Channels']['InitialProcess'] = True
channel_list_current(bot)
foundchannelcount = len(bot.memory['SpiceBot_Channels']['channels'].keys())
bot_logging(bot, 'SpiceBot_Channels', "Channel listing finished! " + str(foundchannelcount) + " channel(s) found.")
bot_events_trigger(bot, botevents.BOT_CHANNELS, "SpiceBot_Channels")
join_all_channels(bot)
chanadmin_all_channels(bot)
if "*" in bot.memory['SpiceBot_Channels']['channels']:
del bot.memory['SpiceBot_Channels']['channels']["*"]
bot_part_empty(bot)
while True:
try:
time.sleep(1800)
bot_part_empty(bot)
oldlist = list(bot.memory['SpiceBot_Channels']['channels'].keys())
bot.write(['LIST'])
bot.memory['SpiceBot_Channels']['ProcessLock'] = True
while bot.memory['SpiceBot_Channels']['ProcessLock']:
pass
newlist = [item.lower() for item in oldlist if item.lower() not in bot.memory['SpiceBot_Channels']['channels']]
if "*" in newlist:
newlist.remove("*")
if len(newlist) and bot.config.SpiceBot_Channels.announcenew:
bot.osd(["The Following channel(s) are new:", spicemanip.main(newlist, 'andlist')], bot.channels.keys())
join_all_channels(bot)
chanadmin_all_channels(bot)
if "*" in bot.memory['SpiceBot_Channels']['channels']:
del bot.memory['SpiceBot_Channels']['channels']["*"]
bot_part_empty(bot)
except KeyError:
return
def bot_part_empty(bot):
ignorepartlist = []
if bot.config.SpiceBot_Logs.logging_channel:
ignorepartlist.append(bot.config.SpiceBot_Logs.logging_channel)
for channel in bot.channels.keys():
if len(bot.channels[channel].privileges.keys()) == 1 and channel not in ignorepartlist:
bot.part(channel, "Leaving Empty Channel")
if channel.lower() in bot.memory['SpiceBot_Channels']['channels']:
del bot.memory['SpiceBot_Channels']['channels'][channel.lower()]
@sopel.module.event(botevents.BOT_CHANNELS)
@sopel.module.rule('.*')
def bot_events_setup(bot, trigger):
bot_events_recieved(bot, trigger.event)

View File

@ -1,32 +0,0 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot_SBTools import topic_compile
@sopel.module.event('321')
@sopel.module.rule('.*')
def watch_chanlist_start(bot, trigger):
bot.memory['SpiceBot_Channels']['ProcessLock'] = True
@sopel.module.event('322')
@sopel.module.rule('.*')
def watch_chanlist_populate(bot, trigger):
channel, _, topic = trigger.args[1:]
if channel.lower() not in bot.memory['SpiceBot_Channels']['channels']:
bot.memory['SpiceBot_Channels']['channels'][channel.lower()] = dict()
bot.memory['SpiceBot_Channels']['channels'][channel.lower()]['name'] = channel
bot.memory['SpiceBot_Channels']['channels'][channel.lower()]['topic'] = topic_compile(topic)
bot.memory['SpiceBot_Channels']['ProcessLock'] = True
@sopel.module.event('323')
@sopel.module.rule('.*')
def watch_chanlist_complete(bot, trigger):
bot.memory['SpiceBot_Channels']['ProcessLock'] = False
if not bot.memory['SpiceBot_Channels']['InitialProcess']:
bot.memory['SpiceBot_Channels']['InitialProcess'] = True

View File

@ -6,20 +6,15 @@ import sopel.module
import spicemanip import spicemanip
from sopel_modules.SpiceBot_Events.System import bot_events_check, botevents from sopel_modules.SpiceBot.Events import botevents
from sopel_modules.SpiceBot_SBTools import ( from sopel_modules.SpiceBot.Channels import botchannels
sopel_triggerargs, inlist, channel_privs, from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, inlist, channel_privs
join_all_channels, channel_list_current,
)
from .Channels import bot_part_empty
@botevents.check_ready([botevents.BOT_LOADED])
@sopel.module.nickname_commands('channels', 'channel') @sopel.module.nickname_commands('channels', 'channel')
def nickname_comand_channels(bot, trigger): def nickname_comand_channels(bot, trigger):
while not bot_events_check(bot, botevents.BOT_LOADED):
pass
triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'nickname_command') triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'nickname_command')
if not len(triggerargs): if not len(triggerargs):
@ -29,8 +24,6 @@ def nickname_comand_channels(bot, trigger):
triggerargs = spicemanip.main(triggerargs, '2+', 'list') triggerargs = spicemanip.main(triggerargs, '2+', 'list')
channel_list_current(bot)
if commandused == 'list': if commandused == 'list':
chanlist = spicemanip.main(bot.channels.keys(), 'andlist') chanlist = spicemanip.main(bot.channels.keys(), 'andlist')
bot.osd("You can find me in " + chanlist) bot.osd("You can find me in " + chanlist)
@ -38,14 +31,14 @@ def nickname_comand_channels(bot, trigger):
elif commandused == 'total': elif commandused == 'total':
botcount = len(bot.channels.keys()) botcount = len(bot.channels.keys())
servercount = len(bot.memory['SpiceBot_Channels']['channels'].keys()) servercount = len(botchannels.SpiceBot_Channels['list'].keys())
bot.osd("I am in " + str(botcount) + " of " + str(servercount) + " channel(s) available on this server.") bot.osd("I am in " + str(botcount) + " of " + str(servercount) + " channel(s) available on this server.")
return return
elif commandused == 'random': elif commandused == 'random':
channel = spicemanip.main(bot.memory['SpiceBot_Channels']['channels'], 'random') channel = spicemanip.main(botchannels.SpiceBot_Channels['list'], 'random')
topic = bot.memory['SpiceBot_Channels']['channels'][channel]['topic'] topic = botchannels.SpiceBot_Channels['list'][channel]['topic']
msg = ["Random channel for you: {}.".format(bot.memory['SpiceBot_Channels']['channels'][channel]['name'])] msg = ["Random channel for you: {}.".format(botchannels.SpiceBot_Channels['list'][channel]['name'])]
if topic and not topic.isspace(): if topic and not topic.isspace():
msg.append("The topic is: {}".format(topic)) msg.append("The topic is: {}".format(topic))
else: else:
@ -57,16 +50,15 @@ def nickname_comand_channels(bot, trigger):
if not trigger.admin: if not trigger.admin:
bot.osd("You do not have permission to update the channel listing.") bot.osd("You do not have permission to update the channel listing.")
return return
bot_part_empty(bot) botchannels.bot_part_empty(bot)
bot.write(['LIST']) botchannels.channel_list_request(bot)
bot.osd(["[SpiceBot_Channels]", "I am now updating the channel listing for this server."]) bot.osd(["[SpiceBot_Channels]", "I am now updating the channel listing for this server."])
bot.memory['SpiceBot_Channels']['ProcessLock'] = True while botchannels.channel_lock:
while bot.memory['SpiceBot_Channels']['ProcessLock']:
pass pass
join_all_channels(bot) botchannels.join_all_channels(bot)
foundchannelcount = len(bot.memory['SpiceBot_Channels']['channels'].keys()) foundchannelcount = len(botchannels.SpiceBot_Channels['list'].keys())
bot.osd("[SpiceBot_Channels]", "Channel listing finished!", str(foundchannelcount) + " channel(s) found.") bot.osd("[SpiceBot_Channels]", "Channel listing finished!", str(foundchannelcount) + " channel(s) found.")
bot_part_empty(bot) botchannels.bot_part_empty(bot)
return return
elif commandused == 'topic': elif commandused == 'topic':
@ -74,11 +66,11 @@ def nickname_comand_channels(bot, trigger):
bot.osd("Channel name input missing.") bot.osd("Channel name input missing.")
return return
channel = spicemanip.main(triggerargs, 1) channel = spicemanip.main(triggerargs, 1)
if not inlist(bot, channel.lower(), bot.memory['SpiceBot_Channels']['channels'].keys()): if not inlist(bot, channel.lower(), botchannels.SpiceBot_Channels['list'].keys()):
bot.osd("Channel name {} not valid.".format(channel)) bot.osd("Channel name {} not valid.".format(channel))
return return
topic = bot.memory['SpiceBot_Channels']['channels'][channel.lower()]['topic'] topic = botchannels.SpiceBot_Channels['list'][channel.lower()]['topic']
channel = bot.memory['SpiceBot_Channels']['channels'][channel.lower()]['name'] channel = botchannels.SpiceBot_Channels['list'][channel.lower()]['name']
bot.osd("Topic for {}: {}".format(channel, topic)) bot.osd("Topic for {}: {}".format(channel, topic))
return return
@ -91,7 +83,7 @@ def nickname_comand_channels(bot, trigger):
channel = trigger.sender channel = trigger.sender
else: else:
channel = spicemanip.main(triggerargs, 1) channel = spicemanip.main(triggerargs, 1)
if not inlist(bot, channel.lower(), bot.memory['SpiceBot_Channels']['channels'].keys()): if not inlist(bot, channel.lower(), botchannels.SpiceBot_Channels['list'].keys()):
bot.osd("Channel name {} not valid.".format(channel)) bot.osd("Channel name {} not valid.".format(channel))
return return
if not inlist(bot, channel.lower(), bot.channels.keys()): if not inlist(bot, channel.lower(), bot.channels.keys()):
@ -111,7 +103,7 @@ def nickname_comand_channels(bot, trigger):
# Users List # Users List
if commandused == 'users': if commandused == 'users':
channel = spicemanip.main(triggerargs, 1) channel = spicemanip.main(triggerargs, 1)
if not inlist(bot, channel.lower(), bot.memory['SpiceBot_Channels']['channels'].keys()): if not inlist(bot, channel.lower(), botchannels.SpiceBot_Channels['list'].keys()):
bot.osd("Channel name {} not valid.".format(channel)) bot.osd("Channel name {} not valid.".format(channel))
return return
if not inlist(bot, channel.lower(), bot.channels.keys()): if not inlist(bot, channel.lower(), bot.channels.keys()):

View File

@ -3,6 +3,4 @@
""" """
from __future__ import unicode_literals, absolute_import, print_function, division from __future__ import unicode_literals, absolute_import, print_function, division
from .Channels import *
from .Channels_Command import * from .Channels_Command import *
from .Channels_Parsing import *

View File

@ -0,0 +1,121 @@
#!/usr/bin/env python
# coding=utf-8
from __future__ import unicode_literals, absolute_import, print_function, division
# sopel imports
import sopel.module
from sopel.config.types import StaticSection, ValidatedAttribute, ListAttribute
from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot.Events import botevents
from sopel_modules.SpiceBot.Channels import botchannels
import spicemanip
import time
class SpiceBot_Channels_MainSection(StaticSection):
announcenew = ValidatedAttribute('announcenew', default=False)
joinall = ValidatedAttribute('joinall', default=False)
operadmin = ValidatedAttribute('operadmin', default=False)
chanignore = ListAttribute('chanignore')
def configure(config):
config.define_section("SpiceBot_Channels", SpiceBot_Channels_MainSection, validate=False)
config.SpiceBot_Channels.configure_setting('announcenew', 'SpiceBot_Channels Announce New Channels')
config.SpiceBot_Channels.configure_setting('joinall', 'SpiceBot_Channels JOIN New Channels')
config.SpiceBot_Channels.configure_setting('operadmin', 'SpiceBot_Channels OPER ADMIN MODE')
config.SpiceBot_Channels.configure_setting('chanignore', 'SpiceBot_Channels Ignore JOIN for channels')
def setup(bot):
botlogs.log('SpiceBot_Channels', "Starting setup procedure")
botevents.startup_add([botevents.BOT_CHANNELS])
bot.config.define_section("SpiceBot_Channels", SpiceBot_Channels_MainSection, validate=False)
@sopel.module.event(botevents.RPL_WELCOME)
@sopel.module.rule('.*')
def unkickable_bot(bot, trigger):
if bot.config.SpiceBot_Channels.operadmin:
bot.write(('SAMODE', bot.nick, '+q'))
@sopel.module.event(botevents.RPL_WELCOME)
@sopel.module.rule('.*')
def request_channels_list_initial(bot, trigger):
botchannels.bot_part_empty(bot)
botlogs.log('SpiceBot_Channels', "Sending Request for all server channels")
botchannels.channel_list_request(bot)
starttime = time.time()
# wait 60 seconds for initial population of information
while not botchannels.SpiceBot_Channels['InitialProcess']:
if time.time() - starttime >= 60:
botlogs.log('SpiceBot_Channels', "Initial Channel list populating Timed Out")
botchannels.SpiceBot_Channels['InitialProcess'] = True
else:
pass
foundchannelcount = len(botchannels.SpiceBot_Channels['list'].keys())
botlogs.log('SpiceBot_Channels', "Channel listing finished! " + str(foundchannelcount) + " channel(s) found.")
botchannels.join_all_channels(bot)
botchannels.chanadmin_all_channels(bot)
if "*" in botchannels.SpiceBot_Channels['list'].keys():
del botchannels.SpiceBot_Channels['list']["*"]
botchannels.bot_part_empty(bot)
botevents.trigger(bot, botevents.BOT_CHANNELS, "SpiceBot_Channels")
@sopel.module.event('321')
@sopel.module.rule('.*')
def watch_chanlist_start(bot, trigger):
botchannels.channel_list_recieve_start()
@sopel.module.event('322')
@sopel.module.rule('.*')
def watch_chanlist_populate(bot, trigger):
botchannels.channel_list_recieve_input(trigger)
@sopel.module.event('323')
@sopel.module.rule('.*')
def watch_chanlist_complete(bot, trigger):
botchannels.channel_list_recieve_finish()
@sopel.module.event(botevents.BOT_CHANNELS)
@sopel.module.rule('.*')
def trigger_channel_list_recurring(bot, trigger):
while True:
time.sleep(1800)
botchannels.bot_part_empty(bot)
oldlist = list(botchannels.SpiceBot_Channels['list'].keys())
botchannels.channel_list_request(bot)
while botchannels.channel_lock:
pass
newlist = [item.lower() for item in oldlist if item.lower() not in list(botchannels.SpiceBot_Channels['list'].keys())]
if "*" in newlist:
newlist.remove("*")
if len(newlist) and bot.config.SpiceBot_Channels.announcenew:
bot.osd(["The Following channel(s) are new:", spicemanip.main(newlist, 'andlist')], bot.channels.keys())
botchannels.join_all_channels(bot)
botchannels.chanadmin_all_channels(bot)
if "*" in botchannels.SpiceBot_Channels['list'].keys():
del botchannels.SpiceBot_Channels['list']["*"]
botchannels.bot_part_empty(bot)

View File

@ -0,0 +1,6 @@
# coding=utf-8
"""Event Parsing from IRC
"""
from __future__ import unicode_literals, absolute_import, print_function, division
from .Channels_Parsing import *

View File

@ -7,15 +7,15 @@ import sopel.module
import os import os
from sopel_modules.SpiceBot_Events.System import bot_events_startup_register, bot_events_recieved, bot_events_trigger, botevents from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot_SBTools import bot_logging from sopel_modules.SpiceBot.Events import botevents
import spicemanip import spicemanip
def setup(bot): def setup(bot):
bot_logging(bot, 'SpiceBot_CommandsQuery', "Starting setup procedure") botlogs.log('SpiceBot_CommandsQuery', "Starting setup procedure")
bot_events_startup_register(bot, [botevents.BOT_COMMANDSQUERY]) botevents.startup_add([botevents.BOT_COMMANDSQUERY])
if 'SpiceBot_CommandsQuery' not in bot.memory: if 'SpiceBot_CommandsQuery' not in bot.memory:
bot.memory['SpiceBot_CommandsQuery'] = {"counts": 0, "commands": {}, "nickrules": []} bot.memory['SpiceBot_CommandsQuery'] = {"counts": 0, "commands": {}, "nickrules": []}
@ -44,7 +44,7 @@ def setup(bot):
pypi_modules_dir = os.path.join(plugin_dir, pathname) pypi_modules_dir = os.path.join(plugin_dir, pathname)
filepathlisting.append(pypi_modules_dir) filepathlisting.append(pypi_modules_dir)
except Exception as e: except Exception as e:
bot_logging(bot, 'SpiceBot_CommandsQuery', "sopel_modules not loaded :" + str(e)) botlogs.log('SpiceBot_CommandsQuery', "sopel_modules not loaded :" + str(e))
# Extra directories # Extra directories
filepathlist = [] filepathlist = []
@ -154,7 +154,7 @@ def setup(bot):
bot.memory['SpiceBot_CommandsQuery']['commands'][comtype][comalias] = {"aliasfor": maincom} bot.memory['SpiceBot_CommandsQuery']['commands'][comtype][comalias] = {"aliasfor": maincom}
for comtype in ['module', 'nickname', 'rule']: for comtype in ['module', 'nickname', 'rule']:
bot_logging(bot, 'SpiceBot_CommandsQuery', "Found " + str(len(bot.memory['SpiceBot_CommandsQuery']['commands'][comtype].keys())) + " " + comtype + " commands.", True) botlogs.log('SpiceBot_CommandsQuery', "Found " + str(len(bot.memory['SpiceBot_CommandsQuery']['commands'][comtype].keys())) + " " + comtype + " commands.", True)
for command in bot.memory['SpiceBot_CommandsQuery']['commands']['rule'].keys(): for command in bot.memory['SpiceBot_CommandsQuery']['commands']['rule'].keys():
if command.startswith("$nickname"): if command.startswith("$nickname"):
@ -162,7 +162,7 @@ def setup(bot):
if command not in bot.memory['SpiceBot_CommandsQuery']['nickrules']: if command not in bot.memory['SpiceBot_CommandsQuery']['nickrules']:
bot.memory['SpiceBot_CommandsQuery']['nickrules'].append(command) bot.memory['SpiceBot_CommandsQuery']['nickrules'].append(command)
bot_events_trigger(bot, botevents.BOT_COMMANDSQUERY, "SpiceBot_CommandsQuery") botevents.trigger(bot, botevents.BOT_COMMANDSQUERY, "SpiceBot_CommandsQuery")
def shutdown(bot): def shutdown(bot):
@ -173,11 +173,10 @@ def shutdown(bot):
@sopel.module.event(botevents.BOT_LOADED) @sopel.module.event(botevents.BOT_LOADED)
@sopel.module.rule('.*') @sopel.module.rule('.*')
def bot_events_complete(bot, trigger): def bot_events_complete(bot, trigger):
bot_events_recieved(bot, trigger.event)
for comtype in bot.memory['SpiceBot_CommandsQuery']['commands'].keys(): for comtype in bot.memory['SpiceBot_CommandsQuery']['commands'].keys():
if comtype not in ['module', 'nickname', 'rule']: if comtype not in ['module', 'nickname', 'rule']:
bot_logging(bot, 'SpiceBot_CommandsQuery', "Found " + str(len(bot.memory['SpiceBot_CommandsQuery']['commands'][comtype].keys())) + " " + comtype + " commands.", True) botlogs.log('SpiceBot_CommandsQuery', "Found " + str(len(bot.memory['SpiceBot_CommandsQuery']['commands'][comtype].keys())) + " " + comtype + " commands.", True)
def commandsquery_register(bot, command_type, validcoms, aliasfor=None): def commandsquery_register(bot, command_type, validcoms, aliasfor=None):
@ -212,9 +211,3 @@ def commandsquery_register(bot, command_type, validcoms, aliasfor=None):
for comalias in comaliases: for comalias in comaliases:
if comalias not in bot.memory['SpiceBot_CommandsQuery']['commands'][command_type].keys(): if comalias not in bot.memory['SpiceBot_CommandsQuery']['commands'][command_type].keys():
bot.memory['SpiceBot_CommandsQuery']['commands'][command_type][comalias] = {"aliasfor": aliasfor} bot.memory['SpiceBot_CommandsQuery']['commands'][command_type][comalias] = {"aliasfor": aliasfor}
@sopel.module.event(botevents.BOT_COMMANDSQUERY)
@sopel.module.rule('.*')
def bot_events_setup(bot, trigger):
bot_events_recieved(bot, trigger.event)

View File

@ -5,19 +5,17 @@ from __future__ import unicode_literals, absolute_import, division, print_functi
import sopel import sopel
import sopel.module import sopel.module
from sopel_modules.SpiceBot_Events.System import bot_events_check, botevents from sopel_modules.SpiceBot.Events import botevents
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, similar_list, letters_in_string from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, similar_list, letters_in_string
import spicemanip import spicemanip
@botevents.check_ready([botevents.BOT_COMMANDSQUERY])
@sopel.module.nickname_commands('(.*)') @sopel.module.nickname_commands('(.*)')
def query_detection_nick(bot, trigger): def query_detection_nick(bot, trigger):
while not bot_events_check(bot, botevents.BOT_COMMANDSQUERY):
pass
triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'nickname_command') triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'nickname_command')
# command issued, check if valid # command issued, check if valid

View File

@ -5,19 +5,17 @@ from __future__ import unicode_literals, absolute_import, division, print_functi
import sopel import sopel
import sopel.module import sopel.module
from sopel_modules.SpiceBot_Events.System import bot_events_check, botevents from sopel_modules.SpiceBot.Events import botevents
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, similar_list, letters_in_string from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, similar_list, letters_in_string
import spicemanip import spicemanip
@botevents.check_ready([botevents.BOT_COMMANDSQUERY])
@sopel.module.rule('^\?(.*)') @sopel.module.rule('^\?(.*)')
def query_detection(bot, trigger): def query_detection(bot, trigger):
while not bot_events_check(bot, botevents.BOT_COMMANDSQUERY):
pass
triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'query_command') triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'query_command')
# command issued, check if valid # command issued, check if valid

View File

@ -5,21 +5,22 @@ from __future__ import unicode_literals, absolute_import, print_function, divisi
# sopel imports # sopel imports
import sopel.module import sopel.module
from sopel.tools import Identifier from sopel.tools import Identifier
from sopel_modules.SpiceBot_SBTools import bot_logging
from sopel.db import SopelDB, NickValues, ChannelValues from sopel.db import SopelDB, NickValues, ChannelValues
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.exc import SQLAlchemyError
import json import json
from sopel_modules.SpiceBot.Logs import botlogs
def setup(bot): def setup(bot):
pass pass
# Inject Database Functions # Inject Database Functions
bot_logging(bot, 'SpiceBot_Databaseaddons', "Implanting Database functions into bot") botlogs.log('SpiceBot_Databaseaddons', "Implanting Database functions into bot")
SopelDB.delete_nick_value = SopelDBCache.delete_nick_value SopelDB.delete_nick_value = SopelDBCache.delete_nick_value
# SopelDB.adjust_nick_value = SopelDBCache.adjust_nick_value SopelDB.adjust_nick_value = SopelDBCache.adjust_nick_value
SopelDB.delete_channel_value = SopelDBCache.delete_channel_value SopelDB.delete_channel_value = SopelDBCache.delete_channel_value
# SopelDB.adjust_channel_value = SopelDBCache.adjust_channel_value SopelDB.adjust_channel_value = SopelDBCache.adjust_channel_value
class SopelDBCache: class SopelDBCache:
@ -38,7 +39,7 @@ class SopelDBCache:
.one_or_none() .one_or_none()
# NickValue exists, delete # NickValue exists, delete
if result: if result:
session.delete(result.value) session.delete(result)
session.commit() session.commit()
except SQLAlchemyError: except SQLAlchemyError:
session.rollback() session.rollback()
@ -85,7 +86,7 @@ class SopelDBCache:
.one_or_none() .one_or_none()
# ChannelValue exists, update # ChannelValue exists, update
if result: if result:
session.delete(result.value) session.delete(result)
session.commit() session.commit()
except SQLAlchemyError: except SQLAlchemyError:
session.rollback() session.rollback()

View File

@ -4,11 +4,12 @@ from __future__ import unicode_literals, absolute_import, print_function, divisi
# sopel imports # sopel imports
import sopel.module import sopel.module
from sopel_modules.SpiceBot_SBTools import bot_logging
from sopel_modules.SpiceBot.Logs import botlogs
def setup(bot): def setup(bot):
bot_logging(bot, 'SpiceBot_DatabaseCache', "Setting up Database Cache") botlogs.log('SpiceBot_DatabaseCache', "Setting up Database Cache")
if 'SpiceBot_DatabaseCache' not in bot.memory: if 'SpiceBot_DatabaseCache' not in bot.memory:
bot.memory['SpiceBot_DatabaseCache'] = dict() bot.memory['SpiceBot_DatabaseCache'] = dict()

View File

@ -0,0 +1,16 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Events import botevents
@sopel.module.event(botevents.BOT_WELCOME)
@sopel.module.rule('.*')
def bot_events_Connected(bot, trigger):
"""Here, we wait until we are in at least one channel"""
while not len(bot.channels.keys()) > 0:
pass
botevents.trigger(bot, botevents.BOT_CONNECTED, "Bot Connected to IRC")

View File

@ -0,0 +1,15 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Events import botevents
@sopel.module.event(botevents.RPL_WELCOME)
@sopel.module.rule('.*')
def bot_startup_welcome(bot, trigger):
botevents.SpiceBot_Events["RPL_WELCOME_Count"] += 1
if botevents.SpiceBot_Events["RPL_WELCOME_Count"] > 1:
botevents.trigger(bot, botevents.BOT_RECONNECTED, "Bot ReConnected to IRC")

View File

@ -1,72 +0,0 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel.trigger import PreTrigger
from .System import bot_events_trigger, bot_events_recieved, bot_events_startup_check, bot_events_setup_check, botevents
from sopel_modules.SpiceBot_SBTools import bot_logging
import time
@sopel.module.event('001')
@sopel.module.rule('.*')
def bot_startup_connection(bot, trigger):
bot_events_trigger(bot, botevents.BOT_WELCOME, "Welcome to the SpiceBot Events System")
while not len(bot.channels.keys()) > 0:
pass
time.sleep(1)
bot_events_trigger(bot, botevents.BOT_CONNECTED, "Bot Connected to IRC")
@sopel.module.event(botevents.BOT_WELCOME)
@sopel.module.rule('.*')
def bot_events_start(bot, trigger):
bot_logging(bot, 'SpiceBot_Events', trigger.args[1], True)
bot_events_recieved(bot, trigger.event)
bot_events_trigger(bot, botevents.BOT_READY, "Ready To Process module setup procedures")
while not bot_events_startup_check(bot):
pass
bot_events_trigger(bot, botevents.BOT_LOADED, "All registered modules setup procedures have completed")
@sopel.module.event(botevents.BOT_READY)
@sopel.module.rule('.*')
def bot_events_ready(bot, trigger):
bot_logging(bot, 'SpiceBot_Events', trigger.args[1], True)
bot_events_recieved(bot, trigger.event)
@sopel.module.event(botevents.BOT_CONNECTED)
@sopel.module.rule('.*')
def bot_events_connected(bot, trigger):
bot_logging(bot, 'SpiceBot_Events', trigger.args[1], True)
bot_events_recieved(bot, trigger.event)
bot_events_setup_check(bot)
while True:
try:
if len(bot.memory['SpiceBot_Events']["queue"]):
number = bot.memory['SpiceBot_Events']["queue"][0]["number"]
message = bot.memory['SpiceBot_Events']["queue"][0]["message"]
pretrigger = PreTrigger(
bot.nick,
":SpiceBot_Events " + str(number) + " " + str(bot.nick) + " :" + message
)
bot.dispatch(pretrigger)
del bot.memory['SpiceBot_Events']["queue"][0]
except KeyError:
return
@sopel.module.event(botevents.BOT_LOADED)
@sopel.module.rule('.*')
def bot_events_complete(bot, trigger):
bot_logging(bot, 'SpiceBot_Events', trigger.args[1], True)
bot_events_recieved(bot, trigger.event)

View File

@ -0,0 +1,15 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Events import botevents
@botevents.startup_check_ready()
@sopel.module.event(botevents.BOT_READY)
@sopel.module.rule('.*')
def bot_events_startup_complete(bot, trigger):
"""All events registered as required for startup have completed"""
botevents.trigger(bot, botevents.BOT_LOADED, "All registered modules setup procedures have completed")

View File

@ -0,0 +1,15 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot.Events import botevents
@sopel.module.event(botevents.BOT_WELCOME, botevents.BOT_READY, botevents.BOT_CONNECTED, botevents.BOT_LOADED)
@sopel.module.rule('.*')
def bot_events_complete(bot, trigger):
"""This is here simply to log to stderr that this was recieved."""
botlogs.log('SpiceBot_Events', trigger.args[1], True)

View File

@ -0,0 +1,18 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Events import botevents
@sopel.module.event(botevents.BOT_WELCOME)
@sopel.module.rule('.*')
def bot_events_connected(bot, trigger):
"""For items tossed in a queue, this will trigger them accordingly"""
while True:
if len(botevents.SpiceBot_Events["trigger_queue"]):
pretriggerdict = botevents.SpiceBot_Events["trigger_queue"][0]
botevents.dispatch(bot, pretriggerdict)
del botevents.SpiceBot_Events["trigger_queue"][0]

View File

@ -0,0 +1,14 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Events import botevents
@sopel.module.event(botevents.BOT_WELCOME)
@sopel.module.rule('.*')
def bot_events_start(bot, trigger):
"""This stage is redundant, but shows the system is working."""
botevents.trigger(bot, botevents.BOT_READY, "Ready To Process module setup procedures")

View File

@ -1,111 +0,0 @@
#!/usr/bin/env python
#coding=utf-8
from __future__ import unicode_literals, absolute_import, print_function, division
# sopel imports
import sopel
from sopel.trigger import PreTrigger
from sopel_modules.SpiceBot_SBTools import bot_logging
class BotEvents(object):
"""A dynamic listing of all the notable Bot numeric events.
Events will be assigned a 4-digit number above 1000.
This allows you to do, ``@module.event(botevents.BOT_WELCOME)````
"""
def __init__(self):
self.usednumbers = [1000]
def __getattr__(self, name):
''' will only get called for undefined attributes '''
eventnumber = max(self.usednumbers) + 1
self.usednumbers.append(eventnumber)
setattr(self, name, str(eventnumber))
return str(eventnumber)
botevents = BotEvents()
def setup(bot):
bot_logging(bot, 'SpiceBot_Events', "Starting setup procedure")
bot_events_setup_check(bot)
bot_events_startup_register(bot, [botevents.BOT_WELCOME, botevents.BOT_READY, botevents.BOT_CONNECTED])
def shutdown(bot):
if "SpiceBot_Events" in bot.memory:
del bot.memory["SpiceBot_Events"]
def bot_events_trigger(bot, number, message):
bot_events_setup_check(bot)
bot.memory["SpiceBot_Events"]["triggers"][str(number)] = message
if str(number) in [botevents.BOT_WELCOME, botevents.BOT_READY, botevents.BOT_CONNECTED]:
pretrigger = PreTrigger(
bot.nick,
":SpiceBot_Events " + str(number) + " " + str(bot.nick) + " :" + message
)
bot.dispatch(pretrigger)
else:
pretriggerdict = {"number": number, "message": message}
bot.memory['SpiceBot_Events']["queue"].append(pretriggerdict)
def bot_events_setup_check(bot):
if "SpiceBot_Events" not in bot.memory:
bot.memory["SpiceBot_Events"] = {"triggers": {}, "startup": [], "loaded": [], "queue": []}
def bot_events_check(bot, listreq):
bot_events_setup_check(bot)
if not isinstance(listreq, list):
listreq = [str(listreq)]
for requirement in listreq:
if requirement not in bot.memory["SpiceBot_Events"]["loaded"]:
return False
return True
def bot_events_startup_register(bot, addonreq):
bot_events_setup_check(bot)
if not isinstance(addonreq, list):
addonreq = [str(addonreq)]
bot.memory["SpiceBot_Events"]["startup"].extend(addonreq)
def bot_events_recieved(bot, number):
bot_events_setup_check(bot)
if str(number) not in bot.memory["SpiceBot_Events"]["loaded"]:
bot.memory["SpiceBot_Events"]["loaded"].append(str(number))
def bot_events_startup_check(bot):
bot_events_setup_check(bot)
notcomplete = []
for startupitem in bot.memory["SpiceBot_Events"]["startup"]:
if str(startupitem) not in bot.memory["SpiceBot_Events"]["loaded"]:
notcomplete.append(str(startupitem))
if len(notcomplete):
return False
else:
return True

View File

@ -0,0 +1,17 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Events import botevents
@sopel.module.event(botevents.RPL_WELCOME)
@sopel.module.rule('.*')
def bot_startup_welcome(bot, trigger):
"""The Bot events system does not start until RPL_WELCOME 001 is recieved
from the server"""
if botevents.check(botevents.BOT_WELCOME):
return
botevents.trigger(bot, botevents.BOT_WELCOME, "Welcome to the SpiceBot Events System")

View File

@ -1,8 +1,12 @@
# coding=utf8 # coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function from __future__ import unicode_literals, absolute_import, division, print_function
from .System import * from .Welcome import *
from .Events import * from .Ready import *
from .Connected import *
from .Loaded import *
from .Queue import *
from .Logging import *
__author__ = 'Sam Zick' __author__ = 'Sam Zick'
__email__ = 'sam@deathbybandaid.net' __email__ = 'sam@deathbybandaid.net'

View File

@ -7,17 +7,15 @@ from sopel import module
from .gifsearch import getGif from .gifsearch import getGif
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs from sopel_modules.SpiceBot_SBTools import sopel_triggerargs
from sopel_modules.SpiceBot_Events.System import bot_events_check, botevents from sopel_modules.SpiceBot.Events import botevents
import spicemanip import spicemanip
@botevents.check_ready([botevents.BOT_GIFSEARCH])
@module.commands('gif') @module.commands('gif')
def gif_trigger(bot, trigger): def gif_trigger(bot, trigger):
while not bot_events_check(bot, botevents.BOT_GIFSEARCH):
pass
triggerargs, triggercommand = sopel_triggerargs(bot, trigger) triggerargs, triggercommand = sopel_triggerargs(bot, trigger)
if not len(triggerargs): if not len(triggerargs):
return bot.osd("Please present a query to search.") return bot.osd("Please present a query to search.")

View File

@ -9,15 +9,13 @@ import sopel.module
import spicemanip import spicemanip
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs from sopel_modules.SpiceBot_SBTools import sopel_triggerargs
from sopel_modules.SpiceBot_Events.System import bot_events_check, botevents from sopel_modules.SpiceBot.Events import botevents
@botevents.check_ready([botevents.BOT_GIFSEARCH])
@sopel.module.commands('(.*)') @sopel.module.commands('(.*)')
def gifapi_triggers(bot, trigger): def gifapi_triggers(bot, trigger):
while not bot_events_check(bot, botevents.BOT_GIFSEARCH):
pass
triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'prefix_command') triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'prefix_command')
if triggercommand not in bot.memory["SpiceBot_GifSearch"]['valid_gif_api_dict'].keys(): if triggercommand not in bot.memory["SpiceBot_GifSearch"]['valid_gif_api_dict'].keys():

View File

@ -5,11 +5,10 @@ from __future__ import unicode_literals, absolute_import, division, print_functi
import sopel.module import sopel.module
from sopel.config.types import StaticSection, ValidatedAttribute from sopel.config.types import StaticSection, ValidatedAttribute
from sopel_modules.SpiceBot_Events.System import bot_events_startup_register, bot_events_recieved, bot_events_trigger, botevents from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot.Events import botevents
from sopel_modules.SpiceBot_CommandsQuery.CommandsQuery import commandsquery_register from sopel_modules.SpiceBot_CommandsQuery.CommandsQuery import commandsquery_register
from sopel_modules.SpiceBot_SBTools import read_directory_json_to_dict
from sopel_modules.SpiceBot_SBTools import read_directory_json_to_dict, bot_logging
import spicemanip import spicemanip
@ -46,8 +45,8 @@ def configure(config):
def setup(bot): def setup(bot):
bot_logging(bot, 'SpiceBot_GifSearch', "Starting Setup Procedure") botlogs.log('SpiceBot_GifSearch', "Starting Setup Procedure")
bot_events_startup_register(bot, [botevents.BOT_GIFSEARCH]) botevents.startup_add([botevents.BOT_GIFSEARCH])
if 'SpiceBot_GifSearch' not in bot.memory: if 'SpiceBot_GifSearch' not in bot.memory:
bot.memory["SpiceBot_GifSearch"] = {"cache": {}, "badgiflinks": [], 'valid_gif_api_dict': {}} bot.memory["SpiceBot_GifSearch"] = {"cache": {}, "badgiflinks": [], 'valid_gif_api_dict': {}}
@ -79,7 +78,7 @@ def setup(bot):
if validgifapi not in bot.memory["SpiceBot_GifSearch"]['cache'].keys(): if validgifapi not in bot.memory["SpiceBot_GifSearch"]['cache'].keys():
bot.memory["SpiceBot_GifSearch"]['cache'][validgifapi] = dict() bot.memory["SpiceBot_GifSearch"]['cache'][validgifapi] = dict()
bot_events_trigger(bot, botevents.BOT_GIFSEARCH, "SpiceBot_GifSearch") botevents.trigger(bot, botevents.BOT_GIFSEARCH, "SpiceBot_GifSearch")
def shutdown(bot): def shutdown(bot):
@ -249,9 +248,3 @@ def getGif(bot, searchdict):
# return dict # return dict
gifdict['error'] = None gifdict['error'] = None
return gifdict return gifdict
@sopel.module.event(botevents.BOT_GIFSEARCH)
@sopel.module.rule('.*')
def bot_events_setup(bot, trigger):
bot_events_recieved(bot, trigger.event)

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals, absolute_import, division, print_functi
import sopel.module import sopel.module
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs from sopel_modules.SpiceBot_SBTools import sopel_triggerargs
from sopel_modules.SpiceBot_Events.System import bot_events_check, bot_events_recieved, botevents from sopel_modules.SpiceBot.Events import botevents
def setup(bot): def setup(bot):
@ -21,19 +21,15 @@ def shutdown(bot):
@sopel.module.event(botevents.BOT_LOADED) @sopel.module.event(botevents.BOT_LOADED)
@sopel.module.rule('.*') @sopel.module.rule('.*')
def bot_events_complete(bot, trigger): def bot_events_complete(bot, trigger):
bot_events_recieved(bot, trigger.event)
for comtype in bot.memory['SpiceBot_CommandsQuery']['commands'].keys(): for comtype in bot.memory['SpiceBot_CommandsQuery']['commands'].keys():
bot.memory["SpiceBot_InvalidCommand"]["valid"].extend(bot.memory['SpiceBot_CommandsQuery']['commands'][comtype].keys()) bot.memory["SpiceBot_InvalidCommand"]["valid"].extend(bot.memory['SpiceBot_CommandsQuery']['commands'][comtype].keys())
@botevents.check_ready([botevents.BOT_LOADED, botevents.BOT_COMMANDSQUERY])
@sopel.module.commands('(.*)') @sopel.module.commands('(.*)')
def InvalidCommand_triggers(bot, trigger): def InvalidCommand_triggers(bot, trigger):
return return
while not bot_events_check(bot, [botevents.BOT_LOADED, botevents.BOT_COMMANDSQUERY]):
pass
triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'prefix_command') triggerargs, triggercommand = sopel_triggerargs(bot, trigger, 'prefix_command')
# patch for people typing "...", maybe other stuff, but this verifies that there is still a command here # patch for people typing "...", maybe other stuff, but this verifies that there is still a command here

View File

@ -12,10 +12,10 @@ from __future__ import unicode_literals, absolute_import, division, print_functi
import sopel.bot import sopel.bot
from sopel import tools, module from sopel import tools, module
from sopel.tools import Identifier from sopel.tools import Identifier
from sopel.module import HALFOP
from sopel.config.types import StaticSection, ValidatedAttribute from sopel.config.types import StaticSection, ValidatedAttribute
from sopel_modules.SpiceBot_SBTools import bot_logging from sopel_modules.SpiceBot.Logs import botlogs
import time import time
from collections import abc from collections import abc
@ -28,20 +28,20 @@ __version__ = '0.1.2'
def configure(config): def configure(config):
config.define_section("MAXTARGCONFIG_KICK", MAXTARGCONFIG_KICK, validate=False) config.define_section("SpiceBot_Kick", SpiceBot_Kick, validate=False)
config.MAXTARGCONFIG_KICK.configure_setting('kick', 'MAXTARG limit for KICK') config.SpiceBot_Kick.configure_setting('kick', 'MAXTARG limit for KICK')
def setup(bot): def setup(bot):
# Inject KICK # Inject KICK
bot_logging(bot, 'SpiceBot_Kick', "Implanting Kick function into bot") botlogs.log('SpiceBot_Kick', "Implanting Kick function into bot")
bot.kick = SopelKICK.kick bot.kick = SopelKICK.kick
sopel.bot.SopelWrapper.kick = SopelWrapperKICK.kick sopel.bot.SopelWrapper.kick = SopelWrapperKICK.kick
# verify config settings for server # verify config settings for server
bot_logging(bot, 'SpiceBot_Kick', "Checking for config settings") botlogs.log('SpiceBot_Kick', "Checking for config settings")
bot.config.define_section("MAXTARGCONFIG_KICK", MAXTARGCONFIG_KICK, validate=False) bot.config.define_section("SpiceBot_Kick", SpiceBot_Kick, validate=False)
@module.event('005') @module.event('005')
@ -63,10 +63,10 @@ def parse_event_005(bot, trigger):
except IndexError: except IndexError:
value = None value = None
if value: if value:
bot.config.MAXTARGCONFIG_KICK.kick = int(value) bot.config.SpiceBot_Kick.kick = int(value)
class MAXTARGCONFIG_KICK(StaticSection): class SpiceBot_Kick(StaticSection):
kick = ValidatedAttribute('kick', default=1) kick = ValidatedAttribute('kick', default=1)
@ -80,8 +80,7 @@ class SopelKICK:
The bot must be a channel operator in specified channel for this to work. The bot must be a channel operator in specified channel for this to work.
.. versionadded:: 7.0 .. versionadded:: 7.0
""" """
if self.channels[channel].privileges[self.nick] < HALFOP: self.write(['KICK', channel, nick], text)
self.write(['KICK', channel, nick], text)
class SopelWrapperKICK(object): class SopelWrapperKICK(object):
@ -89,9 +88,9 @@ class SopelWrapperKICK(object):
def kick(self, nick, channel=None, message=None): def kick(self, nick, channel=None, message=None):
if channel is None: if channel is None:
if self._trigger.is_privmsg: if self._trigger.is_privmsg:
return raise RuntimeError('Error: KICK requires a channel.')
else: else:
channel = self._trigger.sender channel = self._trigger.sender
if nick is None: if nick is None:
return raise RuntimeError('Error: KICK requires a nick.')
self._bot.kick(nick, channel, message) self._bot.kick(nick, channel, message)

File diff suppressed because it is too large Load Diff

View File

@ -1,137 +0,0 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel.config.types import StaticSection, ValidatedAttribute
from sopel_modules.SpiceBot_SBTools import bot_logging
from sopel_modules.SpiceBot_Events.System import bot_events_startup_register, bot_events_recieved, bot_events_trigger, botevents
import os
import spicemanip
def configure(config):
config.define_section("SpiceBot_Logs", SpiceBot_Logs_MainSection, validate=False)
config.SpiceBot_Logs.configure_setting('logging_channel', 'SpiceBot_Logs channels')
class SpiceBot_Logs_MainSection(StaticSection):
logging_channel = ValidatedAttribute('logging_channel', default=False)
def setup(bot):
bot_logging(bot, 'SpiceBot_Logs', "Starting Setup Procedure")
bot.config.define_section("SpiceBot_Logs", SpiceBot_Logs_MainSection, validate=False)
bot_events_startup_register(bot, [botevents.BOT_LOGS])
bot_logs_setup_check(bot)
bot_events_trigger(bot, botevents.BOT_LOGS, "SpiceBot_Logs")
def bot_logs_setup_check(bot):
if 'SpiceBot_Logs' not in bot.memory:
bot.memory['SpiceBot_Logs'] = {"logs": {"Sopel_systemd": [], "Sopel_stdio": []}, "queue": []}
def shutdown(bot):
if "SpiceBot_Logs" in bot.memory:
del bot.memory["SpiceBot_Logs"]
@sopel.module.event(botevents.BOT_CONNECTED)
@sopel.module.rule('.*')
def join_log_channel(bot, trigger):
bot_events_recieved(bot, trigger.event)
if bot.config.SpiceBot_Logs.logging_channel:
channel = bot.config.SpiceBot_Logs.logging_channel
if channel not in bot.channels.keys():
bot.write(('JOIN', bot.nick, channel))
if channel not in bot.channels.keys() and bot.config.SpiceBot_Channels.operadmin:
bot.write(('SAJOIN', bot.nick, channel))
bot_logs_setup_check(bot)
while True:
try:
if len(bot.memory['SpiceBot_Logs']["queue"]):
bot.say(str(bot.memory['SpiceBot_Logs']["queue"][0]), channel)
del bot.memory['SpiceBot_Logs']["queue"][0]
except KeyError:
return
def stdio_logs_fetch(bot):
stdio_ignore = []
for logtype in bot.memory['SpiceBot_Logs']["logs"].keys():
stdio_ignore.append("[" + logtype + "]")
logfile = os.path.os.path.join(bot.config.core.logdir, 'stdio.log')
try:
log_file_lines = []
log_file = open(logfile, 'r')
lines = log_file.readlines()
for line in lines:
log_file_lines.append(line)
log_file.close()
currentline, linenumindex = 0, []
for line in log_file_lines:
if line.startswith("Welcome to Sopel. Loading modules..."):
linenumindex.append(currentline)
currentline += 1
last_start = max(linenumindex)
filelines = log_file_lines[last_start:]
except Exception as e:
debuglines = e
filelines = []
debuglines = []
loadedmodules = []
for line in filelines:
if line.startswith("Loaded:"):
loadedmodules.append(str(line).split("Loaded:")[-1])
else:
if not line.startswith(tuple(stdio_ignore)) and not line.isspace():
debuglines.append(str(line))
loadedmodules = "Loaded: " + spicemanip.main(loadedmodules, 'andlist')
debuglines.insert(1, loadedmodules)
return debuglines
def systemd_logs_fetch(bot):
servicepid = get_running_pid(bot)
debuglines = []
for line in os.popen(str("sudo journalctl _PID=" + str(servicepid))).read().split('\n'):
line = str(line).split(str(os.uname()[1] + " "))[-1]
lineparts = str(line).split(": ")
del lineparts[0]
line = spicemanip.main(lineparts, 0)
if not line.isspace():
debuglines.append(str(line))
return debuglines
def get_running_pid(bot):
try:
filename = "/run/sopel/" + str(bot.nick) + ".pid"
with open(filename, 'r') as pid_file:
pidnum = int(pid_file.read())
except Exception as e:
pidnum = e
pidnum = str(os.popen("systemctl show " + str(bot.nick) + " --property=MainPID").read()).split("=")[-1]
return pidnum
@sopel.module.event(botevents.BOT_LOGS)
@sopel.module.rule('.*')
def bot_events_setup(bot, trigger):
bot_events_recieved(bot, trigger.event)

View File

@ -1,22 +1,19 @@
# coding=utf-8 # coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module import sopel.module
import spicemanip import spicemanip
from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot.Events import botevents
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, command_permissions_check, inlist, inlist_match, similar_list from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, command_permissions_check, inlist, inlist_match, similar_list
from sopel_modules.SpiceBot_Events.System import bot_events_check, botevents
from .Logs import systemd_logs_fetch, stdio_logs_fetch
@botevents.check_ready([botevents.BOT_LOGS])
@sopel.module.nickname_commands('logs', 'debug') @sopel.module.nickname_commands('logs', 'debug')
def bot_command_logs(bot, trigger): def bot_command_logs(bot, trigger):
while not bot_events_check(bot, botevents.BOT_LOGS):
pass
if not command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']): if not command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']):
bot.say("I was unable to process this Bot Nick command due to privilege issues.") bot.say("I was unable to process this Bot Nick command due to privilege issues.")
return return
@ -25,11 +22,11 @@ def bot_command_logs(bot, trigger):
logtype = spicemanip.main(triggerargs, 1) or None logtype = spicemanip.main(triggerargs, 1) or None
if not logtype: if not logtype:
bot.osd("Current valid log(s) include: " + spicemanip.main(bot.memory['SpiceBot_Logs']["logs"].keys(), 'andlist'), trigger.sender, 'action') bot.osd("Current valid log(s) include: " + spicemanip.main(botlogs.SpiceBot_Logs["list"].keys(), 'andlist'), trigger.sender, 'action')
return return
if not inlist(bot, logtype, bot.memory['SpiceBot_Logs']["logs"].keys()): if not inlist(bot, logtype, botlogs.SpiceBot_Logs["list"].keys()):
closestmatches = similar_list(bot, logtype, bot.memory['SpiceBot_Logs']["logs"].keys(), 10, 'reverse') closestmatches = similar_list(bot, logtype, botlogs.SpiceBot_Logs["list"].keys(), 10, 'reverse')
if not len(closestmatches): if not len(closestmatches):
bot.notice("No valid logs match " + str(logtype) + ".", trigger.nick) bot.notice("No valid logs match " + str(logtype) + ".", trigger.nick)
else: else:
@ -37,14 +34,14 @@ def bot_command_logs(bot, trigger):
return return
logtype = inlist_match(bot, logtype, bot.memory['SpiceBot_Logs']["logs"].keys()) logtype = inlist_match(bot, logtype, botlogs.SpiceBot_Logs["list"].keys())
if logtype == "Sopel_systemd": if logtype == "Sopel_systemd":
logindex = systemd_logs_fetch(bot) logindex = botlogs.systemd_logs_fetch(bot)
elif logtype == "Sopel_stdio": elif logtype == "Sopel_stdio":
logindex = stdio_logs_fetch(bot) logindex = botlogs.stdio_logs_fetch(bot)
else: else:
logindex = bot.memory['SpiceBot_Logs']["logs"][logtype] logindex = botlogs.SpiceBot_Logs["list"][logtype]
if not len(logindex): if not len(logindex):
bot.osd("No logs found for " + str(logtype) + ".") bot.osd("No logs found for " + str(logtype) + ".")

View File

@ -0,0 +1,35 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
import sopel.tools
import sopel.config
from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot.Events import botevents
def setup(bot):
botlogs.log('SpiceBot_Logs', "Starting Setup Procedure")
botevents.startup_add([botevents.BOT_LOGS])
botevents.trigger(bot, botevents.BOT_LOGS, "SpiceBot_Logs")
@sopel.module.event(botevents.RPL_WELCOME)
@sopel.module.rule('.*')
def join_log_channel(bot, trigger):
if bot.config.core.logging_channel:
channel = bot.config.core.logging_channel
if channel not in bot.channels.keys():
bot.write(('JOIN', bot.nick, channel))
if channel not in bot.channels.keys() and bot.config.SpiceBot_Channels.operadmin:
bot.write(('SAJOIN', bot.nick, channel))
while True:
if len(botlogs.SpiceBot_Logs["queue"]):
bot.say(str(botlogs.SpiceBot_Logs["queue"][0]), channel)
del botlogs.SpiceBot_Logs["queue"][0]
else:
botlogs.sopel_config["logging_channel"] = False
botlogs.SpiceBot_Logs["queue"] = []

View File

@ -1,9 +1,9 @@
# coding=utf8 # coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function from __future__ import unicode_literals, absolute_import, division, print_function
from .Logs import * from .Queue import *
from .Logs_Command import * from .Logs_Command import *
from .ErrorDisplay import * # from .IRC_Events import *
__author__ = 'Sam Zick' __author__ = 'Sam Zick'
__email__ = 'sam@deathbybandaid.net' __email__ = 'sam@deathbybandaid.net'

View File

@ -6,6 +6,7 @@ import sopel.module
import spicemanip import spicemanip
from sopel_modules.SpiceBot.Channels import botchannels
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, command_permissions_check, inlist from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, command_permissions_check, inlist
@ -41,7 +42,7 @@ def bot_command_process(bot, trigger):
target = spicemanip.main(triggerargs, 1) target = spicemanip.main(triggerargs, 1)
if (target not in ['allchans', 'allnicks'] if (target not in ['allchans', 'allnicks']
and not inlist(bot, target.lower(), bot.memory['SpiceBot_Channels']['channels'].keys()) and not inlist(bot, target.lower(), botchannels.SpiceBot_Channels['list'].keys())
and not inlist(bot, target.lower(), bot.users)): and not inlist(bot, target.lower(), bot.users)):
bot.osd("Channel/nick name {} not valid.".format(target)) bot.osd("Channel/nick name {} not valid.".format(target))
return return

View File

@ -5,7 +5,8 @@ from __future__ import unicode_literals, absolute_import, print_function, divisi
# sopel imports # sopel imports
import sopel.module import sopel.module
from sopel_modules.SpiceBot_SBTools import bot_logging, spicebot_reload from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot_SBTools import spicebot_reload
@sopel.module.nickname_commands('restart') @sopel.module.nickname_commands('restart')
@ -15,7 +16,7 @@ def nickname_comand_restart(bot, trigger):
bot.say("You are not authorized to perform this function.") bot.say("You are not authorized to perform this function.")
quitmessage = "Received command from " + trigger.nick + " to restart. Be Back Soon!" quitmessage = "Received command from " + trigger.nick + " to restart. Be Back Soon!"
bot_logging(bot, 'SpiceBot_Restart', quitmessage) botlogs.log('SpiceBot_Restart', quitmessage)
bot.osd(quitmessage, bot.channels.keys()) bot.osd(quitmessage, bot.channels.keys())
# service_manip(bot, bot.nick, 'restart', 'SpiceBot_Restart') # service_manip(bot, bot.nick, 'restart', 'SpiceBot_Restart')

View File

@ -20,6 +20,8 @@ from pygit2 import clone_repository
import spicemanip import spicemanip
from sopel_modules.SpiceBot.Logs import botlogs
"""Variable References""" """Variable References"""
@ -93,29 +95,6 @@ def command_permissions_check(bot, trigger, privslist):
return True return True
"""Logging"""
def bot_logging(bot, logtype, logentry, stdio=False):
if 'SpiceBot_Logs' not in bot.memory:
bot.memory['SpiceBot_Logs'] = {"logs": {"Sopel_systemd": [], "Sopel_stdio": []}, "queue": []}
logmessage = "[" + logtype + "] " + logentry + ""
bot.memory['SpiceBot_Logs']["queue"].append(logmessage)
if stdio:
sopel.tools.stderr(logmessage)
if logtype not in bot.memory['SpiceBot_Logs']["logs"].keys():
bot.memory['SpiceBot_Logs']["logs"][logtype] = []
bot.memory['SpiceBot_Logs']["logs"][logtype].append(logentry)
if len(bot.memory['SpiceBot_Logs']["logs"][logtype]) > 10:
del bot.memory['SpiceBot_Logs']["logs"][logtype][0]
""" """
Time Time
""" """
@ -291,38 +270,6 @@ def channel_privs(bot, channel, privtype):
return privlist return privlist
def join_all_channels(bot):
if bot.config.SpiceBot_Channels.joinall:
for channel in bot.memory['SpiceBot_Channels']['channels'].keys():
if channel not in bot.channels.keys() and channel not in bot.config.SpiceBot_Channels.chanignore:
bot.write(('JOIN', bot.nick, bot.memory['SpiceBot_Channels']['channels'][channel]['name']))
if channel not in bot.channels.keys() and bot.config.SpiceBot_Channels.operadmin:
bot.write(('SAJOIN', bot.nick, bot.memory['SpiceBot_Channels']['channels'][channel]['name']))
def chanadmin_all_channels(bot):
# Chan ADMIN +a
for channel in bot.channels.keys():
if channel not in bot.config.SpiceBot_Channels.chanignore:
if bot.config.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)
def channel_list_current(bot):
newlist = [item for item in bot.channels.keys() if item.lower() not in bot.memory['SpiceBot_Channels']['channels']]
for channel in newlist:
topic = bot.channels[channel].topic
bot.memory['SpiceBot_Channels']['channels'][str(channel).lower()] = dict()
bot.memory['SpiceBot_Channels']['channels'][str(channel).lower()]['name'] = str(channel)
bot.memory['SpiceBot_Channels']['channels'][str(channel).lower()]['topic'] = topic_compile(topic)
if "*" in bot.memory['SpiceBot_Channels']:
bot.memory['SpiceBot_Channels'].remove("*")
"""Environment Functions""" """Environment Functions"""
@ -358,7 +305,7 @@ def spicebot_update(bot, deps=False):
if not os.path.exists(clonepath) or not os.path.isdir(clonepath): if not os.path.exists(clonepath) or not os.path.isdir(clonepath):
os.system(clonepath) os.system(clonepath)
bot_logging(bot, 'SpiceBot_Update', "Cloning to " + clonepath, True) botlogs.log('SpiceBot_Update', "Cloning to " + clonepath, True)
clone_repository(str(bot.config.SpiceBot_Update.gitrepo + ".git"), clonepath, checkout_branch=bot.config.SpiceBot_Update.gitbranch) clone_repository(str(bot.config.SpiceBot_Update.gitrepo + ".git"), clonepath, checkout_branch=bot.config.SpiceBot_Update.gitbranch)
@ -369,12 +316,12 @@ def spicebot_update(bot, deps=False):
# pipcommand += " git+" + str(bot.config.SpiceBot_Update.gitrepo) + "@" + str(bot.config.SpiceBot_Update.gitbranch) # pipcommand += " git+" + str(bot.config.SpiceBot_Update.gitrepo) + "@" + str(bot.config.SpiceBot_Update.gitbranch)
pipcommand += " /tmp/SpiceBot/" pipcommand += " /tmp/SpiceBot/"
bot_logging(bot, 'SpiceBot_Update', "Running `" + pipcommand + "`", True) botlogs.log('SpiceBot_Update', "Running `" + pipcommand + "`", True)
# for line in os.popen(pipcommand).read().split('\n'): # for line in os.popen(pipcommand).read().split('\n'):
# bot_logging(bot, 'SpiceBot_Update', " " + line) # botlogs.log('SpiceBot_Update', " " + line)
os.system(pipcommand) os.system(pipcommand)
bot_logging(bot, 'SpiceBot_Update', "Deleting " + clonepath, True) botlogs.log('SpiceBot_Update', "Deleting " + clonepath, True)
os.system("sudo rm -r /tmp/SpiceBot") os.system("sudo rm -r /tmp/SpiceBot")
@ -390,10 +337,10 @@ def service_manip(bot, servicename, dowhat, log_from='service_manip'):
if str(dowhat) not in ["start", "stop", "restart"]: if str(dowhat) not in ["start", "stop", "restart"]:
return return
try: try:
bot_logging(bot, log_from, str(dowhat).title() + "ing " + str(servicename) + ".service.") botlogs.log(log_from, str(dowhat).title() + "ing " + str(servicename) + ".service.")
os.system("sudo service " + str(servicename) + " " + str(dowhat)) os.system("sudo service " + str(servicename) + " " + str(dowhat))
except Exception as e: except Exception as e:
bot_logging(bot, log_from, str(dowhat).title() + "ing " + str(servicename) + ".service Failed: " + str(e)) botlogs.log(log_from, str(dowhat).title() + "ing " + str(servicename) + ".service Failed: " + str(e))
"""Config Reading Functions""" """Config Reading Functions"""
@ -425,7 +372,7 @@ def read_directory_json_to_dict(bot, directories, configtypename="Config File",
except Exception as e: except Exception as e:
filereadgood = False filereadgood = False
if bot: if bot:
bot_logging(bot, log_from, "Error loading %s: %s (%s)" % (configtypename, e, filepath)) botlogs.log(log_from, "Error loading %s: %s (%s)" % (configtypename, e, filepath))
dict_from_file = dict() dict_from_file = dict()
# Close File # Close File
inf.close() inf.close()
@ -440,10 +387,10 @@ def read_directory_json_to_dict(bot, directories, configtypename="Config File",
if filecount: if filecount:
if bot: if bot:
bot_logging(bot, log_from, 'Registered %d %s dict files,' % (filecount, configtypename)) botlogs.log(log_from, 'Registered %d %s dict files,' % (filecount, configtypename))
bot_logging(bot, log_from, '%d %s dict files failed to load' % (fileopenfail, configtypename), True) botlogs.log(log_from, '%d %s dict files failed to load' % (fileopenfail, configtypename), True)
else: else:
if bot: if bot:
bot_logging(bot, log_from, "Warning: Couldn't load any %s dict files" % (configtypename)) botlogs.log(log_from, "Warning: Couldn't load any %s dict files" % (configtypename))
return configs_dict return configs_dict

View File

@ -6,16 +6,15 @@ from __future__ import unicode_literals, absolute_import, print_function, divisi
import sopel import sopel
import sopel.module import sopel.module
from sopel_modules.SpiceBot_SBTools import bot_logging, stock_modules_begone from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot_SBTools import stock_modules_begone
import os
def setup(bot): def setup(bot):
bot_logging(bot, 'Sopel_Patch', "Patching Sopels built-in url_callbacks") botlogs.log('Sopel_Patch', "Patching Sopels built-in url_callbacks")
if 'url_callbacks' not in bot.memory: if 'url_callbacks' not in bot.memory:
bot.memory['url_callbacks'] = sopel.tools.SopelMemory() bot.memory['url_callbacks'] = sopel.tools.SopelMemory()
bot_logging(bot, 'Sopel_Patch', "Removing Stock Modules and verifying Dummy Command is present.") botlogs.log('Sopel_Patch', "Removing Stock Modules and verifying Dummy Command is present.")
stock_modules_begone(bot) stock_modules_begone(bot)

View File

@ -4,19 +4,13 @@ from __future__ import unicode_literals, absolute_import, division, print_functi
import sopel.module import sopel.module
from sopel_modules.SpiceBot_Events.System import bot_events_recieved, bot_events_startup_register, botevents from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot_SBTools import bot_logging from sopel_modules.SpiceBot.Events import botevents
def setup(bot): def setup(bot):
bot_logging(bot, 'SpiceBot_StartupMonologue', "Starting setup procedure") botlogs.log('SpiceBot_StartupMonologue', "Starting setup procedure")
bot_events_startup_register(bot, [botevents.BOT_STARTUPMONOLOGUE_CHANNELS, botevents.BOT_STARTUPMONOLOGUE_COMMANDSQUERY, botevents.BOT_STARTUPMONOLOGUE_CONNECTED]) botevents.startup_add([botevents.BOT_STARTUPMONOLOGUE_CHANNELS, botevents.BOT_STARTUPMONOLOGUE_COMMANDSQUERY]) # , botevents.BOT_STARTUPMONOLOGUE_CONNECTED])
if 'SpiceBot_StartupMonologue' not in bot.memory: if 'SpiceBot_StartupMonologue' not in bot.memory:
bot.memory['SpiceBot_StartupMonologue'] = [] bot.memory['SpiceBot_StartupMonologue'] = []
@sopel.module.event(botevents.BOT_STARTUPMONOLOGUE, botevents.BOT_STARTUPMONOLOGUE_CHANNELS, botevents.BOT_STARTUPMONOLOGUE_COMMANDSQUERY, botevents.BOT_STARTUPMONOLOGUE_CONNECTED)
@sopel.module.rule('.*')
def bot_events_setup(bot, trigger):
bot_events_recieved(bot, trigger.event)

View File

@ -1,68 +0,0 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot_Events.System import bot_events_recieved, bot_events_trigger, botevents
from sopel_modules.SpiceBot_SBTools import humanized_time, bot_logging
import time
@sopel.module.event(botevents.BOT_CONNECTED)
@sopel.module.rule('.*')
def bot_startup_monologue_start(bot, trigger):
bot_events_recieved(bot, trigger.event)
# Startup
bot_logging(bot, 'SpiceBot_StartupMonologue', bot.nick + " is now starting. Please wait while I load my configuration")
bot.osd(" is now starting. Please wait while I load my configuration.", bot.channels.keys(), 'ACTION')
bot_events_trigger(bot, botevents.BOT_STARTUPMONOLOGUE_CONNECTED, "SpiceBot_StartupMonologue")
@sopel.module.event(botevents.BOT_COMMANDSQUERY)
@sopel.module.rule('.*')
def bot_startup_monologue_commands(bot, trigger):
bot_events_recieved(bot, trigger.event)
availablecomsnum, availablecomsfiles = 0, 0
for commandstype in bot.memory['SpiceBot_CommandsQuery']['commands'].keys():
availablecomsnum += len(bot.memory['SpiceBot_CommandsQuery']['commands'][commandstype].keys())
availablecomsfiles += bot.memory['SpiceBot_CommandsQuery']['counts']
bot.memory['SpiceBot_StartupMonologue'].append("There are " + str(availablecomsnum) + " commands available in " + str(availablecomsfiles) + " files.")
bot_logging(bot, 'SpiceBot_StartupMonologue', "There are " + str(availablecomsnum) + " commands available in " + str(availablecomsfiles) + " files.")
bot_events_trigger(bot, botevents.BOT_STARTUPMONOLOGUE_COMMANDSQUERY, "SpiceBot_StartupMonologue")
@sopel.module.event(botevents.BOT_CHANNELS)
@sopel.module.rule('.*')
def bot_startup_monologue_channels(bot, trigger):
bot_events_recieved(bot, trigger.event)
botcount = len(bot.channels.keys())
servercount = len(bot.memory['SpiceBot_Channels']['channels'].keys())
bot.memory['SpiceBot_StartupMonologue'].append("I am in " + str(botcount) + " of " + str(servercount) + " channel(s) available on this server.")
bot_events_trigger(bot, botevents.BOT_STARTUPMONOLOGUE_CHANNELS, "SpiceBot_StartupMonologue")
@sopel.module.event(botevents.BOT_LOADED)
@sopel.module.rule('.*')
def bot_startup_monologue_display(bot, trigger):
bot_events_recieved(bot, trigger.event)
timesince = humanized_time(time.time() - bot.memory["SpiceBot_Uptime"])
bot.memory['SpiceBot_StartupMonologue'].append("Startup took " + timesince)
# Announce to chan, then handle some closing stuff
bot_logging(bot, 'SpiceBot_StartupMonologue', bot.nick + " startup complete")
bot.memory['SpiceBot_StartupMonologue'].insert(0, " startup complete")
bot.osd(bot.memory['SpiceBot_StartupMonologue'], bot.channels.keys(), 'ACTION')
bot_events_trigger(bot, botevents.BOT_STARTUPMONOLOGUE, "SpiceBot_StartupMonologue")
bot_logging(bot, 'SpiceBot_StartupMonologue', "Startup Monologue has been issued to all channels.", True)

View File

@ -0,0 +1,21 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot.Events import botevents
from sopel_modules.SpiceBot.Channels import botchannels
@sopel.module.event(botevents.BOT_CHANNELS)
@sopel.module.rule('.*')
def bot_startup_monologue_channels(bot, trigger):
botcount = len(bot.channels.keys())
servercount = len(botchannels.SpiceBot_Channels['list'].keys())
bot.memory['SpiceBot_StartupMonologue'].append("I am in " + str(botcount) + " of " + str(servercount) + " channel(s) available on this server.")
botlogs.log('SpiceBot_StartupMonologue', "I am in " + str(botcount) + " of " + str(servercount) + " channel(s) available on this server.")
botevents.trigger(bot, botevents.BOT_STARTUPMONOLOGUE_CHANNELS, "SpiceBot_StartupMonologue")

View File

@ -0,0 +1,23 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot.Events import botevents
@sopel.module.event(botevents.BOT_COMMANDSQUERY)
@sopel.module.rule('.*')
def bot_startup_monologue_commands(bot, trigger):
availablecomsnum, availablecomsfiles = 0, 0
for commandstype in bot.memory['SpiceBot_CommandsQuery']['commands'].keys():
availablecomsnum += len(bot.memory['SpiceBot_CommandsQuery']['commands'][commandstype].keys())
availablecomsfiles += bot.memory['SpiceBot_CommandsQuery']['counts']
bot.memory['SpiceBot_StartupMonologue'].append("There are " + str(availablecomsnum) + " commands available in " + str(availablecomsfiles) + " files.")
botlogs.log('SpiceBot_StartupMonologue', "There are " + str(availablecomsnum) + " commands available in " + str(availablecomsfiles) + " files.")
botevents.trigger(bot, botevents.BOT_STARTUPMONOLOGUE_COMMANDSQUERY, "SpiceBot_StartupMonologue")

View File

@ -0,0 +1,19 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot.Events import botevents
@sopel.module.event(botevents.BOT_CONNECTED)
@sopel.module.rule('.*')
def bot_startup_monologue_start(bot, trigger):
# Startup
botlogs.log('SpiceBot_StartupMonologue', bot.nick + " is now starting. Please wait while I load my configuration")
bot.osd(" is now starting. Please wait while I load my configuration.", bot.channels.keys(), 'ACTION')
botevents.trigger(bot, botevents.BOT_STARTUPMONOLOGUE_CONNECTED, "SpiceBot_StartupMonologue")

View File

@ -1,20 +1,17 @@
# coding=utf-8 # coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module import sopel.module
from sopel_modules.SpiceBot_Events.System import bot_events_recieved, botevents from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot_SBTools import bot_logging from sopel_modules.SpiceBot.Events import botevents
from .Logs import stdio_logs_fetch
@sopel.module.event(botevents.BOT_STARTUPMONOLOGUE) @sopel.module.event(botevents.BOT_STARTUPMONOLOGUE)
@sopel.module.rule('.*') @sopel.module.rule('.*')
def bot_startup_monologue_start(bot, trigger): def bot_startup_monologue_start(bot, trigger):
bot_events_recieved(bot, trigger.event)
debuglines = stdio_logs_fetch(bot) debuglines = botlogs.stdio_logs_fetch(bot)
searchphrasefound = [] searchphrasefound = []
for line in debuglines: for line in debuglines:
@ -23,9 +20,9 @@ def bot_startup_monologue_start(bot, trigger):
if len(searchphrasefound): if len(searchphrasefound):
for foundphase in searchphrasefound: for foundphase in searchphrasefound:
bot_logging(bot, 'SpiceBot_Logs', str(foundphase)) botlogs.log('SpiceBot_Logs', str(foundphase))
searchphrasefound.insert(0, "Notice to Bot Admins: ") searchphrasefound.insert(0, "Notice to Bot Admins: ")
searchphrasefound.append("Run the debug command for more information.") searchphrasefound.append("Run the debug command for more information.")
bot.osd(searchphrasefound, bot.channels.keys()) bot.osd(searchphrasefound, bot.channels.keys())
else: else:
bot_logging(bot, 'SpiceBot_Logs', "No issues found at bot startup!", True) botlogs.log('SpiceBot_Logs', "No issues found at bot startup!", True)

View File

@ -0,0 +1,29 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, division, print_function
import sopel.module
from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot.Events import botevents
from sopel_modules.SpiceBot_SBTools import humanized_time
import time
@sopel.module.event(botevents.BOT_LOADED)
@sopel.module.rule('.*')
def bot_startup_monologue_display(bot, trigger):
if botevents.SpiceBot_Events["RPL_WELCOME_Count"] == 1:
timesince = humanized_time(time.time() - bot.memory["SpiceBot_Uptime"])
bot.memory['SpiceBot_StartupMonologue'].append("Startup took " + timesince)
# Announce to chan, then handle some closing stuff
botlogs.log('SpiceBot_StartupMonologue', bot.nick + " startup complete")
bot.memory['SpiceBot_StartupMonologue'].insert(0, " startup complete")
bot.osd(bot.memory['SpiceBot_StartupMonologue'], bot.channels.keys(), 'ACTION')
botevents.trigger(bot, botevents.BOT_STARTUPMONOLOGUE, "SpiceBot_StartupMonologue")
botlogs.log('SpiceBot_StartupMonologue', "Startup Monologue has been issued to all channels.", True)

View File

@ -6,7 +6,11 @@ Sopel Startup Monologue displays to all channels that the bot is online
from __future__ import unicode_literals, absolute_import, division, print_function from __future__ import unicode_literals, absolute_import, division, print_function
from .StartupMonologue import * from .StartupMonologue import *
from .StartupMonologue_Display import * from .StartupMonologue_Display_Channels import *
from .StartupMonologue_Display_Commands import *
from .StartupMonologue_Display_Connected import *
from .StartupMonologue_Display_Loaded import *
from .StartupMonologue_Display_Errors import *
__author__ = 'Sam Zick' __author__ = 'Sam Zick'
__email__ = 'sam@deathbybandaid.net' __email__ = 'sam@deathbybandaid.net'

View File

@ -8,7 +8,8 @@ from sopel.config.types import StaticSection, ValidatedAttribute
import spicemanip import spicemanip
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, command_permissions_check, bot_logging, spicebot_reload, spicebot_update from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot_SBTools import sopel_triggerargs, command_permissions_check, spicebot_reload, spicebot_update
class SpiceBot_Update_MainSection(StaticSection): class SpiceBot_Update_MainSection(StaticSection):
@ -23,7 +24,7 @@ def configure(config):
def setup(bot): def setup(bot):
bot_logging(bot, 'SpiceBot_Update', "Initial Setup processing") botlogs.log('SpiceBot_Update', "Initial Setup processing")
bot.config.define_section("SpiceBot_Update", SpiceBot_Update_MainSection, validate=False) bot.config.define_section("SpiceBot_Update", SpiceBot_Update_MainSection, validate=False)
@ -48,7 +49,7 @@ def nickname_comand_update(bot, trigger):
triggerargs = spicemanip.main(triggerargs, '2+', 'list') triggerargs = spicemanip.main(triggerargs, '2+', 'list')
quitmessage = "Received command from " + trigger.nick + " to update from Github and restart" quitmessage = "Received command from " + trigger.nick + " to update from Github and restart"
bot_logging(bot, 'SpiceBot_Update', quitmessage) botlogs.log('SpiceBot_Update', quitmessage)
bot.osd(quitmessage, bot.channels.keys()) bot.osd(quitmessage, bot.channels.keys())
if commandused == 'nodeps': if commandused == 'nodeps':

View File

@ -6,15 +6,14 @@ import sopel.module
import time import time
from sopel_modules.SpiceBot.Logs import botlogs
from sopel_modules.SpiceBot_SBTools import humanized_time from sopel_modules.SpiceBot_SBTools import humanized_time
from sopel_modules.SpiceBot_SBTools import bot_logging
def setup(bot): def setup(bot):
if 'SpiceBot_Uptime' not in bot.memory: if 'SpiceBot_Uptime' not in bot.memory:
now = time.time() now = time.time()
bot_logging(bot, 'SpiceBot_Uptime', "Start time set to " + str(time.time())) botlogs.log('SpiceBot_Uptime', "Start time set to " + str(time.time()))
bot.memory["SpiceBot_Uptime"] = now bot.memory["SpiceBot_Uptime"] = now

View File

@ -14,7 +14,7 @@ from sopel import tools, module
from sopel.tools import Identifier from sopel.tools import Identifier
from sopel.config.types import StaticSection, ValidatedAttribute from sopel.config.types import StaticSection, ValidatedAttribute
from sopel_modules.SpiceBot_SBTools import bot_logging from sopel_modules.SpiceBot.Logs import botlogs
import time import time
from collections import abc from collections import abc
@ -27,15 +27,19 @@ __version__ = '0.1.2'
def configure(config): def configure(config):
config.define_section("MAXTARGCONFIG", MAXTARGCONFIG, validate=False) config.define_section("SpiceBot_OSD", SpiceBot_OSD, validate=False)
config.MAXTARGCONFIG.configure_setting('notice', 'MAXTARG limit for NOTICE') config.SpiceBot_OSD.configure_setting('notice', 'MAXTARG limit for NOTICE')
config.MAXTARGCONFIG.configure_setting('privmsg', 'MAXTARG limit for PRIVMSG') config.SpiceBot_OSD.configure_setting('privmsg', 'MAXTARG limit for PRIVMSG')
config.SpiceBot_OSD.configure_setting('flood_burst_lines', 'How many messages can be sent in burst mode.')
config.SpiceBot_OSD.configure_setting('flood_empty_wait', 'How long to wait between sending messages when not in burst mode, in seconds.')
config.SpiceBot_OSD.configure_setting('flood_refill_rate', 'How quickly burst mode recovers, in messages per second.')
config.SpiceBot_OSD.configure_setting('flood_dots', 'Display dots instead of spam.')
def setup(bot): def setup(bot):
# Inject OSD # Inject OSD
bot_logging(bot, 'SpiceBot_OSD', "Implanting OSD function into bot") botlogs.log('SpiceBot_OSD', "Implanting OSD function into bot")
bot.osd = SopelOSD.osd bot.osd = SopelOSD.osd
sopel.bot.SopelWrapper.osd = SopelWrapperOSD.osd sopel.bot.SopelWrapper.osd = SopelWrapperOSD.osd
tools.get_available_message_bytes = ToolsOSD.get_available_message_bytes tools.get_available_message_bytes = ToolsOSD.get_available_message_bytes
@ -43,7 +47,7 @@ def setup(bot):
tools.get_message_recipientgroups = ToolsOSD.get_message_recipientgroups tools.get_message_recipientgroups = ToolsOSD.get_message_recipientgroups
# overwrite default bot messaging # overwrite default bot messaging
bot_logging(bot, 'SpiceBot_OSD', "Overwrite Default Sopel messaging commands") botlogs.log('SpiceBot_OSD', "Overwrite Default Sopel messaging commands")
bot.osd = SopelOSD.osd bot.osd = SopelOSD.osd
bot.say = SopelOSD.say bot.say = SopelOSD.say
bot.action = SopelOSD.action bot.action = SopelOSD.action
@ -56,8 +60,8 @@ def setup(bot):
sopel.bot.SopelWrapper.reply = SopelWrapperOSD.reply sopel.bot.SopelWrapper.reply = SopelWrapperOSD.reply
# verify config settings for server # verify config settings for server
bot_logging(bot, 'SpiceBot_OSD', "Checking for config settings") botlogs.log('SpiceBot_OSD', "Checking for config settings")
bot.config.define_section("MAXTARGCONFIG", MAXTARGCONFIG, validate=False) bot.config.define_section("SpiceBot_OSD", SpiceBot_OSD, validate=False)
@module.event('005') @module.event('005')
@ -80,15 +84,29 @@ def parse_event_005(bot, trigger):
value = None value = None
if value: if value:
if settingname.upper() == 'NOTICE': if settingname.upper() == 'NOTICE':
bot.config.MAXTARGCONFIG.notice = int(value) bot.config.SpiceBot_OSD.notice = int(value)
elif settingname.upper() == 'PRIVMSG': elif settingname.upper() == 'PRIVMSG':
bot.config.MAXTARGCONFIG.privmsg = int(value) bot.config.SpiceBot_OSD.privmsg = int(value)
class MAXTARGCONFIG(StaticSection): class SpiceBot_OSD(StaticSection):
"""MAXTARG"""
notice = ValidatedAttribute('notice', default=1) notice = ValidatedAttribute('notice', default=1)
privmsg = ValidatedAttribute('privmsg', default=1) privmsg = ValidatedAttribute('privmsg', default=1)
flood_burst_lines = ValidatedAttribute('flood_burst_lines', int, default=4)
"""How many messages can be sent in burst mode."""
flood_empty_wait = ValidatedAttribute('flood_empty_wait', float, default=0.7)
"""How long to wait between sending messages when not in burst mode, in seconds."""
flood_refill_rate = ValidatedAttribute('flood_refill_rate', int, default=1)
"""How quickly burst mode recovers, in messages per second."""
flood_dots = ValidatedAttribute('flood_dots', default=True)
"""Display dots instead of spam."""
class ToolsOSD: class ToolsOSD:
@ -117,9 +135,9 @@ class ToolsOSD:
raise ValueError("Recipients list empty.") raise ValueError("Recipients list empty.")
if text_method == 'NOTICE': if text_method == 'NOTICE':
maxtargets = bot.config.MAXTARGCONFIG.notice maxtargets = bot.config.SpiceBot_OSD.notice
elif text_method in ['PRIVMSG', 'ACTION']: elif text_method in ['PRIVMSG', 'ACTION']:
maxtargets = bot.config.MAXTARGCONFIG.privmsg maxtargets = bot.config.SpiceBot_OSD.privmsg
maxtargets = int(maxtargets) maxtargets = int(maxtargets)
recipientgroups = [] recipientgroups = []
@ -259,17 +277,12 @@ class SopelOSD:
for recipientgroup in recipientgroups: for recipientgroup in recipientgroups:
text_method = text_method_orig text_method = text_method_orig
# No messages within the last 3 seconds? Go ahead!
# Otherwise, wait so it's been at least 0.8 seconds + penalty
recipient_id = Identifier(recipientgroup) recipient_id = Identifier(recipientgroup)
recipient_stack = self.stack.setdefault(recipient_id, { recipient_stack = self.stack.setdefault(recipient_id, {
'messages': [], 'messages': [],
'flood_left': 4, 'flood_left': self.config.SpiceBot_OSD.flood_burst_lines,
'dots': 0, 'dots': 0,
# TODO
# 'flood_left': self.config.core.flood_burst_lines,
}) })
recipient_stack['dots'] = 0 recipient_stack['dots'] = 0
@ -281,32 +294,30 @@ class SopelOSD:
if not recipient_stack['flood_left']: if not recipient_stack['flood_left']:
elapsed = time.time() - recipient_stack['messages'][-1][0] elapsed = time.time() - recipient_stack['messages'][-1][0]
# TODO recipient_stack['flood_left'] = min(
# recipient_stack['flood_left'] = min( self.config.SpiceBot_OSD.flood_burst_lines,
# self.config.core.flood_burst_lines, int(elapsed) * self.config.SpiceBot_OSD.flood_refill_rate)
# int(elapsed) * self.config.core.flood_refill_rate)
recipient_stack['flood_left'] = min(4, int(elapsed) * 1)
if not recipient_stack['flood_left']: if not recipient_stack['flood_left']:
elapsed = time.time() - recipient_stack['messages'][-1][0] elapsed = time.time() - recipient_stack['messages'][-1][0]
penalty = float(max(0, len(text) - 50)) / 70 penalty = float(max(0, len(text) - 50)) / 70
# Never wait more than 2 seconds # Never wait more than 2 seconds
# wait = min(self.config.core.flood_empty_wait + penalty, 2) # TODO wait = min(self.config.SpiceBot_OSD.flood_empty_wait + penalty, 2)
wait = min(0.7 + penalty, 2)
if elapsed < wait: if elapsed < wait:
time.sleep(wait - elapsed) time.sleep(wait - elapsed)
# Loop detection # Loop detection
messages = [m[1] for m in recipient_stack['messages'][-8:]] messages = [m[1] for m in recipient_stack['messages'][-8:]]
# If what we about to send repeated at least 5 times in the if self.config.SpiceBot_OSD.flood_dots:
# last 2 minutes, replace with '...' # If what we about to send repeated at least 5 times in the
if messages.count(text) >= 5 and elapsed < 120: # last 2 minutes, replace with '...'
recipient_stack['dots'] += 1 if messages.count(text) >= 5 and elapsed < 120:
else: recipient_stack['dots'] += 1
recipient_stack['dots'] = 0 else:
recipient_stack['dots'] = 0
if not recipient_stack['dots'] >= 3: if recipient_stack['dots'] <= 3:
recipient_stack['flood_left'] = max(0, recipient_stack['flood_left'] - 1) recipient_stack['flood_left'] = max(0, recipient_stack['flood_left'] - 1)
recipient_stack['messages'].append((time.time(), self.safe(text))) recipient_stack['messages'].append((time.time(), self.safe(text)))
@ -377,7 +388,10 @@ class SopelOSD:
self.osd(text, dest, 'PRIVMSG', max_messages) self.osd(text, dest, 'PRIVMSG', max_messages)
def msg(self, recipient, text, max_messages=1): def msg(self, recipient, text, max_messages=1):
# Deprecated, but way too much of a pain to remove. """
.. deprecated:: 6.0
Use :meth:`say` instead. Will be removed in Sopel 8.
"""
self.osd(text, recipient, 'PRIVMSG', max_messages) self.osd(text, recipient, 'PRIVMSG', max_messages)
@ -392,19 +406,16 @@ class SopelWrapperOSD(object):
if destination is None: if destination is None:
destination = self._trigger.sender destination = self._trigger.sender
self._bot.osd(self, message, destination, 'PRIVMSG', 1) self._bot.osd(self, message, destination, 'PRIVMSG', 1)
# self._bot.say(message, destination, max_messages)
def action(self, message, destination=None, max_messages=1): def action(self, message, destination=None, max_messages=1):
if destination is None: if destination is None:
destination = self._trigger.sender destination = self._trigger.sender
self._bot.osd(self, message, destination, 'ACTION', 1) self._bot.osd(self, message, destination, 'ACTION', 1)
# self._bot.action(message, destination, max_messages)
def notice(self, message, destination=None, max_messages=1): def notice(self, message, destination=None, max_messages=1):
if destination is None: if destination is None:
destination = self._trigger.sender destination = self._trigger.sender
self._bot.osd(self, message, destination, 'NOTICE', 1) self._bot.osd(self, message, destination, 'NOTICE', 1)
# self._bot.notice(message, destination, max_messages)
def reply(self, message, destination=None, reply_to=None, notice=False, max_messages=1): def reply(self, message, destination=None, reply_to=None, notice=False, max_messages=1):
if destination is None: if destination is None:
@ -416,4 +427,3 @@ class SopelWrapperOSD(object):
self._bot.osd(self, message, destination, 'NOTICE', 1) self._bot.osd(self, message, destination, 'NOTICE', 1)
else: else:
self._bot.osd(self, message, destination, 'PRIVMSG', 1) self._bot.osd(self, message, destination, 'PRIVMSG', 1)
# self._bot.reply(message, destination, reply_to, notice, max_messages)