Go to file
2023-07-04 21:07:17 -04:00
extractor Add VOD preview support 2023-07-04 20:57:38 -04:00
routes Add VOD preview support 2023-07-04 20:57:38 -04:00
.woodpecker.yml Fix repo 2023-07-04 21:07:17 -04:00
docker-compose.yml Add docker support 2023-06-07 17:00:58 -04:00
Dockerfile Change golang version 2023-07-04 21:03:12 -04:00
go.mod add login with display name 2023-06-19 22:59:34 -04:00
go.sum add login with display name 2023-06-19 22:59:34 -04:00
main.go Complete translation support 2023-07-03 19:09:39 -04:00
README.md Update readme 2023-07-03 15:28:44 -04:00
tests.yml Fix tests 2023-05-31 08:14:08 -04:00

safetwitch-backend

The backend for SafeTwitch

Documentation

API Endpoints

Disclaimer

Every endpoint can return a 500 status code, and it follows this schema:

{
  status: "error",
  data: "Error message..."
}

/api/users/:username

GET - :username is any streamer Gets a specific twitch streamer

Responses

200

The request was successful, returns data of type Streamer Example:

{
  "status": "ok",
  "data": {
    "username": "filian",
    "about": "Welcome to my Vtuber alpha! 3D streaming and variety games! Join the discord! n_n",
    "pfp": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9qdHZfdXNlcl9waWN0dXJlcy9mNzVkNDEwMy1hMjY1LTRlMjEtODhiNS00NDc0NWZjMWJmNDQtcHJvZmlsZV9pbWFnZS0zMDB4MzAwLnBuZw",
    "banner": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9qdHZfdXNlcl9waWN0dXJlcy9kMjY2OTZlMC1hYjJhLTRlZjEtYTI3Ni0wZmZjZWM5NmM3NzYtcHJvZmlsZV9iYW5uZXItNDgwLnBuZw==",
    "followers": 579463,
    "socials": [
      {
        "type": "discord",
        "name": "discord.gg/filian",
        "link": "https://discord.gg/filian"
      },
      {
        "type": "twitter",
        "name": "twitter.com/filianIsLost",
        "link": "https://twitter.com/filianIsLost"
      }
    ],
    "isLive": false,
    "isPartner": true,
    "colorHex": "#8040E0",
    "id": 198633200,
    "stream": null
  }
}
404

The streamer was not found

/api/discover

GET Gets the discover page of twitch, a list of categories

Responses

200

The request was successful, returns a CategoryData[] Example:

{
  "status": "ok",
  "data": [
    {
      "name": "Just Chatting",
      "displayName": "Just Chatting",
      "viewers": 510365,
      "tags": [
        "IRL"
      ],
      "createdAt": null,
      "cursor": "eyJzIjoxLCJkIjpmYWxzZSwidCI6dHJ1ZX0=",
      "image": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC90dHYtYm94YXJ0LzUwOTY1OC0yODV4MzgwLmpwZw"
    },
    ...
}

/api/discover/:game

GET - :game is a name of a twitch category Gets a specific twitch category

Responses

200

The server found the category, returns data of type CategoryPreview[] Example:

{
  "status": "ok",
  "data": {
    "name": "Just Chatting",
    "cover": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC90dHYtYm94YXJ0LzUwOTY1OC0xNDR4MTkyLmpwZw",
    "description": null,
    "viewers": 533593,
    "followers": 23147702,
    "tags": [
      "IRL"
    ],
    "streams": [
      {
        "title": "CIERRE DEL MERCATO DE LA KINGS LEAGUE | ÚLTIMO DÍA DE MERCATO | ÚLTIMOS CLAUSULAZOS | SE VIENEN LLOROS",
        "viewers": 60897,
        "preview": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9wcmV2aWV3cy10dHYvbGl2ZV91c2VyX2liYWktNDQweDI0OC5qcGc",
        "tags": [
          "Español",
          "KOI",
          "KingsLeague"
        ],
        "cursor": "eyJzIjo2MDg5Ny40NDU3NDY0NjY4NSwiZCI6ZmFsc2UsInQiOnRydWV9",
        "streamer": {
          "name": "ibai",
          "pfp": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9qdHZfdXNlcl9waWN0dXJlcy81NzQyMjhiZS0wMWVmLTRlYWItYmMwZS1hNGY2YjY4YmVkYmEtcHJvZmlsZV9pbWFnZS01MHg1MC5wbmc",
          "colorHex": "2A2B62"
        }
      },
      ...
    ]
  }
}
404

The category was not found

/api/badges?streamerName=NAME

GET Gets global twitch chat badges

streamerName query is optional, if given it will only provide the badges for that streamer.

Responses

200

Server retrieved the badges, returns type Badge[] Example:

{
  "status": "ok",
  "data": [
    {
      "id": "getting-over-it_2;1;",
      "setId": "getting-over-it_2",
      "title": "Getting Over It",
      "version": "1",
      "images": {
        "image1x": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9iYWRnZXMvdjEvYmI2MjBiNDItZTBlMS00MzczLTkyOGUtZDRhNzMyZjk5Y2NiLzE",
        "image2x": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9iYWRnZXMvdjEvYmI2MjBiNDItZTBlMS00MzczLTkyOGUtZDRhNzMyZjk5Y2NiLzI",
        "image4x": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9iYWRnZXMvdjEvYmI2MjBiNDItZTBlMS00MzczLTkyOGUtZDRhNzMyZjk5Y2NiLzM"
      }
    },
    ...
  ]
}

/api/search?query=SEARCHQUERY

GET - SEARCHQUERY is any string Searches for categories, streamers, tags, and live streamers. Returns data of type SearchResult

Responses

200

The server found the search data, returns: Example:

{
  "status": "ok",
  "data": {
    "channels": [
      {
        "username": "filian",
        "followers": 580066,
        "isLive": false,
        "about": "Welcome to my Vtuber alpha! 3D streaming and variety games! Join the discord! n_n",
        "pfp": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9qdHZfdXNlcl9waWN0dXJlcy9mNzVkNDEwMy1hMjY1LTRlMjEtODhiNS00NDc0NWZjMWJmNDQtcHJvZmlsZV9pbWFnZS0xNTB4MTUwLnBuZw",
        "isPartner": null,
        "colorHex": "#fff",
        "id": 198633200
      },
      ...
    ],
    "categories": [
      {
        "name": "Lilian: The beginning of the end",
        "displayName": "Lilian: The beginning of the end",
        "viewers": null,
        "tags": [
          ""
        ],
        "image": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9wcmV2aWV3cy10dHYvbGl2ZV91c2VyX2VsbHllbi0xMjgweDcyMC5qcGc"
      }
    ],
    "relatedChannels": [
      {
        "username": "EllyEN",
        "about": "HI I'M ELLY❗❗ I'm a cwiminal Vtuber who loves cars, boba, games, & getting into trouble~❗❗",
        "pfp": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9qdHZfdXNlcl9waWN0dXJlcy8xZjJjNmQ2Yi1hZmZmLTQ4NGYtYTdjMy1iNGRhZTU2MzllOGMtcHJvZmlsZV9pbWFnZS0zMDB4MzAwLmpwZWc",
        "followers": 100538,
        "socials": [
          {
            "type": "twitter",
            "name": "Twitter",
            "link": "https://www.twitter.com/EllyVtuber"
          },
          {
            "type": "tiktok",
            "name": "Tiktok",
            "link": "https://www.tiktok.com/@ellyvtuber"
          },
          {
            "type": "youtube",
            "name": "YouTube",
            "link": "https://www.youtube.com/EllyEN"
          }
        ],
        "isLive": true,
        "isPartner": true,
        "colorHex": "#FA2929",
        "id": 141045387,
        "stream": {
          "title": "little bit of valheim THEN FFXIV! 🌱 I'M OBSESSED LOL | SUBATHON PART 2 DAY 16 | #AlienwareHive !GamerSupps",
          "topic": "I'm Only Sleeping",
          "startedAt": 1682363001000,
          "tags": [
            "LGBTQIA",
            "NoBackseating",
            "Vtuber",
            "ENVtuber",
            "English"
          ],
          "viewers": 654,
          "preview": "https://safetwitch.dragongoose.us/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9wcmV2aWV3cy10dHYvbGl2ZV91c2VyX2VsbHllbi0xMjgweDcyMC5qcGc"
        }
      },
      ...
    ],
    "channelsWithTag": []
  }
}

Proxying Endpoints

/proxy/img/:base64Url

GET Proxies an image through the server :base64Url can be any base64 encoded Url

Responses

200

Server returns the requested image

404

The requested image was invalid

/proxy/stream/:username/hls.m3u8

GET Gets the m3u8 manifest for a streamer. This manifest will contain all stream qualities if they are live

Responses

200

Returns the manifest

400

The streamer is not live Example:

{
  "status": "error",
  "data": "Streamer is not live"
}

/proxy/stream/sub/:encodedUrl

GET Returns the m3u8 manifest for a specific quality under the master manifest

200

Returns the manifest file

/proxy/stream/segment/:encodedUrl

GET Gets a segment from one of the quality's manifest file. This is the actual video thats displayed on your screen

200

Returns the stream segment, HLS streaming.