UNPKG

@0xtld/tair-node

Version:

A Node.js package for Tair functionality with configuration, core, and helper modules.

301 lines (253 loc) 6.9 kB
import axios, { AxiosInstance } from "axios"; import { Utils } from "../utils"; import { logger } from "../config"; interface IMailRestAccount { address: string; password: string; } enum EMailRestGateway { MAIL_TM = "https://api.mail.tm", MAIL_GW = "https://api.mail.gw", } interface IMailRestConfig { gateway: EMailRestGateway; account: IMailRestAccount; maximumRetries: number; } interface IMailRestArgsGetOtp { receiptEmail: string; extractOtp: (message: IMailRestMessage) => Promise<string>; configs: { retry: number; isGetDetail?: boolean; isDelete?: boolean }; } interface IMailRestMessage { "@id": string; "@type": string; "@context": string; id: string; accountId: string; msgid: string; from: { name: string; address: string; }; to: { name: string; address: string; }[]; subject: string; intro: string; seen: boolean; isDeleted: boolean; hasAttachments: boolean; size: number; downloadUrl: string; createdAt: string; updatedAt: string; // for attributes of message detail text: string; html: [string]; } interface IMailRestDomain { id: string; domain: string; isActive: boolean; createdAt: string; updatedAt: string; } /** * @description MailRest class */ class MailRest { /** * @description jwt token of the account */ token: string | null = null; axios: AxiosInstance; configs: IMailRestConfig; domains: IMailRestDomain[] = []; constructor(configs: IMailRestConfig) { this.configs = { ...configs, maximumRetries: configs.maximumRetries || 20, }; this.axios = axios.create({ baseURL: this.configs.gateway, headers: { "Content-Type": "application/json", Accept: "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3", }, }); this.axios.interceptors.response.use( (response) => { const data = response.data || {}; if (data["hydra:member"]) { return data["hydra:member"]; } return data; }, (error) => { return Promise.reject(error); } ); } setAccount(account: IMailRestAccount) { this.configs.account = account; } async setAccountAndLogin(account: IMailRestAccount) { this.token = null; this.setAccount(account); await this.login(); } async getDomains(): Promise<IMailRestDomain[]> { const data = await this.axios.get("/domains"); this.domains = data as unknown as IMailRestDomain[]; return this.domains; } /** * @description Create an account * @param account IMailRestAccount * @param configs { createAndSet?: boolean } * @returns Promise<IMailRestAccount> */ async createAccount( account: IMailRestAccount, configs: { createAndSet?: boolean } = { createAndSet: false } ) { if (this.domains.length === 0) { await this.getDomains(); } const domain = Utils.shuffleArray(this.domains)[0]; if (domain === undefined) { throw new Error("No domain available"); } if (Utils.isEmail(account.address)) { account.address = account.address.split("@")[0] + "@" + domain.domain; } logger.debug(`[${MailRest.name}] Creating account with email: ${account.address}`); account = await this.axios.post("/accounts", account); logger.debug(`[${MailRest.name}] Account created successfully`); if (configs.createAndSet) { this.setAccount(account); } return account; } async beforeRequest() { if (this.token === null) { await this.login(); } } async login() { const body = { address: this.configs.account.address, password: this.configs.account.password, }; const data = await this.axios.post("/token", body, { headers: { "Content-Type": "application/json", Accept: "application/json", }, }); this.token = (data as any).token; } /** * * @returns Promise<IMailRestMessage[]> */ async messages(): Promise<IMailRestMessage[]> { await this.beforeRequest(); const url = "messages?page=1"; return await this.axios.get(url, { headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${this.token}`, }, }); } async deleteMessage(id: string) { await this.beforeRequest(); const url = `messages/${id}`; return await this.axios.delete(url, { headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${this.token}`, }, }); } async getMessage(id: string): Promise<IMailRestMessage> { await this.beforeRequest(); const url = `messages/${id}`; return await this.axios.get(url, { headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${this.token}`, }, }); } /** * @description Truncate all messages */ async truncateAllMessages() { const messages = await this.messages(); for (const message of messages) { await this.deleteMessage(message.id); logger.debug("Message deleted successfully", message.id); } } /** * @description Get OTP from email * @param args IMailRestArgsGetOtp * @returns Promise<string | null> * */ async getOTP(args: IMailRestArgsGetOtp): Promise<string | null> { const messages = await this.messages(); const { receiptEmail, extractOtp, configs } = args; let message = messages.find((message) => { if (Array.isArray(message.to)) { return message.to.find((to) => to.address === receiptEmail); } }); const { isGetDetail, isDelete } = configs; let retry = configs.retry; if (!message) { if (retry < this.configs.maximumRetries) { logger.debug(`[${MailRest.name}] Retrying getOTP ..... in ${retry + 1} seconds`); await Utils.sleep(retry + 1); return await this.getOTP({ receiptEmail, extractOtp, configs: { retry: retry + 1, isGetDetail, isDelete }, }); } return null; } if (isGetDetail) { try { message = await this.getMessage(message.id); } catch (e) { console.error(`[${MailRest.name}] Error getting message`, e); } } if (isDelete) { try { await this.deleteMessage(message.id); logger.debug("Message deleted successfully", message.id); } catch (e) { console.error(`[${MailRest.name}] Error deleting message`, e); } } return extractOtp(message); } } export { MailRest, IMailRestConfig, IMailRestMessage, EMailRestGateway, IMailRestAccount, IMailRestArgsGetOtp, };