Added initial IRC bot support
Fucking miracles, how do they work.
This commit is contained in:
parent
95d698a5ed
commit
d7bd7af2b7
@ -110,6 +110,8 @@ en = {
|
|||||||
"server-messed-up-motd-too-long": "Message of the Day is too long - maximum of {} chars, {} given.",
|
"server-messed-up-motd-too-long": "Message of the Day is too long - maximum of {} chars, {} given.",
|
||||||
"server-http-reply-argument": "path to file from which http reply will be fetched",
|
"server-http-reply-argument": "path to file from which http reply will be fetched",
|
||||||
"server-default-http-reply": "This server should not be requested with your browser, but with Syncplay software available from http://syncplay.pl",
|
"server-default-http-reply": "This server should not be requested with your browser, but with Syncplay software available from http://syncplay.pl",
|
||||||
|
"server-irc-verbose": "Should server actively report changes in rooms",
|
||||||
|
"server-irc-config": "Path to irc bot config files",
|
||||||
|
|
||||||
#Server errors
|
#Server errors
|
||||||
"unknown-command-server-error" : "Unknown command {}", #message
|
"unknown-command-server-error" : "Unknown command {}", #message
|
||||||
|
|||||||
@ -12,9 +12,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
|
||||||
|
|
||||||
class SyncFactory(Factory):
|
class SyncFactory(Factory):
|
||||||
def __init__(self, password = '', motdFilePath = None, httpReplyFilePath= None):
|
def __init__(self, password = '', motdFilePath = None, httpReplyFilePath= None, ircConfig = None, ircVerbose = False):
|
||||||
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()
|
||||||
@ -24,6 +25,45 @@ 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): #TODO:
|
||||||
|
if(ircConfig and os.path.isfile(ircConfig)):
|
||||||
|
cfg = codecs.open(ircConfig, "r", "utf-8-sig").read()
|
||||||
|
cfg = cfg.splitlines()
|
||||||
|
if(len(cfg) == 7):
|
||||||
|
ircConnectionData = {}
|
||||||
|
ircConnectionData['server'] = cfg[0]
|
||||||
|
ircConnectionData['serverPassword'] = cfg[1]
|
||||||
|
ircConnectionData['port'] = int(cfg[2])
|
||||||
|
ircConnectionData['nick'] = cfg[3]
|
||||||
|
ircConnectionData['nickservPass'] = cfg[4]
|
||||||
|
ircConnectionData['channelPassword'] = cfg[5]
|
||||||
|
ircConnectionData['channel'] = cfg[6]
|
||||||
|
return ircConnectionData
|
||||||
|
|
||||||
|
def setupIRCBot(self, ircConnectionData):
|
||||||
|
botFunctions = [
|
||||||
|
self.ircPauseRoom,
|
||||||
|
self.getRooms,
|
||||||
|
self.getRoomPosition,
|
||||||
|
self.ircSetRoomPosition,
|
||||||
|
self.getRoomUsernames,
|
||||||
|
self.isRoomPaused,
|
||||||
|
]
|
||||||
|
self.ircBot = IRCBot(
|
||||||
|
ircConnectionData['server'],
|
||||||
|
ircConnectionData['serverPassword'],
|
||||||
|
ircConnectionData['port'],
|
||||||
|
ircConnectionData['nick'],
|
||||||
|
ircConnectionData['nickservPass'],
|
||||||
|
ircConnectionData['channel'],
|
||||||
|
ircConnectionData['channelPassword'],
|
||||||
|
botFunctions,
|
||||||
|
)
|
||||||
|
|
||||||
def buildProtocol(self, addr):
|
def buildProtocol(self, addr):
|
||||||
return SyncServerProtocol(self)
|
return SyncServerProtocol(self)
|
||||||
@ -54,6 +94,8 @@ 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():
|
||||||
@ -157,6 +199,7 @@ class SyncFactory(Factory):
|
|||||||
self.__updateWatcherPing(latencyCalculation, watcher)
|
self.__updateWatcherPing(latencyCalculation, watcher)
|
||||||
watcher.lastUpdate = time.time()
|
watcher.lastUpdate = time.time()
|
||||||
if(watcher.file):
|
if(watcher.file):
|
||||||
|
oldPosition = self._roomStates[watcher.room]["position"]
|
||||||
if(position is not None):
|
if(position is not None):
|
||||||
self.__updatePositionState(position, doSeek, watcher)
|
self.__updatePositionState(position, doSeek, watcher)
|
||||||
pauseChanged = False
|
pauseChanged = False
|
||||||
@ -164,6 +207,13 @@ class SyncFactory(Factory):
|
|||||||
pauseChanged = self.__updatePausedState(paused, watcher)
|
pauseChanged = self.__updatePausedState(paused, watcher)
|
||||||
forceUpdate = self.__shouldServerForceUpdateOnRoom(pauseChanged, doSeek)
|
forceUpdate = self.__shouldServerForceUpdateOnRoom(pauseChanged, doSeek)
|
||||||
if(forceUpdate):
|
if(forceUpdate):
|
||||||
|
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, watcher.room, oldPosition, position)
|
||||||
l = lambda w: self.sendState(w, doSeek, watcher.latency, forceUpdate)
|
l = lambda w: self.sendState(w, doSeek, watcher.latency, forceUpdate)
|
||||||
self.broadcastRoom(watcher.watcherProtocol, l)
|
self.broadcastRoom(watcher.watcherProtocol, l)
|
||||||
|
|
||||||
@ -177,7 +227,9 @@ class SyncFactory(Factory):
|
|||||||
watcher.deactivate()
|
watcher.deactivate()
|
||||||
self._deleteRoomIfEmpty(watcher.room)
|
self._deleteRoomIfEmpty(watcher.room)
|
||||||
print getMessage("en", "client-left-server-notification").format(watcher.name)
|
print getMessage("en", "client-left-server-notification").format(watcher.name)
|
||||||
|
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
|
||||||
|
|
||||||
@ -206,6 +258,8 @@ 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)]
|
||||||
@ -220,6 +274,54 @@ 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:
|
||||||
|
self._roomStates[user.room]['paused'] = paused
|
||||||
|
self._roomStates[user.room]['setBy'] = "IRC: " + setBy
|
||||||
|
l = lambda w: self.sendState(w, False, user.latency, 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:
|
||||||
|
self._roomStates[user.room]['paused'] = time
|
||||||
|
self._roomStates[user.room]['setBy'] = "IRC: " + setBy
|
||||||
|
l = lambda w: self.sendState(w, True, user.latency, 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():
|
||||||
|
l.append({'nick': user.name, 'file': user.file['name'], "length": user.file['duration']})
|
||||||
|
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)
|
||||||
|
|||||||
@ -208,3 +208,5 @@ class ServerConfigurationGetter(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"))
|
||||||
@ -9,7 +9,7 @@ from syncplay.ui.ConfigurationGetter import ServerConfigurationGetter
|
|||||||
argsGetter = ServerConfigurationGetter()
|
argsGetter = ServerConfigurationGetter()
|
||||||
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))
|
reactor.listenTCP(int(args.port), SyncFactory(args.password, args.motd_file, args.http_reply_file, args.irc_config_file, args.irc_verbose))
|
||||||
else:
|
else:
|
||||||
reactor.listenTCP(int(args.port), SyncIsolatedFactory(args.password, args.motd_file, args.http_reply_file))
|
reactor.listenTCP(int(args.port), SyncIsolatedFactory(args.password, args.motd_file, args.http_reply_file, args.irc_config_file, args.irc_verbose))
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user