.BANCHO. Switched from tornado to bottle + gevent, code cleaning

This commit is contained in:
Nyo 2016-08-17 16:41:05 +02:00
parent 0e74e5c1ce
commit 7910291b77
32 changed files with 463 additions and 787 deletions

View File

@ -1,8 +1,6 @@
from objects import glob
from constants import clientPackets
from constants import matchModModes
from helpers import consoleHelper
from constants import bcolors
import random
from constants import matchTeamTypes
from constants import matchTeams

View File

@ -1,12 +1,9 @@
from constants import clientPackets
from objects import glob
from helpers import consoleHelper
from constants import bcolors
def handle(userToken, packetData):
# Get usertoken data
userID = userToken.userID
username = userToken.username
# Read packet data
packetData = clientPackets.changeSlot(packetData)

View File

@ -1,6 +1,3 @@
"""
Event called when someone parts a channel
"""
from constants import clientPackets
from helpers import chatHelper as chat

View File

@ -2,27 +2,22 @@ from helpers import userHelper
from constants import serverPackets
from constants import exceptions
from objects import glob
from helpers import consoleHelper
from constants import bcolors
from helpers import locationHelper
from helpers import countryHelper
import time
from helpers import generalFunctions
import sys
import traceback
from helpers import requestHelper
from helpers import discordBotHelper
from helpers import logHelper as log
from helpers import chatHelper as chat
from constants import privileges
from helpers import requestHelper
def handle(tornadoRequest):
def handle(bottleRequest):
# Data to return
responseTokenString = "ayy"
responseData = bytes()
# Get IP from tornado request
requestIP = tornadoRequest.getRequestIP()
requestIP = requestHelper.getRequestIP(bottleRequest)
# Avoid exceptions
clientData = ["unknown", "unknown", "unknown", "unknown", "unknown"]
@ -30,7 +25,8 @@ def handle(tornadoRequest):
# Split POST body so we can get username/password/hardware data
# 2:-3 thing is because requestData has some escape stuff that we don't need
loginData = str(tornadoRequest.request.body)[2:-3].split("\\n")
postBody = bottleRequest.body.read()
loginData = str(postBody)[2:-3].split("\\n")
try:
# If true, print error to console
err = False

View File

@ -1,6 +1,4 @@
from objects import glob
from helpers import consoleHelper
from constants import bcolors
from constants import serverPackets
import time
from helpers import logHelper as log

View File

@ -1,7 +1,6 @@
from objects import glob
from constants import slotStatuses
from constants import serverPackets
from helpers import logHelper as log
def handle(userToken, packetData):
# Get usertoken data

View File

@ -1,5 +1,4 @@
from objects import glob
from events import channelPartEvent
from helpers import logHelper as log
from helpers import chatHelper as chat

View File

@ -1,5 +1,4 @@
from objects import glob
from helpers import chatHelper as chat
def handle(userToken, _):
# get data from usertoken

View File

@ -1,6 +1,4 @@
from constants import clientPackets
from constants import serverPackets
from helpers import userHelper
from helpers import logHelper as log
def handle(userToken, packetData):

View File

@ -0,0 +1,37 @@
from constants import exceptions
import json
from objects import glob
from helpers import chatHelper
import bottle
@bottle.route("/api/v1/fokabotMessage")
def GETApiFokabotMessage():
statusCode = 400
data = {"message": "unknown error"}
try:
# Check arguments
if "k" not in bottle.request.query or "to" not in bottle.request.query or "msg" not in bottle.request.query:
raise exceptions.invalidArgumentsException()
# Check ci key
key = bottle.request.query["k"]
if key is None or key != glob.conf.config["server"]["cikey"]:
raise exceptions.invalidArgumentsException()
# Send chat message
chatHelper.sendMessage("FokaBot", bottle.request.query["to"], bottle.request.query["msg"])
# Status code and message
statusCode = 200
data["message"] = "ok"
except exceptions.invalidArgumentsException:
statusCode = 400
data["message"] = "invalid parameters"
finally:
# Add status code to data
data["status"] = statusCode
# Send response
bottle.response.status = statusCode
bottle.response.add_header("Content-Type", "application/json")
yield json.dumps(data)

View File

@ -1,36 +1,32 @@
from helpers import requestHelper
from constants import exceptions
import json
from objects import glob
import bottle
class handler(requestHelper.asyncRequestHandler):
def asyncGet(self):
@bottle.route("/api/v1/isOnline")
def GETApiIsOnline():
statusCode = 400
data = {"message": "unknown error"}
try:
# Check arguments
if "u" not in bottle.request.query:
raise exceptions.invalidArgumentsException()
# Get online staus
username = bottle.request.query["u"]
data["result"] = True if glob.tokens.getTokenFromUsername(username) != None else False
# Status code and message
statusCode = 200
data["message"] = "ok"
except exceptions.invalidArgumentsException:
statusCode = 400
data = {"message": "unknown error"}
try:
# Check arguments
if requestHelper.checkArguments(self.request.arguments, ["u"]) == False:
raise exceptions.invalidArgumentsException()
data["message"] = "missing required arguments"
finally:
# Add status code to data
data["status"] = statusCode
# Get online staus
username = self.get_argument("u")
if username == None:
data["result"] = False
else:
data["result"] = True if glob.tokens.getTokenFromUsername(username) != None else False
# Status code and message
statusCode = 200
data["message"] = "ok"
except exceptions.invalidArgumentsException:
statusCode = 400
data["message"] = "missing required arguments"
finally:
# Add status code to data
data["status"] = statusCode
# Send response
#self.clear()
self.write(json.dumps(data))
self.set_status(statusCode)
#self.finish(json.dumps(data))
# Send response
bottle.response.status = statusCode
bottle.response.add_header("Content-Type", "application/json")
yield json.dumps(data)

View File

@ -1,24 +1,23 @@
from helpers import requestHelper
import json
from objects import glob
import bottle
class handler(requestHelper.asyncRequestHandler):
def asyncGet(self):
statusCode = 400
data = {"message": "unknown error"}
try:
# Get online users count
data["result"] = len(glob.tokens.tokens)
@bottle.route("/api/v1/onlineUsers")
def GETApiOnlineUsers():
statusCode = 400
data = {"message": "unknown error"}
try:
# Get online users count
data["result"] = len(glob.tokens.tokens)
# Status code and message
statusCode = 200
data["message"] = "ok"
finally:
# Add status code to data
data["status"] = statusCode
# Status code and message
statusCode = 200
data["message"] = "ok"
finally:
# Add status code to data
data["status"] = statusCode
# Send response
#self.clear()
self.write(json.dumps(data))
self.set_status(statusCode)
#self.finish(json.dumps(data))
# Send response
bottle.response.status = statusCode
bottle.response.add_header("Content-Type", "application/json")
yield json.dumps(data)

View File

@ -1,24 +1,23 @@
from helpers import requestHelper
import json
from objects import glob
import bottle
class handler(requestHelper.asyncRequestHandler):
def asyncGet(self):
statusCode = 400
data = {"message": "unknown error"}
try:
# Get online users count
data["result"] = -1 if glob.restarting == True else 1
@bottle.route("/api/v1/serverStatus")
def GETApiServerStatus():
statusCode = 400
data = {"message": "unknown error"}
try:
# Get online users count
data["result"] = -1 if glob.restarting == True else 1
# Status code and message
statusCode = 200
data["message"] = "ok"
finally:
# Add status code to data
data["status"] = statusCode
# Status code and message
statusCode = 200
data["message"] = "ok"
finally:
# Add status code to data
data["status"] = statusCode
# Send response
#self.clear()
self.write(json.dumps(data))
self.set_status(statusCode)
#self.finish(json.dumps(data))
# Send response
bottle.response.status = statusCode
bottle.response.add_header("Content-Type", "application/json")
yield json.dumps(data)

View File

@ -1,46 +1,48 @@
from helpers import requestHelper
from helpers import logHelper as log
import json
from objects import glob
from constants import exceptions
import bottle
class handler(requestHelper.asyncRequestHandler):
def asyncGet(self):
@bottle.route("/api/v1/verifiedStatus")
def GETApiVerifiedStatus():
statusCode = 400
data = {"message": "unknown error"}
try:
# Check arguments
if "u" not in bottle.request.query:
raise exceptions.invalidArgumentsException()
# Get userID and its verified cache thing
# -1: Not in cache
# 0: Not verified (multiacc)
# 1: Verified
userID = bottle.request.query["u"]
callback = None
if "callback" in bottle.request.query:
callback = bottle.request.query["callback"]
data["result"] = -1 if userID not in glob.verifiedCache else glob.verifiedCache[userID]
# Status code and message
statusCode = 200
data["message"] = "ok"
except exceptions.invalidArgumentsException:
statusCode = 400
data = {"message": "unknown error"}
try:
# Check arguments
if requestHelper.checkArguments(self.request.arguments, ["u"]) == False:
raise exceptions.invalidArgumentsException()
data["message"] = "missing required arguments"
finally:
# Add status code to data
data["status"] = statusCode
# Get userID and its verified cache thing
# -1: Not in cache
# 0: Not verified (multiacc)
# 1: Verified
userID = self.get_argument("u")
data["result"] = -1 if userID not in glob.verifiedCache else glob.verifiedCache[userID]
# Send response
bottle.response.add_header("Access-Control-Allow-Origin", "*")
bottle.response.add_header("Content-Type", "application/json")
# Status code and message
statusCode = 200
data["message"] = "ok"
except exceptions.invalidArgumentsException:
statusCode = 400
data["message"] = "missing required arguments"
finally:
# Add status code to data
data["status"] = statusCode
# jquery meme
output = ""
if callback != None:
output += callback+"("
output += json.dumps(data)
if callback != None:
output += ")"
# Send response
self.add_header("Access-Control-Allow-Origin", "*")
self.add_header("Content-Type", "application/json")
# jquery meme
output = ""
if "callback" in self.request.arguments:
output += self.get_argument("callback")+"("
output += json.dumps(data)
if "callback" in self.request.arguments:
output += ")"
self.write(output)
self.set_status(statusCode)
bottle.response.status = statusCode
yield output

View File

@ -1,39 +1,38 @@
from helpers import requestHelper
from constants import exceptions
import json
from objects import glob
from helpers import systemHelper
from helpers import logHelper as log
import bottle
class handler(requestHelper.asyncRequestHandler):
def asyncGet(self):
statusCode = 400
data = {"message": "unknown error"}
try:
# Check arguments
if requestHelper.checkArguments(self.request.arguments, ["k"]) == False:
raise exceptions.invalidArgumentsException()
@bottle.route("/api/v1/ciTrigger")
def GETCiTrigger():
statusCode = 400
data = {"message": "unknown error"}
try:
# Check arguments
if "k" not in bottle.request.query:
raise exceptions.invalidArgumentsException()
# Check ci key
key = self.get_argument("k")
if key is None or key != glob.conf.config["server"]["cikey"]:
raise exceptions.invalidArgumentsException()
# Check ci key
key = bottle.request.query["k"]
if key != glob.conf.config["server"]["cikey"]:
raise exceptions.invalidArgumentsException()
log.info("Ci event triggered!!")
systemHelper.scheduleShutdown(5, False, "A new Bancho update is available and the server will be restarted in 5 seconds. Thank you for your patience.")
log.info("Ci event triggered!!")
systemHelper.scheduleShutdown(5, False, "A new Bancho update is available and the server will be restarted in 5 seconds. Thank you for your patience.")
# Status code and message
statusCode = 200
data["message"] = "ok"
except exceptions.invalidArgumentsException:
statusCode = 400
data["message"] = "invalid ci key"
finally:
# Add status code to data
data["status"] = statusCode
# Status code and message
statusCode = 200
data["message"] = "ok"
except exceptions.invalidArgumentsException:
statusCode = 403
data["message"] = "invalid ci key"
finally:
# Add status code to data
data["status"] = statusCode
# Send response
#self.clear()
self.write(json.dumps(data))
self.set_status(statusCode)
#self.finish(json.dumps(data))
# Send response
bottle.response.status = statusCode
bottle.response.add_header("Content-Type", "application/json")
yield json.dumps(data)

View File

@ -1,39 +0,0 @@
from helpers import requestHelper
from constants import exceptions
import json
from objects import glob
from helpers import chatHelper
from helpers import logHelper as log
class handler(requestHelper.asyncRequestHandler):
def asyncGet(self):
statusCode = 400
data = {"message": "unknown error"}
try:
# Check arguments
if requestHelper.checkArguments(self.request.arguments, ["k", "to", "msg"]) == False:
raise exceptions.invalidArgumentsException()
# Check ci key
key = self.get_argument("k")
if key is None or key != glob.conf.config["server"]["cikey"]:
raise exceptions.invalidArgumentsException()
log.info("API REQUEST FOR FOKABOT MESSAGE AAAAAAA")
chatHelper.sendMessage("FokaBot", self.get_argument("to"), self.get_argument("msg"))
# Status code and message
statusCode = 200
data["message"] = "ok"
except exceptions.invalidArgumentsException:
statusCode = 400
data["message"] = "invalid parameters"
finally:
# Add status code to data
data["status"] = statusCode
# Send response
#self.clear()
self.write(json.dumps(data))
self.set_status(statusCode)
#self.finish(json.dumps(data))

View File

@ -1,10 +1,11 @@
import bottle
import datetime
import gzip
from helpers import requestHelper
from objects import glob
from helpers import packetHelper
from helpers import logHelper as log
from constants import exceptions
from constants import packetIDs
from helpers import packetHelper
from constants import serverPackets
from events import sendPublicMessageEvent
from events import sendPrivateMessageEvent
@ -46,219 +47,198 @@ from events import userStatsRequestEvent
from events import requestStatusUpdateEvent
from events import userPanelRequestEvent
# Exception tracking
import tornado.web
import tornado.gen
import sys
import traceback
from raven.contrib.tornado import SentryMixin
from helpers import logHelper as log
@bottle.route("/", method="POST")
def POSTMain():
# Track time if needed
if glob.outputRequestTime == True:
# Start time
st = datetime.datetime.now()
class handler(SentryMixin, requestHelper.asyncRequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def asyncPost(self):
# Client's token string and request data
requestTokenString = bottle.request.headers.get("osu-token")
requestData = bottle.request.body.read()
# Server's token string and request data
responseTokenString = "ayy"
responseData = bytes()
if requestTokenString == None:
# No token, first request. Handle login.
responseTokenString, responseData = loginEvent.handle(bottle.request)
else:
userToken = None # default value
try:
# Track time if needed
if glob.outputRequestTime == True:
# Start time
st = datetime.datetime.now()
# This is not the first packet, send response based on client's request
# Packet start position, used to read stacked packets
pos = 0
# Client's token string and request data
requestTokenString = self.request.headers.get("osu-token")
requestData = self.request.body
# Make sure the token exists
if requestTokenString not in glob.tokens.tokens:
raise exceptions.tokenNotFoundException()
# Server's token string and request data
responseTokenString = "ayy"
responseData = bytes()
# Token exists, get its object and lock it
userToken = glob.tokens.tokens[requestTokenString]
userToken.lock.acquire()
if requestTokenString == None:
# No token, first request. Handle login.
responseTokenString, responseData = loginEvent.handle(self)
else:
userToken = None # default value
try:
# This is not the first packet, send response based on client's request
# Packet start position, used to read stacked packets
pos = 0
# Keep reading packets until everything has been read
while pos < len(requestData):
# Get packet from stack starting from new packet
leftData = requestData[pos:]
# Make sure the token exists
if requestTokenString not in glob.tokens.tokens:
raise exceptions.tokenNotFoundException()
# Get packet ID, data length and data
packetID = packetHelper.readPacketID(leftData)
dataLength = packetHelper.readPacketLength(leftData)
packetData = requestData[pos:(pos+dataLength+7)]
# Token exists, get its object and lock it
userToken = glob.tokens.tokens[requestTokenString]
userToken.lock.acquire()
# Console output if needed
if glob.outputPackets == True and packetID != 4:
log.debug("Incoming packet ({})({}):\n\nPacket code: {}\nPacket length: {}\nSingle packet data: {}\n".format(requestTokenString, userToken.username, str(packetID), str(dataLength), str(packetData)))
# Keep reading packets until everything has been read
while pos < len(requestData):
# Get packet from stack starting from new packet
leftData = requestData[pos:]
# Event handler
def handleEvent(ev):
def wrapper():
ev.handle(userToken, packetData)
return wrapper
# Get packet ID, data length and data
packetID = packetHelper.readPacketID(leftData)
dataLength = packetHelper.readPacketLength(leftData)
packetData = requestData[pos:(pos+dataLength+7)]
eventHandler = {
# TODO: Rename packets and events
# TODO: Host check for multi
packetIDs.client_changeAction: handleEvent(changeActionEvent),
packetIDs.client_logout: handleEvent(logoutEvent),
packetIDs.client_friendAdd: handleEvent(friendAddEvent),
packetIDs.client_friendRemove: handleEvent(friendRemoveEvent),
packetIDs.client_userStatsRequest: handleEvent(userStatsRequestEvent),
packetIDs.client_requestStatusUpdate: handleEvent(requestStatusUpdateEvent),
packetIDs.client_userPanelRequest: handleEvent(userPanelRequestEvent),
packetIDs.client_channelJoin: handleEvent(channelJoinEvent),
packetIDs.client_channelPart: handleEvent(channelPartEvent),
packetIDs.client_sendPublicMessage: handleEvent(sendPublicMessageEvent),
packetIDs.client_sendPrivateMessage: handleEvent(sendPrivateMessageEvent),
packetIDs.client_setAwayMessage: handleEvent(setAwayMessageEvent),
# Console output if needed
if glob.outputPackets == True and packetID != 4:
log.debug("Incoming packet ({})({}):\n\nPacket code: {}\nPacket length: {}\nSingle packet data: {}\n".format(requestTokenString, userToken.username, str(packetID), str(dataLength), str(packetData)))
packetIDs.client_startSpectating: handleEvent(startSpectatingEvent),
packetIDs.client_stopSpectating: handleEvent(stopSpectatingEvent),
packetIDs.client_cantSpectate: handleEvent(cantSpectateEvent),
packetIDs.client_spectateFrames: handleEvent(spectateFramesEvent),
# Event handler
def handleEvent(ev):
def wrapper():
ev.handle(userToken, packetData)
return wrapper
packetIDs.client_joinLobby: handleEvent(joinLobbyEvent),
packetIDs.client_partLobby: handleEvent(partLobbyEvent),
packetIDs.client_createMatch: handleEvent(createMatchEvent),
packetIDs.client_joinMatch: handleEvent(joinMatchEvent),
packetIDs.client_partMatch: handleEvent(partMatchEvent),
packetIDs.client_matchChangeSlot: handleEvent(changeSlotEvent),
packetIDs.client_matchChangeSettings: handleEvent(changeMatchSettingsEvent),
packetIDs.client_matchChangePassword: handleEvent(changeMatchPasswordEvent),
packetIDs.client_matchChangeMods: handleEvent(changeMatchModsEvent),
packetIDs.client_matchReady: handleEvent(matchReadyEvent),
packetIDs.client_matchNotReady: handleEvent(matchReadyEvent),
packetIDs.client_matchLock: handleEvent(matchLockEvent),
packetIDs.client_matchStart: handleEvent(matchStartEvent),
packetIDs.client_matchLoadComplete: handleEvent(matchPlayerLoadEvent),
packetIDs.client_matchSkipRequest: handleEvent(matchSkipEvent),
packetIDs.client_matchScoreUpdate: handleEvent(matchFramesEvent),
packetIDs.client_matchComplete: handleEvent(matchCompleteEvent),
packetIDs.client_matchNoBeatmap: handleEvent(matchNoBeatmapEvent),
packetIDs.client_matchHasBeatmap: handleEvent(matchHasBeatmapEvent),
packetIDs.client_matchTransferHost: handleEvent(matchTransferHostEvent),
packetIDs.client_matchFailed: handleEvent(matchFailedEvent),
packetIDs.client_matchChangeTeam: handleEvent(matchChangeTeamEvent),
packetIDs.client_invite: handleEvent(matchInviteEvent),
}
eventHandler = {
# TODO: Rename packets and events
# TODO: Host check for multi
packetIDs.client_changeAction: handleEvent(changeActionEvent),
packetIDs.client_logout: handleEvent(logoutEvent),
packetIDs.client_friendAdd: handleEvent(friendAddEvent),
packetIDs.client_friendRemove: handleEvent(friendRemoveEvent),
packetIDs.client_userStatsRequest: handleEvent(userStatsRequestEvent),
packetIDs.client_requestStatusUpdate: handleEvent(requestStatusUpdateEvent),
packetIDs.client_userPanelRequest: handleEvent(userPanelRequestEvent),
packetIDs.client_channelJoin: handleEvent(channelJoinEvent),
packetIDs.client_channelPart: handleEvent(channelPartEvent),
packetIDs.client_sendPublicMessage: handleEvent(sendPublicMessageEvent),
packetIDs.client_sendPrivateMessage: handleEvent(sendPrivateMessageEvent),
packetIDs.client_setAwayMessage: handleEvent(setAwayMessageEvent),
# Packets processed if in restricted mode.
# All other packets will be ignored if the user is in restricted mode
packetsRestricted = [
packetIDs.client_logout,
packetIDs.client_userStatsRequest,
packetIDs.client_requestStatusUpdate,
packetIDs.client_userPanelRequest,
packetIDs.client_changeAction,
packetIDs.client_channelJoin,
packetIDs.client_channelPart,
]
packetIDs.client_startSpectating: handleEvent(startSpectatingEvent),
packetIDs.client_stopSpectating: handleEvent(stopSpectatingEvent),
packetIDs.client_cantSpectate: handleEvent(cantSpectateEvent),
packetIDs.client_spectateFrames: handleEvent(spectateFramesEvent),
# Process/ignore packet
if packetID != 4:
if packetID in eventHandler:
if userToken.restricted == False or (userToken.restricted == True and packetID in packetsRestricted):
eventHandler[packetID]()
else:
log.warning("Ignored packet id from {} ({}) (user is restricted)".format(requestTokenString, packetID))
else:
log.warning("Unknown packet id from {} ({})".format(requestTokenString, packetID))
packetIDs.client_joinLobby: handleEvent(joinLobbyEvent),
packetIDs.client_partLobby: handleEvent(partLobbyEvent),
packetIDs.client_createMatch: handleEvent(createMatchEvent),
packetIDs.client_joinMatch: handleEvent(joinMatchEvent),
packetIDs.client_partMatch: handleEvent(partMatchEvent),
packetIDs.client_matchChangeSlot: handleEvent(changeSlotEvent),
packetIDs.client_matchChangeSettings: handleEvent(changeMatchSettingsEvent),
packetIDs.client_matchChangePassword: handleEvent(changeMatchPasswordEvent),
packetIDs.client_matchChangeMods: handleEvent(changeMatchModsEvent),
packetIDs.client_matchReady: handleEvent(matchReadyEvent),
packetIDs.client_matchNotReady: handleEvent(matchReadyEvent),
packetIDs.client_matchLock: handleEvent(matchLockEvent),
packetIDs.client_matchStart: handleEvent(matchStartEvent),
packetIDs.client_matchLoadComplete: handleEvent(matchPlayerLoadEvent),
packetIDs.client_matchSkipRequest: handleEvent(matchSkipEvent),
packetIDs.client_matchScoreUpdate: handleEvent(matchFramesEvent),
packetIDs.client_matchComplete: handleEvent(matchCompleteEvent),
packetIDs.client_matchNoBeatmap: handleEvent(matchNoBeatmapEvent),
packetIDs.client_matchHasBeatmap: handleEvent(matchHasBeatmapEvent),
packetIDs.client_matchTransferHost: handleEvent(matchTransferHostEvent),
packetIDs.client_matchFailed: handleEvent(matchFailedEvent),
packetIDs.client_matchChangeTeam: handleEvent(matchChangeTeamEvent),
packetIDs.client_invite: handleEvent(matchInviteEvent),
}
# Update pos so we can read the next stacked packet
# +7 because we add packet ID bytes, unused byte and data length bytes
pos += dataLength+7
# Packets processed if in restricted mode.
# All other packets will be ignored if the user is in restricted mode
packetsRestricted = [
packetIDs.client_logout,
packetIDs.client_userStatsRequest,
packetIDs.client_requestStatusUpdate,
packetIDs.client_userPanelRequest,
packetIDs.client_changeAction,
packetIDs.client_channelJoin,
packetIDs.client_channelPart,
]
# Token queue built, send it
responseTokenString = userToken.token
responseData = userToken.queue
userToken.resetQueue()
# Process/ignore packet
if packetID != 4:
if packetID in eventHandler:
if userToken.restricted == False or (userToken.restricted == True and packetID in packetsRestricted):
eventHandler[packetID]()
else:
log.warning("Ignored packet id from {} ({}) (user is restricted)".format(requestTokenString, packetID))
else:
log.warning("Unknown packet id from {} ({})".format(requestTokenString, packetID))
# Update ping time for timeout
userToken.updatePingTime()
except exceptions.tokenNotFoundException:
# Token not found. Disconnect that user
responseData = serverPackets.loginError()
responseData += serverPackets.notification("Whoops! Something went wrong, please login again.")
log.warning("Received packet from unknown token ({}).".format(requestTokenString))
log.info("{} has been disconnected (invalid token)".format(requestTokenString))
finally:
# Unlock token
if userToken != None:
userToken.lock.release()
# Update pos so we can read the next stacked packet
# +7 because we add packet ID bytes, unused byte and data length bytes
pos += dataLength+7
if glob.outputRequestTime == True:
# End time
et = datetime.datetime.now()
# Token queue built, send it
responseTokenString = userToken.token
responseData = userToken.queue
userToken.resetQueue()
# Total time:
tt = float((et.microsecond-st.microsecond)/1000)
log.debug("Request time: {}ms".format(tt))
# Update ping time for timeout
userToken.updatePingTime()
except exceptions.tokenNotFoundException:
# Token not found. Disconnect that user
responseData = serverPackets.loginError()
responseData += serverPackets.notification("Whoops! Something went wrong, please login again.")
log.warning("Received packet from unknown token ({}).".format(requestTokenString))
log.info("{} has been disconnected (invalid token)".format(requestTokenString))
finally:
# Unlock token
if userToken != None:
userToken.lock.release()
# Send server's response to client
# We don't use token object because we might not have a token (failed login)
if glob.gzip == True:
# First, write the gzipped response
responseData = gzip.compress(responseData, int(glob.conf.config["server"]["gziplevel"]))
if glob.outputRequestTime == True:
# End time
et = datetime.datetime.now()
# Then, add gzip headers
bottle.response.add_header("Vary", "Accept-Encoding")
bottle.response.add_header("Content-Encoding", "gzip")
else:
# First, write the response
responseData = responseData
# Total time:
tt = float((et.microsecond-st.microsecond)/1000)
log.debug("Request time: {}ms".format(tt))
# Add all the headers AFTER the response has been written
bottle.response.status = 200
bottle.response.add_header("cho-token", responseTokenString)
bottle.response.add_header("cho-protocol", "19")
bottle.response.add_header("Content-Type", "text/html; charset=UTF-8")
yield responseData
# Send server's response to client
# We don't use token object because we might not have a token (failed login)
if glob.gzip == True:
# First, write the gzipped response
self.write(gzip.compress(responseData, int(glob.conf.config["server"]["gziplevel"])))
# Then, add gzip headers
self.add_header("Vary", "Accept-Encoding")
self.add_header("Content-Encoding", "gzip")
else:
# First, write the response
self.write(responseData)
# Add all the headers AFTER the response has been written
self.set_status(200)
self.add_header("cho-token", responseTokenString)
self.add_header("cho-protocol", "19")
#self.add_header("Keep-Alive", "timeout=5, max=100")
#self.add_header("Connection", "keep-alive")
self.add_header("Content-Type", "text/html; charset=UTF-8")
except:
log.error("Unknown error!\n```\n{}\n{}```".format(sys.exc_info(), traceback.format_exc()))
if glob.sentry:
yield tornado.gen.Task(self.captureException, exc_info=True)
#finally:
# self.finish()
@tornado.web.asynchronous
@tornado.gen.engine
def asyncGet(self):
html = "<html><head><title>MA MAURO ESISTE?</title><style type='text/css'>body{width:30%}</style></head><body><pre>"
html += " _ __<br>"
html += " (_) / /<br>"
html += " ______ __ ____ ____ / /____<br>"
html += " / ___/ / _ \\/ _ \\/ / _ \\<br>"
html += " / / / / /_) / /_) / / ____/<br>"
html += "/__/ /__/ .___/ .___/__/ \\_____/<br>"
html += " / / / /<br>"
html += " /__/ /__/<br>"
html += "<b>PYTHON > ALL VERSION</b><br><br>"
html += "<marquee style='white-space:pre;'><br>"
html += " .. o .<br>"
html += " o.o o . o<br>"
html += " oo...<br>"
html += " __[]__<br>"
html += " phwr--> _\\:D/_/o_o_o_|__ <span style=\"font-family: 'Comic Sans MS'; font-size: 8pt;\">u wot m8</span><br>"
html += " \\\"\"\"\"\"\"\"\"\"\"\"\"\"\"/<br>"
html += " \\ . .. .. . /<br>"
html += "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>"
html += "</marquee><br><strike>reverse engineering a protocol impossible to reverse engineer since always</strike><br>we are actually reverse engineering bancho successfully. for the third time.<br><br><i>&copy; Ripple team, 2016</i></pre></body></html>"
self.write(html)
#yield tornado.gen.Task(self.captureMessage, "test")
#self.finish()
@bottle.route("/", method="GET")
def GETMain():
html = "<html><head><title>MA MAURO ESISTE?</title><style type='text/css'>body{width:30%}</style></head><body><pre>"
html += " _ __<br>"
html += " (_) / /<br>"
html += " ______ __ ____ ____ / /____<br>"
html += " / ___/ / _ \\/ _ \\/ / _ \\<br>"
html += " / / / / /_) / /_) / / ____/<br>"
html += "/__/ /__/ .___/ .___/__/ \\_____/<br>"
html += " / / / /<br>"
html += " /__/ /__/<br>"
html += "<b>PYTHON > ALL VERSION</b><br><br>"
html += "<marquee style='white-space:pre;'><br>"
html += " .. o .<br>"
html += " o.o o . o<br>"
html += " oo...<br>"
html += " __[]__<br>"
html += " phwr--> _\\:D/_/o_o_o_|__ <span style=\"font-family: 'Comic Sans MS'; font-size: 8pt;\">u wot m8</span><br>"
html += " \\\"\"\"\"\"\"\"\"\"\"\"\"\"\"/<br>"
html += " \\ . .. .. . /<br>"
html += "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>"
html += "</marquee><br><strike>reverse engineering a protocol impossible to reverse engineer since always</strike><br>we are actually reverse engineering bancho successfully. for the third time.<br><br><i>&copy; Ripple team, 2016</i></pre></body></html>"
yield html

View File

@ -14,14 +14,14 @@ class config:
default = True
# Check if config.ini exists and load/generate it
def __init__(self, __file):
def __init__(self, file):
"""
Initialize a config object
__file -- filename
file -- filename
"""
self.fileName = __file
self.fileName = file
if os.path.isfile(self.fileName):
# config.ini found, load it
self.config.read(self.fileName)
@ -49,7 +49,6 @@ class config:
self.config.get("db","workers")
self.config.get("server","port")
self.config.get("server","threads")
self.config.get("server","gzip")
self.config.get("server","gziplevel")
self.config.get("server","cikey")
@ -94,7 +93,6 @@ class config:
self.config.add_section("server")
self.config.set("server", "port", "5001")
self.config.set("server", "threads", "16")
self.config.set("server", "gzip", "1")
self.config.set("server", "gziplevel", "6")
self.config.set("server", "cikey", "changeme")

View File

@ -1,138 +0,0 @@
import pymysql
from constants import bcolors
from helpers import consoleHelper
import threading
from objects import glob
class db:
"""A MySQL database connection"""
connection = None
disconnected = False
pingTime = 600
def __init__(self, __host, __username, __password, __database, __pingTime = 600):
"""
Connect to MySQL database
__host -- MySQL host name
__username -- MySQL username
__password -- MySQL password
__database -- MySQL database name
__pingTime -- MySQL database ping time (default: 600)
"""
self.connection = pymysql.connect(host=__host, user=__username, password=__password, db=__database, cursorclass=pymysql.cursors.DictCursor, autocommit=True)
self.pingTime = __pingTime
self.pingLoop()
def bindParams(self, __query, __params):
"""
Replace every ? with the respective **escaped** parameter in array
__query -- query with ?s
__params -- array with params
return -- new query
"""
for i in __params:
escaped = self.connection.escape(i)
__query = __query.replace("?", str(escaped), 1)
return __query
def execute(self, __query, __params = None):
"""
Execute a SQL query
__query -- query, can contain ?s
__params -- array with params. Optional
"""
log.debug(query)
with self.connection.cursor() as cursor:
try:
# Bind params if needed
if __params != None:
__query = self.bindParams(__query, __params)
# Execute the query
cursor.execute(__query)
finally:
# Close this connection
cursor.close()
def fetch(self, __query, __params = None, __all = False):
"""
Fetch the first (or all) element(s) of SQL query result
__query -- query, can contain ?s
__params -- array with params. Optional
__all -- if true, will fetch all values. Same as fetchAll
return -- dictionary with result data or False if failed
"""
log.debug(query)
with self.connection.cursor() as cursor:
try:
# Bind params if needed
if __params != None:
__query = self.bindParams(__query, __params)
# Execute the query with binded params
cursor.execute(__query)
# Get first result and return it
if __all == False:
return cursor.fetchone()
else:
return cursor.fetchall()
finally:
# Close this connection
cursor.close()
def fetchAll(self, __query, __params = None):
"""
Fetch the all elements of SQL query result
__query -- query, can contain ?s
__params -- array with params. Optional
return -- dictionary with result data
"""
return self.fetch(__query, __params, True)
def pingLoop(self):
"""
Pings MySQL server. We need to ping/execute a query at least once every 8 hours
or the connection will die.
If called once, will recall after 30 minutes and so on, forever
CALL THIS FUNCTION ONLY ONCE!
"""
# Default loop time
time = self.pingTime
# Make sure the connection is alive
try:
# Try to ping and reconnect if not connected
self.connection.ping()
if self.disconnected == True:
# If we were disconnected, set disconnected to false and print message
self.disconnected = False
log.error("> Reconnected to MySQL server!", bcolors.GREEN)
except:
# Can't ping MySQL server. Show error and call loop in 5 seconds
log.error("[!] CRITICAL!! MySQL connection died! Make sure your MySQL server is running! Checking again in 5 seconds...", bcolors.RED)
self.disconnected = True
time = 5
# Schedule a new check (endless loop)
threading.Timer(time, self.pingLoop).start()

View File

@ -72,42 +72,42 @@ def logMessage(message, alertType = "INFO", messageColor = bcolors.ENDC, discord
def warning(message, discord = None, alertDev = False):
"""
Log a warning to stdout, warnings.log (always) and discord (optional)
Log a warning to stdout (always) and discord (optional)
message -- warning message
discord -- if not None, send message to that discord channel through schiavo. Optional. Default = None
alertDev -- if True, send al hl to devs on discord. Optional. Default = False.
"""
logMessage(message, "WARNING", bcolors.YELLOW, discord, alertDev, "warnings.txt")
logMessage(message, "WARNING", bcolors.YELLOW, discord, alertDev)
def error(message, discord = None, alertDev = True):
"""
Log an error to stdout, errors.log (always) and discord (optional)
Log an error to stdout (always) and discord (optional)
message -- error message
discord -- if not None, send message to that discord channel through schiavo. Optional. Default = None
alertDev -- if True, send al hl to devs on discord. Optional. Default = False.
"""
logMessage(message, "ERROR", bcolors.RED, discord, alertDev, "errors.txt")
logMessage(message, "ERROR", bcolors.RED, discord, alertDev)
def info(message, discord = None, alertDev = False):
"""
Log an error to stdout (and info.log)
Log an info message to stdout
message -- info message
discord -- if not None, send message to that discord channel through schiavo. Optional. Default = None
alertDev -- if True, send al hl to devs on discord. Optional. Default = False.
"""
logMessage(message, "INFO", bcolors.ENDC, discord, alertDev, "info.txt")
logMessage(message, "INFO", bcolors.ENDC, discord, alertDev)
def debug(message):
"""
Log a debug message to stdout and debug.log if server is running in debug mode
Log a debug message to stdout if server is running in debug mode
message -- debug message
"""
if glob.debug == True:
logMessage(message, "DEBUG", bcolors.PINK, of="debug.txt")
logMessage(message, "DEBUG", bcolors.PINK)
def chat(message):
"""

View File

@ -1,86 +1,7 @@
import tornado
import tornado.web
import tornado.gen
from tornado.ioloop import IOLoop
from objects import glob
from raven.contrib.tornado import SentryMixin
from raven.contrib.tornado import AsyncSentryClient
class asyncRequestHandler(tornado.web.RequestHandler):
"""
Tornado asynchronous request handler
create a class that extends this one (requestHelper.asyncRequestHandler)
use asyncGet() and asyncPost() instad of get() and post().
Done. I'm not kidding.
"""
@tornado.web.asynchronous
@tornado.gen.engine
def get(self, *args, **kwargs):
try:
yield tornado.gen.Task(runBackground, (self.asyncGet, tuple(args), dict(kwargs)))
except Exception as e:
yield tornado.gen.Task(self.captureException, exc_info=True)
finally:
if not self._finished:
self.finish()
@tornado.web.asynchronous
@tornado.gen.engine
def post(self, *args, **kwargs):
try:
yield tornado.gen.Task(runBackground, (self.asyncPost, tuple(args), dict(kwargs)))
except Exception as e:
yield tornado.gen.Task(self.captureException, exc_info=True)
finally:
if not self._finished:
self.finish()
def asyncGet(self, *args, **kwargs):
self.send_error(405)
self.finish()
def asyncPost(self, *args, **kwargs):
self.send_error(405)
self.finish()
def getRequestIP(self):
realIP = self.request.headers.get("X-Forwarded-For") if glob.cloudflare == True else self.request.headers.get("X-Real-IP")
if realIP != None:
return realIP
return self.request.remote_ip
def runBackground(data, callback):
"""
Run a function in the background.
Used to handle multiple requests at the same time
"""
func, args, kwargs = data
def _callback(result):
IOLoop.instance().add_callback(lambda: callback(result))
glob.pool.apply_async(func, args, kwargs, _callback)
def checkArguments(arguments, requiredArguments):
"""
Check that every requiredArguments elements are in arguments
arguments -- full argument list, from tornado
requiredArguments -- required arguments list es: ["u", "ha"]
handler -- handler string name to print in exception. Optional
return -- True if all arguments are passed, none if not
"""
for i in requiredArguments:
if i not in arguments:
return False
return True
def printArguments(t):
"""
Print passed arguments, for debug purposes
t -- tornado object (self)
"""
print("ARGS::")
for i in t.request.arguments:
print ("{}={}".format(i, t.get_argument(i)))
def getRequestIP(bottleRequest):
realIP = bottleRequest.headers.get("X-Forwarded-For") if glob.cloudflare == True else bottleRequest.headers.get("X-Real-IP")
if realIP != None:
return realIP
return bottleRequest.environ.get("REMOTE_ADDR")

View File

@ -8,14 +8,14 @@ class banchoConfig:
config = {"banchoMaintenance": False, "freeDirect": True, "menuIcon": "", "loginNotification": ""}
def __init__(self, __loadFromDB = True):
def __init__(self, loadFromDB = True):
"""
Initialize a banchoConfig object (and load bancho_settings from db)
[__loadFromDB -- if True, load values from db. If False, don't load values. Default: True]
[loadFromDB -- if True, load values from db. If False, don't load values. Default: True]
"""
if __loadFromDB:
if loadFromDB:
try:
self.loadSettings()
except:
@ -31,12 +31,12 @@ class banchoConfig:
self.config["menuIcon"] = glob.db.fetch("SELECT value_string FROM bancho_settings WHERE name = 'menu_icon'")["value_string"]
self.config["loginNotification"] = glob.db.fetch("SELECT value_string FROM bancho_settings WHERE name = 'login_notification'")["value_string"]
def setMaintenance(self, __maintenance):
def setMaintenance(self, maintenance):
"""
Turn on/off bancho maintenance mode. Write new value to db too
__maintenance -- if True, turn on maintenance mode. If false, turn it off
maintenance -- if True, turn on maintenance mode. If false, turn it off
"""
self.config["banchoMaintenance"] = __maintenance
glob.db.execute("UPDATE bancho_settings SET value_int = %s WHERE name = 'bancho_maintenance'", [int(__maintenance)])
self.config["banchoMaintenance"] = maintenance
glob.db.execute("UPDATE bancho_settings SET value_int = %s WHERE name = 'bancho_maintenance'", [int(maintenance)])

View File

@ -5,22 +5,22 @@ class channel:
A chat channel
"""
def __init__(self, __name, __description, __publicRead, __publicWrite, temp, hidden):
def __init__(self, name, description, publicRead, publicWrite, temp, hidden):
"""
Create a new chat channel object
__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
hidden -- if True, channel won't be shown in channels list
"""
self.name = __name
self.description = __description
self.publicRead = __publicRead
self.publicWrite = __publicWrite
self.name = name
self.description = description
self.publicRead = publicRead
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)
@ -34,26 +34,26 @@ class channel:
self.clientName = "#multiplayer"
def userJoin(self, __userID):
def userJoin(self, userID):
"""
Add a user to connected users
__userID -- user ID that joined the channel
userID -- user ID that joined the channel
"""
if __userID not in self.connectedUsers:
self.connectedUsers.append(__userID)
if userID not in self.connectedUsers:
self.connectedUsers.append(userID)
def userPart(self, __userID):
def userPart(self, userID):
"""
Remove a user from connected users
__userID -- user ID that left the channel
userID -- user ID that left the channel
"""
if __userID in self.connectedUsers:
self.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)

View File

@ -56,6 +56,7 @@ class channelList:
self.channels[name] = channel.channel(name, "Chat", True, True, True, True)
log.info("Created temp channel {}".format(name))
def removeChannel(self, name):
"""
Removes a channel from channels list

View File

@ -12,23 +12,17 @@ npRegex = re.compile("^https?:\\/\\/osu\\.ppy\\.sh\\/b\\/(\\d*)")
def connect():
"""Add FokaBot to connected users and send userpanel/stats packet to everyone"""
token = glob.tokens.addToken(999)
token.actionID = actions.idle
glob.tokens.enqueueAll(serverPackets.userPanel(999))
####glob.tokens.enqueueAll(serverPackets.userStats(999))
glob.tokens.enqueueAll(serverPackets.userStats(999))
# NOTE: Debug thing to set all users as connected
#users = glob.db.fetchAll("SELECT id FROM users")
#for i in users:
# t = glob.tokens.addToken(i["id"])
# t.actionID = actions.idle
def disconnect():
"""Remove FokaBot from connected users"""
glob.tokens.deleteToken(glob.tokens.getTokenFromUserID(999))
def fokabotResponse(fro, chan, message):
"""
Check if a message has triggered fokabot (and return its response)
@ -39,7 +33,6 @@ def fokabotResponse(fro, chan, message):
return -- fokabot's response string or False
"""
for i in fokabotCommands.commands:
# Loop though all commands
#if i["trigger"] in message:

View File

@ -20,7 +20,6 @@ tokens = tokenList.tokenList()
channels = channelList.channelList()
matches = matchList.matchList()
restarting = False
pool = None
fLocks = fileLocks.fileLocks()
verifiedCache = {}
cloudflare = False

View File

@ -1,24 +0,0 @@
'''
import threading
class task:
def __init__(self, function, args = (), kwargs = {}):
self.function = function
self.args = args
self.kwargs = kwargs
class logThread:
def __init__(self):
self.thread = threading.Thread()
self.queue = []
def enqueue(self, function, args = (), kwargs = {}):
self.queue.append(task(function, args, kwargs))
def run(self):
for i in self.queue:
self.thread = threading.Thread(i.function, i.args, i.kwargs)
self.thread.run()
self.thread.join()
self.queue = []
'''

View File

@ -29,29 +29,29 @@ class match:
matchModMode = matchModModes.normal
seed = 0
def __init__(self, __matchID, __matchName, __matchPassword, __beatmapID, __beatmapName, __beatmapMD5, __gameMode, __hostUserID):
def __init__(self, matchID, matchName, matchPassword, beatmapID, beatmapName, beatmapMD5, gameMode, hostUserID):
"""
Create a new match object
__matchID -- match progressive identifier
__matchName -- match name, string
__matchPassword -- match md5 password. Leave empty for no password
__beatmapID -- beatmap ID
__beatmapName -- beatmap name, string
__beatmapMD5 -- beatmap md5 hash, string
__gameMode -- game mode ID. See gameModes.py
__hostUserID -- user id of the host
matchID -- match progressive identifier
matchName -- match name, string
matchPassword -- match md5 password. Leave empty for no password
beatmapID -- beatmap ID
beatmapName -- beatmap name, string
beatmapMD5 -- beatmap md5 hash, string
gameMode -- game mode ID. See gameModes.py
hostUserID -- user id of the host
"""
self.matchID = __matchID
self.matchID = matchID
self.inProgress = False
self.mods = 0
self.matchName = __matchName
self.matchPassword = __matchPassword
self.beatmapID = __beatmapID
self.beatmapName = __beatmapName
self.beatmapMD5 = __beatmapMD5
self.hostUserID = __hostUserID
self.gameMode = __gameMode
self.matchName = matchName
self.matchPassword = matchPassword
self.beatmapID = beatmapID
self.beatmapName = beatmapName
self.beatmapMD5 = beatmapMD5
self.hostUserID = hostUserID
self.gameMode = gameMode
self.matchScoringTypes = matchScoringTypes.score # default values
self.matchTeamType = matchTeamTypes.headToHead # default value
self.matchModMode = matchModModes.normal # default value
@ -618,8 +618,6 @@ class match:
self.setSlot(slotID, None, newTeam)
self.sendUpdate()
def sendUpdate(self):
# Send to users in room
for i in range(0,16):

View File

@ -13,50 +13,50 @@ class matchList:
self.usersInLobby = []
self.lastID = 1
def createMatch(self, __matchName, __matchPassword, __beatmapID, __beatmapName, __beatmapMD5, __gameMode, __hostUserID):
def createMatch(self, matchName, matchPassword, beatmapID, beatmapName, beatmapMD5, gameMode, hostUserID):
"""
Add a new match to matches list
__matchName -- match name, string
__matchPassword -- match md5 password. Leave empty for no password
__beatmapID -- beatmap ID
__beatmapName -- beatmap name, string
__beatmapMD5 -- beatmap md5 hash, string
__gameMode -- game mode ID. See gameModes.py
__hostUserID -- user id of who created the match
matchName -- match name, string
matchPassword -- match md5 password. Leave empty for no password
beatmapID -- beatmap ID
beatmapName -- beatmap name, string
beatmapMD5 -- beatmap md5 hash, string
gameMode -- game mode ID. See gameModes.py
hostUserID -- user id of who created the match
return -- match ID
"""
# Add a new match to matches list
matchID = self.lastID
self.lastID+=1
self.matches[matchID] = match.match(matchID, __matchName, __matchPassword, __beatmapID, __beatmapName, __beatmapMD5, __gameMode, __hostUserID)
self.matches[matchID] = match.match(matchID, matchName, matchPassword, beatmapID, beatmapName, beatmapMD5, gameMode, hostUserID)
return matchID
def lobbyUserJoin(self, __userID):
def lobbyUserJoin(self, userID):
"""
Add userID to users in lobby
__userID -- user who joined mp lobby
userID -- user who joined mp lobby
"""
# Make sure the user is not already in mp lobby
if __userID not in self.usersInLobby:
if userID not in self.usersInLobby:
# We don't need to join #lobby, client will automatically send a packet for it
self.usersInLobby.append(__userID)
self.usersInLobby.append(userID)
def lobbyUserPart(self, __userID):
def lobbyUserPart(self, userID):
"""
Remove userID from users in lobby
__userID -- user who left mp lobby
userID -- user who left mp lobby
"""
# Make sure the user is in mp lobby
if __userID in self.usersInLobby:
if userID in self.usersInLobby:
# Part lobby and #lobby channel
self.usersInLobby.remove(__userID)
self.usersInLobby.remove(userID)
def disposeMatch(self, __matchID):

View File

@ -35,11 +35,11 @@ class token:
"""
def __init__(self, __userID, token = None, ip = "", irc = False, timeOffset = 0):
def __init__(self, userID, token = None, ip = "", irc = False, timeOffset = 0):
"""
Create a token object and set userID and token
__userID -- user associated to this token
userID -- user associated to this token
token -- if passed, set token to that value
if not passed, token will be generated
ip -- client ip. optional.
@ -47,7 +47,7 @@ class token:
"""
# Set stuff
self.userID = __userID
self.userID = userID
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")
@ -102,12 +102,6 @@ class token:
if ip != "":
userHelper.saveBanchoSession(self.userID, self.ip)
# If we are restricted, send message from FokaBot to user
# NOTE: Sent later
#if self.restricted == True:
# self.setRestricted()
def enqueue(self, __bytes):
"""
Add bytes (packets) to queue
@ -164,11 +158,11 @@ class token:
return self.location[1]
def startSpectating(self, __userID):
"""Set the spectating user to __userID
def startSpectating(self, userID):
"""Set the spectating user to userID
__userID -- target userID"""
self.spectating = __userID
userID -- target userID"""
self.spectating = userID
def stopSpectating(self):
@ -176,24 +170,24 @@ class token:
self.spectating = 0
def addSpectator(self, __userID):
"""Add __userID to our spectators
def addSpectator(self, userID):
"""Add userID to our spectators
userID -- new spectator userID"""
# Add userID to spectators if not already in
if __userID not in self.spectators:
self.spectators.append(__userID)
if userID not in self.spectators:
self.spectators.append(userID)
def removeSpectator(self, __userID):
"""Remove __userID from our spectators
def removeSpectator(self, userID):
"""Remove userID from our spectators
userID -- old spectator userID"""
# Remove spectator
if __userID in self.spectators:
self.spectators.remove(__userID)
if userID in self.spectators:
self.spectators.remove(userID)
def setCountry(self, __countryID):

65
pep.py
View File

@ -1,17 +1,12 @@
"""Hello, pep.py here, ex-owner of ripple and prime minister of Ripwot."""
import sys
import os
from multiprocessing.pool import ThreadPool
import threading
# Tornado
import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.gen
# Raven
from raven.contrib.tornado import AsyncSentryClient
# Bottle
import bottle
from gevent import monkey as brit_monkey
brit_monkey.patch_all()
# pep.py files
from constants import bcolors
@ -25,27 +20,13 @@ from helpers import databaseHelperNew
from helpers import generalFunctions
from helpers import logHelper as log
from handlers import mainHandler
from handlers import apiIsOnlineHandler
from handlers import apiOnlineUsersHandler
from handlers import apiServerStatusHandler
from handlers import ciTriggerHandler
from handlers import apiVerifiedStatusHandler
from handlers import fokabotMessageHandler
# Raven
from raven import Client
from raven.contrib.bottle import Sentry
# IRC
from irc import ircserver
def make_app():
return tornado.web.Application([
(r"/", mainHandler.handler),
(r"/api/v1/isOnline", apiIsOnlineHandler.handler),
(r"/api/v1/onlineUsers", apiOnlineUsersHandler.handler),
(r"/api/v1/serverStatus", apiServerStatusHandler.handler),
(r"/api/v1/ciTrigger", ciTriggerHandler.handler),
(r"/api/v1/verifiedStatus", apiVerifiedStatusHandler.handler),
(r"/api/v1/fokabotMessage", fokabotMessageHandler.handler)
])
if __name__ == "__main__":
# Server start
consoleHelper.printServerStartHeader(True)
@ -98,15 +79,6 @@ if __name__ == "__main__":
glob.tokens.deleteBanchoSessions()
consoleHelper.printDone()
# Create threads pool
try:
consoleHelper.printNoNl("> Creating threads pool... ")
glob.pool = ThreadPool(int(glob.conf.config["server"]["threads"]))
consoleHelper.printDone()
except:
consoleHelper.printError()
consoleHelper.printColored("[!] Error while creating threads pool. Please check your config.ini and run the server again", bcolors.RED)
try:
consoleHelper.printNoNl("> Loading chat filters... ")
glob.chatFilters = chatFilters.chatFilters()
@ -168,13 +140,21 @@ if __name__ == "__main__":
consoleHelper.printColored("[!] Warning! Server running in debug mode!", bcolors.YELLOW)
# Make app
application = make_app()
app = bottle.app()
app.catchall = False
from handlers import mainHandler
from handlers import apiIsOnlineHandler
from handlers import apiServerStatusHandler
from handlers import ciTriggerHandler
from handlers import apiVerifiedStatusHandler
from handlers import apiFokabotMessageHandler
# Set up sentry
try:
glob.sentry = generalFunctions.stringToBool(glob.conf.config["sentry"]["enable"])
if glob.sentry == True:
application.sentry_client = AsyncSentryClient(glob.conf.config["sentry"]["banchodns"], release=glob.VERSION)
client = Client(glob.conf.config["sentry"]["banchodns"], release=glob.VERSION)
app = Sentry(app, client)
else:
consoleHelper.printColored("[!] Warning! Sentry logging is disabled!", bcolors.YELLOW)
except:
@ -204,9 +184,8 @@ if __name__ == "__main__":
consoleHelper.printColored("[!] Invalid server port! Please check your config.ini and run the server again", bcolors.RED)
# Server start message and console output
log.logMessage("Server started!", discord=True, of="info.txt", stdout=False)
consoleHelper.printColored("> Tornado listening for HTTP(s) clients on 127.0.0.1:{}...".format(serverPort), bcolors.GREEN)
log.logMessage("Server started!", discord=True, stdout=False)
consoleHelper.printColored("> Bottle listening for HTTP(s) clients on 127.0.0.1:{}...".format(serverPort), bcolors.GREEN)
# Start tornado
application.listen(serverPort)
tornado.ioloop.IOLoop.instance().start()
# Start bottle
bottle.run(app=app, host="0.0.0.0", port=serverPort, server="gevent", quiet=True)

View File

@ -0,0 +1 @@
1.7.0