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()
|
self.increment()
|
||||||
return uid
|
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):
|
def add_cmd(func, name=None, **kwargs):
|
||||||
"""Binds an IRC command function to the given command name."""
|
"""Binds an IRC command function to the given command name."""
|
||||||
world.services['pylink'].add_cmd(func, name=name, **kwargs)
|
world.services['pylink'].add_cmd(func, name=name, **kwargs)
|
||||||
|
Loading…
Reference in New Issue
Block a user