Restructured to use primitive plugin system.
This commit is contained in:
parent
57dc15532b
commit
4f53833cc2
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
= Code Attribution
|
= Code Attribution
|
||||||
|
|
||||||
== ameliabot.logger
|
== core.logger
|
||||||
`ameliabot.logger` is based on {url-colargulog}[colargulog] by David Ohana under the {url-apache}[Apache-2.0 License]. Changed for `flake8` compliance.
|
`core.logger` is based on {url-colargulog}[colargulog] by David Ohana under the {url-apache}[Apache-2.0 License]. Changed for `flake8` compliance.
|
||||||
|
|
||||||
|
|
||||||
== ameliabot.owncast
|
== core.owncast
|
||||||
`ameliabot.owncast` originally started as {url-hatbot}[hatbot] by {url-hatnix}[hatniX], licensed under the {url-unlicense}[Unlicense], which this project also uses.
|
`core.owncast` originally started as {url-hatbot}[hatbot] by {url-hatnix}[hatniX], licensed under the {url-unlicense}[Unlicense], which this project also uses.
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
from datetime import datetime, timezone
|
|
||||||
import random
|
|
||||||
import sqlite3
|
|
||||||
from ameliabot.logger import logging
|
|
||||||
|
|
||||||
|
|
||||||
class Quote:
|
|
||||||
def __init__(self):
|
|
||||||
self.__init_table()
|
|
||||||
self.num_quotes = self._get_num_quotes()
|
|
||||||
logging.info("Quote subsystem online")
|
|
||||||
|
|
||||||
def insert(self, owner, submitter, text):
|
|
||||||
conn = self.__connect()
|
|
||||||
text = text.replace("'", "''")
|
|
||||||
conn.execute('''
|
|
||||||
INSERT INTO quotes (submitter, text, timestamp)
|
|
||||||
VALUES ('{}', '{}', {})'''.format(
|
|
||||||
submitter, text, datetime.now().replace(tzinfo=timezone.utc)))
|
|
||||||
self.num_quotes += 1
|
|
||||||
logging.debug("Quote number %s inserted" % self.num_quotes)
|
|
||||||
|
|
||||||
def get(self, arg=None):
|
|
||||||
conn = self.__connect()
|
|
||||||
if arg:
|
|
||||||
ret = "SELECT id, text, timestamp FROM quotes WHERE "
|
|
||||||
try:
|
|
||||||
if int(arg) > self.num_quotes:
|
|
||||||
return "No quote matching that number."
|
|
||||||
ret += "id = %s" % arg
|
|
||||||
except ValueError:
|
|
||||||
ret += "text like '%{}%'".format(arg.lower())
|
|
||||||
|
|
||||||
quote = conn.execute(ret)
|
|
||||||
return self._format(list(quote.fetchone()))
|
|
||||||
else:
|
|
||||||
return self.get(random.randint(0, self.num_quotes))
|
|
||||||
|
|
||||||
def _get_num_quotes(self):
|
|
||||||
conn = self.__connect()
|
|
||||||
try:
|
|
||||||
num = conn.execute("SELECT COUNT(id) FROM quotes")
|
|
||||||
except sqlite3.OperationalError:
|
|
||||||
return 0
|
|
||||||
return int(num.fetchone()[0])
|
|
||||||
|
|
||||||
def _format(self, quote):
|
|
||||||
num, text, timestamp = quote
|
|
||||||
timestamp = datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S.%f%z')
|
|
||||||
return "{}. {}, {}".format(
|
|
||||||
num, text, datetime.strftime(timestamp, '%Y'))
|
|
||||||
|
|
||||||
def __connect(self):
|
|
||||||
return sqlite3.connect("data/quote.db")
|
|
||||||
|
|
||||||
def __init_table(self):
|
|
||||||
try:
|
|
||||||
conn = self.__connect()
|
|
||||||
except sqlite3.OperationalError:
|
|
||||||
import os
|
|
||||||
os.makedirs("data")
|
|
||||||
self.__init_table()
|
|
||||||
|
|
||||||
conn.execute('''
|
|
||||||
CREATE TABLE IF NOT EXISTS quotes (
|
|
||||||
id INTEGER PRIMARY KEY, submitter TEXT,
|
|
||||||
text TEXT, timestamp TEXT
|
|
||||||
)''')
|
|
4
bot.py
4
bot.py
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
from flask import Flask, Response
|
from flask import Flask, Response
|
||||||
from ameliabot import owncast, __version__
|
from core import owncast, __version__
|
||||||
from ameliabot.logger import logging
|
from core.logger import logging
|
||||||
|
|
||||||
|
|
||||||
logging.info("Loaded %s, running ameliabot v%s)" % (
|
logging.info("Loaded %s, running ameliabot v%s)" % (
|
||||||
|
|
|
@ -6,11 +6,14 @@
|
||||||
!save = {sender} is reminding {botowner} to _**SAVE NOW**_!
|
!save = {sender} is reminding {botowner} to _**SAVE NOW**_!
|
||||||
!slap = *slaps {target} with a large trout!*
|
!slap = *slaps {target} with a large trout!*
|
||||||
!version = I am running ameliabot {bot_version}
|
!version = I am running ameliabot {bot_version}
|
||||||
|
!dadjoke = {plugins.dadjoke}
|
||||||
[commands.quote]
|
!quote = {plugins.quote}
|
||||||
!quote = {quote}
|
|
||||||
!addquote = {quote_parameters}
|
!addquote = {quote_parameters}
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
dadjoke = Enabled
|
||||||
|
quote = Enabled
|
||||||
|
|
||||||
[aliases]
|
[aliases]
|
||||||
help = commands
|
help = commands
|
||||||
bot = version
|
bot = version
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
import sys
|
import sys
|
||||||
from ameliabot.logger import ColorizedArgsFormatter, BraceFormatStyleFormatter
|
from core.logger import ColorizedArgsFormatter, BraceFormatStyleFormatter
|
||||||
from ameliabot.logger import logging
|
from core.logger import logging
|
||||||
|
|
||||||
|
|
||||||
__version__ = "0.1.0"
|
__version__ = "0.1.0"
|
||||||
|
@ -46,10 +46,6 @@ cmd_file = ConfigParser()
|
||||||
try:
|
try:
|
||||||
cmd_file.read("commands.ini")
|
cmd_file.read("commands.ini")
|
||||||
commands = cmd_file["commands"]
|
commands = cmd_file["commands"]
|
||||||
if config["quotes"]["Enabled"]:
|
|
||||||
# Perhaps configparser handles this and I haven't figured it out
|
|
||||||
for cmd in cmd_file["commands.quote"]:
|
|
||||||
commands[cmd] = cmd_file["commands.quote"][cmd]
|
|
||||||
logging.info("Commands loaded")
|
logging.info("Commands loaded")
|
||||||
|
|
||||||
aliases = cmd_file["aliases"]
|
aliases = cmd_file["aliases"]
|
|
@ -1,14 +1,22 @@
|
||||||
|
import importlib
|
||||||
|
import os
|
||||||
import random
|
import random
|
||||||
import requests
|
import requests
|
||||||
from requests.structures import CaseInsensitiveDict
|
from requests.structures import CaseInsensitiveDict
|
||||||
from ameliabot import __version__, config, aliases, commands
|
import sys
|
||||||
from ameliabot.logger import logging
|
from core import __version__, config, aliases, commands
|
||||||
|
from core.logger import logging
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
# Make quote system and dependencies optional
|
|
||||||
if config["quotes"]["Enabled"]:
|
# This is gross and needs to be replaced
|
||||||
from ameliabot.quote import Quote
|
plugin_path = "%s/../plugins" % os.path.dirname(os.path.realpath(__file__))
|
||||||
quote = Quote()
|
sys.path.append(plugin_path)
|
||||||
|
modules = os.listdir(plugin_path)
|
||||||
|
|
||||||
|
for module in modules:
|
||||||
|
if module.endswith(".py") and not module.startswith("__"):
|
||||||
|
globals()[module[:-3]] = importlib.import_module(module[:-3])
|
||||||
|
|
||||||
# prepare the header for the bot posts
|
# prepare the header for the bot posts
|
||||||
headers = CaseInsensitiveDict()
|
headers = CaseInsensitiveDict()
|
||||||
|
@ -59,17 +67,22 @@ def get_quote(num):
|
||||||
pass
|
pass
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
return quote.get(num)
|
return quote.get(num) # NOQA should work even if linter complains
|
||||||
|
|
||||||
|
|
||||||
def process_chat(data):
|
def process_chat(data):
|
||||||
sender = data["user"]["displayName"]
|
sender = data["user"]["displayName"]
|
||||||
text = data["body"]
|
text = data["body"]
|
||||||
command_reply = get_command(text)
|
command_reply = get_command(text)
|
||||||
|
|
||||||
logging.info("<{}> {}".format(sender, text))
|
logging.info("<{}> {}".format(sender, text))
|
||||||
|
|
||||||
if command_reply:
|
if command_reply:
|
||||||
|
logging.debug("Command found")
|
||||||
|
if command_reply.startswith("{plugins."):
|
||||||
|
plugin = command_reply[1:-1].split(".")
|
||||||
|
logging.debug("Attempting to run plugin: %s" % plugin[1])
|
||||||
|
reply = globals()[plugin[1]].run()
|
||||||
|
return reply
|
||||||
try:
|
try:
|
||||||
first_parameter = text.split(" ")[1]
|
first_parameter = text.split(" ")[1]
|
||||||
except IndexError:
|
except IndexError:
|
|
@ -0,0 +1,27 @@
|
||||||
|
from urllib import request
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
def get_joke():
|
||||||
|
url = "https://icanhazdadjoke.com"
|
||||||
|
try:
|
||||||
|
with request.urlopen(create_request(url)) as response:
|
||||||
|
joke = json.loads(response.read())
|
||||||
|
if joke["status"] == 200:
|
||||||
|
return joke["joke"]
|
||||||
|
except (request.URLError, request.HTTPError):
|
||||||
|
return "No dad joke right now."
|
||||||
|
|
||||||
|
|
||||||
|
def create_request(url):
|
||||||
|
headers = {
|
||||||
|
"Accept": "application/json",
|
||||||
|
"User-Agent": "ameliabot (https://criminallycute.fi/ameliabot)"
|
||||||
|
}
|
||||||
|
return request.Request(
|
||||||
|
url, data=None, headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
return get_joke()
|
|
@ -0,0 +1,73 @@
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
import random
|
||||||
|
import sqlite3
|
||||||
|
"""
|
||||||
|
This is a really, really rough plugin and needs to be redone.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def insert(owner, submitter, text):
|
||||||
|
conn = __connect()
|
||||||
|
text = text.replace("'", "''")
|
||||||
|
conn.execute('''
|
||||||
|
INSERT INTO quotes (submitter, text, timestamp)
|
||||||
|
VALUES ('{}', '{}', {})'''.format(
|
||||||
|
submitter, text, datetime.now().replace(tzinfo=timezone.utc)))
|
||||||
|
|
||||||
|
|
||||||
|
def get(arg=None):
|
||||||
|
conn = __connect()
|
||||||
|
num_quotes = __get_num_quotes()
|
||||||
|
if arg:
|
||||||
|
ret = "SELECT id, text, timestamp FROM quotes WHERE "
|
||||||
|
try:
|
||||||
|
if int(arg) > num_quotes:
|
||||||
|
return "No quote matching that number."
|
||||||
|
ret += "id = %s" % arg
|
||||||
|
except ValueError:
|
||||||
|
ret += "text like '%{}%'".format(arg.lower())
|
||||||
|
|
||||||
|
quote = conn.execute(ret)
|
||||||
|
return __format(list(quote.fetchone()))
|
||||||
|
else:
|
||||||
|
return get(random.randint(0, num_quotes))
|
||||||
|
|
||||||
|
|
||||||
|
def __get_num_quotes():
|
||||||
|
conn = __connect()
|
||||||
|
try:
|
||||||
|
num = conn.execute("SELECT COUNT(id) FROM quotes")
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
return 0
|
||||||
|
return int(num.fetchone()[0])
|
||||||
|
|
||||||
|
|
||||||
|
def __format(quote):
|
||||||
|
num, text, timestamp = quote
|
||||||
|
timestamp = datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S.%f%z')
|
||||||
|
return "{}. {}, {}".format(
|
||||||
|
num, text, datetime.strftime(timestamp, '%Y'))
|
||||||
|
|
||||||
|
|
||||||
|
def __connect():
|
||||||
|
return sqlite3.connect("data/quote.db")
|
||||||
|
|
||||||
|
|
||||||
|
def __init_table():
|
||||||
|
try:
|
||||||
|
conn = __connect()
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
import os
|
||||||
|
os.makedirs("data")
|
||||||
|
__init_table()
|
||||||
|
|
||||||
|
conn.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS quotes (
|
||||||
|
id INTEGER PRIMARY KEY, submitter TEXT,
|
||||||
|
text TEXT, timestamp TEXT
|
||||||
|
)''')
|
||||||
|
|
||||||
|
|
||||||
|
def run(arg=None):
|
||||||
|
__init_table()
|
||||||
|
return get(arg)
|
Loading…
Reference in New Issue