mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-24 03:29:28 +01:00
Initial Clientbot stub, with very rudimentary user handling (#144)
This commit is contained in:
parent
1770058e1b
commit
c52d542ed8
121
protocols/clientbot.py
Normal file
121
protocols/clientbot.py
Normal file
@ -0,0 +1,121 @@
|
||||
import time
|
||||
|
||||
from pylinkirc import utils, conf
|
||||
from pylinkirc.log import log
|
||||
from pylinkirc.classes import Protocol, IrcUser, IrcServer
|
||||
|
||||
class ClientbotWrapperProtocol(Protocol):
|
||||
def __init__(self, irc):
|
||||
super().__init__(irc)
|
||||
|
||||
# FIXME: Grab this from 005 / RPL_ISUPPORT instead of hardcoding.
|
||||
self.casemapping = 'ascii'
|
||||
|
||||
self.caps = {}
|
||||
|
||||
# Initialize counter-based pseudo UID generators
|
||||
self.uidgen = utils.PUIDGenerator('PUID')
|
||||
self.sidgen = utils.PUIDGenerator('PSID')
|
||||
|
||||
def connect(self):
|
||||
"""Initializes a connection to a server."""
|
||||
ts = self.irc.start_ts
|
||||
f = self.irc.send
|
||||
|
||||
# TODO: fetch channel/user/prefix modes from RPL_ISUPPORT.
|
||||
#self.irc.prefixmodes = {'q': '~', 'a': '&', 'o': '@', 'h': '%', 'v': '+'}
|
||||
|
||||
# HACK: Replace the SID from the config options with our own.
|
||||
old_sid = self.irc.sid
|
||||
self.irc.sid = sid = self.sidgen.next_uid()
|
||||
self.irc.servers[sid] = self.irc.servers[old_sid]
|
||||
del self.irc.servers[old_sid]
|
||||
|
||||
sendpass = self.irc.serverdata.get("sendpass")
|
||||
if sendpass:
|
||||
f('PASS %s' % sendpass)
|
||||
|
||||
# This is a really gross hack to get the defined NICK/IDENT/HOST/GECOS.
|
||||
# But this connection stuff is done before any of the spawnClient stuff in
|
||||
# services_support fires.
|
||||
f('NICK %s' % (self.irc.serverdata.get('pylink_nick') or conf.conf["bot"].get("nick", "PyLink")))
|
||||
ident = self.irc.serverdata.get('pylink_ident') or conf.conf["bot"].get("ident", "pylink")
|
||||
f('USER %s %s 0.0.0.0 %s' % (ident, ident,
|
||||
# TODO: per net realnames or hostnames aren't implemented yet.
|
||||
conf.conf["bot"].get("realname", "PyLink Clientbot")))
|
||||
|
||||
def spawnClient(self, nick, ident='null', host='null', realhost=None, modes=set(),
|
||||
server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None,
|
||||
manipulatable=False):
|
||||
"""
|
||||
STUB: Pretends to spawn a new client with a subset of the given options.
|
||||
"""
|
||||
|
||||
uid = self.uidgen.next_uid()
|
||||
|
||||
ts = ts or int(time.time())
|
||||
realname = realname or ''
|
||||
log.debug('(%s) spawnClient stub called, saving nick %s as PUID %s', self.irc.name, nick, uid)
|
||||
u = self.irc.users[uid] = IrcUser(nick, ts, uid, ident=ident, host=host, realname=realname)
|
||||
log.debug('(%s) self.irc.users: %s', self.irc.name, self.irc.users)
|
||||
self.irc.servers[self.irc.sid].users.add(uid)
|
||||
return u
|
||||
|
||||
def spawnServer(self, name, sid=None, uplink=None, desc=None, endburst_delay=0):
|
||||
"""
|
||||
STUB: Pretends to spawn a new server with a subset of the given options.
|
||||
"""
|
||||
name = name.lower()
|
||||
sid = self.sidgen.next_sid()
|
||||
self.irc.servers[sid] = IrcServer(uplink, name)
|
||||
return sid
|
||||
|
||||
def join(self, *args):
|
||||
return
|
||||
|
||||
def ping(self, *args):
|
||||
return
|
||||
|
||||
def handle_events(self, data):
|
||||
"""Event handler for the RFC1459 (clientbot) protocol.
|
||||
"""
|
||||
data = data.split(" ")
|
||||
args = self.parsePrefixedArgs(data)
|
||||
sender = args[0]
|
||||
|
||||
# PyLink as a services framework expects UIDs and SIDs for everythiung. Since we connect
|
||||
# as a bot here, there's no explicit user introduction, so we're going to generate
|
||||
# pseudo-uids and pseudo-sids as we see prefixes.
|
||||
log.debug('(%s) handle_events: sender is %s', self.irc.name, sender)
|
||||
if '!' not in sender:
|
||||
# Sender is a server name.
|
||||
idsource = self._getSid(sender)
|
||||
if idsource not in self.irc.servers:
|
||||
idsource = self.spawnServer(sender)
|
||||
else:
|
||||
# Sender is a nick!user@host prefix. Split it into its relevant parts.
|
||||
nick, identhost = sender.split('!', 1)
|
||||
idsource = self.irc.nickToUid(nick)
|
||||
if not idsource:
|
||||
ident, host = identhost.split('@', 1)
|
||||
idsource = self.spawnClient(nick, ident, host).uid
|
||||
log.debug('(%s) handle_events: idsource is %s', self.irc.name, idsource)
|
||||
|
||||
command = args[1]
|
||||
args = args[2:]
|
||||
try:
|
||||
func = getattr(self, 'handle_'+command.lower())
|
||||
except AttributeError: # unhandled command
|
||||
pass
|
||||
else:
|
||||
parsed_args = func(idsource, command, args)
|
||||
if parsed_args is not None:
|
||||
return [idsource, command, parsed_args]
|
||||
|
||||
def handle_005(self, source, command, args):
|
||||
"""
|
||||
Handles 005 / RPL_ISUPPORT.
|
||||
"""
|
||||
return {'parse_as': 'ENDBURST'}
|
||||
|
||||
Class = ClientbotWrapperProtocol
|
18
utils.py
18
utils.py
@ -64,6 +64,24 @@ class IncrementalUIDGenerator():
|
||||
self.increment()
|
||||
return uid
|
||||
|
||||
class PUIDGenerator():
|
||||
"""
|
||||
Pseudo UID Generator module, using a prefix and a simple counter.
|
||||
"""
|
||||
|
||||
def __init__(self, prefix):
|
||||
self.prefix = prefix
|
||||
self.counter = 0
|
||||
|
||||
def next_uid(self):
|
||||
"""
|
||||
Generates the next PUID.
|
||||
"""
|
||||
uid = '%s@%s' % (self.prefix, self.counter)
|
||||
self.counter += 1
|
||||
return uid
|
||||
next_sid = next_uid
|
||||
|
||||
def add_cmd(func, name=None, **kwargs):
|
||||
"""Binds an IRC command function to the given command name."""
|
||||
world.services['pylink'].add_cmd(func, name=name, **kwargs)
|
||||
|
Loading…
Reference in New Issue
Block a user