{"id":31480751,"url":"https://github.com/bh90210/soul","last_synced_at":"2026-02-25T17:08:57.252Z","repository":{"id":277521638,"uuid":"932506360","full_name":"bh90210/soul","owner":"bh90210","description":"A Go implementation of the Soulseek protocol.","archived":false,"fork":false,"pushed_at":"2025-04-20T17:03:50.000Z","size":1202,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-04-20T18:23:03.244Z","etag":null,"topics":["client","go","golang","library","module","package","protocol","soulseek"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"a-cordier/goose","license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bh90210.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-02-14T02:47:45.000Z","updated_at":"2025-04-20T17:03:54.000Z","dependencies_parsed_at":"2025-03-21T17:33:17.179Z","dependency_job_id":null,"html_url":"https://github.com/bh90210/soul","commit_stats":null,"previous_names":["bh90210/soul"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/bh90210/soul","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bh90210%2Fsoul","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bh90210%2Fsoul/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bh90210%2Fsoul/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bh90210%2Fsoul/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bh90210","download_url":"https://codeload.github.com/bh90210/soul/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bh90210%2Fsoul/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277963190,"owners_count":25906473,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-02T02:00:08.890Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["client","go","golang","library","module","package","protocol","soulseek"],"created_at":"2025-10-02T05:50:09.757Z","updated_at":"2025-10-02T05:50:10.895Z","avatar_url":"https://github.com/bh90210.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Soul\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/bh90210/soul.svg)](https://pkg.go.dev/github.com/bh90210/soul)\n[![codecov](https://codecov.io/gh/bh90210/soul/graph/badge.svg?token=1VXJR0HV3C)](https://codecov.io/gh/bh90210/soul)\n[![Go Report](https://goreportcard.com/badge/github.com/bh90210/soul)](https://goreportcard.com/report/github.com/bh90210/soul)\n![](https://github.com/bh90210/soul/actions/workflows/tests.yaml/badge.svg)\n\nA Go implementation of the SoulSeek protocol.\n\n# Protocol Specification\n\nThis implementation and naming convention is based on the [Nicotine+](https://nicotine-plus.github.io/nicotine-plus/doc/SLSKPROTOCOL.html) documentation but [aioslsk](https://aioslsk.readthedocs.io) was also consulted regularly too.\n\nThe library offers complete coverage of all server, peer, distributed and file messages' serialization and deserialization.\n\nOn top there is a client package with file sharing capabilities (global search/download/upload API/distributed network participation, obfuscation) but no room searches, direct peer searches for directories or wishlist (PRs are welcome* :)\n\n_* Even though server messages facilitating chat functionality are present in the library for completeness sake, consider not using them as they are unencrypted in the open._\n\n# How to use\n\nSoulSeek protocol has 4 different connection types. Server, Peer, File and Distributed. For each connection type there is a unique set of messages the server and peers expect from us and vice versa.\n\nFor a simple search \u0026 download example see `/cmd/search-download`.\n\n## Low level\n\nLow level code facilitating the serialization and deserialization of each connection type and message code lives under the `server`, `peer`, `file` and `distributed` packages respectively. Each package offers a pair of Read/Write functions and the complete in use message codes (I did not implement obsolete protocol message codes.)\n\nEach message is a struct, for example to make use of the server connection Login message code you need to:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\n\t\"github.com/bh90210/soul/server\"\n)\n\nfunc main() {\n\t// Open a connection with the server.\n\tconn, _ := net.Dial(\"tcp\", \"server.slsknet.org:2242\")\n\n\t// Send the login message.\n\tserver.Write(conn, \u0026server.Login{Username: \"username\", Password: \"password\"})\n\n\t// Receive the server response.\n\tres, _, code, _ := server.Read(conn)\n\tswitch code {\n\tcase server.CodeLogin:\n\t\tlogin := new(server.Login)\n\t\tlogin.Deserialize(res)\n\n\t\tfmt.Println(login.Greet, login.IP, login.Sum)\n\t...\n\t}\n}\n\n```\n\n## Client\n\nTo successfully make use of the network, you will need certain procedures involving multiple types of connections at once. Under `client` package you will find the most common actions a client will probably make (login, search, download, participation in the distributed network and API for responding to search requests and uploads.) If like me your goal is to make a CLI, preferably one that will run on a server rather than a desktop and used as a library inside other Go software, then client code in the `client` package can be potentially useful as is, albeit incomplete (no file indexing/management, no database for state etc, yes PRs are still very welcome!)\n\n### Client \u0026 Peer\n\nThe methods of _Client_ and _Peer_ structs are purposefully small and simple. Both provide a `Relays` field that can produce listeners for all incoming messages. Think of them as routers for incoming messages. This can potentially be your point of departure. Use _Client_ and _Peer_ and come up with your own state solution. Except bug fixes the intention is for those structs/API to remain dormant.\n\n### State\n\n_State_ struct is where the \"business logic\" lives. Besides the public methods it provides, once connected to SoulSeek in the background it will take care of the distributed network and responding to peer and server requests.\n\n## Tests\n\nThe library is covered via unit and integration tests. Running the `-short` test suite will result in running the unit tests. The integration tests need [Soulfind](https://github.com/soulfind-dev/soulfind) (check the `/testdata/Dockerfile.soulfind` for more) running. For convenience you can just `docker run --rm -it -p 2242:2242 ghcr.io/bh90210/soul:latest` and it will spin a Soulfind enabled container.\n\nUnits cover all connection types' serialization/deserialization and internal packages.\n\nThe `client` package contains the integration tests.\n\n```bash\ngo test -parallel 100 --cover -covermode=atomic -coverpkg=./... ./... -tags=testdata\n```\n\n# Acknowledgements\n\nFork of [goose](https://github.com/a-cordier/goose). Thanks to `a-cordier` for starting the effort as this is usually the hardest part.\n\nIf this library was not what you were looking for consider checking out [spotseek](https://github.com/boristopalov/spotseek).\n\nShout-out to [slskd](https://github.com/slskd/slskd), it immensely helped with testing the peer implementation.\n\n# TODO\n- [ ] Finish upload.\n- [ ] Finish directory/folder peer responses.\n- [ ] Client integration tests (login-search-download -\u003e login-respond to search-upload, all server messages.)\n- [ ] Search code for outstanding TODOs.\n- [ ] Release v1.2.0.\n- [ ] Rate limits for peers: (re-)downloads, requests, connections.\n- [ ] Release v1.2.1.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbh90210%2Fsoul","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbh90210%2Fsoul","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbh90210%2Fsoul/lists"}