Coder Social home page Coder Social logo

osuakatsuki / bancho.py Goto Github PK

View Code? Open in Web Editor NEW
191.0 8.0 123.0 7.19 MB

An osu! server implementation optimized for maintainability in modern python

Home Page: https://akatsuki.gg

License: MIT License

Python 97.01% Shell 1.49% Go 1.26% Makefile 0.16% Dockerfile 0.08%
osu python

bancho.py's People

Contributors

7ez avatar 7mochi avatar airiuwu avatar alowave223 avatar arily avatar atakku avatar cfgexe avatar cmyui avatar def750 avatar dependabot[bot] avatar faithy3 avatar g1-1-1 avatar gamerboy80 avatar hedgehog-qd avatar horizoncode avatar hwk929 avatar jacksonisiah avatar jkbgl avatar ledlamp avatar memsdm05 avatar minisbett avatar niceaesth avatar pre-commit-ci[bot] avatar pure-peace avatar sensokaku avatar skrungly avatar sukooo avatar timestwo avatar tsunyoku avatar yo-ru avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bancho.py's Issues

Delay first place announcements in multiplayer matches

This is actually a problem with every server implementation so far I believe; if multiple players achieve first place on a map, it'll announce all of them in the order that it gets the scores in.

The server should enqueue a task once the server knows the match has ended to re-check the first place in a few seconds (~5-10 should be fine), and announce it if it's been set.

additional testing needed for tournament client

very basic tournament client support is being rolled out in 3.2.4, but it's very undertested and certainly has some issues.
gulag was designed without the tourney client in mind (i've never really used it), so having a player online multiple times will likely cause some issues in places where i don't expect it.

we should also probably limit the amount of tourney clients that a user connects with at a time, and perhaps do some more advanced safety checks.

Add IRC Functionality

Proposal

Summary

The offical osu! server has an IRC server. So does Ripple. They provide a platform for external bots such as Tillerino and MaidBot to operate, enriching the user experience on their respective server. I propose we do the same, although make it async.

Motivation

A lot of a private server's job is to emulate Bancho while also adding new features. Even though IRC is not essential to a Bancho clone, it however allows bots to run without needing a Bancho connection. Mostly, this serves as compatibility, since most osu bot frameworks work via IRC (i.e. bancho.js). Also, it's cool.

Describe alternatives you've considered

Using a "modern" IRC-like service (like Firebase) would render the compatibility aspect useless. The only purpose IRC serves on osu! is interacting with osu's chat. It can't submit scores, or even lookup user data. Simple is good.

Additional context

I'm willing to develop it as @cmyui already has enough on his plate. Think of it as an initiation project. If it never gets delivered, it won't cripple Gulag's infrastructure. Likewise, if it does get delivered it (should) warrant a version increase (@cmyui can i commit to devel?)

Some objectives for the IRC server

  • Seamless integration into existing code (Bancho user == IRC user)
  • irc.ppy.sh compatible
  • Redirects DMs to BanchoBot to Aiko
  • Token protected
  • DB table for storing IRC usernames and tokens (with a relational element to userids)
  • gulag-web interface for creating tokens (talk with @yo-ru about that one)
  • command for creating tokens
  • async (runs in main loop instead of threads, because screw threads)
  • lightweight and fast (ad hoc, not a thin layer over a dependency)
  • works with IRC clients like HexChat

-- sansquick

SQL connection & cursor reuse for better efficiency

At the moment I use a thin aiomysql pool wrapper with fetch()/execute() functions which open a connection & retrieve a cursor to perform a single query at a time before closing them.

This is okay most of the time since the conn/cursor retrieval portion of the queries are pretty cheap, but there are some times in the code where I do many back-to-back queries and the cost adds up unnecessarily.

I'll soon be pushing an update to cmyui_pkg to make this simpler & more elegant and the rewriting will begin after that.

chimu.moe/download api support

while the server can already use chimu.moe for osu!direct search (and i plan on adding some more advanced search mechanics for map stats like ar/od/etc.), the api for chimu's downloading is a bit different from cheesegull and also requires an API key, so we'll have to implement that somewhere in config if we want to fully support it.

add CI/CD

BENEFITS : Better collaboration and software quality.

pymysql packet sequence errors

it seems whenever connecting to the server after a while of inactivity, the osu bansho connection takes a long time (like half to one minute) and there's this error printed to console

Allow users to block other users (server-side)

Should be pretty simple, perhaps the existing friendships table should be modified a bit to be dual-purpose for this. A user should not be able to be friends with a user they have blocked, and vice-versa.

(PYL-W0108) Unnecessary lambda expression

Description

A lambda that calls a function without modifying any of its parameters is unnecessary. Python functions are first-class objects and can be passed around in the same way as the resulting lambda. It is recommended to remove the lambda and use the function directly. Example:

loop.add_signal_handler(signal.SIGINT, loop.stop)
loop.add_signal_handler(signal.SIGTERM, loop.stop)

Occurrences

There are 2 occurrences of this issue in the repository.

See all occurrences on DeepSource → deepsource.io/gh/Uniminin/gulag/issue/PYL-W0108/occurrences/

ubuntu 20.04 dropped support for tls versions used by osu!stable

  • ubuntu 20.04 & nginx have unknown issues? i recommend using 18.04

apparently osu uses older tls 1.2 or 1.1 which ubuntu 20.04 doesn't support but 18.04 does.

I tried adding

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:@SECLEVEL=1";

to nginx config but it didn't work. edit: not sure where I tried it (i think on centos 8) but it worked on 20.04

So if you can somehow enable TLS 1.0/1.1 then it should work.

Alternatively you could just use cloudflare, which supports it.

Remove breakpoints & point_of_interest calls

These should be replaced by a system that logs the stacktraces (and automatically sends them to cmyui if enabled), as freezing the entire server is no longer a viable option with gulag starting to be used by 'real' production servers. (it'll only scale worse with time)

AttributeError: 'NoneType' object has no attribute 'as_tuple' error on startup

root@ubuntu-s-2vcpu-4gb-sfo3-01:~/gulag# ./main.py
[08:03:49PM] It is not recommended to run gulag as root, especially in production..
gulag v3.5.4 ran into an issue before starting up :(
Traceback (most recent call last):
File "/root/gulag/./main.py", line 209, in
raise SystemExit(loop.run_until_complete(main()))
File "uvloop/loop.pyx", line 1501, in uvloop.loop.Loop.run_until_complete
File "/root/gulag/./main.py", line 126, in main
await misc.utils.update_mysql_structure()
File "/root/gulag/misc/utils.py", line 691, in update_mysql_structure
if latest_ver == current_ver:
File "/usr/local/lib/python3.9/dist-packages/cmyui/version.py", line 22, in eq
return self.as_tuple == other.as_tuple
AttributeError: 'NoneType' object has no attribute 'as_tuple'

Add testing

Codebase is getting really quite large now and errors do arise and are left unnoticed for longer than ideal, it's time for gulag to get some tests.

Running gulang with pypy3

Is gulag hardly dependent on python3.9? Does it work on python3.7?

I was wondering weather gulag would run with pypy!

unhandled exception when user creates account that has safe_name but not equal name

example: Hello World and Hello_World, they both get the safe name hello_world and if someone tries to make one of either after the other already exists it throws an unhandled exception.

this would be a better check for username, it shouldn't matter whether or not the normal name already exists.

    if 'username' not in errors:
        await db_cursor.execute('SELECT 1 FROM users WHERE safe_name = %s', [name.lower().replace(' ', '_')])
        if db_cursor.rowcount != 0:
            errors['username'].append('Username already taken by another player.')

(PYL-R1705) Unnecessary `else` / `elif` used after `return`

Description

return statement causes the control flow to be disrupted, making the else / elif block here unnecessary. This doesn't mean you can not use it, but it is recommended to refactor this for a better readability. Bad:

def classify_number(x): if x % 2 == 0: return "Even" else: return

Occurrences

There are 9 occurrences of this issue in the repository.

See all occurrences on DeepSource → deepsource.io/gh/Uniminin/gulag/issue/PYL-R1705/occurrences/

Api last seen

I recommend adding last seen timestamp to output of /api/get_player_status?id={id} when user is offline

No sort of update log for sql and configuration changes.

When I first started designing, I didn't think I'd be making such frequent changes to the structure of the database; turns out this happens much more than I was anticipating, and leaving it on users to make their own queries to fix their sql isn't great..

Will probably just make a log file with copy-pastable updates for each version release with sql changes

oppai-ng should use c bindings

currently the implementation uses subprocess, which is pretty gross but works fine for the time being.

this poses some challenges, i've had issues whenever i've tried to use the bindings in an efficient manner (reusing the same instance many times) for mass-recalculations - recently i've been in contact with the main developer and we've been working our way through these slowly, though.

we'll also need to build our own bindings since we've modified oppai-ng's source.

GraphQL API

What's GraphQL

Taken straight from their website:

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data
-GraphQL

Basically, instead of individual endpoints representing objects in the server (ie GET getUser/1 == Player(1)) , GraphQL processes a scheme sent my the client and fills it out with the requested data. This allows our entire api to be one endpoint. You can read more about it on their website.

Here is an example of a GraphQL request and response.

GraphQL is mainly aimed towards sending data from objects. You can request attributes of an object and it will respond with those attributes.


Why

As gulag-web requires more and more data from data, there is a need to keep creating endpoints for every unique information requested. This creates a lot of bloat and unnecessary version communication between gulag and gulag-web. A GraphQL implementation would cut down on this bloat and make development much easier. Most API transactions are about lbs, users, or other data of that nature, which can be simplified with this API system.

On top of this, the server only responses with the data requested. Systems like this would become archaic.
https://github.com/cmyui/gulag/blob/b0a87c123223c5498428169c4a43a9ecd731f16f/domains/osu.py#L1563-L1584


How

Graphene is a robust GraphQL engine for python. Instead of running as a server, it processes string information you pass into it. This allows Graphene to run over cmyui_pkg. With a bit of modification, existing objects can be used by Graphene to make GraphQl schema. On gulag-web, Graphene can be used to parse responses into a dict which can be used by the program. Either way win-win.


Thoughts

While I know GraphQL for its powerful requesting functionality, I also think it can "POST" data too. Maybe we can dip our toes into GraphQL on the "GET" side before using it for posting data, idk.

EDIT: super cool demo https://api.spacex.land/graphql/

Logo

gulag-web has one how come we don't. hmph

Really very beautiful code

The code is beautiful and well written!
It's the first time I felt reading other people's code is so comfortable

Improve API coverage & transfer/improve on existing ones from gulag-web.

The API is currently very lacking; we need at least coverage of user information (stats, scores, achievements, info), beatmaps, clans, etc.), we plan to move the API back to gulag itself mostly due to it's caching.

I need to put more thought into the optimal design for things like ranking graph data.

(PYL-R1706) Consider using if expression

Description

At line handlers.py#L229, One of known pre Python 2.5 ternary syntax is being used. It is recommended to use an if expression like: X if condition else Y. Using [condition] and [on_true] or [on_false] may also give wrong results when on_true has a false boolean value. The inconsistency: Consider the following:

path = _path if os.path.exists(_path) else default_avatar

Occurrences

There is just only 1 occurrence of this issue in the repository.

See all occurrences on DeepSource → deepsource.io/gh/Uniminin/gulag/issue/PYL-R1706/occurrences/

!compare command

!compare is a command that's become commonplace in osu!-related discord bots.
lets you compare to the most recent !top or !recent post in the channel.

Beatmap submission system

This one is pretty large compared to any other issues, it entails the implementation of the following handlers:

POST /web/osu-osz2-bmsubmit-post.php
POST /web/osu-osz2-bmsubmit-upload.php
GET /web/osu-osz2-bmsubmit-getid.php
GET /web/osu-get-beatmap-topic.php

along with writing a program to write osz2 files, and quite a few backend changes.
I've already done a few hundred lines of code of this one, but it will likely not be implemented into master for a while to come.

Create API documentation

At the moment, all documentation of the API is what is provided in the code.

This is mostly fine since we're in python and the implementation is quite simple at the moment, but eventually the docs should be moved into a section of their own, unrelated to the code to help our community developers out.

Multiplayer beatmap selection implementation incorrect

While first designing, I thought I could simply ignore the map name and fetch it from the db (or it's cache wrapper) by md5 (ends up being faster this way), but this also means people can't play unsubmitted maps in multi.. while this doesn't seem major at all, I like playing speedup diffs in multi matches so this is simply unacceptable :D

Should be a pretty ez fix, just needs a recode.

Missing characters cause incorrect results

This problem causes some beatmap file names with special characters :\*></?" | were incorrectly determined for ranking status.

The problem occurred in: osu-osz2-getscores.php [domains/osu.py - getScores]
https://github.com/cmyui/gulag/blob/4de101c800516b1698de13db2a15df1d2933ff48/domains/osu.py#L913

Description

These are the code snippets where the problem occurred:
https://github.com/cmyui/gulag/blob/4de101c800516b1698de13db2a15df1d2933ff48/domains/osu.py#L967-L992
Notice that line 967, gulag uses a regex parsing the beatmap filename sent by the osu client:
https://github.com/cmyui/gulag/blob/4de101c800516b1698de13db2a15df1d2933ff48/domains/osu.py#L967
If parsed correctly, artist, title, creator, version will be extracted from the beatmap filename we received. (There is a bug in the regex, the bug prevents correct parsing, I have submitted the pr here: #78 )

Assuming here that the bug has been resolved, we continue...

The main problem arises in the following code snippet:
https://github.com/cmyui/gulag/blob/4de101c800516b1698de13db2a15df1d2933ff48/domains/osu.py#L975-L982
gulag tries to get the beatmap using the information(artist, title, version, creator) obtained by parsing filename,
but, filename will not include the following characters: :\*></?" |.

Beatmap info (from the osu!api or database) will contain these special characters, this causes the beatmap with the special characters to not match correctly, such as this: https://osu.ppy.sh/beatmapsets/1084205#osu/2267413

diff name: [[[#340000_cyiorlia//alt.remix]]]_Un:Re:sponsive oh..its... but still ranked.

Solutions

Join the beatmap information from the database or osu!api into legal filenames (also removing special characters) so that the filenames can be successfully matched.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.