A python library for serializing and deserializing bancho packets.
Project description
Chio
Chio (Bancho I/O) is a python library for serializing and deserializing bancho packets, with support for all versions of osu! that use bancho (2008-2025).
It was made with the intention of documenting everything about the bancho protocol, and to provide a base for server frameworks, since the packet handling part is most often the annoying part.
Having any client be able to connect to it is a very sweet addition on top, if you are interested in those as well.
If you wish to use this library, I would appreciate some credit for my work. Thanks!
Usage
This library requires an installation of python 3.8 or higher.
You can install the library with pip:
pip install chio
Or you can also install it from source directly, if preferred:
pip install git+https://github.com/Lekuruu/chio.py
Here is a very basic example of how to use this library, and how to get a client to log in:
import chio
# Chio expects you to have the `chio.Stream` class
# implemented, i.e. it needs a `read()` and `write()`
# function to work properly
stream = chio.Stream()
# The client version is how chio determines what
# protocol to use. This one can be parsed through the
# initial login request, that the client makes.
client_version = 20140127
# Chio has combined the user presence, stats and status
# into one class, to support more clients. You are also
# able to provide your own player class, as long as you
# have the same fields added on to it.
info = chio.UserInfo(
id=2,
name="peppy",
presence=chio.UserPresence(),
stats=chio.UserStats(),
status=chio.UserStatus()
)
# Select a client protocol to use for encoding/decoding
io = chio.select_client(client_version)
# Send the users information (userId, presence & stats)
io.write_packet(stream, chio.PacketType.BanchoLoginReply, info.id)
io.write_packet(stream, chio.PacketType.BanchoUserPresence, info)
io.write_packet(stream, chio.PacketType.BanchoUserStats, info)
# Force client to join #osu
io.write_packet(stream, chio.PacketType.BanchoChannelJoinSuccess, "#osu")
# Send a message in #osu from BanchoBot
io.write_packet(
stream,
chio.PacketType.BanchoMessage,
chio.Message(content="Hello, World!", sender="BanchoBot", target="#osu")
)
packet, data = io.read_packet(stream)
print(f"Received packet '{packet.name}' with {data}.")
You can also read & write from bytes directly, for example when using HTTP clients instead of TCP clients:
encoded = io.write_packet_to_bytes(chio.PacketType.BanchoLoginReply, info.id)
packet, data = io.read_packet_from_bytes(b"...")
If you are using asyncio, you may want to use the read_packet_async & write_packet_async functions respectively for asynchronous usage.
This feature is currently untested, but should work in theory. If you encounter any bugs with it, don't be afraid to report them.
encoded = await io.write_packet_async(stream, chio.PacketType.BanchoLoginReply, info.id)
packet, data = await io.read_packet_async(stream)
Patching
You are able to overwrite specifc packet readers/writers, with the chio.patch decorator.
As an example, to patch the BanchoUserStats packet inside of b20120723:
@chio.patch(PacketType.BanchoUserStats, 20120723)
def write_user_stats(cls, info: UserInfo):
stream = MemoryStream()
write_s32(stream, info.id)
stream.write(cls.write_status_update(info.status))
write_u64(stream, info.stats.rscore)
write_f32(stream, info.stats.accuracy)
write_u32(stream, info.stats.playcount)
write_u64(stream, info.stats.tscore)
write_u32(stream, info.stats.rank)
write_u16(stream, info.stats.pp)
yield PacketType.BanchoUserStats, stream.data
Additionally, it's possible to set a certain slot size & protocol version for each version:
# Set protocol version to 10 for b20120818
chio.set_protocol_version(10, 20120818)
# Override slot size to 32 for b20160404
chio.set_slot_size(32, 20160404)
Datatypes
Depending on the packet you send or receive, you will need to account for different datatypes.
Here is a list of them for each packet:
| Packet | Type |
|---|---|
| OsuUserStatus | chio.UserStatus |
| OsuMessage | chio.Message |
| OsuExit | bool (IsUpdating) |
| OsuStatusUpdateRequest | N/A |
| OsuPong | N/A |
| BanchoLoginReply | int (UserId) or chio.LoginError |
| BanchoMessage | chio.Message |
| BanchoPing | N/A |
| BanchoIrcChangeUsername | str (old name), str (new name) |
| BanchoIrcQuit | str (Username) |
| BanchoUserStats | chio.UserInfo |
| BanchoUserQuit | chio.UserQuit |
| BanchoSpectatorJoined | int (UserId) |
| BanchoSpectatorLeft | int (UserId) |
| BanchoSpectateFrames | chio.ReplayFrameBundle |
| OsuStartSpectating | int (UserId) |
| OsuStopSpectating | int (UserId) |
| OsuSpectateFrames | chio.ReplayFrameBundle |
| BanchoVersionUpdate | N/A |
| OsuErrorReport | str (Exception) |
| OsuCantSpectate | N/A |
| BanchoSpectatorCantSpectate | int (UserId) |
| BanchoGetAttention | N/A |
| BanchoAnnounce | str (Message) |
| OsuPrivateMessage | chio.Message |
| BanchoMatchUpdate | chio.Match |
| BanchoMatchNew | chio.Match |
| BanchoMatchDisband | int (MatchId) |
| OsuLobbyPart | N/A |
| OsuLobbyJoin | N/A |
| OsuMatchCreate | chio.Match |
| OsuMatchJoin | int (MatchId) |
| OsuMatchPart | N/A |
| BanchoLobbyJoin | int (UserId) |
| BanchoLobbyPart | int (UserId) |
| BanchoMatchJoinSuccess | chio.Match |
| BanchoMatchJoinFail | N/A |
| OsuMatchChangeSlot | int (SlotId) |
| OsuMatchReady | N/A |
| OsuMatchLock | int (SlotId) |
| OsuMatchChangeSettings | chio.Match |
| BanchoFellowSpectatorJoined | int (UserId) |
| BanchoFellowSpectatorLeft | int (UserId) |
| OsuMatchStart | N/A |
| BanchoMatchStart | chio.Match |
| OsuMatchScoreUpdate | chio.ScoreFrame |
| BanchoMatchScoreUpdate | chio.ScoreFrame |
| OsuMatchComplete | N/A |
| BanchoMatchTransferHost | N/A |
| OsuMatchChangeMods | chio.Mods |
| OsuMatchLoadComplete | N/A |
| BanchoMatchAllPlayersLoaded | N/A |
| OsuMatchNoBeatmap | N/A |
| OsuMatchNotReady | N/A |
| OsuMatchFailed | N/A |
| BanchoMatchPlayerFailed | int (SlotId) |
| BanchoMatchComplete | N/A |
| OsuMatchHasBeatmap | N/A |
| OsuMatchSkipRequest | N/A |
| BanchoMatchSkip | N/A |
| OsuChannelJoin | str (Channel Name) |
| BanchoChannelJoinSuccess | str (Channel Name) |
| BanchoChannelAvailable | chio.Channel |
| BanchoChannelRevoked | str (Channel Name) |
| BanchoChannelAvailableAutojoin | chio.Channel |
| OsuBeatmapInfoRequest | chio.BeatmapInfoRequest |
| BanchoBeatmapInfoReply | chio.BeatmapInfoReply |
| OsuMatchTransferHost | int (SlotId) |
| BanchoLoginPermissions | chio.Permissions or int |
| BanchoFriendsList | list[int] |
| OsuFriendsAdd | int (UserId) |
| OsuFriendsRemove | int (UserId) |
| BanchoProtocolNegotiation | N/A or int |
| BanchoTitleUpdate | chio.TitleUpdate |
| OsuMatchChangeTeam | N/A |
| OsuChannelLeave | str (Channel Name) |
| OsuReceiveUpdates | chio.PresenceFilter |
| BanchoMonitor | N/A |
| BanchoMatchPlayerSkipped | int (SlotId) |
| OsuSetIrcAwayMessage | chio.Message |
| BanchoUserPresence | chio.UserInfo |
| OsuUserStatsRequest | list[int] |
| BanchoRestart | int (Retry After Milliseconds) |
| OsuInvite | int (UserId) |
| BanchoInvite | chio.Message |
| OsuMatchChangePassword | chio.Match |
| BanchoMatchChangePassword | str (New Password) |
| BanchoSilenceInfo | int (Locked Until Seconds) |
| OsuTournamentMatchInfo | int (MatchId) |
| BanchoUserSilenced | int (UserId) |
| BanchoUserPresenceSingle | int (UserId) |
| BanchoUserPresenceBundle | list[int] (UserIDs) |
| OsuPresenceRequest | list[int] (UserIDs) |
| OsuPresenceRequestAll | N/A |
| OsuChangeFriendOnlyDms | bool (Enabled/Disabled) |
| BanchoUserDmsBlocked | chio.Message |
| BanchoTargetIsSilenced | chio.Message |
| BanchoVersionUpdateForced | N/A |
| BanchoSwitchServer | int (After Idle Time) |
| BanchoAccountRestricted | N/A |
| BanchoRTX | str (Message) |
| BanchoMatchAbort | N/A |
| BanchoSwitchTournamentServer | str (Server) |
| OsuTournamentJoinMatchChannel | int (MatchId) |
| OsuTournamentLeaveMatchChannel | int (MatchId) |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chio-1.1.20.tar.gz.
File metadata
- Download URL: chio-1.1.20.tar.gz
- Upload date:
- Size: 40.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.23
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33f682d278d78e9eb8d87f7ad87f9d378c5d96307a718036069a50b452604e61
|
|
| MD5 |
5f0f7706a115c52461ece68d1a77f814
|
|
| BLAKE2b-256 |
8ff632eea7aaa6fd835403235c1540ddda386662186bf015ef5d2f854f0d61c5
|
File details
Details for the file chio-1.1.20-py3-none-any.whl.
File metadata
- Download URL: chio-1.1.20-py3-none-any.whl
- Upload date:
- Size: 70.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.23
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7aa42cc9a137001bd34372279cc0305e30dc390961a1a8c86705d7a36091d77
|
|
| MD5 |
36fbbfe0fa433bce3d1886d20df0201f
|
|
| BLAKE2b-256 |
68ce46ff179cb7e4ebe35e6420e32f15eb01a954c8b28e6a81abb3af7253af9d
|