325 lines
9.5 KiB
TypeScript
325 lines
9.5 KiB
TypeScript
import { http } from "./http";
|
|
import type {
|
|
Chat,
|
|
ChatAttachment,
|
|
ChatDetail,
|
|
ChatInviteLink,
|
|
ChatMember,
|
|
ChatMemberRole,
|
|
ChatType,
|
|
DiscoverChat,
|
|
Message,
|
|
MessageReaction,
|
|
MessageType
|
|
} from "../chat/types";
|
|
import axios from "axios";
|
|
|
|
export interface ChatNotificationSettings {
|
|
chat_id: number;
|
|
user_id: number;
|
|
muted: boolean;
|
|
}
|
|
|
|
export async function getChats(query?: string, archived = false): Promise<Chat[]> {
|
|
const { data } = await http.get<Chat[]>("/chats", {
|
|
params: {
|
|
...(query?.trim() ? { query: query.trim() } : {}),
|
|
...(archived ? { archived: true } : {})
|
|
}
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function createPrivateChat(memberId: number): Promise<Chat> {
|
|
return createChat("private", null, [memberId]);
|
|
}
|
|
|
|
export async function createChat(type: ChatType, title: string | null, memberIds: number[] = []): Promise<Chat> {
|
|
const { data } = await http.post<Chat>("/chats", {
|
|
type,
|
|
title,
|
|
is_public: false,
|
|
member_ids: memberIds
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function createPublicChat(type: "group" | "channel", title: string, handle: string, description?: string): Promise<Chat> {
|
|
const { data } = await http.post<Chat>("/chats", {
|
|
type,
|
|
title,
|
|
handle,
|
|
description,
|
|
is_public: true,
|
|
member_ids: []
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function getMessages(chatId: number, beforeId?: number): Promise<Message[]> {
|
|
const { data } = await http.get<Message[]>(`/messages/${chatId}`, {
|
|
params: {
|
|
limit: 50,
|
|
before_id: beforeId
|
|
}
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function searchMessages(query: string, chatId?: number): Promise<Message[]> {
|
|
const { data } = await http.get<Message[]>("/messages/search", {
|
|
params: {
|
|
query,
|
|
chat_id: chatId
|
|
}
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function sendMessage(chatId: number, text: string, type: MessageType = "text"): Promise<Message> {
|
|
const { data } = await http.post<Message>("/messages", { chat_id: chatId, text, type });
|
|
return data;
|
|
}
|
|
|
|
export async function sendMessageWithClientId(
|
|
chatId: number,
|
|
text: string | null,
|
|
type: MessageType,
|
|
clientMessageId: string,
|
|
replyToMessageId?: number
|
|
): Promise<Message> {
|
|
const { data } = await http.post<Message>("/messages", {
|
|
chat_id: chatId,
|
|
text,
|
|
type,
|
|
client_message_id: clientMessageId,
|
|
reply_to_message_id: replyToMessageId
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export interface UploadUrlResponse {
|
|
upload_url: string;
|
|
file_url: string;
|
|
object_key: string;
|
|
expires_in: number;
|
|
required_headers: Record<string, string>;
|
|
}
|
|
|
|
export async function requestUploadUrl(file: File): Promise<UploadUrlResponse> {
|
|
const { data } = await http.post<UploadUrlResponse>("/media/upload-url", {
|
|
file_name: file.name,
|
|
file_type: file.type || "application/octet-stream",
|
|
file_size: file.size
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function uploadToPresignedUrl(
|
|
uploadUrl: string,
|
|
requiredHeaders: Record<string, string>,
|
|
file: File,
|
|
onProgress?: (percent: number) => void,
|
|
retries = 2
|
|
): Promise<void> {
|
|
let attempt = 0;
|
|
while (attempt <= retries) {
|
|
try {
|
|
await axios.put(uploadUrl, file, {
|
|
headers: requiredHeaders,
|
|
onUploadProgress: (progressEvent) => {
|
|
if (!onProgress || !progressEvent.total) {
|
|
return;
|
|
}
|
|
onProgress(Math.round((progressEvent.loaded * 100) / progressEvent.total));
|
|
}
|
|
});
|
|
return;
|
|
} catch (error) {
|
|
const status = axios.isAxiosError(error) ? error.response?.status : undefined;
|
|
const retryable = status === undefined || status >= 500;
|
|
if (!retryable || attempt >= retries) {
|
|
throw error;
|
|
}
|
|
attempt += 1;
|
|
await new Promise((resolve) => window.setTimeout(resolve, 400 * attempt));
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function attachFile(
|
|
messageId: number,
|
|
fileUrl: string,
|
|
fileType: string,
|
|
fileSize: number,
|
|
waveformPoints?: number[] | null
|
|
): Promise<void> {
|
|
await http.post("/media/attachments", {
|
|
message_id: messageId,
|
|
file_url: fileUrl,
|
|
file_type: fileType,
|
|
file_size: fileSize,
|
|
waveform_points: waveformPoints ?? undefined
|
|
});
|
|
}
|
|
|
|
export async function updateMessageStatus(
|
|
chatId: number,
|
|
messageId: number,
|
|
status: "message_delivered" | "message_read"
|
|
): Promise<void> {
|
|
await http.post("/messages/status", {
|
|
chat_id: chatId,
|
|
message_id: messageId,
|
|
status
|
|
});
|
|
}
|
|
|
|
export async function forwardMessage(messageId: number, targetChatId: number): Promise<Message> {
|
|
const { data } = await http.post<Message>(`/messages/${messageId}/forward`, {
|
|
target_chat_id: targetChatId
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function forwardMessageBulk(messageId: number, targetChatIds: number[]): Promise<Message[]> {
|
|
const { data } = await http.post<Message[]>(`/messages/${messageId}/forward-bulk`, {
|
|
target_chat_ids: targetChatIds
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function listMessageReactions(messageId: number): Promise<MessageReaction[]> {
|
|
const { data } = await http.get<MessageReaction[]>(`/messages/${messageId}/reactions`);
|
|
return data;
|
|
}
|
|
|
|
export async function toggleMessageReaction(messageId: number, emoji: string): Promise<MessageReaction[]> {
|
|
const { data } = await http.post<MessageReaction[]>(`/messages/${messageId}/reactions/toggle`, { emoji });
|
|
return data;
|
|
}
|
|
|
|
export async function pinMessage(chatId: number, messageId: number | null): Promise<Chat> {
|
|
const { data } = await http.post<Chat>(`/chats/${chatId}/pin`, {
|
|
message_id: messageId
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function deleteChat(chatId: number, forAll: boolean): Promise<void> {
|
|
await http.delete(`/chats/${chatId}`, { params: { for_all: forAll } });
|
|
}
|
|
|
|
export async function clearChat(chatId: number): Promise<void> {
|
|
await http.post(`/chats/${chatId}/clear`);
|
|
}
|
|
|
|
export async function archiveChat(chatId: number): Promise<Chat> {
|
|
const { data } = await http.post<Chat>(`/chats/${chatId}/archive`);
|
|
return data;
|
|
}
|
|
|
|
export async function unarchiveChat(chatId: number): Promise<Chat> {
|
|
const { data } = await http.post<Chat>(`/chats/${chatId}/unarchive`);
|
|
return data;
|
|
}
|
|
|
|
export async function pinChat(chatId: number): Promise<Chat> {
|
|
const { data } = await http.post<Chat>(`/chats/${chatId}/pin-chat`);
|
|
return data;
|
|
}
|
|
|
|
export async function unpinChat(chatId: number): Promise<Chat> {
|
|
const { data } = await http.post<Chat>(`/chats/${chatId}/unpin-chat`);
|
|
return data;
|
|
}
|
|
|
|
export async function createInviteLink(chatId: number): Promise<ChatInviteLink> {
|
|
const { data } = await http.post<ChatInviteLink>(`/chats/${chatId}/invite-link`);
|
|
return data;
|
|
}
|
|
|
|
export async function joinByInvite(token: string): Promise<Chat> {
|
|
const { data } = await http.post<Chat>("/chats/join-by-invite", { token });
|
|
return data;
|
|
}
|
|
|
|
export async function getChatAttachments(chatId: number, limit = 100, beforeId?: number): Promise<ChatAttachment[]> {
|
|
const { data } = await http.get<ChatAttachment[]>(`/media/chats/${chatId}/attachments`, {
|
|
params: {
|
|
limit,
|
|
before_id: beforeId
|
|
}
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function deleteMessage(messageId: number, forAll = false): Promise<void> {
|
|
await http.delete(`/messages/${messageId}`, { params: { for_all: forAll } });
|
|
}
|
|
|
|
export async function editMessage(messageId: number, text: string): Promise<Message> {
|
|
const { data } = await http.put<Message>(`/messages/${messageId}`, { text });
|
|
return data;
|
|
}
|
|
|
|
export async function discoverChats(query?: string): Promise<DiscoverChat[]> {
|
|
const { data } = await http.get<DiscoverChat[]>("/chats/discover", {
|
|
params: query?.trim() ? { query: query.trim() } : undefined
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export async function joinChat(chatId: number): Promise<Chat> {
|
|
const { data } = await http.post<Chat>(`/chats/${chatId}/join`);
|
|
return data;
|
|
}
|
|
|
|
export async function getSavedMessagesChat(): Promise<Chat> {
|
|
const { data } = await http.get<Chat>("/chats/saved");
|
|
return data;
|
|
}
|
|
|
|
export async function getChatDetail(chatId: number): Promise<ChatDetail> {
|
|
const { data } = await http.get<ChatDetail>(`/chats/${chatId}`);
|
|
return data;
|
|
}
|
|
|
|
export async function listChatMembers(chatId: number): Promise<ChatMember[]> {
|
|
const { data } = await http.get<ChatMember[]>(`/chats/${chatId}/members`);
|
|
return data;
|
|
}
|
|
|
|
export async function updateChatTitle(chatId: number, title: string): Promise<Chat> {
|
|
const { data } = await http.patch<Chat>(`/chats/${chatId}/title`, { title });
|
|
return data;
|
|
}
|
|
|
|
export async function addChatMember(chatId: number, userId: number): Promise<ChatMember> {
|
|
const { data } = await http.post<ChatMember>(`/chats/${chatId}/members`, { user_id: userId });
|
|
return data;
|
|
}
|
|
|
|
export async function updateChatMemberRole(chatId: number, userId: number, role: ChatMemberRole): Promise<ChatMember> {
|
|
const { data } = await http.patch<ChatMember>(`/chats/${chatId}/members/${userId}/role`, { role });
|
|
return data;
|
|
}
|
|
|
|
export async function removeChatMember(chatId: number, userId: number): Promise<void> {
|
|
await http.delete(`/chats/${chatId}/members/${userId}`);
|
|
}
|
|
|
|
export async function leaveChat(chatId: number): Promise<void> {
|
|
await http.post(`/chats/${chatId}/leave`);
|
|
}
|
|
|
|
export async function getChatNotificationSettings(chatId: number): Promise<ChatNotificationSettings> {
|
|
const { data } = await http.get<ChatNotificationSettings>(`/chats/${chatId}/notifications`);
|
|
return data;
|
|
}
|
|
|
|
export async function updateChatNotificationSettings(chatId: number, muted: boolean): Promise<ChatNotificationSettings> {
|
|
const { data } = await http.put<ChatNotificationSettings>(`/chats/${chatId}/notifications`, { muted });
|
|
return data;
|
|
}
|