Restructured to use primitive plugin system.

This commit is contained in:
Siina Mashek 2022-04-27 11:24:45 +03:00
parent 57dc15532b
commit 4f53833cc2
9 changed files with 135 additions and 91 deletions

View file

@ -6,9 +6,9 @@
= Code Attribution
== ameliabot.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
`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
`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
`core.owncast` originally started as {url-hatbot}[hatbot] by {url-hatnix}[hatniX], licensed under the {url-unlicense}[Unlicense], which this project also uses.

View file

@ -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
View file

@ -1,7 +1,7 @@
#!/usr/bin/env python
from flask import Flask, Response
from ameliabot import owncast, __version__
from ameliabot.logger import logging
from core import owncast, __version__
from core.logger import logging
logging.info("Loaded %s, running ameliabot v%s)" % (

View file

@ -6,11 +6,14 @@
!save = {sender} is reminding {botowner} to _**SAVE NOW**_!
!slap = *slaps {target} with a large trout!*
!version = I am running ameliabot {bot_version}
[commands.quote]
!quote = {quote}
!dadjoke = {plugins.dadjoke}
!quote = {plugins.quote}
!addquote = {quote_parameters}
[plugins]
dadjoke = Enabled
quote = Enabled
[aliases]
help = commands
bot = version

View file

@ -1,7 +1,7 @@
from configparser import ConfigParser
import sys
from ameliabot.logger import ColorizedArgsFormatter, BraceFormatStyleFormatter
from ameliabot.logger import logging
from core.logger import ColorizedArgsFormatter, BraceFormatStyleFormatter
from core.logger import logging
__version__ = "0.1.0"
@ -46,10 +46,6 @@ cmd_file = ConfigParser()
try:
cmd_file.read("commands.ini")
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")
aliases = cmd_file["aliases"]

View file

@ -1,14 +1,22 @@
import importlib
import os
import random
import requests
from requests.structures import CaseInsensitiveDict
from ameliabot import __version__, config, aliases, commands
from ameliabot.logger import logging
import sys
from core import __version__, config, aliases, commands
from core.logger import logging
from flask import request
# Make quote system and dependencies optional
if config["quotes"]["Enabled"]:
from ameliabot.quote import Quote
quote = Quote()
# This is gross and needs to be replaced
plugin_path = "%s/../plugins" % os.path.dirname(os.path.realpath(__file__))
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
headers = CaseInsensitiveDict()
@ -59,17 +67,22 @@ def get_quote(num):
pass
except ValueError:
pass
return quote.get(num)
return quote.get(num) # NOQA should work even if linter complains
def process_chat(data):
sender = data["user"]["displayName"]
text = data["body"]
command_reply = get_command(text)
logging.info("<{}> {}".format(sender, text))
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:
first_parameter = text.split(" ")[1]
except IndexError:

27
plugins/dadjoke.py Normal file
View file

@ -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()

73
plugins/quote.py Normal file
View file

@ -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)