.HIDE. General refactoring and documentation
This commit is contained in:
@@ -12,14 +12,11 @@ def joinChannel(userID = 0, channel = "", token = None, toIRC = True):
|
||||
"""
|
||||
Join a channel
|
||||
|
||||
userID -- user ID of the user that joins the channel. Optional.
|
||||
token can be used instead.
|
||||
token -- user token object of user that joins the channel. Optional.
|
||||
userID can be used instead.
|
||||
channel -- name of channe
|
||||
toIRC -- if True, send this channel join event to IRC. Must be true if joining from bancho.
|
||||
Optional. Defaukt: True
|
||||
return -- returns 0 if joined or other IRC code in case of error. Needed only on IRC-side
|
||||
:param userID: user ID of the user that joins the channel. Optional. token can be used instead.
|
||||
:param token: user token object of user that joins the channel. Optional. userID can be used instead.
|
||||
:param channel: channel name
|
||||
:param toIRC: if True, send this channel join event to IRC. Must be true if joining from bancho. Default: True
|
||||
:return: 0 if joined or other IRC code in case of error. Needed only on IRC-side
|
||||
"""
|
||||
try:
|
||||
# Get token if not defined
|
||||
@@ -77,15 +74,12 @@ def partChannel(userID = 0, channel = "", token = None, toIRC = True, kick = Fal
|
||||
"""
|
||||
Part a channel
|
||||
|
||||
userID -- user ID of the user that parts the channel. Optional.
|
||||
token can be used instead.
|
||||
token -- user token object of user that parts the channel. Optional.
|
||||
userID can be used instead.
|
||||
channel -- name of channel
|
||||
toIRC -- if True, send this channel join event to IRC. Must be true if joining from bancho.
|
||||
Optional. Defaukt: True
|
||||
kick -- if True, channel tab will be closed on client. Used when leaving lobby. Optional. Default: False
|
||||
return -- returns 0 if joined or other IRC code in case of error. Needed only on IRC-side
|
||||
:param userID: user ID of the user that parts the channel. Optional. token can be used instead.
|
||||
:param token: user token object of user that parts the channel. Optional. userID can be used instead.
|
||||
:param channel: channel name
|
||||
:param toIRC: if True, send this channel join event to IRC. Must be true if joining from bancho. Optional. Default: True
|
||||
:param kick: if True, channel tab will be closed on client. Used when leaving lobby. Optional. Default: False
|
||||
:return: 0 if joined or other IRC code in case of error. Needed only on IRC-side
|
||||
"""
|
||||
try:
|
||||
# Get token if not defined
|
||||
@@ -151,15 +145,12 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
|
||||
"""
|
||||
Send a message to osu!bancho and IRC server
|
||||
|
||||
fro -- sender username. Optional.
|
||||
You can use token instead of this if you wish.
|
||||
to -- receiver channel (if starts with #) or username
|
||||
message -- text of the message
|
||||
token -- sender token object.
|
||||
You can use this instead of fro if you are sending messages from bancho.
|
||||
Optional.
|
||||
toIRC -- if True, send the message to IRC. If False, send it to Bancho only.
|
||||
Optional. Default: True
|
||||
:param fro: sender username. Optional. token can be used instead
|
||||
:param to: receiver channel (if starts with #) or username
|
||||
:param message: text of the message
|
||||
:param token: sender token object. Optional. fro can be used instead
|
||||
:param toIRC: if True, send the message to IRC. If False, send it to Bancho only. Default: True
|
||||
:return: 0 if joined or other IRC code in case of error. Needed only on IRC-side
|
||||
"""
|
||||
try:
|
||||
tokenString = ""
|
||||
@@ -231,7 +222,7 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
|
||||
raise exceptions.channelNoPermissionsException
|
||||
|
||||
# Everything seems fine, build recipients list and send packet
|
||||
recipients = glob.channels.channels[to].getConnectedUsers()[:]
|
||||
recipients = glob.channels.channels[to].connectedUsers[:]
|
||||
for key, value in glob.tokens.tokens.items():
|
||||
# Skip our client and irc clients
|
||||
if key == tokenString or value.irc == True:
|
||||
@@ -312,6 +303,12 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
|
||||
|
||||
""" IRC-Bancho Connect/Disconnect/Join/Part interfaces"""
|
||||
def fixUsernameForBancho(username):
|
||||
"""
|
||||
Convert username from IRC format (without spaces) to Bancho format (with spaces)
|
||||
|
||||
:param username: username to convert
|
||||
:return: converted username
|
||||
"""
|
||||
# If there are no spaces or underscores in the name
|
||||
# return it
|
||||
if " " not in username and "_" not in username:
|
||||
@@ -326,9 +323,22 @@ def fixUsernameForBancho(username):
|
||||
return username.replace("_", " ")
|
||||
|
||||
def fixUsernameForIRC(username):
|
||||
"""
|
||||
Convert an username from Bancho format to IRC format (underscores instead of spaces)
|
||||
|
||||
:param username: username to convert
|
||||
:return: converted username
|
||||
"""
|
||||
return username.replace(" ", "_")
|
||||
|
||||
def IRCConnect(username):
|
||||
"""
|
||||
Handle IRC login bancho-side.
|
||||
Add token and broadcast login packet.
|
||||
|
||||
:param username: username
|
||||
:return:
|
||||
"""
|
||||
userID = userUtils.getID(username)
|
||||
if not userID:
|
||||
log.warning("{} doesn't exist".format(username))
|
||||
@@ -339,6 +349,13 @@ def IRCConnect(username):
|
||||
log.info("{} logged in from IRC".format(username))
|
||||
|
||||
def IRCDisconnect(username):
|
||||
"""
|
||||
Handle IRC logout bancho-side.
|
||||
Remove token and broadcast logout packet.
|
||||
|
||||
:param username: username
|
||||
:return:
|
||||
"""
|
||||
token = glob.tokens.getTokenFromUsername(username)
|
||||
if token is None:
|
||||
log.warning("{} doesn't exist".format(username))
|
||||
@@ -347,6 +364,13 @@ def IRCDisconnect(username):
|
||||
log.info("{} disconnected from IRC".format(username))
|
||||
|
||||
def IRCJoinChannel(username, channel):
|
||||
"""
|
||||
Handle IRC channel join bancho-side.
|
||||
|
||||
:param username: username
|
||||
:param channel: channel name
|
||||
:return: IRC return code
|
||||
"""
|
||||
userID = userUtils.getID(username)
|
||||
if not userID:
|
||||
log.warning("{} doesn't exist".format(username))
|
||||
@@ -357,6 +381,13 @@ def IRCJoinChannel(username, channel):
|
||||
return joinChannel(userID, channel)
|
||||
|
||||
def IRCPartChannel(username, channel):
|
||||
"""
|
||||
Handle IRC channel part bancho-side.
|
||||
|
||||
:param username: username
|
||||
:param channel: channel name
|
||||
:return: IRC return code
|
||||
"""
|
||||
userID = userUtils.getID(username)
|
||||
if not userID:
|
||||
log.warning("{} doesn't exist".format(username))
|
||||
@@ -364,9 +395,16 @@ def IRCPartChannel(username, channel):
|
||||
return partChannel(userID, channel)
|
||||
|
||||
def IRCAway(username, message):
|
||||
"""
|
||||
Handle IRC away command bancho-side.
|
||||
|
||||
:param username:
|
||||
:param message: away message
|
||||
:return: IRC return code
|
||||
"""
|
||||
userID = userUtils.getID(username)
|
||||
if not userID:
|
||||
log.warning("{} doesn't exist".format(username))
|
||||
return
|
||||
glob.tokens.getTokenFromUserID(userID).setAwayMessage(message)
|
||||
glob.tokens.getTokenFromUserID(userID).awayMessage = message
|
||||
return 305 if message == "" else 306
|
@@ -5,9 +5,9 @@ class config:
|
||||
# Check if config.ini exists and load/generate it
|
||||
def __init__(self, file):
|
||||
"""
|
||||
Initialize a config object
|
||||
Initialize a config file object
|
||||
|
||||
file -- filename
|
||||
:param file: file name
|
||||
"""
|
||||
self.config = configparser.ConfigParser()
|
||||
self.default = True
|
||||
@@ -25,9 +25,9 @@ class config:
|
||||
# Check if config.ini has all needed the keys
|
||||
def checkConfig(self):
|
||||
"""
|
||||
Check if this config has the required keys
|
||||
Check is the config file has all required keys
|
||||
|
||||
return -- True if valid, False if not
|
||||
:return: True if valid, False if not valid
|
||||
"""
|
||||
try:
|
||||
# Try to get all the required keys
|
||||
@@ -79,7 +79,9 @@ class config:
|
||||
|
||||
def generateDefaultConfig(self):
|
||||
"""
|
||||
Open and set default keys for that config file
|
||||
Write a default config file to disk
|
||||
|
||||
:return:
|
||||
"""
|
||||
# Open config.ini in write mode
|
||||
f = open(self.fileName, "w")
|
||||
|
@@ -1,11 +1,12 @@
|
||||
from common.constants import bcolors
|
||||
from objects import glob
|
||||
|
||||
def printServerStartHeader(asciiArt):
|
||||
def printServerStartHeader(asciiArt=True):
|
||||
"""
|
||||
Print server start header with optional ascii art
|
||||
Print server start message
|
||||
|
||||
asciiArt -- if True, will print ascii art too
|
||||
:param asciiArt: print BanchoBoat ascii art. Default: True
|
||||
:return:
|
||||
"""
|
||||
if asciiArt:
|
||||
print("{} _ __".format(bcolors.GREEN))
|
||||
@@ -32,35 +33,43 @@ def printServerStartHeader(asciiArt):
|
||||
|
||||
def printNoNl(string):
|
||||
"""
|
||||
Print string without new line at the end
|
||||
Print a string without \n at the end
|
||||
|
||||
string -- string to print
|
||||
:param string: string to print
|
||||
:return:
|
||||
"""
|
||||
print(string, end="")
|
||||
|
||||
def printColored(string, color):
|
||||
"""
|
||||
Print colored string
|
||||
Print a colored string
|
||||
|
||||
string -- string to print
|
||||
color -- see bcolors.py
|
||||
:param string: string to print
|
||||
:param color: ANSI color code
|
||||
:return:
|
||||
"""
|
||||
print("{}{}{}".format(color, string, bcolors.ENDC))
|
||||
|
||||
def printError():
|
||||
"""
|
||||
Print error text FOR LOADING
|
||||
Print a red "Error"
|
||||
|
||||
:return:
|
||||
"""
|
||||
printColored("Error", bcolors.RED)
|
||||
|
||||
def printDone():
|
||||
"""
|
||||
Print error text FOR LOADING
|
||||
Print a green "Done"
|
||||
|
||||
:return:
|
||||
"""
|
||||
printColored("Done", bcolors.GREEN)
|
||||
|
||||
def printWarning():
|
||||
"""
|
||||
Print error text FOR LOADING
|
||||
Print a yellow "Warning"
|
||||
|
||||
:return:
|
||||
"""
|
||||
printColored("Warning", bcolors.YELLOW)
|
||||
|
@@ -1,5 +1,4 @@
|
||||
"""Contains all country codes with their osu numeric code"""
|
||||
|
||||
# TODO: Update countries list
|
||||
countryCodes = {
|
||||
"LV": 132,
|
||||
"AD": 3,
|
||||
@@ -255,12 +254,11 @@ countryCodes = {
|
||||
|
||||
def getCountryID(code):
|
||||
"""
|
||||
Get country ID for osu client
|
||||
Get osu country ID from country letters
|
||||
|
||||
code -- country name abbreviation (eg: US)
|
||||
return -- country code int
|
||||
:param code: country letters (eg: US)
|
||||
:return: country osu code
|
||||
"""
|
||||
|
||||
if code in countryCodes:
|
||||
return countryCodes[code]
|
||||
else:
|
||||
@@ -270,10 +268,9 @@ def getCountryLetters(code):
|
||||
"""
|
||||
Get country letters from osu country ID
|
||||
|
||||
code -- country code int
|
||||
return -- country name (2 letters) (XX if code not found)
|
||||
:param code: osu country ID
|
||||
:return: country letters (XX if not found)
|
||||
"""
|
||||
|
||||
for key, value in countryCodes.items():
|
||||
if value == code:
|
||||
return key
|
||||
|
@@ -7,10 +7,10 @@ from objects import glob
|
||||
|
||||
def getCountry(ip):
|
||||
"""
|
||||
Get country from IP address
|
||||
Get country from IP address using geoip api
|
||||
|
||||
ip -- IP Address
|
||||
return -- Country code (2 letters)
|
||||
:param ip: IP address
|
||||
:return: country code. XX if invalid.
|
||||
"""
|
||||
try:
|
||||
# Try to get country from Pikolo Aul's Go-Sanic ip API
|
||||
@@ -22,15 +22,15 @@ def getCountry(ip):
|
||||
|
||||
def getLocation(ip):
|
||||
"""
|
||||
Get latitude and longitude from IP address
|
||||
Get latitude and longitude from IP address using geoip api
|
||||
|
||||
ip -- IP address
|
||||
return -- [latitude, longitude]
|
||||
:param ip: IP address
|
||||
:return: (latitude, longitude)
|
||||
"""
|
||||
try:
|
||||
# Try to get position from Pikolo Aul's Go-Sanic ip API
|
||||
result = json.loads(urllib.request.urlopen("{}/{}".format(glob.conf.config["localize"]["ipapiurl"], ip), timeout=3).read().decode())["loc"].split(",")
|
||||
return [float(result[0]), float(result[1])]
|
||||
return (float(result[0]), float(result[1]))
|
||||
except:
|
||||
log.error("Error in get position")
|
||||
return [0,0]
|
||||
return (0, 0)
|
||||
|
@@ -3,10 +3,10 @@ from constants import dataTypes
|
||||
|
||||
def uleb128Encode(num):
|
||||
"""
|
||||
Encode int -> uleb128
|
||||
Encode an int to uleb128
|
||||
|
||||
num -- int to encode
|
||||
return -- bytearray with encoded number
|
||||
:param num: int to encode
|
||||
:return: bytearray with encoded number
|
||||
"""
|
||||
arr = bytearray()
|
||||
length = 0
|
||||
@@ -25,10 +25,10 @@ def uleb128Encode(num):
|
||||
|
||||
def uleb128Decode(num):
|
||||
"""
|
||||
Decode uleb128 -> int
|
||||
Decode a uleb128 to int
|
||||
|
||||
num -- encoded uleb128
|
||||
return -- list. [total, length]
|
||||
:param num: encoded uleb128 int
|
||||
:return: (total, length)
|
||||
"""
|
||||
shift = 0
|
||||
arr = [0,0] #total, length
|
||||
@@ -45,14 +45,12 @@ def uleb128Decode(num):
|
||||
|
||||
def unpackData(data, dataType):
|
||||
"""
|
||||
Unpacks data according to dataType
|
||||
Unpacks a single section of a packet.
|
||||
|
||||
data -- bytes array to unpack
|
||||
dataType -- data type. See dataTypes.py
|
||||
|
||||
return -- unpacked bytes
|
||||
:param data: bytes to unpack
|
||||
:param dataType: data type
|
||||
:return: unpacked bytes
|
||||
"""
|
||||
|
||||
# Get right pack Type
|
||||
if dataType == dataTypes.UINT16:
|
||||
unpackType = "<H"
|
||||
@@ -78,14 +76,12 @@ def unpackData(data, dataType):
|
||||
|
||||
def packData(__data, dataType):
|
||||
"""
|
||||
Packs data according to dataType
|
||||
Packs a single section of a packet.
|
||||
|
||||
data -- bytes to pack
|
||||
dataType -- data type. See dataTypes.py
|
||||
|
||||
return -- packed bytes
|
||||
:param __data: data to pack
|
||||
:param dataType: data type
|
||||
:return: packed bytes
|
||||
"""
|
||||
|
||||
data = bytes() # data to return
|
||||
pack = True # if True, use pack. False only with strings
|
||||
|
||||
@@ -140,12 +136,11 @@ def packData(__data, dataType):
|
||||
|
||||
def buildPacket(__packet, __packetData=None):
|
||||
"""
|
||||
Build a packet
|
||||
Builds a packet
|
||||
|
||||
packet -- packet id (int)
|
||||
packetData -- list [[data, dataType], [data, dataType], ...]
|
||||
|
||||
return -- packet bytes
|
||||
:param __packet: packet ID
|
||||
:param __packetData: packet structure [[data, dataType], [data, dataType], ...]
|
||||
:return: packet bytes
|
||||
"""
|
||||
# Set some variables
|
||||
if __packetData is None:
|
||||
@@ -170,33 +165,31 @@ def buildPacket(__packet, __packetData=None):
|
||||
|
||||
def readPacketID(stream):
|
||||
"""
|
||||
Read packetID from stream (0-1 bytes)
|
||||
Read packetID (first two bytes) from a packet
|
||||
|
||||
stream -- data stream
|
||||
return -- packet ID (int)
|
||||
:param stream: packet bytes
|
||||
:return: packet ID
|
||||
"""
|
||||
return unpackData(stream[0:2], dataTypes.UINT16)
|
||||
|
||||
def readPacketLength(stream):
|
||||
"""
|
||||
Read packet length from stream (3-4-5-6 bytes)
|
||||
Read packet data length (3:7 bytes) from a packet
|
||||
|
||||
stream -- data stream
|
||||
return -- packet length (int)
|
||||
:param stream: packet bytes
|
||||
:return: packet data length
|
||||
"""
|
||||
return unpackData(stream[3:7], dataTypes.UINT32)
|
||||
|
||||
|
||||
def readPacketData(stream, structure=None, hasFirstBytes = True):
|
||||
"""
|
||||
Read packet data from stream according to structure
|
||||
|
||||
stream -- data stream
|
||||
structure -- [[name, dataType], [name, dataType], ...]
|
||||
hasFirstBytes -- if True, stream has packetID and length bytes.
|
||||
if False, stream has only packetData.
|
||||
Optional. Default: True
|
||||
return -- dictionary. key: name, value: read data
|
||||
Read packet data from `stream` according to `structure`
|
||||
:param stream: packet bytes
|
||||
:param structure: packet structure: [[name, dataType], [name, dataType], ...]
|
||||
:param hasFirstBytes: if True, `stream` has packetID and length bytes.
|
||||
if False, `stream` has only packet data. Default: True
|
||||
:return: {name: unpackedValue, ...}
|
||||
"""
|
||||
# Read packet ID (first 2 bytes)
|
||||
if structure is None:
|
||||
|
@@ -17,6 +17,7 @@ from objects import glob
|
||||
def dispose():
|
||||
"""
|
||||
Perform some clean up. Called on shutdown.
|
||||
|
||||
:return:
|
||||
"""
|
||||
print("> Disposing server... ")
|
||||
@@ -27,7 +28,7 @@ def runningUnderUnix():
|
||||
"""
|
||||
Get if the server is running under UNIX or NT
|
||||
|
||||
return --- True if running under UNIX, otherwise False
|
||||
:return: True if running under UNIX, otherwise False
|
||||
"""
|
||||
return True if os.name == "posix" else False
|
||||
|
||||
@@ -35,9 +36,11 @@ def scheduleShutdown(sendRestartTime, restart, message = "", delay=20):
|
||||
"""
|
||||
Schedule a server shutdown/restart
|
||||
|
||||
sendRestartTime -- time (seconds) to wait before sending server restart packets to every client
|
||||
restart -- if True, server will restart. if False, server will shudown
|
||||
message -- if set, send that message to every client to warn about the shutdown/restart
|
||||
:param sendRestartTime: time (seconds) to wait before sending server restart packets to every client
|
||||
:param restart: if True, server will restart. if False, server will shudown
|
||||
:param message: if set, send that message to every client to warn about the shutdown/restart
|
||||
:param delay: additional restart delay in seconds. Default: 20
|
||||
:return:
|
||||
"""
|
||||
# Console output
|
||||
log.info("Pep.py will {} in {} seconds!".format("restart" if restart else "shutdown", sendRestartTime+delay))
|
||||
@@ -61,13 +64,21 @@ def scheduleShutdown(sendRestartTime, restart, message = "", delay=20):
|
||||
threading.Timer(sendRestartTime+delay, action).start()
|
||||
|
||||
def restartServer():
|
||||
"""Restart pep.py script"""
|
||||
"""
|
||||
Restart pep.py
|
||||
|
||||
:return:
|
||||
"""
|
||||
log.info("Restarting pep.py...")
|
||||
dispose()
|
||||
os.execv(sys.executable, [sys.executable] + sys.argv)
|
||||
|
||||
def shutdownServer():
|
||||
"""Shutdown pep.py"""
|
||||
"""
|
||||
Shutdown pep.py
|
||||
|
||||
:return:
|
||||
"""
|
||||
log.info("Shutting down pep.py...")
|
||||
dispose()
|
||||
sig = signal.SIGKILL if runningUnderUnix() else signal.CTRL_C_EVENT
|
||||
@@ -77,7 +88,7 @@ def getSystemInfo():
|
||||
"""
|
||||
Get a dictionary with some system/server info
|
||||
|
||||
return -- ["unix", "connectedUsers", "webServer", "cpuUsage", "totalMemory", "usedMemory", "loadAverage"]
|
||||
:return: ["unix", "connectedUsers", "webServer", "cpuUsage", "totalMemory", "usedMemory", "loadAverage"]
|
||||
"""
|
||||
data = {"unix": runningUnderUnix(), "connectedUsers": len(glob.tokens.tokens), "matches": len(glob.matches.matches)}
|
||||
|
||||
|
Reference in New Issue
Block a user