kopia lustrzana https://codeberg.org/nmkj/audon
add role update
rodzic
55ca35c3c8
commit
cff4f9eaab
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "audon-fe",
|
||||
"version": "0.2.3",
|
||||
"version": "0.2.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "audon-fe",
|
||||
"version": "0.2.3",
|
||||
"version": "0.2.4",
|
||||
"dependencies": {
|
||||
"@intlify/unplugin-vue-i18n": "^0.8.1",
|
||||
"@picmo/popup-picker": "^5.7.2",
|
||||
|
|
|
@ -18,6 +18,7 @@ export default {
|
|||
muted: Boolean,
|
||||
emoji: String,
|
||||
preview: Boolean,
|
||||
enableMenu: Boolean,
|
||||
},
|
||||
computed: {
|
||||
showEmoji() {
|
||||
|
@ -34,17 +35,17 @@ export default {
|
|||
switch (this.type) {
|
||||
case "host":
|
||||
return {
|
||||
content: "Host",
|
||||
content: this.$t("role.host"),
|
||||
colour: "deep-orange",
|
||||
};
|
||||
case "cohost":
|
||||
return {
|
||||
content: "Cohost",
|
||||
content: this.$t("role.cohost"),
|
||||
colour: "indigo",
|
||||
};
|
||||
case "speaker":
|
||||
return {
|
||||
content: "Speaker",
|
||||
content: this.$t("role.speaker"),
|
||||
colour: "",
|
||||
};
|
||||
default:
|
||||
|
@ -78,7 +79,11 @@ export default {
|
|||
>
|
||||
<span>{{ emoji }}</span>
|
||||
</v-overlay>
|
||||
<v-img :src="data?.avatar"></v-img>
|
||||
<v-img
|
||||
:class="{ cursorPointer: enableMenu }"
|
||||
:id="`mod-${data?.identity}`"
|
||||
:src="data?.avatar"
|
||||
></v-img>
|
||||
</v-avatar>
|
||||
</v-badge>
|
||||
<v-avatar
|
||||
|
@ -97,8 +102,34 @@ export default {
|
|||
>
|
||||
<span>{{ emoji }}</span>
|
||||
</v-overlay>
|
||||
<v-img :src="data?.avatar"></v-img>
|
||||
<v-img
|
||||
:class="{ cursorPointer: enableMenu }"
|
||||
:id="`mod-${data?.identity}`"
|
||||
:src="data?.avatar"
|
||||
></v-img>
|
||||
</v-avatar>
|
||||
<v-menu v-if="enableMenu" :activator="`#mod-${data?.identity}`">
|
||||
<v-list>
|
||||
<v-list-item
|
||||
:title="$t('moderation.promote', { role: $t('role.cohost') })"
|
||||
@click="$emit('moderate', this.data?.identity, 'cohost')"
|
||||
></v-list-item>
|
||||
<v-list-item
|
||||
v-if="type !== 'speaker'"
|
||||
:title="$t('moderation.promote', { role: $t('role.speaker') })"
|
||||
@click="$emit('moderate', this.data?.identity, 'speaker')"
|
||||
></v-list-item>
|
||||
<v-list-item
|
||||
v-else
|
||||
:title="$t('moderation.demote')"
|
||||
@click="$emit('moderate', this.data?.identity, 'demote')"
|
||||
></v-list-item>
|
||||
<v-list-item
|
||||
:title="$t('moderation.kick')"
|
||||
@click="$emit('moderate', this.data?.identity, 'kick')"
|
||||
></v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<h4 :class="canSpeak ? 'mt-1' : 'mt-2'">
|
||||
<v-icon
|
||||
v-if="canSpeak && !preview"
|
||||
|
@ -121,4 +152,8 @@ export default {
|
|||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cursorPointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -25,6 +25,7 @@ editRoom: "Room Edit"
|
|||
comingFuture: "Coming with future update!"
|
||||
processing: "Processing now...<br />Keep this window open!"
|
||||
lostWarning: "Unsaved data will be lost if you leave the page, are you sure?"
|
||||
cannotUndone: "This process cannot be undone. Are you sure?"
|
||||
staticLink:
|
||||
title: "Your Audon Link"
|
||||
hint: "Other participants can join to your room via this personal link while you're hosting."
|
||||
|
@ -33,8 +34,8 @@ form:
|
|||
titleRequired: "Room title required"
|
||||
description: "Description"
|
||||
restriction: "Who can join"
|
||||
cohosts: "Cohosts"
|
||||
cohostCanAlwaysJoin: "Cohosts can join regardless of this setting."
|
||||
cohosts: "CoHosts"
|
||||
cohostCanAlwaysJoin: "CoHosts can join regardless of this setting."
|
||||
schedule: "Schedule at"
|
||||
advertise: "Allow the bot ({bot}) to advertise your room"
|
||||
relationships:
|
||||
|
@ -43,7 +44,7 @@ form:
|
|||
follower: "Followers-only"
|
||||
knowing: "Followed accounts and/or followers"
|
||||
mutual: "Your mutuals"
|
||||
private: "Cohosts only"
|
||||
private: "CoHosts only"
|
||||
shareRoomMessage: "Join my Audon room!\n{link}\n\nTitle: {title}"
|
||||
roomReady:
|
||||
header: "Your room is ready!"
|
||||
|
@ -82,6 +83,15 @@ speakRequest:
|
|||
microphoneBlocked: "Your browser has blocked access to the microphone. Check permission settings of your device and browser."
|
||||
closeRoomConfirm: "Are you sure you want to close this room?"
|
||||
roomEvent:
|
||||
closedByHost: "Host has closed this room."
|
||||
closedByHost: "This room has been closed."
|
||||
removed: "You have been requested to leave."
|
||||
disconnected: "Disconnected from this room."
|
||||
moderation:
|
||||
promote: "Promote to {role}"
|
||||
demote: "Demote to listener"
|
||||
kick: "Kick out"
|
||||
role:
|
||||
host: "Host"
|
||||
cohost: "CoHost"
|
||||
speaker: "Speaker"
|
||||
listener: "Listener"
|
||||
|
|
|
@ -25,6 +25,7 @@ editRoom: "部屋の編集"
|
|||
comingFuture: "今後のアップデートで追加予定"
|
||||
processing: "処理中です。<br />画面を閉じないでください。"
|
||||
lostWarning: "この画面を閉じると保存前の内容が失われます。構いませんか?"
|
||||
cannotUndone: "この操作は取り消せません。続行しますか?"
|
||||
staticLink:
|
||||
title: "Audon リンク"
|
||||
hint: "あなたが部屋をホストしたとき、他の人はこの固定 URL からでも参加できます。"
|
||||
|
@ -82,6 +83,15 @@ speakRequest:
|
|||
microphoneBlocked: "マイクが禁止されています。ブラウザやデバイスの設定からマイクの使用を許可してください。"
|
||||
closeRoomConfirm: "この部屋を閉じますか?"
|
||||
roomEvent:
|
||||
closedByHost: "ホストにより部屋が閉じられました。"
|
||||
closedByHost: "部屋が閉じられました。"
|
||||
removed: "リクエストにより部屋から退去しました。"
|
||||
disconneced: "切断されました。"
|
||||
moderation:
|
||||
promote: "{role} にする"
|
||||
demote: "リスナー に戻す"
|
||||
kick: "追い出す"
|
||||
role:
|
||||
host: "ホスト"
|
||||
cohost: "共同ホスト"
|
||||
speaker: "スピーカー"
|
||||
listener: "リスナー"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import axios from "axios";
|
||||
import { pushNotFound, webfinger } from "../assets/utils";
|
||||
import { useMastodonStore } from "../stores/mastodon";
|
||||
import { map, some, omit, filter, trim, clone } from "lodash-es";
|
||||
import { map, some, omit, filter, trim, clone, differenceBy } from "lodash-es";
|
||||
import { darkTheme } from "picmo";
|
||||
import { createPopup } from "@picmo/popup-picker";
|
||||
import { Howl } from "howler";
|
||||
|
@ -126,7 +126,6 @@ export default {
|
|||
publish: {
|
||||
audioBitrate: AudioPresets.music,
|
||||
forceStereo: false,
|
||||
source: Track.Source.Microphone,
|
||||
},
|
||||
},
|
||||
roomInfo: {
|
||||
|
@ -163,6 +162,7 @@ export default {
|
|||
showRequestDialog: false,
|
||||
showRequestedNotification: false,
|
||||
isEditLoading: false,
|
||||
isRequestLoading: false,
|
||||
closeLoading: false,
|
||||
showEditDialog: false,
|
||||
timeElapsed: "",
|
||||
|
@ -245,7 +245,10 @@ export default {
|
|||
return this.isSpeaker(myAudonID);
|
||||
},
|
||||
micStatusIcon() {
|
||||
if (!this.micGranted) {
|
||||
if (
|
||||
!this.micGranted ||
|
||||
!(this.iamHost || this.iamCohost || this.iamSpeaker)
|
||||
) {
|
||||
return mdiMicrophoneQuestion;
|
||||
}
|
||||
if (this.iamMuted) {
|
||||
|
@ -385,15 +388,39 @@ export default {
|
|||
}
|
||||
})
|
||||
.on(RoomEvent.RoomMetadataChanged, (metadata) => {
|
||||
self.roomInfo = JSON.parse(metadata);
|
||||
const newRoominfo = JSON.parse(metadata);
|
||||
const myAudonID = self.donStore.oauth.audon.audon_id;
|
||||
const iamNewCohost = some(
|
||||
differenceBy(
|
||||
newRoominfo.cohosts,
|
||||
self.roomInfo.cohosts,
|
||||
"audon_id"
|
||||
),
|
||||
(v) => v.audon_id === myAudonID
|
||||
);
|
||||
if (iamNewCohost) {
|
||||
self.closeLoading = true;
|
||||
self.roomClient.disconnect();
|
||||
self.donStore.revertAvatar().finally(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
const iamNewSpeaker = some(
|
||||
differenceBy(
|
||||
newRoominfo.speakers,
|
||||
self.roomInfo.speakers,
|
||||
"audon_id"
|
||||
),
|
||||
(v) => v.audon_id === myAudonID
|
||||
);
|
||||
self.roomInfo = newRoominfo;
|
||||
self.editingRoomInfo = clone(self.roomInfo);
|
||||
if (!self.roomInfo.speakers) return;
|
||||
for (const speakers of self.roomInfo.speakers) {
|
||||
self.speakRequests.delete(speakers.audon_id);
|
||||
if (self.speakRequests.size < 1)
|
||||
self.showRequestNotification = false;
|
||||
}
|
||||
if (self.iamSpeaker && !self.micGranted) {
|
||||
if (self.iamSpeaker && iamNewSpeaker) {
|
||||
self.roomClient.localParticipant
|
||||
.setMicrophoneEnabled(
|
||||
true,
|
||||
|
@ -405,6 +432,7 @@ export default {
|
|||
})
|
||||
.finally(() => {
|
||||
self.roomClient.localParticipant.setMicrophoneEnabled(false);
|
||||
self.mutedSpeakerIDs.add(myAudonID);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -480,13 +508,19 @@ export default {
|
|||
this.sounds.request.play();
|
||||
}
|
||||
},
|
||||
async onAcceptRequest(identity) {
|
||||
// promote user to a speaker
|
||||
// the livekit server will update room metadata
|
||||
async onModerate(identity, op) {
|
||||
if (!identity) return;
|
||||
if (op === "kick" || op === "cohost") {
|
||||
if (!confirm(this.$t("cannotUndone"))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.isRequestLoading = true;
|
||||
try {
|
||||
await axios.put(`/api/room/${this.roomID}/${identity}`);
|
||||
} catch (reqError) {
|
||||
console.log("permission update request error: ", reqError);
|
||||
await axios.put(`/api/room/${this.roomID}`, { identity, op });
|
||||
} finally {
|
||||
this.isRequestLoading = false;
|
||||
this.speakRequests.delete(identity);
|
||||
}
|
||||
},
|
||||
async onDeclineRequest(identity) {
|
||||
|
@ -585,6 +619,7 @@ export default {
|
|||
displayName: account.displayName,
|
||||
avatar: account.avatar,
|
||||
url: account.url,
|
||||
identity,
|
||||
};
|
||||
if (resp.data.avatar) {
|
||||
info.avatar = `/storage/${resp.data.audon_id}/avatar/${resp.data.avatar}`;
|
||||
|
@ -736,7 +771,7 @@ export default {
|
|||
@connect.once="joinRoom"
|
||||
></JoinDialog>
|
||||
<v-dialog v-model="showRequestDialog" max-width="500">
|
||||
<v-card class="d-flex flex-column">
|
||||
<v-card :loading="isRequestLoading" class="d-flex flex-column">
|
||||
<v-card-title>{{ $t("speakRequest.label") }}</v-card-title>
|
||||
<v-card-text class="flex-grow-1 overflow-auto py-0">
|
||||
<v-list v-if="speakRequests.size > 0" lines="two" variant="tonal">
|
||||
|
@ -758,12 +793,14 @@ export default {
|
|||
size="small"
|
||||
variant="text"
|
||||
:icon="mdiCheck"
|
||||
@click="onAcceptRequest(id)"
|
||||
:disabled="isRequestLoading"
|
||||
@click.once="onModerate(id, 'speaker')"
|
||||
></v-btn>
|
||||
<v-btn
|
||||
size="small"
|
||||
variant="text"
|
||||
:icon="mdiClose"
|
||||
:disabled="isRequestLoading"
|
||||
@click="onDeclineRequest(id)"
|
||||
></v-btn>
|
||||
</template>
|
||||
|
@ -884,6 +921,8 @@ export default {
|
|||
:data="cachedMastoData[key]"
|
||||
:muted="mutedSpeakerIDs.has(key)"
|
||||
:emoji="emojiReactions[key]?.emoji"
|
||||
@moderate="onModerate"
|
||||
:enable-menu="iamHost || iamCohost"
|
||||
>
|
||||
</Participant>
|
||||
</template>
|
||||
|
@ -895,6 +934,8 @@ export default {
|
|||
:data="cachedMastoData[key]"
|
||||
type="listener"
|
||||
:emoji="emojiReactions[key]?.emoji"
|
||||
@moderate="onModerate"
|
||||
:enable-menu="iamHost || iamCohost"
|
||||
></Participant>
|
||||
</template>
|
||||
</v-row>
|
||||
|
|
137
room.go
137
room.go
|
@ -34,7 +34,7 @@ func createRoomHandler(c echo.Context) error {
|
|||
host := c.Get("user").(*AudonUser)
|
||||
room.Host = host
|
||||
|
||||
// check if user is already hosting
|
||||
// check if user is already hosting or cohosting
|
||||
lkRooms, err := host.GetCurrentLivekitRooms(c.Request().Context())
|
||||
if err != nil {
|
||||
c.Logger().Error(err)
|
||||
|
@ -46,7 +46,7 @@ func createRoomHandler(c echo.Context) error {
|
|||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
if meta.Host.Equal(host) {
|
||||
if meta.IsHost(host) || meta.IsCoHost(host) {
|
||||
return ErrOperationNotPermitted
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ func createRoomHandler(c echo.Context) error {
|
|||
}
|
||||
|
||||
// Create livekit room
|
||||
roomMetadata := &RoomMetadata{Room: room, MastodonAccounts: make(map[string]*MastodonAccount)}
|
||||
roomMetadata := &RoomMetadata{Room: room, Speakers: []*AudonUser{}, Kicked: []*AudonUser{}, MastodonAccounts: make(map[string]*MastodonAccount)}
|
||||
metadata, _ := json.Marshal(roomMetadata)
|
||||
_, err = lkRoomServiceClient.CreateRoom(c.Request().Context(), &livekit.CreateRoomRequest{
|
||||
Name: room.RoomID,
|
||||
|
@ -257,13 +257,14 @@ func joinRoomHandler(c echo.Context) (err error) {
|
|||
return ErrAlreadyEnded
|
||||
}
|
||||
|
||||
// return 403 if one has been kicked
|
||||
for _, kicked := range room.Kicked {
|
||||
if kicked.Equal(user) {
|
||||
return echo.NewHTTPError(http.StatusForbidden)
|
||||
}
|
||||
lkRoom, _ := getRoomInLivekit(c.Request().Context(), room.RoomID) // lkRoom will be nil if it doesn't exist
|
||||
if lkRoom == nil {
|
||||
return ErrRoomNotFound
|
||||
}
|
||||
|
||||
roomMetadata, _ := getRoomMetadataFromLivekitRoom(lkRoom)
|
||||
room = roomMetadata.Room
|
||||
|
||||
canTalk := room.IsHost(user) || room.IsCoHost(user) // host and cohost can talk from the beginning
|
||||
|
||||
// check room restriction
|
||||
|
@ -301,19 +302,18 @@ func joinRoomHandler(c echo.Context) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
roomMetadata := &RoomMetadata{Room: room, MastodonAccounts: make(map[string]*MastodonAccount)}
|
||||
// return 403 if one has been kicked
|
||||
for _, kicked := range roomMetadata.Kicked {
|
||||
if kicked.Equal(user) {
|
||||
return echo.NewHTTPError(http.StatusForbidden)
|
||||
}
|
||||
}
|
||||
|
||||
// Allows the user to talk if the user is a speaker
|
||||
lkRoom, _ := getRoomInLivekit(c.Request().Context(), room.RoomID) // lkRoom will be nil if it doesn't exist
|
||||
if lkRoom != nil {
|
||||
if existingMetadata, _ := getRoomMetadataFromLivekitRoom(lkRoom); existingMetadata != nil {
|
||||
roomMetadata = existingMetadata
|
||||
for _, speaker := range existingMetadata.Speakers {
|
||||
if speaker.AudonID == user.AudonID {
|
||||
canTalk = true
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, speaker := range roomMetadata.Speakers {
|
||||
if speaker.AudonID == user.AudonID {
|
||||
canTalk = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -401,13 +401,8 @@ func joinRoomHandler(c echo.Context) (err error) {
|
|||
}
|
||||
|
||||
// Update room metadata
|
||||
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)
|
||||
roomMetadata.MastodonAccounts[user.AudonID] = mastoAccount
|
||||
newMetadata, err := json.Marshal(roomMetadata)
|
||||
if err != nil {
|
||||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
|
@ -429,7 +424,7 @@ func joinRoomHandler(c echo.Context) (err error) {
|
|||
return c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
// intended to be called by room's host
|
||||
// intended to be called by room's host or cohost
|
||||
func closeRoomHandler(c echo.Context) error {
|
||||
roomID := c.Param("id")
|
||||
if err := mainValidator.Var(&roomID, "required,printascii"); err != nil {
|
||||
|
@ -444,15 +439,19 @@ func closeRoomHandler(c echo.Context) error {
|
|||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// return 410 if the room has already ended
|
||||
if !room.EndedAt.IsZero() {
|
||||
return ErrAlreadyEnded
|
||||
}
|
||||
|
||||
meta := room.getRoomMetadata(c.Request().Context())
|
||||
if meta == nil {
|
||||
return ErrRoomNotFound
|
||||
}
|
||||
|
||||
// only host or cohost can close the room
|
||||
user := c.Get("user").(*AudonUser)
|
||||
if !room.IsHost(user) && !room.IsCoHost(user) {
|
||||
if !meta.IsHost(user) && !meta.IsCoHost(user) {
|
||||
return ErrOperationNotPermitted
|
||||
}
|
||||
|
||||
|
@ -481,8 +480,8 @@ func leaveRoomHandler(c echo.Context) error {
|
|||
return c.NoContent(http.StatusOK)
|
||||
}
|
||||
|
||||
func updatePermissionHandler(c echo.Context) error {
|
||||
roomID := c.Param("room")
|
||||
func updateRoleHandler(c echo.Context) error {
|
||||
roomID := c.Param("id")
|
||||
|
||||
// look up lkRoom in livekit
|
||||
lkRoom, exists := getRoomInLivekit(c.Request().Context(), roomID)
|
||||
|
@ -502,7 +501,12 @@ func updatePermissionHandler(c echo.Context) error {
|
|||
return ErrOperationNotPermitted
|
||||
}
|
||||
|
||||
audonID := c.Param("user")
|
||||
params := make(map[string]string)
|
||||
if err := c.Bind(¶ms); err != nil {
|
||||
return ErrInvalidRequestFormat
|
||||
}
|
||||
audonID := params["identity"]
|
||||
operation := params["op"]
|
||||
if !lkRoomMetadata.IsUserInLivekitRoom(c.Request().Context(), audonID) {
|
||||
return ErrUserNotFound
|
||||
}
|
||||
|
@ -517,17 +521,48 @@ func updatePermissionHandler(c echo.Context) error {
|
|||
newPermission := &livekit.ParticipantPermission{
|
||||
CanPublishData: true,
|
||||
CanSubscribe: true,
|
||||
CanPublish: true,
|
||||
}
|
||||
|
||||
// promote user to a speaker
|
||||
if c.Request().Method == http.MethodPut {
|
||||
newPermission.CanPublish = true
|
||||
if operation == "speaker" {
|
||||
for _, speaker := range lkRoomMetadata.Speakers {
|
||||
if speaker.Equal(tgtUser) {
|
||||
return echo.NewHTTPError(http.StatusConflict, "already_speaking")
|
||||
}
|
||||
}
|
||||
lkRoomMetadata.Speakers = append(lkRoomMetadata.Speakers, tgtUser)
|
||||
} else if operation == "cohost" {
|
||||
lkRoomMetadata.CoHosts = append(lkRoomMetadata.CoHosts, tgtUser)
|
||||
coll := mainDB.Collection(COLLECTION_ROOM)
|
||||
if _, err = coll.UpdateOne(c.Request().Context(),
|
||||
bson.D{{Key: "room_id", Value: roomID}},
|
||||
bson.D{{Key: "$set", Value: bson.D{{
|
||||
Key: "cohosts",
|
||||
Value: lkRoomMetadata.CoHosts,
|
||||
}}}}); err != nil {
|
||||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
} else if operation == "kick" {
|
||||
lkRoomMetadata.Kicked = append(lkRoomMetadata.Kicked, tgtUser)
|
||||
lkRoomServiceClient.RemoveParticipant(c.Request().Context(), &livekit.RoomParticipantIdentity{
|
||||
Room: roomID,
|
||||
Identity: tgtUser.AudonID,
|
||||
})
|
||||
} else if operation == "demote" {
|
||||
newPermission.CanPublish = false
|
||||
} else {
|
||||
return ErrInvalidRequestFormat
|
||||
}
|
||||
|
||||
if operation == "demote" || operation == "cohost" {
|
||||
newSpeakers := make([]*AudonUser, 0, len(lkRoomMetadata.Speakers))
|
||||
for _, v := range lkRoomMetadata.Speakers {
|
||||
if v.AudonID != tgtUser.AudonID {
|
||||
newSpeakers = append(newSpeakers, v)
|
||||
}
|
||||
}
|
||||
lkRoomMetadata.Speakers = newSpeakers
|
||||
}
|
||||
|
||||
newMetadata, err := json.Marshal(lkRoomMetadata)
|
||||
|
@ -535,26 +570,28 @@ func updatePermissionHandler(c echo.Context) error {
|
|||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
_, err = lkRoomServiceClient.UpdateRoomMetadata(c.Request().Context(), &livekit.UpdateRoomMetadataRequest{
|
||||
Room: roomID,
|
||||
Metadata: string(newMetadata),
|
||||
})
|
||||
|
||||
if operation != "kick" {
|
||||
_, err = lkRoomServiceClient.UpdateParticipant(c.Request().Context(), &livekit.UpdateParticipantRequest{
|
||||
Room: roomID,
|
||||
Identity: audonID,
|
||||
Permission: newPermission,
|
||||
})
|
||||
if err != nil {
|
||||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
metadataRequest := &livekit.UpdateRoomMetadataRequest{Room: roomID, Metadata: string(newMetadata)}
|
||||
|
||||
_, err = lkRoomServiceClient.UpdateRoomMetadata(context.Background(), metadataRequest)
|
||||
if err != nil {
|
||||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
info, err := lkRoomServiceClient.UpdateParticipant(c.Request().Context(), &livekit.UpdateParticipantRequest{
|
||||
Room: roomID,
|
||||
Identity: audonID,
|
||||
Permission: newPermission,
|
||||
})
|
||||
if err != nil {
|
||||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, info)
|
||||
return c.NoContent(http.StatusOK)
|
||||
}
|
||||
|
||||
func getRoomToken(room *Room, user *AudonUser, canTalk bool) (string, error) {
|
||||
|
|
19
schema.go
19
schema.go
|
@ -31,6 +31,7 @@ type (
|
|||
RoomMetadata struct {
|
||||
*Room
|
||||
Speakers []*AudonUser `json:"speakers"`
|
||||
Kicked []*AudonUser `json:"kicked"`
|
||||
MastodonAccounts map[string]*MastodonAccount `json:"accounts"`
|
||||
}
|
||||
|
||||
|
@ -41,7 +42,6 @@ type (
|
|||
Host *AudonUser `bson:"host" json:"host"`
|
||||
CoHosts []*AudonUser `bson:"cohosts" json:"cohosts"`
|
||||
Restriction JoinRestriction `bson:"restriction" json:"restriction"`
|
||||
Kicked []*AudonUser `bson:"kicked" json:"kicked"`
|
||||
EndedAt time.Time `bson:"ended_at" json:"ended_at"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"created_at"`
|
||||
Advertise string `bson:"advertise" json:"advertise"`
|
||||
|
@ -90,6 +90,11 @@ func (a *AudonUser) GetCurrentLivekitRooms(ctx context.Context) ([]*livekit.Room
|
|||
break
|
||||
}
|
||||
}
|
||||
// check host
|
||||
room, _ := getRoomMetadataFromLivekitRoom(r)
|
||||
if room.IsHost(a) {
|
||||
current = append(current, r)
|
||||
}
|
||||
}
|
||||
return current, nil
|
||||
}
|
||||
|
@ -150,6 +155,18 @@ func getRoomMetadataFromLivekitRoom(lkRoom *livekit.Room) (*RoomMetadata, error)
|
|||
return metadata, nil
|
||||
}
|
||||
|
||||
func (r *Room) getRoomMetadata(ctx context.Context) *RoomMetadata {
|
||||
lkRoom, _ := getRoomInLivekit(ctx, r.RoomID)
|
||||
if lkRoom == nil {
|
||||
return nil
|
||||
}
|
||||
meta, err := getRoomMetadataFromLivekitRoom(lkRoom)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return meta
|
||||
}
|
||||
|
||||
func (r *Room) ExistsInLivekit(ctx context.Context) bool {
|
||||
lkRooms, _ := lkRoomServiceClient.ListRooms(ctx, &livekit.ListRoomsRequest{Names: []string{r.RoomID}})
|
||||
|
||||
|
|
|
@ -179,7 +179,7 @@ func main() {
|
|||
api.POST("/room/:id", joinRoomHandler)
|
||||
api.PATCH("/room/:id", updateRoomHandler)
|
||||
api.DELETE("/room/:id", closeRoomHandler)
|
||||
api.PUT("/room/:room/:user", updatePermissionHandler)
|
||||
api.PUT("/room/:id", updateRoleHandler)
|
||||
|
||||
e.Static("/assets", "audon-fe/dist/assets")
|
||||
e.Static("/static", "audon-fe/dist/static")
|
||||
|
|
17
user.go
17
user.go
|
@ -82,9 +82,24 @@ func redirectUserHandler(c echo.Context) error {
|
|||
opts := options.FindOne().SetSort(bson.D{{Key: "created_at", Value: -1}})
|
||||
var room Room
|
||||
|
||||
if err := coll.FindOne(c.Request().Context(), bson.D{{Key: "host.audon_id", Value: user.AudonID}}, opts).Decode(&room); err == nil {
|
||||
if err := coll.FindOne(c.Request().Context(), bson.D{
|
||||
{Key: "host.audon_id", Value: user.AudonID},
|
||||
}, opts).Decode(&room); err == nil {
|
||||
if room.ExistsInLivekit(c.Request().Context()) {
|
||||
// redirect to the hosting room if online
|
||||
return c.Redirect(http.StatusFound, fmt.Sprintf("/r/%s", room.RoomID))
|
||||
} else {
|
||||
// redirect to the first cohosting room if online
|
||||
status, err := user.GetCurrentRoomStatus(c.Request().Context())
|
||||
if err != nil {
|
||||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
for _, v := range status {
|
||||
if v.Role == "cohost" {
|
||||
return c.Redirect(http.StatusFound, fmt.Sprintf("/r/%s", v.RoomID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue