{"id":29182464,"url":"https://github.com/jxsl13/twapi","last_synced_at":"2025-07-01T20:06:01.189Z","repository":{"id":56243263,"uuid":"234808452","full_name":"jxsl13/twapi","owner":"jxsl13","description":"the twapi package is a framework to interact with Teeworlds servers and masterservers. It is slowly being developed to allow working with demos and maps as well as simulating a teeworlds client. Currently interacting with a server's external console(econ) and acting like the server browser(fetching server infos) is supported.","archived":false,"fork":false,"pushed_at":"2024-07-05T20:03:17.000Z","size":218,"stargazers_count":3,"open_issues_count":3,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-07-06T01:05:40.099Z","etag":null,"topics":["framework","go","golang","module","package","teeworlds"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jxsl13.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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}},"created_at":"2020-01-18T22:49:20.000Z","updated_at":"2024-07-05T20:03:20.000Z","dependencies_parsed_at":"2022-08-15T15:20:30.581Z","dependency_job_id":"2acf829a-8013-40b8-b5bd-02157c4ada11","html_url":"https://github.com/jxsl13/twapi","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/jxsl13/twapi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jxsl13%2Ftwapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jxsl13%2Ftwapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jxsl13%2Ftwapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jxsl13%2Ftwapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jxsl13","download_url":"https://codeload.github.com/jxsl13/twapi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jxsl13%2Ftwapi/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263029214,"owners_count":23402354,"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","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":["framework","go","golang","module","package","teeworlds"],"created_at":"2025-07-01T20:06:00.472Z","updated_at":"2025-07-01T20:06:01.172Z","avatar_url":"https://github.com/jxsl13.png","language":"Go","readme":"# Teeworlds API written in Go\n\n## ![Test](https://github.com/jxsl13/twapi/workflows/Test/badge.svg) ![Go Report](https://goreportcard.com/badge/github.com/jxsl13/twapi) [![GoDoc](https://godoc.org/github.com/jxsl13/twapi?status.svg)](https://godoc.org/github.com/jxsl13/twapi) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![codecov](https://codecov.io/gh/jxsl13/twapi/branch/master/graph/badge.svg)](https://codecov.io/gh/jxsl13/twapi) [![Total alerts](https://img.shields.io/lgtm/alerts/g/jxsl13/twapi.svg?logo=lgtm\u0026logoWidth=18)](https://lgtm.com/projects/g/jxsl13/twapi/alerts/) [![codebeat badge](https://codebeat.co/badges/4b5339f2-93d6-4242-96a6-0372e66a7aaf)](https://codebeat.co/projects/github-com-jxsl13-twapi-master) [![Sourcegraph](https://sourcegraph.com/github.com/jxsl13/twapi/-/badge.svg)](https://sourcegraph.com/github.com/jxsl13/twapi?badge) [![deepsource](https://static.deepsource.io/deepsource-badge-light.svg)](https://deepsource.io/gh/jxsl13/twapi/)\n\nCurrently this supports only the server browser api.\nIt is possible to retrieve data from the masterservers as well as the server information from the game servers.\n\nIn order to download the latest released version, execute:\n\n```shell\ngo get github.com/jxsl13/twapi@latest\n```\n\nIn order to download the latest development version, execute:\n\n```shell\ngo get github.com/jxsl13/twapi@master\n```\n\n## Stable packages\n\n- browser\n- compression\n- config\n- econ\n\n## Unstable packages\n\n- network\n- protocol\n\n\n### Example - High Level Abstraction(Open for optimizing suggestions)\n\n```Go\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com/jxsl13/twapi/browser\"\n)\n\nfunc main() {\n    // fetch all server infos (that respond within 16 seconds)\n    // if no servers responded, this list will be empty.\n    infos, err := browser.ServerInfos()\n    if err != nil {\n        panic(err)\n    }\n    for _, info := range infos {\n        fmt.Println(info)\n    }\n\n    // fetches the specified server's players, server name, etc.\n    // if no answer is received within 16 seconds, this function returns\n    // an error\n    infos, err := browser.GetServerInfosOf(\"89.163.148.121:8305\")\n    if err != nil {\n        panic(err)\n    } else {\n        fmt.Println(infos[0])\n    }\n}\n```\n\n### Example - Slightly Higher Level Abstraction - Retrieve Serverlist\n\n```Go\npackage main\n\nimport (\n    \"fmt\"\n    \"net\"\n    \"time\"\n\n    \"github.com/jxsl13/twapi/browser\"\n)\n\nfunc main() {\n    addr, err := net.ResolveUDPAddr(\"udp\", \"master1.teeworlds.com:8283\")\n    if err != nil {\n        panic(err)\n    }\n\n    conn, err := net.DialUDP(\"udp\", nil, addr)\n    if err != nil {\n        panic(err)\n    }\n    defer conn.Close()\n\n    err = browser.RequestToken(conn)\n    if err != nil {\n        panic(err)\n    }\n\n    conn.SetDeadline(time.Now().Add(5 * time.Second))\n\n    buffer := [1500]byte{}\n    bufSlice := buffer[:]\n\n    read, err := conn.Read(bufSlice)\n    if err != nil {\n        panic(err)\n    }\n    bufSlice = bufSlice[:read]\n    fmt.Printf(\"read: %d bytes from %s\\n\", read, conn.RemoteAddr().String())\n\n    // create toke from response\n    token, err := browser.ParseToken(bufSlice)\n    if err != nil {\n        panic(err)\n    }\n    // reset slice\n    bufSlice = bufSlice[:1500]\n\n    err = browser.Request(\"serverlist\", token, conn)\n    if err != nil {\n        panic(err)\n    }\n\n    // timeout after 5 secods\n    // should not return an error\n    conn.SetDeadline(time.Now().Add(5 * time.Second))\n\n    // wait for response or time out\n    read, err = conn.Read(bufSlice)\n    bufSlice = bufSlice[:read]\n    fmt.Printf(\"read: %d bytes from %s\\n\", read, conn.RemoteAddr().String())\n\n    serverList, err := browser.ParseServerList(bufSlice)\n    if err != nil {\n        panic(err)\n    }\n\n    for _, server := range serverList {\n        fmt.Printf(\"Server: %s\\n\", server.String())\n    }\n}\n\n```\n\n### Example - Low Level - Retrieve Serverlist\n\n```Go\npackage main\n\nimport (\n    \"fmt\"\n    \"net\"\n    \"time\"\n\n    \"github.com/jxsl13/twapi/browser\"\n)\n\nfunc main() {\n    addr, err := net.ResolveUDPAddr(\"udp\", \"master1.teeworlds.com:8283\")\n    if err != nil {\n        panic(err)\n    }\n\n    conn, err := net.DialUDP(\"udp\", nil, addr)\n    if err != nil {\n        panic(err)\n    }\n    defer conn.Close()\n\n    // token request packet\n    tokenReq := browser.NewTokenRequestPacket()\n\n    // send request\n    written, err := conn.Write(tokenReq)\n    if err != nil {\n        panic(err)\n    }\n    fmt.Printf(\"written: %d bytes to %s\\n\", written, conn.RemoteAddr().String())\n\n    conn.SetDeadline(time.Now().Add(5 * time.Second))\n\n    buffer := [1500]byte{}\n    bufSlice := buffer[:]\n\n    read, err := conn.Read(bufSlice)\n    if err != nil {\n        panic(err)\n    }\n    bufSlice = bufSlice[:read]\n    fmt.Printf(\"read: %d bytes from %s\\n\", read, conn.RemoteAddr().String())\n\n    // create toke from response\n    token, err := browser.ParseToken(bufSlice)\n    if err != nil {\n        panic(err)\n    }\n    // reset slice\n    bufSlice = bufSlice[:1500]\n\n    // create a new request from token\n    serverListReq, err := browser.NewServerListRequestPacket(token)\n\n    // Send server list request\n    written, err = conn.Write(serverListReq)\n    if err != nil {\n        panic(err)\n    }\n    fmt.Printf(\"written: %d bytes to %s\\n\", written, conn.RemoteAddr().String())\n\n    // timeout after 5 secods\n    // should not return an error\n    conn.SetDeadline(time.Now().Add(5 * time.Second))\n\n    // wait for response or time out\n    read, err = conn.Read(bufSlice)\n    bufSlice = bufSlice[:read]\n    fmt.Printf(\"read: %d bytes from %s\\n\", read, conn.RemoteAddr().String())\n\n    serverList, err := browser.ParseServerList(bufSlice)\n    if err != nil {\n        panic(err)\n    }\n\n    for _, server := range serverList {\n        fmt.Printf(\"Server: %s\\n\", server.String())\n    }\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjxsl13%2Ftwapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjxsl13%2Ftwapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjxsl13%2Ftwapi/lists"}