extractor | ||
routes | ||
.gitignore | ||
.woodpecker.yml | ||
docker-compose.yml | ||
Dockerfile | ||
go.mod | ||
go.sum | ||
LICENSE | ||
main.go | ||
nginx.conf | ||
README.md | ||
tests.yml |
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