.BANCHO. Bancho now uses mysqldb instead of pymysql
This commit is contained in:
parent
26f64e8610
commit
aebf910890
|
@ -481,7 +481,7 @@ def tillerinoLast(fro, chan, message):
|
||||||
FROM scores
|
FROM scores
|
||||||
LEFT JOIN beatmaps ON beatmaps.beatmap_md5=scores.beatmap_md5
|
LEFT JOIN beatmaps ON beatmaps.beatmap_md5=scores.beatmap_md5
|
||||||
LEFT JOIN users ON users.id = scores.userid
|
LEFT JOIN users ON users.id = scores.userid
|
||||||
WHERE users.username = ?
|
WHERE users.username = %s
|
||||||
ORDER BY scores.time DESC
|
ORDER BY scores.time DESC
|
||||||
LIMIT 1""", [fro])
|
LIMIT 1""", [fro])
|
||||||
if data == None:
|
if data == None:
|
||||||
|
|
|
@ -11,23 +11,22 @@ from helpers import generalFunctions
|
||||||
from events import channelJoinEvent
|
from events import channelJoinEvent
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
from helpers import requestHelper
|
||||||
|
|
||||||
def handle(flaskRequest):
|
def handle(tornadoRequest):
|
||||||
# Data to return
|
# Data to return
|
||||||
responseTokenString = "ayy"
|
responseTokenString = "ayy"
|
||||||
responseData = bytes()
|
responseData = bytes()
|
||||||
|
|
||||||
# Get IP from flask request
|
# Get IP from flask request
|
||||||
requestIP = flaskRequest.headers.get('X-Real-IP')
|
requestIP = tornadoRequest.getRequestIP()
|
||||||
if requestIP == None:
|
|
||||||
requestIP = flaskRequest.remote_addr
|
|
||||||
|
|
||||||
# Console output
|
# Console output
|
||||||
print("> Accepting connection from {}...".format(requestIP))
|
print("> Accepting connection from {}...".format(requestIP))
|
||||||
|
|
||||||
# Split POST body so we can get username/password/hardware data
|
# 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
|
# 2:-3 thing is because requestData has some escape stuff that we don't need
|
||||||
loginData = str(flaskRequest.data)[2:-3].split("\\n")
|
loginData = str(tornadoRequest.request.body)[2:-3].split("\\n")
|
||||||
|
|
||||||
# Process login
|
# Process login
|
||||||
print("> Processing login request for {}...".format(loginData[0]))
|
print("> Processing login request for {}...".format(loginData[0]))
|
||||||
|
|
215
handlers/mainHandler.py
Normal file
215
handlers/mainHandler.py
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
import datetime
|
||||||
|
import gzip
|
||||||
|
from helpers import requestHelper
|
||||||
|
from objects import glob
|
||||||
|
from helpers import consoleHelper
|
||||||
|
from constants import bcolors
|
||||||
|
from constants import exceptions
|
||||||
|
from constants import packetIDs
|
||||||
|
from helpers import packetHelper
|
||||||
|
from constants import serverPackets
|
||||||
|
from events import sendPublicMessageEvent
|
||||||
|
from events import sendPrivateMessageEvent
|
||||||
|
from events import channelJoinEvent
|
||||||
|
from events import channelPartEvent
|
||||||
|
from events import changeActionEvent
|
||||||
|
from events import cantSpectateEvent
|
||||||
|
from events import startSpectatingEvent
|
||||||
|
from events import stopSpectatingEvent
|
||||||
|
from events import spectateFramesEvent
|
||||||
|
from events import friendAddEvent
|
||||||
|
from events import friendRemoveEvent
|
||||||
|
from events import logoutEvent
|
||||||
|
from events import loginEvent
|
||||||
|
from events import setAwayMessageEvent
|
||||||
|
from events import joinLobbyEvent
|
||||||
|
from events import createMatchEvent
|
||||||
|
from events import partLobbyEvent
|
||||||
|
from events import changeSlotEvent
|
||||||
|
from events import joinMatchEvent
|
||||||
|
from events import partMatchEvent
|
||||||
|
from events import changeMatchSettingsEvent
|
||||||
|
from events import changeMatchPasswordEvent
|
||||||
|
from events import changeMatchModsEvent
|
||||||
|
from events import matchReadyEvent
|
||||||
|
from events import matchLockEvent
|
||||||
|
from events import matchStartEvent
|
||||||
|
from events import matchPlayerLoadEvent
|
||||||
|
from events import matchSkipEvent
|
||||||
|
from events import matchFramesEvent
|
||||||
|
from events import matchCompleteEvent
|
||||||
|
from events import matchNoBeatmapEvent
|
||||||
|
from events import matchHasBeatmapEvent
|
||||||
|
from events import matchTransferHostEvent
|
||||||
|
from events import matchFailedEvent
|
||||||
|
from events import matchInviteEvent
|
||||||
|
from events import matchChangeTeamEvent
|
||||||
|
from helpers import discordBotHelper
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
class handler(requestHelper.asyncRequestHandler):
|
||||||
|
def asyncPost(self):
|
||||||
|
try:
|
||||||
|
# Track time if needed
|
||||||
|
if glob.requestTime == True:
|
||||||
|
# Start time
|
||||||
|
st = datetime.datetime.now()
|
||||||
|
|
||||||
|
# Client's token string and request data
|
||||||
|
requestTokenString = self.request.headers.get('osu-token')
|
||||||
|
requestData = self.request.body
|
||||||
|
|
||||||
|
# Server's token string and request data
|
||||||
|
responseTokenString = "ayy"
|
||||||
|
responseData = bytes()
|
||||||
|
|
||||||
|
if requestTokenString == None:
|
||||||
|
# No token, first request. Handle login.
|
||||||
|
responseTokenString, responseData = loginEvent.handle(self)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
# This is not the first packet, send response based on client's request
|
||||||
|
# Packet start position, used to read stacked packets
|
||||||
|
pos = 0
|
||||||
|
|
||||||
|
# Make sure the token exists
|
||||||
|
if requestTokenString not in glob.tokens.tokens:
|
||||||
|
raise exceptions.tokenNotFoundException()
|
||||||
|
|
||||||
|
# Token exists, get its object
|
||||||
|
userToken = glob.tokens.tokens[requestTokenString]
|
||||||
|
|
||||||
|
# Keep reading packets until everything has been read
|
||||||
|
while pos < len(requestData):
|
||||||
|
# Get packet from stack starting from new packet
|
||||||
|
leftData = requestData[pos:]
|
||||||
|
|
||||||
|
# Get packet ID, data length and data
|
||||||
|
packetID = packetHelper.readPacketID(leftData)
|
||||||
|
dataLength = packetHelper.readPacketLength(leftData)
|
||||||
|
packetData = requestData[pos:(pos+dataLength+7)]
|
||||||
|
|
||||||
|
# Console output if needed
|
||||||
|
if glob.conf.config["server"]["outputpackets"] == True and packetID != 4:
|
||||||
|
consoleHelper.printColored("Incoming packet ({})({}):".format(requestTokenString, userToken.username), bcolors.GREEN)
|
||||||
|
consoleHelper.printColored("Packet code: {}\nPacket length: {}\nSingle packet data: {}\n".format(str(packetID), str(dataLength), str(packetData)), bcolors.YELLOW)
|
||||||
|
|
||||||
|
# Event handler
|
||||||
|
def handleEvent(ev):
|
||||||
|
def wrapper():
|
||||||
|
ev.handle(userToken, packetData)
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
eventHandler = {
|
||||||
|
# TODO: Rename packets and events
|
||||||
|
# TODO: Host check for multi
|
||||||
|
packetIDs.client_sendPublicMessage: handleEvent(sendPublicMessageEvent),
|
||||||
|
packetIDs.client_sendPrivateMessage: handleEvent(sendPrivateMessageEvent),
|
||||||
|
packetIDs.client_setAwayMessage: handleEvent(setAwayMessageEvent),
|
||||||
|
packetIDs.client_channelJoin: handleEvent(channelJoinEvent),
|
||||||
|
packetIDs.client_channelPart: handleEvent(channelPartEvent),
|
||||||
|
packetIDs.client_changeAction: handleEvent(changeActionEvent),
|
||||||
|
packetIDs.client_startSpectating: handleEvent(startSpectatingEvent),
|
||||||
|
packetIDs.client_stopSpectating: handleEvent(stopSpectatingEvent),
|
||||||
|
packetIDs.client_cantSpectate: handleEvent(cantSpectateEvent),
|
||||||
|
packetIDs.client_spectateFrames: handleEvent(spectateFramesEvent),
|
||||||
|
packetIDs.client_friendAdd: handleEvent(friendAddEvent),
|
||||||
|
packetIDs.client_friendRemove: handleEvent(friendRemoveEvent),
|
||||||
|
packetIDs.client_logout: handleEvent(logoutEvent),
|
||||||
|
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_invite: handleEvent(matchInviteEvent),
|
||||||
|
packetIDs.client_matchChangeTeam: handleEvent(matchChangeTeamEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packetID != 4:
|
||||||
|
if packetID in eventHandler:
|
||||||
|
eventHandler[packetID]()
|
||||||
|
else:
|
||||||
|
consoleHelper.printColored("[!] Unknown packet id from {} ({})".format(requestTokenString, packetID), bcolors.RED)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Token queue built, send it
|
||||||
|
responseTokenString = userToken.token
|
||||||
|
responseData = userToken.queue
|
||||||
|
userToken.resetQueue()
|
||||||
|
|
||||||
|
# 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.")
|
||||||
|
consoleHelper.printColored("[!] Received packet from unknown token ({}).".format(requestTokenString), bcolors.RED)
|
||||||
|
consoleHelper.printColored("> {} have been disconnected (invalid token)".format(requestTokenString), bcolors.YELLOW)
|
||||||
|
|
||||||
|
if glob.requestTime == True:
|
||||||
|
# End time
|
||||||
|
et = datetime.datetime.now()
|
||||||
|
|
||||||
|
# Total time:
|
||||||
|
tt = float((et.microsecond-st.microsecond)/1000)
|
||||||
|
consoleHelper.printColored("Request time: {}ms".format(tt), bcolors.PINK)
|
||||||
|
|
||||||
|
# Send server's response to client
|
||||||
|
# We don't use token object because we might not have a token (failed login)
|
||||||
|
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")
|
||||||
|
self.add_header("Vary", "Accept-Encoding")
|
||||||
|
self.add_header("Content-Encoding", "gzip")
|
||||||
|
self.write(gzip.compress(responseData, 6))
|
||||||
|
self.finish()
|
||||||
|
except:
|
||||||
|
msg = "**asyncppytornadovroom error** *(aka test server, ignore this)*\nUnhandled exception in mainHandler:\n```\n{}\n{}\n```".format(sys.exc_info(), traceback.format_exc())
|
||||||
|
consoleHelper.printColored("[!] {}".format(msg), bcolors.RED)
|
||||||
|
discordBotHelper.sendConfidential(msg)
|
||||||
|
|
||||||
|
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.</pre></body></html>"
|
||||||
|
self.write(html)
|
||||||
|
self.finish()
|
|
@ -46,10 +46,9 @@ class config:
|
||||||
self.config.get("db","username")
|
self.config.get("db","username")
|
||||||
self.config.get("db","password")
|
self.config.get("db","password")
|
||||||
self.config.get("db","database")
|
self.config.get("db","database")
|
||||||
self.config.get("db","pingtime")
|
self.config.get("db","workers")
|
||||||
|
|
||||||
self.config.get("server","server")
|
self.config.get("server","threads")
|
||||||
self.config.get("server","host")
|
|
||||||
self.config.get("server","port")
|
self.config.get("server","port")
|
||||||
self.config.get("server","localizeusers")
|
self.config.get("server","localizeusers")
|
||||||
self.config.get("server","outputpackets")
|
self.config.get("server","outputpackets")
|
||||||
|
@ -57,12 +56,6 @@ class config:
|
||||||
self.config.get("server","timeouttime")
|
self.config.get("server","timeouttime")
|
||||||
self.config.get("server","timeoutlooptime")
|
self.config.get("server","timeoutlooptime")
|
||||||
|
|
||||||
if self.config["server"]["server"] == "flask":
|
|
||||||
# Flask only config
|
|
||||||
self.config.get("flask","threaded")
|
|
||||||
self.config.get("flask","debug")
|
|
||||||
self.config.get("flask","logger")
|
|
||||||
|
|
||||||
self.config.get("discord","enable")
|
self.config.get("discord","enable")
|
||||||
self.config.get("discord","boturl")
|
self.config.get("discord","boturl")
|
||||||
|
|
||||||
|
@ -85,11 +78,10 @@ class config:
|
||||||
self.config.set("db", "username", "root")
|
self.config.set("db", "username", "root")
|
||||||
self.config.set("db", "password", "")
|
self.config.set("db", "password", "")
|
||||||
self.config.set("db", "database", "ripple")
|
self.config.set("db", "database", "ripple")
|
||||||
self.config.set("db", "pingtime", "600")
|
self.config.set("db", "workers", "4")
|
||||||
|
|
||||||
self.config.add_section("server")
|
self.config.add_section("server")
|
||||||
self.config.set("server", "server", "tornado")
|
self.config.set("server", "threads", "16")
|
||||||
self.config.set("server", "host", "0.0.0.0")
|
|
||||||
self.config.set("server", "port", "5001")
|
self.config.set("server", "port", "5001")
|
||||||
self.config.set("server", "localizeusers", "1")
|
self.config.set("server", "localizeusers", "1")
|
||||||
self.config.set("server", "outputpackets", "0")
|
self.config.set("server", "outputpackets", "0")
|
||||||
|
@ -97,18 +89,13 @@ class config:
|
||||||
self.config.set("server", "timeoutlooptime", "100")
|
self.config.set("server", "timeoutlooptime", "100")
|
||||||
self.config.set("server", "timeouttime", "100")
|
self.config.set("server", "timeouttime", "100")
|
||||||
|
|
||||||
self.config.add_section("flask")
|
|
||||||
self.config.set("flask", "threaded", "1")
|
|
||||||
self.config.set("flask", "debug", "0")
|
|
||||||
self.config.set("flask", "logger", "0")
|
|
||||||
|
|
||||||
self.config.add_section("ci")
|
self.config.add_section("ci")
|
||||||
self.config.set("ci", "key", "changeme")
|
self.config.set("ci", "key", "changeme")
|
||||||
|
|
||||||
self.config.add_section("discord")
|
self.config.add_section("discord")
|
||||||
self.config.set("discord", "enable", "False")
|
self.config.set("discord", "enable", "False")
|
||||||
self.config.set("discord", "boturl", "")
|
self.config.set("discord", "boturl", "")
|
||||||
|
|
||||||
# Write ini to file and close
|
# Write ini to file and close
|
||||||
self.config.write(f)
|
self.config.write(f)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
118
helpers/databaseHelperNew.py
Normal file
118
helpers/databaseHelperNew.py
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
import MySQLdb
|
||||||
|
import threading
|
||||||
|
|
||||||
|
class mysqlWorker:
|
||||||
|
"""
|
||||||
|
Instance of a pettirosso meme
|
||||||
|
"""
|
||||||
|
def __init__(self, wid, host, username, password, database):
|
||||||
|
"""
|
||||||
|
Create a pettirosso meme (mysql worker)
|
||||||
|
|
||||||
|
wid -- worker id
|
||||||
|
host -- hostname
|
||||||
|
username -- MySQL username
|
||||||
|
password -- MySQL password
|
||||||
|
database -- MySQL database name
|
||||||
|
"""
|
||||||
|
self.wid = wid
|
||||||
|
self.connection = MySQLdb.connect(host, username, password, database)
|
||||||
|
self.connection.autocommit(True)
|
||||||
|
self.ready = True
|
||||||
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
|
class db:
|
||||||
|
"""
|
||||||
|
A MySQL db connection with multiple workers
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, host, username, password, database, workers):
|
||||||
|
"""
|
||||||
|
Create MySQL workers aka pettirossi meme
|
||||||
|
|
||||||
|
host -- hostname
|
||||||
|
username -- MySQL username
|
||||||
|
password -- MySQL password
|
||||||
|
database -- MySQL database name
|
||||||
|
workers -- Number of workers to spawn
|
||||||
|
"""
|
||||||
|
#self.lock = threading.Lock()
|
||||||
|
#self.connection = MySQLdb.connect(host, username, password, database)
|
||||||
|
|
||||||
|
self.workers = []
|
||||||
|
self.lastWorker = 0
|
||||||
|
self.workersNumber = workers
|
||||||
|
for i in range(0,self.workersNumber):
|
||||||
|
print("> Spawning MySQL pettirosso meme {}".format(i))
|
||||||
|
self.workers.append(mysqlWorker(i, host, username, password, database))
|
||||||
|
|
||||||
|
def getWorker(self):
|
||||||
|
"""
|
||||||
|
Return a worker object (round-robin way)
|
||||||
|
|
||||||
|
return -- worker object
|
||||||
|
"""
|
||||||
|
if self.lastWorker >= self.workersNumber-1:
|
||||||
|
self.lastWorker = 0
|
||||||
|
else:
|
||||||
|
self.lastWorker += 1
|
||||||
|
#print("Using worker {}".format(self.lastWorker))
|
||||||
|
return self.workers[self.lastWorker]
|
||||||
|
|
||||||
|
def execute(self, query, params = ()):
|
||||||
|
"""
|
||||||
|
Executes a query
|
||||||
|
|
||||||
|
query -- Query to execute. You can bind parameters with %s
|
||||||
|
params -- Parameters list. First element replaces first %s and so on. Optional.
|
||||||
|
"""
|
||||||
|
# Get a worker and acquire its lock
|
||||||
|
worker = self.getWorker()
|
||||||
|
worker.lock.acquire()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Create cursor, execute query and commit
|
||||||
|
cursor = worker.connection.cursor(MySQLdb.cursors.DictCursor)
|
||||||
|
cursor.execute(query, params)
|
||||||
|
return cursor.lastrowid
|
||||||
|
finally:
|
||||||
|
# Close the cursor and release worker's lock
|
||||||
|
if cursor:
|
||||||
|
cursor.close()
|
||||||
|
worker.lock.release()
|
||||||
|
|
||||||
|
def fetch(self, query, params = (), all = False):
|
||||||
|
"""
|
||||||
|
Fetch a single value from db that matches given query
|
||||||
|
|
||||||
|
query -- Query to execute. You can bind parameters with %s
|
||||||
|
params -- Parameters list. First element replaces first %s and so on. Optional.
|
||||||
|
all -- Fetch one or all values. Used internally. Use fetchAll if you want to fetch all values.
|
||||||
|
"""
|
||||||
|
# Get a worker and acquire its lock
|
||||||
|
worker = self.getWorker()
|
||||||
|
worker.lock.acquire()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Create cursor, execute the query and fetch one/all result(s)
|
||||||
|
cursor = worker.connection.cursor(MySQLdb.cursors.DictCursor)
|
||||||
|
cursor.execute(query, params)
|
||||||
|
if all == True:
|
||||||
|
return cursor.fetchall()
|
||||||
|
else:
|
||||||
|
return cursor.fetchone()
|
||||||
|
finally:
|
||||||
|
# Close the cursor and release worker's lock
|
||||||
|
if cursor:
|
||||||
|
cursor.close()
|
||||||
|
worker.lock.release()
|
||||||
|
|
||||||
|
def fetchAll(self, query, params = ()):
|
||||||
|
"""
|
||||||
|
Fetch all values from db that matche given query.
|
||||||
|
Calls self.fetch with all = True.
|
||||||
|
|
||||||
|
query -- Query to execute. You can bind parameters with %s
|
||||||
|
params -- Parameters list. First element replaces first %s and so on. Optional.
|
||||||
|
"""
|
||||||
|
return self.fetch(query, params, True)
|
72
helpers/requestHelper.py
Normal file
72
helpers/requestHelper.py
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import tornado
|
||||||
|
import tornado.web
|
||||||
|
import tornado.gen
|
||||||
|
from tornado.ioloop import IOLoop
|
||||||
|
from objects import glob
|
||||||
|
|
||||||
|
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):
|
||||||
|
yield tornado.gen.Task(runBackground, (self.asyncGet, tuple(args), dict(kwargs)))
|
||||||
|
|
||||||
|
@tornado.web.asynchronous
|
||||||
|
@tornado.gen.engine
|
||||||
|
def post(self, *args, **kwargs):
|
||||||
|
yield tornado.gen.Task(runBackground, (self.asyncPost, tuple(args), dict(kwargs)))
|
||||||
|
|
||||||
|
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-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)))
|
|
@ -1,47 +0,0 @@
|
||||||
import flask
|
|
||||||
import gzip
|
|
||||||
|
|
||||||
def generateResponse(token, data = None):
|
|
||||||
"""
|
|
||||||
Return a flask response with required headers for osu! client, token and gzip compressed data
|
|
||||||
|
|
||||||
token -- user token
|
|
||||||
data -- plain response body
|
|
||||||
return -- flask response
|
|
||||||
"""
|
|
||||||
|
|
||||||
resp = flask.Response(gzip.compress(data, 6))
|
|
||||||
resp.headers['cho-token'] = token
|
|
||||||
resp.headers['cho-protocol'] = '19'
|
|
||||||
resp.headers['Keep-Alive'] = 'timeout=5, max=100'
|
|
||||||
resp.headers['Connection'] = 'keep-alive'
|
|
||||||
resp.headers['Content-Type'] = 'text/html; charset=UTF-8'
|
|
||||||
resp.headers['Vary'] = 'Accept-Encoding'
|
|
||||||
resp.headers['Content-Encoding'] = 'gzip'
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
def HTMLResponse():
|
|
||||||
"""Return HTML bancho meme response"""
|
|
||||||
|
|
||||||
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.</pre></body></html>"
|
|
||||||
return html
|
|
|
@ -13,7 +13,7 @@ def getID(username):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Get user ID from db
|
# Get user ID from db
|
||||||
userID = glob.db.fetch("SELECT id FROM users WHERE username = ?", [username])
|
userID = glob.db.fetch("SELECT id FROM users WHERE username = %s", [username])
|
||||||
|
|
||||||
# Make sure the query returned something
|
# Make sure the query returned something
|
||||||
if userID == None:
|
if userID == None:
|
||||||
|
@ -34,7 +34,7 @@ def checkLogin(userID, password):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Get password data
|
# Get password data
|
||||||
passwordData = glob.db.fetch("SELECT password_md5, salt, password_version FROM users WHERE id = ?", [userID])
|
passwordData = glob.db.fetch("SELECT password_md5, salt, password_version FROM users WHERE id = %s", [userID])
|
||||||
|
|
||||||
# Make sure the query returned something
|
# Make sure the query returned something
|
||||||
if passwordData == None:
|
if passwordData == None:
|
||||||
|
@ -48,7 +48,7 @@ def checkLogin(userID, password):
|
||||||
ok = passwordHelper.checkOldPassword(password, passwordData["salt"], passwordData["password_md5"])
|
ok = passwordHelper.checkOldPassword(password, passwordData["salt"], passwordData["password_md5"])
|
||||||
if not ok: return False
|
if not ok: return False
|
||||||
newpass = passwordHelper.genBcrypt(password)
|
newpass = passwordHelper.genBcrypt(password)
|
||||||
glob.db.execute("UPDATE users SET password_md5=?, salt='', password_version='2' WHERE id = ?", [newpass, userID])
|
glob.db.execute("UPDATE users SET password_md5=%s, salt='', password_version='2' WHERE id = %s", [newpass, userID])
|
||||||
|
|
||||||
|
|
||||||
def exists(userID):
|
def exists(userID):
|
||||||
|
@ -59,7 +59,7 @@ def exists(userID):
|
||||||
return -- bool
|
return -- bool
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = glob.db.fetch("SELECT id FROM users WHERE id = ?", [userID])
|
result = glob.db.fetch("SELECT id FROM users WHERE id = %s", [userID])
|
||||||
if result == None:
|
if result == None:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
@ -74,7 +74,7 @@ def getAllowed(userID):
|
||||||
return -- allowed int
|
return -- allowed int
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return glob.db.fetch("SELECT allowed FROM users WHERE id = ?", [userID])["allowed"]
|
return glob.db.fetch("SELECT allowed FROM users WHERE id = %s", [userID])["allowed"]
|
||||||
|
|
||||||
|
|
||||||
def getRankPrivileges(userID):
|
def getRankPrivileges(userID):
|
||||||
|
@ -83,7 +83,7 @@ def getRankPrivileges(userID):
|
||||||
If you want to get that rank, user getUserGameRank instead
|
If you want to get that rank, user getUserGameRank instead
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return glob.db.fetch("SELECT rank FROM users WHERE id = ?", [userID])["rank"]
|
return glob.db.fetch("SELECT rank FROM users WHERE id = %s", [userID])["rank"]
|
||||||
|
|
||||||
|
|
||||||
def getSilenceEnd(userID):
|
def getSilenceEnd(userID):
|
||||||
|
@ -95,7 +95,7 @@ def getSilenceEnd(userID):
|
||||||
return -- UNIX time
|
return -- UNIX time
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return glob.db.fetch("SELECT silence_end FROM users WHERE id = ?", [userID])["silence_end"]
|
return glob.db.fetch("SELECT silence_end FROM users WHERE id = %s", [userID])["silence_end"]
|
||||||
|
|
||||||
|
|
||||||
def silence(userID, silenceEndTime, silenceReason):
|
def silence(userID, silenceEndTime, silenceReason):
|
||||||
|
@ -108,7 +108,7 @@ def silence(userID, silenceEndTime, silenceReason):
|
||||||
silenceReason -- Silence reason shown on website
|
silenceReason -- Silence reason shown on website
|
||||||
"""
|
"""
|
||||||
|
|
||||||
glob.db.execute("UPDATE users SET silence_end = ?, silence_reason = ? WHERE id = ?", [silenceEndTime, silenceReason, userID])
|
glob.db.execute("UPDATE users SET silence_end = %s, silence_reason = %s WHERE id = %s", [silenceEndTime, silenceReason, userID])
|
||||||
|
|
||||||
def getRankedScore(userID, gameMode):
|
def getRankedScore(userID, gameMode):
|
||||||
"""
|
"""
|
||||||
|
@ -120,7 +120,7 @@ def getRankedScore(userID, gameMode):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
modeForDB = gameModes.getGameModeForDB(gameMode)
|
modeForDB = gameModes.getGameModeForDB(gameMode)
|
||||||
return glob.db.fetch("SELECT ranked_score_"+modeForDB+" FROM users_stats WHERE id = ?", [userID])["ranked_score_"+modeForDB]
|
return glob.db.fetch("SELECT ranked_score_"+modeForDB+" FROM users_stats WHERE id = %s", [userID])["ranked_score_"+modeForDB]
|
||||||
|
|
||||||
|
|
||||||
def getTotalScore(userID, gameMode):
|
def getTotalScore(userID, gameMode):
|
||||||
|
@ -133,7 +133,7 @@ def getTotalScore(userID, gameMode):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
modeForDB = gameModes.getGameModeForDB(gameMode)
|
modeForDB = gameModes.getGameModeForDB(gameMode)
|
||||||
return glob.db.fetch("SELECT total_score_"+modeForDB+" FROM users_stats WHERE id = ?", [userID])["total_score_"+modeForDB]
|
return glob.db.fetch("SELECT total_score_"+modeForDB+" FROM users_stats WHERE id = %s", [userID])["total_score_"+modeForDB]
|
||||||
|
|
||||||
|
|
||||||
def getAccuracy(userID, gameMode):
|
def getAccuracy(userID, gameMode):
|
||||||
|
@ -146,7 +146,7 @@ def getAccuracy(userID, gameMode):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
modeForDB = gameModes.getGameModeForDB(gameMode)
|
modeForDB = gameModes.getGameModeForDB(gameMode)
|
||||||
return glob.db.fetch("SELECT avg_accuracy_"+modeForDB+" FROM users_stats WHERE id = ?", [userID])["avg_accuracy_"+modeForDB]
|
return glob.db.fetch("SELECT avg_accuracy_"+modeForDB+" FROM users_stats WHERE id = %s", [userID])["avg_accuracy_"+modeForDB]
|
||||||
|
|
||||||
|
|
||||||
def getGameRank(userID, gameMode):
|
def getGameRank(userID, gameMode):
|
||||||
|
@ -159,7 +159,7 @@ def getGameRank(userID, gameMode):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
modeForDB = gameModes.getGameModeForDB(gameMode)
|
modeForDB = gameModes.getGameModeForDB(gameMode)
|
||||||
result = glob.db.fetch("SELECT position FROM leaderboard_"+modeForDB+" WHERE user = ?", [userID])
|
result = glob.db.fetch("SELECT position FROM leaderboard_"+modeForDB+" WHERE user = %s", [userID])
|
||||||
if result == None:
|
if result == None:
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
|
@ -176,7 +176,7 @@ def getPlaycount(userID, gameMode):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
modeForDB = gameModes.getGameModeForDB(gameMode)
|
modeForDB = gameModes.getGameModeForDB(gameMode)
|
||||||
return glob.db.fetch("SELECT playcount_"+modeForDB+" FROM users_stats WHERE id = ?", [userID])["playcount_"+modeForDB]
|
return glob.db.fetch("SELECT playcount_"+modeForDB+" FROM users_stats WHERE id = %s", [userID])["playcount_"+modeForDB]
|
||||||
|
|
||||||
|
|
||||||
def getUsername(userID):
|
def getUsername(userID):
|
||||||
|
@ -187,7 +187,7 @@ def getUsername(userID):
|
||||||
return -- username
|
return -- username
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return glob.db.fetch("SELECT username FROM users WHERE id = ?", [userID])["username"]
|
return glob.db.fetch("SELECT username FROM users WHERE id = %s", [userID])["username"]
|
||||||
|
|
||||||
|
|
||||||
def getFriendList(userID):
|
def getFriendList(userID):
|
||||||
|
@ -199,7 +199,7 @@ def getFriendList(userID):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Get friends from db
|
# Get friends from db
|
||||||
friends = glob.db.fetchAll("SELECT user2 FROM users_relationships WHERE user1 = ?", [userID])
|
friends = glob.db.fetchAll("SELECT user2 FROM users_relationships WHERE user1 = %s", [userID])
|
||||||
|
|
||||||
if friends == None or len(friends) == 0:
|
if friends == None or len(friends) == 0:
|
||||||
# We have no friends, return 0 list
|
# We have no friends, return 0 list
|
||||||
|
@ -225,11 +225,11 @@ def addFriend(userID, friendID):
|
||||||
return
|
return
|
||||||
|
|
||||||
# check user isn't already a friend of ours
|
# check user isn't already a friend of ours
|
||||||
if glob.db.fetch("SELECT id FROM users_relationships WHERE user1 = ? AND user2 = ?", [userID, friendID]) != None:
|
if glob.db.fetch("SELECT id FROM users_relationships WHERE user1 = %s AND user2 = %s", [userID, friendID]) != None:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Set new value
|
# Set new value
|
||||||
glob.db.execute("INSERT INTO users_relationships (user1, user2) VALUES (?, ?)", [userID, friendID])
|
glob.db.execute("INSERT INTO users_relationships (user1, user2) VALUES (%s, %s)", [userID, friendID])
|
||||||
|
|
||||||
|
|
||||||
def removeFriend(userID, friendID):
|
def removeFriend(userID, friendID):
|
||||||
|
@ -242,7 +242,7 @@ def removeFriend(userID, friendID):
|
||||||
|
|
||||||
# Delete user relationship. We don't need to check if the relationship was there, because who gives a shit,
|
# Delete user relationship. We don't need to check if the relationship was there, because who gives a shit,
|
||||||
# if they were not friends and they don't want to be anymore, be it. ¯\_(ツ)_/¯
|
# if they were not friends and they don't want to be anymore, be it. ¯\_(ツ)_/¯
|
||||||
glob.db.execute("DELETE FROM users_relationships WHERE user1 = ? AND user2 = ?", [userID, friendID])
|
glob.db.execute("DELETE FROM users_relationships WHERE user1 = %s AND user2 = %s", [userID, friendID])
|
||||||
|
|
||||||
|
|
||||||
def getCountry(userID):
|
def getCountry(userID):
|
||||||
|
@ -255,7 +255,7 @@ def getCountry(userID):
|
||||||
return -- country code (two letters)
|
return -- country code (two letters)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return glob.db.fetch("SELECT country FROM users_stats WHERE id = ?", [userID])["country"]
|
return glob.db.fetch("SELECT country FROM users_stats WHERE id = %s", [userID])["country"]
|
||||||
|
|
||||||
def getPP(userID, gameMode):
|
def getPP(userID, gameMode):
|
||||||
"""
|
"""
|
||||||
|
@ -266,7 +266,7 @@ def getPP(userID, gameMode):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
modeForDB = gameModes.getGameModeForDB(gameMode)
|
modeForDB = gameModes.getGameModeForDB(gameMode)
|
||||||
return glob.db.fetch("SELECT pp_{} FROM users_stats WHERE id = ?".format(modeForDB), [userID])["pp_{}".format(modeForDB)]
|
return glob.db.fetch("SELECT pp_{} FROM users_stats WHERE id = %s".format(modeForDB), [userID])["pp_{}".format(modeForDB)]
|
||||||
|
|
||||||
def setAllowed(userID, allowed):
|
def setAllowed(userID, allowed):
|
||||||
"""
|
"""
|
||||||
|
@ -275,7 +275,7 @@ def setAllowed(userID, allowed):
|
||||||
userID -- user
|
userID -- user
|
||||||
allowed -- allowed status. 1: normal, 0: banned
|
allowed -- allowed status. 1: normal, 0: banned
|
||||||
"""
|
"""
|
||||||
glob.db.execute("UPDATE users SET allowed = ? WHERE id = ?", [allowed, userID])
|
glob.db.execute("UPDATE users SET allowed = %s WHERE id = %s", [allowed, userID])
|
||||||
|
|
||||||
def setCountry(userID, country):
|
def setCountry(userID, country):
|
||||||
"""
|
"""
|
||||||
|
@ -284,7 +284,7 @@ def setCountry(userID, country):
|
||||||
userID -- userID
|
userID -- userID
|
||||||
country -- country letters
|
country -- country letters
|
||||||
"""
|
"""
|
||||||
glob.db.execute("UPDATE users_stats SET country = ? WHERE id = ?", [country, userID])
|
glob.db.execute("UPDATE users_stats SET country = %s WHERE id = %s", [country, userID])
|
||||||
|
|
||||||
def getShowCountry(userID):
|
def getShowCountry(userID):
|
||||||
"""
|
"""
|
||||||
|
@ -293,7 +293,7 @@ def getShowCountry(userID):
|
||||||
userID -- userID
|
userID -- userID
|
||||||
return -- True if country is shown, False if it's hidden
|
return -- True if country is shown, False if it's hidden
|
||||||
"""
|
"""
|
||||||
country = glob.db.fetch("SELECT show_country FROM users_stats WHERE id = ?", [userID])
|
country = glob.db.fetch("SELECT show_country FROM users_stats WHERE id = %s", [userID])
|
||||||
if country == None:
|
if country == None:
|
||||||
return False
|
return False
|
||||||
return generalFunctions.stringToBool(country)
|
return generalFunctions.stringToBool(country)
|
||||||
|
@ -303,5 +303,5 @@ def IPLog(userID, ip):
|
||||||
Botnet the user
|
Botnet the user
|
||||||
(log his ip for multiaccount detection)
|
(log his ip for multiaccount detection)
|
||||||
"""
|
"""
|
||||||
glob.db.execute("""INSERT INTO ip_user (userid, ip, occurencies) VALUES (?, ?, '1')
|
glob.db.execute("""INSERT INTO ip_user (userid, ip, occurencies) VALUES (%s, %s, '1')
|
||||||
ON DUPLICATE KEY UPDATE occurencies = occurencies + 1""", [userID, ip])
|
ON DUPLICATE KEY UPDATE occurencies = occurencies + 1""", [userID, ip])
|
||||||
|
|
|
@ -39,4 +39,4 @@ class banchoConfig:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.config["banchoMaintenance"] = __maintenance
|
self.config["banchoMaintenance"] = __maintenance
|
||||||
glob.db.execute("UPDATE bancho_settings SET value_int = ? WHERE name = 'bancho_maintenance'", [int(__maintenance)])
|
glob.db.execute("UPDATE bancho_settings SET value_int = %s WHERE name = 'bancho_maintenance'", [int(__maintenance)])
|
||||||
|
|
|
@ -14,3 +14,5 @@ channels = channelList.channelList()
|
||||||
matches = matchList.matchList()
|
matches = matchList.matchList()
|
||||||
memes = True
|
memes = True
|
||||||
restarting = False
|
restarting = False
|
||||||
|
pool = None
|
||||||
|
requestTime = False
|
||||||
|
|
255
pep.py
255
pep.py
|
@ -1,81 +1,33 @@
|
||||||
"""Hello, pep.py here, ex-owner of ripple and prime minister of Ripwot."""
|
"""Hello, pep.py here, ex-owner of ripple and prime minister of Ripwot."""
|
||||||
import logging
|
|
||||||
import sys
|
import sys
|
||||||
import flask
|
|
||||||
import datetime
|
|
||||||
import os
|
import os
|
||||||
|
from multiprocessing.pool import ThreadPool
|
||||||
|
|
||||||
# Tornado server
|
# Tornado
|
||||||
from tornado.wsgi import WSGIContainer
|
import tornado.ioloop
|
||||||
from tornado.httpserver import HTTPServer
|
import tornado.web
|
||||||
from tornado.ioloop import IOLoop
|
import tornado.httpserver
|
||||||
|
import tornado.gen
|
||||||
|
|
||||||
# pep.py files
|
# pep.py files
|
||||||
from constants import bcolors
|
from constants import bcolors
|
||||||
from constants import packetIDs
|
|
||||||
from constants import serverPackets
|
|
||||||
from helpers import configHelper
|
from helpers import configHelper
|
||||||
from helpers import discordBotHelper
|
from helpers import discordBotHelper
|
||||||
from constants import exceptions
|
|
||||||
from objects import glob
|
from objects import glob
|
||||||
from objects import fokabot
|
from objects import fokabot
|
||||||
from objects import banchoConfig
|
from objects import banchoConfig
|
||||||
|
from handlers import mainHandler
|
||||||
from events import sendPublicMessageEvent
|
|
||||||
from events import sendPrivateMessageEvent
|
|
||||||
from events import channelJoinEvent
|
|
||||||
from events import channelPartEvent
|
|
||||||
from events import changeActionEvent
|
|
||||||
from events import cantSpectateEvent
|
|
||||||
from events import startSpectatingEvent
|
|
||||||
from events import stopSpectatingEvent
|
|
||||||
from events import spectateFramesEvent
|
|
||||||
from events import friendAddEvent
|
|
||||||
from events import friendRemoveEvent
|
|
||||||
from events import logoutEvent
|
|
||||||
from events import loginEvent
|
|
||||||
from events import setAwayMessageEvent
|
|
||||||
from events import joinLobbyEvent
|
|
||||||
from events import createMatchEvent
|
|
||||||
from events import partLobbyEvent
|
|
||||||
from events import changeSlotEvent
|
|
||||||
from events import joinMatchEvent
|
|
||||||
from events import partMatchEvent
|
|
||||||
from events import changeMatchSettingsEvent
|
|
||||||
from events import changeMatchPasswordEvent
|
|
||||||
from events import changeMatchModsEvent
|
|
||||||
from events import matchReadyEvent
|
|
||||||
from events import matchLockEvent
|
|
||||||
from events import matchStartEvent
|
|
||||||
from events import matchPlayerLoadEvent
|
|
||||||
from events import matchSkipEvent
|
|
||||||
from events import matchFramesEvent
|
|
||||||
from events import matchCompleteEvent
|
|
||||||
from events import matchNoBeatmapEvent
|
|
||||||
from events import matchHasBeatmapEvent
|
|
||||||
from events import matchTransferHostEvent
|
|
||||||
from events import matchFailedEvent
|
|
||||||
from events import matchInviteEvent
|
|
||||||
from events import matchChangeTeamEvent
|
|
||||||
|
|
||||||
# pep.py helpers
|
|
||||||
from helpers import packetHelper
|
|
||||||
from helpers import consoleHelper
|
from helpers import consoleHelper
|
||||||
from helpers import databaseHelper
|
from helpers import databaseHelperNew
|
||||||
from helpers import responseHelper
|
|
||||||
from helpers import generalFunctions
|
from helpers import generalFunctions
|
||||||
from helpers import systemHelper
|
|
||||||
|
|
||||||
from flask import request
|
def make_app():
|
||||||
|
return tornado.web.Application([
|
||||||
# Create flask instance
|
(r"/", mainHandler.handler)
|
||||||
app = flask.Flask(__name__)
|
])
|
||||||
|
|
||||||
# Get flask logger
|
|
||||||
flaskLogger = logging.getLogger("werkzeug")
|
|
||||||
|
|
||||||
# Ci trigger
|
# Ci trigger
|
||||||
@app.route("/ci-trigger")
|
'''@app.route("/ci-trigger")
|
||||||
@app.route("/api/ci-trigger")
|
@app.route("/api/ci-trigger")
|
||||||
def ciTrigger():
|
def ciTrigger():
|
||||||
# Ci restart trigger
|
# Ci restart trigger
|
||||||
|
@ -133,135 +85,10 @@ def apiOnlineUsers():
|
||||||
def banchoServer():
|
def banchoServer():
|
||||||
if flask.request.method == 'POST':
|
if flask.request.method == 'POST':
|
||||||
|
|
||||||
# Track time if needed
|
|
||||||
if serverOutputRequestTime == True:
|
|
||||||
# Start time
|
|
||||||
st = datetime.datetime.now()
|
|
||||||
|
|
||||||
# Client's token string and request data
|
|
||||||
requestTokenString = flask.request.headers.get('osu-token')
|
|
||||||
requestData = flask.request.data
|
|
||||||
|
|
||||||
# Server's token string and request data
|
|
||||||
responseTokenString = "ayy"
|
|
||||||
responseData = bytes()
|
|
||||||
|
|
||||||
if requestTokenString == None:
|
|
||||||
# No token, first request. Handle login.
|
|
||||||
responseTokenString, responseData = loginEvent.handle(flask.request)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
# This is not the first packet, send response based on client's request
|
|
||||||
# Packet start position, used to read stacked packets
|
|
||||||
pos = 0
|
|
||||||
|
|
||||||
# Make sure the token exists
|
|
||||||
if requestTokenString not in glob.tokens.tokens:
|
|
||||||
raise exceptions.tokenNotFoundException()
|
|
||||||
|
|
||||||
# Token exists, get its object
|
|
||||||
userToken = glob.tokens.tokens[requestTokenString]
|
|
||||||
|
|
||||||
# Keep reading packets until everything has been read
|
|
||||||
while pos < len(requestData):
|
|
||||||
# Get packet from stack starting from new packet
|
|
||||||
leftData = requestData[pos:]
|
|
||||||
|
|
||||||
# Get packet ID, data length and data
|
|
||||||
packetID = packetHelper.readPacketID(leftData)
|
|
||||||
dataLength = packetHelper.readPacketLength(leftData)
|
|
||||||
packetData = requestData[pos:(pos+dataLength+7)]
|
|
||||||
|
|
||||||
# Console output if needed
|
|
||||||
if serverOutputPackets == True and packetID != 4:
|
|
||||||
consoleHelper.printColored("Incoming packet ({})({}):".format(requestTokenString, userToken.username), bcolors.GREEN)
|
|
||||||
consoleHelper.printColored("Packet code: {}\nPacket length: {}\nSingle packet data: {}\n".format(str(packetID), str(dataLength), str(packetData)), bcolors.YELLOW)
|
|
||||||
|
|
||||||
# Event handler
|
|
||||||
def handleEvent(ev):
|
|
||||||
def wrapper():
|
|
||||||
ev.handle(userToken, packetData)
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
eventHandler = {
|
|
||||||
# TODO: Rename packets and events
|
|
||||||
# TODO: Host check for multi
|
|
||||||
packetIDs.client_sendPublicMessage: handleEvent(sendPublicMessageEvent),
|
|
||||||
packetIDs.client_sendPrivateMessage: handleEvent(sendPrivateMessageEvent),
|
|
||||||
packetIDs.client_setAwayMessage: handleEvent(setAwayMessageEvent),
|
|
||||||
packetIDs.client_channelJoin: handleEvent(channelJoinEvent),
|
|
||||||
packetIDs.client_channelPart: handleEvent(channelPartEvent),
|
|
||||||
packetIDs.client_changeAction: handleEvent(changeActionEvent),
|
|
||||||
packetIDs.client_startSpectating: handleEvent(startSpectatingEvent),
|
|
||||||
packetIDs.client_stopSpectating: handleEvent(stopSpectatingEvent),
|
|
||||||
packetIDs.client_cantSpectate: handleEvent(cantSpectateEvent),
|
|
||||||
packetIDs.client_spectateFrames: handleEvent(spectateFramesEvent),
|
|
||||||
packetIDs.client_friendAdd: handleEvent(friendAddEvent),
|
|
||||||
packetIDs.client_friendRemove: handleEvent(friendRemoveEvent),
|
|
||||||
packetIDs.client_logout: handleEvent(logoutEvent),
|
|
||||||
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_invite: handleEvent(matchInviteEvent),
|
|
||||||
packetIDs.client_matchChangeTeam: handleEvent(matchChangeTeamEvent)
|
|
||||||
}
|
|
||||||
|
|
||||||
if packetID != 4:
|
|
||||||
if packetID in eventHandler:
|
|
||||||
eventHandler[packetID]()
|
|
||||||
else:
|
|
||||||
consoleHelper.printColored("[!] Unknown packet id from {} ({})".format(requestTokenString, packetID), bcolors.RED)
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Token queue built, send it
|
|
||||||
responseTokenString = userToken.token
|
|
||||||
responseData = userToken.queue
|
|
||||||
userToken.resetQueue()
|
|
||||||
|
|
||||||
# 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.")
|
|
||||||
consoleHelper.printColored("[!] Received packet from unknown token ({}).".format(requestTokenString), bcolors.RED)
|
|
||||||
consoleHelper.printColored("> {} have been disconnected (invalid token)".format(requestTokenString), bcolors.YELLOW)
|
|
||||||
|
|
||||||
if serverOutputRequestTime == True:
|
|
||||||
# End time
|
|
||||||
et = datetime.datetime.now()
|
|
||||||
|
|
||||||
# Total time:
|
|
||||||
tt = float((et.microsecond-st.microsecond)/1000)
|
|
||||||
consoleHelper.printColored("Request time: {}ms".format(tt), bcolors.PINK)
|
|
||||||
|
|
||||||
# Send server's response to client
|
|
||||||
# We don't use token object because we might not have a token (failed login)
|
|
||||||
return responseHelper.generateResponse(responseTokenString, responseData)
|
|
||||||
else:
|
else:
|
||||||
# Not a POST request, send html page
|
# Not a POST request, send html page
|
||||||
return responseHelper.HTMLResponse()
|
return responseHelper.HTMLResponse()'''
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -291,8 +118,8 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
# Connect to db
|
# Connect to db
|
||||||
try:
|
try:
|
||||||
consoleHelper.printNoNl("> Connecting to MySQL db... ")
|
print("> Connecting to MySQL db... ")
|
||||||
glob.db = databaseHelper.db(glob.conf.config["db"]["host"], glob.conf.config["db"]["username"], glob.conf.config["db"]["password"], glob.conf.config["db"]["database"], int(glob.conf.config["db"]["pingtime"]))
|
glob.db = databaseHelperNew.db(glob.conf.config["db"]["host"], glob.conf.config["db"]["username"], glob.conf.config["db"]["password"], glob.conf.config["db"]["database"], int(glob.conf.config["db"]["workers"]))
|
||||||
consoleHelper.printDone()
|
consoleHelper.printDone()
|
||||||
except:
|
except:
|
||||||
# Exception while connecting to db
|
# Exception while connecting to db
|
||||||
|
@ -300,6 +127,15 @@ if __name__ == "__main__":
|
||||||
consoleHelper.printColored("[!] Error while connection to database. Please check your config.ini and run the server again", bcolors.RED)
|
consoleHelper.printColored("[!] Error while connection to database. Please check your config.ini and run the server again", bcolors.RED)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
# Load bancho_settings
|
# Load bancho_settings
|
||||||
try:
|
try:
|
||||||
consoleHelper.printNoNl("> Loading bancho settings from DB... ")
|
consoleHelper.printNoNl("> Loading bancho settings from DB... ")
|
||||||
|
@ -344,41 +180,14 @@ if __name__ == "__main__":
|
||||||
consoleHelper.printColored("[!] Warning! users localization is disabled!", bcolors.YELLOW)
|
consoleHelper.printColored("[!] Warning! users localization is disabled!", bcolors.YELLOW)
|
||||||
|
|
||||||
# Get server parameters from config.ini
|
# Get server parameters from config.ini
|
||||||
serverName = glob.conf.config["server"]["server"]
|
|
||||||
serverHost = glob.conf.config["server"]["host"]
|
|
||||||
serverPort = int(glob.conf.config["server"]["port"])
|
serverPort = int(glob.conf.config["server"]["port"])
|
||||||
serverOutputPackets = generalFunctions.stringToBool(glob.conf.config["server"]["outputpackets"])
|
glob.requestTime = generalFunctions.stringToBool(glob.conf.config["server"]["outputrequesttime"])
|
||||||
serverOutputRequestTime = generalFunctions.stringToBool(glob.conf.config["server"]["outputrequesttime"])
|
|
||||||
|
|
||||||
# Send server start message
|
# Server start message and console output
|
||||||
discordBotHelper.sendConfidential("w00t p00t! (pep.py started)")
|
discordBotHelper.sendConfidential("w00t p00t! (pep.py started)")
|
||||||
|
consoleHelper.printColored("> Tornado listening for clients on 127.0.0.1:{}...".format(serverPort), bcolors.GREEN)
|
||||||
|
|
||||||
# Run server sanic way
|
# Start tornado
|
||||||
if serverName == "tornado":
|
app = tornado.httpserver.HTTPServer(make_app())
|
||||||
# Tornado server
|
app.listen(serverPort)
|
||||||
consoleHelper.printColored("> Tornado listening for clients on 127.0.0.1:{}...".format(serverPort), bcolors.GREEN)
|
tornado.ioloop.IOLoop.instance().start()
|
||||||
webServer = HTTPServer(WSGIContainer(app))
|
|
||||||
webServer.listen(serverPort)
|
|
||||||
IOLoop.instance().start()
|
|
||||||
elif serverName == "flask":
|
|
||||||
# Flask server
|
|
||||||
# Get flask settings
|
|
||||||
flaskThreaded = generalFunctions.stringToBool(glob.conf.config["flask"]["threaded"])
|
|
||||||
flaskDebug = generalFunctions.stringToBool(glob.conf.config["flask"]["debug"])
|
|
||||||
flaskLoggerStatus = not generalFunctions.stringToBool(glob.conf.config["flask"]["logger"])
|
|
||||||
|
|
||||||
# Set flask debug mode and logger
|
|
||||||
app.debug = flaskDebug
|
|
||||||
flaskLogger.disabled = flaskLoggerStatus
|
|
||||||
|
|
||||||
# Console output
|
|
||||||
if flaskDebug == False:
|
|
||||||
consoleHelper.printColored("> Flask listening for clients on {}.{}...".format(serverHost, serverPort), bcolors.GREEN)
|
|
||||||
else:
|
|
||||||
consoleHelper.printColored("> Flask "+bcolors.YELLOW+"(debug mode)"+bcolors.ENDC+" listening for clients on {}:{}...".format(serverHost, serverPort), bcolors.GREEN)
|
|
||||||
|
|
||||||
# Run flask server
|
|
||||||
app.run(host=serverHost, port=serverPort, threaded=flaskThreaded)
|
|
||||||
else:
|
|
||||||
print(bcolors.RED+"[!] Unknown server. Please set the server key in config.ini to "+bcolors.ENDC+bcolors.YELLOW+"tornado"+bcolors.ENDC+bcolors.RED+" or "+bcolors.ENDC+bcolors.YELLOW+"flask"+bcolors.ENDC)
|
|
||||||
sys.exit()
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user