2022-12-05 01:11:44 +00:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
2023-01-20 15:39:51 +00:00
|
|
|
|
"fmt"
|
2023-01-23 12:10:21 +00:00
|
|
|
|
"log"
|
2022-12-05 01:11:44 +00:00
|
|
|
|
"net/http"
|
2023-01-20 15:39:51 +00:00
|
|
|
|
"strings"
|
2023-01-23 12:10:21 +00:00
|
|
|
|
"time"
|
2022-12-05 01:11:44 +00:00
|
|
|
|
|
2023-01-23 12:10:21 +00:00
|
|
|
|
"github.com/jellydator/ttlcache/v3"
|
2022-12-05 01:11:44 +00:00
|
|
|
|
"github.com/labstack/echo/v4"
|
|
|
|
|
"github.com/livekit/protocol/auth"
|
|
|
|
|
"github.com/livekit/protocol/webhook"
|
2023-01-20 15:39:51 +00:00
|
|
|
|
mastodon "github.com/mattn/go-mastodon"
|
|
|
|
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
2023-01-23 12:10:21 +00:00
|
|
|
|
"golang.org/x/net/context"
|
2022-12-05 01:11:44 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func livekitWebhookHandler(c echo.Context) error {
|
|
|
|
|
authProvider := auth.NewSimpleKeyProvider(mainConfig.Livekit.APIKey, mainConfig.Livekit.APISecret)
|
|
|
|
|
event, err := webhook.ReceiveWebhookEvent(c.Request(), authProvider)
|
|
|
|
|
|
|
|
|
|
if err == webhook.ErrNoAuthHeader {
|
|
|
|
|
return echo.NewHTTPError(http.StatusForbidden)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if event.GetEvent() == webhook.EventRoomFinished {
|
2023-01-25 06:37:31 +00:00
|
|
|
|
lkRoom := event.GetRoom()
|
|
|
|
|
room, err := findRoomByID(c.Request().Context(), lkRoom.GetName())
|
2023-01-20 15:39:51 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
c.Logger().Error(err)
|
|
|
|
|
return echo.NewHTTPError(http.StatusNotFound)
|
|
|
|
|
}
|
|
|
|
|
if room.EndedAt.IsZero() {
|
|
|
|
|
if err := endRoom(c.Request().Context(), room); err != nil {
|
|
|
|
|
c.Logger().Error(err)
|
|
|
|
|
return echo.NewHTTPError(http.StatusInternalServerError)
|
2022-12-05 01:11:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-23 12:10:21 +00:00
|
|
|
|
} else if event.GetEvent() == webhook.EventParticipantLeft {
|
|
|
|
|
// Revert user's avatar
|
|
|
|
|
audonID := event.GetParticipant().GetIdentity()
|
|
|
|
|
user, err := findUserByID(c.Request().Context(), audonID)
|
|
|
|
|
if user == nil || err != nil {
|
|
|
|
|
c.Logger().Error(err)
|
|
|
|
|
return echo.NewHTTPError(http.StatusNotFound)
|
|
|
|
|
}
|
|
|
|
|
still, err := user.InLivekit(c.Request().Context())
|
|
|
|
|
if !still && err == nil {
|
2023-01-26 22:31:53 +00:00
|
|
|
|
data := userSessionCache.Get(audonID)
|
2023-01-23 12:10:21 +00:00
|
|
|
|
if data == nil {
|
|
|
|
|
return echo.NewHTTPError(http.StatusGone)
|
|
|
|
|
}
|
|
|
|
|
mastoClient := getMastodonClient(data.Value())
|
|
|
|
|
if mastoClient == nil {
|
|
|
|
|
c.Logger().Errorf("unable to get mastodon client: %v", data.Value().MastodonConfig)
|
|
|
|
|
return echo.NewHTTPError(http.StatusInternalServerError)
|
|
|
|
|
}
|
|
|
|
|
cached := webhookTimerCache.Get(audonID)
|
|
|
|
|
if cached != nil {
|
|
|
|
|
oldTimer := cached.Value()
|
|
|
|
|
if !oldTimer.Stop() {
|
|
|
|
|
<-oldTimer.C
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-26 18:28:25 +00:00
|
|
|
|
countdown := time.NewTimer(60 * time.Second)
|
2023-01-23 12:10:21 +00:00
|
|
|
|
webhookTimerCache.Set(audonID, countdown, ttlcache.DefaultTTL)
|
|
|
|
|
|
2023-01-25 06:37:31 +00:00
|
|
|
|
go func() {
|
|
|
|
|
<-countdown.C
|
|
|
|
|
webhookTimerCache.Delete(audonID)
|
2023-01-26 18:28:25 +00:00
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
2023-01-25 06:37:31 +00:00
|
|
|
|
defer cancel()
|
2023-01-23 12:10:21 +00:00
|
|
|
|
|
2023-01-25 06:37:31 +00:00
|
|
|
|
stillAgain, err := user.InLivekit(ctx)
|
2023-01-23 12:10:21 +00:00
|
|
|
|
if err != nil {
|
2023-01-25 06:37:31 +00:00
|
|
|
|
log.Println(err)
|
2023-01-23 12:10:21 +00:00
|
|
|
|
}
|
2023-01-25 06:37:31 +00:00
|
|
|
|
if stillAgain {
|
|
|
|
|
return
|
2023-01-23 12:10:21 +00:00
|
|
|
|
}
|
2023-01-25 06:37:31 +00:00
|
|
|
|
nextUser, err := findUserByID(ctx, audonID)
|
|
|
|
|
if err == nil && nextUser.AvatarFile != "" {
|
2023-01-27 13:28:16 +00:00
|
|
|
|
log.Printf("Recovering avatar: %s --> (%s) %s\n", nextUser.AvatarFile, audonID, nextUser.Webfinger)
|
2023-01-25 06:37:31 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
avatar := nextUser.getAvatarImagePath(nextUser.AvatarFile)
|
|
|
|
|
_, err = updateAvatar(ctx, mastoClient, avatar)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
nextUser.ClearUserAvatar(ctx)
|
|
|
|
|
} else if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
}()
|
2023-01-23 12:10:21 +00:00
|
|
|
|
}
|
2023-01-20 15:39:51 +00:00
|
|
|
|
} else if event.GetEvent() == webhook.EventRoomStarted {
|
|
|
|
|
// Have the bot advertise the room
|
|
|
|
|
room, err := findRoomByID(c.Request().Context(), event.GetRoom().GetName())
|
|
|
|
|
if err != nil {
|
|
|
|
|
c.Logger().Error(err)
|
|
|
|
|
return echo.NewHTTPError(http.StatusNotFound)
|
|
|
|
|
}
|
|
|
|
|
if err == nil && mainConfig.Bot.Enable && room.Advertise != "" && room.Restriction == EVERYONE {
|
|
|
|
|
botClient := mastodon.NewClient(&mastodon.Config{
|
|
|
|
|
Server: mainConfig.Bot.Server.String(),
|
|
|
|
|
ClientID: mainConfig.Bot.ClientID,
|
|
|
|
|
ClientSecret: mainConfig.Bot.ClientSecret,
|
|
|
|
|
AccessToken: mainConfig.Bot.AccessToken,
|
|
|
|
|
})
|
|
|
|
|
botClient.UserAgent = USER_AGENT
|
|
|
|
|
|
|
|
|
|
localizer := i18n.NewLocalizer(localeBundle, room.Advertise)
|
|
|
|
|
header := localizer.MustLocalize(&i18n.LocalizeConfig{
|
|
|
|
|
DefaultMessage: &i18n.Message{
|
|
|
|
|
ID: "Advertise",
|
|
|
|
|
Other: "@{{.Host}} is streaming now!",
|
|
|
|
|
},
|
|
|
|
|
TemplateData: map[string]string{
|
|
|
|
|
"Host": room.Host.Webfinger,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
messages := []string{
|
|
|
|
|
header,
|
2023-01-26 22:43:04 +00:00
|
|
|
|
fmt.Sprintf(":udon: %s\n🎙️ https://%s/u/@%s", room.Title, mainConfig.LocalDomain, room.Host.Webfinger),
|
2023-01-20 15:39:51 +00:00
|
|
|
|
}
|
|
|
|
|
if room.Description != "" {
|
|
|
|
|
messages = append(messages, room.Description)
|
|
|
|
|
}
|
|
|
|
|
messages = append(messages, "#Audon")
|
|
|
|
|
message := strings.Join(messages, "\n\n")
|
2022-12-05 01:11:44 +00:00
|
|
|
|
|
2023-01-20 15:39:51 +00:00
|
|
|
|
if _, err := botClient.PostStatus(c.Request().Context(), &mastodon.Toot{
|
|
|
|
|
Status: message,
|
|
|
|
|
Language: room.Advertise,
|
|
|
|
|
Visibility: "public",
|
|
|
|
|
}); err != nil {
|
|
|
|
|
c.Logger().Error(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-05 01:11:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-20 15:39:51 +00:00
|
|
|
|
return c.NoContent(http.StatusOK)
|
2022-12-05 01:11:44 +00:00
|
|
|
|
}
|