Browse Source

- Added JSDocs for most functions

Parad0x 6 năm trước cách đây
mục cha
commit
58921567a4
10 tập tin đã thay đổi với 230 bổ sung6 xóa
  1. 20 1
      src/authCode.ts
  2. 27 0
      src/bot/app.ts
  3. 8 1
      src/bot/auth.ts
  4. 4 0
      src/bot/index.ts
  5. 29 2
      src/commandRegistry.ts
  6. 70 0
      src/connectionHandler.ts
  7. 5 0
      src/init.ts
  8. 16 0
      src/telegraf.ts
  9. 45 2
      src/utils/Queue.ts
  10. 6 0
      src/utils/parseId.ts

+ 20 - 1
src/authCode.ts

@@ -3,10 +3,19 @@ import fs from "fs";
 import path from "path";
 
 const fn = path.join(process.cwd(), "authCode");
+/**
+ * Authcode handler
+ *
+ * @class Auth
+ */
 class Auth {
 
   code: string;
 
+  /**
+   * Creates an instance of Auth.
+   * @memberof Auth
+   */
   constructor() {
     this.code = "";
     if (fs.existsSync(fn)) {
@@ -16,6 +25,11 @@ class Auth {
     }
   }
 
+  /**
+   * Generate new code and write it to file
+   *
+   * @memberof Auth
+   */
   generate() {
     this.code = [
       rand("A", 4),
@@ -28,10 +42,15 @@ class Auth {
     });
   }
 
+  /**
+   * Get current code
+   *
+   * @returns {string}
+   * @memberof Auth
+   */
   get(): string {
     return this.code;
   }
-
 }
 
 export default new Auth();

+ 27 - 0
src/bot/app.ts

@@ -11,6 +11,11 @@ const ie = _ie("bot/app");
 import parseId from "../utils/parseId";
 import { Context } from "./auth";
 
+/**
+ * Fetch 5 not activated apps and return buttons for user to activate or remove them
+ *
+ * @returns {Promise<CallbackButton[][]>} - Telegraf buttons
+ */
 async function fetchPendingApps(): Promise<CallbackButton[][]> {
   let pendingApps = await db.App.findAll({
     where: {
@@ -27,6 +32,12 @@ async function fetchPendingApps(): Promise<CallbackButton[][]> {
   return apps;
 }
 
+/**
+ * Get pending apps and wrap button with inlineKeyboard
+ *
+ * @param {*} [apps]
+ * @returns {Promise<object>} - Telegraf keyboard
+ */
 async function getPAppsKeyboard(apps?: any): Promise<object> {
   if (!apps) {
     apps = await fetchPendingApps();
@@ -36,6 +47,10 @@ async function getPAppsKeyboard(apps?: any): Promise<object> {
     .extra();
 }
 
+/**
+ * Register app related commands
+ *
+ */
 function app() {
   if (telegraf.bot == null) {
     throw new Error("Bot uninitialized");
@@ -79,6 +94,7 @@ function app() {
     }
   });
 
+  // List not activated apps
   cmdRegistry.register("pendingApps", async (ctx) => {
     try {
       let pendingApps = await fetchPendingApps();
@@ -92,6 +108,8 @@ function app() {
     }
   });
 
+  // Register an App with name passed by argument
+  // Return Name and authcode of new app instance
   cmdRegistry.register("registerApp", async (ctx: Context) => {
     try {
       if(!ctx.state){
@@ -116,6 +134,13 @@ function app() {
     }
   });
 
+  /**
+   * Return list of apps paginated
+   *
+   * @param {number} page
+   * @param {Context} ctx
+   * @returns {Promise<[string, object]>}
+   */
   async function printAppsList(page: number, ctx: Context): Promise<[string, object]> {
     let apps = await db.App.findAndCountAll({
       limit: 5,
@@ -144,6 +169,7 @@ function app() {
     return [msg, Markup.inlineKeyboard(keyboard).extra()];
   }
 
+  // Return list of apps
   cmdRegistry.register("apps", async (ctx: Context) => {
     try {
       if(!ctx.state){
@@ -157,6 +183,7 @@ function app() {
     }
   });
 
+  // Pagination support for list
   telegraf.bot.action(/^apps (\d+)$/, async (ctx) => {
     try {
       if(!ctx.match){

+ 8 - 1
src/bot/auth.ts

@@ -15,11 +15,16 @@ export interface Context extends ContextMessageUpdate{
     }
 }
 
+/**
+ * Register authentication commands
+ *
+ */
 function auth(): void {
   if (telegraf.bot == null) {
     throw new Error("Bot uninitialized");
   }
 
+  // Authentication middleware
   telegraf.bot.use(async (ctx: Context, next) => {
     try {
       if (!ctx.from) {
@@ -35,7 +40,6 @@ function auth(): void {
       });
 
       if (!!ctx.user) {
-        // Czemu tu było jakieś sprawdzenie kiedy ostatnio był aktualizowany profil :shrug:
         if (ctx.user.permanentBan || ctx.user.activated === false) {
           return;
         }
@@ -46,6 +50,7 @@ function auth(): void {
     }
   });
 
+  // Authenticate with code from authCode file
   cmdRegistry.register("auth", async (ctx: Context, next) => {
     try {
       if (!ctx.from || !ctx.state) {
@@ -85,6 +90,7 @@ function auth(): void {
     }
   });
 
+  // /auth should be the only supported command for not authorised account 
   telegraf.bot.use((ctx: Context, next) => {
     try {
       if (ctx.user && next) {
@@ -97,6 +103,7 @@ function auth(): void {
     }
   })
 
+  // Get current authCode
   cmdRegistry.register("getAuthCode", (ctx) => {
     try {
       ctx.reply(`Actual authentication code: ${authCode.get()}`);

+ 4 - 0
src/bot/index.ts

@@ -3,6 +3,10 @@ import app from "./app";
 import telegraf from "../telegraf";
 import commandParts from 'telegraf-command-parts';
 
+/**
+ * Register telegraf commands and start telegraf bot
+ *
+ */
 function bot(): void {
   if(!telegraf.bot){
     throw new Error("Bot need to be initialized");

+ 29 - 2
src/commandRegistry.ts

@@ -3,7 +3,13 @@ import { Middleware, ContextMessageUpdate } from "telegraf";
 
 type middlewareFun =  Middleware<ContextMessageUpdate>;
 type commandArgs = [string|Array<string>, middlewareFun, ...middlewareFun[]]
-class CommandRegistry {
+/**
+ * Command Register.
+ * Stores information what commands has been registred in Telegraf
+ *
+ * @class CommandRegister
+ */
+class CommandRegister {
 
   commands: string[];
 
@@ -11,6 +17,15 @@ class CommandRegistry {
     this.commands = [];
   }
 
+  /**
+   * Telegraf.command wrapper
+   *
+   * @param {(string|Array<string>)} commands - Command(s) name
+   * @param {middlewareFun} middleware - First middleware to handle
+   * @param {...middlewareFun[]} middlewares - Optional middlewares
+   * 
+   * @memberof CommandRegister
+   */
   register(commands: string|Array<string>, middleware: middlewareFun, ...middlewares:middlewareFun[] ) {
     if(!telegraf.bot){
       throw new Error("Can't register if telegraf is not intialized");
@@ -24,13 +39,25 @@ class CommandRegistry {
     return telegraf.bot.command.apply(telegraf.bot, args);
   }
 
+  /**
+   * Sort commands array
+   *
+   * @memberof CommandRegister
+   */
   sort() {
     this.commands = this.commands.sort();
   }
 
+  /**
+   * Check is command name is already used
+   *
+   * @param {string} cmd - Command name
+   * @returns {boolean} - Is name already used
+   * @memberof CommandRegister
+   */
   isReserved(cmd: string): boolean {
     return this.commands.includes(cmd);
   }
 }
 
-export default new CommandRegistry();
+export default new CommandRegister();

+ 70 - 0
src/connectionHandler.ts

@@ -25,6 +25,11 @@ const secureOp = [
   "ping",
   "close"];
 
+/**
+ *Class representing connection with client
+ *
+ * @class Connection
+ */
 class Connection {
   id: number;
   socket: Socket;
@@ -32,6 +37,12 @@ class Connection {
   queue: Queue<string>;
   session: any;
   ended: boolean;
+  /**
+   * Creates an instance of Connection.
+   * @param {number} id - Conection's id
+   * @param {Socket} socket - Connection's socket
+   * @memberof Connection
+   */
   constructor(id: number, socket: Socket) {
     console.log("New connection", id);
 
@@ -94,6 +105,12 @@ class Connection {
   }
 
   
+  /**
+   * Execute operator by running corresponding method of Connection
+   *
+   * @param {string} op - operator
+   * @memberof Connection
+   */
   async execute(op: string) {
     if (secureOp.includes(op)) {
       await this[<secureOp>op]();
@@ -105,6 +122,13 @@ class Connection {
 
   // Session`s Operations
 
+  /**
+   * register new App with name from queue then reply with id and authcode
+   * 
+   * Should only be used by protocol
+   *
+   * @memberof Connection
+   */
   async register() {
     const name = await this.queue.remove();
     let instance = await db.App.create({
@@ -113,6 +137,14 @@ class Connection {
     this.write(`${instance.id}&${instance.auth};`);
   }
 
+  /**
+   * login App with authcode from queue. 
+   * Reply "OK" on success or "ERR" and message on error;
+   * 
+   * Should only be used by protocol
+   *
+   * @memberof Connection
+   */
   async login() {
     const auth = await this.queue.remove();
     if (typeof this.session !== "undefined") {
@@ -135,6 +167,14 @@ class Connection {
     this.write("OK;");
   }
 
+  /**
+   * send message from queue to telegraf bot.
+   * Reply "OK" on success or "ERR" and message on error;
+   * 
+   * Should only be used by protocol
+   *
+   * @memberof Connection
+   */
   async notify() {
     const message = await this.queue.remove();
     if (typeof this.session === "undefined") {
@@ -146,10 +186,24 @@ class Connection {
     this.write("OK;")
   }
 
+  /**
+   * Reply with "pong".
+   * 
+   * Should only be used by protocol
+   *
+   * @memberof Connection
+   */
   ping() {
     this.write("pong;");
   }
 
+  /**
+   * Close connection
+   * 
+   * Should only be used by protocol
+   *
+   * @memberof Connection
+   */
   close() {
     this.write("Closing connection;");
     this.socket.end();
@@ -157,12 +211,23 @@ class Connection {
 
   // Connection methods
 
+  /**
+   * Write message to connection's Socket
+   *
+   * @param {(string | Buffer)} input - Message
+   * @memberof Connection
+   */
   write(input: string | Buffer) {
     if (!this.socket.destroyed && !this.ended) {
       this.socket.write(input);
     }
   }
 
+  /**
+   * Clear connection from map
+   *
+   * @memberof Connection
+   */
   end() {
     delete Connections[id];
     console.log("Connection closed", this.id);
@@ -171,6 +236,11 @@ class Connection {
 
 let id = 0;
 
+/**
+ * Handle new connection with new Connection
+ *
+ * @param {Socket} socket
+ */
 function connectionHandler(socket: Socket): void {
   id++;
   new Connection(id, socket);

+ 5 - 0
src/init.ts

@@ -1,6 +1,11 @@
 import db from "./db";
 import bot from "./telegraf";
 
+/**
+ * Initialization step
+ *
+ * @returns {Promise<void>}
+ */
 async function init(): Promise<void> {
   try {
     await db.sequelize.sync();

+ 16 - 0
src/telegraf.ts

@@ -5,6 +5,11 @@ const telegraf: {
   [propname: string]: any,
   bot?: Telegraf<ContextMessageUpdate>
 } = {
+  /**
+   * Return authenticated chats
+   *
+   * @returns {Promise<number[]>} - Array of chats` ID
+   */
   async chats(): Promise<number[]> {
     let a = await db.User.findAll({
       where: {
@@ -15,6 +20,12 @@ const telegraf: {
     let ids = a.map(el => el.userTelegramId);
     return ids;
   },
+  /**
+   * Send message to all authenticated chats
+   *
+   * @param {string} message - Message to send
+   * @returns {Promise<void>}
+   */
   async send(message: string): Promise<void> {
     if(!this.bot){
       throw new Error("Can't send when telegraf is not initialized");
@@ -25,6 +36,11 @@ const telegraf: {
     }
   },
   bot: undefined,
+  /**
+   * Initilize Telegraf with TELEGRAM_TOKEN
+   *
+   * @returns {Promise<void>}
+   */
   async init(): Promise<void> {
     if (typeof process.env.TELEGRAM_TOKEN === "undefined") {
       throw new Error("Telegram token not found");

+ 45 - 2
src/utils/Queue.ts

@@ -1,22 +1,53 @@
-import ee from "events";
+import EventEmiter from "events";
 
-class Queue<T> extends ee {
+/**
+ * Simple queue with asynchronous support
+ *
+ * @class Queue
+ * @extends {EventEmiter}
+ * @template T
+ */
+class Queue<T> extends EventEmiter {
   queue: Array<T>;
 
+  /**
+   * Creates an instance of Queue.
+   * @memberof Queue
+   */
   constructor() {
     super();
     this.queue = [];
   }
 
+  /**
+   * Return length of queue
+   *
+   * @readonly
+   * @type {number}
+   * @memberof Queue
+   */
   get length(): number {
     return this.queue.length;
   }
 
+  /**
+   * Add element to queue
+   *
+   * @param {T} el
+   * @memberof Queue
+   */
   add(el: T) {
     this.queue.push(el);
     this.emit("add");
   }
 
+  /**
+   * Asynchronous remove first element of queue.
+   * Resolve only with element. There is no timeout
+   *
+   * @returns {Promise<T>}
+   * @memberof Queue
+   */
   remove(): Promise<T> {
     return new Promise((resolve, reject) => {
       if (this.queue.length > 0) {
@@ -30,11 +61,23 @@ class Queue<T> extends ee {
     });
   }
 
+  /**
+   * Synchronous remove
+   *
+   * @returns {(T | undefined)}
+   * @memberof Queue
+   */
   removeSync(): T | undefined {
     this.emit("remove");
     return this.queue.shift();
   }
 
+  /**
+   * Add many elements to queue
+   *
+   * @param {Array<T>} arr
+   * @memberof Queue
+   */
   concat(arr: Array<T>) {
     if (arr.length > 0) {
       this.queue = this.queue.concat(arr);

+ 6 - 0
src/utils/parseId.ts

@@ -1,3 +1,9 @@
+/**
+ * Parse string id. Ensure it's >= 1 and it's integer.
+ *
+ * @param {string} rawId
+ * @returns {number}
+ */
 function parseId(rawId: string): number {
   let id: number = parseInt(rawId);
   if (isNaN(id)) {