diff --git a/nxy/bot.py b/nxy/bot.py index ffc8d89..556bf25 100644 --- a/nxy/bot.py +++ b/nxy/bot.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- +import os import json import sys -import os -# noinspection PyPackageRequirements from dotenv import load_dotenv from irc3 import IrcBot +# This is a development config for use with irc3s server CFG_DEV = { 'nick': 'nxy', 'autojoins': ['#dev'], @@ -23,15 +23,22 @@ CFG_DEV = { } -# TODO: imdb, pay, owe, rape (owe), ddg, regex def main(cfg_file): + # Load dotenv from file load_dotenv('.env') + + # Load config from json file with open(cfg_file, 'r') as fp: cfg = json.load(fp) + + # Apply dev config if env variable is set if bool(os.environ.get('DEV')): cfg.update(CFG_DEV) + # If PASSWORD in env set it in config elif 'PASSWORD' in os.environ: cfg['password'] = os.environ['PASSWORD'] + + # Start the bot with constructed config bot = IrcBot.from_config(cfg) bot.run() diff --git a/nxy/plugins/__init__.py b/nxy/plugins/__init__.py index f9c14a9..9d66139 100644 --- a/nxy/plugins/__init__.py +++ b/nxy/plugins/__init__.py @@ -18,16 +18,14 @@ class Plugin(BasePlugin): return cls(old.bot) -class DatabasePlugin(Plugin): - # @property - # def con(self): - # return self.bot.con - # - # @property - # def cur(self): - # return self.bot.cur +# Import the PgSQL storage plugin +from .storage import Storage - def __init__(self, bot): + +class DatabasePlugin(Plugin): + def __init__(self, bot: IrcBot): super().__init__(bot) - self.con = bot.con.db - self.cur = bot.con.cur + # Get PgSQL storage instance and connection + cursor + self.db = bot.get_plugin(Storage) + self.con = self.db.con + self.cur = self.db.cur diff --git a/nxy/plugins/database.py b/nxy/plugins/database.py deleted file mode 100644 index 1b4a8fb..0000000 --- a/nxy/plugins/database.py +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: utf-8 -*- -import os - -import irc3 -import psycopg2 -from psycopg2.extras import DictCursor - -from . import Plugin - - -@irc3.plugin -class Database(Plugin): - def __init__(self, bot: irc3.IrcBot): - super().__init__(bot) - self.db = psycopg2.connect(os.environ['DATABASE_URI']) - self.cur = self.db.cursor(cursor_factory=DictCursor) - self.bot.con = self diff --git a/nxy/plugins/storage.py b/nxy/plugins/storage.py new file mode 100644 index 0000000..17a958b --- /dev/null +++ b/nxy/plugins/storage.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +import os + +import irc3 +import psycopg2 +from psycopg2.extras import DictCursor + +from . import Plugin + + +@irc3.plugin +class Storage(Plugin): + def __init__(self, bot: irc3.IrcBot): + super().__init__(bot) + # Create database connection + self.con = psycopg2.connect(os.environ['DATABASE_URI']) + # Create database cursor (with dict favtory to access rows by name) + self.cur = self.con.cursor(cursor_factory=DictCursor) diff --git a/nxy/plugins/urban.py b/nxy/plugins/urban.py index 6009bda..bcb818c 100644 --- a/nxy/plugins/urban.py +++ b/nxy/plugins/urban.py @@ -21,21 +21,30 @@ class Urban(Plugin): %%ud ... """ + # Clean, strip and split term by whitespace term = ' '.join(args.get('')).lower().strip().split() if term[-1].isdigit(): - idx = int(term[-1]) - 1 + # Parse number at end as index - 1 and slice term + index = int(term[-1]) - 1 term = ' '.join(term[:-1]) else: - idx = 0 + # Set index to 0 + index = 0 + # Fetch data for term from urban dictionary as json data = requests.get(self.URL, params=dict(term=term)).json() + + # No results if data['result_type'] == 'no_results': return 'Term not found' - res = data['list'][idx] + # Get result by index + res = data['list'][index] + + # Format and return result return '[{idx}/{len}] \x02{word}\x02: {definition} - {example}'.format( - idx=idx + 1, + idx=index + 1, len=len(data['list']), word=res['word'], definition=res['definition'].replace('\r\n', ' '), diff --git a/repl.py b/repl.py index bc0fd8d..4fbd135 100644 --- a/repl.py +++ b/repl.py @@ -1,13 +1,20 @@ # -*- coding: utf-8 -*- -import requests import sys import os import re - from pprint import pprint -# noinspection PyPackageRequirements -from dotenv import load_dotenv +import requests +import psycopg2 +from dotenv import load_dotenv +from psycopg2.extras import DictCursor + +# Handy alias for pprint pp = pprint -load_dotenv('.env') +# Load dotenv from DOTENV_FILE variable (or the default one) +load_dotenv(os.environ.get('DOTENV_FILE', '.env')) + +# Create database connection and cursor +con = psycopg2.connect(os.environ['DATABASE_URI']) +cur = con.cursor(cursor_factory=DictCursor) diff --git a/schema.sql b/schema.sql index a5f3308..ebffb13 100644 --- a/schema.sql +++ b/schema.sql @@ -12,13 +12,13 @@ create table if not exists mcmaniacs ( ); create table if not exists timers ( - id serial primary key, - nick varchar(30) not null, - channel varchar(32) not null, - message text not null, - delay varchar(10) not null, - ends_at timestamp not null, - created_at timestamp not null default current_timestamp + id serial primary key, + mask varchar(255) not null, + target varchar(32) not null, + message text not null, + delay varchar(10) not null, + ends_at timestamp not null, + created_at timestamp not null default current_timestamp ); create table if not exists tells ( @@ -45,3 +45,23 @@ create table if not exists owes ( amount integer not null, unique (nick) ); + + +with ranked_quotes as ( + select + id, + item, + nick, + rank() over (partition by nick order by id), + count(*) over (partition by nick) as total + from + quotes + where + nick = 'mrhanky' +) + +delete from + quotes +where + id = + ranked_quotes; diff --git a/ssl.error b/ssl.error new file mode 100644 index 0000000..5b4e46f --- /dev/null +++ b/ssl.error @@ -0,0 +1,30 @@ +ERROR irc3.mybot [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749) +Traceback (most recent call last): + File "/home/mrhanky/.virtualenvs/irc3/lib/python3.6/site-packages/irc3-1.0.1.dev0-py3.6.egg/irc3/__init__.py", line 161, in connection_made + transport, protocol = f.result() + File "/usr/lib64/python3.6/asyncio/base_events.py", line 802, in create_connection + sock, protocol_factory, ssl, server_hostname) + File "/usr/lib64/python3.6/asyncio/base_events.py", line 828, in _create_connection_transport + yield from waiter + File "/usr/lib64/python3.6/asyncio/sslproto.py", line 503, in data_received + ssldata, appdata = self._sslpipe.feed_ssldata(data) + File "/usr/lib64/python3.6/asyncio/sslproto.py", line 201, in feed_ssldata + self._sslobj.do_handshake() + File "/usr/lib64/python3.6/ssl.py", line 683, in do_handshake + self._sslobj.do_handshake() +ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749) +ERROR irc3.mybot [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:749) +Traceback (most recent call last): + File "/home/mrhanky/.virtualenvs/irc3/lib/python3.6/site-packages/irc3-1.0.1.dev0-py3.6.egg/irc3/__init__.py", line 161, in connection_made + transport, protocol = f.result() + File "/usr/lib64/python3.6/asyncio/base_events.py", line 802, in create_connection + sock, protocol_factory, ssl, server_hostname) + File "/usr/lib64/python3.6/asyncio/base_events.py", line 828, in _create_connection_transport + yield from waiter + File "/usr/lib64/python3.6/asyncio/sslproto.py", line 503, in data_received + ssldata, appdata = self._sslpipe.feed_ssldata(data) + File "/usr/lib64/python3.6/asyncio/sslproto.py", line 201, in feed_ssldata + self._sslobj.do_handshake() + File "/usr/lib64/python3.6/ssl.py", line 683, in do_handshake + self._sslobj.do_handshake() +ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:749)