Files
everyone-can-use-english/enjoy/src/api/client.ts
an-lee 8ec2e5dfc4 Feat like posts (#818)
* add like post api

* add like action

* refactor

* add locale
2024-07-17 06:35:14 +08:00

584 lines
13 KiB
TypeScript

import axios, { AxiosInstance } from "axios";
import decamelizeKeys from "decamelize-keys";
import camelcaseKeys from "camelcase-keys";
const ONE_MINUTE = 1000 * 60; // 1 minute
export class Client {
public api: AxiosInstance;
public baseUrl: string;
public logger: any;
constructor(options: {
baseUrl: string;
accessToken?: string;
logger?: any;
locale?: "en" | "zh-CN";
}) {
const { baseUrl, accessToken, logger, locale = "en" } = options;
this.baseUrl = baseUrl;
this.logger = logger || console;
this.api = axios.create({
baseURL: baseUrl,
timeout: ONE_MINUTE,
headers: {
"Content-Type": "application/json",
},
});
this.api.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${accessToken}`;
config.headers["Accept-Language"] = locale;
this.logger.debug(
config.method.toUpperCase(),
config.baseURL + config.url,
config.data,
config.params
);
return config;
});
this.api.interceptors.response.use(
(response) => {
this.logger.debug(
response.status,
response.config.method.toUpperCase(),
response.config.baseURL + response.config.url
);
return camelcaseKeys(response.data, { deep: true });
},
(err) => {
if (err.response) {
this.logger.error(
err.response.status,
err.response.config.method.toUpperCase(),
err.response.config.baseURL + err.response.config.url
);
this.logger.error(err.response.data);
return Promise.reject(new Error(err.response.data));
}
this.logger.error(err.message);
return Promise.reject(err);
}
);
}
auth(params: {
provider: "mixin" | "github" | "bandu" | "email";
code?: string;
deviceCode?: string;
phoneNumber?: string;
email?: string;
mixinId?: string;
}): Promise<UserType> {
return this.api.post("/api/sessions", decamelizeKeys(params));
}
config(key: string): Promise<any> {
return this.api.get(`/api/config/${key}`);
}
deviceCode(provider = "github"): Promise<{
deviceCode: string;
userCode: string;
verificationUri: string;
expiresIn: number;
interval: number;
}> {
return this.api.post("/api/sessions/device_code", { provider });
}
me(): Promise<UserType> {
return this.api.get("/api/me");
}
updateProfile(
id: string,
params: {
name?: string;
email?: string;
code?: string;
}
): Promise<UserType> {
return this.api.put(`/api/users/${id}`, decamelizeKeys(params));
}
loginCode(params: {
phoneNumber?: string;
email?: string;
mixinId?: string;
}): Promise<void> {
return this.api.post("/api/sessions/login_code", decamelizeKeys(params));
}
rankings(range: "day" | "week" | "month" | "year" | "all" = "day"): Promise<{
rankings: UserType[];
range: string;
}> {
return this.api.get("/api/users/rankings", { params: { range } });
}
users(filter: "following" | "followers" = "followers"): Promise<
{
users: UserType[];
} & PagyResponseType
> {
return this.api.get("/api/users", { params: { filter } });
}
user(id: string): Promise<UserType> {
return this.api.get(`/api/users/${id}`);
}
userFollowing(
id: string,
options: { page: number }
): Promise<
{
users: UserType[];
} & PagyResponseType
> {
return this.api.get(`/api/users/${id}/following`, {
params: decamelizeKeys(options),
});
}
userFollowers(
id: string,
options: { page: number }
): Promise<
{
users: UserType[];
} & PagyResponseType
> {
return this.api.get(`/api/users/${id}/followers`, {
params: decamelizeKeys(options),
});
}
follow(id: string): Promise<
{
user: UserType;
} & {
following: boolean;
}
> {
return this.api.post(`/api/users/${id}/follow`);
}
unfollow(id: string): Promise<
{
user: UserType;
} & {
following: boolean;
}
> {
return this.api.post(`/api/users/${id}/unfollow`);
}
posts(params?: {
page?: number;
items?: number;
userId?: string;
type?:
| "all"
| "recording"
| "medium"
| "story"
| "prompt"
| "text"
| "gpt"
| "note";
by?: "following" | "all";
}): Promise<
{
posts: PostType[];
} & PagyResponseType
> {
return this.api.get("/api/posts", { params: decamelizeKeys(params) });
}
post(id: string): Promise<PostType> {
return this.api.get(`/api/posts/${id}`);
}
createPost(params: {
metadata?: PostType["metadata"];
targetType?: string;
targetId?: string;
}): Promise<PostType> {
return this.api.post("/api/posts", decamelizeKeys(params));
}
updatePost(id: string, params: { content: string }): Promise<PostType> {
return this.api.put(`/api/posts/${id}`, decamelizeKeys(params));
}
deletePost(id: string): Promise<void> {
return this.api.delete(`/api/posts/${id}`);
}
likePost(id: string): Promise<PostType> {
return this.api.post(`/api/posts/${id}/like`);
}
unlikePost(id: string): Promise<PostType> {
return this.api.delete(`/api/posts/${id}/unlike`);
}
transcriptions(params?: {
page?: number;
items?: number;
targetId?: string;
targetType?: string;
targetMd5?: string;
}): Promise<
{
transcriptions: TranscriptionType[];
} & PagyResponseType
> {
return this.api.get("/api/transcriptions", {
params: decamelizeKeys(params),
});
}
syncAudio(audio: Partial<AudioType>) {
return this.api.post("/api/mine/audios", decamelizeKeys(audio));
}
deleteAudio(id: string) {
return this.api.delete(`/api/mine/audios/${id}`);
}
syncVideo(video: Partial<VideoType>) {
return this.api.post("/api/mine/videos", decamelizeKeys(video));
}
deleteVideo(id: string) {
return this.api.delete(`/api/mine/videos/${id}`);
}
syncTranscription(transcription: Partial<TranscriptionType>) {
return this.api.post("/api/transcriptions", decamelizeKeys(transcription));
}
syncSegment(
segment: Partial<Omit<SegmentType, "audio" | "video" | "target">>
) {
return this.api.post("/api/segments", decamelizeKeys(segment));
}
syncNote(note: Partial<Omit<NoteType, "segment">>) {
return this.api.post("/api/notes", decamelizeKeys(note));
}
deleteNote(id: string) {
return this.api.delete(`/api/notes/${id}`);
}
syncRecording(recording: Partial<RecordingType>) {
if (!recording) return;
return this.api.post("/api/mine/recordings", decamelizeKeys(recording));
}
deleteRecording(id: string) {
return this.api.delete(`/api/mine/recordings/${id}`);
}
generateSpeechToken(params?: {
purpose?: string;
targetType?: string;
targetId?: string;
input?: string;
}): Promise<{ id: number; token: string; region: string }> {
return this.api.post("/api/speech/tokens", decamelizeKeys(params || {}));
}
consumeSpeechToken(id: number) {
return this.api.put(`/api/speech/tokens/${id}`, {
state: "consumed",
});
}
revokeSpeechToken(id: number) {
return this.api.put(`/api/speech/tokens/${id}`, {
state: "revoked",
});
}
syncPronunciationAssessment(
pronunciationAssessment: Partial<PronunciationAssessmentType>
) {
if (!pronunciationAssessment) return;
return this.api.post(
"/api/mine/pronunciation_assessments",
decamelizeKeys(pronunciationAssessment)
);
}
recordingAssessment(id: string) {
return this.api.get(`/api/mine/recordings/${id}/assessment`);
}
lookup(params: {
word: string;
context: string;
sourceId?: string;
sourceType?: string;
nativeLanguage?: string;
}): Promise<LookupType> {
return this.api.post("/api/lookups", decamelizeKeys(params));
}
updateLookup(
id: string,
params: {
meaning: Partial<MeaningType>;
sourceId?: string;
sourceType?: string;
}
): Promise<LookupType> {
return this.api.put(`/api/lookups/${id}`, decamelizeKeys(params));
}
lookupInBatch(
lookups: {
word: string;
context: string;
sourceId?: string;
sourceType?: string;
}[]
): Promise<{ successCount: number; errors: string[]; total: number }> {
return this.api.post("/api/lookups/batch", {
lookups: decamelizeKeys(lookups, { deep: true }),
});
}
extractVocabularyFromStory(
storyId: string,
extraction?: {
words?: string[];
idioms?: string[];
}
): Promise<string[]> {
return this.api.post(
`/api/stories/${storyId}/extract_vocabulary`,
decamelizeKeys({ extraction })
);
}
storyMeanings(
storyId: string,
params?: {
page?: number;
items?: number;
}
): Promise<
{
meanings: MeaningType[];
pendingLookups?: LookupType[];
} & PagyResponseType
> {
return this.api.get(`/api/stories/${storyId}/meanings`, {
params: decamelizeKeys(params),
});
}
mineMeanings(params?: {
page?: number;
items?: number;
sourceId?: string;
sourceType?: string;
status?: string;
}): Promise<
{
meanings: MeaningType[];
} & PagyResponseType
> {
return this.api.get("/api/mine/meanings", {
params: decamelizeKeys(params),
});
}
createStory(params: CreateStoryParamsType): Promise<StoryType> {
return this.api.post("/api/stories", decamelizeKeys(params));
}
story(id: string): Promise<StoryType> {
return this.api.get(`/api/stories/${id}`);
}
stories(params?: { page: number }): Promise<
{
stories: StoryType[];
} & PagyResponseType
> {
return this.api.get("/api/stories", { params: decamelizeKeys(params) });
}
mineStories(params?: { page: number }): Promise<
{
stories: StoryType[];
} & PagyResponseType
> {
return this.api.get("/api/mine/stories", {
params: decamelizeKeys(params),
});
}
starStory(storyId: string): Promise<{ starred: boolean }> {
return this.api.post(`/api/mine/stories`, decamelizeKeys({ storyId }));
}
unstarStory(storyId: string): Promise<{ starred: boolean }> {
return this.api.delete(`/api/mine/stories/${storyId}`);
}
createPayment(params: {
amount: number;
reconciledCurrency: string;
processor: string;
paymentType: string;
}): Promise<PaymentType> {
return this.api.post("/api/payments", decamelizeKeys(params));
}
payments(params?: {
paymentType?: string;
page?: number;
items?: number;
}): Promise<
{
payments: PaymentType[];
} & PagyResponseType
> {
return this.api.get("/api/payments", { params: decamelizeKeys(params) });
}
payment(id: string): Promise<PaymentType> {
return this.api.get(`/api/payments/${id}`);
}
mineSegments(params?: {
page?: number;
segmentIndex?: number;
targetId?: string;
targetType?: string;
}): Promise<
{
segments: SegmentType[];
} & PagyResponseType
> {
return this.api.get("/api/mine/segments", {
params: decamelizeKeys(params),
});
}
courses(params?: {
language?: string;
page?: number;
items?: number;
query?: string;
}): Promise<
{
courses: CourseType[];
} & PagyResponseType
> {
return this.api.get("/api/courses", { params: decamelizeKeys(params) });
}
course(id: string): Promise<CourseType> {
return this.api.get(`/api/courses/${id}`);
}
createEnrollment(courseId: string): Promise<EnrollmentType> {
return this.api.post(`/api/enrollments`, decamelizeKeys({ courseId }));
}
courseChapters(
courseId: string,
params?: {
page?: number;
items?: number;
query?: string;
}
): Promise<
{
chapters: ChapterType[];
} & PagyResponseType
> {
return this.api.get(`/api/courses/${courseId}/chapters`, {
params: decamelizeKeys(params),
});
}
coursechapter(courseId: string, id: number | string): Promise<ChapterType> {
return this.api.get(`/api/courses/${courseId}/chapters/${id}`);
}
finishCourseChapter(courseId: string, id: number | string): Promise<void> {
return this.api.post(`/api/courses/${courseId}/chapters/${id}/finish`);
}
enrollments(params?: { page?: number; items?: number }): Promise<
{
enrollments: EnrollmentType[];
} & PagyResponseType
> {
return this.api.get("/api/enrollments", { params: decamelizeKeys(params) });
}
updateEnrollment(
id: string,
params: {
currentChapterId?: string;
}
): Promise<EnrollmentType> {
return this.api.put(`/api/enrollments/${id}`, decamelizeKeys(params));
}
createLlmChat(params: {
agentId: string;
agentType: string;
}): Promise<LLmChatType> {
return this.api.post("/api/chats", decamelizeKeys(params));
}
llmChat(id: string): Promise<LLmChatType> {
return this.api.get(`/api/chats/${id}`);
}
createLlmMessage(
chatId: string,
params: {
query: string;
agentId?: string;
agentType?: string;
}
): Promise<LlmMessageType> {
return this.api.post(
`/api/chats/${chatId}/messages`,
decamelizeKeys(params)
);
}
llmMessages(
chatId: string,
params: {
page?: number;
items?: number;
}
): Promise<
{
messages: LlmMessageType[];
} & PagyResponseType
> {
return this.api.get(`/api/chats/${chatId}/messages`, {
params: decamelizeKeys(params),
});
}
}