.BANCHO. Use streams for public chat
This commit is contained in:
		@@ -89,4 +89,10 @@ class unknownStreamException(Exception):
 | 
			
		||||
	pass
 | 
			
		||||
 | 
			
		||||
class userTournamentException(Exception):
 | 
			
		||||
	pass
 | 
			
		||||
 | 
			
		||||
class userAlreadyInChannelException(Exception):
 | 
			
		||||
	pass
 | 
			
		||||
 | 
			
		||||
class userNotInChannelException(Exception):
 | 
			
		||||
	pass
 | 
			
		||||
@@ -656,7 +656,7 @@ def pp(fro, chan, message):
 | 
			
		||||
	pp = userUtils.getPP(token.userID, gameMode)
 | 
			
		||||
	return "You have {:,} pp".format(pp)
 | 
			
		||||
 | 
			
		||||
def updateBeatmap(fro, chan, to):
 | 
			
		||||
def updateBeatmap(fro, chan, message):
 | 
			
		||||
	try:
 | 
			
		||||
		# Run the command in PM only
 | 
			
		||||
		if chan.startswith("#"):
 | 
			
		||||
 
 | 
			
		||||
@@ -155,11 +155,13 @@ def channelJoinSuccess(userID, chan):
 | 
			
		||||
	return packetHelper.buildPacket(packetIDs.server_channelJoinSuccess, [[chan, dataTypes.STRING]])
 | 
			
		||||
 | 
			
		||||
def channelInfo(chan):
 | 
			
		||||
	if chan not in glob.channels.channels:
 | 
			
		||||
		return bytes()
 | 
			
		||||
	channel = glob.channels.channels[chan]
 | 
			
		||||
	return packetHelper.buildPacket(packetIDs.server_channelInfo, [
 | 
			
		||||
		[chan, dataTypes.STRING],
 | 
			
		||||
		[channel.name, dataTypes.STRING],
 | 
			
		||||
		[channel.description, dataTypes.STRING],
 | 
			
		||||
		[len(channel.connectedUsers), dataTypes.UINT16]
 | 
			
		||||
		[len(glob.streams.streams["chat/{}".format(chan)].clients), dataTypes.UINT16]
 | 
			
		||||
	])
 | 
			
		||||
 | 
			
		||||
def channelInfoEnd():
 | 
			
		||||
 
 | 
			
		||||
@@ -5,13 +5,13 @@ from objects import glob
 | 
			
		||||
 | 
			
		||||
def handle(userToken, _):
 | 
			
		||||
	# Get usertoken data
 | 
			
		||||
	userID = userToken.userID
 | 
			
		||||
	username = userToken.username
 | 
			
		||||
 | 
			
		||||
	# Remove user from users in lobby
 | 
			
		||||
	userToken.leaveStream("lobby")
 | 
			
		||||
 | 
			
		||||
	# Part lobby channel
 | 
			
		||||
	# Done automatically by the client
 | 
			
		||||
	chat.partChannel(channel="#lobby", token=userToken, kick=True)
 | 
			
		||||
 | 
			
		||||
	# Console output
 | 
			
		||||
 
 | 
			
		||||
@@ -27,44 +27,32 @@ def joinChannel(userID = 0, channel = "", token = None, toIRC = True):
 | 
			
		||||
				raise exceptions.userNotFoundException
 | 
			
		||||
		else:
 | 
			
		||||
			token = token
 | 
			
		||||
			userID = token.userID
 | 
			
		||||
 | 
			
		||||
		# Get usertoken data
 | 
			
		||||
		username = token.username
 | 
			
		||||
 | 
			
		||||
		# Normal channel, do check stuff
 | 
			
		||||
		# Make sure the channel exists
 | 
			
		||||
		if channel not in glob.channels.channels:
 | 
			
		||||
			raise exceptions.channelUnknownException
 | 
			
		||||
 | 
			
		||||
		# Check channel permissions
 | 
			
		||||
		channelObject = glob.channels.channels[channel]
 | 
			
		||||
		if channelObject.publicRead == False and token.admin == False:
 | 
			
		||||
			raise exceptions.channelNoPermissionsException
 | 
			
		||||
 | 
			
		||||
		# Add our userID to users in that channel
 | 
			
		||||
		channelObject.userJoin(userID)
 | 
			
		||||
			raise exceptions.channelUnknownException()
 | 
			
		||||
 | 
			
		||||
		# Add the channel to our joined channel
 | 
			
		||||
		token.joinChannel(channel)
 | 
			
		||||
 | 
			
		||||
		# Send channel joined (bancho). We use clientName here because of #multiplayer and #spectator channels
 | 
			
		||||
		token.enqueue(serverPackets.channelJoinSuccess(userID, channelObject.clientName))
 | 
			
		||||
		token.joinChannel(glob.channels.channels[channel])
 | 
			
		||||
 | 
			
		||||
		# Send channel joined (IRC)
 | 
			
		||||
		if glob.irc == True and toIRC == True:
 | 
			
		||||
			glob.ircServer.banchoJoinChannel(username, channel)
 | 
			
		||||
			glob.ircServer.banchoJoinChannel(token.username, channel)
 | 
			
		||||
 | 
			
		||||
		# Console output
 | 
			
		||||
		log.info("{} joined channel {}".format(username, channel))
 | 
			
		||||
		log.info("{} joined channel {}".format(token.username, channel))
 | 
			
		||||
 | 
			
		||||
		# IRC code return
 | 
			
		||||
		return 0
 | 
			
		||||
	except exceptions.channelNoPermissionsException:
 | 
			
		||||
		log.warning("{} attempted to join channel {}, but they have no read permissions".format(username, channel))
 | 
			
		||||
		log.warning("{} attempted to join channel {}, but they have no read permissions".format(token.username, channel))
 | 
			
		||||
		return 403
 | 
			
		||||
	except exceptions.channelUnknownException:
 | 
			
		||||
		log.warning("{} attempted to join an unknown channel ({})".format(username, channel))
 | 
			
		||||
		log.warning("{} attempted to join an unknown channel ({})".format(token.username, channel))
 | 
			
		||||
		return 403
 | 
			
		||||
	except exceptions.userAlreadyInChannelException:
 | 
			
		||||
		log.warning("User {} already in channel {}".format(token.username, channel))
 | 
			
		||||
		return 403
 | 
			
		||||
	except exceptions.userNotFoundException:
 | 
			
		||||
		log.warning("User not connected to IRC/Bancho")
 | 
			
		||||
@@ -82,6 +70,10 @@ def partChannel(userID = 0, channel = "", token = None, toIRC = True, kick = Fal
 | 
			
		||||
	:return: 0 if joined or other IRC code in case of error. Needed only on IRC-side
 | 
			
		||||
	"""
 | 
			
		||||
	try:
 | 
			
		||||
		# Make sure the client is not drunk and sends partChannel when closing a PM tab
 | 
			
		||||
		if not channel.startswith("#"):
 | 
			
		||||
			return
 | 
			
		||||
 | 
			
		||||
		# Get token if not defined
 | 
			
		||||
		if token is None:
 | 
			
		||||
			token = glob.tokens.getTokenFromUserID(userID)
 | 
			
		||||
@@ -90,10 +82,6 @@ def partChannel(userID = 0, channel = "", token = None, toIRC = True, kick = Fal
 | 
			
		||||
				raise exceptions.userNotFoundException
 | 
			
		||||
		else:
 | 
			
		||||
			token = token
 | 
			
		||||
			userID = token.userID
 | 
			
		||||
 | 
			
		||||
		# Get usertoken data
 | 
			
		||||
		username = token.username
 | 
			
		||||
 | 
			
		||||
		# Determine internal/client name if needed
 | 
			
		||||
		# (toclient is used clientwise for #multiplayer and #spectator channels)
 | 
			
		||||
@@ -113,12 +101,22 @@ def partChannel(userID = 0, channel = "", token = None, toIRC = True, kick = Fal
 | 
			
		||||
 | 
			
		||||
		# Make sure the channel exists
 | 
			
		||||
		if channel not in glob.channels.channels:
 | 
			
		||||
			raise exceptions.channelUnknownException
 | 
			
		||||
			raise exceptions.channelUnknownException()
 | 
			
		||||
 | 
			
		||||
		# Make sure the user is in the channel
 | 
			
		||||
		if channel not in token.joinedChannels:
 | 
			
		||||
			raise exceptions.userNotInChannelException()
 | 
			
		||||
 | 
			
		||||
		# Part channel (token-side and channel-side)
 | 
			
		||||
		channelObject = glob.channels.channels[channel]
 | 
			
		||||
		token.partChannel(channel)
 | 
			
		||||
		channelObject.userPart(userID)
 | 
			
		||||
		token.partChannel(channelObject)
 | 
			
		||||
 | 
			
		||||
		# Delete temporary channel if everyone left
 | 
			
		||||
		if "chat/{}".format(channelObject.name) in glob.streams.streams:
 | 
			
		||||
			sas = len(glob.streams.streams["chat/{}".format(channelObject.name)].clients)
 | 
			
		||||
			print(str(sas - 1))
 | 
			
		||||
			if channelObject.temp == True and sas - 1 == 0:
 | 
			
		||||
				glob.channels.removeChannel(channelObject.name)
 | 
			
		||||
 | 
			
		||||
		# Force close tab if needed
 | 
			
		||||
		# NOTE: Maybe always needed, will check later
 | 
			
		||||
@@ -127,16 +125,19 @@ def partChannel(userID = 0, channel = "", token = None, toIRC = True, kick = Fal
 | 
			
		||||
 | 
			
		||||
		# IRC part
 | 
			
		||||
		if glob.irc == True and toIRC == True:
 | 
			
		||||
			glob.ircServer.banchoPartChannel(username, channel)
 | 
			
		||||
			glob.ircServer.banchoPartChannel(token.username, channel)
 | 
			
		||||
 | 
			
		||||
		# Console output
 | 
			
		||||
		log.info("{} parted channel {} ({})".format(username, channel, channelClient))
 | 
			
		||||
		log.info("{} parted channel {} ({})".format(token.username, channel, channelClient))
 | 
			
		||||
 | 
			
		||||
		# Return IRC code
 | 
			
		||||
		return 0
 | 
			
		||||
	except exceptions.channelUnknownException:
 | 
			
		||||
		log.warning("{} attempted to part an unknown channel ({})".format(username, channel))
 | 
			
		||||
		log.warning("{} attempted to part an unknown channel ({})".format(token.username, channel))
 | 
			
		||||
		return 403
 | 
			
		||||
	except exceptions.userNotInChannelException:
 | 
			
		||||
		log.warning("{} attempted to part {}, but he's not in that channel".format(token.username, channel))
 | 
			
		||||
		return 442
 | 
			
		||||
	except exceptions.userNotFoundException:
 | 
			
		||||
		log.warning("User not connected to IRC/Bancho")
 | 
			
		||||
		return 442	# idk
 | 
			
		||||
@@ -153,7 +154,7 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
			
		||||
	:return: 0 if joined or other IRC code in case of error. Needed only on IRC-side
 | 
			
		||||
	"""
 | 
			
		||||
	try:
 | 
			
		||||
		tokenString = ""
 | 
			
		||||
		#tokenString = ""
 | 
			
		||||
		# Get token object if not passed
 | 
			
		||||
		if token is None:
 | 
			
		||||
			token = glob.tokens.getTokenFromUsername(fro)
 | 
			
		||||
@@ -162,11 +163,7 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
			
		||||
		else:
 | 
			
		||||
			# token object alredy passed, get its string and its username (fro)
 | 
			
		||||
			fro = token.username
 | 
			
		||||
			tokenString = token.token
 | 
			
		||||
 | 
			
		||||
		# Set some variables
 | 
			
		||||
		userID = token.userID
 | 
			
		||||
		username = token.username
 | 
			
		||||
			#tokenString = token.token
 | 
			
		||||
 | 
			
		||||
		# Make sure this is not a tournament client
 | 
			
		||||
		if token.tournament:
 | 
			
		||||
@@ -185,7 +182,7 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
			
		||||
		toClient = to
 | 
			
		||||
		if to == "#spectator":
 | 
			
		||||
			if token.spectating is None:
 | 
			
		||||
				s = userID
 | 
			
		||||
				s = token.userID
 | 
			
		||||
			else:
 | 
			
		||||
				s = token.spectatingUserID
 | 
			
		||||
			to = "#spect_{}".format(s)
 | 
			
		||||
@@ -203,7 +200,7 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
			
		||||
		message = glob.chatFilters.filterMessage(message)
 | 
			
		||||
 | 
			
		||||
		# Build packet bytes
 | 
			
		||||
		packet = serverPackets.sendMessage(username, toClient, message)
 | 
			
		||||
		packet = serverPackets.sendMessage(token.username, toClient, message)
 | 
			
		||||
 | 
			
		||||
		# Send the message
 | 
			
		||||
		isChannel = to.startswith("#")
 | 
			
		||||
@@ -211,35 +208,28 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
			
		||||
			# CHANNEL
 | 
			
		||||
			# Make sure the channel exists
 | 
			
		||||
			if to not in glob.channels.channels:
 | 
			
		||||
				raise exceptions.channelUnknownException
 | 
			
		||||
				raise exceptions.channelUnknownException()
 | 
			
		||||
 | 
			
		||||
			# Make sure the channel is not in moderated mode
 | 
			
		||||
			if glob.channels.channels[to].moderated == True and token.admin == False:
 | 
			
		||||
				raise exceptions.channelModeratedException
 | 
			
		||||
				raise exceptions.channelModeratedException()
 | 
			
		||||
 | 
			
		||||
			# Make sure we have write permissions
 | 
			
		||||
			if glob.channels.channels[to].publicWrite == False and token.admin == False:
 | 
			
		||||
				raise exceptions.channelNoPermissionsException
 | 
			
		||||
				raise exceptions.channelNoPermissionsException()
 | 
			
		||||
 | 
			
		||||
			# Everything seems fine, build recipients list and send packet
 | 
			
		||||
			recipients = glob.channels.channels[to].connectedUsers[:]
 | 
			
		||||
			for key, value in glob.tokens.tokens.items():
 | 
			
		||||
				# Skip our client and irc clients
 | 
			
		||||
				if key == tokenString or value.irc == True:
 | 
			
		||||
					continue
 | 
			
		||||
				# Send to this client if it's connected to the channel
 | 
			
		||||
				if value.userID in recipients:
 | 
			
		||||
					value.enqueue(packet)
 | 
			
		||||
			glob.streams.broadcast("chat/{}".format(to), packet, but=[token.token])
 | 
			
		||||
		else:
 | 
			
		||||
			# USER
 | 
			
		||||
			# Make sure recipient user is connected
 | 
			
		||||
			recipientToken = glob.tokens.getTokenFromUsername(to)
 | 
			
		||||
			if recipientToken is None:
 | 
			
		||||
				raise exceptions.userNotFoundException
 | 
			
		||||
				raise exceptions.userNotFoundException()
 | 
			
		||||
 | 
			
		||||
			# Make sure the recipient is not a tournament client
 | 
			
		||||
			if recipientToken.tournament:
 | 
			
		||||
				raise exceptions.userTournamentException()
 | 
			
		||||
			#if recipientToken.tournament:
 | 
			
		||||
			#	raise exceptions.userTournamentException()
 | 
			
		||||
 | 
			
		||||
			# Make sure the recipient is not restricted or we are FokaBot
 | 
			
		||||
			if recipientToken.restricted == True and fro.lower() != "fokabot":
 | 
			
		||||
@@ -248,7 +238,7 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
			
		||||
			# TODO: Make sure the recipient has not disabled PMs for non-friends or he's our friend
 | 
			
		||||
 | 
			
		||||
			# Away check
 | 
			
		||||
			if recipientToken.awayCheck(userID):
 | 
			
		||||
			if recipientToken.awayCheck(token.userID):
 | 
			
		||||
				sendMessage(to, fro, "\x01ACTION is away: {message}\x01".format(code=chr(int(1)), message=recipientToken.awayMessage))
 | 
			
		||||
 | 
			
		||||
			# Check message templates (mods/admins only)
 | 
			
		||||
@@ -263,38 +253,38 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
			
		||||
			glob.ircServer.banchoMessage(fro, to, message)
 | 
			
		||||
 | 
			
		||||
		# Spam protection (ignore FokaBot)
 | 
			
		||||
		if userID > 999:
 | 
			
		||||
		if token.userID > 999:
 | 
			
		||||
			token.spamProtection()
 | 
			
		||||
 | 
			
		||||
		# Fokabot message
 | 
			
		||||
		if isChannel == True or to.lower() == "fokabot":
 | 
			
		||||
			fokaMessage = fokabot.fokabotResponse(username, to, message)
 | 
			
		||||
			fokaMessage = fokabot.fokabotResponse(token.username, to, message)
 | 
			
		||||
			if fokaMessage:
 | 
			
		||||
				sendMessage("FokaBot", to if isChannel else fro, fokaMessage)
 | 
			
		||||
 | 
			
		||||
		# File and discord logs (public chat only)
 | 
			
		||||
		if to.startswith("#") and not (message.startswith("\x01ACTION is playing") and to.startswith("#spect_")):
 | 
			
		||||
			log.chat("{fro} @ {to}: {message}".format(fro=username, to=to, message=str(message.encode("utf-8"))))
 | 
			
		||||
			glob.schiavo.sendChatlog("**{fro} @ {to}:** {message}".format(fro=username, to=to, message=str(message.encode("utf-8"))[2:-1]))
 | 
			
		||||
			log.chat("{fro} @ {to}: {message}".format(fro=token.username, to=to, message=str(message.encode("utf-8"))))
 | 
			
		||||
			glob.schiavo.sendChatlog("**{fro} @ {to}:** {message}".format(fro=token.username, to=to, message=str(message.encode("utf-8"))[2:-1]))
 | 
			
		||||
		return 0
 | 
			
		||||
	except exceptions.userSilencedException:
 | 
			
		||||
		token.enqueue(serverPackets.silenceEndTime(token.getSilenceSecondsLeft()))
 | 
			
		||||
		log.warning("{} tried to send a message during silence".format(username))
 | 
			
		||||
		log.warning("{} tried to send a message during silence".format(token.username))
 | 
			
		||||
		return 404
 | 
			
		||||
	except exceptions.channelModeratedException:
 | 
			
		||||
		log.warning("{} tried to send a message to a channel that is in moderated mode ({})".format(username, to))
 | 
			
		||||
		log.warning("{} tried to send a message to a channel that is in moderated mode ({})".format(token.username, to))
 | 
			
		||||
		return 404
 | 
			
		||||
	except exceptions.channelUnknownException:
 | 
			
		||||
		log.warning("{} tried to send a message to an unknown channel ({})".format(username, to))
 | 
			
		||||
		log.warning("{} tried to send a message to an unknown channel ({})".format(token.username, to))
 | 
			
		||||
		return 403
 | 
			
		||||
	except exceptions.channelNoPermissionsException:
 | 
			
		||||
		log.warning("{} tried to send a message to channel {}, but they have no write permissions".format(username, to))
 | 
			
		||||
		log.warning("{} tried to send a message to channel {}, but they have no write permissions".format(token.username, to))
 | 
			
		||||
		return 404
 | 
			
		||||
	except exceptions.userRestrictedException:
 | 
			
		||||
		log.warning("{} tried to send a message {}, but the recipient is in restricted mode".format(username, to))
 | 
			
		||||
		log.warning("{} tried to send a message {}, but the recipient is in restricted mode".format(token.username, to))
 | 
			
		||||
		return 404
 | 
			
		||||
	except exceptions.userTournamentException:
 | 
			
		||||
		log.warning("{} tried to send a message {}, but the recipient is a tournament client".format(username, to))
 | 
			
		||||
		log.warning("{} tried to send a message {}, but the recipient is a tournament client".format(token.username, to))
 | 
			
		||||
		return 404
 | 
			
		||||
	except exceptions.userNotFoundException:
 | 
			
		||||
		log.warning("User not connected to IRC/Bancho")
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -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))
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -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)
 | 
			
		||||
							
								
								
									
										10
									
								
								pep.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								pep.py
									
									
									
									
									
								
							@@ -154,6 +154,11 @@ if __name__ == "__main__":
 | 
			
		||||
			consoleHelper.printColored("[!] Error while loading chat filters. Make sure there is a filters.txt file present", bcolors.RED)
 | 
			
		||||
			raise
 | 
			
		||||
 | 
			
		||||
		# Start fokabot
 | 
			
		||||
		consoleHelper.printNoNl("> Connecting FokaBot... ")
 | 
			
		||||
		fokabot.connect()
 | 
			
		||||
		consoleHelper.printDone()
 | 
			
		||||
 | 
			
		||||
		# Initialize chat channels
 | 
			
		||||
		print("> Initializing chat channels... ")
 | 
			
		||||
		glob.channels.loadChannels()
 | 
			
		||||
@@ -165,11 +170,6 @@ if __name__ == "__main__":
 | 
			
		||||
		glob.streams.add("lobby")
 | 
			
		||||
		consoleHelper.printDone()
 | 
			
		||||
 | 
			
		||||
		# Start fokabot
 | 
			
		||||
		consoleHelper.printNoNl("> Connecting FokaBot... ")
 | 
			
		||||
		fokabot.connect()
 | 
			
		||||
		consoleHelper.printDone()
 | 
			
		||||
 | 
			
		||||
		# Initialize user timeout check loop
 | 
			
		||||
		consoleHelper.printNoNl("> Initializing user timeout check loop... ")
 | 
			
		||||
		glob.tokens.usersTimeoutCheckLoop()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user