Kaynağa Gözat

- Moved to typescript

Parad0x 6 yıl önce
ebeveyn
işleme
8fdc1faa82

+ 0 - 17
.babelrc

@@ -1,17 +0,0 @@
-{
-  "plugins": [
-    "transform-object-rest-spread"
-  ],
-  "presets": [
-    [
-      "env",
-      {
-        "targets": {
-          "node": "8.10"
-        }
-      }
-    ],
-    "flow"
-  ],
-  "sourceMaps": true
-}

+ 0 - 11
.flowconfig

@@ -1,11 +0,0 @@
-[ignore]
-<PROJECT_ROOT>/dst/.*
-[include]
-
-[libs]
-
-[lints]
-
-[options]
-unsafe.enable_getters_and_setters=true
-[strict]

+ 1 - 0
.gitattributes

@@ -0,0 +1 @@
+* text eol=crlf

+ 0 - 1
.vscode/settings.json

@@ -1,3 +1,2 @@
 {
-  "javascript.validate.enable": false
 }

+ 3 - 17
README.md

@@ -1,16 +1,8 @@
-# Flow project template
-
-Simple template to save some time
+# Totify
 
 ## Dev tools
 
-* Flow
-* Babel
-  * presets:
-    * env (target: node 8.10)
-    * flow
-  * plugin:
-    * rest spread
+* Typescript
 * Nodemon
 
 ## Scripts
@@ -27,14 +19,8 @@ node src/index.js
 nodemon src/index.js
 ```
 
-### prebuild
-
-```
-rm -rf dst
-```
-
 ### build
 
 ```
-babel -d dst src/
+tsc
 ```

+ 1 - 4
client.js

@@ -1,7 +1,4 @@
-//@flow
-
-let net = require("net");
-let path = require("path");
+const net = require("net");
 
 let socketPath = require("./src/utils/socketPath");
 

+ 0 - 98
flow-typed/npm/chalk_v2.x.x.js

@@ -1,98 +0,0 @@
-// flow-typed signature: 9504ccf6e91d9fda2dc048c106c0284d
-// flow-typed version: d662d43161/chalk_v2.x.x/flow_>=v0.25.x
-
-// From: https://github.com/chalk/chalk/blob/master/index.js.flow
-
-declare module "chalk" {
-  declare type TemplateStringsArray = $ReadOnlyArray<string>;
-
-  declare type Level = $Values<{
-    None: 0,
-    Basic: 1,
-    Ansi256: 2,
-    TrueColor: 3
-  }>;
-
-  declare type ChalkOptions = {|
-    enabled?: boolean,
-    level?: Level
-  |};
-
-  declare type ColorSupport = {|
-    level: Level,
-    hasBasic: boolean,
-    has256: boolean,
-    has16m: boolean
-  |};
-
-  declare interface Chalk {
-    (...text: string[]): string,
-    (text: TemplateStringsArray, ...placeholders: string[]): string,
-    constructor(options?: ChalkOptions): Chalk,
-    enabled: boolean,
-    level: Level,
-    rgb(r: number, g: number, b: number): Chalk,
-    hsl(h: number, s: number, l: number): Chalk,
-    hsv(h: number, s: number, v: number): Chalk,
-    hwb(h: number, w: number, b: number): Chalk,
-    bgHex(color: string): Chalk,
-    bgKeyword(color: string): Chalk,
-    bgRgb(r: number, g: number, b: number): Chalk,
-    bgHsl(h: number, s: number, l: number): Chalk,
-    bgHsv(h: number, s: number, v: number): Chalk,
-    bgHwb(h: number, w: number, b: number): Chalk,
-    hex(color: string): Chalk,
-    keyword(color: string): Chalk,
-
-    +reset: Chalk,
-    +bold: Chalk,
-    +dim: Chalk,
-    +italic: Chalk,
-    +underline: Chalk,
-    +inverse: Chalk,
-    +hidden: Chalk,
-    +strikethrough: Chalk,
-
-    +visible: Chalk,
-
-    +black: Chalk,
-    +red: Chalk,
-    +green: Chalk,
-    +yellow: Chalk,
-    +blue: Chalk,
-    +magenta: Chalk,
-    +cyan: Chalk,
-    +white: Chalk,
-    +gray: Chalk,
-    +grey: Chalk,
-    +blackBright: Chalk,
-    +redBright: Chalk,
-    +greenBright: Chalk,
-    +yellowBright: Chalk,
-    +blueBright: Chalk,
-    +magentaBright: Chalk,
-    +cyanBright: Chalk,
-    +whiteBright: Chalk,
-
-    +bgBlack: Chalk,
-    +bgRed: Chalk,
-    +bgGreen: Chalk,
-    +bgYellow: Chalk,
-    +bgBlue: Chalk,
-    +bgMagenta: Chalk,
-    +bgCyan: Chalk,
-    +bgWhite: Chalk,
-    +bgBlackBright: Chalk,
-    +bgRedBright: Chalk,
-    +bgGreenBright: Chalk,
-    +bgYellowBright: Chalk,
-    +bgBlueBright: Chalk,
-    +bgMagentaBright: Chalk,
-    +bgCyanBright: Chalk,
-    +bgWhiteBrigh: Chalk,
-
-    supportsColor: ColorSupport
-  }
-
-  declare module.exports: Chalk;
-}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 189 - 932
package-lock.json


+ 18 - 17
package.json

@@ -7,31 +7,32 @@
   "scripts": {
     "start": "node dst/index.js",
     "startDev": "nodemon src/index.js",
-    "prebuild": "rm -rf dst",
-    "build": "babel -d dst src/",
+    "build": "tsc",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "keywords": [],
   "author": "",
   "license": "MIT",
   "devDependencies": {
-    "babel-cli": "^6.26.0",
-    "babel-plugin-transform-object-rest-spread": "^6.26.0",
-    "babel-preset-env": "^1.7.0",
-    "babel-preset-flow": "^6.23.0",
-    "flow-bin": "^0.77.0",
-    "nodemon": "^1.18.3"
+    "@types/bluebird": "^3.5.29",
+    "@types/chalk": "^2.2.0",
+    "@types/debug": "^4.1.5",
+    "@types/node": "^13.1.2",
+    "@types/sequelize": "^4.28.8",
+    "@types/validator": "^12.0.1",
+    "typescript": "^3.7.4",
+    "nodemon": "^2.0.2",
+    "pkg": "^4.4.2"
   },
   "dependencies": {
-    "chalk": "^2.4.1",
-    "debug": "^3.1.0",
-    "dotenv": "^6.0.0",
-    "moment": "^2.22.2",
-    "pkg": "^4.3.4",
-    "randomatic": "^3.0.0",
-    "sequelize": "^4.38.0",
-    "sqlite3": "^4.0.2",
-    "telegraf": "^3.22.1",
+    "chalk": "^3.0.0",
+    "debug": "^4.1.1",
+    "dotenv": "^8.2.0",
+    "moment": "^2.24.0",
+    "randomatic": "^3.1.1",
+    "sequelize": "^5.21.3",
+    "sqlite3": "^4.1.1",
+    "telegraf": "^3.35.0",
     "telegraf-command-parts": "^1.0.3"
   }
 }

+ 10 - 0
src/@types/randomatic/index.d.ts

@@ -0,0 +1,10 @@
+declare module 'randomatic' {
+    interface RandomaticOptions {
+        chars?: string;
+        exclude?: string|Array<string>;
+    }
+    function randomatic(pattern: string, length?: number, options?: RandomaticOptions): string
+
+    export = randomatic;
+}
+

+ 14 - 0
src/@types/telegraf-command-parts/index.d.ts

@@ -0,0 +1,14 @@
+interface ParsedCommand {
+    text: string;
+    command: string;
+    bot: string;
+    args: string;
+    splitArgs: Array<string>;
+}
+
+declare module "telegraf-command-parts" {
+    import {Middleware, ContextMessageUpdate} from "telegraf"
+
+    function middleware(): Middleware<ContextMessageUpdate>;
+    export default middleware;
+}

+ 3 - 0
src/SocketError.d.ts

@@ -0,0 +1,3 @@
+interface SocketError extends Error {
+    code: string;
+}

+ 5 - 6
src/authCode.js → src/authCode.ts

@@ -1,8 +1,6 @@
-//@flow
-
-const rand = require("randomatic");
-const fs = require("fs");
-const path = require("path");
+import rand from "randomatic";
+import fs from "fs";
+import path from "path";
 
 const fn = path.join(process.cwd(), "authCode");
 class Auth {
@@ -10,6 +8,7 @@ class Auth {
   code: string;
 
   constructor() {
+    this.code = "";
     if (fs.existsSync(fn)) {
       this.code = fs.readFileSync(fn, "utf8");
     } else {
@@ -35,4 +34,4 @@ class Auth {
 
 }
 
-module.exports = new Auth();
+export default new Auth();

+ 49 - 24
src/bot/app.js → src/bot/app.ts

@@ -1,17 +1,17 @@
-//@flow
+import moment from "moment";
+import _debug from "debug";
+import {Markup, CallbackButton} from "telegraf";
+const debug = _debug("totify:bot/app");
 
-const moment = require("moment");
-const debug = require("debug")("totify:bot/app");
+import cmdRegistry from "../commandRegistry";
+import telegraf from "../telegraf";
+import db from "../db";
+import _ie from "../utils/internalError";
+const ie = _ie("bot/app");
+import parseId from "../utils/parseId";
+import { Context } from "./auth";
 
-const cmdRegistry = require("../commandRegistry");
-const telegraf = require("../telegraf");
-const Extra = require('telegraf/extra');
-const Markup = require('telegraf/markup');
-const db = require("../db");
-const ie = require("../utils/internalError")("bot/app");
-const parseId = require("../utils/parseId");
-
-async function fetchPendingApps() {
+async function fetchPendingApps(): Promise<CallbackButton[][]> {
   let pendingApps = await db.App.findAll({
     where: {
       activated: false
@@ -27,7 +27,7 @@ async function fetchPendingApps() {
   return apps;
 }
 
-async function getPAppsKeyboard(apps: ?any) {
+async function getPAppsKeyboard(apps?: any): Promise<object> {
   if (!apps) {
     apps = await fetchPendingApps();
   }
@@ -43,9 +43,15 @@ function app() {
 
   telegraf.bot.action(/^activate (\d+)$/, async (ctx) => {
     try {
+      if(!ctx.match){
+        throw new Error("There is no match attribute");
+      }
       debug("Activating app", ctx.match[1]);
       let id = ctx.match[1];
-      let app = await db.App.findById(id);
+      let app = await db.App.findByPk(id);
+      if(app == null){
+        throw new Error(`There is no app with id equeal ${id}`);
+      }
       await app.update({
         activated: true
       })
@@ -57,9 +63,15 @@ function app() {
 
   telegraf.bot.action(/^deactivate (\d+)$/, async (ctx) => {
     try {
+      if(!ctx.match){
+        throw new Error("There is no match attribute");
+      }
       debug("Deactivating app", ctx.match[1]);
       let id = ctx.match[1];
-      let app = await db.App.findById(id);
+      let app = await db.App.findByPk(id);
+      if(app == null){
+        throw new Error(`There is no app with id equeal ${id}`);
+      }
       await app.destroy();
       await ctx.editMessageText(`[${app.name}] Removed`, await getPAppsKeyboard());
     } catch (e) {
@@ -70,7 +82,7 @@ function app() {
   cmdRegistry.register("pendingApps", async (ctx) => {
     try {
       let pendingApps = await fetchPendingApps();
-      if (pendingApps <= 0) {
+      if (pendingApps.length <= 0) {
         ctx.reply("No application is waiting for activation");
         return;
       }
@@ -80,8 +92,11 @@ function app() {
     }
   });
 
-  cmdRegistry.register("registerApp", async (ctx) => {
+  cmdRegistry.register("registerApp", async (ctx: Context) => {
     try {
+      if(!ctx.state){
+        throw new Error("There is no state attribute");
+      }
       const args: string = await ctx.state.command.args;
       if (args.length > 25) {
         ctx.reply("Name to long!");
@@ -101,19 +116,18 @@ function app() {
     }
   });
 
-  async function printAppsList(page, ctx) {
+  async function printAppsList(page: number, ctx: Context): Promise<[string, object]> {
     let apps = await db.App.findAndCountAll({
       limit: 5,
       offset: 5 * page
     });
     const count = apps.count;
     const maxPage = Math.floor(count / 5);
-    apps = apps.rows;
-    if (apps <= 0) {
+    if (apps.rows.length <= 0) {
       ctx.reply("No apps to show");
-      return;
+      throw new Error("No apps to show");
     }
-    let msg = apps.map(el => {
+    let msg = apps.rows.map(el => {
       return {
         i: el.id,
         n: el.name,
@@ -130,8 +144,11 @@ function app() {
     return [msg, Markup.inlineKeyboard(keyboard).extra()];
   }
 
-  cmdRegistry.register("apps", async (ctx) => {
+  cmdRegistry.register("apps", async (ctx: Context) => {
     try {
+      if(!ctx.state){
+        throw new Error("There is no state attribute");
+      }
       const page = parseId(ctx.state.command.splitArgs[0]) - 1;
       let args = await printAppsList(page, ctx);
       return ctx.reply.apply(ctx, args);
@@ -142,8 +159,14 @@ function app() {
 
   telegraf.bot.action(/^apps (\d+)$/, async (ctx) => {
     try {
+      if(!ctx.match){
+        throw new Error("There is no match attribute");
+      }
       const page = parseInt(ctx.match[1]);
       let args = await printAppsList(page, ctx);
+      if(args == undefined){
+        throw new Error("There is no app on list");
+      }
       return ctx.editMessageText.apply(ctx, args);
     } catch (e) {
       ie(6, e);
@@ -151,4 +174,6 @@ function app() {
   });
 
 }
-module.exports = app;
+
+
+export default app;

+ 31 - 14
src/bot/auth.js → src/bot/auth.ts

@@ -1,20 +1,33 @@
-//@flow
+import cmdRegistry from "../commandRegistry";
+import telegraf from "../telegraf";
+import db from "../db";
+import authCode from "../authCode";
+import _ie from "../utils/internalError";
+const ie = _ie("bot/auth");
 
-const moment = require("moment");
+import {ContextMessageUpdate} from "telegraf";
+import User from "../db/User";
 
-const cmdRegistry = require("../commandRegistry");
-const telegraf = require("../telegraf");
-const db = require("../db");
-const authCode = require("../authCode");
-const ie = require("../utils/internalError")("bot/auth");
+export interface Context extends ContextMessageUpdate{
+    user?: User | null
+    state?: {
+      command: ParsedCommand
+    }
+}
 
-function auth() {
+function auth(): void {
   if (telegraf.bot == null) {
     throw new Error("Bot uninitialized");
   }
 
-  telegraf.bot.use(async (ctx, next) => {
+  telegraf.bot.use(async (ctx: Context, next) => {
     try {
+      if (!ctx.from) {
+        throw new Error("Can't handle anonymous message");
+      }
+      if (!next) {
+        throw new Error("No callback");
+      }
       ctx.user = await db.User.findOne({
         where: {
           userTelegramId: ctx.from.id
@@ -22,7 +35,8 @@ function auth() {
       });
 
       if (!!ctx.user) {
-        if (ctx.user.permanentBan || ctx.user.activated === false && moment().diff(ctx.user.updatedAt) < moment.duration(1, 'days')) {
+        // Czemu tu było jakieś sprawdzenie kiedy ostatnio był aktualizowany profil :shrug:
+        if (ctx.user.permanentBan || ctx.user.activated === false) {
           return;
         }
       }
@@ -32,8 +46,11 @@ function auth() {
     }
   });
 
-  cmdRegistry.register("auth", async (ctx, next) => {
+  cmdRegistry.register("auth", async (ctx: Context, next) => {
     try {
+      if (!ctx.from || !ctx.state) {
+        throw new Error("There is no from attribute");
+      }
       if (ctx.user && ctx.user.activated == true) {
         ctx.reply("Already authorised");
         return
@@ -68,9 +85,9 @@ function auth() {
     }
   });
 
-  telegraf.bot.use((ctx, next) => {
+  telegraf.bot.use((ctx: Context, next) => {
     try {
-      if (ctx.user) {
+      if (ctx.user && next) {
         next()
       } else {
         ctx.reply("You need to be authorised");
@@ -88,4 +105,4 @@ function auth() {
     }
   });
 }
-module.exports = auth;
+export default auth;

+ 0 - 20
src/bot/index.js

@@ -1,20 +0,0 @@
-//@flow
-
-const auth = require("./auth");
-const app = require("./app");
-const telegraf = require("../telegraf");
-const commandParts = require('telegraf-command-parts');
-
-function bot() {
-  // Plugins
-  telegraf.bot.use(commandParts());
-
-  // Modules
-  auth();
-  app();
-
-  // Start
-  telegraf.bot.startPolling();
-}
-
-module.exports = bot;

+ 21 - 0
src/bot/index.ts

@@ -0,0 +1,21 @@
+import auth from "./auth";
+import app from "./app";
+import telegraf from "../telegraf";
+import commandParts from 'telegraf-command-parts';
+
+function bot(): void {
+  if(!telegraf.bot){
+    throw new Error("Bot need to be initialized");
+  }
+  // Plugins
+  telegraf.bot.use(commandParts());
+
+  // Modules
+  auth();
+  app();
+
+  // Start
+  telegraf.bot.startPolling();
+}
+
+export default bot;

+ 0 - 33
src/commandRegistry.js

@@ -1,33 +0,0 @@
-//@flow
-
-const telegraf = require("./telegraf");
-
-class CommandRegistry {
-
-  commands: string[];
-
-  constructor() {
-    this.commands = [];
-  }
-
-  register(...argsRaw) {
-    const args = [].concat(argsRaw);
-    const command = args[0];
-    if (typeof command == "string") {
-      this.commands.push(command)
-    } else if (Array.isArray(command)) {
-      this.commands = this.commands.concat(command);
-    }
-    return telegraf.bot.command.apply(telegraf.bot, args);
-  }
-
-  sort() {
-    this.commands = this.commands.sort();
-  }
-
-  isReserved(cmd: string): boolean {
-    return this.commands.includes(cmd);
-  }
-}
-
-module.exports = new CommandRegistry();

+ 36 - 0
src/commandRegistry.ts

@@ -0,0 +1,36 @@
+import telegraf from "./telegraf";
+import { Middleware, ContextMessageUpdate } from "telegraf";
+
+type middlewareFun =  Middleware<ContextMessageUpdate>;
+type commandArgs = [string|Array<string>, middlewareFun, ...middlewareFun[]]
+class CommandRegistry {
+
+  commands: string[];
+
+  constructor() {
+    this.commands = [];
+  }
+
+  register(commands: string|Array<string>, middleware: middlewareFun, ...middlewares:middlewareFun[] ) {
+    if(!telegraf.bot){
+      throw new Error("Can't register if telegraf is not intialized");
+    }
+    const args: commandArgs = [commands, middleware, ...middlewares];
+    if (typeof commands == "string") {
+      this.commands.push(commands)
+    } else if (Array.isArray(commands)) {
+      this.commands = this.commands.concat(commands);
+    }
+    return telegraf.bot.command.apply(telegraf.bot, args);
+  }
+
+  sort() {
+    this.commands = this.commands.sort();
+  }
+
+  isReserved(cmd: string): boolean {
+    return this.commands.includes(cmd);
+  }
+}
+
+export default new CommandRegistry();

+ 23 - 18
src/connectionHandler.js → src/connectionHandler.ts

@@ -1,17 +1,23 @@
-//@flow
+import { Socket } from "net";
 
-import type { Socket } from "net";
-
-const countAndSlice = require("./utils/countAndSlice");
-const Queue = require("./utils/Queue");
-const db = require("./db");
-const telegraf = require("./telegraf");
-const ie = require("./utils/internalError")("connHand");
+import countAndSlice from "./utils/countAndSlice" ;
+import Queue from "./utils/Queue" ;
+import db from "./db" ;
+import telegraf from "./telegraf" ;
+import _ie from "./utils/internalError";
+const ie = _ie("connHand");
 
 // All connections stored by id
-const Connections = {};
+const Connections:{
+  [id: number]: Connection
+}= {};
 
 // List of operations should be executed
+
+type secureOp = "register" | "login" |
+  "notify" | "ping" |
+  "close";
+
 const secureOp = [
   "register",
   "login",
@@ -26,7 +32,6 @@ class Connection {
   queue: Queue<string>;
   session: any;
   ended: boolean;
-
   constructor(id: number, socket: Socket) {
     console.log("New connection", id);
 
@@ -38,21 +43,21 @@ class Connection {
 
     Connections[id] = this;
 
-    socket.on("data", async data => {
+    socket.on("data", async (data: Buffer | string) => {
       try {
         data = data.toString();
         this.buffer = this.buffer.concat(data);
         console.log("Buffer", this.buffer);
         let [arr, count] = countAndSlice(this.buffer);
         if (arr.length > count) {
-          this.buffer = arr.pop();
+          this.buffer = arr.pop() as string;
         } else {
           this.buffer = "";
         }
         this.queue.concat(arr);
 
         while (this.queue.length > 0) {
-          let op = this.queue.removeSync();
+          let op = this.queue.removeSync() as string;
           op = op.trim();
           if (op.length > 0) {
             try {
@@ -69,7 +74,7 @@ class Connection {
       }
     })
 
-    socket.on("error", (err) => {
+    socket.on("error", (err: SocketError) => {
       if (err.code === 'EPIPE') {
         console.log("Socket used after being closed. (Probably by client)");
         socket.end();
@@ -88,10 +93,10 @@ class Connection {
     });
   }
 
+  
   async execute(op: string) {
     if (secureOp.includes(op)) {
-      // $FlowFixMe
-      await this[op]();
+      await this[<secureOp>op]();
     } else {
       this.write("Unkown operator\n\r");
     }
@@ -165,9 +170,9 @@ class Connection {
 
 let id = 0;
 
-function connectionHandler(socket: Socket) {
+function connectionHandler(socket: Socket): void {
   id++;
   new Connection(id, socket);
 }
 
-module.exports = connectionHandler;
+export default connectionHandler;

+ 0 - 36
src/db/App.js

@@ -1,36 +0,0 @@
-//@flow
-
-const sequelize = require("./sequelize");
-const Sequelize = require("sequelize");
-const randomatic = require("randomatic");
-
-const App = sequelize.define("app", {
-  name: {
-    type: Sequelize.STRING
-  },
-  auth: {
-    type: Sequelize.STRING,
-    defaultValue: "",
-    unique: true
-  },
-  activated: {
-    type: Sequelize.BOOLEAN,
-    defaultValue: false
-  }
-}, {
-    hooks: {
-      afterCreate: (app, options, fn) => {
-        let authCode = [
-          app.id,
-          randomatic("A", 5),
-          randomatic("0", 3),
-          randomatic("Aa0", 20)
-        ].join("-");
-        return app.updateAttributes({
-          auth: authCode
-        });
-      }
-    }
-  });
-
-module.exports = App;

+ 40 - 0
src/db/App.ts

@@ -0,0 +1,40 @@
+import sequelize from "./sequelize";
+import Sequelize, { Model } from "sequelize";
+import randomatic from "randomatic";
+
+class App extends Model {
+  id!: number;
+  name!: string;
+  auth!: string;
+  activated!: boolean;
+}
+
+App.init({
+  name: {
+    type: Sequelize.STRING
+  },
+  auth: {
+    type: Sequelize.STRING,
+    defaultValue: "",
+    unique: true
+  },
+  activated: {
+    type: Sequelize.BOOLEAN,
+    defaultValue: false
+  }
+}, {
+  sequelize,
+  hooks: {
+    afterCreate: (app, options) => {
+      let authCode = [
+        app.id,
+        randomatic("A", 5),
+        randomatic("0", 3),
+        randomatic("Aa0", 20)
+      ].join("-");
+      app.auth = authCode;
+    }
+  }
+});
+
+export default App;

+ 0 - 21
src/db/User.js

@@ -1,21 +0,0 @@
-//@flow
-
-const sequelize = require("./sequelize");
-const Sequelize = require("sequelize");
-const randomatic = require("randomatic");
-
-const User = sequelize.define("user", {
-  userTelegramId: {
-    type: Sequelize.BIGINT
-  },
-  activated: {
-    type: Sequelize.BOOLEAN,
-    defaultValue: false
-  },
-  permanentBan: {
-    type: Sequelize.BOOLEAN,
-    defaultValue: false
-  }
-});
-
-module.exports = User;

+ 29 - 0
src/db/User.ts

@@ -0,0 +1,29 @@
+import sequelize from "./sequelize";
+import Sequelize, { Model } from "sequelize";
+
+class User extends Model {
+  userTelegramId!: number;
+  activated!: boolean;
+  permanentBan!: boolean;
+  
+  public readonly updatedAt!: Date;
+
+}
+
+User.init({
+  userTelegramId: {
+    type: Sequelize.BIGINT
+  },
+  activated: {
+    type: Sequelize.BOOLEAN,
+    defaultValue: false
+  },
+  permanentBan: {
+    type: Sequelize.BOOLEAN,
+    defaultValue: false
+  }
+}, {
+  sequelize
+})
+
+export default User;

+ 0 - 13
src/db/index.js

@@ -1,13 +0,0 @@
-//@flow
-
-const sequelize = require("./sequelize");
-
-const models = {
-  App: require("./App.js"),
-  User: require("./User.js")
-};
-
-module.exports = {
-  sequelize,
-  ...models
-}

+ 14 - 0
src/db/index.ts

@@ -0,0 +1,14 @@
+import sequelize from "./sequelize";
+
+import User from "./User";
+import App from "./App";
+
+const models = {
+  App,
+  User
+};
+
+export default {
+  sequelize,
+  ...models
+}

+ 4 - 5
src/db/sequelize.js → src/db/sequelize.ts

@@ -1,13 +1,12 @@
-//@flow
+import {Sequelize} from 'sequelize';
+import * as path from 'path';
 
-const Sequelize = require('sequelize');
-const path = require("path");
+// TODO custom database path
 const filename = path.join(process.cwd(), 'database.sqlite');
 const sequelize = new Sequelize({
   dialect: 'sqlite',
-  operatorsAliases: false,
   storage: filename,
   logging: false
 });
 
-module.exports = sequelize;
+export default sequelize;

+ 11 - 12
src/index.js → src/index.ts

@@ -1,23 +1,22 @@
-//@flow
-
-const path = require("path");
+import path from "path";
 
 require("dotenv").config({
   path: path.join(process.cwd(), ".env")
 });
 
-const net = require("net");
-const chalk = require("chalk");
-const debug = require("debug")("totify:main");
+import net from "net";
+import chalk from "chalk";
+import _debug from "debug";
+const debug = _debug("totify:main");
 
-const socketPathCon = require("./utils/socketPath");
-const connectionHandler = require("./connectionHandler");
-const init = require("./init");
-const prepareBot = require("./bot");
+import socketPathCon from "./utils/socketPath";
+import connectionHandler from "./connectionHandler";
+import init from "./init";
+import prepareBot from "./bot";
 
 const server = net.createServer(connectionHandler);
 
-const socketPath = socketPathCon();
+const socketPath = socketPathCon(process.env.TOTIFY_INSTANCENAME);
 
 //Main
 
@@ -35,7 +34,7 @@ const socketPath = socketPathCon();
     console.log(`Server is listening on ${socketPath}`);
   });
 
-  server.on("error", err => {
+  server.on("error", (err: SocketError)=> {
     if (err.code == "EADDRINUSE") {
       console.log(chalk.red(
         `Totify stream address is already in use. ` +

+ 4 - 5
src/init.js → src/init.ts

@@ -1,8 +1,7 @@
-//@flow
-const db = require("./db");
-const bot = require("./telegraf");
+import db from "./db";
+import bot from "./telegraf";
 
-async function init() {
+async function init(): Promise<void> {
   try {
     await db.sequelize.sync();
     await bot.init();
@@ -12,4 +11,4 @@ async function init() {
     process.exit(-1);
   }
 }
-module.exports = init;
+export default init;

+ 13 - 11
src/telegraf.js → src/telegraf.ts

@@ -1,10 +1,9 @@
-//@flow
+import Telegraf, {ContextMessageUpdate} from "telegraf";
+import db from "./db";
 
-const Telegraf = require("telegraf");
-const db = require("./db");
-
-const returned: {
-  [string]: any
+const telegraf: {
+  [propname: string]: any,
+  bot?: Telegraf<ContextMessageUpdate>
 } = {
   async chats(): Promise<number[]> {
     let a = await db.User.findAll({
@@ -13,17 +12,20 @@ const returned: {
         permanentBan: false
       }
     });
-    a = a.map(el => el.userTelegramId).map(el => parseInt(el));
-    return a;
+    let ids = a.map(el => el.userTelegramId);
+    return ids;
   },
-  async send(message: string) {
+  async send(message: string): Promise<void> {
+    if(!this.bot){
+      throw new Error("Can't send when telegraf is not initialized");
+    }
     let chats = await this.chats();
     for (let id of chats) {
       await this.bot.telegram.sendMessage(id, message);
     }
   },
   bot: undefined,
-  async init() {
+  async init(): Promise<void> {
     if (typeof process.env.TELEGRAM_TOKEN === "undefined") {
       throw new Error("Telegram token not found");
     }
@@ -32,4 +34,4 @@ const returned: {
   }
 };
 
-module.exports = returned;
+export default telegraf;

+ 6 - 6
src/utils/Queue.js → src/utils/Queue.ts

@@ -1,8 +1,6 @@
-//@flow
+import ee from "events";
 
-const ee = require("events");
-
-module.exports = class Queue<T> extends ee {
+class Queue<T> extends ee {
   queue: Array<T>;
 
   constructor() {
@@ -32,7 +30,7 @@ module.exports = class Queue<T> extends ee {
     });
   }
 
-  removeSync(): T {
+  removeSync(): T | undefined {
     this.emit("remove");
     return this.queue.shift();
   }
@@ -43,4 +41,6 @@ module.exports = class Queue<T> extends ee {
       this.emit("add");
     }
   }
-}
+}
+
+export default Queue;

+ 1 - 3
src/utils/countAndSlice.js → src/utils/countAndSlice.ts

@@ -1,5 +1,3 @@
-//@flow
-
 /**
  * Split string to array by separator and count occurance of it`s
  *
@@ -30,4 +28,4 @@ function countAndSlice(input: string, separator: string = ";", escapeCharacter:
   return [arr, counter];
 }
 
-module.exports = countAndSlice;
+export default countAndSlice;

+ 0 - 12
src/utils/internalError.js

@@ -1,12 +0,0 @@
-//@flow
-
-const debug = require("debug")("totify:ie");
-
-module.exports = (modid) => {
-  return (id, e) => {
-    console.log(`Internal Error: sig[${modid}]${id}`);
-    if (e) {
-      debug(e);
-    }
-  }
-}

+ 11 - 0
src/utils/internalError.ts

@@ -0,0 +1,11 @@
+import _debug from "debug";
+const debug = _debug("totify:ie");
+
+export default (modid: string) => {
+  return (id: number, e: Error) => {
+    console.log(`Internal Error: sig[${modid}]${id}`);
+    if (e) {
+      debug(e.toString());
+    }
+  }
+}

+ 3 - 4
src/utils/parseId.js → src/utils/parseId.ts

@@ -1,6 +1,4 @@
-//@flow
-
-module.exports = function parseId(rawId: any): number {
+function parseId(rawId: string): number {
   let id: number = parseInt(rawId);
   if (isNaN(id)) {
     id = 1;
@@ -8,4 +6,5 @@ module.exports = function parseId(rawId: any): number {
   id = Math.max(id, 1)
   id = Math.trunc(id);
   return id;
-}
+}
+export default parseId;

+ 2 - 4
src/utils/socketPath.js → src/utils/socketPath.ts

@@ -1,6 +1,4 @@
-//@flow
-
-let path = require("path");
+import path from "path";
 
 /**
  * Build path of socket
@@ -23,4 +21,4 @@ function socketPath(instanceName?: string): string {
   return socketPath;
 }
 
-module.exports = socketPath;
+export default socketPath;

+ 67 - 0
tsconfig.json

@@ -0,0 +1,67 @@
+{
+  "compilerOptions": {
+    /* Basic Options */
+    // "incremental": true,                   /* Enable incremental compilation */
+    "target": "es6",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
+    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
+    "lib": ["es6","dom"],                     /* Specify library files to be included in the compilation. */
+    // "allowJs": true,                       /* Allow javascript files to be compiled. */
+    // "checkJs": true,                       /* Report errors in .js files. */
+    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
+    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
+    "sourceMap": true,                     /* Generates corresponding '.map' file. */
+    // "outFile": "./",                       /* Concatenate and emit output to single file. */
+    "outDir": "dst",                          /* Redirect output structure to the directory. */
+    "rootDir": "src",                         /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
+    // "composite": true,                     /* Enable project compilation */
+    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
+    // "removeComments": true,                /* Do not emit comments to output. */
+    // "noEmit": true,                        /* Do not emit outputs. */
+    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
+    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+    /* Strict Type-Checking Options */
+    "strict": true,                           /* Enable all strict type-checking options. */
+    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
+    // "strictNullChecks": true,              /* Enable strict null checks. */
+    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
+    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
+    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
+    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */
+
+    /* Additional Checks */
+    // "noUnusedLocals": true,                /* Report errors on unused locals. */
+    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
+    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
+    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */
+
+    /* Module Resolution Options */
+    "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
+    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
+    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
+    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
+    // "typeRoots": [],                       /* List of folders to include type definitions from. */
+    // "types": [],                           /* Type declaration files to be included in compilation. */
+    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
+    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */
+
+    /* Source Map Options */
+    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
+    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
+    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+    /* Experimental Options */
+    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
+    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
+
+    /* Advanced Options */
+    "resolveJsonModule": true,                /* Include modules imported with '.json' extension */
+    "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
+  }
+}

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor