diff --git a/classes.py b/classes.py index 0e2e611..e75ad6c 100644 --- a/classes.py +++ b/classes.py @@ -23,7 +23,7 @@ try: except ImportError: raise ImportError("PyLink requires ircmatch to function; please install it and try again.") -from . import world, utils, structures, __version__ +from . import world, utils, structures, conf, __version__ from .log import * ### Exceptions @@ -33,7 +33,7 @@ class ProtocolError(Exception): ### Internal classes (users, servers, channels) -class Irc(): +class Irc(utils.DeprecatedAttributesObject): """Base IRC object for PyLink.""" def __init__(self, netname, proto, conf): @@ -42,6 +42,11 @@ class Irc(): (a string), the name of the protocol module to use for this connection, and a configuration object. """ + self.deprecated_attributes = { + 'conf': 'Deprecated since 1.2; consider switching to conf.conf', + 'botdata': "Deprecated since 1.2; consider switching to conf.conf['bot']", + } + self.loghandlers = [] self.name = netname self.conf = conf @@ -76,7 +81,7 @@ class Irc(): Initializes any channel loggers defined for the current network. """ try: - channels = self.conf['logging']['channels'][self.name] + channels = conf.conf['logging']['channels'][self.name] except KeyError: # Not set up; just ignore. return @@ -101,7 +106,6 @@ class Irc(): (Re)sets an IRC object to its default state. This should be called when an IRC object is first created, and on every reconnection to a network. """ - self.botdata = self.conf['bot'] self.pingfreq = self.serverdata.get('pingfreq') or 90 self.pingtimeout = self.pingfreq * 3 @@ -301,7 +305,7 @@ class Irc(): self.servers[self.sid] = IrcServer(None, host, internal=True, desc=self.serverdata.get('serverdesc') - or self.botdata['serverdesc']) + or conf.conf['bot']['serverdesc']) log.info('(%s) Starting ping schedulers....', self.name) self.schedulePing() diff --git a/coremods/handlers.py b/coremods/handlers.py index 01224f8..2ff9208 100644 --- a/coremods/handlers.py +++ b/coremods/handlers.py @@ -75,7 +75,7 @@ def handle_whois(irc, source, command, args): # 3) +H is set, but whois_use_hideoper is disabled in config isHideOper = (irc.umodes.get('hideoper'), None) in user.modes if (not isHideOper) or (isHideOper and sourceisOper) or \ - (isHideOper and not irc.botdata.get('whois_use_hideoper', True)): + (isHideOper and not conf.conf['bot'].get('whois_use_hideoper', True)): # Let's be gramatically correct. (If the opertype starts with a vowel, # write "an Operator" instead of "a Operator") n = 'n' if user.opertype[0].lower() in 'aeiou' else '' diff --git a/plugins/fantasy.py b/plugins/fantasy.py index 9d18a33..c407d82 100644 --- a/plugins/fantasy.py +++ b/plugins/fantasy.py @@ -1,5 +1,5 @@ # fantasy.py: Adds FANTASY command support, to allow calling commands in channels -from pylinkirc import utils, world +from pylinkirc import utils, world, conf from pylinkirc.log import log def handle_fantasy(irc, source, command, args): @@ -9,7 +9,7 @@ def handle_fantasy(irc, source, command, args): # Break if the IRC network isn't ready. return - respondtonick = irc.botdata.get("respondtonick") + respondtonick = conf.conf['bot'].get("respondtonick") channel = args['target'] orig_text = args['text'] @@ -32,8 +32,8 @@ def handle_fantasy(irc, source, command, args): # Try to look up a prefix specific for this bot in # bot: prefixes: , falling back to the default prefix if not # specified. - prefixes = [irc.botdata.get('prefixes', {}).get(botname) or - irc.botdata.get('prefix')] + prefixes = [conf.conf['bot'].get('prefixes', {}).get(botname) or + conf.conf['bot'].get('prefix')] # If responding to nick is enabled, add variations of the current nick # to the prefix list: "," and ":" diff --git a/protocols/hybrid.py b/protocols/hybrid.py index a79bf93..88f328b 100644 --- a/protocols/hybrid.py +++ b/protocols/hybrid.py @@ -1,6 +1,6 @@ import time -from pylinkirc import utils +from pylinkirc import utils, conf from pylinkirc.log import log from pylinkirc.classes import * from pylinkirc.protocols.ts6 import * @@ -79,7 +79,7 @@ class HybridProtocol(TS6Protocol): f('CAPAB :TBURST DLN KNOCK UNDLN UNKLN KLN ENCAP IE EX HOPS CHW SVS CLUSTER EOB QS') f('SERVER %s 0 :%s' % (self.irc.serverdata["hostname"], - self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc'])) + self.irc.serverdata.get('serverdesc') or conf.conf['bot']['serverdesc'])) # send endburst now self.irc.send(':%s EOB' % (self.irc.sid,)) @@ -101,7 +101,7 @@ class HybridProtocol(TS6Protocol): uid = self.uidgen[server].next_uid() ts = ts or int(time.time()) - realname = realname or self.irc.botdata['realname'] + realname = realname or conf.conf['bot']['realname'] realhost = realhost or host raw_modes = self.irc.joinModes(modes) u = self.irc.users[uid] = IrcUser(nick, ts, uid, server, ident=ident, host=host, realname=realname, diff --git a/protocols/inspircd.py b/protocols/inspircd.py index 12db96f..1929e23 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -5,7 +5,7 @@ inspircd.py: InspIRCd 2.x protocol module for PyLink. import time import threading -from pylinkirc import utils +from pylinkirc import utils, conf from pylinkirc.classes import * from pylinkirc.log import log from pylinkirc.protocols.ts6_common import * @@ -47,7 +47,7 @@ class InspIRCdProtocol(TS6BaseProtocol): uid = self.uidgen[server].next_uid() ts = ts or int(time.time()) - realname = realname or self.irc.botdata['realname'] + realname = realname or conf.conf['bot']['realname'] realhost = realhost or host raw_modes = self.irc.joinModes(modes) u = self.irc.users[uid] = IrcUser(nick, ts, uid, server, ident=ident, host=host, realname=realname, @@ -351,7 +351,7 @@ class InspIRCdProtocol(TS6BaseProtocol): uplink = uplink or self.irc.sid name = name.lower() # "desc" defaults to the configured server description. - desc = desc or self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc'] + desc = desc or self.irc.serverdata.get('serverdesc') or conf.conf['bot']['serverdesc'] if sid is None: # No sid given; generate one! sid = self.sidgen.next_sid() assert len(sid) == 3, "Incorrect SID length" @@ -398,7 +398,7 @@ class InspIRCdProtocol(TS6BaseProtocol): host = self.irc.serverdata["hostname"] f('SERVER {host} {Pass} 0 {sid} :{sdesc}'.format(host=host, Pass=self.irc.serverdata["sendpass"], sid=self.irc.sid, - sdesc=self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc'])) + sdesc=self.irc.serverdata.get('serverdesc') or conf.conf['bot']['serverdesc'])) self._send(self.irc.sid, 'BURST %s' % ts) # InspIRCd sends VERSION data on link, instead of whenever requested by a client. diff --git a/protocols/nefarious.py b/protocols/nefarious.py index c137afa..14642ac 100644 --- a/protocols/nefarious.py +++ b/protocols/nefarious.py @@ -7,7 +7,7 @@ import struct from ipaddress import ip_address import time -from pylinkirc import utils, structures +from pylinkirc import utils, structures, conf from pylinkirc.classes import * from pylinkirc.log import log from pylinkirc.protocols.ircs2s_common import * @@ -274,7 +274,7 @@ class P10Protocol(IRCS2SProtocol): # Fill in all the values we need ts = ts or int(time.time()) - realname = realname or self.irc.botdata['realname'] + realname = realname or conf.conf['bot']['realname'] realhost = realhost or host raw_modes = self.irc.joinModes(modes) @@ -642,7 +642,7 @@ class P10Protocol(IRCS2SProtocol): # <- SERVER nefarious.midnight.vpn 1 1460673022 1460673239 J10 ABP]] +h6 :Nefarious2 test server uplink = uplink or self.irc.sid name = name.lower() - desc = desc or self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc'] + desc = desc or self.irc.serverdata.get('serverdesc') or conf.conf['bot']['serverdesc'] if sid is None: # No sid given; generate one! sid = self.sidgen.next_sid() @@ -764,7 +764,7 @@ class P10Protocol(IRCS2SProtocol): # Encode our SID using P10 Base64. self.irc.sid = sid = p10b64encode(self.irc.serverdata["sid"]) - desc = self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc'] + desc = self.irc.serverdata.get('serverdesc') or conf.conf['bot']['serverdesc'] # Enumerate modes, from https://github.com/evilnet/nefarious2/blob/master/doc/modes.txt cmodes = {'op': 'o', 'voice': 'v', 'private': 'p', 'secret': 's', 'moderated': 'm', diff --git a/protocols/ratbox.py b/protocols/ratbox.py index 38ad878..c9fb979 100644 --- a/protocols/ratbox.py +++ b/protocols/ratbox.py @@ -1,6 +1,6 @@ import time -from pylinkirc import utils +from pylinkirc import utils, conf from pylinkirc.log import log from pylinkirc.classes import * from pylinkirc.protocols.ts6 import * @@ -58,7 +58,7 @@ class RatboxProtocol(TS6Protocol): uid = self.uidgen[server].next_uid() ts = ts or int(time.time()) - realname = realname or self.irc.botdata['realname'] + realname = realname or conf.conf['bot']['realname'] raw_modes = self.irc.joinModes(modes) orig_realhost = realhost diff --git a/protocols/ts6.py b/protocols/ts6.py index 93cc984..ff9ac05 100644 --- a/protocols/ts6.py +++ b/protocols/ts6.py @@ -5,7 +5,7 @@ ts6.py: PyLink protocol module for TS6-based IRCds (charybdis, elemental-ircd). import time import re -from pylinkirc import utils +from pylinkirc import utils, conf from pylinkirc.classes import * from pylinkirc.log import log from pylinkirc.protocols.ts6_common import * @@ -46,7 +46,7 @@ class TS6Protocol(TS6BaseProtocol): # parameters: nickname, hopcount, nickTS, umodes, username, # visible hostname, IP address, UID, real hostname, account name, gecos ts = ts or int(time.time()) - realname = realname or self.irc.botdata['realname'] + realname = realname or conf.conf['bot']['realname'] realhost = realhost or host raw_modes = self.irc.joinModes(modes) u = self.irc.users[uid] = IrcUser(nick, ts, uid, server, ident=ident, host=host, realname=realname, @@ -338,7 +338,7 @@ class TS6Protocol(TS6BaseProtocol): f('CAPAB :QS ENCAP EX CHW IE KNOCK SAVE SERVICES TB EUID RSFNC EOPMOD SAVETS_100') f('SERVER %s 0 :%s' % (self.irc.serverdata["hostname"], - self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc'])) + self.irc.serverdata.get('serverdesc') or conf.conf['bot']['serverdesc'])) # Finally, end all the initialization with a PING - that's Charybdis' # way of saying end-of-burst :) diff --git a/protocols/ts6_common.py b/protocols/ts6_common.py index 539673f..2af2d39 100644 --- a/protocols/ts6_common.py +++ b/protocols/ts6_common.py @@ -5,7 +5,7 @@ ts6_common.py: Common base protocol class with functions shared by the UnrealIRC import string import time -from pylinkirc import utils, structures +from pylinkirc import utils, structures, conf from pylinkirc.classes import * from pylinkirc.log import log from pylinkirc.protocols.ircs2s_common import * @@ -260,7 +260,7 @@ class TS6BaseProtocol(IRCS2SProtocol): # -> :0AL SID test.server 1 0XY :some silly pseudoserver uplink = uplink or self.irc.sid name = name.lower() - desc = desc or self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc'] + desc = desc or self.irc.serverdata.get('serverdesc') or conf.conf['bot']['serverdesc'] if sid is None: # No sid given; generate one! sid = self.sidgen.next_sid() assert len(sid) == 3, "Incorrect SID length" diff --git a/protocols/unreal.py b/protocols/unreal.py index 06e5174..ff29767 100644 --- a/protocols/unreal.py +++ b/protocols/unreal.py @@ -7,7 +7,7 @@ import codecs import socket import re -from pylinkirc import utils +from pylinkirc import utils, conf from pylinkirc.classes import * from pylinkirc.log import log from pylinkirc.protocols.ts6_common import * @@ -73,7 +73,7 @@ class UnrealProtocol(TS6BaseProtocol): uid = self.uidgen[server].next_uid() ts = ts or int(time.time()) - realname = realname or self.irc.botdata['realname'] + realname = realname or conf.conf['bot']['realname'] realhost = realhost or host # Add +xt so that vHost cloaking always works. @@ -367,7 +367,7 @@ class UnrealProtocol(TS6BaseProtocol): # ESVID - Supports account names in services stamps instead of just the signon time. # AFAIK this doesn't actually affect services' behaviour? f('PROTOCTL SJOIN SJ3 NOQUIT NICKv2 VL UMODE2 PROTOCTL NICKIP EAUTH=%s SID=%s VHP ESVID' % (self.irc.serverdata["hostname"], self.irc.sid)) - sdesc = self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc'] + sdesc = self.irc.serverdata.get('serverdesc') or conf.conf['bot']['serverdesc'] f('SERVER %s 1 U%s-h6e-%s :%s' % (host, self.proto_ver, self.irc.sid, sdesc)) f('NETINFO 1 %s %s * 0 0 0 :%s' % (self.irc.start_ts, self.proto_ver, self.irc.serverdata.get("netname", self.irc.name))) self._send(self.irc.sid, 'EOS') diff --git a/utils.py b/utils.py index 64616bf..13d93b1 100644 --- a/utils.py +++ b/utils.py @@ -560,3 +560,17 @@ class IRCParser(argparse.ArgumentParser): def error(self, message): raise InvalidArgumentsError(message) + +class DeprecatedAttributesObject(): + """ + Object implementing deprecated attributes and warnings on access. + """ + + def __getattribute__(self, attr): + # Note: "self.deprecated_attributes" calls this too, so the != check is + # needed to prevent a recursive loop! + if attr != 'deprecated_attributes' and attr in self.deprecated_attributes: + log.warning('Attribute %s.%s is deprecated: %s' % (self.__class__.__name__, attr, + self.deprecated_attributes.get(attr))) + + return object.__getattribute__(self, attr)