.BANCHO. Use streams for public chat

This commit is contained in:
Nyo
2016-12-11 11:07:35 +01:00
parent c4a6c84cec
commit 44545c3bcb
11 changed files with 133 additions and 119 deletions

View File

@@ -18,7 +18,6 @@ class channel:
self.publicWrite = publicWrite
self.moderated = False
self.temp = temp
self.connectedUsers = [999] # Fokabot is always connected to every channels (otherwise it doesn't show up in IRC users list)
self.hidden = hidden
# Client name (#spectator/#multiplayer)
@@ -28,27 +27,7 @@ class channel:
elif self.name.startswith("#multi_"):
self.clientName = "#multiplayer"
def userJoin(self, userID):
"""
Add a user to connected users
:param userID:
:return:
"""
if userID not in self.connectedUsers:
self.connectedUsers.append(userID)
def userPart(self, userID):
"""
Remove a user from connected users
:param userID:
:return:
"""
if userID in self.connectedUsers:
self.connectedUsers.remove(userID)
# Remove temp channels if empty or there's only fokabot connected
l = len(self.connectedUsers)
if self.temp == True and ((l == 0) or (l == 1 and 999 in self.connectedUsers)):
glob.channels.removeChannel(self.name)
# Make Foka join the channel
fokaToken = glob.tokens.getTokenFromUserID(999)
if fokaToken is not None:
fokaToken.joinChannel(self)

View File

@@ -1,4 +1,5 @@
from common.log import logUtils as log
from constants import serverPackets
from objects import channel
from objects import glob
@@ -34,6 +35,7 @@ class channelList:
:param hidden: if True, thic channel won't be shown in channels list
:return:
"""
glob.streams.add("chat/{}".format(name))
self.channels[name] = channel.channel(name, description, publicRead, publicWrite, temp, hidden)
log.info("Created channel {}".format(name))
@@ -47,6 +49,7 @@ class channelList:
"""
if name in self.channels:
return False
glob.streams.add("chat/{}".format(name))
self.channels[name] = channel.channel(name, "Chat", True, True, True, True)
log.info("Created temp channel {}".format(name))
@@ -60,5 +63,8 @@ class channelList:
if name not in self.channels:
log.debug("{} is not in channels list".format(name))
return
glob.streams.broadcast("chat/{}".format(name), serverPackets.channelKicked(name))
glob.streams.dispose("chat/{}".format(name))
glob.streams.remove("chat/{}".format(name))
self.channels.pop(name)
log.info("Removed channel {}".format(name))

View File

@@ -5,6 +5,7 @@ import uuid
from common.constants import gameModes, actions
from common.log import logUtils as log
from common.ripple import userUtils
from constants import exceptions
from constants import serverPackets
from events import logoutEvent
from helpers import chatHelper as chat
@@ -98,7 +99,12 @@ class token:
:param bytes: (packet) bytes to enqueue
"""
# TODO: reduce max queue size
# Never enqueue for IRC clients or Foka
if self.irc or self.userID < 999:
return
# Avoid memory leaks
if len(bytes_) < 10 * 10 ** 6:
self.queue += bytes_
else:
@@ -108,23 +114,30 @@ class token:
"""Resets the queue. Call when enqueued packets have been sent"""
self.queue = bytes()
def joinChannel(self, channel):
def joinChannel(self, channelObject):
"""
Add channel to joined channels list
Join a channel
:param channel: channel name
:param channelObject: channel object
:raises: exceptions.userAlreadyInChannelException()
exceptions.channelNoPermissionsException()
"""
if channel not in self.joinedChannels:
self.joinedChannels.append(channel)
if channelObject.name in self.joinedChannels:
raise exceptions.userAlreadyInChannelException()
if channelObject.publicRead == False and self.admin == False:
raise exceptions.channelNoPermissionsException()
self.joinedChannels.append(channelObject.name)
self.joinStream("chat/{}".format(channelObject.name))
self.enqueue(serverPackets.channelJoinSuccess(self.userID, channelObject.clientName))
def partChannel(self, channel):
def partChannel(self, channelObject):
"""
Remove channel from joined channels list
:param channel: channel name
:param channelObject: channel object
"""
if channel in self.joinedChannels:
self.joinedChannels.remove(channel)
self.joinedChannels.remove(channelObject.name)
self.leaveStream("chat/{}".format(channelObject.name))
def setLocation(self, latitude, longitude):
"""
@@ -233,7 +246,7 @@ class token:
chat.partChannel(token=self, channel="#spect_{}".format(self.spectatingUserID), kick=True)
# Console output
log.info("{} is no longer spectating {}".format(self.username, self.spectatingUserID))
log.info("{} is no longer spectating {}. Current spectators: {}".format(self.username, self.spectatingUserID, hostToken.spectators))
# Set our spectating user to 0
self.spectating = None

View File

@@ -43,15 +43,29 @@ class stream:
log.info("{} has left stream {}".format(token, self.name))
self.clients.remove(token)
def broadcast(self, data):
def broadcast(self, data, but=None):
"""
Send some data to all clients connected to this stream
Send some data to all (or some) clients connected to this stream
:param data: data to send
:param but: array of tokens to ignore. Default: None (send to everyone)
:return:
"""
if but is None:
but = []
for i in self.clients:
if i in glob.tokens.tokens:
if i not in but:
glob.tokens.tokens[i].enqueue(data)
else:
self.removeClient(token=i)
def dispose(self):
"""
Tell every client in this stream to leave the stream
:return:
"""
for i in self.clients:
if i in glob.tokens.tokens:
glob.tokens.tokens[i].enqueue(data)
else:
self.removeClient(token=i)
glob.tokens.tokens[i].leaveStream(self.name)

View File

@@ -1,6 +1,7 @@
from objects import stream
from objects import glob
# TODO: use *args and **kwargs
class streamList:
def __init__(self):
self.streams = {}
@@ -55,25 +56,28 @@ class streamList:
return
self.streams[streamName].removeClient(client=client, token=token)
def broadcast(self, streamName, data):
def broadcast(self, streamName, data, but=None):
"""
Send some data to all clients in a stream
:param streamName: stream name
:param data: data to send
:param but: array of tokens to ignore. Default: None (send to everyone)
:return:
"""
if streamName not in self.streams:
return
self.streams[streamName].broadcast(data)
self.streams[streamName].broadcast(data, but)
'''def getClients(self, streamName):
def dispose(self, streamName, *args, **kwargs):
"""
Get all clients in a stream
Call `dispose` on `streamName`
:param streamName: name of the stream
:param args:
:param kwargs:
:return:
"""
if streamName not in self.streams:
return
return self.streams[streamName].clients'''
self.streams[streamName].dispose(*args, **kwargs)