mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
Merge pull request #394 from Monadical-SAS/zulip-auto-post
Zulip auto post
This commit is contained in:
@@ -7,6 +7,7 @@ database = databases.Database(settings.DATABASE_URL)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
|
||||
# import models
|
||||
import reflector.db.meetings # noqa
|
||||
import reflector.db.rooms # noqa
|
||||
import reflector.db.transcripts # noqa
|
||||
|
||||
|
||||
@@ -94,6 +94,16 @@ class MeetingController:
|
||||
|
||||
return Meeting(**result)
|
||||
|
||||
async def get_by_id(self, meeting_id: str, **kwargs) -> Meeting | None:
|
||||
"""
|
||||
Get a meeting by id
|
||||
"""
|
||||
query = meetings.select().where(meetings.c.id == meeting_id)
|
||||
result = await database.fetch_one(query)
|
||||
if not result:
|
||||
return None
|
||||
return Meeting(**result)
|
||||
|
||||
async def get_by_id_for_http(self, meeting_id: str, user_id: str | None) -> Meeting:
|
||||
"""
|
||||
Get a meeting by ID for HTTP request.
|
||||
|
||||
@@ -68,6 +68,9 @@ class RoomController:
|
||||
self,
|
||||
name: str,
|
||||
user_id: str,
|
||||
zulip_auto_post: bool,
|
||||
zulip_stream: str,
|
||||
zulip_topic: str,
|
||||
):
|
||||
"""
|
||||
Add a new room
|
||||
@@ -75,11 +78,24 @@ class RoomController:
|
||||
room = Room(
|
||||
name=name,
|
||||
user_id=user_id,
|
||||
zulip_auto_post=zulip_auto_post,
|
||||
zulip_stream=zulip_stream,
|
||||
zulip_topic=zulip_topic,
|
||||
)
|
||||
query = rooms.insert().values(**room.model_dump())
|
||||
await database.execute(query)
|
||||
return room
|
||||
|
||||
async def update(self, room: Room, values: dict, mutate=True):
|
||||
"""
|
||||
Update a room fields with key/values in values
|
||||
"""
|
||||
query = rooms.update().where(rooms.c.id == room.id).values(**values)
|
||||
await database.execute(query)
|
||||
if mutate:
|
||||
for key, value in values.items():
|
||||
setattr(room, key, value)
|
||||
|
||||
async def get_by_id(self, room_id: str, **kwargs) -> Room | None:
|
||||
"""
|
||||
Get a room by id
|
||||
|
||||
@@ -17,6 +17,8 @@ from contextlib import asynccontextmanager
|
||||
|
||||
from celery import chord, group, shared_task
|
||||
from pydantic import BaseModel
|
||||
from reflector.db.meetings import meetings_controller
|
||||
from reflector.db.rooms import rooms_controller
|
||||
from reflector.db.transcripts import (
|
||||
Transcript,
|
||||
TranscriptDuration,
|
||||
@@ -53,6 +55,7 @@ from reflector.processors.types import (
|
||||
from reflector.processors.types import Transcript as TranscriptProcessorType
|
||||
from reflector.settings import settings
|
||||
from reflector.ws_manager import WebsocketManager, get_ws_manager
|
||||
from reflector.zulip import get_zulip_message, send_message_to_zulip
|
||||
from structlog import BoundLogger as Logger
|
||||
|
||||
|
||||
@@ -564,6 +567,31 @@ async def pipeline_summaries(transcript: Transcript, logger: Logger):
|
||||
logger.info("Summaries done")
|
||||
|
||||
|
||||
@get_transcript
|
||||
async def pipeline_post_to_zulip(transcript: Transcript, logger: Logger):
|
||||
logger.info("Starting post to zulip")
|
||||
|
||||
if not transcript.meeting_id:
|
||||
logger.info("Transcript has no meeting")
|
||||
return
|
||||
|
||||
meeting = await meetings_controller.get_by_id(transcript.meeting_id)
|
||||
if not meeting:
|
||||
logger.info("No meeting found for this transcript")
|
||||
return
|
||||
|
||||
room = await rooms_controller.get_by_id(meeting.room_id)
|
||||
if not room:
|
||||
logger.error(f"Missing room for a meeting {meeting.id}")
|
||||
return
|
||||
|
||||
if room.zulip_auto_post:
|
||||
message = get_zulip_message(transcript=transcript)
|
||||
send_message_to_zulip(room.zulip_stream, room.zulip_topic, message)
|
||||
|
||||
logger.info("Posted to zulip")
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# Celery tasks that can be called from the API
|
||||
# ===================================================================
|
||||
@@ -611,6 +639,12 @@ async def task_pipeline_final_summaries(*, transcript_id: str):
|
||||
await pipeline_summaries(transcript_id=transcript_id)
|
||||
|
||||
|
||||
@shared_task
|
||||
@asynctask
|
||||
async def task_pipeline_post_to_zulip(*, transcript_id: str):
|
||||
await pipeline_post_to_zulip(transcript_id=transcript_id)
|
||||
|
||||
|
||||
def pipeline_post(*, transcript_id: str):
|
||||
"""
|
||||
Run the post pipeline
|
||||
@@ -632,7 +666,8 @@ def pipeline_post(*, transcript_id: str):
|
||||
chain = chord(
|
||||
group(chain_mp3_and_diarize, chain_title_preview),
|
||||
chain_final_summaries,
|
||||
)
|
||||
) | task_pipeline_post_to_zulip.si(transcript_id=transcript_id)
|
||||
|
||||
chain.delay()
|
||||
|
||||
|
||||
|
||||
@@ -141,5 +141,9 @@ class Settings(BaseSettings):
|
||||
AWS_WHEREBY_ACCESS_KEY_ID: str | None = None
|
||||
AWS_WHEREBY_ACCESS_KEY_SECRET: str | None = None
|
||||
|
||||
ZULIP_REALM: str | None = None
|
||||
ZULIP_API_KEY: str | None = None
|
||||
ZULIP_BOT_EMAIL: str | None = None
|
||||
|
||||
|
||||
settings = Settings()
|
||||
|
||||
@@ -21,6 +21,9 @@ class Room(BaseModel):
|
||||
name: str
|
||||
user_id: str
|
||||
created_at: datetime
|
||||
zulip_auto_post: bool
|
||||
zulip_stream: str
|
||||
zulip_topic: str
|
||||
|
||||
|
||||
class Meeting(BaseModel):
|
||||
@@ -35,6 +38,16 @@ class Meeting(BaseModel):
|
||||
|
||||
class CreateRoom(BaseModel):
|
||||
name: str
|
||||
zulip_auto_post: bool
|
||||
zulip_stream: str
|
||||
zulip_topic: str
|
||||
|
||||
|
||||
class UpdateRoom(BaseModel):
|
||||
name: str
|
||||
zulip_auto_post: bool
|
||||
zulip_stream: str
|
||||
zulip_topic: str
|
||||
|
||||
|
||||
class DeletionStatus(BaseModel):
|
||||
@@ -69,9 +82,27 @@ async def rooms_create(
|
||||
return await rooms_controller.add(
|
||||
name=room.name,
|
||||
user_id=user_id,
|
||||
zulip_auto_post=room.zulip_auto_post,
|
||||
zulip_stream=room.zulip_stream,
|
||||
zulip_topic=room.zulip_topic,
|
||||
)
|
||||
|
||||
|
||||
@router.patch("/rooms/{room_id}", response_model=Room)
|
||||
async def rooms_update(
|
||||
room_id: str,
|
||||
info: UpdateRoom,
|
||||
user: Annotated[Optional[auth.UserInfo], Depends(auth.current_user_optional)],
|
||||
):
|
||||
user_id = user["sub"] if user else None
|
||||
room = await rooms_controller.get_by_id_for_http(room_id, user_id=user_id)
|
||||
if not room:
|
||||
raise HTTPException(status_code=404, detail="Room not found")
|
||||
values = info.dict(exclude_unset=True)
|
||||
await rooms_controller.update(room, values)
|
||||
return room
|
||||
|
||||
|
||||
@router.delete("/rooms/{room_id}", response_model=DeletionStatus)
|
||||
async def rooms_delete(
|
||||
room_id: str,
|
||||
|
||||
72
server/reflector/zulip.py
Normal file
72
server/reflector/zulip.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from datetime import timedelta
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import requests
|
||||
from reflector.db.transcripts import Transcript
|
||||
from reflector.settings import settings
|
||||
|
||||
|
||||
def send_message_to_zulip(stream: str, topic: str, message: str):
|
||||
if not stream or not topic or not message:
|
||||
raise ValueError("Missing required parameters")
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
f"https://{settings.ZULIP_REALM}/api/v1/messages",
|
||||
data={
|
||||
"type": "stream",
|
||||
"to": stream,
|
||||
"topic": topic,
|
||||
"content": message,
|
||||
},
|
||||
auth=(settings.ZULIP_BOT_EMAIL, settings.ZULIP_API_KEY),
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
return response.json()
|
||||
except requests.RequestException as error:
|
||||
raise Exception(f"Failed to send message to Zulip: {error}")
|
||||
|
||||
|
||||
def get_zulip_message(transcript: Transcript):
|
||||
domain = (
|
||||
"http://localhost:3000" # Replace this with your deployment base URL if needed
|
||||
)
|
||||
transcript_url = f"{domain}/transcripts/{transcript.id}"
|
||||
|
||||
header_text = f"# Reflector – {transcript.title or 'Unnamed recording'}\n\n"
|
||||
header_text += f"**Date**: <time:{transcript.created_at.isoformat()}>\n"
|
||||
header_text += f"**Link**: [{extract_domain(transcript_url)}]({transcript_url})\n"
|
||||
header_text += f"**Duration**: {format_time_ms(transcript.duration)}\n\n"
|
||||
|
||||
topic_text = ""
|
||||
|
||||
if transcript.topics:
|
||||
topic_text = "```spoiler Topics\n"
|
||||
for topic in transcript.topics:
|
||||
topic_text += f"1. [{format_time(topic.timestamp)}] {topic.title}\n"
|
||||
topic_text += "```\n\n"
|
||||
|
||||
summary = "```spoiler Summary\n"
|
||||
summary += transcript.long_summary
|
||||
summary += "```\n\n"
|
||||
|
||||
message = header_text + summary + topic_text + "-----\n"
|
||||
return message
|
||||
|
||||
|
||||
def extract_domain(url: str) -> str:
|
||||
return urlparse(url).netloc
|
||||
|
||||
|
||||
def format_time_ms(milliseconds: float) -> str:
|
||||
return format_time(milliseconds // 1000)
|
||||
|
||||
|
||||
def format_time(seconds: float) -> str:
|
||||
td = timedelta(seconds=seconds)
|
||||
time = str(td - timedelta(microseconds=td.microseconds))
|
||||
|
||||
return time[2:] if time.startswith("0:") else time
|
||||
3
www/.gitignore
vendored
3
www/.gitignore
vendored
@@ -41,3 +41,6 @@ next-env.d.ts
|
||||
.sentryclirc
|
||||
|
||||
config.ts
|
||||
|
||||
# openapi logs
|
||||
openapi-ts-error-*.log
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
CardBody,
|
||||
@@ -9,7 +8,6 @@ import {
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
FormLabel,
|
||||
Grid,
|
||||
Heading,
|
||||
Input,
|
||||
Link,
|
||||
@@ -29,47 +27,145 @@ import {
|
||||
MenuButton,
|
||||
MenuList,
|
||||
MenuItem,
|
||||
AlertDialog,
|
||||
IconButton,
|
||||
Checkbox,
|
||||
} from "@chakra-ui/react";
|
||||
import NextLink from "next";
|
||||
import React, { ReactNode, useState } from "react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { Container } from "@chakra-ui/react";
|
||||
import { PlusSquareIcon } from "@chakra-ui/icons";
|
||||
import { FaEllipsisVertical, FaTrash, FaPencil } from "react-icons/fa6";
|
||||
import useApi from "../../lib/useApi";
|
||||
import useRoomList from "./useRoomList";
|
||||
import { FaEllipsisVertical, FaTrash } from "react-icons/fa6";
|
||||
import next from "next";
|
||||
import { DomainContext } from "../domainContext";
|
||||
import { Select, Options, OptionBase } from "chakra-react-select";
|
||||
|
||||
interface Stream {
|
||||
id: number;
|
||||
name: string;
|
||||
topics: string[];
|
||||
}
|
||||
|
||||
interface SelectOption extends OptionBase {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export default function RoomsList() {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const [roomName, setRoomName] = useState("");
|
||||
const [room, setRoom] = useState({
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
});
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [editRoomId, setEditRoomId] = useState("");
|
||||
const api = useApi();
|
||||
const [page, setPage] = useState<number>(1);
|
||||
const { loading, response, refetch } = useRoomList(page);
|
||||
const [streams, setStreams] = useState<Stream[]>([]);
|
||||
|
||||
const handleAddRoom = async () => {
|
||||
const { zulip_streams } = useContext(DomainContext);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchZulipStreams = async () => {
|
||||
try {
|
||||
const response = await fetch(zulip_streams + "/streams.json");
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
let data = await response.json();
|
||||
data = data.sort((a: Stream, b: Stream) =>
|
||||
a.name.localeCompare(b.name),
|
||||
);
|
||||
setStreams(data);
|
||||
} catch (err) {
|
||||
console.error("Error fetching streams:", err);
|
||||
}
|
||||
};
|
||||
|
||||
if (room.zulipAutoPost) {
|
||||
fetchZulipStreams();
|
||||
}
|
||||
}, [room.zulipAutoPost]);
|
||||
|
||||
const streamOptions: Options<SelectOption> = streams.map((stream) => {
|
||||
return { label: stream.name, value: stream.name };
|
||||
});
|
||||
|
||||
const topicOptions =
|
||||
streams
|
||||
.find((stream) => stream.name === room.zulipStream)
|
||||
?.topics.map((topic) => ({ label: topic, value: topic })) || [];
|
||||
|
||||
const handleSaveRoom = async () => {
|
||||
try {
|
||||
const response = await api?.v1RoomsCreate({
|
||||
requestBody: { name: roomName },
|
||||
console.log(room);
|
||||
if (isEditing) {
|
||||
await api?.v1RoomsUpdate({
|
||||
roomId: editRoomId,
|
||||
requestBody: {
|
||||
name: room.name,
|
||||
zulip_auto_post: room.zulipAutoPost,
|
||||
zulip_stream: room.zulipStream,
|
||||
zulip_topic: room.zulipTopic,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await api?.v1RoomsCreate({
|
||||
requestBody: {
|
||||
name: room.name,
|
||||
zulip_auto_post: room.zulipAutoPost,
|
||||
zulip_stream: room.zulipStream,
|
||||
zulip_topic: room.zulipTopic,
|
||||
},
|
||||
});
|
||||
}
|
||||
setRoom({
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
});
|
||||
setRoomName("");
|
||||
setIsEditing(false);
|
||||
setEditRoomId("");
|
||||
refetch();
|
||||
} catch (err) {}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleEditRoom = (roomId, roomData) => {
|
||||
setRoom({
|
||||
name: roomData.name,
|
||||
zulipAutoPost: roomData.zulip_auto_post,
|
||||
zulipStream: roomData.zulip_stream,
|
||||
zulipTopic: roomData.zulip_topic,
|
||||
});
|
||||
setEditRoomId(roomId);
|
||||
setIsEditing(true);
|
||||
onOpen();
|
||||
};
|
||||
|
||||
const handleDeleteRoom = async (roomId: string) => {
|
||||
try {
|
||||
const response = await api?.v1RoomsDelete({
|
||||
await api?.v1RoomsDelete({
|
||||
roomId,
|
||||
});
|
||||
refetch();
|
||||
} catch (err) {}
|
||||
};
|
||||
|
||||
const handleRoomNameChange = (e) => {
|
||||
setRoomName(e.target.value);
|
||||
const handleRoomChange = (e) => {
|
||||
let { name, value, type, checked } = e.target;
|
||||
if (name === "name") {
|
||||
value = value
|
||||
.replace(/[^a-zA-Z0-9\s-]/g, "")
|
||||
.replace(/\s+/g, "-")
|
||||
.toLowerCase();
|
||||
}
|
||||
setRoom({
|
||||
...room,
|
||||
[name]: type === "checkbox" ? checked : value,
|
||||
});
|
||||
};
|
||||
|
||||
if (loading && !response)
|
||||
@@ -91,23 +187,81 @@ export default function RoomsList() {
|
||||
>
|
||||
<Heading>Rooms</Heading>
|
||||
<Spacer />
|
||||
<Button colorScheme="blue" onClick={onOpen}>
|
||||
<Button
|
||||
colorScheme="blue"
|
||||
onClick={() => {
|
||||
setIsEditing(false);
|
||||
setRoom({
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
});
|
||||
onOpen();
|
||||
}}
|
||||
>
|
||||
Add Room
|
||||
</Button>
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader>Add Room</ModalHeader>
|
||||
<ModalHeader>{isEditing ? "Edit Room" : "Add Room"}</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<FormControl>
|
||||
<FormLabel>Room name</FormLabel>
|
||||
<Input
|
||||
name="name"
|
||||
placeholder="room-name"
|
||||
value={roomName}
|
||||
onChange={handleRoomNameChange}
|
||||
value={room.name}
|
||||
onChange={handleRoomChange}
|
||||
/>
|
||||
<FormHelperText>
|
||||
No spaces or special characters allowed
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
<FormControl mt={8}>
|
||||
<Checkbox
|
||||
name="zulipAutoPost"
|
||||
isChecked={room.zulipAutoPost}
|
||||
onChange={handleRoomChange}
|
||||
>
|
||||
Automatically post transcription to Zulip
|
||||
</Checkbox>
|
||||
</FormControl>
|
||||
<FormControl mt={4}>
|
||||
<FormLabel>Zulip stream</FormLabel>
|
||||
<Select
|
||||
name="zulipStream"
|
||||
options={streamOptions}
|
||||
placeholder="Select stream"
|
||||
value={{ label: room.zulipStream, value: room.zulipStream }}
|
||||
onChange={(newValue) =>
|
||||
setRoom({
|
||||
...room,
|
||||
zulipStream: newValue!.value,
|
||||
zulipTopic: "",
|
||||
})
|
||||
}
|
||||
isDisabled={!room.zulipAutoPost}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl mt={4}>
|
||||
<FormLabel>Zulip topic</FormLabel>
|
||||
<Select
|
||||
name="zulipTopic"
|
||||
options={topicOptions}
|
||||
placeholder="Select topic"
|
||||
value={{ label: room.zulipTopic, value: room.zulipTopic }}
|
||||
onChange={(newValue) =>
|
||||
setRoom({
|
||||
...room,
|
||||
zulipTopic: newValue!.value,
|
||||
})
|
||||
}
|
||||
isDisabled={!room.zulipAutoPost}
|
||||
/>
|
||||
<FormHelperText>Please enter room name</FormHelperText>
|
||||
</FormControl>
|
||||
</ModalBody>
|
||||
|
||||
@@ -116,8 +270,14 @@ export default function RoomsList() {
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<Button colorScheme="blue" onClick={handleAddRoom}>
|
||||
Add
|
||||
<Button
|
||||
colorScheme="blue"
|
||||
onClick={handleSaveRoom}
|
||||
isDisabled={
|
||||
!room.name || (room.zulipAutoPost && !room.zulipTopic)
|
||||
}
|
||||
>
|
||||
{isEditing ? "Save" : "Add"}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
@@ -126,17 +286,13 @@ export default function RoomsList() {
|
||||
|
||||
<VStack>
|
||||
{response?.items && response.items.length > 0 ? (
|
||||
response.items.map((room) => (
|
||||
<Card w={"full"}>
|
||||
response.items.map((roomData) => (
|
||||
<Card w={"full"} key={roomData.id}>
|
||||
<CardBody>
|
||||
<Flex align={"center"}>
|
||||
<Heading size="md">
|
||||
<Link
|
||||
// as={NextLink}
|
||||
href={`/rooms/${room.name}`}
|
||||
noOfLines={2}
|
||||
>
|
||||
{room.name}
|
||||
<Link href={`/rooms/${roomData.name}`}>
|
||||
{roomData.name}
|
||||
</Link>
|
||||
</Heading>
|
||||
<Spacer />
|
||||
@@ -148,7 +304,13 @@ export default function RoomsList() {
|
||||
/>
|
||||
<MenuList>
|
||||
<MenuItem
|
||||
onClick={() => handleDeleteRoom(room.id)}
|
||||
onClick={() => handleEditRoom(roomData.id, roomData)}
|
||||
icon={<FaPencil />}
|
||||
>
|
||||
Edit
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => handleDeleteRoom(roomData.id)}
|
||||
icon={<FaTrash color={"red.500"} />}
|
||||
>
|
||||
Delete
|
||||
|
||||
@@ -59,9 +59,21 @@ export const $CreateRoom = {
|
||||
type: "string",
|
||||
title: "Name",
|
||||
},
|
||||
zulip_auto_post: {
|
||||
type: "boolean",
|
||||
title: "Zulip Auto Post",
|
||||
},
|
||||
zulip_stream: {
|
||||
type: "string",
|
||||
title: "Zulip Stream",
|
||||
},
|
||||
zulip_topic: {
|
||||
type: "string",
|
||||
title: "Zulip Topic",
|
||||
},
|
||||
},
|
||||
type: "object",
|
||||
required: ["name"],
|
||||
required: ["name", "zulip_auto_post", "zulip_stream", "zulip_topic"],
|
||||
title: "CreateRoom",
|
||||
} as const;
|
||||
|
||||
@@ -643,9 +655,29 @@ export const $Room = {
|
||||
format: "date-time",
|
||||
title: "Created At",
|
||||
},
|
||||
zulip_auto_post: {
|
||||
type: "boolean",
|
||||
title: "Zulip Auto Post",
|
||||
},
|
||||
zulip_stream: {
|
||||
type: "string",
|
||||
title: "Zulip Stream",
|
||||
},
|
||||
zulip_topic: {
|
||||
type: "string",
|
||||
title: "Zulip Topic",
|
||||
},
|
||||
},
|
||||
type: "object",
|
||||
required: ["id", "name", "user_id", "created_at"],
|
||||
required: [
|
||||
"id",
|
||||
"name",
|
||||
"user_id",
|
||||
"created_at",
|
||||
"zulip_auto_post",
|
||||
"zulip_stream",
|
||||
"zulip_topic",
|
||||
],
|
||||
title: "Room",
|
||||
} as const;
|
||||
|
||||
@@ -807,6 +839,30 @@ export const $UpdateParticipant = {
|
||||
title: "UpdateParticipant",
|
||||
} as const;
|
||||
|
||||
export const $UpdateRoom = {
|
||||
properties: {
|
||||
name: {
|
||||
type: "string",
|
||||
title: "Name",
|
||||
},
|
||||
zulip_auto_post: {
|
||||
type: "boolean",
|
||||
title: "Zulip Auto Post",
|
||||
},
|
||||
zulip_stream: {
|
||||
type: "string",
|
||||
title: "Zulip Stream",
|
||||
},
|
||||
zulip_topic: {
|
||||
type: "string",
|
||||
title: "Zulip Topic",
|
||||
},
|
||||
},
|
||||
type: "object",
|
||||
required: ["name", "zulip_auto_post", "zulip_stream", "zulip_topic"],
|
||||
title: "UpdateRoom",
|
||||
} as const;
|
||||
|
||||
export const $UpdateTranscript = {
|
||||
properties: {
|
||||
name: {
|
||||
|
||||
@@ -8,6 +8,8 @@ import type {
|
||||
V1RoomsListResponse,
|
||||
V1RoomsCreateData,
|
||||
V1RoomsCreateResponse,
|
||||
V1RoomsUpdateData,
|
||||
V1RoomsUpdateResponse,
|
||||
V1RoomsDeleteData,
|
||||
V1RoomsDeleteResponse,
|
||||
V1RoomsCreateMeetingData,
|
||||
@@ -120,6 +122,31 @@ export class DefaultService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Rooms Update
|
||||
* @param data The data for the request.
|
||||
* @param data.roomId
|
||||
* @param data.requestBody
|
||||
* @returns Room Successful Response
|
||||
* @throws ApiError
|
||||
*/
|
||||
public v1RoomsUpdate(
|
||||
data: V1RoomsUpdateData,
|
||||
): CancelablePromise<V1RoomsUpdateResponse> {
|
||||
return this.httpRequest.request({
|
||||
method: "PATCH",
|
||||
url: "/v1/rooms/{room_id}",
|
||||
path: {
|
||||
room_id: data.roomId,
|
||||
},
|
||||
body: data.requestBody,
|
||||
mediaType: "application/json",
|
||||
errors: {
|
||||
422: "Validation Error",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Rooms Delete
|
||||
* @param data The data for the request.
|
||||
|
||||
@@ -16,6 +16,9 @@ export type CreateParticipant = {
|
||||
|
||||
export type CreateRoom = {
|
||||
name: string;
|
||||
zulip_auto_post: boolean;
|
||||
zulip_stream: string;
|
||||
zulip_topic: string;
|
||||
};
|
||||
|
||||
export type CreateTranscript = {
|
||||
@@ -126,6 +129,9 @@ export type Room = {
|
||||
name: string;
|
||||
user_id: string;
|
||||
created_at: string;
|
||||
zulip_auto_post: boolean;
|
||||
zulip_stream: string;
|
||||
zulip_topic: string;
|
||||
};
|
||||
|
||||
export type RtcOffer = {
|
||||
@@ -165,6 +171,13 @@ export type UpdateParticipant = {
|
||||
name?: string | null;
|
||||
};
|
||||
|
||||
export type UpdateRoom = {
|
||||
name: string;
|
||||
zulip_auto_post: boolean;
|
||||
zulip_stream: string;
|
||||
zulip_topic: string;
|
||||
};
|
||||
|
||||
export type UpdateTranscript = {
|
||||
name?: string | null;
|
||||
locked?: boolean | null;
|
||||
@@ -216,6 +229,13 @@ export type V1RoomsCreateData = {
|
||||
|
||||
export type V1RoomsCreateResponse = Room;
|
||||
|
||||
export type V1RoomsUpdateData = {
|
||||
requestBody: UpdateRoom;
|
||||
roomId: string;
|
||||
};
|
||||
|
||||
export type V1RoomsUpdateResponse = Room;
|
||||
|
||||
export type V1RoomsDeleteData = {
|
||||
roomId: string;
|
||||
};
|
||||
@@ -426,6 +446,19 @@ export type $OpenApiTs = {
|
||||
};
|
||||
};
|
||||
"/v1/rooms/{room_id}": {
|
||||
patch: {
|
||||
req: V1RoomsUpdateData;
|
||||
res: {
|
||||
/**
|
||||
* Successful Response
|
||||
*/
|
||||
200: Room;
|
||||
/**
|
||||
* Validation Error
|
||||
*/
|
||||
422: HTTPValidationError;
|
||||
};
|
||||
};
|
||||
delete: {
|
||||
req: V1RoomsDeleteData;
|
||||
res: {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"@whereby.com/browser-sdk": "^3.3.4",
|
||||
"autoprefixer": "10.4.14",
|
||||
"axios": "^1.6.2",
|
||||
"chakra-react-select": "^4.7.6",
|
||||
"chakra-react-select": "^4.9.1",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-next": "^14.0.4",
|
||||
"fontawesome": "^5.6.3",
|
||||
|
||||
@@ -2347,12 +2347,12 @@ caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.300015
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz"
|
||||
integrity sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw==
|
||||
|
||||
chakra-react-select@^4.7.6:
|
||||
version "4.7.6"
|
||||
resolved "https://registry.yarnpkg.com/chakra-react-select/-/chakra-react-select-4.7.6.tgz#3be8ffb314b8e75ef02663fd3e2fdf872b79683b"
|
||||
integrity sha512-ZL43hyXPnWf1g/HjsZDecbeJ4F2Q6tTPYJozlKWkrQ7lIX7ORP0aZYwmc5/Wly4UNzMimj2Vuosl6MmIXH+G2g==
|
||||
chakra-react-select@^4.9.1:
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/chakra-react-select/-/chakra-react-select-4.9.1.tgz#38e421a0400c26e7f25d3dd28e6b93a021f08b77"
|
||||
integrity sha512-jmgfN+S/wnTaCp3pW30GYDIZ5J8jWcT1gIbhpw6RdKV+atm/U4/sT+gaHOHHhRL8xeaYip+iI/m8MPGREkve0w==
|
||||
dependencies:
|
||||
react-select "5.7.7"
|
||||
react-select "5.8.0"
|
||||
|
||||
chalk@3.0.0:
|
||||
version "3.0.0"
|
||||
@@ -5116,10 +5116,10 @@ react-select-search@^4.1.7:
|
||||
resolved "https://registry.yarnpkg.com/react-select-search/-/react-select-search-4.1.7.tgz#5662729b9052282bde52e1352006d495d9c5ed6e"
|
||||
integrity sha512-pU7ONAdK+bmz2tbhBWYQv9m5mnXOn8yImuiy+5UhimIG80d5iKv3nSYJIjJWjDbdrrdoXiCRwQm8xbA8llTjmQ==
|
||||
|
||||
react-select@5.7.7:
|
||||
version "5.7.7"
|
||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.7.7.tgz#dbade9dbf711ef2a181970c10f8ab319ac37fbd0"
|
||||
integrity sha512-HhashZZJDRlfF/AKj0a0Lnfs3sRdw/46VJIRd8IbB9/Ovr74+ZIwkAdSBjSPXsFMG+u72c5xShqwLSKIJllzqw==
|
||||
react-select@5.8.0:
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.8.0.tgz#bd5c467a4df223f079dd720be9498076a3f085b5"
|
||||
integrity sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.0"
|
||||
"@emotion/cache" "^11.4.0"
|
||||
|
||||
Reference in New Issue
Block a user