Merge pull request #71 from SpiceBot/development

Development
This commit is contained in:
Deathbybandaid 2019-06-26 08:47:06 -04:00 committed by GitHub
commit 08383979ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
128 changed files with 1083 additions and 326 deletions

View File

@ -13,6 +13,7 @@ import aiml
from .Database import db as botdb
from .Config import config as botconfig
from .Read import read as botread
import spicemanip
@ -59,16 +60,7 @@ class SpiceBot_AI():
self.save_brain()
def load_brain(self):
import sopel_modules
braindirs = []
for plugin_dir in set(sopel_modules.__path__):
configsdir = os.path.join(plugin_dir, "SpiceBot_Configs")
aimldir = os.path.join(configsdir, "aiml")
braindirs.append(aimldir)
if len(botconfig.SpiceBot_AI.extra):
for extrabraindir in botconfig.SpiceBot_AI.extra:
braindirs.append(extrabraindir)
braindirs = botread.get_config_dirs("SpiceBot_AI")
# learn directories
self.learn(braindirs)

View File

@ -13,10 +13,12 @@ import os
import threading
import spicemanip
import sopel_modules
from .Logs import logs
from .Config import config as botconfig
from .Database import db as botdb
from .Read import read as botread
class SpiceBot_Commands_MainSection(StaticSection):
@ -29,7 +31,6 @@ class BotCommands():
self.setup_commands()
self.lock = threading.Lock()
self.dict = {
"counts": 0,
'nickrules': [],
'nickaiml': [],
"commands": {
@ -57,11 +58,13 @@ class BotCommands():
self.dict['nickrules'].append(command)
def find_command_type(self, command):
for commandstype in list(self.dict['commands'].keys()):
if commandstype not in ['rule']:
for com in list(self.dict['commands'][commandstype].keys()):
if com.lower() == command.lower():
return commandstype
commandtype_list = list(self.dict['commands'].keys())
if 'rule' in commandtype_list:
commandtype_list.remove('rule')
for commandstype in commandtype_list:
for com in list(self.dict['commands'][commandstype].keys()):
if com.lower() == command.lower():
return commandstype
return None
def get_commands_disabled(self, channel):
@ -107,27 +110,24 @@ class BotCommands():
self.lock.acquire()
command_type = command_dict["comtype"]
validcoms = command_dict["validcoms"]
if not isinstance(validcoms, list):
validcoms = [validcoms]
if command_type not in list(self.dict['commands'].keys()):
self.dict['commands'][command_type] = dict()
dict_from_file = dict()
# default command to filename
if "validcoms" not in list(dict_from_file.keys()):
dict_from_file["validcoms"] = validcoms
if "validcoms" not in list(command_dict.keys()):
command_dict["validcoms"] = [command_dict["filename"]]
maincom = dict_from_file["validcoms"][0]
if len(dict_from_file["validcoms"]) > 1:
comaliases = spicemanip.main(dict_from_file["validcoms"], '2+', 'list')
validcoms = command_dict["validcoms"]
if not isinstance(validcoms, list):
validcoms = [validcoms]
maincom = command_dict["validcoms"][0]
if len(command_dict["validcoms"]) > 1:
comaliases = spicemanip.main(command_dict["validcoms"], '2+', 'list')
else:
comaliases = []
self.dict['commands'][command_type][maincom] = dict_from_file
self.dict['commands'][command_type][maincom] = command_dict
for comalias in comaliases:
if comalias not in list(self.dict['commands'][command_type].keys()):
self.dict['commands'][command_type][comalias] = {"aliasfor": maincom}
@ -148,14 +148,10 @@ class BotCommands():
filepathlisting.append(home_modules_dir)
# pypi installed
try:
import sopel_modules
for plugin_dir in set(sopel_modules.__path__):
for pathname in os.listdir(plugin_dir):
pypi_modules_dir = os.path.join(plugin_dir, pathname)
filepathlisting.append(pypi_modules_dir)
except Exception as e:
logs.log('SpiceBOT_COMMANDS', "sopel_modules not loaded :" + str(e))
for plugin_dir in set(sopel_modules.__path__):
for pathname in os.listdir(plugin_dir):
pypi_modules_dir = os.path.join(plugin_dir, pathname)
filepathlisting.append(pypi_modules_dir)
# Extra directories
for directory in botconfig.extra:
@ -194,6 +190,22 @@ class BotCommands():
module_file_lines.append(line)
module_file.close()
# gather file stats
slashsplit = str(modulefile).split("/")
filename = slashsplit[-1]
filename_base = os.path.basename(filename).rsplit('.', 1)[0]
folderpath = str(modulefile).split("/" + filename)[0]
foldername = str(folderpath).split("/")[-1]
# check for json reference file
validcomdict = botread.module_json_to_dict(str(modulefile))
# replace json defaults
validcomdict["filepath"] = str(modulefile)
validcomdict["filename"] = str(filename_base)
validcomdict["folderpath"] = str(folderpath)
validcomdict["foldername"] = str(foldername)
detected_lines = []
for line in module_file_lines:
@ -222,38 +234,41 @@ class BotCommands():
filelinelist = []
currentsuccesslines = 0
for detected_line in detected_lines:
try:
# Commands
if str(detected_line).startswith("commands"):
comtype = "module"
validcoms = eval(str(detected_line).split("commands")[-1])
elif str(detected_line).startswith("nickname_commands"):
comtype = "nickname"
validcoms = eval(str(detected_line).split("nickname_commands")[-1])
elif str(detected_line).startswith("rule"):
comtype = "rule"
validcoms = eval(str(detected_line).split("rule")[-1])
# Commands
if str(detected_line).startswith("commands"):
comtype = "module"
validcoms = eval(str(detected_line).split("commands")[-1])
elif str(detected_line).startswith("nickname_commands"):
comtype = "nickname"
validcoms = eval(str(detected_line).split("nickname_commands")[-1])
elif str(detected_line).startswith("rule"):
comtype = "rule"
validcoms = eval(str(detected_line).split("rule")[-1])
if isinstance(validcoms, tuple):
validcoms = list(validcoms)
else:
validcoms = [validcoms]
for regexcom in ["(.*)", '^\?(.*)']:
if regexcom in validcoms:
while regexcom in validcoms:
validcoms.remove(regexcom)
if isinstance(validcoms, tuple):
validcoms = list(validcoms)
else:
validcoms = [validcoms]
for regexcom in ["(.*)", '^\?(.*)']:
if regexcom in validcoms:
while regexcom in validcoms:
validcoms.remove(regexcom)
if len(validcoms):
validcomdict = {"comtype": comtype, "validcoms": validcoms}
filelinelist.append(validcomdict)
currentsuccesslines += 1
if currentsuccesslines:
self.dict['counts'] += 1
if len(validcoms):
validcomdict["comtype"] = comtype
validcomdict["validcoms"] = validcoms
filelinelist.append(validcomdict)
currentsuccesslines += 1
except Exception as e:
addnothing = e
if addnothing:
currentsuccesslines += 0
if len(filelinelist):
for atlinefound in filelinelist:
self.register(atlinefound)
for vcomdict in filelinelist:
self.register(vcomdict)
commands = BotCommands()

View File

@ -0,0 +1,282 @@
# coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function
"""
This is the SpiceBot JSON Commands system.
This Class stores commands in an easy to access manner
"""
from sopel.config.types import StaticSection, ListAttribute
from .Config import config as botconfig
from .Read import read as botread
from .Commands import commands as botcommands
# import requests
from fake_useragent import UserAgent
# import urllib
import os
import copy
class SpiceBot_DictComs_MainSection(StaticSection):
extra = ListAttribute('extra')
class BotDictCommands():
def __init__(self):
self.setup_dictcoms()
self.header = {'User-Agent': str(UserAgent().chrome)}
self.valid_com_types = ['simple']
self.valid_com_types_old = [
'simple', 'fillintheblank', 'targetplusreason',
'sayings', "readfromfile", "readfromurl",
"ascii_art", "gif", "translate", "responses",
"feeds", "search"
]
self.dict_required = ["?default"]
self.builtin_keys = [
"filepath", "filename", "folderpath", "foldername",
"comtype", "type", "validcoms",
"author", "contributors",
"description", "exampleresponse", "example",
"privs"
]
self.dictcom_load()
def get_dict(self, triggersb):
# simplify usage of the bot command going forward
# copy dict to not overwrite
triggersb['comdict'] = copy.deepcopy(botcommands.dict['commands']["dictcom"][triggersb['realcom']])
# execute function based on command type
triggersb['comtype'] = triggersb['comdict']["type"].lower()
return triggersb
def dictcom_load(self):
self.dir_to_scan = botread.get_config_dirs("SpiceBot_DictComs")
for directory in self.dir_to_scan:
for valid_com_type in self.valid_com_types:
poss_path = os.path.join(directory, valid_com_type)
if os.path.exists(poss_path) and os.path.isdir(poss_path):
if len(os.listdir(poss_path)) > 0:
self.dir_to_scan.append(poss_path)
self.valid_dictcom_dict = botread.json_to_dict(self.dir_to_scan, "Dictionary Commands", "SpiceBot_DictComs")
for jsondict in list(self.valid_dictcom_dict.keys()):
dict_from_file = self.valid_dictcom_dict[jsondict]
dict_from_file["comtype"] = "dictcom"
# default command to filename
if "validcoms" not in list(dict_from_file.keys()):
dict_from_file["validcoms"] = [dict_from_file["filename"]]
elif dict_from_file["validcoms"] == []:
dict_from_file["validcoms"] = [dict_from_file["filename"]]
elif not isinstance(dict_from_file['validcoms'], list):
dict_from_file["validcoms"] = [dict_from_file["validcoms"]]
maincom = dict_from_file["validcoms"][0]
# check for tuple dict keys and split
validkeys = [x for x in list(dict_from_file.keys())]
for validkey in validkeys:
if isinstance(validkey, tuple):
tuple_bak = validkey
tuple_contents_bak = dict_from_file[validkey]
del dict_from_file[validkey]
for var in tuple_bak:
dict_from_file[var] = tuple_contents_bak
# check that type is set, use cases will inherit this if not set
if "type" not in list(dict_from_file.keys()) or dict_from_file["type"] not in self.valid_com_types:
dict_from_file["type"] = 'simple'
# handle basic required dict handling
dict_from_file = self.dictcom_load_usecases(maincom, dict_from_file, self.dict_required)
# all other keys not processed above are considered potential use cases
otherkeys = []
for otherkey in list(dict_from_file.keys()):
if otherkey not in self.builtin_keys:
otherkeys.append(otherkey)
if otherkeys != []:
dict_from_file = self.dictcom_load_usecases(maincom, dict_from_file, otherkeys)
botcommands.register(dict_from_file)
def dictcom_load_usecases(self, maincom, dict_from_file, process_list):
for mustbe in process_list:
# All of the above need to be in the dict if not
if mustbe not in list(dict_from_file.keys()):
dict_from_file[mustbe] = dict()
# verify if already there, that the key is a dict
if not isinstance(dict_from_file[mustbe], dict):
dict_from_file[mustbe] = dict()
# Each usecase for the command must have a type, flat files inherit this type
if "type" not in list(dict_from_file[mustbe].keys()):
if "type" in list(dict_from_file.keys()):
dict_from_file[mustbe]["type"] = dict_from_file["type"]
else:
dict_from_file[mustbe]["type"] = "simple"
return dict_from_file
"""
# each usecase needs to know if it can be updated. Default is false
if "updates_enabled" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["updates_enabled"] = False
if dict_from_file[mustbe]["updates_enabled"]:
if dict_from_file[mustbe]["updates_enabled"] not in ["shared", "user"]:
dict_from_file[mustbe]["updates_enabled"] = "shared"
# each usecase needs to know if it needs a target
if "target_required" not in list(dict_from_file[mustbe].keys()):
if dict_from_file[mustbe]["type"] in ['target', 'targetplusreason']:
dict_from_file[mustbe]["target_required"] = True
else:
dict_from_file[mustbe]["target_required"] = False
if "target_backup" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["target_backup"] = False
if "target_bypass" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["target_bypass"] = []
# special target reactions
for reason in ['self', 'bot', 'bots', 'offline', 'unknown', 'privmsg', 'diffchannel', 'diffbot']:
if 'react_'+reason not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]['react_'+reason] = False
# each usecase needs to know if it needs input for fillintheblank
if "blank_required" not in list(dict_from_file[mustbe].keys()):
if dict_from_file[mustbe]["type"] in ['fillintheblank', 'targetplusreason', "translate"]:
dict_from_file[mustbe]["blank_required"] = True
else:
dict_from_file[mustbe]["blank_required"] = False
if "blank_backup" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["blank_backup"] = False
if "blank_fail" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["blank_fail"] = ["This command requires input."]
if not isinstance(dict_from_file[mustbe]["blank_fail"], list):
dict_from_file[mustbe]["blank_fail"] = [dict_from_file[mustbe]["blank_fail"]]
if "blank_phrasehandle" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["blank_phrasehandle"] = False
if dict_from_file[mustbe]["blank_phrasehandle"]:
if not isinstance(dict_from_file[mustbe]["blank_phrasehandle"], list):
dict_from_file[mustbe]["blank_phrasehandle"] = [dict_from_file[mustbe]["blank_phrasehandle"]]
if "response_fail" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["response_fail"] = False
if dict_from_file[mustbe]["response_fail"]:
if not isinstance(dict_from_file[mustbe]["response_fail"], list):
dict_from_file[mustbe]["response_fail"] = [dict_from_file[mustbe]["response_fail"]]
# if dict_from_file[mustbe]["updates_enabled"]:
# adjust_nick_array(bot, str(bot.nick), 'long', 'sayings', maincom + "_" + str(mustbe), dict_from_file[mustbe]["responses"], 'startup')
# dict_from_file[mustbe]["responses"] = get_nick_value(bot, str(bot.nick), 'long', 'sayings', maincom + "_" + str(mustbe)) or []
# each usecase needs a response
if "responses" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["responses"] = []
# verify responses are in list form
if not isinstance(dict_from_file[mustbe]["responses"], list):
# TODO read text files
# if dict_from_file[mustbe]["responses"] in bot.memory["botdict"]["tempvals"]['txt_files'].keys():
# dict_from_file[mustbe]["responses"] = bot.memory["botdict"]["tempvals"]['txt_files'][dict_from_file[mustbe]["responses"]]
if str(dict_from_file[mustbe]["responses"]).startswith(tuple(["https://", "http://"])):
try:
page = requests.get(dict_from_file[mustbe]["responses"], headers=self.header)
except Exception as e:
page = e
page = None
if page and not str(page.status_code).startswith(tuple(["4", "5"])):
htmlfile = urllib.request.urlopen(dict_from_file[mustbe]["responses"])
lines = htmlfile.read().splitlines()
dict_from_file[mustbe]["responses"] = lines
else:
dict_from_file[mustbe]["responses"] = [dict_from_file[mustbe]["responses"]]
# each usecase needs a prefixtext
if "prefixtext" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["prefixtext"] = False
if dict_from_file[mustbe]["prefixtext"]:
if not isinstance(dict_from_file[mustbe]["prefixtext"], list):
dict_from_file[mustbe]["prefixtext"] = [dict_from_file[mustbe]["prefixtext"]]
# each usecase needs a suffixtext
if "suffixtext" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["suffixtext"] = False
if dict_from_file[mustbe]["suffixtext"]:
if not isinstance(dict_from_file[mustbe]["suffixtext"], list):
dict_from_file[mustbe]["suffixtext"] = [dict_from_file[mustbe]["suffixtext"]]
# Translations
if "translations" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["translations"] = False
if dict_from_file[mustbe]["translations"]:
if not isinstance(dict_from_file[mustbe]["translations"], list):
dict_from_file[mustbe]["translations"] = [dict_from_file[mustbe]["translations"]]
# make sure we have the smaller variation list
if "replyvariation" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["replyvariation"] = []
if not isinstance(dict_from_file[mustbe]["replyvariation"], list):
dict_from_file[mustbe]["replyvariation"] = [dict_from_file[mustbe]["replyvariation"]]
# This is to provide functionality for flat dictionaries responses
if dict_from_file[mustbe]["responses"] == [] and mustbe == "?default":
if "responses" in list(dict_from_file.keys()):
if isinstance(dict_from_file["responses"], list):
dict_from_file[mustbe]["responses"].extend(dict_from_file["responses"])
else:
dict_from_file[mustbe]["responses"].append(dict_from_file["responses"])
del dict_from_file["responses"]
# Verify responses list is not empty
if dict_from_file[mustbe]["responses"] == []:
dict_from_file[mustbe]["responses"].append("No " + str(mustbe) + " responses set for " + str(maincom) + ".")
# Some commands run query mode
if "search_fail" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["search_fail"] = None
if dict_from_file[mustbe]["search_fail"]:
if not isinstance(dict_from_file[mustbe]["search_fail"], list):
dict_from_file[mustbe]["search_fail"] = [dict_from_file[mustbe]["search_fail"]]
if "selection_allowed" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["selection_allowed"] = True
# Translations
if "randnum" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["randnum"] = False
if dict_from_file[mustbe]["randnum"]:
if not isinstance(dict_from_file[mustbe]["randnum"], list):
dict_from_file[mustbe]["randnum"] = [0, 50]
if len(dict_from_file[mustbe]["randnum"]) == 1:
dict_from_file[mustbe]["randnum"] = [0, dict_from_file[mustbe]["randnum"][0]]
if "hardcoded_channel_block" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["hardcoded_channel_block"] = []
if "privs" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["privs"] = []
return dict_from_file
"""
def setup_dictcoms(self):
botconfig.define_section("SpiceBot_DictComs", SpiceBot_DictComs_MainSection, validate=False)
dictcoms = BotDictCommands()

View File

@ -3,15 +3,13 @@ from __future__ import unicode_literals, absolute_import, division, print_functi
"""How to handle gifs"""
from sopel.config.types import StaticSection, ValidatedAttribute, ListAttribute
import sopel_modules
from .Config import config as botconfig
from .Tools import read_directory_json_to_dict
from .Read import read as botread
from .Commands import commands as botcommands
import spicemanip
import os
from fake_useragent import UserAgent
import urllib
import random
@ -36,17 +34,9 @@ class BotGif():
self.header = {'User-Agent': str(UserAgent().chrome)}
self.valid_api = {}
dir_to_scan = []
for plugin_dir in set(sopel_modules.__path__):
configsdir = os.path.join(plugin_dir, "SpiceBot_Configs")
gifcfgdir = os.path.join(configsdir, "gifapi")
dir_to_scan.append(gifcfgdir)
self.dir_to_scan = botread.get_config_dirs("SpiceBot_Gif")
if len(botconfig.SopelGifSearch.extra):
for extragifcfgdir in botconfig.SopelGifSearch.extra:
dir_to_scan.append(extragifcfgdir)
valid_gif_api_dict = read_directory_json_to_dict(dir_to_scan, "Gif API", "SpiceBot_Gif")
valid_gif_api_dict = botread.json_to_dict(self.dir_to_scan, "Gif API", "SpiceBot_Gif")
for gif_api in list(valid_gif_api_dict.keys()):
botconfig.define_section(gif_api, GifAPISection, validate=False)
@ -59,16 +49,12 @@ class BotGif():
if apikey:
self.valid_api[gif_api]["apikey"] = apikey
for validgifapi in list(self.valid_api.keys()):
command_dict = {
"comtype": "gif_prefix",
"validcoms": validgifapi
}
botcommands.dict['counts'] += 1
botcommands.register(command_dict)
self.valid_api[gif_api]["comtype"] = "gif_prefix"
self.valid_api[gif_api]["validcoms"] = [self.valid_api[gif_api]["filename"]]
botcommands.register(self.valid_api[gif_api])
def setup_gif(self):
botconfig.define_section("SopelGifSearch", SpiceBot_Gif_MainSection, validate=False)
botconfig.define_section("SpiceBot_Gif", SpiceBot_Gif_MainSection, validate=False)
def get_gif(self, searchdict):
@ -90,7 +76,7 @@ class BotGif():
for remx in query_defaults["gifsearchremove"]:
searchdict["gifsearch"].remove(remx)
if botconfig.SopelGifSearch.nsfw:
if botconfig.SpiceBot_Gif.nsfw:
query_defaults["nsfw"] = True
# verify query is there to search

View File

@ -23,7 +23,8 @@ class Google():
self.setup_google()
self.cache = {
"info": {},
"maps": {}
"maps": {},
"youtube": {}
}
def setup_google(self):

View File

@ -9,6 +9,7 @@ from sopel.tools import Identifier
import functools
import copy
import datetime
import spicemanip
from .Tools import command_permissions_check
@ -16,183 +17,204 @@ from .Commands import commands as botcommands
from .Database import db as botdb
class BotPrerun():
def __init__(self):
self.dict = {}
def prerun(t_command_type='module', t_command_subtype=None):
"""Command Splitting"""
def actual_decorator(function):
def prerun(self, trigger_command_type='module'):
def actual_decorator(function):
@functools.wraps(function)
def internal_prerun(bot, trigger, *args, **kwargs):
@functools.wraps(function)
def internal_prerun(bot, trigger, *args, **kwargs):
trigger_command_type = str(t_command_type)
# Primary command used for trigger, and a list of all words
trigger_args, trigger_command = self.trigger_args(trigger.args[1], trigger_command_type)
# Primary command used for trigger, and a list of all words
trigger_args, trigger_command = make_trigger_args(trigger.args[1], trigger_command_type)
# Argsdict Defaults
argsdict_default = {}
argsdict_default["type"] = trigger_command_type
argsdict_default["com"] = trigger_command
realcom = botcommands.get_realcom(argsdict_default["com"], trigger_command_type)
argsdict_default["realcom"] = realcom
# split into && groupings
and_split = self.trigger_and_split(trigger_args)
# Create dict listings for trigger.sb
argsdict_list = self.trigger_argsdict_list(argsdict_default, and_split)
# Run the function for all splits
for argsdict in argsdict_list:
trigger.sb = copy.deepcopy(argsdict)
trigger.sb["args"], trigger.sb["hyphen_arg"] = self.trigger_hyphen_args(trigger.sb["args"])
if not trigger.sb["hyphen_arg"]:
# check if anything prohibits the nick from running the command
if self.trigger_runstatus(bot, trigger):
function(bot, trigger, *args, **kwargs)
else:
self.trigger_hyphen_arg_handler(bot, trigger)
trigger_command_type = botcommands.find_command_type(trigger_command)
if not trigger_command_type:
return
return internal_prerun
return actual_decorator
if t_command_subtype:
if trigger_command_type != t_command_subtype:
return
def trigger_args(self, triggerargs_one, trigger_command_type='module'):
trigger_args = spicemanip.main(triggerargs_one, 'create')
if trigger_command_type in ['nickname']:
trigger_command = spicemanip.main(trigger_args, 2).lower()
trigger_args = spicemanip.main(trigger_args, '3+', 'list')
# Argsdict Defaults
argsdict_default = {}
argsdict_default["type"] = trigger_command_type
argsdict_default["com"] = trigger_command
realcom = botcommands.get_realcom(argsdict_default["com"], trigger_command_type)
argsdict_default["realcom"] = realcom
# split into && groupings
and_split = trigger_and_split(trigger_args)
# Create dict listings for trigger.sb
argsdict_list = trigger_argsdict_list(argsdict_default, and_split)
# Run the function for all splits
for argsdict in argsdict_list:
trigger.sb = copy.deepcopy(argsdict)
trigger.sb["args"], trigger.sb["hyphen_arg"] = trigger_hyphen_args(trigger.sb["args"])
if not trigger.sb["hyphen_arg"]:
# check if anything prohibits the nick from running the command
if trigger_runstatus(bot, trigger):
function(bot, trigger, *args, **kwargs)
else:
trigger_hyphen_arg_handler(bot, trigger)
return internal_prerun
return actual_decorator
def make_trigger_args(triggerargs_one, trigger_command_type='module'):
trigger_args = spicemanip.main(triggerargs_one, 'create')
if trigger_command_type in ['nickname']:
trigger_command = spicemanip.main(trigger_args, 2).lower()
trigger_args = spicemanip.main(trigger_args, '3+', 'list')
else:
trigger_command = spicemanip.main(trigger_args, 1).lower()[1:]
trigger_args = spicemanip.main(trigger_args, '2+', 'list')
return trigger_args, trigger_command
def trigger_and_split(trigger_args):
trigger_args_list_split = spicemanip.main(trigger_args, "split_&&")
if not len(trigger_args_list_split):
trigger_args_list_split.append([])
return trigger_args_list_split
def trigger_argsdict_list(argsdict_default, and_split):
prerun_split = []
for trigger_args_part in and_split:
argsdict_part = copy.deepcopy(argsdict_default)
argsdict_part["args"] = spicemanip.main(trigger_args_part, 'create')
if len(argsdict_part["args"]) and argsdict_part["args"][0] == "-a":
argsdict_part["adminswitch"] = True
argsdict_part["args"] = spicemanip.main(argsdict_part["args"], '2+', 'list')
else:
trigger_command = spicemanip.main(trigger_args, 1).lower()[1:]
trigger_args = spicemanip.main(trigger_args, '2+', 'list')
return trigger_args, trigger_command
argsdict_part["adminswitch"] = False
prerun_split.append(argsdict_part)
return prerun_split
def trigger_and_split(self, trigger_args):
trigger_args_list_split = spicemanip.main(trigger_args, "split_&&")
if not len(trigger_args_list_split):
trigger_args_list_split.append([])
return trigger_args_list_split
def trigger_argsdict_list(self, argsdict_default, and_split):
prerun_split = []
for trigger_args_part in and_split:
argsdict_part = copy.deepcopy(argsdict_default)
argsdict_part["args"] = spicemanip.main(trigger_args_part, 'create')
if len(argsdict_part["args"]) and argsdict_part["args"][0] == "-a":
argsdict_part["adminswitch"] = True
argsdict_part["args"] = spicemanip.main(argsdict_part["args"], '2+', 'list')
else:
argsdict_part["adminswitch"] = False
prerun_split.append(argsdict_part)
return prerun_split
def trigger_argsdict_single(argsdict_default, trigger_args_part):
argsdict_part = copy.deepcopy(argsdict_default)
argsdict_part["args"] = spicemanip.main(trigger_args_part, 'create')
if len(argsdict_part["args"]) and argsdict_part["args"][0] == "-a":
argsdict_part["adminswitch"] = True
argsdict_part["args"] = spicemanip.main(argsdict_part["args"], '2+', 'list')
else:
argsdict_part["adminswitch"] = False
return argsdict_part
def trigger_runstatus(self, bot, trigger):
return True
# Bots can't run commands
if Identifier(trigger.nick) == bot.nick:
return False
def trigger_runstatus(bot, trigger):
# Allow permissions for enabling and disabling commands via hyphenargs
if trigger.sb["adminswitch"]:
if command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']):
return True
else:
bot.osd("The admin switch (-a) is for use by authorized nicks ONLY.", 'notice')
return False
# don't run commands that are disabled in channels
if not trigger.is_privmsg:
commandused = trigger.sb["realcom"]
disabled_list = botdb.get_channel_value(trigger.sender, 'commands_disabled') or {}
if commandused in list(disabled_list.keys()):
reason = disabled_list[trigger.sb["realcom"]]["reason"]
timestamp = disabled_list[trigger.sb["realcom"]]["timestamp"]
bywhom = disabled_list[trigger.sb["realcom"]]["disabledby"]
message = "The " + str(trigger.sb["com"]) + " command was disabled by " + bywhom + " in " + str(trigger.sender) + " at " + str(timestamp) + " for the following reason: " + str(reason)
return self.trigger_cant_run(bot, trigger, message)
return True
def trigger_cant_run(self, bot, trigger, message=None):
if message:
bot.osd(message, trigger.nick, 'notice')
if command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']):
bot.osd("You however are authorized to bypass this warning with the (-a) admin switch.", trigger.nick, 'notice')
# Bots can't run commands
if Identifier(trigger.nick) == bot.nick:
return False
def trigger_hyphen_args(self, trigger_args_part):
valid_hyphen_args = [
'check',
'enable', 'disable'
]
hyphen_args = []
trigger_args_unhyphend = []
for worditem in trigger_args_part:
if str(worditem).startswith("--") and worditem[2:] in valid_hyphen_args:
hyphen_args.append(worditem[2:])
else:
trigger_args_unhyphend.append(worditem)
if len(hyphen_args):
hyphenarg = hyphen_args[0]
# Allow permissions for enabling and disabling commands via hyphenargs
if trigger.sb["adminswitch"]:
if command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']):
return True
else:
hyphenarg = None
return trigger_args_unhyphend, hyphenarg
bot.osd("The admin switch (-a) is for use by authorized nicks ONLY.", 'notice')
return False
def trigger_hyphen_arg_handler(self, bot, trigger):
if trigger.sb["hyphen_arg"]:
return False
# Commands that cannot run via privmsg
if trigger.sb["hyphen_arg"] in ['check']:
if trigger.sb["com"].lower() != trigger.sb["realcom"]:
bot.osd(trigger.sb["com"] + " is a valid alias command for " + trigger.sb["realcom"])
else:
bot.osd(trigger.sb["com"] + " is a valid command")
return
# don't run commands that are disabled in channels
if not trigger.is_privmsg:
commandused = trigger.sb["realcom"]
disabled_list = botdb.get_channel_value(trigger.sender, 'commands_disabled') or {}
if commandused in list(disabled_list.keys()):
reason = disabled_list[trigger.sb["realcom"]]["reason"]
timestamp = disabled_list[trigger.sb["realcom"]]["timestamp"]
bywhom = disabled_list[trigger.sb["realcom"]]["disabledby"]
message = "The " + str(trigger.sb["com"]) + " command was disabled by " + bywhom + " in " + str(trigger.sender) + " at " + str(timestamp) + " for the following reason: " + str(reason)
return trigger_cant_run(bot, trigger, message)
elif trigger.sb["hyphen_arg"] in ['enable']:
return True
if not command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']):
bot.osd("I was unable to disable this command due to privilege issues.")
return
if trigger.is_privmsg:
bot.osd("This command must be run in a channel you which to enable it in.", trigger.nick, 'notice')
return
def trigger_cant_run(bot, trigger, message=None):
if message:
bot.osd(message, trigger.nick, 'notice')
if command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']):
bot.osd("You however are authorized to bypass this warning with the (-a) admin switch.", trigger.nick, 'notice')
return False
if not botcommands.check_commands_disabled(trigger.sb["realcom"], trigger.sender):
bot.osd(trigger.sb["com"] + " is already enabled in " + str(trigger.sender), trigger.nick, 'notice')
return
botcommands.unset_command_disabled(trigger.sb["realcom"], trigger.sender)
bot.osd(trigger.sb["com"] + " is now enabled in " + str(trigger.sender))
return
def trigger_hyphen_args(trigger_args_part):
valid_hyphen_args = [
'check',
'enable', 'disable'
]
hyphen_args = []
trigger_args_unhyphend = []
for worditem in trigger_args_part:
if str(worditem).startswith("--") and worditem[2:] in valid_hyphen_args:
hyphen_args.append(worditem[2:])
else:
trigger_args_unhyphend.append(worditem)
if len(hyphen_args):
hyphenarg = hyphen_args[0]
else:
hyphenarg = None
return trigger_args_unhyphend, hyphenarg
elif trigger.sb["hyphen_arg"] in ['disable']:
if not command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']):
bot.osd("I was unable to disable this command due to privilege issues.")
return
if trigger.is_privmsg:
bot.osd("This command must be run in a channel you which to disable it in.", trigger.nick, 'notice')
return
if botcommands.check_commands_disabled(trigger.sb["realcom"], trigger.sender):
bot.osd(trigger.sb["com"] + " is already disabled in " + str(trigger.sender), trigger.nick, 'notice')
return
trailingmessage = spicemanip.main(trigger.sb["args"], 0) or "No reason given."
timestamp = str(datetime.datetime.utcnow())
botcommands.set_command_disabled(trigger.sb["realcom"], trigger.sender, timestamp, trailingmessage, trigger.nick)
bot.osd(trigger.sb["com"] + " is now disabled in " + str(trigger.sender))
return
def trigger_hyphen_arg_handler(bot, trigger):
# Commands that cannot run via privmsg
if trigger.sb["hyphen_arg"] in ['check']:
if trigger.sb["com"].lower() != trigger.sb["realcom"]:
bot.osd(trigger.sb["com"] + " is a valid alias command for " + trigger.sb["realcom"])
else:
bot.osd(trigger.sb["com"] + " is a valid command")
return
elif trigger.sb["hyphen_arg"] in ['enable']:
prerun = BotPrerun()
if not command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']):
bot.osd("I was unable to disable this command due to privilege issues.")
return
if trigger.is_privmsg:
bot.osd("This command must be run in a channel you which to enable it in.", trigger.nick, 'notice')
return
if not botcommands.check_commands_disabled(trigger.sb["realcom"], trigger.sender):
bot.osd(trigger.sb["com"] + " is already enabled in " + str(trigger.sender), trigger.nick, 'notice')
return
botcommands.unset_command_disabled(trigger.sb["realcom"], trigger.sender)
bot.osd(trigger.sb["com"] + " is now enabled in " + str(trigger.sender))
return
elif trigger.sb["hyphen_arg"] in ['disable']:
if not command_permissions_check(bot, trigger, ['admins', 'owner', 'OP', 'ADMIN', 'OWNER']):
bot.osd("I was unable to disable this command due to privilege issues.")
return
if trigger.is_privmsg:
bot.osd("This command must be run in a channel you which to disable it in.", trigger.nick, 'notice')
return
if botcommands.check_commands_disabled(trigger.sb["realcom"], trigger.sender):
bot.osd(trigger.sb["com"] + " is already disabled in " + str(trigger.sender), trigger.nick, 'notice')
return
trailingmessage = spicemanip.main(trigger.sb["args"], 0) or "No reason given."
timestamp = str(datetime.datetime.utcnow())
botcommands.set_command_disabled(trigger.sb["realcom"], trigger.sender, timestamp, trailingmessage, trigger.nick)
bot.osd(trigger.sb["com"] + " is now disabled in " + str(trigger.sender))
return
return

View File

@ -0,0 +1,184 @@
# coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function
"""This is a method to read files, online and local, and cache them"""
import sopel_modules
import os
import codecs
from .Logs import logs
from .Config import config as botconfig
class BotRead():
def __init__(self):
self.dict = dict()
def get_config_dirs(self, config_dir_name):
dir_to_scan = []
# check config directory stored within this project
for plugin_dir in set(sopel_modules.__path__):
configsdir = os.path.join(plugin_dir, "SpiceBot_Configs")
cfgdir = os.path.join(configsdir, config_dir_name)
if os.path.exists(cfgdir) and os.path.isdir(cfgdir):
if len(os.listdir(cfgdir)) > 0:
dir_to_scan.append(cfgdir)
# attempt to check for extra directories
try:
extradir = botconfig.extra
extradir = eval("botconfig." + config_dir_name + ".extra")
except Exception as e:
extradir = e
extradir = []
if len(extradir):
for extracfgdir in extradir:
if os.path.exists(extracfgdir) and os.path.isdir(extracfgdir):
if len(os.listdir(extracfgdir)) > 0:
dir_to_scan.append(extracfgdir)
return dir_to_scan
def json_to_dict(self, directories, configtypename="Config File", log_from='read_directory_json_to_dict', logging=True):
if not isinstance(directories, list):
directories = [directories]
configs_dict = {}
filesprocess, fileopenfail, filecount = [], 0, 0
for directory in directories:
if os.path.exists(directory) and os.path.isdir(directory):
if len(os.listdir(directory)) > 0:
for file in os.listdir(directory):
filepath = os.path.join(directory, file)
if os.path.isfile(filepath) and filepath.endswith('.json'):
filesprocess.append(filepath)
for filepath in filesprocess:
# Read dictionary from file, if not, enable an empty dict
filereadgood = True
try:
inf = codecs.open(filepath, "r", encoding='utf-8')
infread = inf.read()
# Close File
inf.close()
dict_from_file = eval(infread)
except Exception as e:
filereadgood = False
if logging:
logs.log(log_from, "Error loading %s: %s (%s)" % (configtypename, e, filepath))
dict_from_file = dict()
# gather file stats
slashsplit = str(filepath).split("/")
filename = slashsplit[-1]
filename_base = os.path.basename(filename).rsplit('.', 1)[0]
if not filereadgood or not isinstance(dict_from_file, dict):
fileopenfail += 1
else:
filecount += 1
dict_from_file["filepath"] = str(filepath)
dict_from_file["filename"] = str(filename_base)
dict_from_file["folderpath"] = dict_from_file["filepath"].split("/" + dict_from_file["filename"])[0]
dict_from_file["foldername"] = str(dict_from_file["folderpath"]).split("/")[-1]
dict_from_file = self.command_defaults(dict_from_file)
configs_dict[filename_base] = dict_from_file
if filecount:
if logging:
logs.log(log_from, 'Registered %d %s dict files,' % (filecount, configtypename))
logs.log(log_from, '%d %s dict files failed to load' % (fileopenfail, configtypename), True)
else:
if logging:
logs.log(log_from, "Warning: Couldn't load any %s dict files" % (configtypename))
return configs_dict
def module_json_to_dict(self, filepath, logging=True):
# gather file stats
slashsplit = str(filepath).split("/")
filename = slashsplit[-1]
filename_base = os.path.basename(filename).rsplit('.', 1)[0]
folderpath = str(filepath).split("/" + filename)[0]
jsonpath = os.path.join(folderpath, filename_base + ".json")
if os.path.exists(jsonpath) and os.path.isfile(jsonpath):
# Read dictionary from file, if not, enable an empty dict
filereadgood = True
try:
inf = codecs.open(jsonpath, "r", encoding='utf-8')
infread = inf.read()
dict_from_file = eval(infread)
# Close File
inf.close()
except Exception as e:
filereadgood = False
if logging:
logs.log("SpiceBot_Modules", "Error loading %s: %s (%s)" % ("Module Commands", e, jsonpath))
dict_from_file = dict()
# gather file stats
slashsplit = str(filepath).split("/")
filename = slashsplit[-1]
filename_base = os.path.basename(filename).rsplit('.', 1)[0]
if not filereadgood or not isinstance(dict_from_file, dict):
dict_from_file = {}
else:
dict_from_file["filepath"] = str(jsonpath)
dict_from_file["filename"] = str(filename_base)
dict_from_file["folderpath"] = dict_from_file["filepath"].split("/" + dict_from_file["filename"])[0]
dict_from_file["foldername"] = str(dict_from_file["folderpath"]).split("/")[-1]
dict_from_file = self.command_defaults(dict_from_file)
else:
dict_from_file = {}
dict_from_file = self.command_defaults(dict_from_file)
return dict_from_file
def command_defaults(self, dict_from_file):
# the command must have an author
if "author" not in list(dict_from_file.keys()):
dict_from_file["author"] = "deathbybandaid"
# the command must have a contributors list
if "contributors" not in list(dict_from_file.keys()):
dict_from_file["contributors"] = []
if not isinstance(dict_from_file["contributors"], list):
dict_from_file["contributors"] = [dict_from_file["contributors"]]
if "deathbybandaid" not in dict_from_file["contributors"]:
dict_from_file["contributors"].append("deathbybandaid")
if dict_from_file["author"] not in dict_from_file["contributors"]:
dict_from_file["contributors"].append(dict_from_file["author"])
if "example" not in list(dict_from_file.keys()):
dict_from_file["example"] = "$maincom"
# TODO
#if dict_from_file["comtype"] == "nickname":
# dict_from_file["example"] = str(botconfig.nick + " $maincom")
# else:
# dict_from_file["example"] = str(botconfig.core.prefix_list[0] + "$maincom")
if not dict_from_file["example"].startswith("$maincom"):
dict_from_file["example"] = "$maincom " + dict_from_file["example"]
if "exampleresponse" not in list(dict_from_file.keys()):
dict_from_file["exampleresponse"] = None
if "description" not in list(dict_from_file.keys()):
dict_from_file["description"] = None
if "privs" not in list(dict_from_file.keys()):
dict_from_file["privs"] = []
return dict_from_file
read = BotRead()

View File

@ -0,0 +1,214 @@
# coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function
"""
This is the SpiceBot Reddit system.
"""
from sopel.config.types import StaticSection, ValidatedAttribute
from sopel.formatting import bold, color, colors
import spicemanip
import datetime as dt
import praw
import prawcore
from random import randint
from .Config import config as botconfig
from .Logs import logs
class SpiceBot_Reddit_MainSection(StaticSection):
client_id = ValidatedAttribute('client_id', default=None)
client_secret = ValidatedAttribute('client_secret', default=None)
class BotReddit():
"""This Logs all channels known to the server"""
def __init__(self):
self.setup_reddit()
self.cache = {}
self.client_id = botconfig.SpiceBot_Reddit.client_id
self.client_secret = botconfig.SpiceBot_Reddit.client_secret
if not self.client_id or not self.client_secret:
self.praw = None
logs.log('SpiceBot_Reddit', "Client ID or Secret missing from config", True)
else:
self.praw = praw.Reddit(
client_id=self.client_id,
client_secret=self.client_secret,
user_agent='spicebot:net.example.myredditapp:v1.2.3 (by /u/SpiceBot-dbb)'
)
def setup_reddit(self):
botconfig.define_section("SpiceBot_Reddit", SpiceBot_Reddit_MainSection, validate=False)
def prerun(self, trigger):
if not self.praw:
return "Reddit API is not available"
message = "if you see this, there may be an error"
trigger_argsdict = self.trigger_handler(trigger)
if trigger_argsdict["slashcomm"] == "u":
return self.user_handler(trigger_argsdict)
elif trigger_argsdict["slashcomm"] == "r":
return self.subreddit_handler(trigger_argsdict)
return message
def user_handler(self, trigger_argsdict):
subcommand_valid = ['check']
subcommand = spicemanip.main([x for x in trigger_argsdict["args"] if x in subcommand_valid], 1) or 'check'
userreal = self.reddit_user_exists(trigger_argsdict["command"])
if not userreal["exists"]:
return userreal["error"]
fulluurul = str("https://www.reddit.com/" + trigger_argsdict["slashcomm"] + "/" + trigger_argsdict["command"])
if subcommand == 'check':
u = self.praw.redditor(trigger_argsdict["command"])
message = ['[REDDITOR] ' + u.name]
is_cakeday = self.user_cakeday(u.created_utc)
if is_cakeday:
message.append(bold(color('Cake day', colors.LIGHT_PURPLE)))
message.append(fulluurul)
if u.is_gold:
message.append(bold(color('Gold', colors.YELLOW)))
if u.is_mod:
message.append(bold(color('Mod', colors.GREEN)))
message.append('Link: ' + str(u.link_karma))
message.append('Comment: ' + str(u.comment_karma))
return message
def user_cakeday(self, created):
now = dt.datetime.utcnow()
cakeday_start = dt.datetime.utcfromtimestamp(created)
cakeday_start = cakeday_start.replace(year=now.year)
day = dt.timedelta(days=1)
year_div_by_400 = now.year % 400 == 0
year_div_by_100 = now.year % 100 == 0
year_div_by_4 = now.year % 4 == 0
is_leap = year_div_by_400 or ((not year_div_by_100) and year_div_by_4)
if (not is_leap) and ((cakeday_start.month, cakeday_start.day) == (2, 29)):
# If cake day is 2/29 and it's not a leap year, cake day is 3/1.
# Cake day begins at exact account creation time.
is_cakeday = cakeday_start + day <= now <= cakeday_start + (2 * day)
else:
is_cakeday = cakeday_start <= now <= cakeday_start + day
return is_cakeday
def subreddit_handler(self, trigger_argsdict):
subcommand_valid = ['check', 'hot', 'new', 'top', 'random', 'controversial', 'gilded', 'rising', 'best']
subcommand = spicemanip.main([x for x in trigger_argsdict["args"] if x in subcommand_valid], 1) or 'check'
fullrurul = str("https://www.reddit.com/" + trigger_argsdict["slashcomm"] + "/" + trigger_argsdict["command"])
subredditcheck = self.reddit_subreddit_check(trigger_argsdict["command"])
if not subredditcheck["exists"]:
return subredditcheck["error"]
subreddit = self.praw.subreddit(trigger_argsdict["command"])
if subcommand == 'check':
dispmsg = []
dispmsg.append("[Reddit " + trigger_argsdict["slashcomm"] + "/" + trigger_argsdict["command"] + "]")
if subreddit.over18:
dispmsg.append("<NSFW>")
dispmsg.append(str(subreddit.public_description))
dispmsg.append(fullrurul)
return dispmsg
if subcommand == 'random':
targnum = spicemanip.main([x for x in trigger_argsdict["args"] if str(x).isdigit()], 1) or 500
else:
targnum = spicemanip.main([x for x in trigger_argsdict["args"] if str(x).isdigit()], 1) or 1
targnum = int(targnum)
if subcommand == 'new':
submissions = subreddit.new(limit=targnum)
elif subcommand == 'top':
submissions = subreddit.top(limit=targnum)
elif subcommand == 'hot':
submissions = subreddit.hot(limit=targnum)
elif subcommand == 'controversial':
submissions = subreddit.controversial(limit=targnum)
elif subcommand == 'gilded':
submissions = subreddit.gilded(limit=targnum)
elif subcommand == 'rising':
submissions = subreddit.rising(limit=targnum)
elif subcommand == 'random':
submissions = subreddit.hot(limit=targnum)
else:
return "An error has occured."
listarray = []
for submission in submissions:
listarray.append(submission)
if listarray == []:
submission = None
elif subcommand == 'random':
submission = listarray[randint(0, len(listarray) - 1)]
else:
submission = listarray[targnum - 1]
dispmsg = []
dispmsg.append("[Reddit " + trigger_argsdict["slashcomm"] + "/" + trigger_argsdict["command"] + " " + subcommand + "]")
if subreddit.over18:
dispmsg.append("<NSFW>")
if submission:
dispmsg.append("{" + str(submission.score) + "}")
dispmsg.append(submission.title)
dispmsg.append(submission.url)
else:
dispmsg.append("No Content Found.")
return dispmsg
def trigger_handler(self, trigger):
trigger_args = spicemanip.main(trigger.args[1], 'create')
trigger_argsdict = {
"slashcomm": spicemanip.main(trigger_args, 1).lower()[:1],
"command": spicemanip.main(trigger_args, 1).lower()[2:],
"args": spicemanip.main(trigger_args, "2+", 'list')
}
if trigger_argsdict["slashcomm"] == "u":
trigger_argsdict["urltypetxt"] = "user"
if trigger_argsdict["slashcomm"] == "r":
trigger_argsdict["urltypetxt"] = "subreddit"
return trigger_argsdict
def reddit_subreddit_check(self, sub):
returndict = {"exists": True, "error": None}
try:
self.praw.subreddits.search_by_name(sub, exact=True)
except prawcore.exceptions.NotFound:
returndict["error"] = str(sub + " appears to not exist!")
returndict["exists"] = False
return returndict
try:
subtype = self.praw.subreddit(sub).subreddit_type
returndict["subtype"] = subtype
except Exception as e:
returndict["exists"] = False
if str(e) == "received 403 HTTP response":
returndict["error"] = str(sub + " appears to be an private subreddit!")
return returndict
elif str(e) == "received 404 HTTP response":
returndict["error"] = str(sub + " appears to be an banned subreddit!")
return returndict
else:
returndict["error"] = str(sub + " appears to not have a type")
return returndict
return returndict
def reddit_user_exists(self, user):
returndict = {"exists": True, "error": None}
try:
self.praw.redditor(user).fullname
except prawcore.exceptions.NotFound:
returndict["exists"] = False
returndict["error"] = str(user + " appears to not exist!")
return returndict
return returndict
reddit = BotReddit()

View File

@ -2,34 +2,38 @@
from __future__ import unicode_literals, absolute_import, division, print_function
"""A way to search google"""
import sopel_modules
from sopel.config.types import StaticSection, ListAttribute
from .Tools import read_directory_json_to_dict
from .Read import read as botread
from .Config import config as botconfig
import os
from fake_useragent import UserAgent
import requests
import time
class SpiceBot_Sherlock_MainSection(StaticSection):
extra = ListAttribute('extra')
class Sherlock():
def __init__(self):
self.setup_sherlock()
self.header = {'User-Agent': str(UserAgent().chrome)}
self.dict = {}
dir_to_scan = []
for plugin_dir in set(sopel_modules.__path__):
configsdir = os.path.join(plugin_dir, "SpiceBot_Configs")
usercfgdir = os.path.join(configsdir, "sherlock")
dir_to_scan.append(usercfgdir)
dir_to_scan = botread.get_config_dirs("SpiceBot_Sherlock")
valid_usernames_dict = read_directory_json_to_dict(dir_to_scan, "Gif API", "SpiceBot_Gif")
valid_usernames_dict = botread.json_to_dict(dir_to_scan, "Sherlock", "SpiceBot_Sherlock")
for social_network in list(valid_usernames_dict.keys()):
self.dict[social_network] = valid_usernames_dict[social_network]
self.dict[social_network]["cache"] = dict()
def setup_sherlock(self):
botconfig.define_section("SpiceBot_Sherlock", SpiceBot_Sherlock_MainSection, validate=False)
def check_network(self, username, social_network):
username = str(username).lower()

View File

@ -9,7 +9,6 @@ import sopel
import collections
import os
import sys
import codecs
from difflib import SequenceMatcher
from operator import itemgetter
from collections import abc
@ -316,57 +315,3 @@ def service_manip(servicename, dowhat, log_from='service_manip'):
os.system("sudo service " + str(servicename) + " " + str(dowhat))
except Exception as e:
logs.log(log_from, str(dowhat).title() + "ing " + str(servicename) + ".service Failed: " + str(e))
"""Config Reading Functions"""
def read_directory_json_to_dict(directories, configtypename="Config File", log_from='read_directory_json_to_dict', logging=True):
if not isinstance(directories, list):
directories = [directories]
configs_dict = {}
filesprocess, fileopenfail, filecount = [], 0, 0
for directory in directories:
if os.path.exists(directory) and os.path.isdir(directory):
if len(os.listdir(directory)) > 0:
for file in os.listdir(directory):
filepath = os.path.join(directory, file)
if os.path.isfile(filepath) and filepath.endswith('.json'):
filesprocess.append(filepath)
for filepath in filesprocess:
# Read dictionary from file, if not, enable an empty dict
filereadgood = True
inf = codecs.open(filepath, "r", encoding='utf-8')
infread = inf.read()
try:
dict_from_file = eval(infread)
except Exception as e:
filereadgood = False
if logging:
logs.log(log_from, "Error loading %s: %s (%s)" % (configtypename, e, filepath))
dict_from_file = dict()
# Close File
inf.close()
if filereadgood and isinstance(dict_from_file, dict):
filecount += 1
slashsplit = str(filepath).split("/")
filename = slashsplit[-1]
filename_base = os.path.basename(filename).rsplit('.', 1)[0]
configs_dict[filename_base] = dict_from_file
else:
fileopenfail += 1
if filecount:
if logging:
logs.log(log_from, 'Registered %d %s dict files,' % (filecount, configtypename))
logs.log(log_from, '%d %s dict files failed to load' % (fileopenfail, configtypename), True)
else:
if logging:
logs.log(log_from, "Warning: Couldn't load any %s dict files" % (configtypename))
return configs_dict

View File

@ -25,6 +25,9 @@ from .AI import *
from .Google import *
from .Gif import *
from .Sherlock import *
from .Reddit import *
from .DictComs import *
from .Read import *
from .configure import *

View File

@ -8,6 +8,9 @@ from .Google import SpiceBot_Google_MainSection
from .AI import SpiceBot_AI_MainSection
from .Update import SpiceBot_Update_MainSection
from .Gif import SpiceBot_Gif_MainSection
from .DictComs import SpiceBot_DictComs_MainSection
from .Reddit import SpiceBot_Reddit_MainSection
from .Sherlock import SpiceBot_Sherlock_MainSection
from .Kick import SpiceBot_Kick
from .osd import SpiceBot_OSD
@ -47,5 +50,15 @@ def configure(config):
config.SpiceBot_Google.configure_setting('search_api', 'api key for google searching')
config.define_section("SpiceBot_Gif", SpiceBot_Gif_MainSection, validate=False)
config.SopelGifSearch.configure_setting('extra', 'SpiceBot_Gif API Extra directory')
config.SopelGifSearch.configure_setting('nsfw', 'SpiceBot_Gif API nsfw content')
config.SpiceBot_Gif.configure_setting('extra', 'SpiceBot_Gif API Extra directory')
config.SpiceBot_Gif.configure_setting('nsfw', 'SpiceBot_Gif API nsfw content')
config.define_section("SpiceBot_Reddit", SpiceBot_Reddit_MainSection, validate=False)
config.SpiceBot_Gif.configure_setting('client_id', 'SpiceBot_Reddit client_id')
config.SpiceBot_Gif.configure_setting('client_secret', 'SpiceBot_Reddit client_secret')
config.define_section("SpiceBot_DictComs", SpiceBot_DictComs_MainSection, validate=False)
config.SpiceBot_DictComs.configure_setting('extra', 'SpiceBot_DictComs API Extra directory')
config.define_section("SpiceBot_Sherlock", SpiceBot_Sherlock_MainSection, validate=False)
config.SpiceBot_Sherlock.configure_setting('extra', 'SpiceBot_Sherlock API Extra directory')

View File

@ -15,9 +15,12 @@ from .Channels import SpiceBot_Channels_MainSection
from .Commands import SpiceBot_Commands_MainSection
from .Google import SpiceBot_Google_MainSection
from .Update import SpiceBot_Update_MainSection
from .Reddit import SpiceBot_Reddit_MainSection
from .osd import SopelWrapperOSD, ToolsOSD, SopelOSD, SpiceBot_OSD
from .Kick import SopelWrapperKICK, SopelKICK, SpiceBot_Kick
from .Gif import SpiceBot_Gif_MainSection
from .DictComs import SpiceBot_DictComs_MainSection
from .Sherlock import SpiceBot_Sherlock_MainSection
from .AI import SpiceBot_AI_MainSection
@ -55,6 +58,12 @@ def setup(bot):
setup_gif(bot)
setup_reddit(bot)
setup_dictcoms(bot)
setup_sherlock(bot)
def setup_config(bot):
logs.log('SpiceBot_Config', "Setting Up Configuration")
@ -144,4 +153,16 @@ def setup_kick(bot):
def setup_gif(bot):
bot.config.define_section("SopelGifSearch", SpiceBot_Gif_MainSection, validate=False)
bot.config.define_section("SpiceBot_Gif", SpiceBot_Gif_MainSection, validate=False)
def setup_reddit(bot):
bot.config.define_section("SpiceBot_Reddit", SpiceBot_Reddit_MainSection, validate=False)
def setup_dictcoms(bot):
bot.config.define_section("SpiceBot_DictComs", SpiceBot_DictComs_MainSection, validate=False)
def setup_sherlock(bot):
bot.config.define_section("SpiceBot_Sherlock", SpiceBot_Sherlock_MainSection, validate=False)

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "simple",
"responses": ["Bandaids? You mean bitch stickers??"],
},
}

Some files were not shown because too many files have changed in this diff Show More