.BANCHO. Add IRC support, internal changes
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
from objects import glob
|
||||
|
||||
class channel:
|
||||
"""
|
||||
A chat channel
|
||||
@@ -10,15 +12,7 @@ class channel:
|
||||
moderated -- bool
|
||||
"""
|
||||
|
||||
name = ""
|
||||
description = ""
|
||||
connectedUsers = []
|
||||
|
||||
publicRead = False
|
||||
publicWrite = False
|
||||
moderated = False
|
||||
|
||||
def __init__(self, __name, __description, __publicRead, __publicWrite):
|
||||
def __init__(self, __name, __description, __publicRead, __publicWrite, temp):
|
||||
"""
|
||||
Create a new chat channel object
|
||||
|
||||
@@ -26,13 +20,23 @@ class channel:
|
||||
__description -- channel description
|
||||
__publicRead -- bool, if true channel can be read by everyone, if false it can be read only by mods/admins
|
||||
__publicWrite -- bool, same as public read but relative to write permissions
|
||||
temp -- if True, channel will be deleted when there's no one in the channel. Optional. Default = False.
|
||||
"""
|
||||
|
||||
self.name = __name
|
||||
self.description = __description
|
||||
self.publicRead = __publicRead
|
||||
self.publicWrite = __publicWrite
|
||||
self.connectedUsers = []
|
||||
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)
|
||||
|
||||
# Client name (#spectator/#multiplayer)
|
||||
self.clientName = self.name
|
||||
if self.name.startswith("#spect_"):
|
||||
self.clientName = "#spectator"
|
||||
elif self.name.startswith("#multi_"):
|
||||
self.clientName = "#multiplayer"
|
||||
|
||||
|
||||
def userJoin(self, __userID):
|
||||
@@ -53,9 +57,13 @@ class channel:
|
||||
__userID -- user ID that left the channel
|
||||
"""
|
||||
|
||||
connectedUsers = self.connectedUsers
|
||||
if __userID in connectedUsers:
|
||||
connectedUsers.remove(__userID)
|
||||
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)
|
||||
|
||||
|
||||
def getConnectedUsers(self):
|
||||
@@ -64,7 +72,6 @@ class channel:
|
||||
|
||||
return -- connectedUsers list
|
||||
"""
|
||||
|
||||
return self.connectedUsers
|
||||
|
||||
|
||||
@@ -74,5 +81,4 @@ class channel:
|
||||
|
||||
return -- connected users number
|
||||
"""
|
||||
|
||||
return len(self.connectedUsers)
|
||||
|
@@ -1,5 +1,6 @@
|
||||
from objects import glob
|
||||
from objects import channel
|
||||
from helpers import logHelper as log
|
||||
|
||||
class channelList:
|
||||
"""
|
||||
@@ -27,14 +28,40 @@ class channelList:
|
||||
self.addChannel(i["name"], i["description"], publicRead, publicWrite)
|
||||
|
||||
|
||||
def addChannel(self, __name, __description, __publicRead, __publicWrite):
|
||||
def addChannel(self, name, description, publicRead, publicWrite, temp = False):
|
||||
"""
|
||||
Add a channel object to channels dictionary
|
||||
|
||||
__name -- channel name
|
||||
__description -- channel description
|
||||
__publicRead -- bool, if true channel can be read by everyone, if false it can be read only by mods/admins
|
||||
__publicWrite -- bool, same as public read but relative to write permissions
|
||||
name -- channel name
|
||||
description -- channel description
|
||||
publicRead -- bool, if true channel can be read by everyone, if false it can be read only by mods/admins
|
||||
publicWrite -- bool, same as public read but relative to write permissions
|
||||
temp -- if True, channel will be deleted when there's no one in the channel. Optional. Default = False.
|
||||
"""
|
||||
self.channels[name] = channel.channel(name, description, publicRead, publicWrite, temp)
|
||||
log.info("Created channel {}".format(name))
|
||||
|
||||
self.channels[__name] = channel.channel(__name, __description, __publicRead, __publicWrite)
|
||||
|
||||
def addTempChannel(self, name):
|
||||
"""
|
||||
Add a temporary channel (like #spectator or #multiplayer), gets deleted when there's no one in the channel
|
||||
|
||||
name -- channel name
|
||||
return -- True if channel was created, False if failed
|
||||
"""
|
||||
if name in self.channels:
|
||||
return False
|
||||
self.channels[name] = channel.channel(name, "Chat", True, True, True)
|
||||
log.info("Created temp channel {}".format(name))
|
||||
|
||||
def removeChannel(self, name):
|
||||
"""
|
||||
Removes a channel from channels list
|
||||
|
||||
name -- channel name
|
||||
"""
|
||||
if name not in self.channels:
|
||||
log.debug("{} is not in channels list".format(name))
|
||||
return
|
||||
self.channels.pop(name)
|
||||
log.info("Removed channel {}".format(name))
|
||||
|
@@ -9,6 +9,8 @@ from raven import Client
|
||||
try:
|
||||
with open("version") as f:
|
||||
VERSION = f.read()
|
||||
if VERSION == "":
|
||||
raise
|
||||
except:
|
||||
VERSION = "¯\_(xd)_/¯"
|
||||
|
||||
|
@@ -9,6 +9,7 @@ from constants import serverPackets
|
||||
from constants import dataTypes
|
||||
from constants import matchTeams
|
||||
from helpers import logHelper as log
|
||||
from helpers import chatHelper as chat
|
||||
|
||||
class match:
|
||||
"""Multiplayer match object"""
|
||||
@@ -61,6 +62,9 @@ class match:
|
||||
for _ in range(0,16):
|
||||
self.slots.append({"status": slotStatuses.free, "team": 0, "userID": -1, "mods": 0, "loaded": False, "skip": False, "complete": False})
|
||||
|
||||
# Create #multiplayer channel
|
||||
glob.channels.addTempChannel("#multi_{}".format(self.matchID))
|
||||
|
||||
|
||||
def getMatchData(self):
|
||||
"""
|
||||
@@ -577,11 +581,11 @@ class match:
|
||||
|
||||
# FokaBot is too busy
|
||||
if to == 999:
|
||||
froToken.enqueue(serverPackets.sendMessage("FokaBot", froToken.username, "I would love to join your match, but I'm busy keeping ripple up and running. Sorry. Beep Boop."))
|
||||
chat.sendMessage("FokaBot", froToken.username, "I would love to join your match, but I'm busy keeping ripple up and running. Sorry. Beep Boop.")
|
||||
|
||||
# Send message
|
||||
message = "Come join my multiplayer match: \"[osump://{}/{} {}]\"".format(self.matchID, self.matchPassword.replace(" ", "_"), self.matchName)
|
||||
toToken.enqueue(serverPackets.sendMessage(froToken.username, toToken.username, message))
|
||||
chat.sendMessage(token=froToken, to=toToken.username, message=message)
|
||||
|
||||
|
||||
def countUsers(self):
|
||||
|
@@ -9,6 +9,7 @@ import uuid
|
||||
import time
|
||||
import threading
|
||||
from helpers import logHelper as log
|
||||
from helpers import chatHelper as chat
|
||||
|
||||
class token:
|
||||
"""
|
||||
@@ -34,7 +35,7 @@ class token:
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, __userID, token = None, ip = ""):
|
||||
def __init__(self, __userID, token = None, ip = "", irc = False):
|
||||
"""
|
||||
Create a token object and set userID and token
|
||||
|
||||
@@ -42,6 +43,7 @@ class token:
|
||||
token -- if passed, set token to that value
|
||||
if not passed, token will be generated
|
||||
ip -- client ip. optional.
|
||||
irc -- if True, set this token as IRC client. optional.
|
||||
"""
|
||||
|
||||
# Set stuff
|
||||
@@ -49,6 +51,7 @@ class token:
|
||||
self.username = userHelper.getUsername(self.userID)
|
||||
self.privileges = userHelper.getPrivileges(self.userID)
|
||||
self.admin = userHelper.isInPrivilegeGroup(self.userID, "developer") or userHelper.isInPrivilegeGroup(self.userID, "community manager")
|
||||
self.irc = irc
|
||||
self.restricted = userHelper.isRestricted(self.userID)
|
||||
self.loginTime = int(time.time())
|
||||
self.pingTime = self.loginTime
|
||||
@@ -78,7 +81,6 @@ class token:
|
||||
self.actionMd5 = ""
|
||||
self.actionMods = 0
|
||||
self.gameMode = gameModes.std
|
||||
|
||||
self.rankedScore = 0
|
||||
self.accuracy = 0.0
|
||||
self.playcount = 0
|
||||
@@ -100,8 +102,9 @@ class token:
|
||||
userHelper.saveBanchoSession(self.userID, self.ip)
|
||||
|
||||
# If we are restricted, send message from FokaBot to user
|
||||
if self.restricted == True:
|
||||
self.setRestricted()
|
||||
# NOTE: Sent later
|
||||
#if self.restricted == True:
|
||||
# self.setRestricted()
|
||||
|
||||
|
||||
def enqueue(self, __bytes):
|
||||
@@ -110,8 +113,8 @@ class token:
|
||||
|
||||
__bytes -- (packet) bytes to enqueue
|
||||
"""
|
||||
|
||||
self.queue += __bytes
|
||||
if self.irc == False:
|
||||
self.queue += __bytes
|
||||
|
||||
|
||||
def resetQueue(self):
|
||||
@@ -228,11 +231,11 @@ class token:
|
||||
"""Set match to -1"""
|
||||
self.matchID = -1
|
||||
|
||||
def kick(self):
|
||||
def kick(self, message="You have been kicked from the server. Please login again."):
|
||||
"""Kick this user from the server"""
|
||||
# Send packet to target
|
||||
log.info("{} has been disconnected. (kick)".format(self.username))
|
||||
self.enqueue(serverPackets.notification("You have been kicked from the server. Please login again."))
|
||||
self.enqueue(serverPackets.notification(message))
|
||||
self.enqueue(serverPackets.loginFailed())
|
||||
|
||||
# Logout event
|
||||
@@ -301,10 +304,22 @@ class token:
|
||||
self.gameRank = stats["gameRank"]
|
||||
self.pp = stats["pp"]
|
||||
|
||||
def checkRestricted(self, force=False):
|
||||
"""
|
||||
Check if this token is restricted. If so, send fokabot message
|
||||
|
||||
force -- If True, get restricted value from db.
|
||||
If false, get the cached one. Optional. Default: False
|
||||
"""
|
||||
if force == True:
|
||||
self.restricted = userHelper.isRestricted(self.userID)
|
||||
if self.restricted == True:
|
||||
self.setRestricted()
|
||||
|
||||
def setRestricted(self):
|
||||
"""
|
||||
Set this token as restricted, send FokaBot message to user
|
||||
and send offline packet to everyone
|
||||
"""
|
||||
self.restricted = True
|
||||
self.enqueue(serverPackets.sendMessage("FokaBot", self.username, "Your account is currently in restricted mode. Please visit ripple's website for more information."))
|
||||
chat.sendMessage("FokaBot",self.username, "Your account is currently in restricted mode. Please visit ripple's website for more information.")
|
||||
|
@@ -19,15 +19,16 @@ class tokenList:
|
||||
"""
|
||||
self.tokens = {}
|
||||
|
||||
def addToken(self, userID, ip = ""):
|
||||
def addToken(self, userID, ip = "", irc = False):
|
||||
"""
|
||||
Add a token object to tokens list
|
||||
|
||||
userID -- user id associated to that token
|
||||
irc -- if True, set this token as IRC client
|
||||
return -- token object
|
||||
"""
|
||||
|
||||
newToken = osuToken.token(userID, ip=ip)
|
||||
newToken = osuToken.token(userID, ip=ip, irc=irc)
|
||||
self.tokens[newToken.token] = newToken
|
||||
return newToken
|
||||
|
||||
@@ -40,7 +41,8 @@ class tokenList:
|
||||
|
||||
if token in self.tokens:
|
||||
# Delete session from DB
|
||||
userHelper.deleteBanchoSessions(self.tokens[token].userID, self.tokens[token].ip)
|
||||
if self.tokens[token].ip != "":
|
||||
userHelper.deleteBanchoSessions(self.tokens[token].userID, self.tokens[token].ip)
|
||||
|
||||
# Pop token from list
|
||||
self.tokens.pop(token)
|
||||
@@ -108,13 +110,14 @@ class tokenList:
|
||||
"""
|
||||
|
||||
# Delete older tokens
|
||||
for key, value in self.tokens.items():
|
||||
for key, value in list(self.tokens.items()):
|
||||
if value.userID == userID:
|
||||
# Delete this token from the dictionary
|
||||
self.tokens.pop(key)
|
||||
self.tokens[key].kick("You have logged in from somewhere else. You can't connect to Bancho/IRC from more than one device at the same time.")
|
||||
#self.tokens.pop(key)
|
||||
|
||||
# break or items() function throws errors
|
||||
break
|
||||
#break
|
||||
|
||||
|
||||
def multipleEnqueue(self, packet, who, but = False):
|
||||
@@ -136,8 +139,6 @@ class tokenList:
|
||||
if shouldEnqueue:
|
||||
value.enqueue(packet)
|
||||
|
||||
|
||||
|
||||
def enqueueAll(self, packet):
|
||||
"""
|
||||
Enqueue packet(s) to every connected user
|
||||
@@ -162,7 +163,7 @@ class tokenList:
|
||||
timeoutLimit = time.time()-__timeoutTime
|
||||
for key, value in self.tokens.items():
|
||||
# Check timeout (fokabot is ignored)
|
||||
if value.pingTime < timeoutLimit and value.userID != 999:
|
||||
if value.pingTime < timeoutLimit and value.userID != 999 and value.irc == False:
|
||||
# That user has timed out, add to disconnected tokens
|
||||
# We can't delete it while iterating or items() throws an error
|
||||
timedOutTokens.append(key)
|
||||
@@ -195,3 +196,18 @@ class tokenList:
|
||||
Call at bancho startup to delete old cached sessions
|
||||
"""
|
||||
glob.db.execute("TRUNCATE TABLE bancho_sessions")
|
||||
|
||||
def tokenExists(self, username = "", userID = -1):
|
||||
"""
|
||||
Check if a token exists (aka check if someone is connected)
|
||||
|
||||
username -- Optional.
|
||||
userID -- Optional.
|
||||
return -- True if it exists, otherwise False
|
||||
|
||||
Use username or userid, not both at the same time.
|
||||
"""
|
||||
if userID > -1:
|
||||
return True if self.getTokenFromUserID(userID) is not None else False
|
||||
else:
|
||||
return True if self.getTokenFromUsername(username) is not None else False
|
||||
|
Reference in New Issue
Block a user