refactored config
This commit is contained in:
parent
d06b8f2fdc
commit
b552c35baa
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -10,3 +10,4 @@ logs/
|
|||
*.txt
|
||||
*.db-journal
|
||||
tourettes.py
|
||||
config.py
|
||||
|
|
46
README.md
46
README.md
|
@ -1,56 +1,10 @@
|
|||
# Fulvia
|
||||
## NIGGER DICKS 2: Electric Boogaloo
|
||||
It's like Sopel, except rewritten from scratch using Twisted as a base and over half the features ripped out.
|
||||
|
||||
## Requirements
|
||||
Python 3.6+
|
||||
Python packages: `twisted python-dateutil requests bs4 wolframalpha pyenchant emoji Pillow xml2dict ipython numpy numpngw`
|
||||
|
||||
## Config
|
||||
`nickname` - The nickname the bot will use.
|
||||
`realname` - The realname the bot will use.
|
||||
`username` - The user ident the bot will use.
|
||||
`prefix` - The command prefix the bot will listen for.
|
||||
`homedir` - The bot's home directory. Required for the bot to get certain pathing right. In the future that will be obtained automatically.
|
||||
`server` - The server address to connect to.
|
||||
`port` - The server port to connect to. SSL will probably not work.
|
||||
`use_ssl` - Place holder.
|
||||
`channels` - Which channels to join upon connection.
|
||||
`db_filename` - Filename to use for the bot's database.
|
||||
`owner` - The bot's owner. Use for permission purposes on restricted commands. Outranks admins. Should be the full hostmask of the user.
|
||||
`admins` - Comma-delineated list of admins the bot will recognize for restricted commands. Should be the full hostmask for each one.
|
||||
`default_time_format` - The format used for all timestamp operations. See the official python docs for the `time` library for more information.
|
||||
`disabled_modules` - Comma-delineated list of modules *not* to load on startup. Modules should be specified without the `.py` extension.
|
||||
|
||||
### Example default.cfg
|
||||
```
|
||||
[core]
|
||||
nickname = DiceBot9002
|
||||
realname = DiceBot9002
|
||||
username = DiceBot9002
|
||||
prefix = .
|
||||
homedir = /home/iou1name/fulvia
|
||||
server = irc.steelbea.me
|
||||
port = 6667
|
||||
use_ssl = false
|
||||
channels = #SomaIsGay,#test
|
||||
db_filename = DiceBot9002.db
|
||||
owner = iou1name!~iou1name@operational.operator
|
||||
admins =
|
||||
default_time_format = [%Y-%m-%d %H:%M:%S]
|
||||
disabled_modules = countdown
|
||||
|
||||
[wolfram]
|
||||
app_id = API_KEY
|
||||
units = nonmetric
|
||||
|
||||
[movie]
|
||||
tmdb_api_key = API_KEY
|
||||
|
||||
[currency]
|
||||
api_key = API_KEY
|
||||
```
|
||||
|
||||
## TODO
|
||||
Fix the movie table
|
||||
Consider re-adding the following modules: `etymology, ip`
|
||||
|
|
50
bot.py
50
bot.py
|
@ -5,7 +5,6 @@ The core bot class for Fulvia.
|
|||
import os
|
||||
import sys
|
||||
import time
|
||||
import functools
|
||||
import threading
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
|
@ -15,35 +14,30 @@ from twisted.words.protocols import irc
|
|||
|
||||
import db
|
||||
import tools
|
||||
import config
|
||||
import loader
|
||||
from trigger import Trigger
|
||||
|
||||
class Fulvia(irc.IRCClient):
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
"""The bot's config, loaded from file."""
|
||||
|
||||
self.nickname = config.core.nickname
|
||||
self.nick = config.core.nickname
|
||||
def __init__(self):
|
||||
self.nickname = config.nickname
|
||||
self.nick = config.nickname
|
||||
"""The bot's current nickname."""
|
||||
|
||||
self.realname = config.core.realname
|
||||
self.realname = config.realname
|
||||
"""The bot's 'real name', used in whois."""
|
||||
|
||||
self.username = config.core.username
|
||||
self.username = config.username
|
||||
"""The bot's username ident used for logging into the server."""
|
||||
|
||||
self.host = ""
|
||||
"""The bot's host, virtual or otherwise. To be filled in later."""
|
||||
|
||||
self.prefix = config.core.prefix
|
||||
"""The command prefix the bot watches for."""
|
||||
|
||||
self.static = os.path.join(config.homedir, "static")
|
||||
self.static = "static"
|
||||
os.makedirs(self.static, exist_ok=True)
|
||||
"""The path to the bot's static file directory."""
|
||||
|
||||
self.log_path = os.path.join(config.homedir, "logs")
|
||||
self.log_path = "logs"
|
||||
os.makedirs(self.static, exist_ok=True)
|
||||
"""The path to the bot's log files."""
|
||||
|
||||
|
@ -68,7 +62,7 @@ class Fulvia(irc.IRCClient):
|
|||
modules need it.
|
||||
"""
|
||||
|
||||
self.db = db.FulviaDB(self.config)
|
||||
self.db = db.FulviaDB()
|
||||
"""
|
||||
A class with some basic interactions for the bot's sqlite3 databse.
|
||||
"""
|
||||
|
@ -100,7 +94,7 @@ class Fulvia(irc.IRCClient):
|
|||
self._user_joined = []
|
||||
"""These get called when a user joins a channel."""
|
||||
|
||||
self._disabled_modules = self.config.core.disabled_modules.split(",")
|
||||
self._disabled_modules = config.disabled_modules
|
||||
"""These modules will NOT be loaded when load_modules() is called."""
|
||||
|
||||
self.load_modules()
|
||||
|
@ -117,7 +111,7 @@ class Fulvia(irc.IRCClient):
|
|||
self.url_callbacks = {}
|
||||
# ensure they're empty
|
||||
|
||||
modules = loader.find_modules(self.config.homedir)
|
||||
modules = loader.find_modules()
|
||||
loaded = 0
|
||||
failed = 0
|
||||
for name, path in modules.items():
|
||||
|
@ -215,7 +209,7 @@ class Fulvia(irc.IRCClient):
|
|||
"""
|
||||
# TODO: use time module instead of datetime
|
||||
t = datetime.fromtimestamp(time.time())
|
||||
timestamp = t.strftime(self.config.core.default_time_format)
|
||||
timestamp = t.strftime(config.default_time_format)
|
||||
self._log_dump[channel].append(timestamp + " " + text)
|
||||
|
||||
if time.time() - self._last_log_dump > 1:
|
||||
|
@ -248,9 +242,9 @@ class Fulvia(irc.IRCClient):
|
|||
self.log(channel, line)
|
||||
|
||||
funcs = []
|
||||
if message.startswith(self.prefix) and message != self.prefix:
|
||||
if message.startswith(config.prefix) and message != config.prefix:
|
||||
command = message.partition(" ")[0]
|
||||
command = command.replace(self.prefix, "", 1)
|
||||
command = command.replace(config.prefix, "", 1)
|
||||
cmd = self.commands.get(command)
|
||||
if not cmd:
|
||||
return
|
||||
|
@ -259,7 +253,7 @@ class Fulvia(irc.IRCClient):
|
|||
funcs += self._hooks
|
||||
|
||||
for func in funcs:
|
||||
trigger = Trigger(user, channel, message, "PRIVMSG", self.config)
|
||||
trigger = Trigger(user, channel, message, "PRIVMSG")
|
||||
bot = FulviaWrapper(self, trigger)
|
||||
|
||||
if func.rate:
|
||||
|
@ -352,8 +346,8 @@ class Fulvia(irc.IRCClient):
|
|||
|
||||
def signedOn(self):
|
||||
"""Called when the bot successfully connects to the server."""
|
||||
if self.config.core.oper_password:
|
||||
self.sendLine("OPER " + self.config.core.nickname + ' ' + self.config.core.oper_password)
|
||||
if config.oper_password:
|
||||
self.sendLine("OPER " + config.nickname + ' ' + config.oper_password)
|
||||
print(f"Signed on as {self.nickname}")
|
||||
self.whois(self.nickname)
|
||||
|
||||
|
@ -361,7 +355,7 @@ class Fulvia(irc.IRCClient):
|
|||
line += f"{self.nickname}!{self.username}@{self.host}"
|
||||
self.log(self.hostname, line)
|
||||
|
||||
for channel in self.config.core.channels.split(","):
|
||||
for channel in config.channels:
|
||||
self.join(channel)
|
||||
|
||||
|
||||
|
@ -400,7 +394,7 @@ class Fulvia(irc.IRCClient):
|
|||
self.channels[channel].users[nick] = user
|
||||
|
||||
for func in self._user_joined:
|
||||
trigger = Trigger(user, channel, f"{user} has joined", "PRIVMSG", self.config)
|
||||
trigger = Trigger(user, channel, f"{user} has joined", "PRIVMSG")
|
||||
bot = FulviaWrapper(self, trigger)
|
||||
t = threading.Thread(target=self.call,args=(func, bot, trigger))
|
||||
t.start()
|
||||
|
@ -667,8 +661,4 @@ class FulviaWrapper():
|
|||
|
||||
|
||||
class FulviaFactory(protocol.ReconnectingClientFactory):
|
||||
# black magic going on here
|
||||
protocol = property(lambda s: functools.partial(Fulvia, s.config))
|
||||
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
protocol = Fulvia
|
||||
|
|
116
config.py
116
config.py
|
@ -1,116 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
For parsing and generating config files.
|
||||
"""
|
||||
from configparser import ConfigParser
|
||||
|
||||
class Config():
|
||||
def __init__(self, filename):
|
||||
"""
|
||||
The bot's configuration.
|
||||
|
||||
The given filename will be associated with the configuration, and is
|
||||
the file which will be written if write() is called. If load is not
|
||||
given or True, the configuration object will load the attributes from
|
||||
the file at filename.
|
||||
|
||||
A few default values will be set here if they are not defined in the
|
||||
config file, or a config file is not loaded. They are documented below.
|
||||
"""
|
||||
self.filename = filename
|
||||
"""The config object's associated file, as noted above."""
|
||||
|
||||
self.parser = ConfigParser(allow_no_value=True, interpolation=None)
|
||||
self.parser.read(self.filename)
|
||||
|
||||
@property
|
||||
def homedir(self):
|
||||
"""An alias to config.core.homedir"""
|
||||
# Technically it's the other way around, so we can bootstrap filename
|
||||
# attributes in the core section, but whatever.
|
||||
configured = None
|
||||
if self.parser.has_option('core', 'homedir'):
|
||||
configured = self.parser.get('core', 'homedir')
|
||||
if configured:
|
||||
return configured
|
||||
else:
|
||||
return os.path.dirname(self.filename)
|
||||
|
||||
def save(self):
|
||||
"""Save all changes to the config file."""
|
||||
with open(self.filename, 'w') as cfgfile:
|
||||
self.parser.write(cfgfile)
|
||||
|
||||
def add_section(self, name):
|
||||
"""
|
||||
Add a section to the config file.
|
||||
|
||||
Returns ``False`` if already exists.
|
||||
"""
|
||||
try:
|
||||
return self.parser.add_section(name)
|
||||
except ConfigParser.DuplicateSectionError:
|
||||
return False
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Allows sections to be called like class attributes."""
|
||||
if name in self.parser.sections():
|
||||
items = self.parser.items(name)
|
||||
section = ConfigSection(name, items, self) # Return a section
|
||||
setattr(self, name, section)
|
||||
return section
|
||||
else:
|
||||
raise AttributeError("%r object has no attribute %r"
|
||||
% (type(self).__name__, name))
|
||||
|
||||
|
||||
class ConfigSection(object):
|
||||
"""
|
||||
Represents a section of the config file.
|
||||
|
||||
Contains all keys in thesection as attributes.
|
||||
"""
|
||||
def __init__(self, name, items, parent):
|
||||
object.__setattr__(self, '_name', name)
|
||||
object.__setattr__(self, '_parent', parent)
|
||||
for item in items:
|
||||
value = item[1].strip()
|
||||
if not value.lower() == 'none':
|
||||
if value.lower() == 'false':
|
||||
value = False
|
||||
object.__setattr__(self, item[0], value)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return None
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
object.__setattr__(self, name, value)
|
||||
if type(value) is list:
|
||||
value = ','.join(value)
|
||||
self._parent.parser.set(self._name, name, value)
|
||||
|
||||
def get_list(self, name):
|
||||
value = getattr(self, name)
|
||||
if not value:
|
||||
return []
|
||||
if isinstance(value, str):
|
||||
value = value.split(',')
|
||||
# Keep the split value, so we don't have to keep doing this
|
||||
setattr(self, name, value)
|
||||
return value
|
||||
|
||||
|
||||
def readConfig(filename):
|
||||
"""
|
||||
Parses the provided filename and returns the config object.
|
||||
"""
|
||||
config = ConfigParser(allow_no_value=True, interpolation=None)
|
||||
config.read(filename)
|
||||
return config
|
||||
|
||||
|
||||
def generateConfig(filename):
|
||||
"""
|
||||
Generates a blank config file with minimal defaults.
|
||||
"""
|
||||
pass
|
33
config.template.py
Executable file
33
config.template.py
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
The bot's config file.
|
||||
"""
|
||||
|
||||
""" Core """
|
||||
nickname = 'DiceBot9002'
|
||||
realname = 'DiceBot9002'
|
||||
username = 'DiceBot9002'
|
||||
prefix = '.'
|
||||
server = 'irc.steelbea.me'
|
||||
port = 6667
|
||||
use_ssl = False
|
||||
channels = ['#test', '#SomaIsGay']
|
||||
db_filename = 'DiceBot9002.db'
|
||||
owner = 'iou1name!~iou1name@operational.operator'
|
||||
admins = []
|
||||
default_time_format = '[%Y-%m-%d %H:%M:%S]'
|
||||
disabled_modules = ['countdown']
|
||||
oper_password = 'password'
|
||||
|
||||
""" Wolfram """
|
||||
wolfram_app_id = 'password'
|
||||
wolfram_units = 'nonmetric'
|
||||
|
||||
""" Movie """
|
||||
tmdb_api_key = 'password'
|
||||
|
||||
""" Currency """
|
||||
exchangerate_api_key = 'password'
|
||||
|
||||
""" Crypto """
|
||||
coinlib_api_key = 'password'
|
8
db.py
8
db.py
|
@ -6,13 +6,15 @@ import os
|
|||
import sqlite3
|
||||
import threading
|
||||
|
||||
class FulviaDB(object):
|
||||
import config
|
||||
|
||||
class FulviaDB:
|
||||
"""
|
||||
Defines a basic interface and some convenience functionsfor the bot's
|
||||
database.
|
||||
"""
|
||||
def __init__(self, config):
|
||||
path = config.core.db_filename
|
||||
def __init__(self):
|
||||
path = config.db_filename
|
||||
self.filename = path
|
||||
self.db_lock = threading.Lock()
|
||||
|
||||
|
|
17
loader.py
17
loader.py
|
@ -14,7 +14,7 @@ def load_module(bot, path):
|
|||
module = importlib.import_module(path)
|
||||
if hasattr(module, 'setup'):
|
||||
module.setup(bot)
|
||||
relevant_parts = process_module(module, bot.config)
|
||||
relevant_parts = process_module(module)
|
||||
for part in relevant_parts:
|
||||
bot.register_callable(part)
|
||||
|
||||
|
@ -34,14 +34,13 @@ def unload_module(bot, name):
|
|||
del sys.modules[name]
|
||||
|
||||
|
||||
def find_modules(homedir):
|
||||
def find_modules():
|
||||
"""
|
||||
Searches through homedir/modules for python files and returns a dictionary
|
||||
Searches through 'modules/' for python files and returns a dictionary
|
||||
with the module name as the key and the path as the value.
|
||||
"""
|
||||
modules_dir = os.path.join(homedir, "modules")
|
||||
modules = {}
|
||||
for file in os.listdir(modules_dir):
|
||||
for file in os.listdir('modules'):
|
||||
if not file.endswith(".py"):
|
||||
continue
|
||||
name = file.replace(".py", "")
|
||||
|
@ -49,7 +48,7 @@ def find_modules(homedir):
|
|||
return modules
|
||||
|
||||
|
||||
def process_module(module, config):
|
||||
def process_module(module):
|
||||
"""
|
||||
Takes a module object and extracts relevant data objects out of it.
|
||||
Returns all callables(read: functions) and shutdowns(?).
|
||||
|
@ -58,7 +57,7 @@ def process_module(module, config):
|
|||
for key, obj in dict.items(vars(module)):
|
||||
if callable(obj):
|
||||
if is_triggerable(obj):
|
||||
process_callable(obj, config)
|
||||
process_callable(obj)
|
||||
callables.append(obj)
|
||||
return callables
|
||||
|
||||
|
@ -72,12 +71,10 @@ def is_triggerable(obj):
|
|||
return any(hasattr(obj, attr) for attr in triggerable_attributes)
|
||||
|
||||
|
||||
def process_callable(func, config):
|
||||
def process_callable(func):
|
||||
"""
|
||||
Sets various helper atributes about a given function.
|
||||
"""
|
||||
prefix = config.core.prefix
|
||||
|
||||
func.thread = getattr(func, "thread", True)
|
||||
func.hook = getattr(func, "hook", False)
|
||||
func.rate = getattr(func, "rate", 0)
|
||||
|
|
|
@ -15,6 +15,6 @@ def BQstatus(bot, trigger):
|
|||
status = "\x0304DEAD"
|
||||
deathdate = "[2017-02-16 00:19:00]"
|
||||
msg = "Banished Quest status: " + status + "\nTime since death: "
|
||||
msg += relativeTime(bot.config, datetime.now(), deathdate) + " ago "
|
||||
msg += relativeTime(datetime.now(), deathdate) + " ago "
|
||||
msg += deathdate
|
||||
bot.msg(msg)
|
||||
|
|
|
@ -27,6 +27,6 @@ def generic_countdown(bot, trigger):
|
|||
except:
|
||||
return bot.msg("Please use correct format: .countdown 2012 12 21")
|
||||
|
||||
msg = relativeTime(bot.config, datetime.now(), date)
|
||||
msg = relativeTime(datetime.now(), date)
|
||||
msg += " until " + trigger.group(2)
|
||||
bot.msg(msg)
|
||||
|
|
|
@ -6,6 +6,7 @@ import re
|
|||
|
||||
import requests
|
||||
|
||||
import config
|
||||
from module import commands, example, require_admin
|
||||
|
||||
URI = "https://coinlib.io/api/v1"
|
||||
|
@ -19,7 +20,7 @@ def crypto(bot, trigger):
|
|||
Queries coinlib.io for information about various crytocurrencies.
|
||||
"""
|
||||
params = {
|
||||
"key": bot.config.crypto.api_key,
|
||||
"key": config.coinlib_api_key,
|
||||
"pref": "USD",
|
||||
}
|
||||
symbol = trigger.group(3)
|
||||
|
|
|
@ -33,7 +33,7 @@ def exchange(bot, trigger):
|
|||
cur_to = cur_to.upper()
|
||||
cur_from = cur_from.upper()
|
||||
|
||||
api_key = bot.config.currency.api_key
|
||||
api_key = config.exchangerate_api_key
|
||||
url = CUR_URI.format(**{"API_KEY": api_key, "CUR_FROM": cur_from})
|
||||
res = requests.get(url, verify=True)
|
||||
res.raise_for_status()
|
||||
|
|
|
@ -11,6 +11,7 @@ from sqlite3 import IntegrityError, OperationalError
|
|||
import bs4
|
||||
import requests
|
||||
|
||||
import config
|
||||
from module import commands, example, require_admin
|
||||
|
||||
def setup(bot):
|
||||
|
@ -50,7 +51,7 @@ def movieInfo(bot, trigger):
|
|||
return bot.reply("What movie?")
|
||||
word = word.replace(" ", "+")
|
||||
|
||||
api_key = bot.config.movie.tmdb_api_key
|
||||
api_key = config.tmdb_api_key
|
||||
uri = "https://api.themoviedb.org/3/search/movie?" + \
|
||||
f"api_key={api_key}&query={word}"
|
||||
data = requests.get(uri, timeout=30, verify=True).json()
|
||||
|
@ -151,7 +152,7 @@ def pickMovie(bot, trigger):
|
|||
bot.reply(movie[0])
|
||||
|
||||
if trigger.group(2) == "-m":
|
||||
trigger.set_group(f".movie {movie}", bot.config)
|
||||
trigger.set_group(f".movie {movie}")
|
||||
movieInfo(bot, trigger)
|
||||
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import datetime
|
|||
import threading
|
||||
import collections
|
||||
|
||||
import config
|
||||
from module import commands, example
|
||||
|
||||
class MonitorThread(threading.Thread):
|
||||
|
@ -213,7 +214,7 @@ def create_reminder(bot, trigger, duration, message):
|
|||
|
||||
if duration >= 60:
|
||||
remind_at = datetime.datetime.fromtimestamp(t)
|
||||
t_format = bot.config.core.default_time_format
|
||||
t_format = config.default_time_format
|
||||
timef = datetime.datetime.strftime(remind_at, t_format)
|
||||
|
||||
bot.reply('Okay, will remind at %s' % timef)
|
||||
|
|
|
@ -73,7 +73,7 @@ def findandreplace(bot, trigger):
|
|||
if not group:
|
||||
return
|
||||
g = (trigger.group(0),) + group.groups()
|
||||
trigger.set_group(g, bot.config)
|
||||
trigger.set_group(g)
|
||||
|
||||
# Correcting other person vs self.
|
||||
rnick = (trigger.group(1) or trigger.nick)
|
||||
|
|
|
@ -11,6 +11,7 @@ from sqlite3 import OperationalError
|
|||
|
||||
from requests.structures import CaseInsensitiveDict
|
||||
|
||||
import config
|
||||
from tools.time import relativeTime
|
||||
from module import commands, example, hook, require_chanmsg, rate
|
||||
|
||||
|
@ -87,9 +88,9 @@ def seen(bot, trigger):
|
|||
return bot.msg(f"I haven't seen \x0308{args.nick}")
|
||||
|
||||
timestamp = datetime.fromtimestamp(timestamp)
|
||||
t_format = bot.config.core.default_time_format
|
||||
t_format = config.default_time_format
|
||||
timestamp = datetime.strftime(timestamp, t_format)
|
||||
reltime = relativeTime(bot.config, datetime.now(), timestamp)
|
||||
reltime = relativeTime(datetime.now(), timestamp)
|
||||
|
||||
if args.first:
|
||||
msg = "First"
|
||||
|
|
|
@ -9,6 +9,7 @@ import threading
|
|||
from datetime import datetime
|
||||
from sqlite3 import OperationalError
|
||||
|
||||
import config
|
||||
from tools.time import relativeTime
|
||||
from module import commands, example, hook
|
||||
|
||||
|
@ -107,8 +108,8 @@ def tell_hook(bot, trigger):
|
|||
teller, unixtime, message = tell
|
||||
|
||||
telldate = datetime.fromtimestamp(unixtime)
|
||||
reltime = relativeTime(bot.config, datetime.now(), telldate)
|
||||
t_format = bot.config.core.default_time_format
|
||||
reltime = relativeTime(datetime.now(), telldate)
|
||||
t_format = config.default_time_format
|
||||
telldate = datetime.strftime(telldate, t_format)
|
||||
|
||||
msg = f"{tellee}: \x0310{message}\x03 (\x0308{teller}\x03) {telldate}" \
|
||||
|
|
|
@ -4,9 +4,9 @@ Querying Wolfram Alpha.
|
|||
"""
|
||||
import wolframalpha
|
||||
|
||||
import config
|
||||
from module import commands, example
|
||||
|
||||
|
||||
@commands('wa', 'wolfram')
|
||||
@example('.wa 2+2', '[W|A] 2+2 = 4')
|
||||
@example(".wa python language release date",
|
||||
|
@ -17,11 +17,11 @@ def wa_command(bot, trigger):
|
|||
"""
|
||||
if not trigger.group(2):
|
||||
return bot.reply("You must provide a query.")
|
||||
if not bot.config.wolfram.app_id:
|
||||
if not config.wolfram_app_id:
|
||||
bot.reply("Wolfram|Alpha API app ID not configured.")
|
||||
query = trigger.group(2).strip()
|
||||
app_id = bot.config.wolfram.app_id
|
||||
units = bot.config.wolfram.units
|
||||
app_id = config.wolfram_app_id
|
||||
units = config.wolfram_units
|
||||
|
||||
res = wa_query(query, app_id, units)
|
||||
|
||||
|
|
23
run.py
23
run.py
|
@ -6,26 +6,11 @@ import os
|
|||
|
||||
from twisted.internet import reactor
|
||||
|
||||
import config
|
||||
from bot import FulviaFactory
|
||||
from config import Config
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Fulvia IRC Bot")
|
||||
parser.add_argument(
|
||||
"-c",
|
||||
"--config",
|
||||
help="Use a specific config file.")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.config:
|
||||
args.config = "default.cfg"
|
||||
|
||||
config = Config(args.config)
|
||||
|
||||
server = config.core.server
|
||||
port = int(config.core.port)
|
||||
reactor.connectTCP(server, port, FulviaFactory(config))
|
||||
server = config.server
|
||||
port = config.port
|
||||
reactor.connectTCP(server, port, FulviaFactory())
|
||||
reactor.run()
|
||||
|
|
|
@ -6,15 +6,17 @@ from datetime import datetime
|
|||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
import config
|
||||
|
||||
def relativeTime(config, time_1, time_2):
|
||||
|
||||
def relativeTime(time_1, time_2):
|
||||
"""
|
||||
Returns the relative time difference between 'time_1' and 'time_2'.
|
||||
If either 'time_1' or 'time_2' is a string, it will be converted to a
|
||||
datetime object according to the 'default_time_format' variable in the
|
||||
config.
|
||||
"""
|
||||
t_format = config.core.default_time_format
|
||||
t_format = config.default_time_format
|
||||
if type(time_1) == str:
|
||||
time_1 = datetime.strptime(time_1, t_format)
|
||||
if type(time_2) == str:
|
||||
|
|
23
trigger.py
23
trigger.py
|
@ -4,6 +4,8 @@ The trigger abstraction layer.
|
|||
"""
|
||||
import datetime
|
||||
|
||||
import config
|
||||
|
||||
def split_user(user):
|
||||
"""
|
||||
Splits a user hostmask into <nick>!<ident>@<host>
|
||||
|
@ -21,14 +23,14 @@ class Group(list):
|
|||
Custom list class that permits calling it like a function so as to
|
||||
emulate a re.group instance.
|
||||
"""
|
||||
def __init__(self, message, config):
|
||||
def __init__(self, message):
|
||||
"""
|
||||
Initializes the group class. If 'message' is a string, we split
|
||||
it into groups according to the usual trigger.group structure.
|
||||
Otherwise we assume it's already been split appropriately.
|
||||
"""
|
||||
if type(message) == str:
|
||||
message = self.split_group(message, config)
|
||||
message = self.split_group(message)
|
||||
list.__init__(self, message)
|
||||
|
||||
|
||||
|
@ -45,7 +47,7 @@ class Group(list):
|
|||
return item
|
||||
|
||||
|
||||
def split_group(self, message, config):
|
||||
def split_group(self, message):
|
||||
"""
|
||||
Splits the message by spaces.
|
||||
group(0) is always the entire message.
|
||||
|
@ -54,11 +56,10 @@ class Group(list):
|
|||
group(2) is always the entire message after the first word.
|
||||
group(3+) is always every individual word after the first word.
|
||||
"""
|
||||
prefix = config.core.prefix
|
||||
group = []
|
||||
group.append(message)
|
||||
words = message.split()
|
||||
group.append(words[0].replace(prefix, "", 1))
|
||||
group.append(words[0].replace(config.prefix, "", 1))
|
||||
group.append(" ".join(words[1:]))
|
||||
group += words[1:]
|
||||
|
||||
|
@ -66,7 +67,7 @@ class Group(list):
|
|||
|
||||
|
||||
class Trigger():
|
||||
def __init__(self, user, channel, message, event, config):
|
||||
def __init__(self, user, channel, message, event):
|
||||
self.channel = channel
|
||||
"""
|
||||
The channel from which the message was sent.
|
||||
|
@ -112,7 +113,7 @@ class Trigger():
|
|||
message.
|
||||
"""
|
||||
|
||||
self.group = Group(message, config)
|
||||
self.group = Group(message)
|
||||
"""The ``group`` function of the ``match`` attribute.
|
||||
|
||||
See Python :mod:`re` documentation for details."""
|
||||
|
@ -125,14 +126,14 @@ class Trigger():
|
|||
``('#example', '-m')``
|
||||
"""
|
||||
|
||||
admins = config.core.admins.split(",") + [config.core.owner]
|
||||
admins = config.admins + [config.owner]
|
||||
self.admin = any([self.compare_hostmask(admin) for admin in admins])
|
||||
"""
|
||||
True if the nick which triggered the command is one of the bot's
|
||||
admins.
|
||||
"""
|
||||
|
||||
self.owner = self.compare_hostmask(config.core.owner)
|
||||
self.owner = self.compare_hostmask(config.owner)
|
||||
"""True if the nick which triggered the command is the bot's owner."""
|
||||
|
||||
|
||||
|
@ -147,9 +148,9 @@ class Trigger():
|
|||
return compare_against == "@".join(self.nick, self.host)
|
||||
|
||||
|
||||
def set_group(self, line, config):
|
||||
def set_group(self, line):
|
||||
"""
|
||||
Allows a you to easily change the current group to a new Group
|
||||
instance.
|
||||
"""
|
||||
self.group = Group(line, config)
|
||||
self.group = Group(line)
|
||||
|
|
Loading…
Reference in New Issue
Block a user