Example #1
0
File: cho.py Project: Mxnuuel/gulag
    else:
        del user_info['clan_id']
        del user_info['clan_rank']
        clan = clan_rank = None

    # user_info: {id, name, priv, pw_bcrypt, silence_end}
    p = Player.login(user_info,
                     utc_offset=utc_offset,
                     osu_ver=s[0],
                     pm_private=pm_private,
                     login_time=login_time,
                     clan=clan,
                     clan_rank=clan_rank)

    data = bytearray(packets.userID(p.id))
    data += packets.protocolVersion(19)
    data += packets.banchoPrivileges(p.bancho_priv
                                     | ClientPrivileges.Supporter)
    if first_login:
        data += packets.sendMessage(
            'Ruji',
            'Welcome to Iteki!\n\nIteki has a relatively unique experience from other servers as it is based on different source code and has many unique features.'
            '\n\nTo get started, you may be interested in knowing some useful commands:\n\n!req <rank/love> <set/map> - this is our request system:'
            '\nTo use this command you must first /np a map to Ruji (our bot) and you will then be able to request maps.'
            '\nThe choice between rank/love depends on whether you would like to request the map to be ranked or loved.\nThe map/set choices are depending on whether you want the entire set to be requested, or just the difficulty you did /np to.'
            '\n\nThats all you need to know for now.\nIf you have any issues please report them and have fun playing Iteki!\n\n',
            p.name, 1)

    if p.priv & Privileges.Nominator and not p.priv & Privileges.Staff:
        request = await glob.db.fetch('SELECT COUNT(id) AS count FROM requests'
                                      )
Example #2
0
        'login_time': login_time,
        'clan': clan,
        'clan_priv': clan_priv
    }

    p = Player(
        **user_info,  # {id, name, priv, pw_bcrypt, silence_end}
        **extras  # {utc_offset, osu_ver, pm_private,
        #  login_time, clan, clan_priv}
    )

    for mode in GameMode:
        p.recent_scores[mode] = None  # TODO: sql?
        p.stats[mode] = None

    data = bytearray(packets.protocolVersion(19))
    data += packets.userID(p.id)

    # *real* client privileges are sent with this packet,
    # then the user's apparent privileges are sent in the
    # userPresence packets to other players. we'll send
    # supporter along with the user's privileges here,
    # but not in userPresence (so that only donators
    # show up with the yellow name in-game, but everyone
    # gets osu!direct & other in-game perks).
    data += packets.banchoPrivileges(p.bancho_priv
                                     | ClientPrivileges.Supporter)

    data += packets.notification('Welcome back to the gulag!\n'
                                 f'Current build: v{glob.version}')
Example #3
0
        # sort out geoloc | SPEEEEEEEEEEEEEED gains
        ip = headers['X-Real-IP']
        reader = database.Reader('ext/geoloc.mmdb')
        geoloc = reader.city(ip)
        country, user['lat'], user['lon'] = (geoloc.country.iso_code, geoloc.location.latitude, geoloc.location.longitude)
        user['country'] = country_codes[country]
        await glob.db.execute('UPDATE users SET country = %s WHERE id = %s', [country.lower(), user['id']]) # update country code in db

        friends = {row['user2'] async for row in glob.db.iterall('SELECT user2 FROM friends WHERE user1 = %s', [user['id']])} # select all friends from db

        ucache = glob.cache['user']
        if str(token) not in ucache:
            ucache[str(token)] = user['id'] # cache token to use outside of this request
        data = bytearray(packets.userID(user['id'])) # initiate login by providing the user's id
        data += packets.protocolVersion(19) # no clue what this does
        data += packets.banchoPrivileges(1 << 4) # force priv to developer for now
        data += (packets.userPresence(user) + packets.userStats(user)) # provide user & other user's presence/stats (for f9 + user stats)
        data += packets.notification(f'Welcome to Asahi v{glob.version}') # send notification as indicator they've logged in i guess
        data += packets.channelInfoEnd() # no clue what this does either
        data += packets.menuIcon() # set main menu icon
        data += packets.friends(*friends) # send user friend list
        data += packets.silenceEnd(0) # force to 0 for now since silences arent a thing
        #data += packets.sendMessage(user['name'], 'test message lol so cool', user['name'], user['id']) # test message

        # add user to cache?
        pcache = glob.players
        pcache.append(user)
        for p in pcache: # enqueue other users to client
            data += (packets.userPresence(p) + packets.userStats(p))
Example #4
0
        p_row['priv'] |= int(Privileges.Verified)

        await glob.db.execute(
            'UPDATE users SET priv = priv | %s WHERE id = %s',
            [p_row['priv'], p_row['id']])

    p_row |= {
        'utc_offset': utc_offset,
        'pm_private': pm_private,
        'osu_ver': osu_ver
    }

    p = Player(**p_row)

    data = bytearray(
        packets.userID(p.id) + packets.protocolVersion(19) +
        packets.banchoPrivileges(p.bancho_priv) +
        packets.notification('Welcome back to the gulag!\n'
                             f'Current build: {glob.version}') +

        # tells osu! to load channels from config, i believe?
        packets.channelInfoEnd())

    # channels
    for c in glob.channels:
        if not p.priv & c.read:
            continue  # no priv to read

        # autojoinable channels
        if c.auto_join and await p.join_channel(c):
            # NOTE: p.join_channel enqueues channelJoin, but
Example #5
0
async def login():
    headers = request.headers  # request headers, used for things such as user ip and agent

    if 'User-Agent' not in headers or headers['User-Agent'] != 'osu!':
        # request isn't sent from osu client, return nothing
        return

    if 'osu-token' not in headers:  # sometimes a login request will be a re-connect attempt, in which case they will already have a token, if not: login the user
        data = await request.data  # request data, used to get info such as username to login the user
        info = data.decode().split(
            '\n')[:-1]  # format data so we can use it easier

        username = info[0]
        pw = info[1].encode(
        )  # password in md5 form, we will use this to compare against db's stored bcrypt later

        user = await glob.db.fetch(
            'SELECT id, pw, country, name FROM users WHERE name = %s',
            [username])
        if not user:  # ensure user actually exists before attempting to do anything else
            log(f'User {username} does not exist.', Ansi.LRED)
            resp = await make_response(packets.userID(-1))
            resp.headers['cho-token'] = 'no'
            return resp

        bcache = glob.cache[
            'bcrypt']  # get our cached bcrypts to potentially enhance speed
        pw_bcrypt = user['pw'].encode()
        if pw_bcrypt in bcache:
            if pw != bcache[
                    pw_bcrypt]:  # compare provided md5 with the stored (cached) bcrypt to ensure they have provided the correct password
                log(
                    f"{username}'s login attempt failed: provided an incorrect password",
                    Ansi.LRED)
                resp = await make_response(packets.userID(-1))
                resp.headers['cho-token'] = 'no'
                return resp
        else:
            if not bcrypt.checkpw(
                    pw, pw_bcrypt
            ):  # compare provided md5 with the stored bcrypt to ensure they have provided the correct password
                log(
                    f"{username}'s login attempt failed: provided an incorrect password",
                    Ansi.LRED)
                resp = await make_response(packets.userID(-1))
                resp.headers['cho-token'] = 'no'
                return resp

            bcache[pw_bcrypt] = pw  # cache pw for future

        token = uuid.uuid4()  # generate token for client to use as auth
        ucache = glob.cache['user']
        if str(token) not in ucache:
            ucache[str(token)] = user[
                'id']  # cache token to use outside of this request
        data = bytearray(packets.userID(
            user['id']))  # initiate login by providing the user's id
        data += packets.protocolVersion(19)  # no clue what this does
        data += packets.banchoPrivileges(
            1 << 4)  # force priv to developer for now
        data += (
            packets.userPresence(user) + packets.userStats(user)
        )  # provide user & other user's presence/stats (for f9 + user stats)
        data += packets.notification(
            f'Welcome to Asahi v{glob.version}'
        )  # send notification as indicator they've logged in iguess
        data += packets.channelInfoEnd()  # no clue what this does either

        resp = await make_response(bytes(data))
        resp.headers['cho-token'] = token
        log(f'{username} successfully logged in.', Ansi.GREEN)
        return resp

    # if we have made it this far then it's a reconnect attempt with token already provided
    user_token = headers['osu-token']  # client-provided token
    tcache = glob.cache[
        'user']  # get token/userid cache to see if we need to relog the user or not
    if user_token not in tcache:
        # user is logged in but token is not found? most likely a restart so we force a reconnection
        return packets.restartServer(0)

    user = await glob.db.fetch(
        'SELECT id, pw, country, name FROM users WHERE id = %s',
        [tcache[user_token]])
    body = await request.body

    # handle any packets the client has sent | doesn't really work **for now**
    for packet in BanchoPacketReader(body, glob.packets):
        await packet.handle(user)
        log(f'Handled packet {packet}')

    resp = await make_response(b'')
    resp.headers['Content-Type'] = 'text/html; charset=UTF-8'  # ?
    return resp