Merge pull request #77 from SpiceBot/development

Development
This commit is contained in:
Deathbybandaid 2019-06-28 14:30:01 -04:00 committed by GitHub
commit 4d40a112cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
490 changed files with 7513 additions and 95 deletions

2
.gitignore vendored
View File

@ -54,4 +54,4 @@ coverage.xml
docs/_build/ docs/_build/
# PyBuilder # PyBuilder
target/ #target/

View File

@ -7,3 +7,4 @@ recursive-include tests *
recursive-exclude * __pycache__ recursive-exclude * __pycache__
recursive-exclude * *.py[co] recursive-exclude * *.py[co]
recursive-include sopel_modules/SpiceBot_Configs/* * recursive-include sopel_modules/SpiceBot_Configs/* *
recursive-include sopel_modules/SpiceBot_Text/*

View File

@ -3,3 +3,5 @@ gitpython
pygit2 pygit2
fake-useragent fake-useragent
google-api-python-client google-api-python-client
num2words
word2number

View File

@ -104,7 +104,7 @@ class BotCommands():
return self.dict['disabled'][disabletype]["users"] return self.dict['disabled'][disabletype]["users"]
elif botchannels.check_channel_bot(target, True): elif botchannels.check_channel_bot(target, True):
if not len(list(self.dict['disabled'][disabletype]["channels"])): if not len(list(self.dict['disabled'][disabletype]["channels"])):
self.dict['disabled'][disabletype]["channels"] = botdb.get_channel_value(target, 'commands_disabled') or {} self.dict['disabled'][disabletype]["channels"] = botdb.get_channel_value(target, 'commands_' + disabletype + 'disabled') or {}
return self.dict['disabled'][disabletype]["channels"] return self.dict['disabled'][disabletype]["channels"]
else: else:
raise Exception(str(target.lower()) + " appears to not be a valid user/channel") raise Exception(str(target.lower()) + " appears to not be a valid user/channel")
@ -128,14 +128,14 @@ class BotCommands():
} }
if botdb.check_nick_id(target): if botdb.check_nick_id(target):
if not len(list(self.dict['disabled'][disabletype]["users"])): if not len(list(self.dict['disabled'][disabletype]["users"])):
self.dict['disabled'][disabletype]["users"] = botdb.get_nick_value(target, 'commands_disabled') or {} self.dict['disabled'][disabletype]["users"] = botdb.get_nick_value(target, 'commands_' + disabletype + 'disabled') or {}
self.dict['disabled'][disabletype]["users"][command] = {"reason": reason, "timestamp": timestamp, "disabledby": bywhom} self.dict['disabled'][disabletype]["users"][command] = {"reason": reason, "timestamp": timestamp, "disabledby": bywhom}
botdb.set_nick_value(target, 'commands_disabled', self.dict['disabled'][disabletype]["users"]) botdb.set_nick_value(target, 'commands_' + disabletype + 'disabled', self.dict['disabled'][disabletype]["users"])
elif botchannels.check_channel_bot(target, True): elif botchannels.check_channel_bot(target, True):
if not len(list(self.dict['disabled'][disabletype]["channels"])): if not len(list(self.dict['disabled'][disabletype]["channels"])):
self.dict['disabled'][disabletype]["channels"] = botdb.get_channel_value(target, 'commands_disabled') or {} self.dict['disabled'][disabletype]["channels"] = botdb.get_channel_value(target, 'commands_' + disabletype + 'disabled') or {}
self.dict['disabled'][disabletype]["channels"][command] = {"reason": reason, "timestamp": timestamp, "disabledby": bywhom} self.dict['disabled'][disabletype]["channels"][command] = {"reason": reason, "timestamp": timestamp, "disabledby": bywhom}
botdb.set_channel_value(target, 'commands_disabled', self.dict['disabled'][disabletype]["channels"]) botdb.set_channel_value(target, 'commands_' + disabletype + 'disabled', self.dict['disabled'][disabletype]["channels"])
else: else:
raise Exception(str(target.lower()) + " appears to not be a valid user/channel") raise Exception(str(target.lower()) + " appears to not be a valid user/channel")
@ -147,16 +147,16 @@ class BotCommands():
} }
if botdb.check_nick_id(target): if botdb.check_nick_id(target):
if not len(list(self.dict['disabled'][disabletype]["users"])): if not len(list(self.dict['disabled'][disabletype]["users"])):
self.dict['disabled'][disabletype]["users"] = botdb.get_nick_value(target, 'commands_disabled') or {} self.dict['disabled'][disabletype]["users"] = botdb.get_nick_value(target, 'commands_' + disabletype + 'disabled') or {}
if command in list(self.dict['disabled'][disabletype]["users"].keys()): if command in list(self.dict['disabled'][disabletype]["users"].keys()):
del self.dict['disabled'][disabletype]["users"][command] del self.dict['disabled'][disabletype]["users"][command]
botdb.set_nick_value(target, 'commands_disabled', self.dict['disabled'][disabletype]["users"]) botdb.set_nick_value(target, 'commands_' + disabletype + 'disabled', self.dict['disabled'][disabletype]["users"])
elif botchannels.check_channel_bot(target, True): elif botchannels.check_channel_bot(target, True):
if not len(list(self.dict['disabled'][disabletype]["channels"])): if not len(list(self.dict['disabled'][disabletype]["channels"])):
self.dict['disabled'][disabletype]["channels"] = botdb.get_channel_value(target, 'commands_disabled') or {} self.dict['disabled'][disabletype]["channels"] = botdb.get_channel_value(target, 'commands_' + disabletype + 'disabled') or {}
if command in list(self.dict['disabled'][disabletype]["channels"].keys()): if command in list(self.dict['disabled'][disabletype]["channels"].keys()):
del self.dict['disabled'][disabletype]["channels"][command] del self.dict['disabled'][disabletype]["channels"][command]
botdb.set_channel_value(target, 'commands_disabled', self.dict['disabled'][disabletype]["channels"]) botdb.set_channel_value(target, 'commands_' + disabletype + 'disabled', self.dict['disabled'][disabletype]["channels"])
else: else:
raise Exception(str(target.lower()) + " appears to not be a valid user/channel") raise Exception(str(target.lower()) + " appears to not be a valid user/channel")

View File

@ -11,12 +11,14 @@ from sopel.db import SopelDB, _deserialize
from .Config import config as botconfig from .Config import config as botconfig
from sqlalchemy import Column, String, ForeignKey, Integer, Text from sqlalchemy.engine.url import URL
from sqlalchemy import create_engine, Column, String, ForeignKey, Integer, Text
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
import json import json
import threading import threading
import os
BASE = declarative_base() BASE = declarative_base()
@ -531,6 +533,48 @@ class BotDatabase():
def __init__(self): def __init__(self):
db_type = botconfig.core.db_type
if db_type == 'sqlite':
path = botconfig.core.db_filename
config_dir, config_file = os.path.split(botconfig.filename)
config_name, _ = os.path.splitext(config_file)
if path is None:
path = os.path.join(config_dir, config_name + '.db')
path = os.path.expanduser(path)
if not os.path.isabs(path):
path = os.path.normpath(os.path.join(config_dir, path))
SopelDB.filename = path
SopelDB.url = 'sqlite:///%s' % path
# Otherwise, handle all other database engines
else:
if db_type == 'mysql':
drivername = botconfig.core.db_driver or 'mysql'
elif db_type == 'postgres':
drivername = botconfig.core.db_driver or 'postgresql'
elif db_type == 'oracle':
drivername = botconfig.core.db_driver or 'oracle'
elif db_type == 'mssql':
drivername = botconfig.core.db_driver or 'mssql+pymssql'
elif db_type == 'firebird':
drivername = botconfig.core.db_driver or 'firebird+fdb'
elif db_type == 'sybase':
drivername = botconfig.core.db_driver or 'sybase+pysybase'
else:
raise Exception('Unknown db_type')
db_user = botconfig.core.db_user
db_pass = botconfig.core.db_pass
db_host = botconfig.core.db_host
db_port = botconfig.core.db_port # Optional
db_name = botconfig.core.db_name # Optional, depending on DB
SopelDB.url = URL(drivername=drivername, username=db_user, password=db_pass,
host=db_host, port=db_port, database=db_name, query={'charset': 'utf8'})
SopelDB.engine = create_engine(SopelDB.url, encoding='utf-8')
SopelDB.nick_id_lock = threading.Lock() SopelDB.nick_id_lock = threading.Lock()
sopel.db.NickIDs = NickIDs sopel.db.NickIDs = NickIDs

View File

@ -11,10 +11,8 @@ from sopel.config.types import StaticSection, ListAttribute
from .Config import config as botconfig from .Config import config as botconfig
from .Read import read as botread from .Read import read as botread
from .Commands import commands as botcommands from .Commands import commands as botcommands
from .Database import db as botdb
# import requests
from fake_useragent import UserAgent
# import urllib
import os import os
import copy import copy
@ -27,10 +25,8 @@ class BotDictCommands():
def __init__(self): def __init__(self):
self.setup_dictcoms() self.setup_dictcoms()
self.header = {'User-Agent': str(UserAgent().chrome)} self.valid_com_types = [
self.valid_com_types = ['simple'] 'simple', 'fillintheblank', 'target', 'targetplusreason',
self.valid_com_types_old = [
'simple', 'fillintheblank', 'targetplusreason',
'sayings', "readfromfile", "readfromurl", 'sayings', "readfromfile", "readfromurl",
"ascii_art", "gif", "translate", "responses", "ascii_art", "gif", "translate", "responses",
"feeds", "search" "feeds", "search"
@ -129,9 +125,6 @@ class BotDictCommands():
else: else:
dict_from_file[mustbe]["type"] = "simple" dict_from_file[mustbe]["type"] = "simple"
return dict_from_file
"""
# each usecase needs to know if it can be updated. Default is false # each usecase needs to know if it can be updated. Default is false
if "updates_enabled" not in list(dict_from_file[mustbe].keys()): if "updates_enabled" not in list(dict_from_file[mustbe].keys()):
dict_from_file[mustbe]["updates_enabled"] = False dict_from_file[mustbe]["updates_enabled"] = False
@ -180,9 +173,9 @@ class BotDictCommands():
if not isinstance(dict_from_file[mustbe]["response_fail"], list): if not isinstance(dict_from_file[mustbe]["response_fail"], list):
dict_from_file[mustbe]["response_fail"] = [dict_from_file[mustbe]["response_fail"]] dict_from_file[mustbe]["response_fail"] = [dict_from_file[mustbe]["response_fail"]]
# if dict_from_file[mustbe]["updates_enabled"]: 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') self.adjust_nick_array(str(botconfig.nick), '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 [] dict_from_file[mustbe]["responses"] = botdb.get_plugin_value("dictcom", maincom + "_" + str(mustbe)) or []
# each usecase needs a response # each usecase needs a response
if "responses" not in list(dict_from_file[mustbe].keys()): if "responses" not in list(dict_from_file[mustbe].keys()):
@ -190,20 +183,17 @@ class BotDictCommands():
# verify responses are in list form # verify responses are in list form
if not isinstance(dict_from_file[mustbe]["responses"], list): 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"])): # text files
htmlfile = urllib.request.urlopen(dict_from_file[mustbe]["responses"]) if dict_from_file[mustbe]["responses"] in list(botread.dict["text"].keys()):
lines = htmlfile.read().splitlines() dict_from_file[mustbe]["responses"] = botread.dict["text"][dict_from_file[mustbe]["responses"]]["lines"]
dict_from_file[mustbe]["responses"] = lines
if str(dict_from_file[mustbe]["responses"]).startswith(tuple(["https://", "http://"])):
botread.webpage_to_list(dict_from_file[mustbe]["responses"])
# TODO assign dict value, but don't load until needed
# TODO use botdb to store an offline version
if dict_from_file[mustbe]["responses"] in list(botread.dict["webpage"].keys()):
dict_from_file[mustbe]["responses"] = botread.dict["webpage"][dict_from_file[mustbe]["responses"]]["lines"]
else: else:
dict_from_file[mustbe]["responses"] = [dict_from_file[mustbe]["responses"]] dict_from_file[mustbe]["responses"] = [dict_from_file[mustbe]["responses"]]
@ -273,7 +263,34 @@ class BotDictCommands():
dict_from_file[mustbe]["privs"] = [] dict_from_file[mustbe]["privs"] = []
return dict_from_file return dict_from_file
"""
def adjust_nick_array(self, nick, sortingkey, usekey, values, direction):
if not isinstance(values, list):
values = [values]
oldvalues = botdb.get_nick_value(nick, usekey, sortingkey) or []
# startup entries
if direction == 'startup':
if oldvalues == []:
direction == 'add'
else:
return
# adjust
for value in values:
if direction == 'add':
if value not in oldvalues:
oldvalues.append(value)
elif direction == 'startup':
if value not in oldvalues:
oldvalues.append(value)
elif direction in ['del', 'remove']:
if value in oldvalues:
oldvalues.remove(value)
botdb.set_nick_value(nick, usekey, oldvalues, sortingkey)
def setup_dictcoms(self): def setup_dictcoms(self):
botconfig.define_section("SpiceBot_DictComs", SpiceBot_DictComs_MainSection, validate=False) botconfig.define_section("SpiceBot_DictComs", SpiceBot_DictComs_MainSection, validate=False)

View File

@ -134,7 +134,7 @@ def prerun_query(t_command_type='module', t_command_subtype=None):
# messagelog ID # messagelog ID
argsdict_default["log_id"] = botmessagelog.messagelog_assign() argsdict_default["log_id"] = botmessagelog.messagelog_assign()
argsdict_default["realcom"] = "query_command" argsdict_default["realcom"] = "query"
argsdict_default["comtext"] = "'" + bot.nick + " query'" argsdict_default["comtext"] = "'" + bot.nick + " query'"
argsdict_default["realcomtext"] = "'" + bot.nick + " query'" argsdict_default["realcomtext"] = "'" + bot.nick + " query'"
@ -143,28 +143,19 @@ def prerun_query(t_command_type='module', t_command_subtype=None):
argsdict_default["dict"] = botcommands.get_command_dict("query", 'nickname') argsdict_default["dict"] = botcommands.get_command_dict("query", 'nickname')
# split into && groupings
and_split = trigger_and_split(trigger_args)
# Create dict listings for trigger.sb # Create dict listings for trigger.sb
argsdict_list = trigger_argsdict_list(argsdict_default, and_split) argsdict = trigger_argsdict_single(argsdict_default, trigger_args)
# Run the function for all splits # Run the function for all splits
botmessagelog.messagelog_start(bot, trigger, argsdict_default["log_id"]) botmessagelog.messagelog_start(bot, trigger, argsdict_default["log_id"])
runcount = 0
for argsdict in argsdict_list:
runcount += 1
trigger.sb = copy.deepcopy(argsdict) trigger.sb = copy.deepcopy(argsdict)
trigger.sb["runcount"] = runcount trigger.sb["runcount"] = 1
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 # check if anything prohibits the nick from running the command
if trigger_runstatus(bot, trigger): if trigger_runstatus_query(bot, trigger):
function(bot, trigger, *args, **kwargs) function(bot, trigger, *args, **kwargs)
else:
trigger_hyphen_arg_handler(bot, trigger)
botmessagelog.messagelog_exit(bot, argsdict_default["log_id"]) botmessagelog.messagelog_exit(bot, argsdict_default["log_id"])
return internal_prerun return internal_prerun
@ -198,9 +189,12 @@ def trigger_argsdict_list(argsdict_default, and_split):
for trigger_args_part in and_split: for trigger_args_part in and_split:
argsdict_part = copy.deepcopy(argsdict_default) argsdict_part = copy.deepcopy(argsdict_default)
argsdict_part["args"] = spicemanip.main(trigger_args_part, 'create') argsdict_part["args"] = spicemanip.main(trigger_args_part, 'create')
if len(argsdict_part["args"]) and argsdict_part["args"][0] == "-a": if len(argsdict_part["args"]) and (argsdict_part["args"][0] == "-a" or argsdict_part["args"][-1] == "-a"):
argsdict_part["adminswitch"] = True argsdict_part["adminswitch"] = True
if argsdict_part["args"][0] == "-a":
argsdict_part["args"] = spicemanip.main(argsdict_part["args"], '2+', 'list') argsdict_part["args"] = spicemanip.main(argsdict_part["args"], '2+', 'list')
elif argsdict_part["args"][-1] == "-a":
del argsdict_part["args"][-1]
else: else:
argsdict_part["adminswitch"] = False argsdict_part["adminswitch"] = False
prerun_split.append(argsdict_part) prerun_split.append(argsdict_part)
@ -210,14 +204,68 @@ def trigger_argsdict_list(argsdict_default, and_split):
def trigger_argsdict_single(argsdict_default, trigger_args_part): def trigger_argsdict_single(argsdict_default, trigger_args_part):
argsdict_part = copy.deepcopy(argsdict_default) argsdict_part = copy.deepcopy(argsdict_default)
argsdict_part["args"] = spicemanip.main(trigger_args_part, 'create') argsdict_part["args"] = spicemanip.main(trigger_args_part, 'create')
if len(argsdict_part["args"]) and argsdict_part["args"][0] == "-a": if len(argsdict_part["args"]) and (argsdict_part["args"][0] == "-a" or argsdict_part["args"][-1] == "-a"):
argsdict_part["adminswitch"] = True argsdict_part["adminswitch"] = True
if argsdict_part["args"][0] == "-a":
argsdict_part["args"] = spicemanip.main(argsdict_part["args"], '2+', 'list') argsdict_part["args"] = spicemanip.main(argsdict_part["args"], '2+', 'list')
elif argsdict_part["args"][-1] == "-a":
del argsdict_part["args"][-1]
else: else:
argsdict_part["adminswitch"] = False argsdict_part["adminswitch"] = False
return argsdict_part return argsdict_part
def trigger_runstatus_query(bot, trigger):
# Bots can't run commands
if Identifier(trigger.nick) == bot.nick:
return False
# 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:
botmessagelog.messagelog_error(trigger.sb["log_id"], "The admin switch (-a) is for use by authorized nicks ONLY.")
return False
# don't run commands that are disabled in channels
if not trigger.is_privmsg:
channel_disabled_list = botcommands.get_commands_disabled(str(trigger.sender), "fully")
if "nickname_query" in list(channel_disabled_list.keys()):
return False
# don't run commands that are disabled for specific users
nick_disabled_list = botcommands.get_commands_disabled(str(trigger.nick), "fully")
if "nickname_query" in list(nick_disabled_list.keys()):
return False
# don't run commands that are disabled in channels
if not trigger.is_privmsg:
channel_disabled_list = botcommands.get_commands_disabled(str(trigger.sender), "fully")
if "nickname_query" in list(channel_disabled_list.keys()):
reason = channel_disabled_list["nickname_query"]["reason"]
timestamp = channel_disabled_list["nickname_query"]["timestamp"]
bywhom = channel_disabled_list["nickname_query"]["disabledby"]
message = "The " + str(trigger.sb["comtext"]) + " command was disabled by " + bywhom + " for " + str(trigger.sender) + " at " + str(timestamp) + " for the following reason: " + str(reason)
return trigger_cant_run(bot, trigger, message)
# don't run commands that are disabled for specific users
nick_disabled_list = botcommands.get_commands_disabled(str(trigger.nick), "fully")
if "nickname_query" in list(nick_disabled_list.keys()):
bywhom = nick_disabled_list["nickname_query"]["disabledby"]
if bywhom != trigger.nick:
reason = nick_disabled_list["nickname_query"]["reason"]
timestamp = nick_disabled_list["nickname_query"]["timestamp"]
message = "The " + str(trigger.sb["comtext"]) + " command was disabled by " + bywhom + " for " + str(trigger.sender) + " at " + str(timestamp) + " for the following reason: " + str(reason)
return trigger_cant_run(bot, trigger, message)
else:
botcommands.unset_command_disabled(trigger.sb["realcomref"], trigger.nick, "fully")
botmessagelog.messagelog(trigger.sb["log_id"], trigger.sb["comtext"] + " is now enabled for " + str(trigger.nick))
return True
def trigger_runstatus(bot, trigger): def trigger_runstatus(bot, trigger):
# Bots can't run commands # Bots can't run commands

View File

@ -6,6 +6,9 @@ import sopel_modules
import os import os
import codecs import codecs
import requests
import urllib
from fake_useragent import UserAgent
from .Logs import logs from .Logs import logs
from .Config import config as botconfig from .Config import config as botconfig
@ -14,7 +17,46 @@ from .Config import config as botconfig
class BotRead(): class BotRead():
def __init__(self): def __init__(self):
self.dict = dict() self.header = {'User-Agent': str(UserAgent().chrome)}
self.dict = {
"text": {},
"webpage": {},
}
self.load_txt_files()
def load_txt_files(self):
dir_to_scan = []
for plugin_dir in set(sopel_modules.__path__):
textdir = os.path.join(plugin_dir, "SpiceBot_Text")
if os.path.exists(textdir) and os.path.isdir(textdir):
if len(os.listdir(textdir)) > 0:
dir_to_scan.append(textdir)
# iterate over files within
for directory in dir_to_scan:
for txtfile in os.listdir(directory):
text_file_list = []
text_file = open(os.path.join(directory, txtfile), 'r')
lines = text_file.readlines()
for line in lines:
text_file_list.append(line)
text_file.close()
self.dict["text"][txtfile] = {
"lines": text_file_list
}
def webpage_to_list(self, url):
try:
page = requests.get(url, 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(url)
lines = htmlfile.read().splitlines()
self.dict["webpage"][url] = {
"lines": lines
}
def get_config_dirs(self, config_dir_name): def get_config_dirs(self, config_dir_name):
dir_to_scan = [] dir_to_scan = []

View File

@ -0,0 +1,195 @@
# coding=utf8
from __future__ import unicode_literals, absolute_import, division, print_function
import spicemanip
import re
from num2words import num2words
class Translate():
def __init__(self):
self.dict = {}
def bot_translate_process(self, totranslate, translationtypes):
# just in case
if not isinstance(translationtypes, list):
translationtypes = [translationtypes]
for translationtype in translationtypes:
if translationtype == "hyphen":
totranslate = spicemanip.main(totranslate, 0).replace(' ', '-')
elif translationtype == "underscore":
totranslate = spicemanip.main(totranslate, 0).replace(' ', '_')
elif translationtype == "ermahgerd":
totranslate = self.trernslert(totranslate)
elif translationtype == "obscure":
totranslate = self.text_obscure(totranslate)
elif translationtype == "piglatin":
totranslate = self.text_piglatin(totranslate)
elif translationtype == "binaryinvert":
totranslate = self.text_binary_swap(totranslate)
elif translationtype == "onetozero":
totranslate = self.text_one_to_zero_swap(totranslate)
elif translationtype == "upper":
totranslate = spicemanip.main(totranslate, 0).upper()
elif translationtype == "lower":
totranslate = spicemanip.main(totranslate, 0).lower()
return totranslate
def text_obscure(self, words):
amountofletters = len(words)
mystring = "*" * amountofletters
return mystring
def text_piglatin(self, words):
if not isinstance(words, list):
words = [words]
rebuildarray = []
for word in words:
word = word.lower()
first = word[:1]
if first in ['a', 'e', 'i', 'o', 'u']:
new_word = word + 'ay'
else:
new_word = word[1:] + first + 'ay'
rebuildarray.append(new_word)
words = spicemanip.main(rebuildarray, 0)
return words
def trernslert(self, werds):
terkerns = werds.split()
er = ''
for terk in terkerns:
if terk.endswith(','):
terk = re.sub(r"[,]+", '', terk)
cermmer = 'true'
else:
cermmer = 'false'
if terk.startswith('('):
terk = re.sub(r"[(]+", '', terk)
lerftperernthersers = 'true'
else:
lerftperernthersers = 'false'
if terk.endswith(')'):
terk = re.sub(r"[)]+", '', terk)
rerghtperernthersers = 'true'
else:
rerghtperernthersers = 'false'
if terk.endswith('%'):
terk = re.sub(r"[%]+", '', terk)
percernt = 'true'
else:
percernt = 'false'
werd = self.ermergerd(terk)
if lerftperernthersers == 'true':
werd = str('(' + werd)
if percernt == 'true':
werd = str(werd + ' PERCERNT')
if rerghtperernthersers == 'true':
werd = str(werd + ')')
if cermmer == 'true':
werd = str(werd + ',')
cermmer
er = er + ' ' + werd
return er
def ermergerd(self, w):
w = w.strip().lower()
derctshernerer = {'me': 'meh', 'you': 'u', 'are': 'er', "you're": "yer", "i'm": "erm", "i've": "erv", "my": "mah", "the": "da", "omg": "ermahgerd"}
if w in derctshernerer:
return derctshernerer[w].upper()
else:
w = re.sub(r"[\.,/;:!@#$%^&*\?)(]+", '', w)
if w[0].isdigit():
w = num2words(int(w))
w = re.sub(r"tion", "shun", w)
pat = r"[aeiouy]+"
er = re.sub(pat, "er", w)
if w.startswith('y'):
er = 'y' + re.sub(pat, "er", w[1:])
if w.endswith('e') and not w.endswith('ee') and len(w) > 3:
er = re.sub(pat, "er", w[:-1])
if w.endswith('ing'):
er = re.sub(pat, "er", w[:-3]) + 'in'
er = er[0] + er[1:].replace('y', 'er')
er = er.replace('rr', 'r')
return er.upper()
def text_one_to_zero_swap(self, words):
if not words or words == []:
return "No input provided"
if not isinstance(words, list):
words = [words]
words = spicemanip.main(words, 0).split(" ")
outputarray = []
for word in words:
if not self.isitbinary(word):
word = self.text_binary_swap(word)
word = str(word).replace('1', '2')
word = str(word).replace('0', '1')
word = str(word).replace('2', '0')
outputarray.append(str(word))
outputarray = spicemanip.main(outputarray, 0)
return outputarray
def text_binary_swap(self, words):
if not words or words == []:
return "No input provided"
if not isinstance(words, list):
words = [words]
words = spicemanip.main(words, 0).split(" ")
outputarray = []
for word in words:
if self.isitbinary(word):
word = self.bits2string(word) or 'error'
else:
word = self.string2bits(word) or 1
word = spicemanip.main(word, 0)
outputarray.append(str(word))
outputarray = spicemanip.main(outputarray, 0)
return outputarray
def unicode_string_cleanup(string):
for r in (("\u2013", "-"), ("\u2019", "'"), ("\u2026", "...")):
string = string.replace(*r)
return string
def isitbinary(self, string):
p = set(string)
s = {'0', '1'}
if s == p or p == {'0'} or p == {'1'}:
return True
else:
return False
def string2bits(self, s=''):
return [bin(ord(x))[2:].zfill(8) for x in s]
def bits2string(self, b=None):
return ''.join(chr(int(b[i*8:i*8+8], 2)) for i in range(len(b)//8))
translate = Translate()

View File

@ -5,7 +5,9 @@ from __future__ import unicode_literals, absolute_import, division, print_functi
from sopel.tools import Identifier from sopel.tools import Identifier
from .Database import db as botdb from .Database import db as botdb
from .Tools import is_number from .Tools import is_number, inlist, similar, array_arrangesort
import spicemanip
# TODO timestamp for new .seen # TODO timestamp for new .seen
@ -45,9 +47,15 @@ class BotUsers():
nick_id = self.whois_ident(nickinput) nick_id = self.whois_ident(nickinput)
return nick_id return nick_id
def whois_ident(self, nick): def whois_ident(self, nick, usercreate=True):
nick = Identifier(nick) nick = Identifier(nick)
nick_id = botdb.db.get_nick_id(nick, create=True) try:
nick_id = botdb.db.get_nick_id(nick, create=usercreate)
except Exception as e:
nick_id = e
nick_id = None
if usercreate:
self.add_to_all(nick, nick_id)
return int(nick_id) return int(nick_id)
def save_user_db(self): def save_user_db(self):
@ -84,8 +92,8 @@ class BotUsers():
# set current nick # set current nick
self.dict["current"][nick_id]["nick"] = user self.dict["current"][nick_id]["nick"] = user
# add joined channel to nick list # add joined channel to nick list
if channel not in self.dict["current"][nick_id]["channels"]: if str(channel).lower() not in self.dict["current"][nick_id]["channels"]:
self.dict["current"][nick_id]["channels"].append(channel) self.dict["current"][nick_id]["channels"].append(str(channel).lower())
# mark user as online # mark user as online
if nick_id not in self.dict["online"]: if nick_id not in self.dict["online"]:
self.dict["online"].append(int(nick_id)) self.dict["online"].append(int(nick_id))
@ -104,8 +112,8 @@ class BotUsers():
# set current nick # set current nick
self.dict["current"][nick_id]["nick"] = user self.dict["current"][nick_id]["nick"] = user
# add joined channel to nick list # add joined channel to nick list
if trigger.sender not in self.dict["current"][nick_id]["channels"]: if str(trigger.sender).lower() not in self.dict["current"][nick_id]["channels"]:
self.dict["current"][nick_id]["channels"].append(trigger.sender) self.dict["current"][nick_id]["channels"].append(str(trigger.sender).lower())
# mark user as online # mark user as online
if nick_id not in self.dict["online"]: if nick_id not in self.dict["online"]:
self.dict["online"].append(int(nick_id)) self.dict["online"].append(int(nick_id))
@ -121,8 +129,8 @@ class BotUsers():
# set current nick # set current nick
self.dict["current"][nick_id]["nick"] = trigger.nick self.dict["current"][nick_id]["nick"] = trigger.nick
# add joined channel to nick list # add joined channel to nick list
if trigger.sender not in self.dict["current"][nick_id]["channels"]: if str(trigger.sender).lower() not in self.dict["current"][nick_id]["channels"]:
self.dict["current"][nick_id]["channels"].append(trigger.sender) self.dict["current"][nick_id]["channels"].append(str(trigger.sender).lower())
# mark user as online # mark user as online
if nick_id not in self.dict["online"]: if nick_id not in self.dict["online"]:
self.dict["online"].append(int(nick_id)) self.dict["online"].append(int(nick_id))
@ -139,8 +147,8 @@ class BotUsers():
# Verify nick is in the all list # Verify nick is in the all list
self.add_to_current(trigger.nick, nick_id) self.add_to_current(trigger.nick, nick_id)
# empty nicks channel list # empty nicks channel list
if trigger.sender in self.dict["current"][nick_id]["channels"]: if str(trigger.sender).lower() in self.dict["current"][nick_id]["channels"]:
self.dict["current"][nick_id]["channels"].remove(trigger.sender) self.dict["current"][nick_id]["channels"].remove(str(trigger.sender).lower())
self.dict["current"][nick_id]["channels"] = [] self.dict["current"][nick_id]["channels"] = []
# mark user as offline # mark user as offline
if nick_id in self.dict["online"]: if nick_id in self.dict["online"]:
@ -151,8 +159,8 @@ class BotUsers():
def part(self, bot, trigger): def part(self, bot, trigger):
if trigger.nick == bot.nick: if trigger.nick == bot.nick:
for nick_id in list(self.dict["current"].keys()): for nick_id in list(self.dict["current"].keys()):
if trigger.sender in self.dict["current"][nick_id]["channels"]: if str(trigger.sender).lower() in self.dict["current"][nick_id]["channels"]:
self.dict["current"][nick_id]["channels"].remove(trigger.sender) self.dict["current"][nick_id]["channels"].remove(str(trigger.sender).lower())
# mark offline # mark offline
if not len(self.dict["current"][nick_id]["channels"]) and nick_id in self.dict["online"]: if not len(self.dict["current"][nick_id]["channels"]) and nick_id in self.dict["online"]:
self.dict["online"].remove(nick_id) self.dict["online"].remove(nick_id)
@ -166,8 +174,8 @@ class BotUsers():
# Verify nick is in the all list # Verify nick is in the all list
self.add_to_current(trigger.nick, nick_id) self.add_to_current(trigger.nick, nick_id)
# remove channel from nick list # remove channel from nick list
if trigger.sender in self.dict["current"][nick_id]["channels"]: if str(trigger.sender).lower() in self.dict["current"][nick_id]["channels"]:
self.dict["current"][nick_id]["channels"].remove(trigger.sender) self.dict["current"][nick_id]["channels"].remove(str(trigger.sender).lower())
# mark offline # mark offline
if not len(self.dict["current"][nick_id]["channels"]) and nick_id in self.dict["online"]: if not len(self.dict["current"][nick_id]["channels"]) and nick_id in self.dict["online"]:
self.dict["online"].remove(nick_id) self.dict["online"].remove(nick_id)
@ -178,8 +186,8 @@ class BotUsers():
targetnick = Identifier(str(trigger.args[1])) targetnick = Identifier(str(trigger.args[1]))
if targetnick == bot.nick: if targetnick == bot.nick:
for nick_id in list(self.dict["current"].keys()): for nick_id in list(self.dict["current"].keys()):
if trigger.sender in self.dict["current"][nick_id]["channels"]: if str(trigger.sender).lower() in self.dict["current"][nick_id]["channels"]:
self.dict["current"][nick_id]["channels"].remove(trigger.sender) self.dict["current"][nick_id]["channels"].remove(str(trigger.sender).lower())
# mark offline # mark offline
if not len(self.dict["current"][nick_id]["channels"]) and nick_id in self.dict["online"]: if not len(self.dict["current"][nick_id]["channels"]) and nick_id in self.dict["online"]:
self.dict["online"].remove(nick_id) self.dict["online"].remove(nick_id)
@ -193,8 +201,8 @@ class BotUsers():
# Verify nick is in the all list # Verify nick is in the all list
self.add_to_current(targetnick, nick_id) self.add_to_current(targetnick, nick_id)
# remove channel from nick list # remove channel from nick list
if trigger.sender in self.dict["current"][nick_id]["channels"]: if str(trigger.sender).lower() in self.dict["current"][nick_id]["channels"]:
self.dict["current"][nick_id]["channels"].remove(trigger.sender) self.dict["current"][nick_id]["channels"].remove(str(trigger.sender).lower())
# mark offline # mark offline
if not len(self.dict["current"][nick_id]["channels"]) and nick_id in self.dict["online"]: if not len(self.dict["current"][nick_id]["channels"]) and nick_id in self.dict["online"]:
self.dict["online"].remove(nick_id) self.dict["online"].remove(nick_id)
@ -217,8 +225,8 @@ class BotUsers():
# set current nick # set current nick
self.dict["current"][nick_id]["nick"] = newnick self.dict["current"][nick_id]["nick"] = newnick
# add joined channel to nick list # add joined channel to nick list
if trigger.sender not in self.dict["current"][nick_id]["channels"]: if str(trigger.sender).lower() not in self.dict["current"][nick_id]["channels"]:
self.dict["current"][nick_id]["channels"].append(trigger.sender) self.dict["current"][nick_id]["channels"].append(str(trigger.sender).lower())
# mark user as online # mark user as online
if nick_id not in self.dict["online"]: if nick_id not in self.dict["online"]:
self.dict["online"].append(int(nick_id)) self.dict["online"].append(int(nick_id))
@ -228,12 +236,107 @@ class BotUsers():
def mode(self, bot, trigger): def mode(self, bot, trigger):
return return
def targetcheck(self): def targetcheck(self, target):
return True return True
# idk whois # idk whois
if not botdb.check_nick_id(posstarget): if not botdb.check_nick_id(target):
return return
def nick_actual(self, nick, altlist=None):
nick_id = self.whois_ident(nick)
nick_actual = self.ID(nick_id)
return nick_actual
def target_online(self, nick, nick_id=None):
if not nick_id:
nick_id = self.ID(nick)
if nick_id in self.dict["online"]:
return True
else:
return False
def target_check(self, bot, trigger, target, targetbypass):
targetgood = {"targetgood": True, "error": "None", "reason": None}
if not isinstance(targetbypass, list):
targetbypass = [targetbypass]
if "notarget" not in targetbypass:
if not target or target == '':
return {"targetgood": False, "error": "No target Given.", "reason": "notarget"}
# Optional don't allow self-target
if "self" not in targetbypass:
if inlist(target, trigger.nick):
return {"targetgood": False, "error": "This command does not allow you to target yourself.", "reason": "self"}
# cannot target bots
if "bot" not in targetbypass:
if inlist(target, bot.nick):
return {"targetgood": False, "error": "I am a bot and cannot be targeted.", "reason": "bot"}
if "bots" not in targetbypass:
if inlist(target, bot.nick):
return {"targetgood": False, "error": self.nick_actual(target) + " is a bot and cannot be targeted.", "reason": "bots"}
# Not a valid user
if "unknown" not in targetbypass:
if not botdb.check_nick_id(target):
sim_user, sim_num = [], []
for nick_id in list(self.dict["all"].keys()):
nick_list = self.dict["all"][nick_id]
for nick in nick_list:
similarlevel = similar(str(target).lower(), nick.lower())
if similarlevel >= .75:
sim_user.append(nick)
sim_num.append(similarlevel)
if sim_user != [] and sim_num != []:
sim_num, sim_user = array_arrangesort(bot, sim_num, sim_user)
closestmatch = spicemanip.main(sim_user, 'reverse', "list")
listnumb, relist = 1, []
for item in closestmatch:
if listnumb <= 3:
relist.append(str(item))
listnumb += 1
closestmatches = spicemanip.main(relist, "andlist")
targetgooderror = "It looks like you're trying to target someone! Did you mean: " + str(closestmatches) + "?"
else:
targetgooderror = "I am not sure who that is."
return {"targetgood": False, "error": targetgooderror, "reason": "unknown"}
nick_id = self.whois_ident(target, usercreate=False)
# User offline
if "offline" not in targetbypass:
if not self.target_online(target, nick_id):
return {"targetgood": False, "error": "It looks like " + self.nick_actual(target) + " is offline right now!", "reason": "offline"}
# Private Message
if "privmsg" not in targetbypass:
if trigger.is_privmsg and not inlist(target, trigger.nick):
return {"targetgood": False, "error": "Leave " + self.nick_actual(target) + " out of this private conversation!", "reason": "privmsg"}
# not in the same channel
if "diffchannel" not in targetbypass:
if not trigger.is_privmsg and self.target_online(target, nick_id):
if str(trigger.sender).lower() not in self.dict["current"][nick_id]["channels"]:
return {"targetgood": False, "error": "It looks like " + self.nick_actual(target) + " is online right now, but in a different channel.", "reason": "diffchannel"}
return targetgood
def random_valid_target(self, bot, trigger, outputtype):
validtargs = []
if trigger.is_privmsg:
validtargs.extend([str(bot.nick), trigger.nick])
else:
for nick_id in self.dict["online"]:
if str(trigger.sender).lower() in self.dict["current"][nick_id]["channels"]:
nick = self.dict["all"][nick_id][0]
validtargs.append(nick)
if outputtype == 'list':
return validtargs
elif outputtype == 'random':
return spicemanip.main(validtargs, 'random')
users = BotUsers() users = BotUsers()

View File

@ -29,6 +29,7 @@ from .Sherlock import *
from .Reddit import * from .Reddit import *
from .DictComs import * from .DictComs import *
from .Read import * from .Read import *
from .Translate import *
from .configure import * from .configure import *

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' ( 〇□〇) '],
},
}

View File

@ -0,0 +1,28 @@
{
"?default": {
"type": "simple",
"responses": [
[
"_________$$____________",
"________$__$___________",
"________$__$___________",
"_______$$__$$__________",
"______$__$__$_$$_$$____",
"______$__$__$__$$__$___",
"_$$$__$__$__$__$$__$___",
"$___$$_______________$_",
"$____$$_______________$",
"_$____________________$",
"__$___________________$",
"___$_________________$_",
"____$_______________$__",
"_____$_____________$___",
"______$___________$____",
"_______$$$$$$$$$$$_____",
],
],
},
}

View File

@ -0,0 +1,7 @@
{
"validcoms": ['confused', 'wat'],
"?default": {
"type": "simple",
"responses": [' (●__●)??? '],
},
}

View File

@ -0,0 +1,16 @@
{
"?default": {
"type": "simple",
"responses": [
[
" (",
" __________ )\\",
" / /\______{,}",
" \_________\/",
],
],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' ⊙_ʘ '],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' ( p′︵‵。) '],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' ᕕ( ᐛ )ᕗ '],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' ლ(´ڡ`ლ) '],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' (●♡∀♡) '],
},
}

View File

@ -0,0 +1,7 @@
{
"validcoms": ['rage', 'anger'],
"?default": {
"type": "simple",
"responses": [' щ(ಠ益ಠщ) '],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [" ¯\_(ツ)_/¯ "],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' (-﹏-。) '],
},
}

View File

@ -0,0 +1,7 @@
{
"validcoms": ['success', 'winner'],
"?default": {
"type": "simple",
"responses": [' ٩( ᐛ )و '],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' (((( ;°Д°)))) '],
},
}

View File

@ -0,0 +1,7 @@
{
"validcoms": ['tableflip', 'flip', 'tflip'],
"?default": {
"type": "simple",
"responses": [' (╯°□°)╯︵ ┻━┻ '],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' ┬┬ ノ( ゜-゜ノ) '],
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "simple",
"responses": [' ( ゚д゚) '],
},
}

View File

@ -0,0 +1,7 @@
{
"validcoms": ['sword', 'link', 'zelda'],
"?default": {
"type": "simple",
"responses": ["It's dangerous to go alone take this 0==|======>"],
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['atwebby', 'actualtechwebby'],
"?default": {
"type": "feeds",
"responses": "actualtechwebby",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['comptiawebby'],
"?default": {
"type": "feeds",
"responses": "comptiawebby",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['dilbert'],
"?default": {
"type": "feeds",
"responses": "dilbert",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,22 @@
{
"validcoms": ['github', 'repo'],
"?default": {
"type": "simple",
"responses": ['You have two choices. master or dev'],
},
"master": {
"type": "feeds",
"responses": "githubrepomaster",
"selection_allowed": False,
},
("dev", "development"): {
"type": "feeds",
"responses": "githubrepodev",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['packt'],
"?default": {
"type": "feeds",
"responses": "packt",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['gcal', 'spicebotcal', 'spicecal'],
"?default": {
"type": "feeds",
"responses": "spicebotcalendar",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['spicewebby', 'spiceworkswebby'],
"?default": {
"type": "feeds",
"responses": "spiceworkswebby",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['stardate'],
"?default": {
"type": "feeds",
"responses": "stardates",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['onion', 'theonion'],
"?default": {
"type": "feeds",
"responses": "theonion",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['truthinit'],
"?default": {
"type": "feeds",
"responses": "truthinit",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['twitlive'],
"?default": {
"type": "feeds",
"responses": "twitlive",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['xkcd'],
"?default": {
"type": "feeds",
"responses": "xkcd",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['zits'],
"?default": {
"type": "feeds",
"responses": "zits",
"selection_allowed": False,
},
}

View File

@ -0,0 +1,10 @@
{
"validcoms": ['notsaying', 'aliens'],
"?default": {
"type": "fillintheblank",
"blank_phrasehandle": ["a", "an"],
"responses": ["I'm not saying it was $blank, but it was $blank!"],
"blank_backup": "aliens",
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['ants', 'ant'],
"?default": {
"type": "fillintheblank",
"responses": ["Do you want $blank cause that's how you get $blank!"],
"blank_backup": 'ants',
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["$instigator approves $blank"],
"blank_backup": 'that',
},
}

View File

@ -0,0 +1,10 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["$instigator introduces a backdoor into $blank system"],
"response_fail": [
"$instigator introduces a backdoor into my system... Ohhh... It tickles.",
],
},
}

View File

@ -0,0 +1,9 @@
{
"validcoms": ['backup', 'backups'],
"?default": {
"type": "fillintheblank",
"responses": ["$blank? weee dun neeeed no steenkin $blank!!"],
"blank_backup": "backups"
},
}

View File

@ -0,0 +1,6 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["If you $blank, you're gonna have a bad time"],
},
}

View File

@ -0,0 +1,9 @@
{
"validcoms": ['beach'],
"?default": {
"type": "fillintheblank",
"responses": ["$instigator wants to start a ransomware company on the beach because of $blank!"],
"blank_backup": "money",
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["We're gonna need a bigger $blank!"],
"blank_backup": 'boat',
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['boop', 'r2d2'],
"?default": {
"type": "fillintheblank",
"responses": ["$botnick boops $instigator softly because $input!"],
"response_fail": "$botnick boops $instigator softly!",
},
}

View File

@ -0,0 +1,20 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["let me call my buddy and get him down here... he's an expert on $blank"],
"response_fail": [
"What is your buddy good at?",
],
},
"not": {
"type": "simple",
"responses": [
[
"I'm not your friend, buddy",
"I'm not your buddy, pal",
"I'm not your pal, guy",
"I'm not your guy, friend ",
]
],
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['catch', 'first'],
"?default": {
"type": "fillintheblank",
"responses": ["The first $blank of the day!"],
"blank_backup": 'catch',
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['chump', 'chumps'],
"?default": {
"type": "fillintheblank",
"responses": ["$blanks are for chumps!!!!"],
},
}

View File

@ -0,0 +1,9 @@
{
"validcoms": ['cdh', 'colddeadhands'],
"?default": {
"type": "fillintheblank",
"responses": ["You can have my $blank, when you pry it from my cold dead hands!!"],
"blank_backup": 'gun',
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["Needs Moar $blank!!"],
"blank_backup": 'cowbell',
},
}

View File

@ -0,0 +1,6 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["$blank, $blank everywhere!"],
},
}

View File

@ -0,0 +1,9 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["For the record: $blank"],
"blank_backup": "it was not my fault",
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['grind', 'gears', 'grinds', 'gears'],
"?default": {
"type": "fillintheblank",
"responses": ["You know what grinds my gears?? $blank"],
"blank_required": False,
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["YOU CAN'T HANDLE THE $blank"],
"blank_backup": 'truth',
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['got', 'milk'],
"?default": {
"type": "fillintheblank",
"responses": ["Got $blank?"],
"blank_backup": 'milk',
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["If you could $blank,,, That'd be great."],
"blank_backup": 'come in on Saturday',
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["Stop trying to make $blank happen. It's not going to happen!"],
"blank_backup": "stuff",
},
}

View File

@ -0,0 +1,18 @@
{
"validcoms": ['hashbrown', 'hb'],
"?default": {
"type": "fillintheblank",
"responses": ["hashbrown $blank"],
"blank_backup": 'fail',
},
"fwp": {
"type": "fillintheblank",
"responses": ["hashbrown $blank"],
"blank_backup": 'firstworldproblems',
},
"ym": {
"type": "fillintheblank",
"responses": ["hashbrown $blank"],
"blank_backup": 'yo momma',
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["Too much $blank is bad for your health."],
"blank_backup": '$instigator',
},
}

View File

@ -0,0 +1,18 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["mmmmmmm $blank"],
"blank_backup": 'donuts',
},
('good', 'g'): {
"type": "simple",
"responses": ["WooHoo!"],
},
('bad', 'b', 'bad?', 'good?'): {
"type": "simple",
"responses": ["D'ooooh!"],
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['ich', 'icanhaz'],
"?default": {
"type": "fillintheblank",
"responses": ["I can haz $blank??"],
"blank_backup": 'stuff',
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["I Can't Even $blank"],
"blank_backup": '...',
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["I don't always $blank, but when I do, I drink Dos Equis."],
"blank_backup": 'drink beer',
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["$blank IS HAAAAARD!!!"],
"blank_backup": 'stuff',
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["$blank??? is THAT what the kids are calling it these days?"],
},
}

View File

@ -0,0 +1,6 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["Am I the only one around here who $blank???"],
},
}

View File

@ -0,0 +1,10 @@
{
"validcoms": ['let', 'letit', 'letitgo'],
"?default": {
"type": "fillintheblank",
"responses": ["Let it $blank, let it $blank; Can't hold it back anymore; Let it $blank, let it $blank; Turn away and slam the door; I don't care what they're going to say; Let the storm rage on; The cold never bothered me anyway; Let it $blank, let it $blank; Can't hold it back anymore; Let it $blank, let it $blank; Turn away and slam the door"],
"blank_backup": "go",
# "blank_phrasehandle": ["a", "an"],
},
}

View File

@ -0,0 +1,9 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["I like $blank!"],
"blank_backup": "$replyvariation",
"replyvariation": ["porn", "turtles", "trains"],
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['mf', 'motherfuckers'],
"?default": {
"type": "fillintheblank",
"responses": ["Y'all motherfuckers need $blank!"],
"blank_backup": 'Surak',
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["$instigator thinks it's starting to get a little misty up in $blank"],
"blank_backup": 'this biznatch',
},
}

View File

@ -0,0 +1,6 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["What if I told you $blank"],
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["Fine! I'll build my own $blank, with blackjack and hookers. In fact, forget the $blank and the blackjack. Ahh, screw the whole thing!"],
"blank_backup": "lunar lander",
},
}

View File

@ -0,0 +1,10 @@
{
"validcoms": ['never'],
"?default": {
"type": "fillintheblank",
"blank_phrasehandle": ["a", "an"],
"responses": ["they say there's never a $blank around when you need them"],
"blank_backup": "cop",
},
}

View File

@ -0,0 +1,9 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["Really ?? We dont have a $blank yet??"],
"blank_backup": "new",
},
}

View File

@ -0,0 +1,14 @@
{
"?default": {
"type": "fillintheblank",
"blank_phrasehandle": ["for"],
"responses": ["Ain't nobody got time $blank!"],
"blank_backup": "dat",
},
"full": {
"type": "fillintheblank",
"blank_phrasehandle": ["for"],
"responses": ["Well I woke up to get me a cold pop and then I thought somebody was barbequing. I said oh lord Jesus it's a fire. Then I ran out, I didn't grab no shoes or nothin' Jesus, I ran for my life. And then the smoke got me, I got bronchitis ain't nobody got time $blank!"],
"blank_backup": "dat",
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['old'],
"?default": {
"type": "fillintheblank",
"responses": ["Sorry dude, I'm way too fucking old right now for $blank!!"],
"blank_backup": 'that shit',
},
}

View File

@ -0,0 +1,9 @@
{
"?default": {
"type": "fillintheblank",
"blank_phrasehandle": ["a", "an"],
"responses": ["You get $blank! And You get $blank! Everyone gets $blank!"],
"blank_backup": "car",
},
}

View File

@ -0,0 +1,11 @@
{
"validcoms": ['pepperidgefarms', 'pf'],
"?default": {
"type": "fillintheblank",
"responses": ["Pepperidge Farms remembers $blank"],
"response_fail": [
"You're so old Pepperidge Farms doesn't even remember that.",
],
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["How can you have any $blank if you don't eat your meat!?!"],
"blank_backup": 'anything good',
},
}

View File

@ -0,0 +1,7 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["Piping to bash is dangerous, this pipe only accessible to $blank"],
"blank_backup": "Mario",
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['props','prop'],
"?default": {
"type": "fillintheblank",
"responses": ["I'll give you props for doing that $blank!"],
"blank_required": False,
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["The reason I gathered you all here today is... $blank!"],
"blank_required": False,
},
}

View File

@ -0,0 +1,9 @@
{
"validcoms": ['rrr', 'reducereuserecycle'],
"?default": {
"type": "fillintheblank",
"responses": ["Reduce, Reuse, Recycle $blank"],
"blank_backup": 'everything',
},
}

View File

@ -0,0 +1,11 @@
{
"?default": {
"type": "fillintheblank",
"prefixtext": "<secret_bot_code> ",
"suffixtext": " </secret_bot_code>",
"responses": ["$blank"],
"translations": ["underscore"],
"blank_backup": 'whisper_whisper_whisper',
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['simply', 'lotr'],
"?default": {
"type": "fillintheblank",
"responses": ["One does not simply $blank"],
"blank_backup": 'walk into mordor',
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["NO $blank FOR YOU!"],
"blank_backup": 'soup',
"translations": ["upper"],
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['steenkin', 'dontneed'],
"?default": {
"type": "fillintheblank",
"responses": ["$blank? weee dun neeeed no steenkin $blank!!"],
},
}

View File

@ -0,0 +1,10 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["$instigator struggles with $blank"],
"response_fail": [
"You don't know me! You don't know my struggles!",
],
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['suckers', 'sucker'],
"?default": {
"type": "fillintheblank",
"responses": ["$blanks are for suckers!!!!"],
},
}

View File

@ -0,0 +1,8 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["sudo $blank"],
"blank_backup": 'Go make me a sandwich',
},
}

View File

@ -0,0 +1,10 @@
{
"?default": {
"type": "fillintheblank",
"responses": ["to be honest; $blank"],
"response_fail": [
"Lets be honest...",
],
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['tr', 'thatsracist'],
"?default": {
"type": "fillintheblank",
"responses": ["That's Racist against $blank!"],
"response_fail": "That's Racist!™",
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['ts', 'thatssexist'],
"?default": {
"type": "fillintheblank",
"responses": ["That's sexist against $blank! (you misogynistic prick!)"],
"response_fail": "That's Sexist!™ (you misogynistic prick!)",
},
}

View File

@ -0,0 +1,8 @@
{
"validcoms": ['thc', 'doobie', 'pot'],
"?default": {
"type": "fillintheblank",
"responses": ["Sorry dude, I'm way too fucking high right now for $blank!!"],
"blank_backup": 'that shit',
},
}

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