mirror of
https://github.com/solero/houdini.git
synced 2025-10-18 05:18:13 +00:00
Rename all modules to comply with PEP8
Lowercase with underscores
This commit is contained in:
@@ -1,120 +0,0 @@
|
||||
from Houdini import Handlers
|
||||
from Houdini.Handlers import XMLPacket, Login
|
||||
from Houdini.Converters import CredentialsConverter
|
||||
from Houdini.Data.Penguin import Penguin
|
||||
from Houdini.Data.Buddy import BuddyList
|
||||
from Houdini.Data.Moderator import Ban
|
||||
from Houdini.Crypto import Crypto
|
||||
|
||||
import asyncio
|
||||
import bcrypt
|
||||
import time
|
||||
import os
|
||||
import config
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@Handlers.handler(XMLPacket('login'))
|
||||
@Handlers.allow_once()
|
||||
async def handle_login(p, credentials: CredentialsConverter):
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
login_timestamp = time.time()
|
||||
username, password = credentials
|
||||
p.logger.info('{} is logging in!'.format(username))
|
||||
|
||||
data = await Penguin.query.where(Penguin.Username == username).gino.first()
|
||||
|
||||
if data is None:
|
||||
p.logger.info('{} failed to login: penguin does not exist')
|
||||
await p.send_error_and_disconnect(100)
|
||||
|
||||
password_correct = await loop.run_in_executor(None, bcrypt.checkpw,
|
||||
password.encode('utf-8'), data.Password.encode('utf-8'))
|
||||
|
||||
ip_addr = p.peer_name[0]
|
||||
|
||||
if not password_correct:
|
||||
p.logger.info('{} failed to login: incorrect password'.format(username))
|
||||
|
||||
if ip_addr in p.server.login_attempts:
|
||||
last_failed_attempt, failure_count = p.server.login_attempts[ip_addr]
|
||||
|
||||
failure_count = 1 if login_timestamp - last_failed_attempt >= p.server.server_config['LoginFailureTimer'] \
|
||||
else failure_count + 1
|
||||
|
||||
p.server.login_attempts[ip_addr] = [login_timestamp, failure_count]
|
||||
|
||||
if failure_count >= p.server.server_config['LoginFailureLimit']:
|
||||
return await p.send_error_and_disconnect(150)
|
||||
else:
|
||||
p.server.login_attempts[ip_addr] = [login_timestamp, 1]
|
||||
|
||||
return await p.send_error_and_disconnect(101)
|
||||
|
||||
if ip_addr in p.server.login_attempts:
|
||||
previous_attempt, failure_count = p.server.login_attempts[ip_addr]
|
||||
|
||||
max_attempts_exceeded = failure_count >= p.server.server_config['LoginFailureLimit']
|
||||
timer_surpassed = (login_timestamp - previous_attempt) > p.server.server_config['LoginFailureTimer']
|
||||
|
||||
if max_attempts_exceeded and not timer_surpassed:
|
||||
return await p.send_error_and_disconnect(150)
|
||||
else:
|
||||
del p.server.login_attempts[ip_addr]
|
||||
|
||||
if not data.Active:
|
||||
return await p.send_error_and_disconnect(900)
|
||||
|
||||
if data.Permaban:
|
||||
return await p.send_error_and_disconnect(603)
|
||||
|
||||
active_ban = await Ban.query.where(Ban.PenguinID == data.ID and Ban.Expires >= datetime.now()).gino.first()
|
||||
|
||||
if active_ban is not None:
|
||||
hours_left = round((active_ban.Expires - datetime.now()).total_seconds() / 60 / 60)
|
||||
|
||||
if hours_left == 0:
|
||||
return await p.send_error_and_disconnect(602)
|
||||
else:
|
||||
await p.send_error_and_disconnect(601, hours_left)
|
||||
|
||||
p.logger.info('{} has logged in successfully'.format(username))
|
||||
|
||||
random_key = Crypto.generate_random_key()
|
||||
login_key = Crypto.hash(random_key[::-1])
|
||||
confirmation_hash = Crypto.hash(os.urandom(24))
|
||||
|
||||
await p.server.redis.setex('{}.lkey'.format(data.ID), p.server.server_config['KeyTTL'], login_key)
|
||||
await p.server.redis.setex('{}.ckey'.format(data.ID), p.server.server_config['KeyTTL'], confirmation_hash)
|
||||
|
||||
buddy_worlds = []
|
||||
world_populations = []
|
||||
|
||||
servers_config = config.servers
|
||||
|
||||
for server_name, server_config in servers_config.items():
|
||||
if server_config['World']:
|
||||
server_population = await p.server.redis.get('{}.population'.format(server_name))
|
||||
server_population = int(server_population) / (server_config['Capacity'] / 6) if server_population else 0
|
||||
|
||||
server_players = await p.server.redis.smembers('{}.players'.format(server_name))
|
||||
|
||||
world_populations.append('{},{}'.format(server_config['Id'], server_population))
|
||||
|
||||
if not len(server_players) > 0:
|
||||
p.logger.debug('Skipping buddy iteration for {}'.format(server_name))
|
||||
continue
|
||||
|
||||
buddies = await BuddyList.select('BuddyID').where(BuddyList.PenguinID == data.ID).gino.all()
|
||||
for buddy_id in buddies:
|
||||
if str(buddy_id) in server_players:
|
||||
buddy_worlds.append(server_config['Id'])
|
||||
break
|
||||
|
||||
raw_login_data = '|'.join([str(data.ID), str(data.ID), data.Username, login_key, str(data.approval), '1'])
|
||||
await p.send_xt('l', raw_login_data, confirmation_hash, 'friendsKey', '|'.join(world_populations), data.Email)
|
||||
|
||||
handle_version_check = Login.handle_version_check
|
||||
handle_random_key = Login.handle_random_key
|
@@ -1,19 +0,0 @@
|
||||
from Houdini import Handlers
|
||||
from Houdini.Handlers import XMLPacket
|
||||
from Houdini.Converters import VersionChkConverter
|
||||
|
||||
|
||||
@Handlers.handler(XMLPacket('verChk'))
|
||||
@Handlers.allow_once()
|
||||
async def handle_version_check(p, version: VersionChkConverter):
|
||||
if not version == 153:
|
||||
await p.send_xml({'body': {'action': 'apiKO', 'r': '0'}})
|
||||
await p.close()
|
||||
else:
|
||||
await p.send_xml({'body': {'action': 'apiOK', 'r': '0'}})
|
||||
|
||||
|
||||
@Handlers.handler(XMLPacket('rndK'))
|
||||
@Handlers.allow_once()
|
||||
async def handle_random_key(p, data):
|
||||
await p.send_xml({'body': {'action': 'rndK', 'r': '-1'}, 'k': 'houdini'})
|
@@ -1,214 +0,0 @@
|
||||
import inspect
|
||||
import enum
|
||||
import os
|
||||
import itertools
|
||||
from types import FunctionType
|
||||
|
||||
from Houdini.Converters import _listener, _ArgumentDeserializer, get_converter, do_conversion, _ConverterContext
|
||||
|
||||
from Houdini.Cooldown import _Cooldown, _CooldownMapping, BucketType
|
||||
from Houdini import Plugins
|
||||
|
||||
|
||||
class AuthorityError(Exception):
|
||||
"""Raised when a packet is received but user has not yet authenticated"""
|
||||
|
||||
|
||||
class _Packet:
|
||||
__slots__ = ['id']
|
||||
|
||||
def __init__(self):
|
||||
self.id = None
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.id == other.id
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.id)
|
||||
|
||||
|
||||
class XTPacket(_Packet):
|
||||
def __init__(self, *packet_id):
|
||||
super().__init__()
|
||||
self.id = '#'.join(packet_id)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.id)
|
||||
|
||||
|
||||
class XMLPacket(_Packet):
|
||||
def __init__(self, packet_id):
|
||||
super().__init__()
|
||||
self.id = packet_id
|
||||
|
||||
|
||||
class Priority(enum.Enum):
|
||||
Override = 3
|
||||
High = 2
|
||||
Low = 1
|
||||
|
||||
|
||||
class _Listener(_ArgumentDeserializer):
|
||||
|
||||
__slots__ = ['priority', 'packet', 'overrides']
|
||||
|
||||
def __init__(self, packet, callback, **kwargs):
|
||||
super().__init__(packet.id, callback, **kwargs)
|
||||
self.packet = packet
|
||||
|
||||
self.priority = kwargs.get('priority', Priority.Low)
|
||||
self.overrides = kwargs.get('overrides', [])
|
||||
|
||||
if type(self.overrides) is not list:
|
||||
self.overrides = [self.overrides]
|
||||
|
||||
|
||||
class _XTListener(_Listener):
|
||||
|
||||
__slots__ = ['pre_login']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.pre_login = kwargs.get('pre_login')
|
||||
|
||||
async def __call__(self, p, packet_data):
|
||||
if not self.pre_login and not p.joined_world:
|
||||
await p.close()
|
||||
raise AuthorityError('{} tried sending XT packet before authentication!'.format(p))
|
||||
|
||||
await super()._check_cooldown(p)
|
||||
super()._check_list(p)
|
||||
|
||||
await super().__call__(p, packet_data)
|
||||
|
||||
|
||||
class _XMLListener(_Listener):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
async def __call__(self, p, packet_data):
|
||||
await super()._check_cooldown(p)
|
||||
super()._check_list(p)
|
||||
|
||||
handler_call_arguments = [self.instance, p] if self.instance is not None else [p]
|
||||
|
||||
ctx = _ConverterContext(None, None, packet_data, p)
|
||||
for ctx.component in itertools.islice(self._signature, len(handler_call_arguments), len(self._signature)):
|
||||
if ctx.component.default is not ctx.component.empty:
|
||||
handler_call_arguments.append(ctx.component.default)
|
||||
elif ctx.component.kind == ctx.component.POSITIONAL_OR_KEYWORD:
|
||||
converter = get_converter(ctx.component)
|
||||
|
||||
handler_call_arguments.append(await do_conversion(converter, ctx))
|
||||
return await self.callback(*handler_call_arguments)
|
||||
|
||||
|
||||
def get_relative_function_path(function_obj):
|
||||
abs_function_file = inspect.getfile(function_obj)
|
||||
rel_function_file = os.path.relpath(abs_function_file)
|
||||
|
||||
return rel_function_file
|
||||
|
||||
|
||||
def handler(packet, **kwargs):
|
||||
if not issubclass(type(packet), _Packet):
|
||||
raise TypeError('All handlers can only listen for either XMLPacket or XTPacket.')
|
||||
|
||||
listener_class = _XTListener if isinstance(packet, XTPacket) else _XMLListener
|
||||
return _listener(listener_class, packet, **kwargs)
|
||||
|
||||
|
||||
def listener_exists(xt_listeners, xml_listeners, packet):
|
||||
listener_collection = xt_listeners if isinstance(packet, XTPacket) else xml_listeners
|
||||
return packet in listener_collection
|
||||
|
||||
|
||||
def is_listener(listener):
|
||||
return issubclass(type(listener), _Listener)
|
||||
|
||||
|
||||
def listeners_from_module(xt_listeners, xml_listeners, module):
|
||||
listener_objects = inspect.getmembers(module, is_listener)
|
||||
for listener_name, listener_object in listener_objects:
|
||||
if isinstance(module, Plugins.IPlugin):
|
||||
listener_object.instance = module
|
||||
|
||||
listener_collection = xt_listeners if type(listener_object) == _XTListener else xml_listeners
|
||||
if listener_object.packet not in listener_collection:
|
||||
listener_collection[listener_object.packet] = []
|
||||
|
||||
if listener_object not in listener_collection[listener_object.packet]:
|
||||
if listener_object.priority == Priority.High:
|
||||
listener_collection[listener_object.packet].insert(0, listener_object)
|
||||
elif listener_object.priority == Priority.Override:
|
||||
listener_collection[listener_object.packet] = [listener_object]
|
||||
else:
|
||||
listener_collection[listener_object.packet].append(listener_object)
|
||||
|
||||
for listener_name, listener_object in listener_objects:
|
||||
listener_collection = xt_listeners if type(listener_object) == _XTListener else xml_listeners
|
||||
for override in listener_object.overrides:
|
||||
listener_collection[override.packet].remove(override)
|
||||
|
||||
|
||||
def remove_handlers_by_module(xt_listeners, xml_listeners, handler_module_path):
|
||||
def remove_handlers(remove_handler_items):
|
||||
for handler_id, handler_listeners in remove_handler_items:
|
||||
for handler_listener in handler_listeners:
|
||||
handler_file = get_relative_function_path(handler_listener.callback)
|
||||
if handler_file == handler_module_path:
|
||||
handler_listeners.remove(handler_listener)
|
||||
remove_handlers(xt_listeners.items())
|
||||
remove_handlers(xml_listeners.items())
|
||||
|
||||
|
||||
def cooldown(per=1.0, rate=1, bucket_type=BucketType.Default, callback=None):
|
||||
def decorator(handler_function):
|
||||
handler_function.__cooldown = _CooldownMapping(callback, _Cooldown(per, rate, bucket_type))
|
||||
return handler_function
|
||||
return decorator
|
||||
|
||||
|
||||
def check(predicate):
|
||||
def decorator(handler_function):
|
||||
if not hasattr(handler_function, 'checks'):
|
||||
handler_function.__checks = []
|
||||
|
||||
if not type(predicate) == FunctionType:
|
||||
raise TypeError('All handler checks must be a function')
|
||||
|
||||
handler_function.__checks.append(predicate)
|
||||
return handler_function
|
||||
return decorator
|
||||
|
||||
|
||||
def allow_once():
|
||||
def check_for_packet(listener, p):
|
||||
return listener.packet not in p.received_packets
|
||||
return check(check_for_packet)
|
||||
|
||||
|
||||
def player_attribute(**attrs):
|
||||
def check_for_attributes(_, p):
|
||||
for attr, value in attrs.items():
|
||||
if not getattr(p, attr) == value:
|
||||
return False
|
||||
return True
|
||||
return check(check_for_attributes)
|
||||
|
||||
|
||||
def player_data_attribute(**attrs):
|
||||
def check_for_attributes(_, p):
|
||||
for attr, value in attrs.items():
|
||||
if not getattr(p.data, attr) == value:
|
||||
return False
|
||||
return True
|
||||
return check(check_for_attributes)
|
||||
|
||||
|
||||
def player_in_room(*room_ids):
|
||||
def check_room_id(_, p):
|
||||
return p.room.ID in room_ids
|
||||
return check(check_room_id)
|
Reference in New Issue
Block a user