Files
makelore/electron/coding-teacher/config-client.ts

82 lines
3.1 KiB
TypeScript

import { WORKS_SQUARE_CONFIG } from '../api/works-config';
import { proxyAwareFetch } from '../utils/proxy-fetch';
import {
getValidWorksSquareAccessToken,
getWorksSquareAccountBinding,
isCurrentWorksSquareAccountBinding,
type WorksSquareAccountBinding,
} from '../services/works-square-session';
import type { TeacherAvailability, TeacherDefinition } from '../../shared/coding-teacher';
export class TeacherError extends Error {
constructor(
public status: number,
public code: string,
message: string
) {
super(message);
}
}
export interface TeacherAccount {
id: string;
binding: WorksSquareAccountBinding;
}
export function assertTeacherAccount(account: TeacherAccount) {
if (!isCurrentWorksSquareAccountBinding(account.binding))
throw new TeacherError(401, 'teacher_account_changed', '登录账号已变化,请重新打开老师。');
}
export async function teacherCloudRequest<T>(
account: TeacherAccount,
pathname: string
): Promise<T> {
assertTeacherAccount(account);
const token = await getValidWorksSquareAccessToken();
assertTeacherAccount(account);
if (!token) throw new TeacherError(401, 'teacher_auth_required', '请先登录。');
const response = await proxyAwareFetch(
WORKS_SQUARE_CONFIG.apiBaseUrl.replace(/\/+$/, '') + pathname,
{
headers: { Authorization: 'Bearer ' + token },
signal: AbortSignal.timeout(30000),
}
);
assertTeacherAccount(account);
if (!response.ok) {
const code =
response.status === 403
? 'teacher_access_denied'
: response.status === 409
? 'teacher_draft_changed'
: 'teacher_config_unavailable';
const message =
response.status === 403
? '当前账号没有使用权限。'
: response.status === 409
? '草稿已变化,请在运营页面重新打开试聊。'
: '老师配置暂不可用,请稍后重试。';
throw new TeacherError(response.status, code, message);
}
return (await response.json()) as T;
}
export async function currentTeacherAccount(): Promise<TeacherAccount> {
const binding = getWorksSquareAccountBinding();
if (!binding) throw new TeacherError(401, 'teacher_auth_required', '请先登录。');
const provisional = { id: '', binding };
const profile = await teacherCloudRequest<{ id: string }>(provisional, '/api/auth/me');
if (!/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(profile.id))
throw new TeacherError(502, 'teacher_account_unavailable', '无法确认当前账号。');
return { id: profile.id, binding };
}
export const teacherAvailability = (account: TeacherAccount) =>
teacherCloudRequest<TeacherAvailability>(account, '/api/coding-teacher/config');
export const teacherVersion = (account: TeacherAccount, version: number) =>
teacherCloudRequest<{ version: number; payload: TeacherDefinition }>(
account,
'/api/coding-teacher/versions/' + version
);
export const teacherPreview = (account: TeacherAccount, revision: number) =>
teacherCloudRequest<{ draft_revision: number; payload: TeacherDefinition }>(
account,
'/api/admin/coding-teacher/preview?draft_revision=' + revision
);