add eventsub notifications for channels going live

This commit is contained in:
lyx0 2024-02-13 19:13:44 +01:00
parent 3ace231495
commit e09ec92a3b
4 changed files with 104 additions and 0 deletions

View file

@ -122,6 +122,18 @@ func (app *application) handleCommand(message twitch.PrivateMessage) {
case "frankerfacez": case "frankerfacez":
reply = commands.Ffz(cmdParams[1]) reply = commands.Ffz(cmdParams[1])
case "notify":
switch cmdParams[1] {
case "live":
if userLevel >= 100 {
reply = app.createLiveSubscription(target, cmdParams[2])
}
case "offline":
if userLevel >= 100 {
//reply = app.createFollowSubscription(target, cmdParams[2])
}
}
case "ddg": case "ddg":
reply = commands.DuckDuckGo(message.Message[6:len(message.Message)]) reply = commands.DuckDuckGo(message.Message[6:len(message.Message)])

44
cmd/nourybot/eventsub.go Normal file
View file

@ -0,0 +1,44 @@
package main
import (
"fmt"
"github.com/lyx0/nourybot/pkg/ivr"
"github.com/nicklaw5/helix/v2"
)
func (app *application) createLiveSubscription(target, channel string) string {
client, err := helix.NewClient(&helix.Options{
ClientID: app.Config.twitchClientId,
AppAccessToken: app.HelixClient.GetAppAccessToken(),
})
if err != nil {
app.Log.Errorw("Error creating new helix client",
"err", err,
)
}
uid := ivr.IDByUsername(channel)
resp, err := client.CreateEventSubSubscription(&helix.EventSubSubscription{
Type: helix.EventSubTypeStreamOnline,
Version: "1",
Condition: helix.EventSubCondition{
BroadcasterUserID: uid,
},
Transport: helix.EventSubTransport{
Method: "webhook",
Callback: "https://bot.noury.li/eventsub",
Secret: app.Config.eventSubSecret,
},
})
if err != nil {
app.Log.Errorw("Error creating EvenSub subscription",
"resp", resp,
"err", err,
)
}
app.Log.Infof("%+v\n", resp)
return fmt.Sprintf("Created subscription for channel %v; uid=%v", channel, uid)
}

View file

@ -25,6 +25,7 @@ type config struct {
twitchOauth string twitchOauth string
twitchClientId string twitchClientId string
twitchClientSecret string twitchClientSecret string
eventSubSecret string
twitchID string twitchID string
wolframAlphaAppID string wolframAlphaAppID string
commandPrefix string commandPrefix string
@ -88,6 +89,7 @@ func run(ctx context.Context, w io.Writer, args []string) error {
cfg.twitchOauth = os.Getenv("TWITCH_OAUTH") cfg.twitchOauth = os.Getenv("TWITCH_OAUTH")
cfg.twitchClientId = os.Getenv("TWITCH_CLIENT_ID") cfg.twitchClientId = os.Getenv("TWITCH_CLIENT_ID")
cfg.twitchClientSecret = os.Getenv("TWITCH_CLIENT_SECRET") cfg.twitchClientSecret = os.Getenv("TWITCH_CLIENT_SECRET")
cfg.eventSubSecret = os.Getenv("EVENTSUB_SECRET")
cfg.wolframAlphaAppID = os.Getenv("WOLFRAMALPHA_APP_ID") cfg.wolframAlphaAppID = os.Getenv("WOLFRAMALPHA_APP_ID")
cfg.twitchID = os.Getenv("TWITCH_ID") cfg.twitchID = os.Getenv("TWITCH_ID")
cfg.env = os.Getenv("ENV") cfg.env = os.Getenv("ENV")

View file

@ -1,8 +1,12 @@
package main package main
import ( import (
"bytes"
"encoding/json"
"fmt" "fmt"
"html/template" "html/template"
"io/ioutil"
"log"
"net/http" "net/http"
"os" "os"
"sort" "sort"
@ -10,12 +14,14 @@ import (
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/lyx0/nourybot/internal/common" "github.com/lyx0/nourybot/internal/common"
"github.com/lyx0/nourybot/internal/data" "github.com/lyx0/nourybot/internal/data"
"github.com/nicklaw5/helix/v2"
) )
func (app *application) startRouter() { func (app *application) startRouter() {
router := httprouter.New() router := httprouter.New()
router.GET("/", app.homeRoute) router.GET("/", app.homeRoute)
router.GET("/status", app.statusPageRoute) router.GET("/status", app.statusPageRoute)
router.POST("/eventsub", app.eventsubFollow)
router.GET("/commands", app.commandsRoute) router.GET("/commands", app.commandsRoute)
router.GET("/commands/:channel", app.channelCommandsRoute) router.GET("/commands/:channel", app.channelCommandsRoute)
router.GET("/timer", app.timersRoute) router.GET("/timer", app.timersRoute)
@ -29,6 +35,46 @@ func (app *application) startRouter() {
app.Log.Fatal(http.ListenAndServe(":8080", router)) app.Log.Fatal(http.ListenAndServe(":8080", router))
} }
type eventSubNotification struct {
Subscription helix.EventSubSubscription `json:"subscription"`
Challenge string `json:"challenge"`
Event json.RawMessage `json:"event"`
}
func (app *application) eventsubFollow(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Println(err)
return
}
defer r.Body.Close()
// verify that the notification came from twitch using the secret.
if !helix.VerifyEventSubNotification(app.Config.eventSubSecret, r.Header, string(body)) {
log.Println("no valid signature on subscription")
return
} else {
log.Println("verified signature for subscription")
}
var vals eventSubNotification
err = json.NewDecoder(bytes.NewReader(body)).Decode(&vals)
if err != nil {
log.Println(err)
return
}
// if there's a challenge in the request, respond with only the challenge to verify your eventsub.
if vals.Challenge != "" {
w.Write([]byte(vals.Challenge))
return
}
var liveEvent helix.EventSubStreamOnlineEvent
err = json.NewDecoder(bytes.NewReader(vals.Event)).Decode(&liveEvent)
log.Printf("got stream online event webhook: %s is live\n", liveEvent.BroadcasterUserName)
w.WriteHeader(200)
w.Write([]byte("ok"))
app.SendNoContext("nouryxd", fmt.Sprintf("%s is now live!", liveEvent.BroadcasterUserName))
}
type timersRouteData struct { type timersRouteData struct {
Timers []data.Timer Timers []data.Timer
} }