Huge cleanup and refactoring :>
This commit is contained in:
parent
7f5571fc09
commit
f33a17038a
@ -1,4 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
|
||||
REPO_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
import irc3
|
||||
from dotenv import load_dotenv
|
||||
|
||||
MODULE = __name__
|
||||
|
||||
|
||||
# TODO: ddg
|
||||
class Bot(irc3.IrcBot):
|
||||
DEV = 'BOT_DEV' in os.environ
|
||||
REPO_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
CONFIG_DIR = REPO_DIR if DEV else os.path.dirname(REPO_DIR)
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, cfg_file: str = 'config.json', env_file: str = '.env'):
|
||||
cfg_file = os.path.join(cls.CONFIG_DIR, cfg_file)
|
||||
env_file = os.path.join(cls.CONFIG_DIR, env_file)
|
||||
|
||||
load_dotenv('.env')
|
||||
|
||||
with open(cfg_file, 'r') as fp:
|
||||
conf = json.load(fp)
|
||||
|
||||
return cls.from_config(conf)
|
||||
|
||||
|
||||
@irc3.plugin
|
||||
class BasePlugin:
|
||||
requires = ['irc3.plugins.command']
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
self.bot = bot
|
||||
self.log = logging.getLogger('irc3.{}'.format(self.__class__.__name__.lower()))
|
||||
|
||||
|
||||
class Plugin(BasePlugin):
|
||||
@classmethod
|
||||
def reload(cls, old: BasePlugin):
|
||||
return cls(old.bot)
|
||||
|
||||
|
||||
from .storage import Storage # noqa
|
||||
|
||||
|
||||
class DatabasePlugin(Plugin):
|
||||
requires = Plugin.requires + ['bot.storage']
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
self.db = bot.get_plugin(Storage)
|
||||
self.con = self.db.con
|
||||
self.cur = self.db.cur
|
||||
|
@ -1,51 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
|
||||
# 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'],
|
||||
'host': 'localhost',
|
||||
'port': 6667,
|
||||
'ssl': False,
|
||||
'raw': True,
|
||||
'debug': True,
|
||||
'verbose': True,
|
||||
'irc3.plugins.command.masks': {
|
||||
'*!admin@127.0.0.1': 'all_permissions',
|
||||
'*': 'view',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# TODO: ddg
|
||||
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
|
||||
if 'PASSWORD' in os.environ:
|
||||
cfg['password'] = os.environ['PASSWORD']
|
||||
|
||||
# Start the bot with constructed config
|
||||
bot = IrcBot.from_config(cfg)
|
||||
|
||||
bot.run()
|
||||
bot.mode(bot.nick, '+R')
|
||||
|
||||
from bot import Bot
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1])
|
||||
bot = Bot.from_json(*sys.argv[1:])
|
||||
bot.run()
|
||||
|
@ -7,14 +7,13 @@ from docopt import Dict
|
||||
from irc3.plugins.command import command
|
||||
from irc3.utils import IrcString
|
||||
|
||||
from . import MODULE, Plugin
|
||||
from .. import REPO_DIR
|
||||
from . import MODULE, Bot, Plugin
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@command(permission='admin', show_in_help_list=False)
|
||||
def reload(bot: irc3.IrcBot, mask: IrcString, target: IrcString, args: Dict):
|
||||
def reload(bot: Bot, mask: IrcString, target: IrcString, args: Dict):
|
||||
"""Reloads a plugin or the whole bot.
|
||||
|
||||
%%reload [<plugin>]
|
||||
@ -34,9 +33,9 @@ def connected(bot, srv, me, data):
|
||||
|
||||
|
||||
class Admin(Plugin):
|
||||
def __init__(self, bot: irc3.IrcBot):
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
self.repo = Repo(REPO_DIR)
|
||||
self.repo = Repo(self.bot.REPO_DIR)
|
||||
|
||||
@command(permission='all_permissions')
|
||||
def pull(self, mask: IrcString, target: IrcString, args: Dict):
|
||||
@ -68,7 +67,10 @@ class Admin(Plugin):
|
||||
|
||||
%%join <channel>
|
||||
"""
|
||||
self.join_part('join', mask, target, args)
|
||||
channel = args.get('<channel>', target)
|
||||
|
||||
self.bot.join(channel)
|
||||
self.bot.notice(mask.nick, 'Joined channel {}'.format(channel))
|
||||
|
||||
@command(permission='all_permissions')
|
||||
def part(self, mask: IrcString, target: IrcString, args: Dict):
|
||||
@ -76,7 +78,10 @@ class Admin(Plugin):
|
||||
|
||||
%%part [<channel>]
|
||||
"""
|
||||
self.join_part('part', mask, target, args)
|
||||
channel = args.get('<channel>', target)
|
||||
|
||||
self.bot.join(channel)
|
||||
self.bot.notice(mask.nick, 'Parted channel {}'.format(channel))
|
||||
|
||||
@command(permission='all_permissions')
|
||||
def cycle(self, mask: IrcString, target: IrcString, args: Dict):
|
||||
@ -84,12 +89,8 @@ class Admin(Plugin):
|
||||
|
||||
%%cycle [<channel>]
|
||||
"""
|
||||
self.join_part('part', mask, target, args)
|
||||
self.join_part('join', mask, target, args)
|
||||
channel = args.get('<channel>', target)
|
||||
|
||||
def join_part(self, func: str, mask: IrcString, target: IrcString, args: Dict):
|
||||
channel = IrcString(args.get('<channel>') or target)
|
||||
|
||||
if channel.is_channel:
|
||||
getattr(self.bot, func)(channel)
|
||||
self.bot.notice(mask.nick, '{}ed channel {}'.format(func, channel))
|
||||
self.bot.part(channel)
|
||||
self.bot.join(channel)
|
||||
self.bot.notice(mask.nick, 'Cycled channel {}'.format(channel))
|
@ -8,8 +8,6 @@ from . import Plugin
|
||||
|
||||
|
||||
class Coins(Plugin):
|
||||
requires = ['irc3.plugins.command']
|
||||
|
||||
API_URL = 'https://api.cryptowat.ch/markets/coinbase/{crypto}{currency}/summary'
|
||||
CURRENCIES = {
|
||||
'usd': '$',
|
@ -9,28 +9,10 @@ from . import Plugin
|
||||
|
||||
|
||||
class CTCP(Plugin):
|
||||
requires = ['irc3.plugins.async',
|
||||
'irc3.plugins.command']
|
||||
requires = Plugin.requires + ['irc3.plugins.async']
|
||||
|
||||
TIMEOUT = 5
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
def _ctcp(self, name: str, nick: str, reply: str):
|
||||
return '\x02[{}]\x02 {}: {}'.format(name.upper(), nick, reply)
|
||||
|
||||
async def ctcp(self, name: str, mask: IrcString, args: Dict):
|
||||
nick = args.get('<nick>', mask.nick)
|
||||
data = await self.bot.ctcp_async(nick, name.upper(), self.TIMEOUT)
|
||||
|
||||
if not data or data['timeout']:
|
||||
reply = 'timeout'
|
||||
elif not data['success']:
|
||||
reply = 'Error: {}'.format(data['reply'])
|
||||
else:
|
||||
reply = data['reply']
|
||||
|
||||
return self._ctcp(name, nick, reply)
|
||||
|
||||
@command
|
||||
async def ping(self, mask: IrcString, target: IrcString, args: Dict):
|
||||
"""Sends ping via CTCP to user and sends the time needed
|
||||
@ -70,3 +52,20 @@ class CTCP(Plugin):
|
||||
%%ver [<nick>]
|
||||
"""
|
||||
return await self.ctcp('version', mask, args)
|
||||
|
||||
async def ctcp(self, name: str, mask: IrcString, args: Dict):
|
||||
nick = args.get('<nick>', mask.nick)
|
||||
data = await self.bot.ctcp_async(nick, name.upper(), self.TIMEOUT)
|
||||
|
||||
if not data or data['timeout']:
|
||||
reply = 'timeout'
|
||||
elif not data['success']:
|
||||
reply = 'Error: {}'.format(data['reply'])
|
||||
else:
|
||||
reply = data['reply']
|
||||
|
||||
return self._ctcp(name, nick, reply)
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
def _ctcp(self, name: str, nick: str, reply: str):
|
||||
return '\x02[{}]\x02 {}: {}'.format(name.upper(), nick, reply)
|
@ -6,13 +6,10 @@ from docopt import Dict
|
||||
from irc3.plugins.command import command
|
||||
from irc3.utils import IrcString
|
||||
|
||||
from . import DatabasePlugin
|
||||
from . import Plugin
|
||||
|
||||
|
||||
class Useless(DatabasePlugin):
|
||||
requires = ['irc3.plugins.command',
|
||||
'bot.plugins.storage']
|
||||
|
||||
class Useless(Plugin):
|
||||
@command
|
||||
def isup(self, mask: IrcString, target: IrcString, args: Dict):
|
||||
"""Checks if a address is up or down
|
@ -8,7 +8,7 @@ from irc3.plugins.command import command
|
||||
from irc3.utils import IrcString
|
||||
|
||||
from . import Plugin
|
||||
from ..utils import re_generator
|
||||
from .utils import re_generator
|
||||
|
||||
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,
|
@ -6,13 +6,10 @@ from irc3.utils import IrcString
|
||||
from psycopg2 import Error
|
||||
|
||||
from . import DatabasePlugin
|
||||
from ..utils import parse_int
|
||||
from .utils import parse_int
|
||||
|
||||
|
||||
class McManiac(DatabasePlugin):
|
||||
requires = ['irc3.plugins.command',
|
||||
'bot.plugins.storage']
|
||||
|
||||
@command(options_first=True)
|
||||
def mcmaniac(self, mask: IrcString, target: IrcString, args: Dict):
|
||||
"""Get a random McManiaC or by index.
|
@ -1,32 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import irc3
|
||||
from irc3.plugins.command import Commands
|
||||
|
||||
MODULE = __name__
|
||||
|
||||
|
||||
@irc3.plugin
|
||||
class BasePlugin(object):
|
||||
def __init__(self, bot: irc3.IrcBot):
|
||||
self.bot = bot
|
||||
self.log = bot.log
|
||||
self.guard = bot.get_plugin(Commands).guard
|
||||
|
||||
|
||||
class Plugin(BasePlugin):
|
||||
@classmethod
|
||||
def reload(cls, old: BasePlugin):
|
||||
return cls(old.bot)
|
||||
|
||||
|
||||
# Import the PgSQL storage plugin
|
||||
from .storage import Storage # noqa
|
||||
|
||||
|
||||
class DatabasePlugin(Plugin):
|
||||
def __init__(self, bot: irc3.IrcBot):
|
||||
super().__init__(bot)
|
||||
# Get PgSQL storage instance and connection + cursor
|
||||
self.db = bot.get_plugin(Storage)
|
||||
self.con = self.db.con
|
||||
self.cur = self.db.cur
|
@ -2,17 +2,18 @@
|
||||
import re
|
||||
|
||||
from docopt import Dict
|
||||
from irc3.plugins.command import command
|
||||
from irc3.plugins.command import Commands, command
|
||||
from irc3.utils import IrcString
|
||||
from psycopg2 import Error
|
||||
|
||||
from . import DatabasePlugin
|
||||
from ..utils import parse_int
|
||||
from . import DatabasePlugin, Bot
|
||||
from .utils import parse_int
|
||||
|
||||
|
||||
class Quotes(DatabasePlugin):
|
||||
requires = ['irc3.plugins.command',
|
||||
'bot.plugins.storage']
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
self.guard = bot.get_plugin(Commands).guard
|
||||
|
||||
def add_quote(self, mask: IrcString, nick: str, quote: str, channel: IrcString):
|
||||
# Parse nick from "<@foobar>" like strings
|
||||
@ -51,7 +52,7 @@ class Quotes(DatabasePlugin):
|
||||
quotes
|
||||
WHERE
|
||||
id = (
|
||||
SELECT
|
||||
SELECT
|
||||
id
|
||||
FROM
|
||||
ranked_quotes
|
@ -9,9 +9,6 @@ from . import DatabasePlugin
|
||||
|
||||
|
||||
class Rape(DatabasePlugin):
|
||||
requires = ['irc3.plugins.command',
|
||||
'bot.plugins.storage']
|
||||
|
||||
@command
|
||||
def owe(self, mask: IrcString, target: IrcString, args: Dict):
|
||||
"""Shows how much a nick owes
|
@ -8,8 +8,7 @@ from . import DatabasePlugin
|
||||
|
||||
|
||||
class Useless(DatabasePlugin):
|
||||
requires = ['irc3.plugins.command',
|
||||
'bot.plugins.storage']
|
||||
requires = []
|
||||
|
||||
@irc3.event(r'^:(?P<mask>\S+) PRIVMSG (?P<target>#\S+) :s/'
|
||||
r'(?P<search>(?:[^/\\]|\\.)*)/'
|
@ -10,9 +10,6 @@ from . import DatabasePlugin
|
||||
|
||||
|
||||
class Seen(DatabasePlugin):
|
||||
requires = ['irc3.plugins.command',
|
||||
'bot.plugins.storage']
|
||||
|
||||
@command
|
||||
def seen(self, mask: IrcString, target: IrcString, args: Dict):
|
||||
"""Get last seen date and message for a nick
|
@ -1,17 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
|
||||
import irc3
|
||||
import psycopg2
|
||||
from psycopg2.extras import DictCursor
|
||||
|
||||
from . import Plugin
|
||||
from . import Plugin, Bot
|
||||
|
||||
|
||||
class Storage(Plugin):
|
||||
def __init__(self, bot: irc3.IrcBot):
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
# Create database connection
|
||||
self.bot.sql = self
|
||||
self.con = psycopg2.connect(os.environ['DATABASE_URI'])
|
||||
# Create database cursor (with dict factory to access rows by name)
|
||||
self.cur = self.con.cursor(cursor_factory=DictCursor)
|
@ -7,14 +7,11 @@ from irc3.plugins.command import command
|
||||
from irc3.utils import IrcString
|
||||
from psycopg2 import Error
|
||||
|
||||
from . import DatabasePlugin
|
||||
from . import DatabasePlugin, Bot
|
||||
|
||||
|
||||
class Tell(DatabasePlugin):
|
||||
requires = ['irc3.plugins.command',
|
||||
'bot.plugins.storage']
|
||||
|
||||
def __init__(self, bot: irc3.IrcBot):
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
self.tell_queue = {}
|
||||
|
@ -3,7 +3,6 @@ import re
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
import irc3
|
||||
from aiocron import crontab
|
||||
from docopt import Dict
|
||||
from irc3.plugins.command import command
|
||||
@ -11,14 +10,11 @@ from irc3.utils import IrcString
|
||||
from psycopg2 import Error
|
||||
from psycopg2.extras import DictRow
|
||||
|
||||
from . import DatabasePlugin
|
||||
from . import DatabasePlugin, Bot
|
||||
|
||||
|
||||
class Timer(DatabasePlugin):
|
||||
requires = ['irc3.plugins.command',
|
||||
'bot.plugins.storage']
|
||||
|
||||
def __init__(self, bot: irc3.IrcBot):
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
self.timers = set()
|
||||
self.set_timers()
|
@ -8,8 +8,6 @@ from . import Plugin
|
||||
|
||||
|
||||
class Urban(Plugin):
|
||||
requires = ['irc3.plugins.command']
|
||||
|
||||
URL = 'https://api.urbandictionary.com/v0/define'
|
||||
|
||||
@command
|
@ -9,22 +9,17 @@ from irc3.utils import IrcString
|
||||
from psycopg2 import Error
|
||||
|
||||
from . import DatabasePlugin
|
||||
from ..utils import re_generator
|
||||
from .utils import re_generator
|
||||
|
||||
|
||||
class Useless(DatabasePlugin):
|
||||
requires = ['irc3.plugins.command',
|
||||
'bot.plugins.storage']
|
||||
|
||||
RAINBOW = (5, 7, 8, 9, 3, 10, 12, 2, 6, 13)
|
||||
|
||||
WOAH = (
|
||||
'woah',
|
||||
'woah indeed',
|
||||
'woah woah woah!',
|
||||
'keep your woahs to yourself',
|
||||
)
|
||||
|
||||
ISPS = (
|
||||
't-ipconnect',
|
||||
'telefonica',
|
||||
@ -32,7 +27,6 @@ class Useless(DatabasePlugin):
|
||||
'kabel',
|
||||
'unity-media',
|
||||
)
|
||||
|
||||
GENDERS = (
|
||||
'male',
|
||||
'female',
|
@ -8,8 +8,6 @@ from . import Plugin
|
||||
|
||||
|
||||
class Weather(Plugin):
|
||||
requires = ['irc3.plugins.command']
|
||||
|
||||
URL = 'https://query.yahooapis.com/v1/public/yql?format=json&q=' \
|
||||
'select * from weather.forecast where u="c" and woeid in ' \
|
||||
'(select woeid from geo.places(1) where text="{}")'
|
@ -9,12 +9,10 @@ from irc3.plugins.command import command
|
||||
from irc3.utils import IrcString
|
||||
|
||||
from . import Plugin
|
||||
from ..utils import date_from_iso
|
||||
from .utils import date_from_iso
|
||||
|
||||
|
||||
class YouTube(Plugin):
|
||||
requires = ['irc3.plugins.command']
|
||||
|
||||
URL = 'https://www.googleapis.com/youtube/v3'
|
||||
API = '{}/videos?part=snippet,statistics,contentDetails'.format(URL)
|
||||
SEARCH = '{}/search?part=id'.format(URL)
|
@ -11,22 +11,22 @@
|
||||
"flood_rate_delay": 1,
|
||||
"includes": [
|
||||
"irc3.plugins.uptime",
|
||||
"bot.plugins.admin",
|
||||
"bot.plugins.coins",
|
||||
"bot.plugins.ctcp",
|
||||
"bot.plugins.isup",
|
||||
"bot.plugins.linux",
|
||||
"bot.plugins.mcmaniac",
|
||||
"bot.plugins.quotes",
|
||||
"bot.plugins.rape",
|
||||
"bot.plugins.regex",
|
||||
"bot.plugins.seen",
|
||||
"bot.plugins.tell",
|
||||
"bot.plugins.timer",
|
||||
"bot.plugins.urban",
|
||||
"bot.plugins.useless",
|
||||
"bot.plugins.weather",
|
||||
"bot.plugins.youtube"
|
||||
"bot.admin",
|
||||
"bot.coins",
|
||||
"bot.ctcp",
|
||||
"bot.isup",
|
||||
"bot.linux",
|
||||
"bot.mcmaniac",
|
||||
"bot.quotes",
|
||||
"bot.rape",
|
||||
"bot.regex",
|
||||
"bot.seen",
|
||||
"bot.tell",
|
||||
"bot.timer",
|
||||
"bot.urban",
|
||||
"bot.useless",
|
||||
"bot.weather",
|
||||
"bot.youtube"
|
||||
],
|
||||
"irc3.plugins.command": {
|
||||
"guard": "irc3.plugins.command.mask_based_policy",
|
||||
|
Loading…
Reference in New Issue
Block a user