import type { ClientParams, Provider, User } from './index' import { createFetcher } from '../lib/fetcher' import { API_BASE } from '../consts' export interface Config { version: string auth_providers: Provider[] edit_duration: number admin_edit: boolean max_comment_size: number admins: string[] admin_email: string low_score: number critical_score: number positive_score: boolean readonly_age: number max_image_size: number simple_view: boolean anon_vote: boolean email_notifications: boolean telegram_notifications: boolean emoji_enabled: boolean } export interface Comment { /** comment id */ id: string /** parent id */ pid: string /** comment text, after md processing */ text: string /** original comment text */ orig?: string user: User locator: { /** site id */ site: string /** page url */ url: string } score: number voted_ips: { Timestamp: string; Value: boolean }[] /** * vote delta, * if user hasn't voted delta will be 0, * -1/+1 for downvote/upvote */ vote: 0 | 1 | -1 /** comment controversy */ controversy?: number /** pointer to have empty default in json response */ edit?: { time: string summary: string } /** timestamp */ time: string pin?: boolean delete?: boolean /** page title */ title?: string } export interface CommentsTree { comment: Comment replies: Comment[] } export interface CommentPayload { title?: string pid?: string text: string } export type Sort = '-active' | '+active' export interface GetUserCommentsParams { url: string sort?: Sort limit?: number skip?: number } export type Vote = -1 | 1 export function createPublicClient({ siteId: site, baseUrl }: ClientParams) { const fetcher = createFetcher(site, `${baseUrl}${API_BASE}`) const authFetcher = createFetcher(site, `${baseUrl}/auth`) /** * Get server config */ async function getConfig(): Promise { return fetcher.get('/config') } /** * Get current authorized user. * Probes /auth/status first (always 200, no console 401), then fetches /user only if logged in. */ async function getUser(): Promise { const status = await authFetcher.get<{ status: string }>('/status').catch(() => null) if (status?.status !== 'logged in') { return null } return fetcher.get('/user').catch(() => null) } /** * Get comments */ async function getComments(url: string): Promise async function getComments(params: GetUserCommentsParams): Promise async function getComments( params: string | GetUserCommentsParams ): Promise { if (typeof params === 'string') { return fetcher.get('/comments', { url: params }) } return fetcher.get('/find', { ...params, format: 'tree' }) } /** * Add new comment */ async function addComment(url: string, payload: CommentPayload): Promise { const locator = { site, url } return fetcher.post('/comment', {}, { ...payload, locator }) } /** * Update comment */ async function updateComment(url: string, id: string, text: string): Promise { return fetcher.put(`/comment/${id}`, { url }, { text }) } /** * Remove comment on a page */ async function removeComment(url: string, id: string): Promise { return fetcher.put(`/comment/${id}`, { url }, { delete: true }) } /** * Vote for a comment */ async function vote(url: string, id: string, vote: Vote): Promise<{ id: string; vote: number }> { return fetcher.put<{ id: string; vote: number }>(`/vote/${id}`, { url, vote }) } return { getConfig, getUser, getComments, addComment, updateComment, removeComment, vote, } }