From 492cd515c6a089fc18445be769694030420e600a Mon Sep 17 00:00:00 2001 From: Luxferre Date: Sat, 14 Sep 2024 23:42:47 +0300 Subject: [PATCH] owncast support draft --- .gitignore | 1 + config.json | 5 ++++- src/Makefile | 2 +- src/server.go | 4 ++++ src/youtube.go | 32 ++++++++++++++++---------------- 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index f07be17..b91896c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.dylib out/ auth/twitch-token.txt +auth/oc-token.txt go.work go.work.sum .env diff --git a/config.json b/config.json index 1d1b54d..ac041fc 100644 --- a/config.json +++ b/config.json @@ -8,5 +8,8 @@ "yt_backend_enabled": false, "yt_api_root_url": "https://yt.lemnoslife.com/noKey", "yt_api_poll_timeout": 3, - "yt_channel": "@foxyshadow" + "yt_channel": "@foxyshadow", + "oc_backend_enabled": false, + "oc_server": "https://streams.luxferre.top", + "oc_api_poll_timeout": 2 } diff --git a/src/Makefile b/src/Makefile index 84c912d..7a18819 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,7 @@ LDFLAGS = -s -w LDFLAGS_WIN = -H windowsgui -s -w GOFLAGS = -trimpath -SOURCES = server.go twitch.go youtube.go +SOURCES = server.go twitch.go youtube.go owncast.go BIN = streamgoose unix: diff --git a/src/server.go b/src/server.go index fa7cdfd..f657898 100644 --- a/src/server.go +++ b/src/server.go @@ -164,6 +164,10 @@ func main() { go youtube_run(config) /* start the YouTube backend */ } + if _, ok := config["oc_backend_enabled"]; ok && config["oc_backend_enabled"].(bool) == true { + go owncast_run(config) /* start the Owncast backend */ + } + /* start the GUI */ debug := false if _, ok := config["debug"]; ok && config["debug"].(bool) == true { diff --git a/src/youtube.go b/src/youtube.go index 02933e8..25998a2 100644 --- a/src/youtube.go +++ b/src/youtube.go @@ -16,16 +16,16 @@ import ( ) /* global API root URL placeholder */ -var API_ROOT string +var YT_API_ROOT string -const ID_CACHE_LIMIT = 1000 +const YT_ID_CACHE_LIMIT = 1000 /* global message ID cache */ -var msg_id_cache []string +var yt_msg_id_cache []string /* API request helper function */ -func api_get(endpoint string) map[string]interface{} { - url := API_ROOT + endpoint /* get full URL */ +func yt_api_get(endpoint string) map[string]interface{} { + url := YT_API_ROOT + endpoint /* get full URL */ req, err := http.NewRequest("GET", url, nil) req.Header.Set("Accept", "application/json; charset=utf-8") @@ -52,7 +52,7 @@ func api_get(endpoint string) map[string]interface{} { func yt_process_message(rawmsg map[string]interface{}) { /* if the message came from a real user, this is the one we should process */ if rawmsg["kind"] == "youtube#liveChatMessage" && rawmsg["snippet"].(map[string]interface{})["type"] == "textMessageEvent" { - if !slices.Contains(msg_id_cache, rawmsg["id"].(string)) { /* we have a fresh message here */ + if !slices.Contains(yt_msg_id_cache, rawmsg["id"].(string)) { /* we have a fresh message here */ snip := rawmsg["snippet"].(map[string]interface{}) author := rawmsg["authorDetails"].(map[string]interface{}) @@ -97,10 +97,10 @@ func yt_process_message(rawmsg map[string]interface{}) { message_transport <- out_message /* update the ID cache */ - msg_id_cache = append(msg_id_cache, rawmsg["id"].(string)) - cachelen := len(msg_id_cache) - if cachelen > ID_CACHE_LIMIT { /* trim the excess */ - msg_id_cache = msg_id_cache[cachelen-ID_CACHE_LIMIT:cachelen] + yt_msg_id_cache = append(yt_msg_id_cache, rawmsg["id"].(string)) + cachelen := len(yt_msg_id_cache) + if cachelen > YT_ID_CACHE_LIMIT { /* trim the excess */ + yt_msg_id_cache = yt_msg_id_cache[cachelen-YT_ID_CACHE_LIMIT:cachelen] } } @@ -112,7 +112,7 @@ func youtube_run(config map[string]interface{}) { API_POLL_TIMEOUT := 1 /* polling timeout in seconds */ if _, ok := config["yt_api_root_url"]; ok { - API_ROOT = config["yt_api_root_url"].(string) + YT_API_ROOT = config["yt_api_root_url"].(string) } else { log.Fatal("API Root URL missing in config!") } @@ -126,7 +126,7 @@ func youtube_run(config map[string]interface{}) { video_id = config["yt_video_id"].(string) } else { /* no video ID supplied, begin with the usual flow */ /* first, get channel ID by YouTube handle */ - channel_id_data := api_get("/channels?part=id&forHandle=" + config["yt_channel"].(string)) + channel_id_data := yt_api_get("/channels?part=id&forHandle=" + config["yt_channel"].(string)) channel_id := "" if _, ok := channel_id_data["items"]; ok && len(channel_id_data["items"].([]interface{})) > 0 { channel_id = channel_id_data["items"].([]interface{})[0].(map[string]interface{})["id"].(string) @@ -135,7 +135,7 @@ func youtube_run(config map[string]interface{}) { } /* then, get live broadcast video ID by channel ID */ - video_id_data := api_get("/search?part=snippet&eventType=live&type=video&channelId=" + channel_id) + video_id_data := yt_api_get("/search?part=snippet&eventType=live&type=video&channelId=" + channel_id) if _, ok := video_id_data["items"]; ok && len(video_id_data["items"].([]interface{})) > 0 { id_desc := video_id_data["items"].([]interface{})[0].(map[string]interface{})["id"] video_id = id_desc.(map[string]interface{})["videoId"].(string) @@ -146,7 +146,7 @@ func youtube_run(config map[string]interface{}) { /* now, get active live chat ID by broadcast video ID */ chat_id := "" - chat_id_data := api_get("/videos?part=liveStreamingDetails&id=" + video_id) + chat_id_data := yt_api_get("/videos?part=liveStreamingDetails&id=" + video_id) if _, ok := chat_id_data["items"]; ok && len(chat_id_data["items"].([]interface{})) > 0 { details := chat_id_data["items"].([]interface{})[0].(map[string]interface{})["liveStreamingDetails"] chat_id = details.(map[string]interface{})["activeLiveChatId"].(string) @@ -161,9 +161,9 @@ func youtube_run(config map[string]interface{}) { log.Println("StreamGoose YouTube Go backend started") var raw_chat_data map[string]interface{} - msg_id_cache = append(msg_id_cache, "") /* init the cache */ + yt_msg_id_cache = append(yt_msg_id_cache, "") /* init the cache */ for { /* main loop */ - raw_chat_data = api_get("/liveChat/messages?part=snippet,authorDetails&liveChatId=" + chat_id) + raw_chat_data = yt_api_get("/liveChat/messages?part=snippet,authorDetails&liveChatId=" + chat_id) if _, ok := raw_chat_data["items"]; ok && len(raw_chat_data["items"].([]interface{})) > 0 { for _, rawmsg := range raw_chat_data["items"].([]interface{}) { /* iterate over raw message objects */ yt_process_message(rawmsg.(map[string]interface{}))