API Reference

aioslsk.client

class aioslsk.client.SoulSeekClient(settings, shares_cache=None, transfer_cache=None, executor_factory=None, event_bus=None)

SoulSeek client class. This class is a facade for a collection of different aioslsk.base_manager.BaseManager classes and orchestrates the lifecycle of those classes

Parameters:
get_event_loop()
register_listeners()
async start(connect=True)

Performs a start up of the client consisting of:

  • Calls load_data on all defined services

  • Calls start on all defined services

  • Optionally: Starts a scan of the defined shares

  • Optionally: Connecting to the server and opening listening ports

Parameters:

connect (bool) – Whether to connect the network after start up

async run_until_stopped()
async stop()

Stops the client, this method consists of:

  • Disconnecting the network and waiting for all connections to close

  • Cancel all pending tasks and waiting for them to complete

  • Write the transfer and shares caches

async connect()

Initializes the network by connecting to the server and opening the configured listening ports

async login(client_version=157, minor_version=100)

Performs a logon to the server with the credentials defined in the settings

Raises:

AuthenticationError – When authentication failed

Parameters:
  • client_version (int)

  • minor_version (int)

async execute(command, response=False, timeout=10)

Execute a BaseCommand, see the aioslsk.commands module for a list of possible commands.

Waiting for a response is optional; the protocol does not always send error messages in case of failure. In these cases this method will timeout if the command is configured to wait for a response.

Example waiting for response:

..code-block:: python

from aioslsk.commands import GetUserStatusCommand

status = await client.execute(

GetUserStatusCommand(‘someuser’), reponse=True)

Example without response:

..code-block:: python

from aioslsk.commands import JoinRoomCommand

await client.execute(JoinRoomCommand(‘cool room’))

Parameters:
  • command (BaseCommand[RC, RT | None]) – Command class to execute

  • response (bool) – Whether to wait for the response or simply send (default: False)

  • timeout (float) – Timeout waiting for response (default: 10)

Raises:

InvalidSessionError – When no logon has been performed

Returns:

Optional response depending on how the command was configured

Return type:

RT | None

create_network()
Return type:

Network

create_user_manager()
Return type:

UserManager

create_room_manager()
Return type:

RoomManager

create_interest_manager()
Return type:

InterestManager

create_shares_manager(cache, executor_factory=None)
Parameters:
Return type:

SharesManager

create_transfer_manager(cache)
Parameters:

cache (TransferCache)

Return type:

TransferManager

create_search_manager()
Return type:

SearchManager

create_server_manager()
Return type:

ServerManager

create_peer_manager()
Return type:

PeerManager

create_distributed_network()
Return type:

DistributedNetwork

aioslsk.commands

class aioslsk.commands.RC

Response class type

alias of TypeVar(‘RC’, bound=MessageDataclass | None)

class aioslsk.commands.RT

Response value type

alias of TypeVar(‘RT’)

class aioslsk.commands.UserStatusInfo(status, privileged)
Parameters:
status: UserStatus

Alias for field number 0

privileged: bool

Alias for field number 1

class aioslsk.commands.UserStatsInfo(avg_speed, uploads, shared_file_count, shared_folder_count)
Parameters:
  • avg_speed (int)

  • uploads (int)

  • shared_file_count (int)

  • shared_folder_count (int)

avg_speed: int

Alias for field number 0

uploads: int

Alias for field number 1

shared_file_count: int

Alias for field number 2

shared_folder_count: int

Alias for field number 3

class aioslsk.commands.UserInfo(description, picture, has_slots_free, upload_slots, queue_length, upload_permissions)
Parameters:
description: str

Alias for field number 0

picture: bytes | None

Alias for field number 1

has_slots_free: bool

Alias for field number 2

upload_slots: int

Alias for field number 3

queue_length: int

Alias for field number 4

upload_permissions: UploadPermissions

Alias for field number 5

class aioslsk.commands.BaseCommand
abstractmethod async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

Optional[RT]

class aioslsk.commands.GetUserStatusCommand(username)
Parameters:

username (str)

username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

UserStatusInfo

class aioslsk.commands.GetUserStatsCommand(username)
Parameters:

username (str)

username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

UserStatsInfo

class aioslsk.commands.GetRoomListCommand
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

list[Room]

class aioslsk.commands.JoinRoomCommand(room, private=False)
Parameters:
room: str
private: bool
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

Room

class aioslsk.commands.LeaveRoomCommand(room)
Parameters:

room (str)

room: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

Room

class aioslsk.commands.GrantRoomMembershipCommand(room, username)
Parameters:
room: str
username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

tuple[Room, User]

class aioslsk.commands.RevokeRoomMembershipCommand(room, username)
Parameters:
room: str
username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

tuple[Room, User]

class aioslsk.commands.DropRoomMembershipCommand(room)
Parameters:

room (str)

room: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

Room

class aioslsk.commands.DropRoomOwnershipCommand(room)
Parameters:

room (str)

room: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.GetItemRecommendationsCommand(item)
Parameters:

item (str)

item: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

list[Recommendation]

class aioslsk.commands.GetRecommendationsCommand
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

Recommendations

class aioslsk.commands.GetGlobalRecommendationsCommand
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

Recommendations

class aioslsk.commands.GetItemSimilarUsersCommand(item)
Parameters:

item (str)

item: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

list[User]

class aioslsk.commands.GetSimilarUsersCommand
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

list[tuple[User, int]]

class aioslsk.commands.GetPeerAddressCommand(username)
Parameters:

username (str)

username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

tuple[str, int, Optional[int]]

class aioslsk.commands.GrantRoomOperatorCommand(room, username)
Parameters:
room: str
username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

None

class aioslsk.commands.RevokeRoomOperatorCommand(room, username)
Parameters:
room: str
username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

None

class aioslsk.commands.TogglePublicChatCommand(enable)
Parameters:

enable (bool)

enable: bool
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.TogglePrivateRoomInvitesCommand(enable)
Parameters:

enable (bool)

enable: bool
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

None

class aioslsk.commands.GlobalSearchCommand(query)
Parameters:

query (str)

query: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.UserSearchCommand(username, query)
Parameters:
username: str
query: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.RoomSearchCommand(room, query)
Parameters:
room: str
query: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.PrivateMessageCommand(username, message)
Parameters:
  • username (str)

  • message (str)

username: str
message: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.PrivateMessageUsersCommand(usernames, message)

Sends a private message to multiple users

Parameters:
usernames: list[str]
message: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.RoomMessageCommand(room, message)
Parameters:
room: str
message: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

RoomMessage

class aioslsk.commands.SetRoomTickerCommand(room, ticker)
Parameters:
room: str
ticker: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

class aioslsk.commands.AddInterestCommand(interest)
Parameters:

interest (str)

interest: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.AddHatedInterestCommand(hated_interest)
Parameters:

hated_interest (str)

hated_interest: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.RemoveInterestCommand(interest)
Parameters:

interest (str)

interest: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.RemoveHatedInterestCommand(hated_interest)
Parameters:

hated_interest (str)

hated_interest: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.GetUserInterestsCommand(username)
Parameters:

username (str)

username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

UserInterests

class aioslsk.commands.SetStatusCommand(status)
Parameters:

status (UserStatus)

status: UserStatus
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.SetNewPasswordCommand(password)
Parameters:

password (str)

password: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.CheckPrivilegesCommand
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

int

class aioslsk.commands.GivePrivilegesCommand(username, days)
Parameters:
username: str
days: int
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.TrackUserCommand(username)
Parameters:

username (str)

username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

User

class aioslsk.commands.UntrackUserCommand(username)
Parameters:

username (str)

username: str
async send(client)
Parameters:

client (SoulSeekClient)

class aioslsk.commands.PeerGetUserInfoCommand(username)
Parameters:

username (str)

username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

UserInfo

class aioslsk.commands.PeerGetSharesCommand(username)
Parameters:

username (str)

username: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

SharesReply

class aioslsk.commands.PeerGetDirectoryContentCommand(username, directory)
Parameters:
  • username (str)

  • directory (str)

username: str
directory: str
async send(client)
Parameters:

client (SoulSeekClient)

build_expected_response(client)
Parameters:

client (SoulSeekClient)

Return type:

Optional[ExpectedResponse]

handle_response(client, response)
Parameters:
Return type:

list[DirectoryData]

aioslsk.events

aioslsk.events.on_message(message_class)

Decorator for methods listening to specific MessageData events

Parameters:

message_class (type[MessageDataclass])

aioslsk.events.build_message_map(obj)
Parameters:

obj (object)

Return type:

dict[type[MessageDataclass], Callable]

class aioslsk.events.EventBus
register(event_class, listener, priority=100)

Registers an event listener to listen on an event class. The order in which the listeners are called can be managed using the priority parameter

Parameters:
unregister(event_class, listener)

Unregisters the event listener from event bus

Parameters:
async emit(event)

Emit an event on the event bus. Listeners can be co-routines or regular functions

Parameters:

event (Event) – the event instance to emit

emit_sync(event)

Emit an event on the event bus. Only listener functions are notified

Parameters:

event (Event) – the event instance to emit

class aioslsk.events.Event

Base class for events

class aioslsk.events.SessionInitializedEvent(session, raw_message)

Emitted after successful login

Parameters:
session: Session
raw_message: Response
class aioslsk.events.SessionDestroyedEvent(session)

Emitted after the login session has been destroyed (this is always after disconnect)

Parameters:

session (Session)

session: Session
class aioslsk.events.AdminMessageEvent(message, raw_message)

Emitted when a global admin message has been received

Parameters:
message: str
raw_message: Response
class aioslsk.events.KickedEvent(raw_message)

Emitted when we are kicked from the server

Parameters:

raw_message (Response)

raw_message: Response
class aioslsk.events.UserTrackingStateChangedEvent(user, state, raw_message=None)

Emitted when the tracking state of a user has changed.

Possibly states for the state property will be defined in by the TrackingState flags

Parameters:
user: User
state: TrackingState
raw_message: Response | None
class aioslsk.events.UserTrackingEvent(user, raw_message)

Emitted when a user is now successfully by the library tracked. This will be triggered when:

The user object will contain the tracked user. data will contain the data returned by the server

Deprecated since version 1.6: Use UserTrackingStateChangedEvent instead

Parameters:
user: User
raw_message: Response
class aioslsk.events.UserTrackingFailedEvent(username, raw_message)

Deprecated since version 1.6: Use UserTrackingStateChangedEvent instead

Parameters:
username: str
raw_message: Response
class aioslsk.events.UserUntrackingEvent(user)

Emitted when a user is no longer tracked by the library

Deprecated since version 1.6: Use UserTrackingStateChangedEvent instead

Parameters:

user (User)

user: User
class aioslsk.events.UserStatusUpdateEvent(before, current, raw_message)

Emitted when the server sends an update for the users status / privileges or a request for it

Parameters:
before: User
current: User
raw_message: Response
class aioslsk.events.UserStatsUpdateEvent(before, current, raw_message)

Emitted when the server send an update for the user’s sharing statistics

Parameters:
before: User
current: User
raw_message: Response
class aioslsk.events.UserInfoUpdateEvent(before, current, raw_message)

Emitted when user info has been received

Parameters:
before: User
current: User
raw_message: Request
class aioslsk.events.RoomListEvent(rooms: 'list[Room]', raw_message: 'RoomList.Response')
Parameters:
rooms: list[Room]
raw_message: Response
class aioslsk.events.RoomMessageEvent(message: 'RoomMessage', raw_message: 'RoomChatMessage.Response')
Parameters:
message: RoomMessage
raw_message: Response
class aioslsk.events.RoomTickersEvent(room, tickers, raw_message)

Emitted when a list of tickers has been received for a room

Parameters:
room: Room
tickers: dict[str, str]
raw_message: Response
class aioslsk.events.RoomTickerAddedEvent(room, user, ticker, raw_message)

Emitted when a ticker has been added to the room by a user

Parameters:
room: Room
user: User
ticker: str
raw_message: Response
class aioslsk.events.RoomTickerRemovedEvent(room, user, raw_message)

Emitted when a ticker has been removed from the room by a user

Parameters:
room: Room
user: User
raw_message: Response
class aioslsk.events.RoomJoinedEvent(room, raw_message, user=None)

Emitted after a user joined a chat room

The value of user will be None in case it is us who has joined the room

Parameters:
room: Room
raw_message: Response | Response
user: User | None
class aioslsk.events.RoomLeftEvent(room, raw_message, user=None)

Emitted after a user left a chat room

The value of user will be None in case it is us who has left the room

Parameters:
room: Room
raw_message: Response | Response
user: User | None
class aioslsk.events.RoomMembershipGrantedEvent(room, raw_message, member=None)

Emitted when a member has been added to the private room

The value of member will be None in case it is us who has been added to the room

Parameters:
room: Room
raw_message: Response | Response
member: User | None
class aioslsk.events.RoomMembershipRevokedEvent(room, raw_message, member=None)

Emitted when a member has been removed to the private room

The value of member will be None in case it is us who has been removed from the room

Parameters:
room: Room
raw_message: Response | Response
member: User | None
class aioslsk.events.RoomOperatorGrantedEvent(room, raw_message, member=None)

Emitted when a member has been granted operator privileges on a private room

The value of member will be None in case it is us who has been granted operator

Parameters:
room: Room
raw_message: Response | Response
member: User | None
class aioslsk.events.RoomOperatorRevokedEvent(room, raw_message, member=None)

Emitted when a member had operator privileges revoked on a private room

The value of user will be None in case it is us who has been revoked operator

Parameters:
room: Room
raw_message: Response | Response
member: User | None
class aioslsk.events.RoomOperatorsEvent(room, operators, raw_message)

Emitted when the server sends us a list of operators in a room

Parameters:
room: Room
operators: list[User]
raw_message: Response
class aioslsk.events.RoomMembersEvent(room, members, raw_message)

Emitted when the server sends us a list of members of a room. The list of members always excludes the owner of the room

Parameters:
room: Room
members: list[User]
raw_message: Response
class aioslsk.events.PrivateMessageEvent(message, raw_message)

Emitted when a private message has been received

Parameters:
message: ChatMessage
raw_message: Response
class aioslsk.events.PublicMessageEvent(timestamp, user, room, message, raw_message)

Emitted when a message has been received from a public room and public chat has been enabled

Parameters:
timestamp: int
user: User
room: Room
message: str
raw_message: Response
class aioslsk.events.SearchRequestSentEvent(query)

Emitted when a search request has been sent out

Parameters:

query (SearchRequest)

query: SearchRequest
class aioslsk.events.SearchRequestRemovedEvent(query)

Emitted when a search request has been removed

Parameters:

query (SearchRequest)

query: SearchRequest
class aioslsk.events.SearchResultEvent(query, result)

Emitted when a search result has been received

Parameters:
query: SearchRequest
result: SearchResult
class aioslsk.events.SearchRequestReceivedEvent(username, query, result_count)

Emitted when a search request by another user has been received

Parameters:
  • username (str)

  • query (str)

  • result_count (int)

username: str
query: str
result_count: int
class aioslsk.events.SimilarUsersEvent(users: 'list[tuple[User, int]]', raw_message: 'GetSimilarUsers.Response')
Parameters:
users: list[tuple[User, int]]
raw_message: Response
class aioslsk.events.ItemSimilarUsersEvent(item: 'str', users: 'list[User]', raw_message: 'GetItemSimilarUsers.Response')
Parameters:
item: str
users: list[User]
raw_message: Response
class aioslsk.events.RecommendationsEvent(recommendations: 'list[Recommendation]', unrecommendations: 'list[Recommendation]', raw_message: 'GetRecommendations.Response')
Parameters:
recommendations: list[Recommendation]
unrecommendations: list[Recommendation]
raw_message: Response
class aioslsk.events.GlobalRecommendationsEvent(recommendations: 'list[Recommendation]', unrecommendations: 'list[Recommendation]', raw_message: 'GetGlobalRecommendations.Response')
Parameters:
recommendations: list[Recommendation]
unrecommendations: list[Recommendation]
raw_message: Response
class aioslsk.events.ItemRecommendationsEvent(item: 'str', recommendations: 'list[Recommendation]', raw_message: 'GetItemRecommendations.Response')
Parameters:
item: str
recommendations: list[Recommendation]
raw_message: Response
class aioslsk.events.UserInterestsEvent(user: 'User', interests: 'list[str]', hated_interests: 'list[str]', raw_message: 'GetUserInterests.Response')
Parameters:
user: User
interests: list[str]
hated_interests: list[str]
raw_message: Response
class aioslsk.events.PrivilegedUsersEvent(users, raw_message)

Emitted when the list of privileged users has been received

Parameters:
users: list[User]
raw_message: Response
class aioslsk.events.PrivilegedUserAddedEvent(user)

Emitted when a new privileged user has been added

Parameters:

user (User)

user: User
class aioslsk.events.PrivilegesUpdateEvent(time_left, raw_message)

Emitted when we receive a message containing how much time is left on the current user’s privileges. If time_left is 0 the current user has no privileges

Parameters:
time_left: int
raw_message: Response
class aioslsk.events.UserSharesReplyEvent(user: 'User', directories: 'list[DirectoryData]', locked_directories: 'list[DirectoryData]', raw_message: 'PeerSharesReply.Request')
Parameters:
user: User
directories: list[DirectoryData]
locked_directories: list[DirectoryData]
raw_message: Request
class aioslsk.events.UserDirectoryEvent(user: 'User', directory: 'str', directories: 'list[DirectoryData]', raw_message: 'PeerDirectoryContentsReply.Request')
Parameters:
user: User
directory: str
directories: list[DirectoryData]
raw_message: Request
class aioslsk.events.TransferAddedEvent(transfer)

Emitted when a transfer has been attached to the client

Parameters:

transfer (Transfer)

transfer: Transfer
class aioslsk.events.TransferRemovedEvent(transfer)

Emitted when a transfer has been detached from the client

Parameters:

transfer (Transfer)

transfer: Transfer
class aioslsk.events.TransferProgressEvent(updates)

Called periodically to report progress. The interval is determined by the transfers.progress_interval settings parameter

This event only includes transfers where the transfer state has been changed since the previous event. If there are no updates the event will no be called

Parameters:

updates (list[tuple[Transfer, TransferProgressSnapshot, TransferProgressSnapshot]])

updates: list[tuple[Transfer, TransferProgressSnapshot, TransferProgressSnapshot]]

List of progress updates: transfer instance, previous snapshot, current snapshot

class aioslsk.events.InternalEvent

Base class for internal events

class aioslsk.events.ConnectionStateChangedEvent(connection, state, close_reason=None)

Indicates a state change in any type of connection

Parameters:
connection: Connection
state: ConnectionState
close_reason: CloseReason | None
class aioslsk.events.ServerReconnectedEvent

Indicates server reconnected, used internally to automatically log back in

class aioslsk.events.MessageReceivedEvent(message, connection)

Emitted when a message was received on a connection

Parameters:
message: MessageDataclass
connection: Connection
class aioslsk.events.PeerInitializedEvent(connection, requested)

Emitted when a new peer connection has been established and the initialization message has been received or sent

Parameters:
connection: PeerConnection
requested: bool

Indictes whether the connection was initialized by another user or opened on the client’s request

class aioslsk.events.ScanCompleteEvent(folder_count, file_count)

Emitted when shares scan was completed

Parameters:
  • folder_count (int)

  • file_count (int)

folder_count: int
file_count: int
class aioslsk.events.FriendListChangedEvent(added=<factory>, removed=<factory>)

Emitted when a change was detected in the friends list

Parameters:
added: set[str]
removed: set[str]
class aioslsk.events.BlockListChangedEvent(changes)

Emitted when a change was detected in the blocked list

Parameters:

changes (dict[str, tuple[BlockingFlag, BlockingFlag]])

changes: dict[str, tuple[BlockingFlag, BlockingFlag]]

List of changes. The key contains the username, the value is a tuple containing the old and new flags.

class aioslsk.events.SharedDirectoryChangeEvent(shared_directory: 'SharedDirectory')
Parameters:

shared_directory (SharedDirectory)

shared_directory: SharedDirectory

aioslsk.log_utils

aioslsk.log_utils.resolve(message_class)
Parameters:

message_class (str)

Return type:

type[MessageDataclass]

class aioslsk.log_utils.MessageFilter(message_types)

Logging filter for protocol messages

Parameters:

message_types (Collection[type[MessageDataclass] | str])

filter(record)

Determine if the specified record is to be logged.

Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place.

Parameters:

record (LogRecord)

Return type:

bool

class aioslsk.log_utils.DistributedSearchMessageFilter

Logging filter that filters out any distributed search request messages

TYPES = (<class 'aioslsk.protocol.messages.ServerSearchRequest.Response'>, <class 'aioslsk.protocol.messages.DistributedSearchRequest.Request'>, <class 'aioslsk.protocol.messages.DistributedServerSearchRequest.Request'>)
class aioslsk.log_utils.ConnectionLoggerAdapter(logger, extra=None)
process(msg, kwargs)

Process the logging message and keyword arguments passed in to a logging call to insert contextual information. You can either manipulate the message itself, the keyword args or both. Return the message and kwargs modified (or not) to suit your needs.

Normally, you’ll only need to override this one method in a LoggerAdapter subclass for your specific needs.

aioslsk.naming

class aioslsk.naming.NamingStrategy
NAME = None
should_be_applied(local_dir, local_filename)
Parameters:
  • local_dir (str)

  • local_filename (str)

Return type:

bool

apply(remote_path, local_dir, local_filename)

Apply the naming changes

Parameters:
  • remote_path (str) – the original remote path

  • local_dir (str) – the local directory the file should be written to

  • local_filename (str) – the local filename the file should be written to

Returns:

the local_dir and local_filename after applying the desired changes

Return type:

tuple[str, str]

class aioslsk.naming.DefaultNamingStrategy

The default naming strategy determines the filename using the remote_path parameter. The local_filename parameter is ignored

apply(remote_path, local_dir, local_filename)

Apply the naming changes

Parameters:
  • remote_path (str) – the original remote path

  • local_dir (str) – the local directory the file should be written to

  • local_filename (str) – the local filename the file should be written to

Returns:

the local_dir and local_filename after applying the desired changes

Return type:

tuple[str, str]

class aioslsk.naming.KeepDirectoryStrategy

Keeps the original directory the remote file was in

apply(remote_path, local_dir, local_filename)

Apply the naming changes

Parameters:
  • remote_path (str) – the original remote path

  • local_dir (str) – the local directory the file should be written to

  • local_filename (str) – the local filename the file should be written to

Returns:

the local_dir and local_filename after applying the desired changes

Return type:

tuple[str, str]

class aioslsk.naming.DuplicateNamingStrategy
should_be_applied(local_dir, local_filename)
Parameters:
  • local_dir (str)

  • local_filename (str)

Return type:

bool

class aioslsk.naming.NumberDuplicateStrategy

Duplicate name strategy that appends a number to the filename in case it already exists

PATTERN = ' \\((\\d+)\\)'
apply(remote_path, local_dir, local_filename)

Apply the naming changes

Parameters:
  • remote_path (str) – the original remote path

  • local_dir (str) – the local directory the file should be written to

  • local_filename (str) – the local filename the file should be written to

Returns:

the local_dir and local_filename after applying the desired changes

Return type:

tuple[str, str]

aioslsk.naming.chain_strategies(strategies, remote_path, local_dir)

Chains strategies together to find the target location and filename to which the file should be written.

Parameters:
  • strategies (list[NamingStrategy]) – list of strategies to apply

  • remote_path (str) – the full remote path

  • local_dir (str) – initial local path, this should be the initial download directory

Returns:

tuple with the path and filename

Return type:

tuple[str, str]

aioslsk.exceptions

exception aioslsk.exceptions.AioSlskException
exception aioslsk.exceptions.AuthenticationError(reason, message)
Parameters:
exception aioslsk.exceptions.InvalidSessionError

Raised when trying to execute a command but the user is not logged in

exception aioslsk.exceptions.NoSuchUserError
exception aioslsk.exceptions.UnknownMessageError(message_id, data, message)
Parameters:
exception aioslsk.exceptions.MessageSerializationError
exception aioslsk.exceptions.MessageDeserializationError(proto_message, message)
Parameters:
Return type:

None

exception aioslsk.exceptions.FileError
exception aioslsk.exceptions.FileNotFoundError
exception aioslsk.exceptions.FileNotSharedError
exception aioslsk.exceptions.SharedDirectoryError
exception aioslsk.exceptions.TransferException
exception aioslsk.exceptions.TransferNotFoundError
exception aioslsk.exceptions.InvalidStateTransition(transfer, current, desired, message='could not make the desired state transition')
Parameters:
  • transfer (Transfer)

  • current (TransferState.State)

  • desired (TransferState.State)

  • message (str)

exception aioslsk.exceptions.RequestPlaceFailedError
exception aioslsk.exceptions.NetworkError
exception aioslsk.exceptions.PeerConnectionError
exception aioslsk.exceptions.ConnectionFailedError
exception aioslsk.exceptions.ListeningConnectionFailedError
exception aioslsk.exceptions.ConnectionReadError
exception aioslsk.exceptions.ConnectionWriteError

aioslsk.settings

aioslsk.settings.translate_blocked_users(value)

Converts blocked user set to a dictionary object

Parameters:

value (Any)

Return type:

dict[str, BlockingFlag]

class aioslsk.settings.SharedDirectorySettingEntry(*, path, share_mode=DirectoryShareMode.EVERYONE, users=<factory>)
Parameters:
path: str
share_mode: DirectoryShareMode
users: list[str]
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.WishlistSettingEntry(*, query, enabled=True)
Parameters:
query: str
enabled: bool
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.UpnpSettings(*, enabled=True, lease_duration=21600, check_interval=600, search_timeout=10)
Parameters:
  • enabled (bool)

  • lease_duration (int)

  • check_interval (int)

  • search_timeout (int)

enabled: bool
lease_duration: int
check_interval: int
search_timeout: int
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.ReconnectSettings(*, auto=False, timeout=10)
Parameters:
auto: bool
timeout: int
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.ServerSettings(*, hostname='server.slsknet.org', port=2416, reconnect=ReconnectSettings(auto=False, timeout=10))
Parameters:
hostname: str
port: int
reconnect: ReconnectSettings
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.ListeningSettings(*, error_mode=ListeningConnectionErrorMode.CLEAR, port=60000, obfuscated_port=60001)
Parameters:
error_mode: ListeningConnectionErrorMode
port: int
obfuscated_port: int
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.PeerSettings(*, obfuscate=False, connect_mode=PeerConnectMode.RACE)
Parameters:
obfuscate: bool
connect_mode: PeerConnectMode
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.NetworkLimitSettings(*, upload_speed_kbps=0, download_speed_kbps=0)
Parameters:
  • upload_speed_kbps (int)

  • download_speed_kbps (int)

upload_speed_kbps: int
download_speed_kbps: int
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.NetworkSettings(*, server=<factory>, listening=<factory>, peer=<factory>, upnp=<factory>, limits=<factory>)
Parameters:
server: ServerSettings
listening: ListeningSettings
peer: PeerSettings
upnp: UpnpSettings
limits: NetworkLimitSettings
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.UserInfoSettings(*, description=None, picture=None)
Parameters:
  • description (str | None)

  • picture (bytes | None)

description: str | None
picture: bytes | None
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.CredentialsSettings(*, username, password, info=<factory>)
Parameters:
username: str
password: str
info: UserInfoSettings
are_configured()

Returns whether the credentials are correctly configured

Return type:

bool

model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.SearchSendSettings(*, store_results=True, request_timeout=0, wishlist_request_timeout=-1)
Parameters:
  • store_results (bool)

  • request_timeout (int)

  • wishlist_request_timeout (int)

store_results: bool
request_timeout: int
wishlist_request_timeout: int
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.SearchReceiveSettings(*, store_amount=500, max_results=100)
Parameters:
  • store_amount (int)

  • max_results (int)

store_amount: int
max_results: int
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.SearchSettings(*, send=<factory>, receive=<factory>, wishlist=<factory>)
Parameters:
send: SearchSendSettings
receive: SearchReceiveSettings
wishlist: list[WishlistSettingEntry]
classmethod handle_max_result_alias(values)
Parameters:

values (dict)

property max_results: int
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.TransferLimitSettings(*, upload_slots=2)
Parameters:

upload_slots (int)

upload_slots: int
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.TransfersSettings(*, limits=<factory>, report_interval=0.25)
Parameters:
limits: TransferLimitSettings
report_interval: float
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.SharesSettings(*, scan_on_start=True, download='/home/docs/checkouts/readthedocs.org/user_builds/aioslsk/checkouts/stable/docs/source', directories=<factory>)
Parameters:
scan_on_start: bool
download: str
directories: list[SharedDirectorySettingEntry]
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.RoomsSettings(*, auto_join=True, private_room_invites=True, favorites=<factory>)
Parameters:
auto_join: bool
private_room_invites: bool
favorites: set[str]
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.UsersSettings(*, friends=<factory>, blocked=<factory>)
Parameters:
  • friends (set[str])

  • blocked (Annotated[dict[str, BlockingFlag], BeforeValidator(func=~aioslsk.settings.translate_blocked_users, json_schema_input_type=PydanticUndefined)])

friends: set[str]
blocked: Annotated[dict[str, BlockingFlag], BeforeValidator(func=translate_blocked_users, json_schema_input_type=PydanticUndefined)]
is_blocked(username, flag)
Parameters:
Return type:

bool

model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.InterestsSettings(*, liked=<factory>, hated=<factory>)
Parameters:
liked: set[str]
hated: set[str]
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.DebugSettings(*, search_for_parent=True, ip_overrides=<factory>, log_connection_count=False)
Parameters:
search_for_parent: bool
ip_overrides: dict[str, str]
log_connection_count: bool
model_config = {'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aioslsk.settings.Settings(_case_sensitive=None, _nested_model_default_partial_update=None, _env_prefix=None, _env_file=PosixPath('.'), _env_file_encoding=None, _env_ignore_empty=None, _env_nested_delimiter=None, _env_nested_max_split=None, _env_parse_none_str=None, _env_parse_enums=None, _cli_prog_name=None, _cli_parse_args=None, _cli_settings_source=None, _cli_parse_none_str=None, _cli_hide_none_type=None, _cli_avoid_json=None, _cli_enforce_required=None, _cli_use_class_docs_for_groups=None, _cli_exit_on_error=None, _cli_prefix=None, _cli_flag_prefix_char=None, _cli_implicit_flags=None, _cli_ignore_unknown_args=None, _cli_kebab_case=None, _cli_shortcuts=None, _secrets_dir=None, *, network=<factory>, credentials=<factory>, searches=<factory>, shares=<factory>, users=<factory>, rooms=<factory>, interests=<factory>, transfers=<factory>, debug=<factory>)
Parameters:
network: NetworkSettings
credentials: CredentialsSettings
searches: SearchSettings
shares: SharesSettings
users: UsersSettings
rooms: RoomsSettings
interests: InterestsSettings
transfers: TransfersSettings
debug: DebugSettings
model_config = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_kebab_case': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_shortcuts': None, 'cli_use_class_docs_for_groups': False, 'enable_decoding': True, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_nested_max_split': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': '', 'extra': 'forbid', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_validate', 'model_dump', 'settings_customise_sources'), 'secrets_dir': None, 'toml_file': None, 'validate_assignment': True, 'validate_default': True, 'yaml_config_section': None, 'yaml_file': None, 'yaml_file_encoding': None}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

aioslsk.base_manager

class aioslsk.base_manager.BaseManager

Base class for manager instances. This class provides hooks that will get called during starting and stopping of the client

async load_data()

Load the data for the manager. This method gets called during client client start-up before any connection is made

async store_data()

Stores data from the manager. This gets called during the client shutdown

async start()

Optionally performs a start action on the manager. Gets called after loading the data but before connecting

async stop()

Cancel all running tasks. The implementation of this method should simply cancel the task and return, the code calling this method should be responsible for awaiting the cancellation

Returns:

list of all cancelled tasks

Return type:

list[Task]

aioslsk.constants

aioslsk.constants.PEER_CONNECT_TIMEOUT: float = 10

Direct connection timeout

aioslsk.constants.PEER_INDIRECT_CONNECT_TIMEOUT: float = 60

Indirect connection timeout

aioslsk.constants.PEER_INIT_TIMEOUT: float = 5

Timeout waiting for Peer Initialization message

aioslsk.constants.PEER_READ_TIMEOUT: float = 60

Timeout waiting for message on a peer or distributed connection

aioslsk.constants.TRANSFER_TIMEOUT: float = 180

Timeout waiting for new data on a file connection

aioslsk.constants.PATH_SEPERATOR_PATTERN = re.compile('[\\\\/]+')

Pattern for splitting/normalizing remote paths

aioslsk.constants.POTENTIAL_PARENTS_CACHE_SIZE: int = 20

Maximum amount of potential parents stored

aioslsk.distributed

aioslsk.distributed.task_counter()

Implement next(self).

class aioslsk.distributed.DistributedPeer(username, connection, branch_level=None, branch_root=None)

Represents a distributed peer and its values in the distributed network

Parameters:
username: str
connection: PeerConnection

Distributed connection (type=D) associated with the peer

branch_level: int | None
branch_root: str | None
class aioslsk.distributed.DistributedNetwork(settings, event_bus, network)

Class responsible for handling the distributed network

Parameters:
parent: DistributedPeer | None

Distributed parent. This variable is None if we are looking for a parent

children: list[DistributedPeer]
potential_parents: deque[str]
distributed_peers: list[DistributedPeer]
parent_min_speed: int | None
parent_speed_ratio: int | None
min_parents_in_cache: int | None
parent_inactivity_timeout: int | None
distributed_alive_interval: int | None
register_listeners()
get_distributed_peer(connection)

Get the distributed peer object related to the given connection.

This method will return None if the connection was not properly initialized (no username set on the connection) or if there is no peer object associated with the connection

Parameters:

connection (PeerConnection)

Return type:

DistributedPeer | None

async reset()

Disconnects all parent and child connections

async send_messages_to_children(*messages)
Parameters:

messages (MessageDataclass | bytes)

async stop()

Cancels all pending tasks

Returns:

a list of tasks that have been cancelled so that they can be awaited

Return type:

list[Task]

aioslsk.peer

class aioslsk.peer.PeerManager(settings, event_bus, user_manager, shares_manager, upload_info_provider, network)

Peer manager is responsible for handling peer messages

Parameters:
register_listeners()

aioslsk.server

class aioslsk.server.ServerManager(settings, event_bus, network)

Class handling server state changes

Parameters:
property connection_state: ConnectionState
register_listeners()
async send_ping()

Send ping to the server

aioslsk.session

class aioslsk.session.Session(user: aioslsk.user.model.User, ip_address: str, greeting: str, client_version: int, minor_version: int, logged_in_at: datetime.datetime = <factory>, privileges_time_left: int = 0)
Parameters:
  • user (User)

  • ip_address (str)

  • greeting (str)

  • client_version (int)

  • minor_version (int)

  • logged_in_at (datetime)

  • privileges_time_left (int)

user: User
ip_address: str
greeting: str
client_version: int
minor_version: int
logged_in_at: datetime
privileges_time_left: int
property privileged: bool

aioslsk.tasks

class aioslsk.tasks.BackgroundTask(interval, task_coro, preempt_wait=False, name='background-task', context=None)

Wrapper class for a background task

Variables:
  • interval – interval at which the task should run

  • task_coro – coroutine function that should be run at the provided interval

  • preempt_wait – whether to perform an initial wait before running the coroutine for the first time

  • name – optional task name

  • context – optional context to pass to the coroutine

Parameters:
resolve_interval()
Return type:

float

start()
cancel()
Return type:

Task | None

is_running()
Return type:

bool

async runner()
class aioslsk.tasks.Timer(timeout, callback)

Re-schedulable timer which runs a callback after completion

Parameters:
start()
cancel()
Return type:

Task | None

async runner()
reschedule(timeout=None)
Parameters:

timeout (float | None)

aioslsk.utils

aioslsk.utils.task_counter()

Implement next(self).

aioslsk.utils.try_decoding(value)
Parameters:

value (bytes)

aioslsk.utils.split_remote_path(path)

Splits a remote path into parts. Empty parts will be filtered out

Parameters:

path (str)

Return type:

list[str]

aioslsk.utils.get_duration(attributes)
Parameters:

attributes (list[Attribute])

Return type:

str

aioslsk.utils.get_attribute_string(attributes)

Returns an attributes list to a string (excludes duration)

Parameters:

attributes (list[Attribute])

Return type:

str

aioslsk.utils.ticket_generator(initial=1)

Generator for tickets to be used in various protocol messages. The generator will be reset to the initial value once the value would exceed 2 ^ 32

Parameters:

initial (int)

Return type:

Generator[int, None, None]

async aioslsk.utils.cancel_task(task)
Parameters:

task (Task | None)

aioslsk.transfer.manager

aioslsk.transfer.manager.task_counter()

Implement next(self).

class aioslsk.transfer.manager.TransferManager(settings, event_bus, user_manager, shares_manager, network, cache=None)

Class responsible for transfer related functionality. This class stores transfer objects and handles related events.

Parameters:
property transfers
register_listeners()
async read_cache()

Reads the transfers from the caches and corrects the state of those transfers

write_cache()

Write all currently stored transfers to the cache

async load_data()

Load the data for the manager. This method gets called during client client start-up before any connection is made

async store_data()

Stores data from the manager. This gets called during the client shutdown

async start()

Optionally performs a start action on the manager. Gets called after loading the data but before connecting

async stop()

Cancel all current transfer tasks

Returns:

a list of tasks that have been cancelled so that they can be awaited

Return type:

list[Task]

async start_progress_reporting_task()

Start the transfer progress reporting background task which will emit aioslsk.events.TransferProgressEvent events at an interval defined in the settings. This method is called automatically when starting the client

stop_progress_reporting_task()

Start the transfer progress reporting task

async download(username, filename, paused=False)

Requests to start a downloading the file from the given user

Parameters:
  • user – User from which to download the file

  • filename (str) – Name of the file to download. This should be the full path to the file as returned in the search results

  • paused (bool) – Adds the download in the paused state

  • username (str)

Returns:

a Transfer object from which the status of the transfer can be requested. If the transfer already exists in the client then this transfer will be returned

Return type:

Transfer

async abort(transfer)

Aborts the given transfer. This will cancel all pending transfers and remove the file (in case of download)

Parameters:

transfer (Transfer) – Transfer object to abort

Raises:
async queue(transfer)

Places given transfer (back) in the queue

This method can be called on downloads that are in the following states:

  • ABORTED: Re-starts the aborted download

  • PAUSED: Continues the paused download

  • COMPLETE: Re-downloads the file. By default this will download the file to a new location unless the initial file was removed

  • INCOMPLETE: The library should automatically attempt to retry a download in this state

  • FAILED: Re-attempt to download the file

Parameters:

transfer (Transfer) – Transfer object to queue

Raises:
async pause(transfer)
Parameters:

transfer (Transfer)

async add(transfer)

Adds a transfer if it does not already exist, otherwise it returns the already existing transfer. This method will emit a TransferAddedEvent only if the transfer did not exist.

This method only adds a transfer and does not automatically start it. To do so call queue() on the manager

Parameters:

transfer (Transfer) – Transfer to be added

Returns:

either the transfer we have passed or the already existing transfer

Return type:

Transfer

async remove(transfer)

Remove a transfer from the list of transfers. This will attempt to abort the transfer before removing it. Emits a TransferRemovedEvent after removal

Parameters:

transfer (Transfer) – Transfer object to remove

Raises:

TransferNotFoundError – Raised when the transfer was not added to the manager

get_uploads()
Return type:

list[Transfer]

get_downloads()
Return type:

list[Transfer]

get_upload_slots()

Returns the total amount of upload slots

Return type:

int

has_slots_free()
Return type:

bool

get_free_upload_slots()
Return type:

int

get_queue_size()

Returns the amount of queued uploads

Return type:

int

get_downloading()

Returns all transfers that are currently downloading or an attempt is is made to start downloading

Return type:

list[Transfer]

get_uploading()

Returns all transfers that are currently uploading or an attempt is is made to start uploading

Return type:

list[Transfer]

get_finished_transfers()

Returns a complete list of transfers that are in a finalized state (COMPLETE, ABORTED, FAILED)

Return type:

list[Transfer]

get_unfinished_transfers()

Returns a complete list of transfers that are not in a finalized state (COMPLETE, ABORTED, FAILED)

Return type:

list[Transfer]

get_download_speed()

Return current download speed (in bytes/second)

Return type:

float

get_upload_speed()

Return current upload speed (in bytes/second)

Return type:

float

get_average_upload_speed()

Returns average upload speed (in bytes/second)

Return type:

float

get_place_in_queue(transfer)

Gets the place of the given upload in the transfer queue

Returns:

The place in the queue, 0 if not in the queue a value equal or greater than 1 indicating the position otherwise

Parameters:

transfer (Transfer)

Return type:

int

get_transfer(username, remote_path, direction)

Lookup transfer by username, remote_path and transfer direction. This method will raise an exception in case the transfer is not found

Parameters:
  • username (str) – Username of the transfer

  • remote_path (str) – Full remote path of the transfer

  • direction (TransferDirection) – Direction of the transfer (upload / download)

Returns:

The matching transfer object

Raises:

ValueError – If the transfer is not found

Return type:

Transfer

find_transfer(username, remote_path, direction)

Lookup transfer by username, remote_path and transfer direction. This method will return None if the transfer is not found

Parameters:
  • username (str) – Username of the transfer

  • remote_path (str) – Full remote path of the transfer

  • direction (TransferDirection) – Direction of the transfer (upload / download)

Returns:

The matching transfer object or None

Return type:

Transfer | None

async manage_user_tracking()

Remove or add user tracking based on the list of transfers. This method will untrack users for which there are no more unfinished transfers and start/keep tracking users for which there are unfinished transfers

request_management_cycle(flag)
Parameters:

flag (_RequestFlag)

manage_transfers()

This method analyzes the state of the current downloads/uploads and starts them up in case there are free slots available

async manage_shares_changed()
async request_place_in_queue(transfer)

Requests the place in queue for the given transfer. The method will return the value in case of success and return the value

Returns:

place in queue or None in case of error

Raises:

RequestPlaceFailedError – when the request failed to send to the peer or waiting for a response timed out

Parameters:

transfer (Transfer)

Return type:

int | None

async on_transfer_state_changed(transfer, old, new)
Parameters:
  • transfer (Transfer)

  • old (State)

  • new (State)

aioslsk.transfer.model

class aioslsk.transfer.model.FailReason

Definition of reasons for which an transfer queue request or transfer request was rejected

CANCELLED = 'Cancelled'
COMPLETE = 'Complete'
QUEUED = 'Queued'
FILE_NOT_SHARED = 'File not shared.'
FILE_READ_ERROR = 'File read error.'
class aioslsk.transfer.model.AbortReason
REQUESTED = 'Requested'
BLOCKED = 'Blocked'
FILE_NOT_SHARED = 'File not shared'
class aioslsk.transfer.model.TransferDirection(*values)
UPLOAD = 0
DOWNLOAD = 1
class aioslsk.transfer.model.TransferProgressSnapshot(state, bytes_transfered, speed, start_time=None, complete_time=None, fail_reason=None, abort_reason=None)

Represents the current progress of a transfer, used for reporting progress back to the user through a TransferProgressEvent

Parameters:
  • state (State)

  • bytes_transfered (int)

  • speed (float)

  • start_time (float | None)

  • complete_time (float | None)

  • fail_reason (str | None)

  • abort_reason (str | None)

state: State
bytes_transfered: int

Amount of bytes transfered in bytes

speed: float

Current transfer speed if the transfer is still downloading, average speed if the transfer has completed

start_time: float | None = None
complete_time: float | None = None
fail_reason: str | None = None

Optional transfer fail reason

abort_reason: str | None = None

Optional transfer abort reason

class aioslsk.transfer.model.Transfer(username, remote_path, direction)

Class representing a transfer

Parameters:
state: TransferState
direction: TransferDirection

Determines whether this transfer is an upload or a download

username: str

Username of the peer

remote_path: str

Remote path, this is the path that is shared between peers

local_path: str | None

Absolute path to the file on disk

remotely_queued: bool

Indicates whether the transfer queue message was received by the peer. This only used for downloads

place_in_queue: int | None
fail_reason: str | None

Reason for failure in case the transfer has failed

abort_reason: str | None

Reason for why transfer was aborted

filesize: int | None

Filesize in bytes

bytes_transfered: int

Amount of bytes transfered

queue_attempts: int
last_queue_attempt: float
upload_request_attempts: int
last_upload_request_attempt: float
start_time: float | None

Time at which the transfer was started. This is the time the transfer entered the DOWNLOADING or UPLOADING state

complete_time: float | None

Time at which the transfer was completed. This is the time the transfer entered the COMPLETE, INCOMPLETE, ABORTED or FAILED state

progress_snapshot: TransferProgressSnapshot

Snapshot of the transfer progress. Used internally to report progress at set intervals

state_listeners: list[TransferStateListener]
reset_local_vars()

Resets the local file variables

reset_progress_vars()
reset_queue_vars()

Reset all variables when the

reset_time_vars()

Clear all time related variables

set_start_time()

Set the start time, clear the complete time

set_complete_time()

Set the complete time only if the start time has not been set

increase_queue_attempts()
reset_queue_attempts()
increase_upload_request_attempt()
reset_upload_request_attempts()
async transition(state)

Transitions the state of the transfer and notifies the state_listeners. This is an internal method and should not be used directly.

Parameters:

state (TransferState)

get_speed()

Retrieve the speed of the transfer

Returns:

0 if the transfer has not yet begun. The current speed if the transfer is ongoing. The transfer speed if the transfer was complete. Bytes per second

Return type:

float

add_speed_log_entry(bytes_transfered)

Logs a transfer speed entry. This is an internal method

Parameters:

bytes_transfered (int)

is_upload()
Return type:

bool

is_download()
Return type:

bool

is_finalized()

Return true if the transfer is in a finalized state

Return type:

bool

is_processing()

Return true if an attempt is being made to start transferring the file or the transfer is currently in progress.

Return type:

bool

is_transferring()

Return true if the transfer is in progress

Return type:

bool

is_transfered()
Return type:

bool

get_tasks()
Return type:

list[Task]

cancel_tasks()

Cancels all tasks for the transfer, this method returns the tasks which have been cancelled

Return type:

list[Task]

take_progress_snapshot()

Saves and returns a snapshot of the transfer progress

Return type:

TransferProgressSnapshot

aioslsk.transfer.cache

class aioslsk.transfer.cache.TransferCache(*args, **kwargs)

Abstract base class for storing shares

read()
Return type:

list[Transfer]

write(transfers)
Parameters:

transfers (list[Transfer])

class aioslsk.transfer.cache.TransferNullCache

Transfer cache object that does not perform any caching

read()
Return type:

list[Transfer]

write(transfers)
Parameters:

transfers (list[Transfer])

class aioslsk.transfer.cache.TransferShelveCache(data_directory)

Transfer cache that uses the Python built-in shelve module to store transfer objects

Parameters:

data_directory (str)

DEFAULT_FILENAME = 'transfers'
read()
Return type:

list[Transfer]

write(transfers)
Parameters:

transfers (list[Transfer])

aioslsk.shares.cache

class aioslsk.shares.cache.SharesCache(*args, **kwargs)

Abstract base class for storing shares

read()
Return type:

list[SharedDirectory]

write(shared_directories)
Parameters:

shared_directories (list[SharedDirectory])

class aioslsk.shares.cache.SharesNullCache
read()
Return type:

list[SharedDirectory]

write(shared_directories)
Parameters:

shared_directories (list[SharedDirectory])

class aioslsk.shares.cache.SharesShelveCache(data_directory, filename='shares_index')

Shares cache that uses the Python built-in shelve module

Parameters:
  • data_directory (str)

  • filename (str)

DEFAULT_FILENAME = 'shares_index'
read()
Return type:

list[SharedDirectory]

write(shared_directories)
Parameters:

shared_directories (list[SharedDirectory])

aioslsk.shares.model

class aioslsk.shares.model.DirectoryShareMode(*values)

Share mode for directories. The mode determines for who the results are locked and who can download the file

EVERYONE = 'everyone'
FRIENDS = 'friends'
USERS = 'users'
class aioslsk.shares.model.SharedDirectory(directory, absolute_path, alias, share_mode=DirectoryShareMode.EVERYONE, users=<factory>)

Class representing a directory that is explicitly shared by the user. This class holds information on how the directory is shared and is a container for shared items within this directory.

Parameters:
directory: str
absolute_path: str
alias: str
share_mode: DirectoryShareMode = 'everyone'
users: list[str]
items: set[SharedItem]
is_parent_of(directory)

Returns true if the current directory is any parent of the passed shared directory

Parameters:

directory (str | SharedDirectory) – directory to test, if this directory is of str type it should be an absolute path. If it is of SharedDirectory type the absolute_path will be taken

Return type:

bool

is_child_of(directory)

Returns true if the passed directory is a (sub)child of the current directory

Parameters:

directory (str | SharedDirectory) – directory to test, if this directory is of str type it should be an absolute path. If it is of SharedDirectory type the absolute_path will be taken

Return type:

bool

get_remote_path()
Return type:

str

get_item_by_remote_path(remote_path)

Returns the SharedItem instance belonging to the passed remote_path

Raises:

FileNotFoundError – when the item cannot be found in the set of items

Parameters:

remote_path (str)

Return type:

SharedItem

get_items_for_directory(directory)

Gets items in the current directory that are part of given directory

Parameters:

directory (SharedDirectory)

Return type:

set[SharedItem]

class aioslsk.shares.model.SharedItem(shared_directory: aioslsk.shares.model.SharedDirectory, subdir: str, filename: str, modified: float)
Parameters:
shared_directory: SharedDirectory
subdir: str
filename: str
modified: float
attributes: list[tuple[int, int]] | None = None
get_absolute_path()

Returns the absolute path of the shared item

Return type:

str

get_remote_path()

Returns the full remote path of this file.

Returns:

Full remote file path: Example: “@@abcdeMusicsong.mp3”

Return type:

str

get_remote_directory_path()

Returns the remote directory path this file resides in

Returns:

Remote directory path. Example: “@@abcdeMusic”

Return type:

str

get_remote_directory_path_parts()

Returns the remote directory path split into parts

Return type:

tuple[str, …]

get_query_path()

Returns the query-able part of the shared item

Returns:

Queryable path of the item. Example: “MusicMetalSong.mp3”

Return type:

str

aioslsk.shares.manager

aioslsk.shares.manager.scan_directory(shared_directory, children=None)

Scans the directory for items to share

Warning: when using ProcessPoolExecutor on this method the returned items will not have the shared directory set in some cases. The shared_directory passed here is a copy and the object will be removed once this function finishes (see https://stackoverflow.com/a/72726998/1419478). In this case you should manually assign it again

Parameters:
Returns:

set of SharedItem objects found during the scan

Return type:

set[SharedItem]

aioslsk.shares.manager.extract_attributes(filepath)

Attempts to extract attributes from the file at filepath. If there was an error attempting to extract the attributes this method will log a warning and return an empty list of attributes

Parameters:

filepath (str)

Return type:

list[tuple[int, int]]

class aioslsk.shares.manager.SharesManager(settings, event_bus, network, cache=None, executor_factory=None)
Parameters:
register_listeners()
property shared_directories
generate_alias(path, offset=0)

Generates a directory alias for the given path, this method will be called recursively increasing the offset in case the alias is already found in the shared_directories.

The hardware address is mixed in to avoid getting the same alias for the same directory on different machines. Admittedly this is a lousy security measure but hopefully this will prevent easy leaking of files in case such issue would occur. Example: ‘abcde’ is always generated for ‘C:' so the attacker could guess where a file is located.

Parameters:
  • path (str) – the path for which to generate an alias

  • offset (int) – offset for the value of the initial 5 bytes (default=0)

Returns:

a string of 5 alphabetic characters all lowercased

Return type:

str

async start()

Optionally performs a start action on the manager. Gets called after loading the data but before connecting

async stop()

Cancel all running tasks. The implementation of this method should simply cancel the task and return, the code calling this method should be responsible for awaiting the cancellation

Returns:

list of all cancelled tasks

Return type:

list[Task]

async load_data()

Load the data for the manager. This method gets called during client client start-up before any connection is made

async store_data()

Stores data from the manager. This gets called during the client shutdown

load_from_settings()

Loads the shared directories from the settings. Existing directories will be updated, non-existing directories added, directories that no longer exist will be removed

read_cache()

Read the directories from the cache

write_cache()

Write current shared directories to the cache

get_download_directory()

Gets the absolute path the to download directory configured from the settings

Returns:

Absolute path of the value of the shares.download setting

Return type:

str

async create_directory(absolute_path)

Ensures the passed directory exists

Parameters:

absolute_path (str)

rebuild_term_map()
get_shared_item_cache(remote_path, username=None)

Gets a shared item from the cache if it exists

If a username is passed this will also check if the file is locked and raise a FileNotSharedError if the file is not accessible for that user

Parameters:
  • remote_path (str) – the remote_path

  • username (str | None) – optional username to check if the file is shared or not

Raises:
Return type:

SharedItem

async get_shared_item(remote_path, username=None)

Same as get_shared_item_cache() but also checks if the file exists on disk

Parameters:
  • remote_path (str) – the remote_path

  • username (str | None) – optional username to check if the file is shared or not

Raises:
Return type:

SharedItem

find_shared_item_cache(remote_path, username=None)

Equivelant to get_shared_item_cache() but returns None if the shared item is not found

Parameters:
  • remote_path (str)

  • username (str | None)

Return type:

SharedItem | None

async find_shared_item(remote_path, username=None)

Equivelant to get_shared_item() but returns None if the shared item is not found

Parameters:
  • remote_path (str)

  • username (str | None)

Return type:

SharedItem | None

add_shared_directory(shared_directory, share_mode=DirectoryShareMode.EVERYONE, users=None)

Adds a shared directory. This method will call generate_alias() and add the directory to the directory map.

This method will not scan the directory, however if the directory is a (sub)child of an already registered shared directory the items from that directory will be removed from the parent directory to the new directory

For scanning see the scan(), scan_directory_files() and scan_directory_file_attributes() methods.

Parameters:
  • shared_directory (str) – path of the shared directory

  • share_mode (DirectoryShareMode) – the share mode for the directory

  • users (list[str] | None) – in case the share mode is USERS, a list of users to share it with

Returns:

a SharedDirectory object

Raises:

SharedDirectoryError – if the directory is already shared

Return type:

SharedDirectory

update_shared_directory(directory, share_mode=None, users=None)

Updates share_mode and users values for the given directory

Parameters:
Returns:

the updated directory

Raises:

SharedDirectoryError – if the given directory is a string and not in the list of shared directories

Return type:

SharedDirectory

remove_shared_directory(directory)

Removes the given shared directory. If the directory was a subdirectory of another shared directory its items will be moved into that directory

Example file structure:

  • Music

    • Artist_One

      • song_one.mp3

    • Artist_Two

      • song_two.mp3

If the user shares 2 directories:

  • Music: EVERYONE

  • MusicArtist_One: FRIENDS

And removes the MusicArtist_Oneshared directory the files of that directory get returned back to the parent directory. In this case file ``song_two.mp3` will be shared with EVERYONE again

Parameters:
Returns:

the removed directory

Raises:

SharedDirectoryError – raised when the passed directory was not added to the manager

Return type:

SharedDirectory

get_shared_directory(directory)

Calculates the absolute path of given directory and looks for the matching SharedDirectory instance

Raises:

SharedDirectoryError – if there is no corresponding SharedDirectory instance registered in this class

Parameters:

directory (str)

Return type:

SharedDirectory

is_directory_shared(directory)

Checks if a directory is already a shared directory by checking the absolute path of that directory

Parameters:

directory (str)

Return type:

bool

async scan_directory_files(shared_directory)

Scans the files for the given shared_directory

Parameters:

shared_directory (SharedDirectory) – SharedDirectory instance to scan

Raises:

SharedDirectoryError – raised when the passed shared_directory was not added to the manager

async scan_directory_file_attributes(shared_directory)

Scans the file attributes for files in the given shared_directory only files that do not have attributes will be scanned

The results of the scan are handled internally and are automatically to the SharedItem object for which the scan was performed

Parameters:

shared_directory (SharedDirectory) – SharedDirectory instance for which the files need to be scanned

async scan()

Scan the files and their attributes for all directories currently defined in the shared_directories

This method will emit a ScanCompleteEvent on the event bus and report the shares to the server

async get_filesize(shared_item)
Parameters:

shared_item (SharedItem)

Return type:

int

query(query, username=None, excluded_search_phrases=None)

Performs a query on the shared_directories returning the matching items. If username is passed this method will return a list of visible results and list of locked results. If None the second list will always be empty.

This method makes a first pass using the built in term map and filters the remaining results using regular expressions.

Parameters:
  • query (str | SearchQuery) – the query to perform on the shared directories

  • username (str | None) – optionally the username of the user making the query. This is used to determine locked results, if not given the locked results list will be empty

  • excluded_search_phrases (list[str] | None) – optional list of search phrases that should be excluded from the search results

Returns:

two lists of visible results and locked results

Return type:

tuple[list[SharedItem], list[SharedItem]]

get_stats()

Gets the total amount of shared directories and files.

Returns:

directory and file count as a tuple

Return type:

tuple[int, int]

calculate_download_path(remote_path)

Calculates the local download path for a remote path returned by another peer.

Returns:

tuple of the directory and file name

Parameters:

remote_path (str)

Return type:

tuple[str, str]

get_shared_directories_for_user(username)
Parameters:

username (str)

Return type:

tuple[list[SharedDirectory], list[SharedDirectory]]

create_shares_reply(username)

Creates a complete list of the currently shared items as a reply to a PeerSharesRequest messages

Parameters:

username (str) – username of the user requesting the shares reply, this is used to determine the locked results

Returns:

tuple with two lists: public directories and locked directories

Return type:

tuple[list[DirectoryData], list[DirectoryData]]

create_directory_reply(remote_directory)

Lists directory data as a response to a directory request. This will not contain any information about subdirectories, only the files within that directory

This method differs from the official clients who don’t respond at all to the message if the directory does not exist. Instead if the directory does not exist and empty list is returned

Parameters:

remote_directory (str) – remote path of the directory

Returns:

list of directories. Empty if the directory is not shared, a list with one entry if the directory is found

Return type:

list[DirectoryData]

is_directory_locked(directory, username)

Checks if the shared directory is locked for the given username

Parameters:
Return type:

bool

is_item_locked(item, username)

Checks if the shared item is locked for the given username

Parameters:
Return type:

bool

async report_shares()

Reports the shares amount to the server

aioslsk.user.model

class aioslsk.user.model.UserStatus(*values)

User status values, everything except the UNKNOWN status are used by the server

UNKNOWN = -1
OFFLINE = 0
AWAY = 1
ONLINE = 2
class aioslsk.user.model.UploadPermissions(*values)

Upload permissions returned / sent by PeerUserInfoReply message

UNKNOWN = -1
NOONE = 0

Don’t allow uploads from anyone

EVERYONE = 1

Allow uploads from anyone

USER_LIST = 2

Only allow uploads from users in the users list

PERMITTED_LIST = 3

Only allow uploads from users in a specific list

class aioslsk.user.model.TrackingFlag(*values)

Tracking flags hold information how the user is being tracked

REQUESTED = 1

Tracking was explicitly requested by the user

TRANSFER = 2

Tracking was requested through transfer manager

FRIEND = 4

Tracking because the user is a friend

class aioslsk.user.model.TrackingState(*values)
UNTRACKED = 'untracked'
TRACKED = 'tracked'
RETRY_PENDING = 'retry_pending'
class aioslsk.user.model.BlockingFlag(*values)
NONE = 0
PRIVATE_MESSAGES = 1

Blocks private messages sent by the user

ROOM_MESSAGES = 2

Blocks room messages sent by the user

SEARCHES = 4

Blocks incoming searches from the user

SHARES = 8

Blocks shares, directory listing requests

INFO = 16
UPLOADS = 32

Blocks all uploads and upload requests

IGNORE = 3

Ignore all messaging

ALL = 63

Fully blocks the user: includes messaging, shares requests, uploads

class aioslsk.user.model.User(name: 'str', status: 'UserStatus' = <UserStatus.UNKNOWN: -1>, privileged: 'bool' = False, description: 'Optional[str]' = None, picture: 'Optional[bytes]' = None, country: 'Optional[str]' = None, avg_speed: 'Optional[int]' = None, uploads: 'Optional[int]' = None, shared_file_count: 'Optional[int]' = None, shared_folder_count: 'Optional[int]' = None, has_slots_free: 'Optional[bool]' = None, slots_free: 'Optional[int]' = None, upload_slots: 'Optional[int]' = None, queue_length: 'Optional[int]' = None, upload_permissions: 'UploadPermissions' = <UploadPermissions.UNKNOWN: -1>, interests: 'set[str]' = <factory>, hated_interests: 'set[str]' = <factory>)
Parameters:
  • name (str)

  • status (UserStatus)

  • privileged (bool)

  • description (str | None)

  • picture (bytes | None)

  • country (str | None)

  • avg_speed (int | None)

  • uploads (int | None)

  • shared_file_count (int | None)

  • shared_folder_count (int | None)

  • has_slots_free (bool | None)

  • slots_free (int | None)

  • upload_slots (int | None)

  • queue_length (int | None)

  • upload_permissions (UploadPermissions)

  • interests (set[str])

  • hated_interests (set[str])

name: str
status: UserStatus
privileged: bool
description: str | None
picture: bytes | None
country: str | None
avg_speed: int | None
uploads: int | None
shared_file_count: int | None
shared_folder_count: int | None
has_slots_free: bool | None
slots_free: int | None
upload_slots: int | None
queue_length: int | None
upload_permissions: UploadPermissions
interests: set[str]
hated_interests: set[str]
update_from_user_stats(user_stats)
Parameters:

user_stats (UserStats)

clear_all()

Clears all user data except user status and privileges info and country

clear(info=False, interests=False, stats=False, upload_info=False)

Resets selected fields

Parameters:
class aioslsk.user.model.ChatMessage(id, timestamp, user, message, is_direct)

Represents a private chat message

Parameters:
id: int
timestamp: int
user: User
message: str
is_direct: bool
is_server_message()
Return type:

bool

property is_admin: bool

Only kept to keep backward compatibility. Use is_direct

This property does not actually represent whether the message was sent by an admin. Instead it represents whether the message was sent directly or was queued on the server before being sent (example, when user was offline and came back online)

aioslsk.user.manager

class aioslsk.user.manager.TrackingRequest(operation: Callable[[aioslsk.user.model.TrackingFlag], NoneType], flag: aioslsk.user.model.TrackingFlag, handled: asyncio.locks.Event = <factory>)
Parameters:
operation: Callable[[TrackingFlag], None]
flag: TrackingFlag
handled: Event
class aioslsk.user.manager.TrackedUser(user: aioslsk.user.model.User, flags: aioslsk.user.model.TrackingFlag = <TrackingFlag: 0>, state: aioslsk.user.model.TrackingState = <TrackingState.UNTRACKED: 'untracked'>, queue: asyncio.queues.Queue[aioslsk.user.manager.TrackingRequest] = <factory>, task: _asyncio.Task | None = None, retry_task: _asyncio.Task | None = None)
Parameters:
user: User
flags: TrackingFlag
state: TrackingState
queue: Queue[TrackingRequest]
task: Task | None
retry_task: Task | None
add_flag(flag)
Parameters:

flag (TrackingFlag)

remove_flag(flag)
Parameters:

flag (TrackingFlag)

class aioslsk.user.manager.UserManagementContext(friends: set[str], blocked: dict[str, aioslsk.user.model.BlockingFlag])
Parameters:
friends: set[str]
blocked: dict[str, BlockingFlag]
class aioslsk.user.manager.UserManager(settings, event_bus, network)

Class responsible for handling user messages and storing users

Parameters:
register_listeners()
property users: dict[str, User]
property privileged_users: set[str]
async start()

Optionally performs a start action on the manager. Gets called after loading the data but before connecting

async stop()

Cancel all running tasks. The implementation of this method should simply cancel the task and return, the code calling this method should be responsible for awaiting the cancellation

Returns:

list of all cancelled tasks

Return type:

list[Task]

get_self()

Returns the user object for the current session

Return type:

User

get_user_object(username)

Gets a User object for given username, if the user is not stored it will be created and stored.

A user will be stored only if there is a strong reference to the User object, otherwise it will be removed

Parameters:

username (str) – Name of the user

Returns:

a User object

Return type:

User

is_tracked(username)

Returns whether a user is currently being tracked

Parameters:

username (str)

Return type:

bool

reset_users()

Performs a reset on all users. This method is called when the connection with the server is disconnected and shouldn’t be called directly

async track_user(username, flag=<TrackingFlag.REQUESTED: 1>)

Requests to start tracking a user. Tracking of a user will be handled in the background

Parameters:
  • username (str) – user to track

  • flag (TrackingFlag) – tracking flag to add from the user

async untrack_user(username, flag=<TrackingFlag.REQUESTED: 1>)

Requests to stop tracking a user. Tracking of a user will be handled in the background.

Untracking does not necesserily mean that the library stops receiving user updates, the library could internally still be wanting to track a user for example for managing transfers

Parameters:
  • username (str) – user to track

  • flag (TrackingFlag) – tracking flag to add from the user

async track_friend(username)

Request to track a friend with given username

Parameters:

username (str)

async track_friends()

Starts tracking the users defined in the friends list

async untrack_friend(username)

Request to stop tracking a friend with given username

Parameters:

username (str)

get_tracking_flags(username)

Returns current desired tracking flags of the user

Parameters:

username (str) – username of the user

Return type:

TrackingFlag

get_tracking_state(username)

Returns current tracking state of the user

Parameters:

username (str) – username of the user

Return type:

TrackingState

class aioslsk.user.manager.UserTrackingManager(settings, event_bus, network)

Keeps the user tracking state in sync with the server

Parameters:
register_listeners()
get_tracking_flags(username)

Returns current desired tracking flags of the user with given username

Parameters:

username (str) – username of the user

Return type:

TrackingFlag

get_tracking_state(username)

Returns the current tracking state of the given user

Parameters:

username (str)

Return type:

TrackingState

track_user(user, flag=<TrackingFlag.REQUESTED: 1>)
Parameters:
Return type:

TrackingRequest

untrack_user(user, flag=<TrackingFlag.REQUESTED: 1>)
Parameters:
Return type:

TrackingRequest | None

stop()
Return type:

list[Task]

aioslsk.room.model

class aioslsk.room.model.Room(name: 'str', private: 'bool' = False, users: 'list[User]' = <factory>, joined: 'bool' = False, user_count: 'int' = 0, tickers: 'dict[str, str]'=<factory>, members: 'set[str]' = <factory>, owner: 'Optional[str]' = None, operators: 'set[str]' = <factory>)
Parameters:
name: str
private: bool
users: list[User]

Current list of joined users

joined: bool
user_count: int
tickers: dict[str, str]

Room tickers (room wall)

members: set[str]

For private rooms, names of members of the room (excludes owner)

owner: str | None

For private rooms, name of the room owner

operators: set[str]

For private rooms, names of operators

add_user(user)
Parameters:

user (User)

remove_user(user)
Parameters:

user (User)

class aioslsk.room.model.RoomMessage(timestamp: 'int', user: 'User', message: 'str', room: 'Room')
Parameters:
timestamp: int
user: User
message: str
room: Room

aioslsk.room.manager

class aioslsk.room.manager.RoomManager(settings, event_bus, user_manager, network)

Class handling rooms

Parameters:
property rooms: dict[str, Room]
get_joined_rooms()

Returns a list of all rooms currently joined

Return type:

list[Room]

get_private_rooms()

Returns a list of all private rooms of which we are a member or owner. This includes rooms that are not joined

Return type:

list[Room]

get_public_rooms()

Returns the list of public rooms

Return type:

list[Room]

get_owned_rooms()

Returns a list of which we are the owner

Return type:

list[Room]

get_operated_rooms()

Returns a list of rooms in which we have operator privileges

Return type:

list[Room]

get_or_create_room(room_name, private=False)
Parameters:
Return type:

Room

reset_rooms()

Performs a reset on all users and rooms

register_listeners()
async auto_join_rooms()

Automatically joins rooms stored in the settings

aioslsk.search.model

class aioslsk.search.model.SearchType(*values)
NETWORK = 1
USER = 2
ROOM = 3
WISHLIST = 4
class aioslsk.search.model.ReceivedSearch(username, query, result_count)

Used for keeping track of searches received from the distributed parent or server

Parameters:
  • username (str)

  • query (str)

  • result_count (int)

username: str
query: str
result_count: int
class aioslsk.search.model.SearchQuery(query: str, include_terms: set[str] = <factory>, exclude_terms: set[str] = <factory>, wildcard_terms: set[str] = <factory>)
Parameters:
query: str
include_terms: set[str]
exclude_terms: set[str]
wildcard_terms: set[str]
classmethod parse(query)

Parses the given query string into terms and creates a new SearchQuery object

Parameters:

query (str)

Return type:

SearchQuery

matchers_iter()

Generator for term matchers

Return type:

Generator[Callable[[str], bool], None, None]

has_inclusion_terms()

Return whether this query has any valid inclusion terms

Return type:

bool

class aioslsk.search.model.SearchResult(ticket, username, has_free_slots=False, avg_speed=0, queue_size=0, shared_items=<factory>, locked_results=<factory>)

Search result received from a user

Parameters:
ticket: int
username: str
has_free_slots: bool
avg_speed: int
queue_size: int
shared_items: list[FileData]
locked_results: list[FileData]
class aioslsk.search.model.SearchRequest(ticket, query, search_type=SearchType.NETWORK, room=None, username=None, results=<factory>, started=<factory>, timer=None)

Search request we have made

Parameters:
ticket: int
query: str
search_type: SearchType
room: str | None
username: str | None
results: list[SearchResult]
started: datetime
timer: Timer | None

aioslsk.search.manager

aioslsk.search.manager.task_counter()

Implement next(self).

class aioslsk.search.manager.SearchManager(settings, event_bus, shares_manager, upload_info_provider, network)

Handler for searches requests

Parameters:
register_listeners()
remove_request(request)

Removes the search request from the client. Incoming results after the request has been removed will be ignored

Parameters:

request (SearchRequest | int) – SearchRequest object or ticket number to remove

async search(query)

Performs a global search. The results generated by this query will stored in the returned object or can be listened to through the SearchResultEvent event

Parameters:

query (str) – The search query

Returns:

An object containing the search request details and results

Return type:

SearchRequest

async search_room(room, query)

Performs a search request on the specific room. The results generated by this query will stored in the returned object or can be listened to through the SearchResultEvent event

Parameters:
  • room (str | Room) – Room object or name to query

  • query (str) – The search query

Returns:

An object containing the search request details and results

Return type:

SearchRequest

async search_user(username, query)

Performs a search request on the specific user. The results generated by this query will stored in the returned object or can be listened to through the SearchResultEvent event

Parameters:
  • user – User object or name to query

  • query (str) – The search query

  • username (str)

Returns:

An object containing the search request details and results

Return type:

SearchRequest

async stop()

Cancels all pending tasks

Returns:

a list of tasks that have been cancelled so that they can be awaited

Return type:

list[Task]

aioslsk.interest.manager

class aioslsk.interest.manager.InterestManager(settings, event_bus, user_manager, network)

Class handling interests and recommendations

Parameters:
register_listeners()
async advertise_interests()

Advertises all interests and hated interests defined in the settings to the server

aioslsk.network.connection

aioslsk.network.connection.task_counter()

Implement next(self).

class aioslsk.network.connection.PeerConnectionType
FILE = 'F'
PEER = 'P'
DISTRIBUTED = 'D'
class aioslsk.network.connection.ConnectionState(*values)
UNINITIALIZED = 1
CONNECTING = 2
CONNECTED = 3
CLOSING = 4
CLOSED = 5
class aioslsk.network.connection.CloseReason(*values)
UNKNOWN = 1
CONNECT_FAILED = 2
REQUESTED = 3
READ_ERROR = 4
WRITE_ERROR = 5
TIMEOUT = 6
EOF = 7
class aioslsk.network.connection.PeerConnectionState(*values)
AWAITING_INIT = 1

No init message has been received yet (PeerInit, PeerPierceFirewall)

ESTABLISHED = 2

Message connections: ready to receive / send data

NEGOTIATING_TRANSFER = 3

Transfer connections: negotiating the transfer ticket / offset

TRANSFERRING = 4

Transfer connections: ready to receive / send data

class aioslsk.network.connection.Connection(hostname, port, network)
Parameters:
hostname: str
port: int
network: Network
state: ConnectionState
abstractmethod async disconnect(reason=CloseReason.UNKNOWN)
Parameters:

reason (CloseReason)

async set_state(state, close_reason=CloseReason.UNKNOWN)
Parameters:
class aioslsk.network.connection.ListeningConnection(hostname, port, network, obfuscated=False)

A listening connection, objects of this class are responsible for accepting incoming connections from peers

Parameters:
obfuscated: bool
async disconnect(reason=CloseReason.UNKNOWN)
Parameters:

reason (CloseReason)

async connect()

Open a listening connection on the current hostname and port

Raises:

ConnectionFailedError – raised when binding failed

async accept(reader, writer)
Parameters:
  • reader (StreamReader)

  • writer (StreamWriter)

class aioslsk.network.connection.DataConnection(hostname, port, network, obfuscated=False, read_timeout=60)

Connection for message and data transfer

Parameters:
read_timeout: float
get_connecting_ip()

Gets the IP address being used to connect to the server/peer.

The connection needs to be established for this method to work

Return type:

str

async connect(timeout=30)

Opens a TCP connection the hostname:ip provided in this object. The state of the connection will be changed to CONNECTING before the attempt is made

Upon success the state will be set to CONNECTED and the message reader loop will be started. Upon failure the state will be set to CLOSED with CONNECT_FAILED as its reason

Parameters:

timeout (float) – timeout in seconds before giving up (default: 30)

Raises:

ConnectionFailedError – raised when connection failed or timed out

async disconnect(reason=CloseReason.UNKNOWN)

Disconnects the TCP connection. The method will not raise an exception in case the connection wasn’t yet connected

Parameters:

reason (CloseReason) – optional reason for the disconnect. This parameter is purely informational

start_reader_task()

Starts the message reader task

stop_reader_task()

Stops the message reader task if it exists

async receive_message()

Receives a single raw message

Returns:

The message as a bytes object. None if the connection returned EOF

Return type:

bytes | None

async receive_message_object()

Receives a single message and parses it to a MessageDataclass

Returns:

The parsed message, None if the connection returned EOF

Return type:

MessageDataclass | None

async receive_until_eof(raise_exception=True)

Receives data until the other end closes the connection. If raise_exception parameter is set to True other read errors are treated as EOF as well

Parameters:

raise_exception (bool)

Return type:

bytes | None

queue_message(message)
Parameters:

message (bytes | MessageDataclass)

Return type:

Task

queue_messages(*messages)
Parameters:

messages (bytes | MessageDataclass)

Return type:

list[Task]

async send_message(message)

Sends a message or a set of bytes over the connection. In case an object of MessageDataClass is provided the object will first be serialized. If the obfuscated flag is set for the connection the message or bytes will first be obfuscated

Parameters:

message (bytes | MessageDataclass) – message to be sent over the connection

Raises:

ConnectionWriteError – error or timeout occured during writing

encode_message_data(message)

Serializes the MessageDataclass or bytes and obfuscates the contents. See serialize_message()

Returns:

bytes object

Raises:

MessageSerializationError – raised when serialization failed

Parameters:

message (bytes | MessageDataclass)

Return type:

bytes

decode_message_data(data)

De-obfuscates and deserializes message data into a MessageDataclass object. See deserialize_message()

Parameters:

data (bytes) – message bytes to decode

Returns:

object of MessageDataclass

Raises:

MessageDeserializationError – raised when deserialization failed

Return type:

MessageDataclass

abstractmethod deserialize_message(message_data)

Should be called after a full message has been received. This method should parse the message

Parameters:

message_data (bytes)

Return type:

MessageDataclass

serialize_message(message)
Parameters:

message (bytes | MessageDataclass)

Return type:

bytes

class aioslsk.network.connection.ServerConnection(hostname, port, network, obfuscated=False, read_timeout=600)
Parameters:
async connect(timeout=30)

Opens a TCP connection the hostname:ip provided in this object. The state of the connection will be changed to CONNECTING before the attempt is made

Upon success the state will be set to CONNECTED and the message reader loop will be started. Upon failure the state will be set to CLOSED with CONNECT_FAILED as its reason

Parameters:

timeout (float) – timeout in seconds before giving up (default: 30)

Raises:

ConnectionFailedError – raised when connection failed or timed out

deserialize_message(message_data)

Should be called after a full message has been received. This method should parse the message

Parameters:

message_data (bytes)

Return type:

MessageDataclass

class aioslsk.network.connection.PeerConnection(hostname, port, network, obfuscated=False, username=None, connection_type='P', incoming=False, read_timeout=60, transfer_read_timeout=180)
Parameters:
transfer_read_timeout: float
incoming: bool
connection_type: str
username: str | None
download_rate_limiter: RateLimiter
upload_rate_limiter: RateLimiter
async connect(timeout=10)

Opens a TCP connection the hostname:ip provided in this object. The state of the connection will be changed to CONNECTING before the attempt is made

Upon success the state will be set to CONNECTED and the message reader loop will be started. Upon failure the state will be set to CLOSED with CONNECT_FAILED as its reason

Parameters:

timeout (float) – timeout in seconds before giving up (default: 30)

Raises:

ConnectionFailedError – raised when connection failed or timed out

set_connection_state(state)

Sets the current connection state.

If the current state is AWAITING_INIT and the connection type is a distributed or file connection the obfuscated flag for this connection will be set to False

If the state goes to the ESTABLISHED state the message reader task will be started. In all other cases it will be stopped (in case the task was running)

Parameters:

state (PeerConnectionState) – The new state of the connection

async receive_transfer_ticket()

Receive the transfer ticket from the connection

Return type:

int

async receive_transfer_offset()

Receive the transfer offset from the connection

Return type:

int

async receive_data(n_bytes)

Receives data on the connection. The n_bytes indicates the max amount of bytes that should be received on the connection, less bytes can be returned.

In case of error the socket will be disconnected. If no data is received it is assumed to be EOF and the connection will be disconnected.

Parameters:

n_bytes (int) – max amount of bytes to receive

Raises:

ConnectionReadError – in case timeout occured on an error on the socket

Returns:

bytes object containing the received data or None in case the connection reached EOF

Return type:

bytes | None

async receive_file(file_handle, filesize, callback=None)

Receives a file on the current connection and writes it to the given file_handle

This method will attempt to keep reading data until EOF is received from the connection or the amount of received bytes has reached the filesize

Parameters:
  • file_handle (aiofiles.threadpool.binary.AsyncBufferedIOBase) – a file handle to write the received data to

  • filesize (int) – expected filesize

  • callback (Callable[[bytes], None] | None) – optional callback that gets called each time a chunk of data is received

async send_data(data)
Parameters:

data (bytes)

async send_file(file_handle, callback=None)

Sends a file over the connection. This method makes use of the upload_rate_limiter to limit how many bytes are being sent at a time

Parameters:
  • file_handle (aiofiles.threadpool.binary.AsyncBufferedReader) – binary opened file handle

  • callback (Callable[[bytes], None] | None) – progress callback that gets called each time a chunk of data was sent

deserialize_message(message_data)

Should be called after a full message has been received. This method should parse the message

Parameters:

message_data (bytes)

Return type:

MessageDataclass

aioslsk.network.network

aioslsk.network.network.task_counter()

Implement next(self).

class aioslsk.network.network.ListeningConnectionErrorMode(*values)

Error mode for listening connections. During initialization of the network the connect_listening_connections method will raise an error depending on the error mode

ALL = 'all'

Raise an exception if all listening connections failed to connect

ANY = 'any'

Raise an exception if any listening connections failed to connect

CLEAR = 'clear'

Raise an exception only if the non-obfuscated connection failed to connect

class aioslsk.network.network.PeerConnectMode(*values)

Connection mode to use when connecting to peers

FALLBACK = 'fallback'

Attempt direct connection first, fallback on indirect connection

RACE = 'race'

Attempt both direct and indirect connection at the same time. First to connect will be used and the other will be disconnected

class aioslsk.network.network.ExpectedResponse(connection_class, message_class, peer=None, fields=None, loop=None)

Future for an expected response message

Parameters:
connection_class: type[PeerConnection | ServerConnection]
message_class: type[MessageDataclass]
peer: str | None
fields: dict[str, Any]
matches(connection, response)
Parameters:
Return type:

bool

class aioslsk.network.network.PeerFuture(ticket, username, typ, loop=None)
Parameters:
ticket: int
username: str
typ: str
class aioslsk.network.network.WatchdogContext(last_state: 'ConnectionState')
Parameters:

last_state (ConnectionState)

last_state: ConnectionState
class aioslsk.network.network.Network(settings, event_bus)
Parameters:
server_connection: ServerConnection
listening_connections: ListeningConnections
peer_connections: list[PeerConnection]
register_listeners()
create_server_connection()
Return type:

ServerConnection

create_listening_connections()
Return type:

tuple[ListeningConnection | None, ListeningConnection | None]

async initialize()

Initializes the server and listening connections

async connect_listening_ports()

This method will attempt to connect both listening ports (if configured) but will raise an exception depending on the settings network.listening.error_mode setting. All other listening connections will be disconnected before raising the error

Raises:

ListeningConnectionFailedError – if an error occurred connecting the listening ports

async disconnect_listening_ports()

Disconnects all listening ports

async connect_server()
async disconnect_server()
async disconnect()

Cancels all connection creation tasks and disconnects all current open connections

get_listening_ports()

Gets the currently connected listening ports

Returns:

tuple with 2 elements: the non-obfuscated- and obfuscated ports. If either is not connected or not configured 0 will be returned for this port

Return type:

tuple[int, int]

async advertise_listening_ports()

Notifies the server of our current listening ports

load_speed_limits()

(Re)loads the speed limits from the settings

set_upload_speed_limit(limit_kbps)

Modifies the upload speed limit. Passing 0 will set the upload speed to unlimited

Parameters:

limit_kbps (int) – the new upload limit

set_download_speed_limit(limit_kbps)

Modifies the download speed limit. Passing 0 will set the download speed to unlimited

Parameters:

limit_kbps (int) – the new download limit

async start_server_connection_watchdog()

Starts the server connection watchdog if it is not already running

stop_server_connection_watchdog()

Stops the server connection watchdog if it is running

async start_upnp_job()
stop_upnp_job()
select_port(port, obfuscated_port)

Selects the port used for making a connection. This attempts to take into account the network.peer.obfuscate parameter however falls back on using whatever port is available if necessary

Parameters:
  • port – available non-obfuscated port

  • obfuscated_port – available obfuscated port

Returns:

a tuple with the port number and whether the port is obfuscated

Return type:

tuple[int, bool]

async create_peer_connection(username, typ, ip=None, port=None, obfuscate=False)

Creates a new peer connection to the given username and connection type.

Optionally this method takes ip, port and obfuscate parameters. If not given it will be requested to the server (GetPeerAddress) before attempting connection

Parameters:
  • username (str) – username of the peer

  • typ (str) – connection type (‘P’, ‘D’, ‘F’)

  • ip (str | None) – optional ip address of the peer

  • port (int | None) – optional port of the peer

  • obfuscate (bool) – whether to obfuscate the connection. Should be used in combination with the ip and port

Returns:

an object of PeerConnection

Raises:

PeerConnectionError – when establishing a peer connection has failed

Return type:

PeerConnection

async get_peer_connection(username, typ='P')

Gets a peer connection for the given username. It will first try to re-use an existing connection, otherwise it will create a new connection

Parameters:
  • username (str) – username of the peer to connect to

  • typ (str) – Type of connection to create or reuse

Returns:

A PeerConnection instance

Return type:

PeerConnection

create_server_response_future(message_class, fields=None)

Creates a future for a server message to arrive, the message must match the message_class and fields defined in the keyword arguments.

The future will be stored by the current class and will be removed once the future is complete or cancelled.

Parameters:
  • message_class (type[T]) – The expected MessageDataClass

  • fields (dict[str, Any] | None)

Returns:

ExpectedResponse object

Return type:

ExpectedResponse

register_response_future(expected_response)

Registers an expected response future

Parameters:

expected_response (ExpectedResponse)

async wait_for_server_message(message_class, fields=None, timeout=10)

Waits for a message from the server

Parameters:
  • message_class (type[T]) – Class of the expected server message

  • fields (dict[str, Any] | None) – Optional matchers for the message fields

  • timeout (float)

Returns:

The MessageData object corresponding to the response

Raise:

TimeoutError

Return type:

T

create_peer_response_future(peer, message_class, fields=None)

Creates a future for a peer message to arrive, the message must match the message_class and fields defined in the keyword arguments and must be coming from a connection by peer.

The future will be stored by the current class and will be removed once the future is complete or cancelled.

Parameters:
  • peer (str) – name of the peer for which the message should be received

  • message_class (type[T])

  • fields (dict[str, Any] | None)

Returns:

ExpectedResponse object

Return type:

ExpectedResponse

async wait_for_peer_message(peer, message_class, fields=None, timeout=60)
Parameters:
Return type:

T

get_peer_connections(username, typ)

Returns all connections for peer with given username and peer connection types.

Parameters:
Returns:

list of connections for that matches the parameters

Return type:

list[PeerConnection]

get_active_peer_connections(username, typ)

Return a list of currently active messaging connections for given peer connection type.

Parameters:
  • username (str) – username for which to get the active peer

  • typ (str) – peer connection type

Returns:

list of PeerConnection instances

Return type:

list[PeerConnection]

remove_peer_connection(connection)
Parameters:

connection (PeerConnection)

async send_peer_messages(username, *messages, raise_on_error=True)

Sends a list of messages to the peer with given username. This uses get_peer_connection and will attempt to re-use a connection or create a new peer (P) connection

Parameters:
  • username (str) – Peer username to send the messages to

  • messages (bytes | MessageDataclass) – List of messages to send

  • raise_on_error (bool) – When True an exception is raised when a message failed to send, if False a list of tuples with the result for each message will be returned

Returns:

a list of tuples containing the sent messages and the result of the sent messages. If None is returned for a message it was successfully sent, otherwise the result will contain the exception. None if the raise_on_error is True

queue_server_messages(*messages)

Queues server messages

Parameters:

messages (bytes | MessageDataclass) – list of messages to queue

Return type:

list[Task]

async send_server_messages(*messages, raise_on_error=True)

Sends a list of messages to the server

Parameters:
  • messages (bytes | MessageDataclass) – List of messages to send

  • raise_on_error (bool) – When True an exception is raised when a message failed to send, if False a list of tuples with the result for each message will be returned

Returns:

a list of tuples containing the sent messages and the result of the sent messages. If None is returned for a message it was successfully sent, otherwise the result will contain the exception. None if the raise_on_error is True

async on_state_changed(state, connection, close_reason=CloseReason.UNKNOWN)

Called when the state of a connection changes. This method calls 3 private method based on the type of connection that was passed

Parameters:
  • state (ConnectionState) – the new state the connection has received

  • connection (Connection) – the connection for which the state changed

  • close_reason (CloseReason) – in case ConnectionState.CLOSED is passed a reason will be given as well

async on_peer_accepted(connection)

Called when a connection has been accepted on one of the listening connections. This method will wait for the peer initialization message: either PeerInit or PeerPierceFirewall.

In case of PeerInit the method will perform the initialization of the connection.

In case of PeerPierceFirewall we look for an associated future object for the ticket provided in the message; there should be a task waiting for it to be completed (see _make_indirect_connection). Full initialization of the connection should be done in that method.

In any other case we disconnect the connection.

Parameters:

connection (PeerConnection) – the accepted PeerConnection

async on_message_received(message, connection)

Method called by connection instances when a message is received

Parameters:

aioslsk.protocol.obfuscation

aioslsk.protocol.obfuscation.KEY_SIZE = 4
Variables:

KEY_SIZE – Amount of bytes in the key

aioslsk.protocol.obfuscation.generate_key()
Return type:

bytes

aioslsk.protocol.obfuscation.rotate_key(key, rot_bits=31)

Rotate the key to the right by const bits

Parameters:
  • key (bytes) – Key to rotate

  • rot_bits (int) – Amount of bits to rotate

Returns:

The rotated key

Return type:

bytes

aioslsk.protocol.obfuscation.decode(data)

De-obfuscate given data, the key should be the first 4 bytes of the data

Parameters:

data (bytes) – Data to be de-obfuscated

Returns:

De-obfuscated data

Return type:

bytes

aioslsk.protocol.obfuscation.encode(data, key=None)

Obfuscate the given data with the provided key, if no key is given it will be automatically generated

Parameters:
Return type:

bytes

aioslsk.protocol.primitives

Module defining all data primitives used in the protocol messages

Field metadata:

During (de)serialization the metadata parameter of the dataclasses.field function to control how to perform (de)serialization.

These metadata keys are implemented:

  • ‘type’: <type_class>

    • defines the primary type of the data

  • ‘subtype’: <type_class>

    • used for arrays : the type of the elements contained in the array

  • ‘if_true’: <field_name>

    • serialization : only pack this field if the value of field with name <field_name> evaluates to True

    • deserialization : only parse this field if the value of field with name <field_name> evaluates to True

  • ‘if_false’: <field_name>

    • serialization : only pack this field if the value of field with name <field_name> evaluates to False

    • deserialization : only parse this field if the value of field with name <field_name> evaluates to False

  • ‘optional’: True
    • serialization : only pack this field if its value is anything other than None

    • deserialization : during deserialization the code will determine if the message has been fully parsed. If not it will parse this field

class aioslsk.protocol.primitives.Serializable(*args, **kwargs)
Parameters:
classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, Self]

serialize(*args, **kwargs)
Return type:

bytes

serialize_into(buffer, *args, **kwargs)
Parameters:

buffer (bytearray)

class aioslsk.protocol.primitives.AttributeKey(*values)
BITRATE = 0
DURATION = 1
VBR = 2
SAMPLE_RATE = 4
BIT_DEPTH = 5
aioslsk.protocol.primitives.decode_string(value)
Parameters:

value (bytes)

Return type:

str

class aioslsk.protocol.primitives.uint8
STRUCT = <_struct.Struct object>
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, int]

class aioslsk.protocol.primitives.uint16
STRUCT = <_struct.Struct object>
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, int]

class aioslsk.protocol.primitives.uint32
STRUCT = <_struct.Struct object>
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, int]

class aioslsk.protocol.primitives.uint64
STRUCT = <_struct.Struct object>
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, int]

class aioslsk.protocol.primitives.int32
STRUCT = <_struct.Struct object>
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, int]

class aioslsk.protocol.primitives.string
serialize(encoding='utf-8')
Parameters:

encoding (str)

Return type:

bytes

serialize_into(buffer, encoding='utf-8')
Parameters:
classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, str]

class aioslsk.protocol.primitives.bytearr
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, bytes]

class aioslsk.protocol.primitives.ipaddr
STRUCT = <_struct.Struct object>
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, str]

class aioslsk.protocol.primitives.boolean
STRUCT = <_struct.Struct object>
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

classmethod deserialize(pos, data)
Parameters:
Return type:

tuple[int, bool]

class aioslsk.protocol.primitives.array(iterable=(), /)
serialize(element_type)
Parameters:

element_type (type[Serializable])

Return type:

bytes

serialize_into(buffer, element_type)
Parameters:
classmethod deserialize(pos, data, element_type)
Parameters:
Return type:

tuple[int, list[T]]

class aioslsk.protocol.primitives.ProtocolDataclass

The ProtocolDataclass defines a collection of primitives that can be serialized or deserialized. Classes inheriting from this class should use the @dataclass(order=True) decorator. The order needs to be kept as the fields definitions will be evaluated during (de)serialization.

Example definition:

@dataclass(order=True)
class CustomDataclass(ProtocolDataclass):
    username: str = field(metadata={'type': string})
    password: str = field(metadata={'type': string})
    has_privileges: bool = field(metadata={'type': boolean})
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

classmethod deserialize(pos, message)
Parameters:
class aioslsk.protocol.primitives.MessageDataclass

Message data class for which protocol messages should inherit from. This takes all behaviour from the ProtocolDataclass class but adds:

  • Prepending the message with length and MESSAGE_ID

  • Optionally the message data will (de)compressed

MESSAGE_ID: ClassVar[uint8 | uint32] = 0
serialize(compress=False)

Serializes the current MessageDataClass object and prepends the message length and MESSAGE_ID

In case the message needs to be compressed just override this method in the subclass and simply call the super method with compress=True

Parameters:

compress (bool) – use gzip compression on the message contents

Return type:

bytes

serialize_into(buffer, compress=False)
Parameters:
classmethod deserialize(pos, message, decompress=False)

Deserializes the passed message into an object of the current type

In case the message needs to be decompressed just override this method in the subclass and simply call the super method with decompress=True

Parameters:
  • decompress (bool) – use gzip decompression on the message contents

  • pos (int)

  • message (bytes)

Raises:

ValueError – if the message_id found the data does not match the MESSAGE_ID defined in the current class

Returns:

an object of the current class

Return type:

Self

class aioslsk.protocol.primitives.Attribute(key: int, value: int)
Parameters:
key: int
value: int
classmethod deserialize(pos, message)
Parameters:
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

class aioslsk.protocol.primitives.SimilarUser(username: str, score: int)
Parameters:
username: str
score: int
class aioslsk.protocol.primitives.Recommendation(recommendation: str, score: int)
Parameters:
  • recommendation (str)

  • score (int)

recommendation: str
score: int
class aioslsk.protocol.primitives.RoomTicker(username: str, ticker: str)
Parameters:
username: str
ticker: str
class aioslsk.protocol.primitives.PotentialParent(username: str, ip: str, port: int)
Parameters:
username: str
ip: str
port: int
class aioslsk.protocol.primitives.UserStats(avg_speed: int, uploads: int, shared_file_count: int, shared_folder_count: int)
Parameters:
  • avg_speed (int)

  • uploads (int)

  • shared_file_count (int)

  • shared_folder_count (int)

avg_speed: int
uploads: int
shared_file_count: int
shared_folder_count: int
class aioslsk.protocol.primitives.FileData(unknown: int, filename: str, filesize: int, extension: str, attributes: list[aioslsk.protocol.primitives.Attribute])
Parameters:
unknown: int
filename: str
filesize: int
extension: str
attributes: list[Attribute]
classmethod deserialize(pos, message)
Parameters:
serialize()
Return type:

bytes

serialize_into(buffer)
Parameters:

buffer (bytearray)

get_attribute_map()

Converts the attribute list to a dictionary. The resulting dictionary will only contain known attributes and attributes present in the list

Return type:

dict[AttributeKey, int]

class aioslsk.protocol.primitives.DirectoryData(name: str, files: list[aioslsk.protocol.primitives.FileData])
Parameters:
name: str
files: list[FileData]
classmethod deserialize(pos, message)
Parameters:
serialize()
Return type:

bytes

aioslsk.protocol.primitives.has_unparsed_bytes(pos, message)
Parameters:
Return type:

bool

aioslsk.protocol.primitives.calc_md5(value)
Parameters:

value (str)

Return type:

str

aioslsk.protocol.messages

Definition of all SoulSeek protocol messages.

This file contains 2 types of messages:

  • Server

    Requestused from client to server. A client will only use the

    serialize method of these messages

    Responseused from server to client. A client will only use the

    deserialize method of these messages

  • Peer

    Requestpeer messages only consist of request type messages. The client

    should use the deserialize method of these messages upon receiving data from another peer and the serialize method when sending to another peer

class aioslsk.protocol.messages.ServerMessage

Class for identifying server messages

classmethod deserialize_request(message)
Parameters:

message (bytes)

classmethod deserialize_response(message)
class aioslsk.protocol.messages.PeerInitializationMessage

Class for identifying peer initialization messages

classmethod deserialize_request(message)
Parameters:

message (bytes)

class aioslsk.protocol.messages.PeerMessage

Class for identifying peer messages

classmethod deserialize_request(message)
Parameters:

message (bytes)

class aioslsk.protocol.messages.DistributedMessage

Class for identifying distributed messages

classmethod deserialize_request(message)
Parameters:

message (bytes)

class aioslsk.protocol.messages.Login

Login into the server, this should be the first message sent to the server upon connecting

  • The md5hash parameter in the request is the MD5 hash of the concatenated username and password

  • The md5hash parameter in the response is the MD5 hash of the password

Note

Older client versions (at least 149 or below) would not send the md5hash and minor_version

Status:

USED

class Request(username: str, password: str, client_version: int, md5hash: str, minor_version: int)
Parameters:
  • username (str)

  • password (str)

  • client_version (int)

  • md5hash (str)

  • minor_version (int)

MESSAGE_ID: ClassVar[uint32] = 1
username: str
password: str
client_version: int
md5hash: str
minor_version: int
class Response(success: bool, greeting: str | None = None, ip: str | None = None, md5hash: str | None = None, privileged: bool | None = None, reason: str | None = None)
Parameters:
  • success (bool)

  • greeting (str | None)

  • ip (str | None)

  • md5hash (str | None)

  • privileged (bool | None)

  • reason (str | None)

MESSAGE_ID: ClassVar[uint32] = 1
success: bool
greeting: str | None
ip: str | None
md5hash: str | None
privileged: bool | None
reason: str | None
class aioslsk.protocol.messages.SetListenPort

Advertise our listening ports to the server

Obfuscated port: this part seems to be optional, either it can be omitted completely or both values set to 0

Status:

USED

class Request(port: int, obfuscated_port_amount: int | None = None, obfuscated_port: int | None = None)
Parameters:
  • port (int)

  • obfuscated_port_amount (int | None)

  • obfuscated_port (int | None)

MESSAGE_ID: ClassVar[uint32] = 2
port: int
obfuscated_port_amount: int | None
obfuscated_port: int | None
class aioslsk.protocol.messages.GetPeerAddress

Retrieve the IP address/port of a peer. Obfuscated port: this part is optional, either it can be omitted completely or both values set to 0 to indicate there is no obfuscated port

If the peer does not exist or is not logged on the server will respond with IP address set to 0.0.0.0, port set to 0

Status:

USED

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 3
username: str
class Response(username: str, ip: str, port: int, obfuscated_port_amount: int | None = None, obfuscated_port: int | None = None)
Parameters:
  • username (str)

  • ip (str)

  • port (int)

  • obfuscated_port_amount (int | None)

  • obfuscated_port (int | None)

MESSAGE_ID: ClassVar[uint32] = 3
username: str
ip: str
port: int
obfuscated_port_amount: int | None
obfuscated_port: int | None
class aioslsk.protocol.messages.AddUser

When a user is added with this message the server will automatically send user status updates using the GetUserStatus (Code 7) message.

When a user sends a message to multiple users using the PrivateChatMessageUsers (Code 149) message then this message will only be received if the sender was added first using this message.

To remove a user use the RemoveUser (Code 6) message. Keep in mind that you will still receive status updates in case you are joined in the same room with the user.

Status:

USED

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 5
username: str
class Response(username: str, exists: bool, status: int | None = None, user_stats: aioslsk.protocol.primitives.UserStats | None = None, country_code: str | None = None)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 5
username: str
exists: bool
status: int | None
user_stats: UserStats | None
country_code: str | None
class aioslsk.protocol.messages.RemoveUser

Remove the tracking of user status which was previously added with the AddUser (Code 5) message.

Status:

USED

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 6
username: str
class aioslsk.protocol.messages.GetUserStatus

Get the user status. The server will automatically send updates for users that we have added with AddUser (Code 5) or which we share a room with.

Status:

USED

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 7
username: str
class Response(username: str, status: int, privileged: bool)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 7
username: str
status: int
privileged: bool
class aioslsk.protocol.messages.IgnoreUser

Sent when we want to ignore a user. Received when another user ignores us

Status:

DEPRECATED, DEFUNCT

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 11
username: str
class Response(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 11
username: str
class aioslsk.protocol.messages.UnignoreUser

Sent when we want to unignore a user. Received when another user unignores us

Status:

DEPRECATED, DEFUNCT

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 12
username: str
class Response(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 12
username: str
class aioslsk.protocol.messages.RoomChatMessage

Used when sending a message to a room or receiving a message from someone (including self) who sent a message to a room

Status:

USED

class Request(room: str, message: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 13
room: str
message: str
class Response(room: str, username: str, message: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 13
room: str
username: str
message: str
class aioslsk.protocol.messages.JoinRoom

Used when we want to join a chat room. If the chat room does not exist it will be created. Upon successfully joining the room the server will send the response message

Status:

USED

class Request(room: str, is_private: bool = False)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 14
room: str
is_private: bool
class Response(room: str, users: list[str], users_status: list[int], users_stats: list[aioslsk.protocol.primitives.UserStats], users_slots_free: list[int], users_countries: list[str], owner: str | None = None, operators: list[str] | None = None)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 14
room: str
users: list[str]
users_status: list[int]
users_stats: list[UserStats]
users_slots_free: list[int]
users_countries: list[str]
owner: str | None
operators: list[str] | None
class aioslsk.protocol.messages.LeaveRoom

Used when we want to leave a chat room. The receive message is confirmation that we left the room

Status:

USED

class Request(room: str)
Parameters:

room (str)

MESSAGE_ID: ClassVar[uint32] = 15
room: str
class Response(room: str)
Parameters:

room (str)

MESSAGE_ID: ClassVar[uint32] = 15
room: str
class aioslsk.protocol.messages.UserJoinedRoom

Received when a user joined a room

Status:

USED

class Response(room: str, username: str, status: int, user_stats: aioslsk.protocol.primitives.UserStats, slots_free: int, country_code: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 16
room: str
username: str
status: int
user_stats: UserStats
slots_free: int
country_code: str
class aioslsk.protocol.messages.UserLeftRoom

Received when a user left a room

Status:

USED

class Response(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 17
room: str
username: str
class aioslsk.protocol.messages.ConnectToPeer

Used for making an indirect connection to another peer. If an indirect connection is needed the request should be sent to the server who will pass on the message to the other peer. The peer should try to make a connection with the information (IP, port) provided by the server.

Likewise if the response is received an attempt should be made to connect to the requesting peer

Peer A –Request(username=Peer B)–> Server –Response(username=Peer A)–> Peer B

Also see: CannotConnect (Code 1001)

Status:

USED

class Request(ticket: int, username: str, typ: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 18
ticket: int
username: str
typ: str
class Response(username: str, typ: str, ip: str, port: int, ticket: int, privileged: bool, obfuscated_port_amount: int | None = None, obfuscated_port: int | None = None)
Parameters:
  • username (str)

  • typ (str)

  • ip (str)

  • port (int)

  • ticket (int)

  • privileged (bool)

  • obfuscated_port_amount (int | None)

  • obfuscated_port (int | None)

MESSAGE_ID: ClassVar[uint32] = 18
username: str
typ: str
ip: str
port: int
ticket: int
privileged: bool
obfuscated_port_amount: int | None
obfuscated_port: int | None
class aioslsk.protocol.messages.PrivateChatMessage

Send or receive a private message. The chat_id should be used in the PrivateChatMessageAck (Code 23) message to acknowledge the message has been received. If the acknowledgement is not sent the server will repeat the message on the next logon.

The is_direct boolean indicates whether it is the first attempt to send the message, if the server retries then this parameter will be false

Status:

USED

class Request(username: str, message: str)
Parameters:
  • username (str)

  • message (str)

MESSAGE_ID: ClassVar[uint32] = 22
username: str
message: str
class Response(chat_id: int, timestamp: int, username: str, message: str, is_direct: bool | None = False)
Parameters:
  • chat_id (int)

  • timestamp (int)

  • username (str)

  • message (str)

  • is_direct (bool | None)

MESSAGE_ID: ClassVar[uint32] = 22
chat_id: int
timestamp: int
username: str
message: str
is_direct: bool | None
property is_admin: bool | None

Only kept to keep backward compatibility. Use is_direct

This property does not actually represent whether the message was sent by an admin. Instead it represents whether the message was sent directly or was queued on the server before being sent (example, when user was offline and came back online)

class aioslsk.protocol.messages.PrivateChatMessageAck

Acknowledge we have received a private message after receiving a PrivateChatMessage (Code 22)

Status:

USED

class Request(chat_id: int)
Parameters:

chat_id (int)

MESSAGE_ID: ClassVar[uint32] = 23
chat_id: int
class aioslsk.protocol.messages.FileSearchRoom

Deprecated message for searching a room

Status:

DEPRECATED, DEFUNCT

class Request(ticket: int, room_id: int, query: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 25
ticket: int
room_id: int
query: str
class aioslsk.protocol.messages.FileSearch

This message is received when another user performed a RoomSearch (Code 120) or UserSearch (Code 42) request and we are part of the room or we are the user the user would like to search in

Status:

USED

class Request(ticket: int, query: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 26
ticket: int
query: str
class Response(username: str, ticket: int, query: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 26
username: str
ticket: int
query: str
class aioslsk.protocol.messages.SetStatus

Used to update the online status. Possible values for status: online = 2, away = 1, offline = 0

Status:

USED

class Request(status: int)
Parameters:

status (int)

MESSAGE_ID: ClassVar[uint32] = 28
status: int
class aioslsk.protocol.messages.Ping

Send a ping to the server to let it know we are still alive (every 5 minutes)

Older server versions would respond to this message with the response message

Status:

USED

class Request
MESSAGE_ID: ClassVar[uint32] = 32
class Response
MESSAGE_ID: ClassVar[uint32] = 32
class aioslsk.protocol.messages.SendConnectTicket

Deprecated predecessor to ConnectToPeer (Code 18). A peer would send this message to the server when wanting to create a connection to another peer, the server would then pass to this to the targeted peer

The value of the ticket parameter would be used in the PeerInit (Code 1) message.

Status:

DEPRECATED, DEFUNCT

class Request(username: str, ticket: int)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 33
username: str
ticket: int
class Response(username: str, ticket: int)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 33
username: str
ticket: int
class aioslsk.protocol.messages.SendDownloadSpeed

Sent by old clients after download has completed. SendUploadSpeed (Code 121) should be used instead. The speed value should be in bytes per second

Status:

DEPRECATED, DEFUNCT

class Request(username: str, speed: int)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 34
username: str
speed: int
class aioslsk.protocol.messages.SharedFoldersFiles

Let the server know the amount of files and directories we are sharing. These would be returned in several messages, for example the GetUserStats (Code 36) and AddUser (Code 5) messages

Status:

USED

class Request(shared_folder_count: int, shared_file_count: int)
Parameters:
  • shared_folder_count (int)

  • shared_file_count (int)

MESSAGE_ID: ClassVar[uint32] = 35
shared_folder_count: int
shared_file_count: int
class aioslsk.protocol.messages.GetUserStats

Request a user’s transfer statistics. This message will be received automatically for users with which we share a room

Status:

USED

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 36
username: str
class Response(username: str, user_stats: aioslsk.protocol.primitives.UserStats)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 36
username: str
user_stats: UserStats
class aioslsk.protocol.messages.Kicked

You were kicked from the server. This message is currently only known to be sent when the user was logged into at another location

Status:

USED

class Response
MESSAGE_ID: ClassVar[uint32] = 41
class aioslsk.protocol.messages.UserSearch

Search for a file on a specific user, the user will receive this query in the form of a FileSearch (Code 26) message

Status:

USED

class Request(username: str, ticket: int, query: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 42
username: str
ticket: int
query: str
class aioslsk.protocol.messages.DeprecatedGetItemRecommendations

Similar to GetItemRecommendations (Code 111) except that no score is returned

Status:

DEPRECATED, DEFUNCT

class Request(item: str)
Parameters:

item (str)

MESSAGE_ID: ClassVar[uint32] = 50
item: str
class Response(item: str, recommendations: list[str])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 50
item: str
recommendations: list[str]
class aioslsk.protocol.messages.AddInterest

Adds an interest. This is used when requesting recommendations (eg.: GetRecommendations (Code 54), …)

Status:

USED

class Request(interest: str)
Parameters:

interest (str)

MESSAGE_ID: ClassVar[uint32] = 51
interest: str
class aioslsk.protocol.messages.RemoveInterest

Removes an interest previously added with AddInterest (Code 51) message

Status:

USED

class Request(interest: str)
Parameters:

interest (str)

MESSAGE_ID: ClassVar[uint32] = 52
interest: str
class aioslsk.protocol.messages.GetRecommendations

Request the server to send a list of recommendations and unrecommendations. A maximum of 100 each will be returned. The score can be negative.

Status:

USED

class Request
MESSAGE_ID: ClassVar[uint32] = 54
class Response(recommendations: list[aioslsk.protocol.primitives.Recommendation], unrecommendations: list[aioslsk.protocol.primitives.Recommendation])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 54
recommendations: list[Recommendation]
unrecommendations: list[Recommendation]
class aioslsk.protocol.messages.GetInterests

Request the server the list of interests it currently has stored for us. This was sent by older clients during logon, presumably to sync the interests on the client and the server. Deprecated as the client should just advertise all interests after logon using the AddInterest (Code 51) and AddHatedInterest (Code 117) messages

Not known whether the server still responds to this command

Status:

DEPRECATED, DEFUNCT

class Request
MESSAGE_ID: ClassVar[uint32] = 55
class Response(interests: list[str])
Parameters:

interests (list[str])

MESSAGE_ID: ClassVar[uint32] = 55
interests: list[str]
class aioslsk.protocol.messages.GetGlobalRecommendations

Get the global list of recommendations. This does not take into account interests or hated interests that were previously added and is just a ranking of interests that other users have set

Status:

USED

class Request
MESSAGE_ID: ClassVar[uint32] = 56
class Response(recommendations: list[aioslsk.protocol.primitives.Recommendation], unrecommendations: list[aioslsk.protocol.primitives.Recommendation])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 56
recommendations: list[Recommendation]
unrecommendations: list[Recommendation]
class aioslsk.protocol.messages.GetUserInterests

Get the interests and hated interests of a particular user

Status:

DEPRECATED

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 57
username: str
class Response(username: str, interests: list[str], hated_interests: list[str])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 57
username: str
interests: list[str]
hated_interests: list[str]
class aioslsk.protocol.messages.ExecuteCommand

Send a command to the server.

The command type has only ever been seen as having value admin, the arguments array contains the subcommand and arguments. Example when banning a user:

  • command_type : admin

  • arguments

    • 0 : ban

    • 1 : some user

    • 2 : probably some extra args, perhaps time limit in case of ban, … (optional)

Status:

DEPRECATED, DEFUNCT

class Request(command_type: str, arguments: list[str])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 58
command_type: str
arguments: list[str]
class aioslsk.protocol.messages.RoomList

Request or receive the list of rooms. This message will be initially sent after logging on but can also be manually requested afterwards. The initial message after logon will only return a limited number of public rooms (only the rooms with 5 or more users).

Parameter rooms_private excludes private rooms of which we are owner

Parameter rooms_private_owned_user_count / rooms_private_user_count should be the amount of users who have joined the private room, not the amount of members

Status:

USED

class Request
MESSAGE_ID: ClassVar[uint32] = 64
class Response(rooms: list[str], rooms_user_count: list[int], rooms_private_owned: list[str], rooms_private_owned_user_count: list[int], rooms_private: list[str], rooms_private_user_count: list[int], rooms_private_operated: list[str])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 64
rooms: list[str]
rooms_user_count: list[int]
rooms_private_owned: list[str]
rooms_private_owned_user_count: list[int]
rooms_private: list[str]
rooms_private_user_count: list[int]
rooms_private_operated: list[str]
class aioslsk.protocol.messages.ExactFileSearch

Used by older clients but doesn’t return anything. The pathname is optional but is still required to be sent.

For the message sending: The first 4 parameters are verified, the meaning of the final 5 bytes is unknown

For the message receiving: message is never seen and is based on other documentation (PySlsk)

Status:

DEPRECATED, DEFUNCT

class Request(ticket: int, filename: str, pathname: str, filesize: int, checksum: int, unknown: int)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 65
ticket: int
filename: str
pathname: str
filesize: int
checksum: int
unknown: int
class Response(username: str, ticket: int, filename: str, pathname: str, filesize: int, checksum: int)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 65
username: str
ticket: int
filename: str
pathname: str
filesize: int
checksum: int
class aioslsk.protocol.messages.AdminMessage

Sent by the admin when the server is going down for example

Status:

UNKNOWN

class Response(message: str)
Parameters:

message (str)

MESSAGE_ID: ClassVar[uint32] = 66
message: str
class aioslsk.protocol.messages.GetUserList

Gets a list of all users on the server

Status:

DEPRECATED, DEFUNCT

class Request
MESSAGE_ID: ClassVar[uint32] = 67
class Response(users: list[str], users_status: list[int], users_stats: list[aioslsk.protocol.primitives.UserStats], users_slots_free: list[int], users_countries: list[str])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 67
users: list[str]
users_status: list[int]
users_stats: list[UserStats]
users_slots_free: list[int]
users_countries: list[str]
class aioslsk.protocol.messages.TunneledMessage

Tunnel a message through the server to a user

Status:

DEPRECATED, DEFUNCT

class Request(username: str, ticket: int, code: int, message: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 68
username: str
ticket: int
code: int
message: str
class Response(username: str, ticket: int, code: int, ip: str, port: int, message: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 68
username: str
ticket: int
code: int
ip: str
port: int
message: str
class aioslsk.protocol.messages.PrivilegedUsers

List of users with privileges sent after login

Status:

USED

class Response(users: list[str])
Parameters:

users (list[str])

MESSAGE_ID: ClassVar[uint32] = 69
users: list[str]
class aioslsk.protocol.messages.ToggleParentSearch

Indicates whether we want to receive PotentialParents (Code 102) messages from the server. A message should be sent to disable if we have found a parent

Status:

USED

class Request(enable: bool)
Parameters:

enable (bool)

MESSAGE_ID: ClassVar[uint32] = 71
enable: bool
class aioslsk.protocol.messages.ParentIP

IP address of the parent. Not sent by newer clients

Status:

DEPRECATED

class Request(ip: str)
Parameters:

ip (str)

MESSAGE_ID: ClassVar[uint32] = 73
ip: str
class aioslsk.protocol.messages.Unknown80

Unknown message used by old client versions. The client would establish 2 connections to the server: to one it would send the Login (Code 1) message, to the other this message would be sent. This second connection seemed to be related to the distributed network as the client would automatically disconnect after DistributedAliveInterval (Code 90) had been reached. It would seem like the server would be the client’s parent in this case.

After an interval determined by DistributedDistributeInterval (Code 89) the client would send another message over this connection which is described in DistributedInit (Code 1). There’s many unknowns in this message and even the types are unknown as many values were just 0, only known value is the last value which is the second listening port these clients used

Status:

DEPRECATED, DEFUNCT

class Request
MESSAGE_ID: ClassVar[uint32] = 80
class aioslsk.protocol.messages.ParentMinSpeed

Used for calculating the maximum amount of children we can have in the distributed network. If our average upload speed is below this value then we should accept no children. The average upload speed should be determined by the upload speed returned by GetUserStats (Code 36) (with our own username)

Status:

USED

class Response(speed: int)
Parameters:

speed (int)

MESSAGE_ID: ClassVar[uint32] = 83
speed: int
class aioslsk.protocol.messages.ParentSpeedRatio

Used for calculating the maximum amount of children we can have in the distributed network

Status:

USED

class Response(ratio: int)
Parameters:

ratio (int)

MESSAGE_ID: ClassVar[uint32] = 84
ratio: int
class aioslsk.protocol.messages.ParentInactivityTimeout

Timeout for the distributed parent

Status:

DEPRECATED

class Response(timeout: int)
Parameters:

timeout (int)

MESSAGE_ID: ClassVar[uint32] = 86
timeout: int
class aioslsk.protocol.messages.SearchInactivityTimeout

Presumably indicates after how much time search responses should no longer be accepted

Status:

DEPRECATED

class Response(timeout: int)
Parameters:

timeout (int)

MESSAGE_ID: ClassVar[uint32] = 87
timeout: int
class aioslsk.protocol.messages.MinParentsInCache

Amount of parents (received through PotentialParents (Code 102)) we should keep in cache. Message has not been seen being sent by the server

Status:

DEPRECATED, DEFUNCT

class Response(amount: int)
Parameters:

amount (int)

MESSAGE_ID: ClassVar[uint32] = 88
amount: int
class aioslsk.protocol.messages.DistributedDistributeInterval

Deprecated distributed network related message

Status:

DEPRECATED, DEFUNCT

class Response(interval: int)
Parameters:

interval (int)

MESSAGE_ID: ClassVar[uint32] = 89
interval: int
class aioslsk.protocol.messages.DistributedAliveInterval

Interval at which a DistributedPing (Code 0) message should be sent to the children

Status:

DEPRECATED

class Response(interval: int)
Parameters:

interval (int)

MESSAGE_ID: ClassVar[uint32] = 90
interval: int
class aioslsk.protocol.messages.AddPrivilegedUser

Usage unknown

Status:

UNKNOWN

class Response(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 91
username: str
class aioslsk.protocol.messages.CheckPrivileges

Checks whether the requesting user has privileges, time_left will be 0 in case the user has no privileges, time left in seconds otherwise

Status:

USED

class Request
MESSAGE_ID: ClassVar[uint32] = 92
class Response(time_left: int)
Parameters:

time_left (int)

MESSAGE_ID: ClassVar[uint32] = 92
time_left: int
class aioslsk.protocol.messages.ServerSearchRequest

Search request sent by another user through the server. Upon receiving this the message should be passed on to the distributed children

Status:

USED

class Response(distributed_code: int, unknown: int, username: str, ticket: int, query: str)
Parameters:
  • distributed_code (int)

  • unknown (int)

  • username (str)

  • ticket (int)

  • query (str)

MESSAGE_ID: ClassVar[uint32] = 93
distributed_code: int
unknown: int
username: str
ticket: int
query: str
class aioslsk.protocol.messages.AcceptChildren

Tell the server whether or not we are accepting any distributed children, the server should take this into account when sending PotentialParents (Code 102) messages to other peers

Status:

USED

class Request(accept: bool)
Parameters:

accept (bool)

MESSAGE_ID: ClassVar[uint32] = 100
accept: bool
class aioslsk.protocol.messages.PotentialParents

List of potential parents, used in distributed network

Status:

USED

class Response(entries: list[aioslsk.protocol.primitives.PotentialParent])
Parameters:

entries (list[PotentialParent])

MESSAGE_ID: ClassVar[uint32] = 102
entries: list[PotentialParent]
class aioslsk.protocol.messages.WishlistSearch

Perform a wishlist search. The interval at which a client should send this message is determined by the WishlistInterval (Code 104) message

Status:

USED

class Request(ticket: int, query: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 103
ticket: int
query: str
class aioslsk.protocol.messages.WishlistInterval

The server lets us know at what interval we should perform wishlist searches (WishlistSearch (Code 103)). Sent by the server after logon

Status:

USED

class Response(interval: int)
Parameters:

interval (int)

MESSAGE_ID: ClassVar[uint32] = 104
interval: int
class aioslsk.protocol.messages.GetSimilarUsers

Get a list of similar users

Status:

USED

class Request
MESSAGE_ID: ClassVar[uint32] = 110
class Response(users: list[aioslsk.protocol.primitives.SimilarUser])
Parameters:

users (list[SimilarUser])

MESSAGE_ID: ClassVar[uint32] = 110
users: list[SimilarUser]
class aioslsk.protocol.messages.GetItemRecommendations

Get a list of recommendations based on a single interest

Status:

USED

class Request(item: str)
Parameters:

item (str)

MESSAGE_ID: ClassVar[uint32] = 111
item: str
class Response(item: str, recommendations: list[aioslsk.protocol.primitives.Recommendation])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 111
item: str
recommendations: list[Recommendation]
class aioslsk.protocol.messages.GetItemSimilarUsers

Get a list of similar users based on a single interest

Status:

USED

class Request(item: str)
Parameters:

item (str)

MESSAGE_ID: ClassVar[uint32] = 112
item: str
class Response(item: str, usernames: list[str])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 112
item: str
usernames: list[str]
class aioslsk.protocol.messages.RoomTickers

List of chat room tickers (room wall)

Status:

USED

class Response(room: str, tickers: list[aioslsk.protocol.primitives.RoomTicker])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 113
room: str
tickers: list[RoomTicker]
class aioslsk.protocol.messages.RoomTickerAdded

A ticker has been added to the room (room wall)

Status:

USED

class Response(room: str, username: str, ticker: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 114
room: str
username: str
ticker: str
class aioslsk.protocol.messages.RoomTickerRemoved

A ticker has been removed to the room (room wall)

Status:

USED

class Response(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 115
room: str
username: str
class aioslsk.protocol.messages.SetRoomTicker

Add or update a ticker for a room (room wall)

Note

An empty ticker value is not allowed in most clients. However, the server does accept it and clears the ticker from the room

Status:

USED

class Request(room: str, ticker: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 116
room: str
ticker: str
class aioslsk.protocol.messages.AddHatedInterest

Adds an hated interest. This is used when requesting recommendations (eg.: GetRecommendations (Code 54), …)

Status:

USED

class Request(hated_interest: str)
Parameters:

hated_interest (str)

MESSAGE_ID: ClassVar[uint32] = 117
hated_interest: str
class aioslsk.protocol.messages.RemoveHatedInterest

Removes a hated interest previously added with AddHatedInterest (Code 117) message

Status:

USED

class Request(hated_interest: str)
Parameters:

hated_interest (str)

MESSAGE_ID: ClassVar[uint32] = 118
hated_interest: str
class aioslsk.protocol.messages.RoomSearch

Perform a search query on all users in the given room, this can only be performed if the room was joined first. The server will send a FileSearch (Code 26) to every user in the requested room

Status:

USED

class Request(room: str, ticket: int, query: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 120
room: str
ticket: int
query: str
class aioslsk.protocol.messages.SendUploadSpeed

Sent to the server right after an upload completed. speed parameter should be in bytes per second. This should not be the global average upload speed but rather the upload speed for that particular transfer. After this message has been sent the server will recalculate the average speed and increase the amount of uploads for your user.

In exception cases, for example if a transfer was failed midway then resumed, only the speed of the resumed part is taken into account. However this might be client dependent.

Status:

USED

class Request(speed: int)
Parameters:

speed (int)

MESSAGE_ID: ClassVar[uint32] = 121
speed: int
class aioslsk.protocol.messages.GetUserPrivileges

Retrieve whether a user has privileges

Status:

USED

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 122
username: str
class Response(username: str, privileged: bool)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 122
username: str
privileged: bool
class aioslsk.protocol.messages.GiveUserPrivileges

Gift a user privileges. This only works if the user sending the message has privileges and needs to be less than what the gifting user has left, part of its privileges will be taken

Status:

USED

class Request(username: str, days: int)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 123
username: str
days: int
class aioslsk.protocol.messages.PrivilegesNotification
class Request(notification_id: int, username: str)
Parameters:
  • notification_id (int)

  • username (str)

MESSAGE_ID: ClassVar[uint32] = 124
notification_id: int
username: str
class aioslsk.protocol.messages.PrivilegesNotificationAck
class Request(notification_id: int)
Parameters:

notification_id (int)

MESSAGE_ID: ClassVar[uint32] = 125
notification_id: int
class aioslsk.protocol.messages.BranchLevel

Notify the server which branch level we are at in the distributed network

Status:

USED

class Request(level: int)
Parameters:

level (int)

MESSAGE_ID: ClassVar[uint32] = 126
level: int
class aioslsk.protocol.messages.BranchRoot

Notify the server who our branch root user is in the distributed network

Status:

USED

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint32] = 127
username: str
class aioslsk.protocol.messages.ChildDepth

See DistributedChildDepth (Code 7)

Note

SoulSeekQt sends the depth as a uint8

Status:

DEPRECATED

class Request(depth: int)
Parameters:

depth (int)

MESSAGE_ID: ClassVar[uint32] = 129
depth: int
class aioslsk.protocol.messages.ResetDistributed

Server requests to reset our parent and children

Status:

USED

class Response
MESSAGE_ID: ClassVar[uint32] = 130
class aioslsk.protocol.messages.PrivateRoomMembers

List of all members that are part of the private room (excludes owner)

Status:

USED

class Response(room: str, usernames: list[str])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 133
room: str
usernames: list[str]
class aioslsk.protocol.messages.PrivateRoomGrantMembership

Add another user to the private room. Only operators and the owner can add members to a private room.

This message is also received by all other members in the private room

Status:

USED

class Request(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 134
room: str
username: str
class Response(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 134
room: str
username: str
class aioslsk.protocol.messages.PrivateRoomRevokeMembership

Remove another user from the private room. Operators can remove regular members but not other operators or the owner. The owner can remove anyone aside from himself (see PrivateRoomDropOwnership (Code 137)).

This message is also received by all other members in the private room

Status:

USED

class Request(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 135
room: str
username: str
class Response(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 135
room: str
username: str
class aioslsk.protocol.messages.PrivateRoomDropMembership

Drops membership of a private room, this will not do anything for the owner of the room. See PrivateRoomDropOwnership (Code 137) for owners

Status:

USED

class Request(room: str)
Parameters:

room (str)

MESSAGE_ID: ClassVar[uint32] = 136
room: str
class aioslsk.protocol.messages.PrivateRoomDropOwnership

Drops ownership of a private room, this disbands the entire room.

Status:

USED

class Request(room: str)
Parameters:

room (str)

MESSAGE_ID: ClassVar[uint32] = 137
room: str
class aioslsk.protocol.messages.PrivateRoomMembershipGranted

Received when the current user has been granted membership to a private room

Status:

USED

class Response(room: str)
Parameters:

room (str)

MESSAGE_ID: ClassVar[uint32] = 139
room: str
class aioslsk.protocol.messages.PrivateRoomMembershipRevoked

Received when the current user had its membership revoked from a private room

Status:

USED

class Response(room: str)
Parameters:

room (str)

MESSAGE_ID: ClassVar[uint32] = 140
room: str
class aioslsk.protocol.messages.TogglePrivateRoomInvites

Enables or disables private room invites (through PrivateRoomGrantMembership (Code 134))

Status:

USED

class Request(enable: bool)
Parameters:

enable (bool)

MESSAGE_ID: ClassVar[uint32] = 141
enable: bool
class Response(enabled: bool)
Parameters:

enabled (bool)

MESSAGE_ID: ClassVar[uint32] = 141
enabled: bool
class aioslsk.protocol.messages.NewPassword

Modifies the user’s password

Status:

USED

class Request(password: str)
Parameters:

password (str)

MESSAGE_ID: ClassVar[uint32] = 142
password: str
class aioslsk.protocol.messages.PrivateRoomGrantOperator

Grant operator privileges to a member in a private room. This message will also be received by all other members in the room (irrelevant of if they are online or not)

Status:

USED

class Request(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 143
room: str
username: str
class Response(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 143
room: str
username: str
class aioslsk.protocol.messages.PrivateRoomRevokeOperator

Revoke operator privileges from a member in a private room. This message will also be received by all other members in the room (irrelevant of if they are online or not).

Status:

USED

class Request(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 144
room: str
username: str
class Response(room: str, username: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 144
room: str
username: str
class aioslsk.protocol.messages.PrivateRoomOperatorGranted

Received when granted operator privileges in a private room

Status:

USED

class Response(room: str)
Parameters:

room (str)

MESSAGE_ID: ClassVar[uint32] = 145
room: str
class aioslsk.protocol.messages.PrivateRoomOperatorRevoked

Received when operator privileges in a private room were revoked

Status:

USED

class Response(room: str)
Parameters:

room (str)

MESSAGE_ID: ClassVar[uint32] = 146
room: str
class aioslsk.protocol.messages.PrivateRoomOperators

List of operators for a private room

Status:

USED

class Response(room: str, usernames: list[str])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 148
room: str
usernames: list[str]
class aioslsk.protocol.messages.PrivateChatMessageUsers

Send a private message to a list of users. This message will only be received by users who have added you using the AddUser (Code 5) message first

Status:

USED

class Request(usernames: list[str], message: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 149
usernames: list[str]
message: str
class aioslsk.protocol.messages.EnablePublicChat

Enables public chat, see PublicChatMessage (Code 152)

Status:

USED

class Request
MESSAGE_ID: ClassVar[uint32] = 150
class aioslsk.protocol.messages.DisablePublicChat

Disables public chat, see PublicChatMessage (Code 152)

Status:

USED

class Request
MESSAGE_ID: ClassVar[uint32] = 151
class aioslsk.protocol.messages.PublicChatMessage

When public chat is enabled all messages sent to public rooms will also be sent to us using this message. Use EnablePublicChat (Code 150) and DisablePublicChat (Code 151) to disable or enable receiving these messages.

Status:

USED

class Response(room: str, username: str, message: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 152
room: str
username: str
message: str
class aioslsk.protocol.messages.GetRelatedSearches

Usually this is sent by the client right after the FileSearch (Code 26) message using the same query to retrieve the related searches for that query

Status:

USED

class Request(query: str)
Parameters:

query (str)

MESSAGE_ID: ClassVar[uint32] = 153
query: str
class Response(query: str, related_searches: list[str])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 153
query: str
related_searches: list[str]
class aioslsk.protocol.messages.ExcludedSearchPhrases

Optionally sent by the server after logging on. Search results containing at least one of the phrases (exact match, case insensitive) should be filtered out before being sent.

It is highly recommended to take this filtering into account as not doing so could jeopardize the network

Status:

USED

class Response(phrases: list[str])
Parameters:

phrases (list[str])

MESSAGE_ID: ClassVar[uint32] = 160
phrases: list[str]
class aioslsk.protocol.messages.CannotConnect

Indicates an indirect connection attempt failed

The request message should be sent to the server after we received a ConnectToPeer (Code 18) message but the connection attempt failed

The response will be received from the server if we sent out a ConnectToPeer (Code 18) message but the target user failed to connect to us

Status:

USED

class Request(ticket: int, username: str | None)
Parameters:
  • ticket (int)

  • username (str | None)

MESSAGE_ID: ClassVar[uint32] = 1001
ticket: int
username: str | None
class Response(ticket: int)
Parameters:

ticket (int)

MESSAGE_ID: ClassVar[uint32] = 1001
ticket: int
class aioslsk.protocol.messages.CannotCreateRoom

Sent by the server when attempting to create/join a private room which already exists or the user is not part of

Status:

USED

class Response(room: str)
Parameters:

room (str)

MESSAGE_ID: ClassVar[uint32] = 1003
room: str
class aioslsk.protocol.messages.PeerPierceFirewall

Sent after connection was successfully established in response to a ConnectToPeer (Code 18) message. The ticket used here should be the ticket from that ConnectToPeer (Code 18) message

Status:

USED

class Request(ticket: int)
Parameters:

ticket (int)

MESSAGE_ID: ClassVar[uint8] = 0
ticket: int
class aioslsk.protocol.messages.PeerInit

Sent after direct connection was successfully established (not as a response to a ConnectToPeer (Code 18) received from the server)

The ticket is usually 0 and was filled in with ticket value from the SendConnectTicket (Code 33) message by older versions of the client

Status:

USED

class Request(username: str, typ: str, ticket: int)
Parameters:
MESSAGE_ID: ClassVar[uint8] = 1
username: str
typ: str
ticket: int
class aioslsk.protocol.messages.PeerSharesRequest

Request all shared files/directories from a peer

Status:

USED

class Request(ticket: int | None = None)
Parameters:

ticket (int | None)

MESSAGE_ID: ClassVar[uint32] = 4
ticket: int | None
class aioslsk.protocol.messages.PeerSharesReply

Response to PeerSharesRequest. The response should include empty parent directories.

Status:

USED

class Request(directories: list[aioslsk.protocol.primitives.DirectoryData], unknown: int = 0, locked_directories: list[aioslsk.protocol.primitives.DirectoryData] | None = None)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 5
directories: list[DirectoryData]
unknown: int
locked_directories: list[DirectoryData] | None
serialize(compress=True)

Serializes the current MessageDataClass object and prepends the message length and MESSAGE_ID

In case the message needs to be compressed just override this method in the subclass and simply call the super method with compress=True

Parameters:

compress (bool) – use gzip compression on the message contents

Return type:

bytes

classmethod deserialize(pos, message, decompress=True)

Deserializes the passed message into an object of the current type

In case the message needs to be decompressed just override this method in the subclass and simply call the super method with decompress=True

Parameters:
  • decompress (bool) – use gzip decompression on the message contents

  • pos (int)

  • message (bytes)

Raises:

ValueError – if the message_id found the data does not match the MESSAGE_ID defined in the current class

Returns:

an object of the current class

class aioslsk.protocol.messages.PeerSearchReply

Response to a search request

Status:

USED

class Request(username: str, ticket: int, results: list[aioslsk.protocol.primitives.FileData], has_slots_free: bool, avg_speed: int, queue_size: int, unknown: int | None = 0, locked_results: list[aioslsk.protocol.primitives.FileData] | None = None)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 9
username: str
ticket: int
results: list[FileData]
has_slots_free: bool
avg_speed: int
queue_size: int
unknown: int | None
locked_results: list[FileData] | None
serialize(compress=True)

Serializes the current MessageDataClass object and prepends the message length and MESSAGE_ID

In case the message needs to be compressed just override this method in the subclass and simply call the super method with compress=True

Parameters:

compress (bool) – use gzip compression on the message contents

Return type:

bytes

classmethod deserialize(pos, message, decompress=True)

Deserializes the passed message into an object of the current type

In case the message needs to be decompressed just override this method in the subclass and simply call the super method with decompress=True

Parameters:
  • decompress (bool) – use gzip decompression on the message contents

  • pos (int)

  • message (bytes)

Raises:

ValueError – if the message_id found the data does not match the MESSAGE_ID defined in the current class

Returns:

an object of the current class

class aioslsk.protocol.messages.PeerUserInfoRequest

Request information from the peer

Status:

USED

class Request
MESSAGE_ID: ClassVar[uint32] = 15
class aioslsk.protocol.messages.PeerUserInfoReply

Response to PeerUserInfoRequest (Code 15). Possible values for upload_permissions can be found here

Status:

USED

class Request(description: str, has_picture: bool, picture: bytes | None = None, upload_slots: int = 0, queue_size: int = 0, has_slots_free: bool = False, upload_permissions: int | None = None)
Parameters:
  • description (str)

  • has_picture (bool)

  • picture (bytes | None)

  • upload_slots (int)

  • queue_size (int)

  • has_slots_free (bool)

  • upload_permissions (int | None)

MESSAGE_ID: ClassVar[uint32] = 16
description: str
has_picture: bool
picture: bytes | None
upload_slots: int
queue_size: int
has_slots_free: bool
upload_permissions: int | None
class aioslsk.protocol.messages.PeerDirectoryContentsRequest

Request the contents of a directory

Status:

USED

class Request(ticket: int, directory: str)
Parameters:
  • ticket (int)

  • directory (str)

MESSAGE_ID: ClassVar[uint32] = 36
ticket: int
directory: str
class aioslsk.protocol.messages.PeerDirectoryContentsReply

Reply to PeerDirectoryContentsRequest (Code 36).

Although the returned directories is an array it will only contain one element and will not list files from subdirectories

Status:

USED

class Request(ticket: int, directory: str, directories: list[aioslsk.protocol.primitives.DirectoryData])
Parameters:
MESSAGE_ID: ClassVar[uint32] = 37
ticket: int
directory: str
directories: list[DirectoryData]
serialize(compress=True)

Serializes the current MessageDataClass object and prepends the message length and MESSAGE_ID

In case the message needs to be compressed just override this method in the subclass and simply call the super method with compress=True

Parameters:

compress (bool) – use gzip compression on the message contents

Return type:

bytes

classmethod deserialize(pos, message, decompress=True)

Deserializes the passed message into an object of the current type

In case the message needs to be decompressed just override this method in the subclass and simply call the super method with decompress=True

Parameters:
  • decompress (bool) – use gzip decompression on the message contents

  • pos (int)

  • message (bytes)

Raises:

ValueError – if the message_id found the data does not match the MESSAGE_ID defined in the current class

Returns:

an object of the current class

class aioslsk.protocol.messages.PeerTransferRequest

filesize can be omitted if the direction==1 however a value of 0 can be used in this case as well

Status:

USED

class Request(direction: int, ticket: int, filename: str, filesize: int | None = None)
Parameters:
  • direction (int)

  • ticket (int)

  • filename (str)

  • filesize (int | None)

MESSAGE_ID: ClassVar[uint32] = 40
direction: int
ticket: int
filename: str
filesize: int | None
class aioslsk.protocol.messages.PeerTransferReply

Response message to PeerTransferRequest (Code 40)

Status:

USED

class Request(ticket: int, allowed: bool, filesize: int | None = None, reason: str | None = None)
Parameters:
  • ticket (int)

  • allowed (bool)

  • filesize (int | None)

  • reason (str | None)

MESSAGE_ID: ClassVar[uint32] = 41
ticket: int
allowed: bool
filesize: int | None
reason: str | None
class aioslsk.protocol.messages.PeerTransferQueue

Request to place the provided transfer of filename in the queue

Status:

USED

class Request(filename: str)
Parameters:

filename (str)

MESSAGE_ID: ClassVar[uint32] = 43
filename: str
class aioslsk.protocol.messages.PeerPlaceInQueueReply

Response to PeerPlaceInQueueRequest (Code 51)

Status:

USED

class Request(filename: str, place: int)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 44
filename: str
place: int
class aioslsk.protocol.messages.PeerUploadFailed

Sent when uploading failed

Status:

USED

class Request(filename: str)
Parameters:

filename (str)

MESSAGE_ID: ClassVar[uint32] = 46
filename: str
class aioslsk.protocol.messages.PeerTransferQueueFailed

Sent when placing the transfer in queue failed

Status:

USED

class Request(filename: str, reason: str)
Parameters:
MESSAGE_ID: ClassVar[uint32] = 50
filename: str
reason: str
class aioslsk.protocol.messages.PeerPlaceInQueueRequest

Request the place of the transfer in the queue.

Status:

USED

class Request(filename: str)
Parameters:

filename (str)

MESSAGE_ID: ClassVar[uint32] = 51
filename: str
class aioslsk.protocol.messages.PeerUploadQueueNotification

Deprecated message

Status:

DEPRECATED

class Request
MESSAGE_ID: ClassVar[uint32] = 52
class aioslsk.protocol.messages.DistributedPing

Ping request from the parent. Most clients do not send this.

Status:

DEPRECATED

class Request
MESSAGE_ID: ClassVar[uint8] = 0
class aioslsk.protocol.messages.DistributedInit

Deprecated distributed network related message

Status:

DEPRECATED, DEFUNCT

class Request(unknown1: int, unknown2: int, unknown3: str, port: int)
Parameters:
MESSAGE_ID: ClassVar[uint8] = 1
unknown1: int
unknown2: int
unknown3: str
port: int
class aioslsk.protocol.messages.DistributedSearchRequest

Search request coming from the parent

Status:

USED

class Request(unknown: int, username: str, ticket: int, query: str)
Parameters:
MESSAGE_ID: ClassVar[uint8] = 3
unknown: int
username: str
ticket: int
query: str
class aioslsk.protocol.messages.DistributedBranchLevel

Distributed branch level

Status:

USED

class Request(level: int)
Parameters:

level (int)

MESSAGE_ID: ClassVar[uint8] = 4
level: int
class aioslsk.protocol.messages.DistributedBranchRoot

Distributed branch root

Status:

USED

class Request(username: str)
Parameters:

username (str)

MESSAGE_ID: ClassVar[uint8] = 5
username: str
class aioslsk.protocol.messages.DistributedChildDepth

Used by SoulSeek NS and still passed on by SoulSeekQt, sent to the parent upon connecting to that parent (although unclear what happens when a peer attaches to another parent while already having children). The parent should increase the depth by 1 until it reaches the branch root, which should increase by 1 and send it to the server as a ChildDepth (Code 129) message.

Status:

DEPRECATED

class Request(depth: int)
Parameters:

depth (int)

MESSAGE_ID: ClassVar[uint8] = 7
depth: int
class aioslsk.protocol.messages.DistributedServerSearchRequest

The branch root should just pass the ServerSearchRequest as-is to all its children; meaning we will get this message if we are at level 1. If we get this message we should translate it to a proper DistributedSearchRequest message.

This message might need to be revisited, as it’s only currently used for parsing

Status:

USED

class Request(distributed_code: int, unknown: int, username: str, ticket: int, query: str)
Parameters:
  • distributed_code (int)

  • unknown (int)

  • username (str)

  • ticket (int)

  • query (str)

MESSAGE_ID: ClassVar[uint32] = 93
distributed_code: int
unknown: int
username: str
ticket: int
query: str