274 lines
8.3 KiB
TypeScript
274 lines
8.3 KiB
TypeScript
import { http } from "./http";
|
|
import type { Chat, ChatDetail, 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,
|
|
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): Promise<void> {
|
|
await http.post("/media/attachments", {
|
|
message_id: messageId,
|
|
file_url: fileUrl,
|
|
file_type: fileType,
|
|
file_size: fileSize
|
|
});
|
|
}
|
|
|
|
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 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 deleteMessage(messageId: number, forAll = false): Promise<void> {
|
|
await http.delete(`/messages/${messageId}`, { params: { for_all: forAll } });
|
|
}
|
|
|
|
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;
|
|
}
|