kopia lustrzana https://codeberg.org/nmkj/audon
change timing to create room
rodzic
b21aa42aaa
commit
1a6b838c9c
|
@ -20,7 +20,7 @@ webhook:
|
||||||
|
|
||||||
room:
|
room:
|
||||||
auto_create: false
|
auto_create: false
|
||||||
empty_timeout: 3600
|
empty_timeout: 30
|
||||||
max_participants: 0
|
max_participants: 0
|
||||||
max_metadata_size: 0
|
max_metadata_size: 0
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ LIVEKIT_API_SECRET=secret
|
||||||
LIVEKIT_HOST=livekit.example.com
|
LIVEKIT_HOST=livekit.example.com
|
||||||
# This value will be returned by Audon backend to browsers. Set the same domain as LIVEKIT_HOST if you are not sure.
|
# This value will be returned by Audon backend to browsers. Set the same domain as LIVEKIT_HOST if you are not sure.
|
||||||
LIVEKIT_LOCAL_DOMAIN=livekit.example.com
|
LIVEKIT_LOCAL_DOMAIN=livekit.example.com
|
||||||
|
# If this period (seconds) passes, the new room will be automatically closed.
|
||||||
|
LIVEKIT_EMPTY_ROOM_TIMEOUT=300
|
||||||
|
|
||||||
### Bot Settings ###
|
### Bot Settings ###
|
||||||
# Leave the following fields empty to disable the notification bot.
|
# Leave the following fields empty to disable the notification bot.
|
||||||
|
|
|
@ -26,8 +26,8 @@ comingFuture: "Coming with future update!"
|
||||||
processing: "Processing now...<br />Keep this window open!"
|
processing: "Processing now...<br />Keep this window open!"
|
||||||
lostWarning: "Unsaved data will be lost if you leave the page, are you sure?"
|
lostWarning: "Unsaved data will be lost if you leave the page, are you sure?"
|
||||||
staticLink:
|
staticLink:
|
||||||
title: "Your Static Link"
|
title: "Your Audon Link"
|
||||||
hint: "Other can join to your room via this link while you're hosting."
|
hint: "Other can join to your room via this personal link while you're hosting."
|
||||||
form:
|
form:
|
||||||
title: "Title"
|
title: "Title"
|
||||||
titleRequired: "Room title required"
|
titleRequired: "Room title required"
|
||||||
|
@ -48,6 +48,7 @@ shareRoomMessage: "Join my Audon room!\n{link}\n\nTitle: {title}"
|
||||||
roomReady:
|
roomReady:
|
||||||
header: "Your room is ready!"
|
header: "Your room is ready!"
|
||||||
message: "Your room \"{title}\" is now ready. Share the following URL with other participants."
|
message: "Your room \"{title}\" is now ready. Share the following URL with other participants."
|
||||||
|
timeout: "The room will be closed automatically if no one joins within {minutes} minutes."
|
||||||
errors:
|
errors:
|
||||||
offline: "This user is not hosting now."
|
offline: "This user is not hosting now."
|
||||||
invalidAddress: "Invalid address"
|
invalidAddress: "Invalid address"
|
||||||
|
|
|
@ -26,8 +26,8 @@ comingFuture: "今後のアップデートで追加予定"
|
||||||
processing: "処理中です。<br />画面を閉じないでください。"
|
processing: "処理中です。<br />画面を閉じないでください。"
|
||||||
lostWarning: "この画面を閉じると保存前の内容が失われます。構いませんか?"
|
lostWarning: "この画面を閉じると保存前の内容が失われます。構いませんか?"
|
||||||
staticLink:
|
staticLink:
|
||||||
title: "固定リンク"
|
title: "Audon リンク"
|
||||||
hint: "プロフィール欄などに固定しておくと、あなたが部屋をホストしたとき他の人はこのリンクを使って参加できます。"
|
hint: "あなたが部屋をホストしたとき、他の人はこの固定 URL からでも参加できます。"
|
||||||
form:
|
form:
|
||||||
title: "タイトル"
|
title: "タイトル"
|
||||||
titleRequired: "部屋の名前を入力してください"
|
titleRequired: "部屋の名前を入力してください"
|
||||||
|
@ -48,6 +48,7 @@ shareRoomMessage: "Audon で部屋を作りました!\n参加用リンク: {
|
||||||
roomReady:
|
roomReady:
|
||||||
header: "お部屋の用意ができました!"
|
header: "お部屋の用意ができました!"
|
||||||
message: "{title} を作りました。参加者に以下の URL を共有してください。"
|
message: "{title} を作りました。参加者に以下の URL を共有してください。"
|
||||||
|
timeout: "{minutes} 分以内に誰も入室しないと部屋が閉じますのでご注意ください。"
|
||||||
errors:
|
errors:
|
||||||
offline: "このユーザーは現在ホスト中ではありません。"
|
offline: "このユーザーは現在ホスト中ではありません。"
|
||||||
invalidAddress: "アドレスが有効ではありません"
|
invalidAddress: "アドレスが有効ではありません"
|
||||||
|
|
|
@ -104,11 +104,13 @@ export default {
|
||||||
if (!donURL) return "";
|
if (!donURL) return "";
|
||||||
const url = new URL(donURL);
|
const url = new URL(donURL);
|
||||||
const texts = [
|
const texts = [
|
||||||
this.$t("shareRoomMessage", { link: this.roomURL, title: this.title }),
|
this.$t("shareRoomMessage", {
|
||||||
|
link: this.donStore.myStaticLink,
|
||||||
|
title: this.title,
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
if (this.description)
|
if (this.description)
|
||||||
texts.push(truncate("\n" + this.description, { length: 200 }));
|
texts.push(truncate("\n" + this.description, { length: 200 }));
|
||||||
texts.push("\n#Audon");
|
|
||||||
return encodeURI(`${url.origin}/share?text=${texts.join("\n")}`);
|
return encodeURI(`${url.origin}/share?text=${texts.join("\n")}`);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -209,7 +211,7 @@ export default {
|
||||||
{{ $t("roomReady.message", { title }) }}
|
{{ $t("roomReady.message", { title }) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<h3 style="word-break: break-all">{{ roomURL }}</h3>
|
<h3 style="word-break: break-all">{{ donStore.myStaticLink }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<v-btn
|
<v-btn
|
||||||
|
@ -221,7 +223,7 @@ export default {
|
||||||
>{{ $t("share") }}</v-btn
|
>{{ $t("share") }}</v-btn
|
||||||
>
|
>
|
||||||
<v-btn
|
<v-btn
|
||||||
@click="clipboard.copy(roomURL)"
|
@click="clipboard.copy(donStore.myStaticLink)"
|
||||||
color="lime"
|
color="lime"
|
||||||
size="small"
|
size="small"
|
||||||
:prepend-icon="
|
:prepend-icon="
|
||||||
|
@ -230,7 +232,10 @@ export default {
|
||||||
>{{ clipboard.copied.value ? $t("copied") : $t("copy") }}</v-btn
|
>{{ clipboard.copied.value ? $t("copied") : $t("copy") }}</v-btn
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center mt-10 mb-1">
|
<v-alert class="mt-5" density="compact" type="warning" variant="tonal">{{
|
||||||
|
$t("roomReady.timeout", { minutes: 5 })
|
||||||
|
}}</v-alert>
|
||||||
|
<div class="text-center mt-5 mb-1">
|
||||||
<v-btn
|
<v-btn
|
||||||
color="indigo"
|
color="indigo"
|
||||||
:to="{ name: 'room', params: { id: createdRoomID } }"
|
:to="{ name: 'room', params: { id: createdRoomID } }"
|
||||||
|
|
|
@ -10,9 +10,8 @@ export default {
|
||||||
if (!type) return;
|
if (!type) return;
|
||||||
|
|
||||||
if (type === "offline") {
|
if (type === "offline") {
|
||||||
const target = new URL(decodeURI(this.$route.query.url));
|
|
||||||
alert(this.$t("errors.offline"));
|
alert(this.$t("errors.offline"));
|
||||||
window.location.href = target.toString();
|
this.$router.push({ name: "home" });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
26
config.go
26
config.go
|
@ -6,6 +6,8 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
@ -30,11 +32,12 @@ type (
|
||||||
}
|
}
|
||||||
|
|
||||||
LivekitConfig struct {
|
LivekitConfig struct {
|
||||||
APIKey string `validate:"required,ascii"`
|
APIKey string `validate:"required,ascii"`
|
||||||
APISecret string `validate:"required,ascii"`
|
APISecret string `validate:"required,ascii"`
|
||||||
Host string `validate:"required,hostname|hostname_port"`
|
Host string `validate:"required,hostname|hostname_port"`
|
||||||
LocalDomain string `validate:"required,hostname|hostname_port"`
|
LocalDomain string `validate:"required,hostname|hostname_port"`
|
||||||
URL *url.URL
|
URL *url.URL
|
||||||
|
EmptyRoomTimeout time.Duration `validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
DBConfig struct {
|
DBConfig struct {
|
||||||
|
@ -164,11 +167,16 @@ func loadConfig(envname string) (*AppConfig, error) {
|
||||||
appConf.Redis = redisConf
|
appConf.Redis = redisConf
|
||||||
|
|
||||||
// Setup LiveKit config
|
// Setup LiveKit config
|
||||||
|
timeout, err := strconv.Atoi(os.Getenv("LIVEKIT_EMPTY_ROOM_TIMEOUT"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
lkConf := &LivekitConfig{
|
lkConf := &LivekitConfig{
|
||||||
APIKey: os.Getenv("LIVEKIT_API_KEY"),
|
APIKey: os.Getenv("LIVEKIT_API_KEY"),
|
||||||
APISecret: os.Getenv("LIVEKIT_API_SECRET"),
|
APISecret: os.Getenv("LIVEKIT_API_SECRET"),
|
||||||
Host: os.Getenv("LIVEKIT_HOST"),
|
Host: os.Getenv("LIVEKIT_HOST"),
|
||||||
LocalDomain: os.Getenv("LIVEKIT_LOCAL_DOMAIN"),
|
LocalDomain: os.Getenv("LIVEKIT_LOCAL_DOMAIN"),
|
||||||
|
EmptyRoomTimeout: time.Duration(timeout) * time.Second,
|
||||||
}
|
}
|
||||||
if err := mainValidator.Struct(lkConf); err != nil {
|
if err := mainValidator.Struct(lkConf); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
94
room.go
94
room.go
|
@ -99,6 +99,8 @@ func createRoomHandler(c echo.Context) error {
|
||||||
}
|
}
|
||||||
room.RoomID = canonic()
|
room.RoomID = canonic()
|
||||||
|
|
||||||
|
room.CreatedAt = now
|
||||||
|
|
||||||
// if cohosts are already registered, retrieve their data from DB
|
// if cohosts are already registered, retrieve their data from DB
|
||||||
for i, cohost := range room.CoHosts {
|
for i, cohost := range room.CoHosts {
|
||||||
cohostUser, err := findUserByRemote(c.Request().Context(), cohost.RemoteID, cohost.RemoteURL)
|
cohostUser, err := findUserByRemote(c.Request().Context(), cohost.RemoteID, cohost.RemoteURL)
|
||||||
|
@ -112,6 +114,37 @@ func createRoomHandler(c echo.Context) error {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create livekit room
|
||||||
|
roomMetadata := &RoomMetadata{Room: room, MastodonAccounts: make(map[string]*MastodonAccount)}
|
||||||
|
metadata, _ := json.Marshal(roomMetadata)
|
||||||
|
_, err = lkRoomServiceClient.CreateRoom(c.Request().Context(), &livekit.CreateRoomRequest{
|
||||||
|
Name: room.RoomID,
|
||||||
|
Metadata: string(metadata),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
return echo.NewHTTPError(http.StatusConflict)
|
||||||
|
}
|
||||||
|
countdown := time.NewTimer(mainConfig.Livekit.EmptyRoomTimeout)
|
||||||
|
orphanRooms.Set(room.RoomID, true, ttlcache.DefaultTTL)
|
||||||
|
|
||||||
|
go func(r *Room, logger echo.Logger) {
|
||||||
|
<-countdown.C
|
||||||
|
|
||||||
|
if orphaned := orphanRooms.Get(r.RoomID); orphaned == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if !r.IsAnyomeInLivekitRoom(ctx) {
|
||||||
|
if err := endRoom(ctx, r); err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(room, c.Logger())
|
||||||
|
|
||||||
return c.String(http.StatusCreated, room.RoomID)
|
return c.String(http.StatusCreated, room.RoomID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,50 +435,31 @@ func joinRoomHandler(c echo.Context) (err error) {
|
||||||
c.Logger().Error(err)
|
c.Logger().Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create room in LiveKit if it doesn't exist
|
// Update room metadata
|
||||||
if lkRoom == nil {
|
currentMeta, err := getRoomMetadataFromLivekitRoom(lkRoom)
|
||||||
room.CreatedAt = now
|
if err != nil {
|
||||||
coll := mainDB.Collection(COLLECTION_ROOM)
|
c.Logger().Error(err)
|
||||||
if _, err := coll.UpdateOne(c.Request().Context(),
|
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||||
bson.D{{Key: "room_id", Value: roomID}},
|
}
|
||||||
bson.D{{Key: "$set", Value: bson.D{{Key: "created_at", Value: now}}}}); err != nil {
|
currentMeta.MastodonAccounts[user.AudonID] = mastoAccount
|
||||||
c.Logger().Error(err)
|
newMetadata, err := json.Marshal(currentMeta)
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
if err != nil {
|
||||||
}
|
c.Logger().Error(err)
|
||||||
metadata, _ := json.Marshal(roomMetadata)
|
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||||
_, err = lkRoomServiceClient.CreateRoom(c.Request().Context(), &livekit.CreateRoomRequest{
|
}
|
||||||
Name: room.RoomID,
|
_, err = lkRoomServiceClient.UpdateRoomMetadata(c.Request().Context(), &livekit.UpdateRoomMetadataRequest{
|
||||||
Metadata: string(metadata),
|
Room: roomID,
|
||||||
})
|
Metadata: string(newMetadata),
|
||||||
if err != nil {
|
})
|
||||||
c.Logger().Error(err)
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusConflict)
|
c.Logger().Error(err)
|
||||||
}
|
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||||
} else {
|
|
||||||
currentMeta, err := getRoomMetadataFromLivekitRoom(lkRoom)
|
|
||||||
if err != nil {
|
|
||||||
c.Logger().Error(err)
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
currentMeta.MastodonAccounts[user.AudonID] = mastoAccount
|
|
||||||
newMetadata, err := json.Marshal(currentMeta)
|
|
||||||
if err != nil {
|
|
||||||
c.Logger().Error(err)
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
_, err = lkRoomServiceClient.UpdateRoomMetadata(c.Request().Context(), &livekit.UpdateRoomMetadataRequest{
|
|
||||||
Room: roomID,
|
|
||||||
Metadata: string(newMetadata),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
c.Logger().Error(err)
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store user's session data in cache
|
// Store user's session data in cache
|
||||||
data, _ := getSessionData(c)
|
data, _ := getSessionData(c)
|
||||||
roomSessionCache.Set(user.AudonID, data, ttlcache.DefaultTTL)
|
userSessionCache.Set(user.AudonID, data, ttlcache.DefaultTTL)
|
||||||
|
orphanRooms.Delete(roomID)
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, resp)
|
return c.JSON(http.StatusOK, resp)
|
||||||
}
|
}
|
||||||
|
|
12
server.go
12
server.go
|
@ -53,8 +53,9 @@ var (
|
||||||
mainConfig *AppConfig
|
mainConfig *AppConfig
|
||||||
lkRoomServiceClient *lksdk.RoomServiceClient
|
lkRoomServiceClient *lksdk.RoomServiceClient
|
||||||
localeBundle *i18n.Bundle
|
localeBundle *i18n.Bundle
|
||||||
roomSessionCache *ttlcache.Cache[string, *SessionData]
|
userSessionCache *ttlcache.Cache[string, *SessionData]
|
||||||
webhookTimerCache *ttlcache.Cache[string, *time.Timer]
|
webhookTimerCache *ttlcache.Cache[string, *time.Timer]
|
||||||
|
orphanRooms *ttlcache.Cache[string, bool]
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -154,10 +155,12 @@ func main() {
|
||||||
e.Use(session.Middleware(redisStore))
|
e.Use(session.Middleware(redisStore))
|
||||||
|
|
||||||
// Setup caches
|
// Setup caches
|
||||||
roomSessionCache = ttlcache.New(ttlcache.WithTTL[string, *SessionData](24 * time.Hour))
|
userSessionCache = ttlcache.New(ttlcache.WithTTL[string, *SessionData](24 * time.Hour))
|
||||||
webhookTimerCache = ttlcache.New(ttlcache.WithTTL[string, *time.Timer](60 * time.Second))
|
webhookTimerCache = ttlcache.New(ttlcache.WithTTL[string, *time.Timer](60 * time.Second))
|
||||||
go roomSessionCache.Start()
|
orphanRooms = ttlcache.New(ttlcache.WithTTL[string, bool](24 * time.Hour))
|
||||||
|
go userSessionCache.Start()
|
||||||
go webhookTimerCache.Start()
|
go webhookTimerCache.Start()
|
||||||
|
go orphanRooms.Start()
|
||||||
|
|
||||||
e.POST("/app/login", loginHandler)
|
e.POST("/app/login", loginHandler)
|
||||||
e.GET("/app/oauth", oauthHandler)
|
e.GET("/app/oauth", oauthHandler)
|
||||||
|
@ -203,8 +206,9 @@ func main() {
|
||||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
e.Logger.Print("Attempting graceful shutdown")
|
e.Logger.Print("Attempting graceful shutdown")
|
||||||
defer shutdownCancel()
|
defer shutdownCancel()
|
||||||
roomSessionCache.DeleteAll()
|
userSessionCache.DeleteAll()
|
||||||
webhookTimerCache.DeleteAll()
|
webhookTimerCache.DeleteAll()
|
||||||
|
orphanRooms.DeleteAll()
|
||||||
if err := e.Shutdown(shutdownCtx); err != nil {
|
if err := e.Shutdown(shutdownCtx); err != nil {
|
||||||
e.Logger.Fatalf("Failed shutting down gracefully: %s\n", err.Error())
|
e.Logger.Fatalf("Failed shutting down gracefully: %s\n", err.Error())
|
||||||
}
|
}
|
||||||
|
|
19
user.go
19
user.go
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
mastodon "github.com/mattn/go-mastodon"
|
mastodon "github.com/mattn/go-mastodon"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MastodonAccount struct {
|
type MastodonAccount struct {
|
||||||
|
@ -77,19 +78,13 @@ func redirectUserHandler(c echo.Context) error {
|
||||||
return ErrUserNotFound
|
return ErrUserNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
rooms, err := user.GetCurrentLivekitRooms(c.Request().Context())
|
coll := mainDB.Collection(COLLECTION_ROOM)
|
||||||
if err != nil {
|
opts := options.FindOne().SetSort(bson.D{{Key: "created_at", Value: -1}})
|
||||||
c.Logger().Error(err)
|
var room Room
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range rooms {
|
if err := coll.FindOne(c.Request().Context(), bson.D{{Key: "host.audon_id", Value: user.AudonID}}, opts).Decode(&room); err == nil {
|
||||||
meta, err := getRoomMetadataFromLivekitRoom(r)
|
if room.ExistsInLivekit(c.Request().Context()) {
|
||||||
if err != nil {
|
return c.Redirect(http.StatusFound, fmt.Sprintf("/r/%s", room.RoomID))
|
||||||
continue
|
|
||||||
}
|
|
||||||
if meta.Host.Equal(user) {
|
|
||||||
return c.Redirect(http.StatusFound, fmt.Sprintf("/r/%s", r.GetName()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,11 +47,10 @@ func livekitWebhookHandler(c echo.Context) error {
|
||||||
}
|
}
|
||||||
still, err := user.InLivekit(c.Request().Context())
|
still, err := user.InLivekit(c.Request().Context())
|
||||||
if !still && err == nil {
|
if !still && err == nil {
|
||||||
data := roomSessionCache.Get(audonID)
|
data := userSessionCache.Get(audonID)
|
||||||
if data == nil {
|
if data == nil {
|
||||||
return echo.NewHTTPError(http.StatusGone)
|
return echo.NewHTTPError(http.StatusGone)
|
||||||
}
|
}
|
||||||
roomSessionCache.Delete(audonID)
|
|
||||||
mastoClient := getMastodonClient(data.Value())
|
mastoClient := getMastodonClient(data.Value())
|
||||||
if mastoClient == nil {
|
if mastoClient == nil {
|
||||||
c.Logger().Errorf("unable to get mastodon client: %v", data.Value().MastodonConfig)
|
c.Logger().Errorf("unable to get mastodon client: %v", data.Value().MastodonConfig)
|
||||||
|
@ -93,6 +92,7 @@ func livekitWebhookHandler(c echo.Context) error {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
nextUser.ClearUserAvatar(ctx)
|
nextUser.ClearUserAvatar(ctx)
|
||||||
|
userSessionCache.Delete(audonID)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue