|  | @@ -1,3 +1,99 @@
 | 
	
		
			
				|  |  | +import request from "request-promise-native";
 | 
	
		
			
				|  |  | +import { Dict } from "./util";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +enum ReqMethod {
 | 
	
		
			
				|  |  | +    GET = "get",
 | 
	
		
			
				|  |  | +    POST = "post",
 | 
	
		
			
				|  |  | +    DELETE = "delete"
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export interface RequestError {
 | 
	
		
			
				|  |  | +    code: string;
 | 
	
		
			
				|  |  | +    message: string;
 | 
	
		
			
				|  |  | +    params: { key: string; value: any; }[];
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export type RequestErrorSet = { errors: RequestError[] };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export class XenforoClient {
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    constructor(private endpoint: string, private userKey: string) {  
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private async makeRequest<T>(uri :string, method: ReqMethod, data?: any) {
 | 
	
		
			
				|  |  | +        let result = await request(`${this.endpoint}/${uri}`, {
 | 
	
		
			
				|  |  | +            method: method,
 | 
	
		
			
				|  |  | +            headers: {
 | 
	
		
			
				|  |  | +                "XF-Api-Key": this.userKey
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            form: data || undefined,
 | 
	
		
			
				|  |  | +            resolveWithFullResponse: true
 | 
	
		
			
				|  |  | +        }) as Response;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if(result.status != 200){
 | 
	
		
			
				|  |  | +            throw await result.json() as RequestErrorSet;
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            return await result.json() as T;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    async getThread(id: string, opts?: GetThreadOptions) {
 | 
	
		
			
				|  |  | +        return await this.makeRequest<GetThreadResponse>(`threads/${id}`, ReqMethod.GET, opts);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    async deleteThread(id: string, opts?: DeleteThreadOptions) {
 | 
	
		
			
				|  |  | +        return await this.makeRequest<SuccessResponse>(`threads/${id}`, ReqMethod.DELETE, opts);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    async createThread(forumId: string, title: string, message: string, opts?: CreateThreadOptions) {
 | 
	
		
			
				|  |  | +        return await this.makeRequest<CreateThreadResponse>(`threads/`, ReqMethod.POST, {
 | 
	
		
			
				|  |  | +            node_id: forumId,
 | 
	
		
			
				|  |  | +            title: title,
 | 
	
		
			
				|  |  | +            message: message,
 | 
	
		
			
				|  |  | +            ...opts
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//#region Request types
 | 
	
		
			
				|  |  | +interface DeleteThreadOptions {
 | 
	
		
			
				|  |  | +    hard_delete?: boolean;
 | 
	
		
			
				|  |  | +    reason?: boolean;
 | 
	
		
			
				|  |  | +    starter_alert?: boolean;
 | 
	
		
			
				|  |  | +    starter_alert_reason?: boolean;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +interface GetThreadOptions {
 | 
	
		
			
				|  |  | +    with_posts?: boolean;
 | 
	
		
			
				|  |  | +    page?: number;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +interface CreateThreadOptions {
 | 
	
		
			
				|  |  | +    prefix_id?: number;
 | 
	
		
			
				|  |  | +    tags?: string[];
 | 
	
		
			
				|  |  | +    custom_fields?: Dict<string>;
 | 
	
		
			
				|  |  | +    discussion_open?: boolean;
 | 
	
		
			
				|  |  | +    sticky?: boolean;
 | 
	
		
			
				|  |  | +    attachment_key?: boolean;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +//#endregion
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//#region Response types 
 | 
	
		
			
				|  |  | +type GetThreadResponse = {
 | 
	
		
			
				|  |  | +    thread: Thread;
 | 
	
		
			
				|  |  | +    messages: Post[];
 | 
	
		
			
				|  |  | +    pagination: any;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +type SuccessResponse = {
 | 
	
		
			
				|  |  | +    success: boolean;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +type CreateThreadResponse = SuccessResponse & { thread: Thread; };
 | 
	
		
			
				|  |  | +//#endregion
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//#region Data types
 | 
	
		
			
				|  |  |  export interface Forum {
 | 
	
		
			
				|  |  |      allow_posting: boolean;
 | 
	
		
			
				|  |  |      allow_poll: boolean;
 | 
	
	
		
			
				|  | @@ -153,4 +249,5 @@ export interface Post {
 | 
	
		
			
				|  |  |      last_edit_date: number;
 | 
	
		
			
				|  |  |      reaction_score: number;
 | 
	
		
			
				|  |  |      User: User;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +//#endregion
 |