Created
May 30, 2014 18:54
-
-
Save Justasic/e6af83fbc705e8d202b8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from twisted.internet.protocol import Protocol, Factory | |
from twisted.internet import reactor, protocol | |
from twisted.protocols.basic import LineReceiver | |
from twisted.python import log | |
import sys, time | |
class Channel(): | |
def __init__(self, name, ctime, modes): | |
self.name = name | |
if not ctime: | |
self.ctime = int(time.time()) | |
else: | |
self.ctime = ctime | |
self.modes = modes | |
self.users = [] | |
def AddUser(self, user): | |
self.users.append(user) | |
def RemoveUser(self, user): | |
del self.users[self.users.index(user)] | |
class User(): | |
def __init__(self, server, UID, ctime, nick, host, vhost, ident, ip, ts, modes, real): | |
self.server = server | |
self.UUID = UID | |
self.ctime = ctime | |
self.nick = nick | |
self.host = host | |
self.vhost = vhost | |
self.ident = ident | |
self.ip = ip | |
self.ts = ts | |
self.modes = modes | |
self.real = real | |
class Server(): | |
def __init__(self, host, passwd, wut, SID, desc): | |
self.host = host | |
self.passwd = passwd | |
self.wut = wut | |
self.SID = SID | |
self.desc = desc | |
self.channels = {} | |
self.users = {} | |
class PseudoClient(): | |
def __init__(self, factory, UID, nick, host, ident, real, modes): | |
self.factory = factory | |
self.UUID = UID | |
self.nick = nick | |
self.host = host | |
self.ident = ident | |
self.real = real | |
# the mode 'I' is for pseudoclients only | |
self.modes = modes + "Ik" | |
self.timestamp = int(time.time()) | |
def SendJoin(self, c): | |
# Send the join message | |
self.factory.SendNumeric("FJOIN %s %s %s :,%s" % (c.name, c.ctime, c.modes, self.UUID)) | |
def SendIntroduction(self): | |
self.factory.SendNumeric("UID %s %d %s %s %s %s 0.0.0.0 %d +%s :%s" % | |
(self.UUID, | |
self.timestamp, | |
self.nick, | |
self.host, | |
self.host, | |
self.ident, | |
self.timestamp, | |
self.modes, | |
self.real | |
)) | |
def SendMessage(self, c, message): | |
log.msg("< :%s PRIVMSG %s :%s" % (self.UUID, c.name, message)) | |
self.factory.sendLine(":%s PRIVMSG %s :%s" % (self.UUID, c.name, message)) | |
servers = {} | |
linked_server = None | |
class CommandHandler(): | |
def __init__(self, _command, _proto): | |
self.proto = _proto | |
self.factory = _proto.factory | |
self._command = _command | |
commandargs = [] | |
command, commandargs = self.ParseCommandString(_command) | |
self.HandleCommand(command, commandargs) | |
def ParseCommandString(self, _command): | |
# Get the command by itself | |
cmd = _command.split(':') | |
command = cmd[0].strip() | |
try: | |
commandargs = cmd[1].strip().split() | |
except: | |
commandargs = None | |
#log.msg("> ", command, commandargs) | |
log.msg("> ", _command) | |
return command, commandargs | |
def HandleCommand(self, command, commandargs): | |
# If a command was received then process it, otherwise skip to the command arguments | |
# and handle the :UID based commands there | |
if command.strip(): | |
cmd = command.split() | |
# FIXME: Check version here | |
if cmd[0] == "CAPAB": | |
# Get the capabilities from the other server | |
if cmd[1] == "START": | |
self.sendCAPAB() | |
# Okay, we've sent the shit we support, now do a netburst | |
elif cmd[1] == "END": | |
self.sendServer() | |
# We received a server from somewhere. | |
if cmd[0] == "SERVER": | |
# Add the server to the list | |
s = Server(cmd[1], cmd[2], cmd[3], cmd[4], " ".join(commandargs)) | |
servers[s.SID] = s | |
global linked_server | |
linked_server = s | |
# Continue to the netburst now | |
self.SendNumeric("BURST %d" % (int(time.time() + 125))) | |
self.SendNumeric("VERSION :Bot %s :Whatever bot 1.0.0" % self.factory.server) | |
# If we're sending via SID, this will almost always be true | |
if commandargs: | |
if commandargs[1] == "BURST": | |
if self.proto.isSyncing: | |
self.SendNumeric("ENDBURST") | |
if commandargs[1] == "ENDBURST": | |
self.proto.isSyncing = False | |
self.proto.serverSynced() | |
if commandargs[1] == "PING": | |
self.SendNumeric("PONG %s %s" % (commandargs[3], commandargs[2])) | |
# We're adding another server to the list | |
if commandargs[1] == "SERVER": | |
desc = self._command.split(':')[2] | |
#def __init__(self, host, passwd, wut, SID, desc): | |
s = Server(commandargs[2], commandargs[3], commandargs[4], commandargs[5], desc) | |
servers[s.SID] = s | |
#log.msg("NEW SERVER!", commandargs, desc) | |
if commandargs[1] == "UID": | |
# Add another user to the server. | |
server = servers[commandargs[0]] | |
uuid = commandargs[2] | |
ctime = commandargs[3] | |
nick = commandargs[4] | |
host = commandargs[5] | |
vhost = commandargs[6] | |
ident = commandargs[7] | |
ip = commandargs[8] | |
ts = commandargs[9] | |
modes = commandargs[10] | |
desc = self._command.split(':')[2] | |
u = User(server, uuid, ctime, nick, host, vhost, ident, ip, ts, modes, desc) | |
server.users[uuid] = u | |
if commandargs[1] == "FJOIN": | |
server = servers[commandargs[0]] | |
name = commandargs[2] | |
ctime = commandargs[3] | |
modes = commandargs[4] | |
# Create the new channel | |
c = Channel(name, ctime, modes) | |
# Get all the users joined in the channel | |
_users = self._command.split(':')[2].split(',') | |
# Lookup all the users | |
for u in _users: | |
if not u: | |
continue | |
u_s = u.split(' ') | |
uuid = u_s[0] | |
if 1 in u_s: | |
op = u_s[1] | |
else: | |
op = None | |
user = self.proto.FindUser(uuid) | |
if user: | |
c.AddUser(user) | |
server.channels[name] = c | |
def sendServer(self): | |
server = self.factory.server | |
pw = self.factory.sendpass | |
sid = self.factory.SID | |
# command name pw ? SID :Description | |
self.Send("SERVER %s %s 0 %s :Test Bot that links here" % (server, pw, sid)) | |
def sendCAPAB(self): | |
self.Send("CAPAB START 1202") | |
self.Send("CAPAB CAPABILITIES :PROTOCOL=1202") | |
self.Send("CAPAB END") | |
def Send(self, line): | |
log.msg("< %s" % line) | |
self.proto.sendLine(line) | |
def SendNumeric(self, line): | |
self.Send(":%s %s" % (self.factory.SID, line)) | |
# The Inspircd Protocol handling class | |
class InspircdProto(LineReceiver): | |
def __init__(self, factory): | |
self.factory = factory | |
self.connectionValid = False | |
self.isSyncing = True; | |
self.delimiter = '\n' | |
self.currentuid = 000000 | |
# See: https://github.com/inspircd/inspircd/blob/master/src/server.cpp#L89 | |
def genNextUUID(self): | |
self.currentuid += 1 | |
# Rollover | |
if self.currentuid == 1000000: | |
self.currentuid = 0 | |
return "%s%06d" % (self.factory.SID, self.currentuid) | |
def connectionMade(self): | |
log.startLogging(sys.stdout) | |
log.msg("Successfully connected to %s." % self.addr.host) | |
reactor.callLater(45, self.sendPing) | |
def connectionLost(self, reason): | |
log.msg("Lost connection to %s." % self.addr.host) | |
pass | |
def lineReceived(self, data): | |
""" Default handler for all incoming data """ | |
if not data.strip(): | |
# If the entered data is empty, ignore it | |
return | |
CommandHandler(data, self) | |
def serverSynced(self): | |
log.msg("Servers synced!"); | |
self.bot1 = PseudoClient(self, self.genNextUUID(), "herp", "d.derp.com", "derp", "herp derp bot", "") | |
self.bot1.SendIntroduction() | |
c = linked_server.channels['#Computers'] | |
self.bot1.SendJoin(c) | |
self.bot1.SendMessage(c, "Y'all're niggas.") | |
def FindUser(self, uuid): | |
if not uuid: | |
return None | |
# Iterate over all servers | |
for sid, s in servers.items(): | |
# iterate over all users in that server | |
for uid, u in s.users.items(): | |
# If the uuids match, we found our user. | |
if uid == uuid: | |
return u | |
return None | |
def SendNumeric(self, line): | |
log.msg("< :%s %s" % (self.factory.SID, line)) | |
self.sendLine(":%s %s" % (self.factory.SID, line)) | |
def sendPing(self): | |
self.SendNumeric("PING %s %s" % (self.factory.SID, linked_server.SID)) | |
reactor.callLater(45, self.sendPing) | |
def sendQuit(self, reason): | |
self.SendNumeric("SQUIT: %s" % reason) | |
self.transport.loseConnection() | |
def sendError(self, error): | |
self.sendLine("ERROR: %s" % reason) | |
self.transport.loseConnection() | |
class InspircFactory(protocol.ClientFactory): | |
def __init__(self, SID, server, sendpass): | |
self.sendpass = sendpass | |
self.server = server | |
self.SID = SID | |
def buildProtocol(self, addr): | |
p = InspircdProto(self) | |
p.addr = addr | |
return p | |
def clientConnectionLost(self, connector, reason): | |
"""If we get disconnected, reconnect to server.""" | |
connector.connect() | |
def clientConnectionFailed(self, connector, reason): | |
print ("connection failed:", reason) | |
reactor.stop() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from twisted.application import service, internet | |
from twisted.web import static, server | |
#import Bot, TelnetServer | |
import inspircd | |
#channel = ["#Test"] | |
#channel = "#Test" | |
host = "15.0.1.10" | |
SID = "52R" | |
server = "justasic.vemnet.us" | |
pw = "polarbears" | |
port = 7000 | |
application = service.Application("BasicINSPBot") | |
#tcpservice = TelnetServer.SubScribeFactory() | |
#botservice = Bot.BotFactory(channel, tcpservice) | |
inspservice = inspircd.InspircFactory(SID, server, pw) | |
service = internet.TCPClient(host, port, inspservice) | |
#listenservice = internet.TCPServer(7050, tcpservice) | |
#listenservice.setServiceParent(application) | |
service.setServiceParent(application) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment