Removed IRC Bot support (Faulty and obsolete)

This commit is contained in:
Uriziel 2014-04-19 11:30:28 +02:00
parent 2a736d613f
commit 36d2b432b9
3 changed files with 33 additions and 348 deletions

View File

@ -1,190 +0,0 @@
from twisted.words.protocols import irc
from twisted.internet import reactor, protocol
from syncplay import utils
class ColorCode(object):
NORMAL = chr(15)
BOLD = chr(2)
RED = chr(3) + "5"
BLUE = chr(3) + "12"
'''
@author Uriziel
@author HarHar
'''
class Bot(object):
def __init__(self, server='irc.rizon.net', port=6667, nick='SyncBot', channel='', functions=[]):
'''
functions - dict of functions that can be used from the bot:
functions = {
"pause": lambda setBy, state: None,
"getRooms": lambda: ["",],
"setRoomPosition": lambda setBy, seconds 0: None,
"getRoomPosition": lambda room: 0,
"getRoomUsers": lambda room: [{"nick": "", "file": "", "duration": 0},],
"isRoomPaused": lambda room: True,
}
'''
self.factory = BotFactory(self, channel.encode("ascii", "replace"), nick.encode("ascii", "replace"))
self.proto = None
self.server = server
self.port = port
self._functions = functions
def start(self):
reactor.connectTCP(self.server, self.port, self.factory)
def registerProto(self, proto):
self.proto = proto
def takeAction(self, action, user):
if(action == "help" or action == "h"):
v = (ColorCode.BOLD, ColorCode.NORMAL)
return "{}Available commands:{} !rooms / !roominfo [room] / !playpause (or aliases: !r, !ri [room], !p).".format(*v)
elif(action == "rooms" or action == "r"):
return self.__listRooms()
elif(action.startswith("roominfo") or action.startswith("ri")):
return self.__getRoomInfo(action)
elif(action == "playpause" or action == "p"):
return self.__playpause(user)
else:
return "{}Error!{} Unknown command".format(ColorCode.RED, ColorCode.NORMAL)
def sp_joined(self, who, room):
msg ="{}<{}>{} has joined the room: `{}`".format(ColorCode.BOLD, who, ColorCode.NORMAL, room)
self._sendChanMessage(msg)
def sp_left(self, who, room):
msg ="{}<{}>{} has left the room: `{}`".format(ColorCode.BOLD, who, ColorCode.NORMAL, room)
self._sendChanMessage(msg)
def sp_unpaused(self, who, room):
msg ="{}<{}>{} has unpaused (in room `{}`)".format(ColorCode.BOLD, who, ColorCode.NORMAL, room)
self._sendChanMessage(msg)
def sp_paused(self, who, room):
msg ="{}<{}>{} has paused (in room `{}`)".format(ColorCode.BOLD, who, ColorCode.NORMAL, room)
self._sendChanMessage(msg)
def sp_fileplaying(self, who, filename, room):
if filename:
msg ="{}<{}>{} is playing {} (in room `{}`)".format(ColorCode.BOLD, who, ColorCode.NORMAL, filename, room)
self._sendChanMessage(msg)
def sp_seek(self, who, fromTime, toTime, room):
v = (ColorCode.BOLD, who, ColorCode.NORMAL, utils.formatTime(fromTime), utils.formatTime(toTime), room,)
msg ="{}<{}>{} has jumped from {} to {} (in room `{}`)".format(*v)
self._sendChanMessage(msg)
def __playpause(self, user):
rooms = self._functions["getRooms"]()
for room in rooms:
users = self._functions["getRoomUsers"](room)
for u in users:
if u['nick'] == user:
paused = self._functions["isRoomPaused"](room)
self._functions["pause"](user, not (paused))
return "<{}> {} the room: `{}`".format(ColorCode.BOLD, user, ColorCode.NORMAL, "paused" if paused else "unpaused", room)
return "{}Error!{} Your nick was not found on the server.".format(ColorCode.RED, ColorCode.NORMAL)
def __listRooms(self):
rooms = self._functions["getRooms"]()
if(len(rooms) >= 3):
v = ("`, `".join(rooms[:-1]), rooms[-1])
return "Currently the Syncplay server hosts viewing sessions as follows: `{}` and ultimately `{}`.".format(*v)
elif(len(rooms) == 2):
return "Currently the Syncplay server hosts viewing sessions as follows: `{}` and `{}`.".format(rooms[0], rooms[1])
elif(len(rooms) == 1):
return "Currently the Syncplay server hosts one viewing session called `{}`".format(rooms[0])
else:
return "{}Notice:{} No rooms have been found on server".format(ColorCode.BLUE, ColorCode.NORMAL)
def __getListOfFiles(self, users):
files = []
for u in users:
if [u["file"], u["duration"]] not in files:
files.append([u["file"], u["duration"]])
return files
def __getUserlist(self, room):
users = self._functions["getRoomUsers"](room)
position = self._functions["getRoomPosition"](room)
paused = "Paused" if self._functions["isRoomPaused"](room) else "Playing"
files = self.__getListOfFiles(users)
message = ""
for f in files:
if (f[0] == None):
message += "No file:\n"
else:
v = (
ColorCode.BOLD, paused, ColorCode.NORMAL,
utils.formatTime(position),
utils.formatTime(f[1]), f[0]
)
message += "{}<{}>{} [{}/{}] {}\n".format(*v)
u = [u['nick'] for u in users if f[0] == u['file'] and f[1] == u['duration']]
if (len(u) > 1):
message += "Played by: <{}> and <{}>.\n".format(">, <".join(u[:-1]), u[-1])
else:
message += "Played by {} alone.\n".format(u[0])
return message
def __getRoomInfo(self, action):
if(action.startswith("rooms")):
room = action.replace("rooms", "", 1)
else:
room = action.replace("ri", "", 1)
room = room.strip()
if('' == room):
return "{}Usage:{} !roominfo [room]".format(ColorCode.BLUE, ColorCode.NORMAL)
rooms = self._functions["getRooms"]()
if(not room in rooms):
return "{}Error!{} Room does not exists.".format(ColorCode.RED, ColorCode.NORMAL)
message = self.__getUserlist(room)
return message
def _sendChanMessage(self, msg):
if(self.proto):
self.proto.sendChanMessage(msg)
class BotProto(irc.IRCClient):
def __init__(self, bot, nickname):
self.nickname = nickname
self.bot = bot
self.bot.registerProto(self)
def signedOn(self):
self.join(self.factory.channel)
def joined(self, channel):
self.msg(channel, "Syncplay IRC Bot - I'm all fired up!")
def privmsg(self, user, channel, msg):
user = user.split('!', 1)[0]
isActionMessage = channel == self.nickname or msg.startswith(self.nickname + ":") or msg.startswith("!") or msg.startswith(".")
if isActionMessage:
action = msg.replace(self.nickname + ":", "")
action = msg.lstrip(".!")
reply = self.bot.takeAction(action.lower(), user)
for line in reply.splitlines():
self.msg(channel, line)
def sendChanMessage(self, msg):
self.msg(self.factory.channel, msg)
class BotFactory(protocol.ClientFactory):
def __init__(self, bot, channel, nickname):
self.channel = channel
self.nickname = nickname
self.bot = bot
def buildProtocol(self, addr):
p = BotProto(self.bot, self.nickname)
p.factory = self
return p
def clientConnectionLost(self, connector, reason):
connector.connect()
def clientConnectionFailed(self, connector, reason):
print "IRC Bot connection failed, please check your configuration"

View File

@ -1,4 +1,4 @@
#coding:utf8 # coding:utf8
import hashlib import hashlib
from twisted.internet import task, reactor from twisted.internet import task, reactor
from twisted.internet.protocol import Factory from twisted.internet.protocol import Factory
@ -11,11 +11,10 @@ from syncplay.messages import getMessage
import codecs import codecs
import os import os
from string import Template from string import Template
from ircBot import Bot as IRCBot
import argparse import argparse
class SyncFactory(Factory): class SyncFactory(Factory):
def __init__(self, password = '', motdFilePath = None, httpReplyFilePath= None, ircConfig = None, ircVerbose = False): def __init__(self, password='', motdFilePath=None, httpReplyFilePath=None):
print getMessage("en", "welcome-server-notification").format(syncplay.version) print getMessage("en", "welcome-server-notification").format(syncplay.version)
if(password): if(password):
password = hashlib.md5(password).hexdigest() password = hashlib.md5(password).hexdigest()
@ -25,52 +24,6 @@ class SyncFactory(Factory):
self._rooms = {} self._rooms = {}
self._roomStates = {} self._roomStates = {}
self._roomUpdate = threading.RLock() self._roomUpdate = threading.RLock()
self.ircVerbose = ircVerbose
ircConnectionData = self.readIrcConfig(ircConfig)
if(ircConnectionData):
self.setupIRCBot(ircConnectionData)
def readIrcConfig(self, ircConfig):
if(ircConfig and os.path.isfile(ircConfig)):
cfg = codecs.open(ircConfig, "r", "utf-8-sig").read()
cfg = cfg.splitlines()
ircConnectionData = {
"server": "",
"port": "",
"nick": "",
"channel": ""
}
for line in cfg:
if("irc.server: " in line):
ircConnectionData['server'] = line.split(": ")[1]
elif("irc.serverPort: " in line):
ircConnectionData['port'] = int(line.split(": ")[1])
elif("irc.botName: " in line):
ircConnectionData['nick'] = line.split(": ")[1]
elif("irc.channel: " in line):
ircConnectionData['channel'] = line.split(": ")[1]
return ircConnectionData
def setupIRCBot(self, ircConnectionData):
botFunctions = {
"pause": self.ircPauseRoom,
"getRooms": self.getRooms,
"setRoomPosition": self.ircSetRoomPosition,
"getRoomPosition": self.getRoomPosition,
"getRoomUsers": self.getRoomUsernames,
"isRoomPaused": self.isRoomPaused,
}
try:
self.ircBot = IRCBot(
ircConnectionData['server'],
ircConnectionData['port'],
ircConnectionData['nick'],
ircConnectionData['channel'],
botFunctions,
)
self.ircBot.start()
except:
print "IRC Bot could not be started, please check your configuration"
def buildProtocol(self, addr): def buildProtocol(self, addr):
return SyncServerProtocol(self) return SyncServerProtocol(self)
@ -100,15 +53,13 @@ class SyncFactory(Factory):
reactor.callLater(0.1, watcher.scheduleSendState) reactor.callLater(0.1, watcher.scheduleSendState)
l = lambda w: w.sendUserSetting(username, roomName, None, {"joined": True}) l = lambda w: w.sendUserSetting(username, roomName, None, {"joined": True})
self.broadcast(watcherProtocol, l) self.broadcast(watcherProtocol, l)
if(self.ircVerbose):
self.ircBot.sp_joined(username, roomName)
def getWatcher(self, watcherProtocol): def getWatcher(self, watcherProtocol):
for room in self._rooms.itervalues(): for room in self._rooms.itervalues():
if(room.has_key(watcherProtocol)): if(room.has_key(watcherProtocol)):
return room[watcherProtocol] return room[watcherProtocol]
def getAllWatchers(self, watcherProtocol): #TODO: Optimize me def getAllWatchers(self, watcherProtocol): # TODO: Optimize me
watchers = {} watchers = {}
for room in self._rooms.itervalues(): for room in self._rooms.itervalues():
for watcher in room.itervalues(): for watcher in room.itervalues():
@ -139,7 +90,7 @@ class SyncFactory(Factory):
def getMotd(self, userIp, username, room, clientVersion): def getMotd(self, userIp, username, room, clientVersion):
oldClient = False oldClient = False
if constants.WARN_OLD_CLIENTS: if constants.WARN_OLD_CLIENTS:
if int(clientVersion.replace(".","")) < int(constants.RECENT_CLIENT_THRESHOLD.replace(".","")): if int(clientVersion.replace(".", "")) < int(constants.RECENT_CLIENT_THRESHOLD.replace(".", "")):
oldClient = True oldClient = True
if(self._motdFilePath and os.path.isfile(self._motdFilePath)): if(self._motdFilePath and os.path.isfile(self._motdFilePath)):
tmpl = codecs.open(self._motdFilePath, "r", "utf-8-sig").read() tmpl = codecs.open(self._motdFilePath, "r", "utf-8-sig").read()
@ -147,7 +98,7 @@ class SyncFactory(Factory):
try: try:
motd = Template(tmpl).substitute(args) motd = Template(tmpl).substitute(args)
if oldClient: if oldClient:
motdwarning = getMessage("en","new-syncplay-available-motd-message").format(clientVersion) motdwarning = getMessage("en", "new-syncplay-available-motd-message").format(clientVersion)
motd = "{}\n{}".format(motdwarning, motd) motd = "{}\n{}".format(motdwarning, motd)
return motd if len(motd) < constants.SERVER_MAX_TEMPLATE_LENGTH else getMessage("en", "server-messed-up-motd-too-long").format(constants.SERVER_MAX_TEMPLATE_LENGTH, len(motd)) return motd if len(motd) < constants.SERVER_MAX_TEMPLATE_LENGTH else getMessage("en", "server-messed-up-motd-too-long").format(constants.SERVER_MAX_TEMPLATE_LENGTH, len(motd))
except ValueError: except ValueError:
@ -164,7 +115,7 @@ class SyncFactory(Factory):
else: else:
return getMessage("en", "server-default-http-reply") return getMessage("en", "server-default-http-reply")
def sendState(self, watcherProtocol, doSeek = False, forcedUpdate = False): def sendState(self, watcherProtocol, doSeek=False, forcedUpdate=False):
watcher = self.getWatcher(watcherProtocol) watcher = self.getWatcher(watcherProtocol)
if(not watcher): if(not watcher):
return return
@ -201,16 +152,6 @@ class SyncFactory(Factory):
self._roomStates[watcher.room]["setBy"] = setter.name self._roomStates[watcher.room]["setBy"] = setter.name
self._roomStates[watcher.room]["lastUpdate"] = setter.lastUpdate self._roomStates[watcher.room]["lastUpdate"] = setter.lastUpdate
def __notifyIrcBot(self, position, paused, doSeek, watcher, oldPosition, pauseChanged):
if (self.ircVerbose):
if (paused and pauseChanged):
self.ircBot.sp_paused(watcher.name, watcher.room)
elif (not paused and pauseChanged):
self.ircBot.sp_unpaused(watcher.name, watcher.room)
if (doSeek and position):
self.ircBot.sp_seek(watcher.name, oldPosition, position, watcher.room)
def updateWatcherState(self, watcherProtocol, position, paused, doSeek, messageAge): def updateWatcherState(self, watcherProtocol, position, paused, doSeek, messageAge):
watcher = self.getWatcher(watcherProtocol) watcher = self.getWatcher(watcherProtocol)
if(not watcher): if(not watcher):
@ -227,7 +168,6 @@ class SyncFactory(Factory):
self.__updatePositionState(position, doSeek or pauseChanged, watcher) self.__updatePositionState(position, doSeek or pauseChanged, watcher)
forceUpdate = self.__shouldServerForceUpdateOnRoom(pauseChanged, doSeek) forceUpdate = self.__shouldServerForceUpdateOnRoom(pauseChanged, doSeek)
if(forceUpdate): if(forceUpdate):
self.__notifyIrcBot(position, paused, doSeek, watcher, oldPosition, pauseChanged)
l = lambda w: self.sendState(w, doSeek, forceUpdate) l = lambda w: self.sendState(w, doSeek, forceUpdate)
self.broadcastRoom(watcher.watcherProtocol, l) self.broadcastRoom(watcher.watcherProtocol, l)
@ -240,8 +180,6 @@ class SyncFactory(Factory):
self._removeWatcherFromTheRoom(watcherProtocol) self._removeWatcherFromTheRoom(watcherProtocol)
watcher.deactivate() watcher.deactivate()
self._deleteRoomIfEmpty(watcher.room) self._deleteRoomIfEmpty(watcher.room)
if(self.ircVerbose):
self.ircBot.sp_left(watcher.name, watcher.room)
def watcherGetUsername(self, watcherProtocol): def watcherGetUsername(self, watcherProtocol):
return self.getWatcher(watcherProtocol).name return self.getWatcher(watcherProtocol).name
@ -271,8 +209,6 @@ class SyncFactory(Factory):
watcher.file = file_ watcher.file = file_
l = lambda w: w.sendUserSetting(watcher.name, watcher.room, watcher.file, None) l = lambda w: w.sendUserSetting(watcher.name, watcher.room, watcher.file, None)
self.broadcast(watcherProtocol, l) self.broadcast(watcherProtocol, l)
if(self.ircVerbose):
self.ircBot.sp_fileplaying(watcher.name, watcher.file['name'], watcher.room)
def broadcastRoom(self, sender, what): def broadcastRoom(self, sender, what):
room = self._rooms[self.watcherGetRoom(sender)] room = self._rooms[self.watcherGetRoom(sender)]
@ -287,65 +223,6 @@ class SyncFactory(Factory):
for receiver in room: for receiver in room:
what(receiver) what(receiver)
def _findUserByUsername(self, username):
with self._roomUpdate:
for room in self._rooms.itervalues():
for user in room.itervalues():
if user.name == username:
return user
def ircPauseRoom(self, setBy, paused):
user = self._findUserByUsername(setBy)
if(user):
with self._roomUpdate:
if(self._roomStates[user.room]['paused'] != paused):
self._roomStates[user.room]['paused'] = paused
self._roomStates[user.room]['setBy'] = "IRC: " + setBy
if(paused):
self.ircBot.sp_paused("IRC: " + user.name, user.room)
elif(not paused):
self.ircBot.sp_unpaused("IRC: " + user.name, user.room)
l = lambda w: self.sendState(w, False, 0, True)
self.broadcastRoom(user.watcherProtocol, l)
def getRooms(self):
return self._rooms.keys()
def getRoomPosition(self, room):
with self._roomUpdate:
if room in self._roomStates:
return self._roomStates[room]["position"]
def ircSetRoomPosition(self, setBy, time):
user = self._findUserByUsername(setBy)
if(user):
with self._roomUpdate:
oldPosition = self._roomStates[user.room]['paused']
if(oldPosition - time > 1):
self._roomStates[user.room]['paused'] = time
self._roomStates[user.room]['setBy'] = "IRC: " + setBy
self.ircBot.sp_seek(user.name, oldPosition, time, user.room)
l = lambda w: self.sendState(w, True, 0, True)
self.broadcastRoom(user.watcherProtocol, l)
def getRoomUsernames(self, room):
l = []
with self._roomUpdate:
if room in self._rooms:
for user in self._rooms[room].itervalues():
if(user.file):
l.append({'nick': user.name, 'file': user.file['name'], "duration": user.file['duration']})
else:
l.append({'nick': user.name, 'file': None, "duration": None})
return l
def isRoomPaused(self, room):
with self._roomUpdate:
if room in self._roomStates:
return self._roomStates[room]["paused"]
class SyncIsolatedFactory(SyncFactory): class SyncIsolatedFactory(SyncFactory):
def broadcast(self, sender, what): def broadcast(self, sender, what):
self.broadcastRoom(sender, what) self.broadcastRoom(sender, what)
@ -420,5 +297,3 @@ class ConfigurationGetter(object):
self._argparser.add_argument('--isolate-rooms', action='store_true', help=getMessage("en", "server-isolate-room-argument")) self._argparser.add_argument('--isolate-rooms', action='store_true', help=getMessage("en", "server-isolate-room-argument"))
self._argparser.add_argument('--motd-file', metavar='file', type=str, nargs='?', help=getMessage("en", "server-motd-argument")) self._argparser.add_argument('--motd-file', metavar='file', type=str, nargs='?', help=getMessage("en", "server-motd-argument"))
self._argparser.add_argument('--http-reply-file', metavar='file', type=str, nargs='?', help=getMessage("en", "server-http-reply-argument")) self._argparser.add_argument('--http-reply-file', metavar='file', type=str, nargs='?', help=getMessage("en", "server-http-reply-argument"))
self._argparser.add_argument('--irc-verbose', action='store_true', help=getMessage("en", "server-irc-verbose"))
self._argparser.add_argument('--irc-config-file', metavar='file', type=str, nargs='?', help=getMessage("en", "server-irc-config"))

View File

@ -13,7 +13,7 @@ argsGetter = ConfigurationGetter()
args = argsGetter.getConfiguration() args = argsGetter.getConfiguration()
if(not args.isolate_rooms): if(not args.isolate_rooms):
reactor.listenTCP(int(args.port), SyncFactory(args.password, args.motd_file, args.http_reply_file, args.irc_config_file, args.irc_verbose)) reactor.listenTCP(int(args.port), SyncFactory(args.password, args.motd_file, args.http_reply_file))
else: else:
reactor.listenTCP(int(args.port), SyncIsolatedFactory(args.password, args.motd_file, args.http_reply_file, args.irc_config_file, args.irc_verbose)) reactor.listenTCP(int(args.port), SyncIsolatedFactory(args.password, args.motd_file, args.http_reply_file))
reactor.run() reactor.run()