예제 #1
0
파일: cho.py 프로젝트: Mxnuuel/gulag
    async def handle(self, p: Player) -> None:
        # XXX: this only sends when the client can see > 256 players,
        # so this probably won't have much use for private servers.

        # NOTE: i'm not exactly sure how bancho implements this and whether
        # i'm supposed to filter the users presences to send back with the
        # player's presence filter; i can add it in the future perhaps.
        for t in glob.players:
            if p is not t:
                p.enqueue(packets.userPresence(t))
예제 #2
0
파일: cho.py 프로젝트: Mxnuuel/gulag
        data += packets.channelInfo(*c.basic_info)

    # fetch some of the player's
    # information from sql to be cached.
    await p.achievements_from_sql()
    await p.stats_from_sql_full()
    await p.friends_from_sql()

    if glob.config.server_build:
        # update their country data with
        # the IP from the login request.
        await p.fetch_geoloc(ip)

    # update our new player's stats, and broadcast them.
    user_data = (packets.userPresence(p) + packets.userStats(p))

    data += user_data

    # o for online, or other
    for o in glob.players:
        # enqueue us to them
        o.enqueue(user_data)

        # enqueue them to us.
        data += packets.userPresence(o)
        data += packets.userStats(o)

    data += packets.mainMenuIcon()
    data += packets.friendsList(*p.friends)
    data += packets.silenceEnd(p.remaining_silence)
예제 #3
0
파일: cho.py 프로젝트: Mxnuuel/gulag
 async def handle(self, p: Player) -> None:
     for pid in self.user_ids:
         if t := await glob.players.get(id=pid):
             p.enqueue(packets.userPresence(t))
예제 #4
0
            data.extend(packets.channelJoin(c.name))

        data.extend(packets.channelInfo(*c.basic_info))

    # fetch some of the player's
    # information from sql to be cached.
    await p.stats_from_sql_full()
    await p.friends_from_sql()

    if glob.config.server_build:
        # update their country data with
        # the IP from the login request.
        await p.fetch_geoloc(ip)

    # update our new player's stats, and broadcast them.
    user_data = (packets.userPresence(p) + packets.userStats(p))

    data.extend(user_data)

    # o for online, or other
    for o in glob.players:
        # enqueue us to them
        o.enqueue(user_data)

        # enqueue them to us.
        data.extend(packets.userPresence(o) + packets.userStats(o))

    data.extend(packets.mainMenuIcon() + packets.friendsList(*p.friends) +
                packets.silenceEnd(p.remaining_silence))

    # thank u osu for doing this by username rather than id
예제 #5
0
        data += packets.channelInfo(*c.basic_info)

    # fetch some of the player's
    # information from sql to be cached.
    await p.stats_from_sql_full()
    await p.friends_from_sql()

    if glob.config.server_build:
        # update their country data with
        # the IP from the login request.
        await p.fetch_geoloc(ip)

    # update our new player's stats, and broadcast them.
    user_data = (
        packets.userPresence(p) +
        packets.userStats(p)
    )

    data += user_data

    # o for online, or other
    for o in glob.players:
        # enqueue us to them
        o.enqueue(user_data)

        # enqueue them to us.
        data += packets.userPresence(o)
        data += packets.userStats(o)

    data += packets.mainMenuIcon()
예제 #6
0
        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))

        resp = await make_response(bytes(data))
        resp.headers['cho-token'] = token
예제 #7
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
예제 #8
0
파일: bancho.py 프로젝트: kingdom5500/gulag
def userPresenceRequest(p: Player, pr: PacketReader) -> None:
    for pid in pr.read(osuTypes.i32_list):
        if t := glob.players.get_by_id(pid):
            p.enqueue(packets.userPresence(t))