/ytLiveChatBot

ytLiveChatBot is a golang library for cli base applications that makes it easy to read and write live-chat on/from youtube live streams using youtube api.

Primary LanguageGo

ytLiveChatBot

ytLiveChatBot is a golang library for cli base applications that makes it easy to read and write live-chat on/from youtube live streams using youtube api.

It is designed for handling multiple live-streams at a time. But can also be used for a single live-stream

Features

  • Abstracts youtube API Oauth logic
  • converts youtube live-stream chat in easily manageable readable and writable go channels
  • ChatReader channel will receive incoming chat-messages
  • Anything written on ChatWriter channel will be sent directly to youtube stream

Setup

  • Obtain OAuth 2.0 credentials from the Google API Console
    Go through before you start section of youtube api, and download client_secret.json

image

  • Make sure client_secret.json is stored inside your application root directory.

Usage

import "github.com/ketan-10/ytLiveChatBot"
  • Intantiate LiveChatBot with youtube live-stream Urls, urls can be in any of the following formats https://www.youtube.com/watch?v=5qap5aO4i9A", "5qap5aO4i9A", "https://youtu.be/5qap5aO4i9A
var chatBot *ytbot.LiveChatBot = ytbot.NewLiveChatBot(&ytbot.LiveChatBotInput{
  Urls: []string{"https://youtu.be/KSU023LJKS", "https://youtu.be/eo22kjof2", "5qap5aO4i9A"},
})
  • LiveChatBot have ChatReaders and ChatWriters which are Maps having key of youtube-url and value as respective chat reader or writer channel
type LiveChatBot struct {
	ChatReaders map[string]<-chan *youtube.LiveChatMessage
	ChatWriters map[string]chan<- string
}
  • NewLiveChatBot func will initiate oauth flow, it will print the google oauth url in console where user has open the url in browser and grant youtube Access.
Choose Account Grant Access
image image
  • Google Sign in will show a token, which to be copy pasted to console

  • For subsequent re-runs token will be cached in .credentials file in home directory, to ignore cache use RefetchCache: true

chatBot := ytbot.NewLiveChatBot(&ytbot.LiveChatBotInput{
  RefetchCache: true,
  Urls:         []string{"5qap5aO4i9A", "3304aO430C"},
},

Examples

  1. Read live chats from a single live-stream
package main

import (
	"fmt"
	"github.com/ketan-10/ytLiveChatBot"
)

func main() {
	chatBot := ytbot.NewLiveChatBot(&ytbot.LiveChatBotInput{
		Urls: []string{"5qap5aO4i9A"},
	})
	chatReader := chatBot.ChatReaders["5qap5aO4i9A"]

	for newChat := range chatReader {
		fmt.Println(newChat.Snippet.DisplayMessage)
	}
}
  1. Read from console and write directly to youtube live-stream chat
package main

import (
	"bufio"
	"os"
	"github.com/ketan-10/ytLiveChatBot"
)

func main() {
	chatBot := ytbot.NewLiveChatBot(&ytbot.LiveChatBotInput{
		Urls: []string{"5qap5aO4i9A"},
	})
	chatWriter := chatBot.ChatWriters["5qap5aO4i9A"]

	scanner := bufio.NewScanner(os.Stdin)
	for {
		if scanner.Scan() {
			newChat := scanner.Text()
			chatWriter <- newChat
		}
	}
}
  1. Read multiple youtube live-stream chat and print live result.
package main

import (
	"fmt"
	"sync"

	"github.com/ketan-10/ytLiveChatBot"
	"google.golang.org/api/youtube/v3"
)

var wg = sync.WaitGroup{}
// read multiple youtube live stream chat
func main() {

	chatBot := ytbot.NewLiveChatBot(&ytbot.LiveChatBotInput{
		// enter list of livestream urls
		Urls: []string{"https://youtu.be/KSU023LJKS", "https://youtu.be/eo22kjof2", "5qap5aO4i9A"},
	})
	for url, valueReader := range chatBot.ChatReaders {
		wg.Add(1)
		go readChannel(valueReader, url)
	}
	wg.Wait()
}

func readChannel(valueReader <-chan *youtube.LiveChatMessage, url string) {
	defer wg.Done()
	for item := range valueReader {
		newMessage := item.Snippet.DisplayMessage
		fmt.Println("Form stream: " + url + " -> Message: " + newMessage)
	}
}
  1. If chat-message have prefix /a send the message to all other live-streams
package main

import (
	"fmt"
	"os"
	"regexp"
	"strings"
	"sync"

	"github.com/ketan-10/ytLiveChatBot"
	"google.golang.org/api/youtube/v3"
)

func main() {

	refetchCache := false
	if len(os.Args) > 1 && os.Args[1] == "ignoreCache" {
		refetchCache = true
	}

	chatBot := ytbot.NewLiveChatBot(&ytbot.LiveChatBotInput{
		RefetchCache: refetchCache,
		Urls:         []string{"5qap5aO4i9A", "WUG1AocK2Ys"},
	})

	var wg = sync.WaitGroup{}

	const prefix string = "/a "
	re := regexp.MustCompile("^(" + prefix + ")*")

	fmt.Println("Starting bot...")
	for rUrl, readChannel := range chatBot.ChatReaders {
		wg.Add(1)
		go func(readChannel <-chan *youtube.LiveChatMessage, rUrl string) {
			defer wg.Done()
			for item := range readChannel {
				newMessage := item.Snippet.DisplayMessage
				if !strings.HasPrefix(newMessage, prefix) {
					continue
				}
				// remove prefix
				newMessage = re.ReplaceAllString(newMessage, "")

				fmt.Println(item.AuthorDetails)
				// send to all other live-stream
				sendMessage := "@" + item.AuthorDetails.DisplayName + " From: " + rUrl + " Said: " + newMessage
				fmt.Println(sendMessage)
				for wUrl, writeChannel := range chatBot.ChatWriters {
					if wUrl != rUrl {
						writeChannel <- sendMessage
					}
				}
			}

		}(readChannel, rUrl)
	}

	wg.Wait()
}

References

GO

Are there any security concerns with sharing the client secrets of a Google API project?

Youtube API examples

Google OAuth2

Flutter Example Video 1   Flutter Example Video 2

Youtube API path

Why need Authorization-code

Publish go module

go run . new

go mod init github.com/ketan-10/combine-youtube-live-chat go mod tidy

  • If client-id is compromised, an attacker can request use-data on your behalf, But the attacker will not be able to access actual user-data as he will just get authorization code after user login/consent NOT access or refresh token, for that hey have to exchange authorization code with access/refresh token which requires client-secret.
  • If client-secret and client-id is compromised, the attacker might be able to access user data, assuming we are using a web application, we have to register the redirect url as our on google API. so Google will send the authorization-code to only redirect-url so the user will be navigated to our site and not attacker site. But if the browser is also compromised that will cause an issue.