Go to file
dragongoose 91dda1ceb5
Consistency
2024-02-06 12:02:50 -05:00
extractor Consistency 2024-02-06 12:02:50 -05:00
routes Improve following streamer data fetching 2024-02-06 12:02:28 -05:00
.gitignore Ignore tmp directory (air) 2023-07-05 11:33:43 -04:00
.woodpecker.yml Update '.woodpecker.yml' 2023-07-10 20:15:50 +00:00
Dockerfile Change golang version 2023-07-04 21:03:12 -04:00
LICENSE Add 'LICENSE' 2023-07-14 20:49:33 +00:00
README.md Update 'README.md' 2023-07-20 18:39:26 +00:00
docker-compose.yml harden docker 2023-07-15 19:23:47 +00: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 Update permissions 2023-09-27 19:27:51 -04:00
nginx.conf Create backend-nginx.conf example 2023-07-15 19:24:46 +00: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..."
}

https://streamapi.whateveritworks.org/api/users/xqc

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

https://streamapi.whateveritworks.org/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"
    },
    ...
}

https://streamapi.whateveritworks.org/api/discover/Grand Theft Auto V

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

https://streamapi.whateveritworks.org/api/badges?streamerName=xqc

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"
      }
    },
    ...
  ]
}

https://streamapi.whateveritworks.org/api/search?query=xqc

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": []
  }
}

https://streamapi.whateveritworks.org/api/vods/1872917122

GET - vodID is any id of a vod
Gets metadata of a VOD, returns Video

Responses

200

The server found the VOD Example:

{
  "status": "ok",
  "data": {
    "type": "vod",
    "preview": "http://localhost:8080/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9jZl92b2RzL2QxbTdqZm9lOXpkYzFqL2JjODQyZGVhNmY2MWVlODM5MzNkX2ZpbGlhbl80MTY0NzEwMjg3M18xNjg5NDU4NzA2Ly90aHVtYi90aHVtYjAtOTB4NjAuanBn",
    "game": {
      "image": "http://localhost:8080/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC90dHYtYm94YXJ0LzUwOTY1OC17d2lkdGh9eHtoZWlnaHR9LmpwZw==",
      "id": "509658",
      "name": "Just Chatting",
      "displayName": "Just Chatting"
    },
    "duration": 17520,
    "title": "🦂 YOU LAUGH, YOU LOSE today! Eating a Scorpion today. This is it. After 10 laughs it's guaranteed no matter what. Wait I hear something beh",
    "publishedAt": "2023-07-15T22:05:11Z",
    "views": 81357,
    "streamer": {
      "username": "filian",
      "login": "filian",
      "about": "Welcome to my Vtuber alpha! 3D streaming and variety games! Join the discord! n_n",
      "pfp": "http://localhost:8080/proxy/img/aHR0cHM6Ly9zdGF0aWMtY2RuLmp0dm53Lm5ldC9qdHZfdXNlcl9waWN0dXJlcy9mNzVkNDEwMy1hMjY1LTRlMjEtODhiNS00NDc0NWZjMWJmNDQtcHJvZmlsZV9pbWFnZS0zMDB4MzAwLnBuZw==",
      "banner": null,
      "followers": 656278,
      "socials": [
        {
          "type": "discord",
          "name": "discord.gg/filian",
          "url": "https://discord.gg/filian"
        },
        {
          "type": "twitter",
          "name": "twitter.com/filianIsLost",
          "url": "https://twitter.com/filianIsLost"
        }
      ],
      "isLive": false,
      "isPartner": true,
      "colorHex": "8040E0",
      "id": "198633200"
    },
    "id": "1872917122"
  }
}

https://streamapi.whateveritworks.org/api/vods/1872917122/10

GET - vodID is any id of a vod, offset is the seconds into the vod Gets comments at that second of a song, returns VodComment[]

Responses

200

The server found the VOD Example:

{
  "status": "ok",
  "data": [
    {
      "message": "Pog",
      "messager": {
        "name": "equiro",
        "login": "equiro",
        "pfp": "",
        "colorHex": "#FF4500"
      },
      "offset": 6,
      "cursor": "eyJpZCI6ImMwM2M0Mzg2LTRhMTUtNGVlMC05NGQ2LTMyYWExZTZjYjFhYSIsImhrIjoiYnJvYWRjYXN0OjQxNjQ3MTAyODczIiwic2siOiJBQUFBQmpwT0Z3QVhjaW5GZjk5a0FBIn0",
      "badges": []
    }...
  ]
}

Proxying Endpoints

https://streamapi.whateveritworks.org/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

https://streamapi.whateveritworks.org/proxy/stream/xqc/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"
}

https://streamapi.whateveritworks.org/proxy/stream/sub/encodedUrl

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

200

Returns the manifest file

https://streamapi.whateveritworks.org/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.

https://streamapi.whateveritworks.org//proxy/vod/:vodID/video.m3u8

GET
Gets the master manifest for a VOD

200

Returns the manifest file

https://streamapi.whateveritworks.org//proxy/vod/sub/:encodedUrl/video.m3u8

GET
Gets the sub manifest for a VOD
encodedUrl is the url to the sub manifiest from twitch encoded in base64

200

Returns the manifest file

https://streamapi.whateveritworks.org//proxy/vod/sub/:encodedUrl/:segment

GET
Gets the sub manifest for a VOD
encodedUrl is the url to the sub manifiest from twitch encoded in base64

segment is the segment from the playlist file, etc 0.ts, 1.ts

200

Returns the manifest file