owncast support draft

This commit is contained in:
Luxferre
2024-09-14 23:42:47 +03:00
parent 4b11209e6d
commit 492cd515c6
5 changed files with 26 additions and 18 deletions
+1
View File
@@ -7,6 +7,7 @@
*.dylib
out/
auth/twitch-token.txt
auth/oc-token.txt
go.work
go.work.sum
.env
+4 -1
View File
@@ -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
}
+1 -1
View File
@@ -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:
+4
View File
@@ -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 {
+16 -16
View File
@@ -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{}))