Lots of stuff

This commit is contained in:
mrhanky 2017-05-16 07:45:10 +02:00
parent 5d46afa2da
commit cb8011aa67
No known key found for this signature in database
GPG Key ID: 67D772C481CB41B8
12 changed files with 113 additions and 64 deletions

View File

@ -5,7 +5,7 @@
"ssl": true, "ssl": true,
"raw": true, "raw": true,
"autojoins": ["#nxy-dev"], "autojoins": ["#nxy-dev"],
"storage": "json://data/db.json", "storage": "sqlite://data/nxy.db",
"flood_burst": 1, "flood_burst": 1,
"flood_rate": 4, "flood_rate": 4,
"flood_rate_delay": 1, "flood_rate_delay": 1,
@ -13,11 +13,11 @@
"irc3.plugins.async", "irc3.plugins.async",
"irc3.plugins.cron", "irc3.plugins.cron",
"irc3.plugins.command", "irc3.plugins.command",
"irc3.plugins.storage",
"irc3.plugins.uptime", "irc3.plugins.uptime",
"nxy.plugins.admin", "nxy.plugins.admin",
"nxy.plugins.bitcoin", "nxy.plugins.bitcoin",
"nxy.plugins.ctcp", "nxy.plugins.ctcp",
"nxy.plugins.database",
"nxy.plugins.mcmaniac", "nxy.plugins.mcmaniac",
"nxy.plugins.quotes", "nxy.plugins.quotes",
"nxy.plugins.reminder", "nxy.plugins.reminder",
@ -28,8 +28,9 @@
"guard": "irc3.plugins.command.mask_based_policy" "guard": "irc3.plugins.command.mask_based_policy"
}, },
"irc3.plugins.command.masks": { "irc3.plugins.command.masks": {
"*!ceo@cocaine-import.agency": "all_permissions", "mrhanky!mrhanky@cocaine-import.agency": "all_permissions",
"*!ceo@unterschicht.tv": "all_permissions", "jkhsjdhjs!jkhsjdhjs@smoke.weed.everyday": "admin",
"sirx!sirx@n0xy.net": "admin",
"*": "view" "*": "view"
} }
} }

View File

@ -37,8 +37,6 @@ def main(cfg_file):
if not os.path.exists(data): if not os.path.exists(data):
os.makedirs(data) os.makedirs(data)
bot = IrcBot.from_config(cfg) bot = IrcBot.from_config(cfg)
if bool(os.environ.get('DEV')):
bot.con = sqlite3.connect('nxy.db')
bot.run() bot.run()

View File

@ -17,16 +17,7 @@ class Plugin(BasePlugin):
class DatabasePlugin(Plugin): class DatabasePlugin(Plugin):
def __init__(self, bot: IrcBot): def __init__(self, bot):
super().__init__(bot) super().__init__(bot)
# noinspection PyUnresolvedReferences self.con = bot.con.db
self._db = bot.db self.cur = self.con.cursor()
self.prepare_db()
@property
def db(self):
return self._db[self]
def prepare_db(self):
if self not in self._db:
self._db[self] = {}

View File

@ -3,6 +3,7 @@ from docopt import Dict as DocoptDict
from irc3 import IrcBot from irc3 import IrcBot
from irc3.utils import IrcString from irc3.utils import IrcString
from irc3.plugins.command import command from irc3.plugins.command import command
import irc3
from . import MODULE, Plugin from . import MODULE, Plugin
@ -18,5 +19,6 @@ def reload(bot: IrcBot, mask: IrcString, channel: IrcString, args: DocoptDict):
bot.notice(mask.nick, 'Reloaded plugin "{plugin}"'.format(plugin=plugin)) bot.notice(mask.nick, 'Reloaded plugin "{plugin}"'.format(plugin=plugin))
@irc3.plugin
class Admin(Plugin): class Admin(Plugin):
pass pass

View File

@ -2,12 +2,14 @@
from docopt import Dict as DocOptDict from docopt import Dict as DocOptDict
from irc3.plugins.command import command from irc3.plugins.command import command
from irc3.utils import IrcString from irc3.utils import IrcString
import irc3
from . import Plugin from . import Plugin
from ..utils import fmt, req from ..utils import fmt, req
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
@irc3.plugin
class Bitcoin(Plugin): class Bitcoin(Plugin):
requires = [ requires = [
'irc3.plugins.command', 'irc3.plugins.command',

View File

@ -3,12 +3,14 @@ from docopt import Dict as DocOptDict
from irc3.plugins.command import command from irc3.plugins.command import command
from irc3.utils import IrcString from irc3.utils import IrcString
import time import time
import irc3
from . import Plugin from . import Plugin
from ..utils import fmt from ..utils import fmt
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
@irc3.plugin
class CTCP(Plugin): class CTCP(Plugin):
TIMEOUT = 5 TIMEOUT = 5

18
nxy/plugins/database.py Normal file
View File

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
import sqlite3
import irc3
from . import Plugin
@irc3.plugin
class Database(Plugin):
def __init__(self, bot):
super().__init__(bot)
file = bot.config.storage.split('sqlite://', 1)[1]
if not file:
raise ValueError('Invalid database: {}'.format(bot.config.storage))
self.db = sqlite3.connect(file)
self.db.row_factory = sqlite3.Row
self.bot = bot
self.bot.con = self

View File

@ -1,24 +1,18 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from docopt import Dict as DocOptDict from docopt import Dict as DocOptDict
from irc3.utils import IrcString from irc3.utils import IrcString
from irc3.plugins.command import command from irc3.plugins.command import command, Commands
import random
import irc3
from . import DatabasePlugin from . import DatabasePlugin
from ..utils import parse_int from ..utils import parse_int
@irc3.plugin
class McManiac(DatabasePlugin): class McManiac(DatabasePlugin):
requires = [ requires = [
'irc3.plugins.command', 'irc3.plugins.command',
'nxy.plugins.database',
] ]
@property
def items(self):
return self.db['items']
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
@command(options_first=True) @command(options_first=True)
def mcmaniac(self, mask: IrcString, channel: IrcString, args: DocOptDict): def mcmaniac(self, mask: IrcString, channel: IrcString, args: DocOptDict):
@ -27,33 +21,43 @@ class McManiac(DatabasePlugin):
%%mcmaniac [<index>] %%mcmaniac [<index>]
""" """
cmd = args.get('<cmd>') cmd = args.get('<cmd>')
mcmaniac = args.get('<mcmaniac>') item = args.get('<mcmaniac>')
index = args.get('<index>') guard = self.bot.get_plugin(Commands).guard
if cmd and mcmaniac: if cmd and item:
if cmd == 'add': if guard.has_permission(mask, 'admin'):
if mcmaniac not in self.items: if cmd == 'add':
self.items.append(mcmaniac) self.cur.execute('insert into mcmaniac (item) values (?)',
if cmd == 'del': [item])
try: if cmd == 'del':
self.items.pop(parse_int(mcmaniac)) order, index, op = parse_int(item, select=False)
except (IndexError, TypeError): if not index:
return return
self._db.SIGINT() self.cur.execute('''delete from mcmaniac where id =
elif self.items: (select id from mcmaniac a where ? = (select count(id)
if index: from mcmaniac b where a.id {op} b.id) order by id {order})
try: '''.format(op=op, order=order), [index])
mcmaniac = self.items[parse_int(index)] self.con.commit()
except (IndexError, TypeError):
return
else: else:
mcmaniac = random.choice(self.items) self.bot.notice(mask.nick, 'Permission denied')
return '[{index}/{total}] {item}'.format( else:
index=self.items.index(mcmaniac) + 1, index = args.get('<index>')
total=len(self.items), if index:
item=mcmaniac index = parse_int(index)
) if not index:
return
def prepare_db(self): order, index, _ = index
super().prepare_db() order = 'id {order}'.format(order=order)
self._db.setdefault(self, items=[]) extra = 'offset ?'
self._db.SIGINT() binds = [index]
else:
order = 'random()'
extra = ''
binds = []
self.cur.execute('''select item,
(select count(id) from mcmaniac b where a.id >= b.id) as idx,
(select count(id) from mcmaniac) as len
from mcmaniac a order by {order} limit 1 {extra}
'''.format(order=order, extra=extra), binds)
item = self.cur.fetchone()
if item:
return '[{idx}/{len}] {item}'.format(**item)

View File

@ -17,11 +17,10 @@ class Quotes(DatabasePlugin):
] ]
REGEX = re.compile(r'<?[~&@%+]?([a-zA-Z0-9_\-^`|\\\[\]{}]+)>?') REGEX = re.compile(r'<?[~&@%+]?([a-zA-Z0-9_\-^`|\\\[\]{}]+)>?')
RESPONSE = '[{index}/{total}] <{nick}> {quote}'
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
@command(options_first=True) @command(options_first=True)
def q(self, mask: IrcString, channel: IrcString, args: DocOptDict): def q(self, mask: IrcString, channel: IrcString, args: DocOptDict) -> str:
""" """
Manage quotes. Manage quotes.
%%q <cmd> <nick> <quote>... %%q <cmd> <nick> <quote>...
@ -44,19 +43,19 @@ class Quotes(DatabasePlugin):
if not self.db[nick]: if not self.db[nick]:
del self.db[nick] del self.db[nick]
except (KeyError, IndexError, TypeError): except (KeyError, IndexError, TypeError):
return return ''
self._db.SIGINT() self._db.SIGINT()
else: else:
if quote: if quote:
try: try:
quote = self.db[nick][parse_int(quote)] quote = self.db[nick][parse_int(quote)]
except (KeyError, IndexError, TypeError): except (KeyError, IndexError, TypeError):
return return ''
else: else:
quote = random.choice(self.db[nick]) quote = random.choice(self.db[nick])
self.bot.privmsg(channel, self.RESPONSE.format( return '[{index}/{total}] <{nick}> {quote}'.format(
index=self.db[nick].index(quote) + 1, index=self.db[nick].index(quote) + 1,
total=len(self.db[nick]), total=len(self.db[nick]),
nick=nick, nick=nick,
quote=quote, quote=quote,
)) )

View File

@ -4,6 +4,7 @@ from irc3.plugins.command import command
from irc3.utils import IrcString from irc3.utils import IrcString
from irc3.dec import event from irc3.dec import event
import random import random
import irc3
from . import Plugin from . import Plugin
from ..utils import fmt from ..utils import fmt
@ -16,11 +17,12 @@ GNU_LINUX = """I'd Just Like To Interject For A Moment. What you're referring
to as Linux, is in fact, GNU/Linux, or as I've recently taken to calling it, to as Linux, is in fact, GNU/Linux, or as I've recently taken to calling it,
GNU plus Linux. Linux is not an operating system unto itself, but rather GNU plus Linux. Linux is not an operating system unto itself, but rather
another free component of a fully functioning GNU system made useful by the another free component of a fully functioning GNU system made useful by the
GNU corelibs, shell utilities and vital system components comprising a full OS GNU corelibs, shell utilities and vital system components comprising a full
as defined by POSIX.""" OS as defined by POSIX."""
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
@irc3.plugin
class Useless(Plugin): class Useless(Plugin):
requires = [ requires = [
'irc3.plugins.command', 'irc3.plugins.command',

View File

@ -83,7 +83,25 @@ def time_to_sec(text: str) -> int:
return num * 52 * 604800 return num * 52 * 604800
def parse_int(val: list) -> int: def parse_int(val: str, select: bool = True) -> tuple:
try:
val = int(val)
if val is not 0:
if val < 1:
order = 'desc'
val *= -1
op = '<='
else:
order = 'asc'
op = '>='
if select:
val -= 1
return order, val, op
except ValueError:
pass
def _parse_int(val: list) -> int:
""" """
Parses an int from list, decremts by -1 if positiv. Parses an int from list, decremts by -1 if positiv.
Only returns if value from list is not 0. Only returns if value from list is not 0.

12
schema.sql Normal file
View File

@ -0,0 +1,12 @@
create table if not exists quotes (
id integer primary key autoincrement,
nick text not null,
value text not null,
unique (nick, value collate nocase)
);
create table if not exists mcmaniac (
id integer primary key autoincrement,
item text not null,
unique (item collate nocase) on conflict replace
);