Moved from postgres to sqlite for portability and dependency reduction

This commit is contained in:
Siina Mashek 2022-04-24 02:48:43 +03:00
parent 57e36dd7cb
commit eda71bd725
8 changed files with 83 additions and 85 deletions

1
.gitignore vendored
View file

@ -1,6 +1,7 @@
# Project specific
*.kate-swp
*.log
data/
config/owncast.json
# ---> Python

View file

@ -8,13 +8,11 @@ Code attributions can be found in `ATTRIBUTIONS.md`
* [Owncast][] server
* Python 3
* Flask
* psycopg2
## Setup
* Install Flask and (optionally for the quote system) psycopg2
* `pip --user install Flask`
* If you don't want to fiddle with psycopg2, you can install `python-psycopg2` from your distribution's package manager
* Create an Owncast webhook url pointing to your bot's location
* http://localhost:5000/webhook/owncast if bot and owncast are on the same machine
* Copy `config-example.json` to `config.json` and fill out the information required

44
ameliabot/__init__.py Normal file
View file

@ -0,0 +1,44 @@
import json
import sys
from ameliabot.logger import ColorizedArgsFormatter, BraceFormatStyleFormatter
from ameliabot.logger import logging
__version__ = "0.0.1"
# Set up logging
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
console_level = "DEBUG"
console_handler = logging.StreamHandler(stream=sys.stdout)
console_handler.setLevel(console_level)
console_format = "%(asctime)s - %(levelname)-8s - %(name)-25s - %(message)s" # NOQA
colored_formatter = ColorizedArgsFormatter(console_format)
console_handler.setFormatter(colored_formatter)
root_logger.addHandler(console_handler)
file_handler = logging.FileHandler("app.log")
file_level = "DEBUG"
file_handler.setLevel(file_level)
file_format = "%(asctime)s - %(name)s (%(lineno)s) - %(levelname)-8s - %(threadName)-12s - %(message)s" # NOQA
file_handler.setFormatter(BraceFormatStyleFormatter(file_format))
root_logger.addHandler(file_handler)
# Get basic owncast bot config
try:
with open("config/owncast.json", "r") as f:
config = json.load(f)
logging.info("Configuration loaded")
except FileNotFoundError:
logging.error("Configuration file not found.")
logging.error("Please see README.md for more information.")
raise SystemExit
with open("commands.json", "r") as f:
commands = json.load(f)
logging.info("Commands loaded")
with open("alias.json", "r") as f:
aliases = json.load(f)
logging.info("Aliases loaded")

View file

@ -1,30 +0,0 @@
"""
colargulog
Python3 Logging with Colored Arguments and new string formatting style
Written by david.ohana@ibm.com
License: Apache-2.0
"""
import sys
from ameliabot.logger import ColorizedArgsFormatter, BraceFormatStyleFormatter
from ameliabot.logger import logging
def init_logging():
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
console_level = "DEBUG"
console_handler = logging.StreamHandler(stream=sys.stdout)
console_handler.setLevel(console_level)
console_format = "%(asctime)s - %(levelname)-8s - %(name)-25s - %(message)s" # NOQA
colored_formatter = ColorizedArgsFormatter(console_format)
console_handler.setFormatter(colored_formatter)
root_logger.addHandler(console_handler)
file_handler = logging.FileHandler("app.log")
file_level = "DEBUG"
file_handler.setLevel(file_level)
file_format = "%(asctime)s - %(name)s (%(lineno)s) - %(levelname)-8s - %(threadName)-12s - %(message)s" # NOQA
file_handler.setFormatter(BraceFormatStyleFormatter(file_format))
root_logger.addHandler(file_handler)

View file

@ -1,41 +1,15 @@
import html
import json
import random
import requests
from requests.structures import CaseInsensitiveDict
from ameliabot.init_logging import init_logging
from ameliabot import __version__, config, aliases, commands
from ameliabot.logger import logging
from flask import request
init_logging()
bot_version = "0.0.1"
# Get basic owncast bot config
try:
with open("config/owncast.json", "r") as f:
config = json.load(f)
logging.info("Configuration loaded")
except FileNotFoundError:
logging.error("Configuration file not found.")
logging.error("Please see README.md for more information.")
raise SystemExit
# Make quote system and dependencies optional
if config["quote_enabled"]:
from ameliabot.quote import Quote
quote = Quote(
database=config["quote_db_name"],
user=config["quote_db_user"],
password=config["quote_db_pass"],
)
with open("commands.json", "r") as f:
commands = json.load(f)
logging.info("Commands loaded")
with open("alias.json", "r") as f:
aliases = json.load(f)
logging.info("Aliases loaded")
quote = Quote()
# prepare the header for the bot posts
headers = CaseInsensitiveDict()
@ -112,7 +86,7 @@ def process_chat(data):
"random": str(random.randrange(1, 100, 1)),
"commands": ", ".join(list(commands.keys())),
"aliases": ", ".join(list(aliases.keys())),
"bot_version": bot_version,
"bot_version": __version__,
"quote": get_quote(first_parameter),
"quote_parameters": "Not implemented yet",
}

View file

@ -1,32 +1,25 @@
from datetime import datetime
import random
import sqlite3
from ameliabot.logger import logging
try:
import psycopg2
except ModuleNotFoundError:
logging.error("Please install psycopg2.")
logging.error("Please see README.md for more information.")
raise SystemExit
class Quote:
def __init__(self, database, user, password):
self.conn = psycopg2.connect(
database=database, user=user, password=password)
def __init__(self):
# TODO: Generalise the db connection so that other parts can use it
self.conn = ""
self.__init_table()
self.num_quotes = self._get_num_quotes()
logging.info("Quote subsystem online")
def insert(self, owner, submitter, text):
cur = self.conn.cursor()
text = text.replace("'", "''")
cur.execute('''
INSERT INTO quotes (owner, submitter, text, timestamp)
VALUES ('{}', '{}', E'{}', current_timestamp)'''.format(
owner, submitter, text))
self.conn.commit()
cur.close()
self.conn.execute('''
INSERT INTO quotes (submitter, text, timestamp)
VALUES ('{}', E'{}', {})'''.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):
if arg:
@ -50,7 +43,10 @@ class Quote:
def _get_num_quotes(self):
cur = self.conn.cursor()
cur.execute("SELECT COUNT(id) FROM quotes")
try:
cur.execute("SELECT COUNT(id) FROM quotes")
except sqlite3.OperationalError:
return 0
return cur.fetchone()[0]
def _format(self, quotes):
@ -63,3 +59,20 @@ class Quote:
return "No quote."
return "{}. {}, {}".format(
data[0], data[1], datetime.strftime(data[2], '%Y'))
def __connect(self):
self.conn = sqlite3.connect("data/quote.db")
def __init_table(self):
try:
self.__connect()
except sqlite3.OperationalError:
import os
os.makedirs("data")
self.__connect()
self.conn.execute('''
CREATE TABLE IF NOT EXISTS quotes (
id INTEGER PRIMARY KEY, submitter TEXT,
text TEXT, timestamp TEXT
)''')

4
bot.py
View file

@ -1,10 +1,10 @@
#!/usr/bin/env python
from flask import Flask, Response
from ameliabot import owncast
from ameliabot import owncast, __version__
from ameliabot.logger import logging
logging.info("Loaded ameliabot v%s" % owncast.bot_version)
logging.info("Loaded %s v%s" % (owncast.config["bot_name"], __version__))
# the url of the Owncast API for bot posts
owncast_url = "{}/api/integrations/chat/send".format(

View file

@ -1,9 +1,7 @@
{
"owncast_server": "localhost",
"access_token": "",
"bot_name": "ameliabot",
"streamer_name": "owncast streamer",
"quote_enabled": false,
"quote_db_name": "",
"quote_db_user": "",
"quote_db_pass": ""
}