Bläddra i källkod

- Add authentication for telegram user
- Add /auth and /getAuthCode

Parad0x 7 år sedan
förälder
incheckning
1245b6c632
11 ändrade filer med 245 tillägg och 4 borttagningar
  1. 1 0
      .gitignore
  2. 51 0
      package-lock.json
  3. 4 1
      package.json
  4. 37 0
      src/authCode.js
  5. 73 0
      src/bot/auth.js
  6. 18 0
      src/bot/index.js
  7. 21 0
      src/db/User.js
  8. 2 1
      src/db/index.js
  9. 6 2
      src/index.js
  10. 14 0
      src/init.js
  11. 18 0
      src/telegraf.js

+ 1 - 0
.gitignore

@@ -1,5 +1,6 @@
 dst
 *.sqlite
+authCode
 # Created by https://www.gitignore.io/api/node
 
 ### Node ###

+ 51 - 0
package-lock.json

@@ -2529,6 +2529,11 @@
         "sax": "1.2.4"
       }
     },
+    "node-fetch": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.2.0.tgz",
+      "integrity": "sha512-OayFWziIxiHY8bCUyLX6sTpDH8Jsbp4FfYd1j1f7vZyfgkcOnAyM4oQR16f8a0s7Gl/viMGRey8eScYk4V4EZA=="
+    },
     "node-pre-gyp": {
       "version": "0.10.3",
       "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz",
@@ -3516,6 +3521,11 @@
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
+    "sandwich-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/sandwich-stream/-/sandwich-stream-1.0.0.tgz",
+      "integrity": "sha1-eDDkV5e1kzKH8fmyj4cZB0ViYvI="
+    },
     "sax": {
       "version": "1.2.4",
       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
@@ -3930,6 +3940,42 @@
         }
       }
     },
+    "telegraf": {
+      "version": "3.22.1",
+      "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.22.1.tgz",
+      "integrity": "sha512-jZGgv+kG70WA4n7jPRgcYOD874vG6lQi8yBb5GMG+WyDoDSWDxvCrx13bp8tDQTeqrCjVdIXfFl159JubBUpWA==",
+      "requires": {
+        "@types/node": "10.5.4",
+        "debug": "3.1.0",
+        "node-fetch": "2.2.0",
+        "sandwich-stream": "1.0.0",
+        "telegram-typings": "3.6.1",
+        "typescript": "2.9.2"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "telegraf-command-parts": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/telegraf-command-parts/-/telegraf-command-parts-1.0.3.tgz",
+      "integrity": "sha1-0OB40Qzj9oRptSnl6jp25C1XiLM=",
+      "requires": {
+        "telegraf": "3.22.1"
+      }
+    },
+    "telegram-typings": {
+      "version": "3.6.1",
+      "resolved": "https://registry.npmjs.org/telegram-typings/-/telegram-typings-3.6.1.tgz",
+      "integrity": "sha512-njVv1EAhIZnmQVLocZEADYUyqA1WIXuVcDYlsp+mXua/XB0pxx+PKtMSPeZ/EE4wPWTw9h/hA9ASTT6yQelkiw=="
+    },
     "term-size": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
@@ -4058,6 +4104,11 @@
       "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
       "optional": true
     },
+    "typescript": {
+      "version": "2.9.2",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
+      "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w=="
+    },
     "undefsafe": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz",

+ 4 - 1
package.json

@@ -23,8 +23,11 @@
   },
   "dependencies": {
     "chalk": "^2.4.1",
+    "moment": "^2.22.2",
     "randomatic": "^3.0.0",
     "sequelize": "^4.38.0",
-    "sqlite3": "^4.0.2"
+    "sqlite3": "^4.0.2",
+    "telegraf": "^3.22.1",
+    "telegraf-command-parts": "^1.0.3"
   }
 }

+ 37 - 0
src/authCode.js

@@ -0,0 +1,37 @@
+//@flow
+
+const rand = require("randomatic");
+const fs = require("fs");
+
+const fn = "authCode";
+class Auth {
+
+  code: string;
+
+  constructor() {
+    if (fs.existsSync(fn)) {
+      this.code = fs.readFileSync(fn, "utf8");
+    } else {
+      this.generate();
+    }
+  }
+
+  generate() {
+    this.code = [
+      rand("A", 4),
+      rand("0", 4),
+      rand("Aa", 4),
+      rand("0", 4),
+    ].join("-")
+    fs.writeFileSync(fn, this.code, {
+      flag: "w"
+    });
+  }
+
+  get(): string {
+    return this.code;
+  }
+
+}
+
+module.exports = new Auth();

+ 73 - 0
src/bot/auth.js

@@ -0,0 +1,73 @@
+//@flow
+
+const moment = require("moment");
+
+const telegraf = require("../telegraf");
+const db = require("../db");
+const authCode = require("../authCode");
+
+function auth() {
+  if (telegraf.bot == null) {
+    throw new Error("Bot uninitialized");
+  }
+
+  telegraf.bot.use(async (ctx, next) => {
+    ctx.user = await db.User.findOne({
+      where: {
+        userTelegramId: ctx.from.id
+      }
+    });
+
+    if (!!ctx.user) {
+      if (ctx.user.permanentBan || ctx.user.activated === false && moment().diff(ctx.user.updatedAt) < moment.duration(1, 'days')) {
+        return;
+      }
+    }
+    next();
+  });
+
+  telegraf.bot.command("auth", async (ctx, next) => {
+    if (ctx.user && ctx.user.activated == true) {
+      ctx.reply("Already authorised");
+      return
+    }
+    const args = ctx.state.command.args;
+    let actualAuthCode = authCode.get();
+    if (args === actualAuthCode) {
+      if (ctx.user) {
+        await ctx.user.update({
+          activated: true
+        });
+      } else {
+        let user = await db.User.findOrCreate({
+          where: {
+            userTelegramId: ctx.from.id
+          }, defaults: {
+            activated: true
+          }
+        });
+      }
+      authCode.generate();
+      ctx.reply("User authenticated");
+    } else {
+      let user = await db.User.create({
+        userTelegramId: ctx.from.id,
+        activated: false
+      });
+      ctx.reply("Wrong authentication code. Will be banned for 24H")
+    }
+  });
+
+  telegraf.bot.use((ctx, next) => {
+    if (ctx.user) {
+      next()
+    } else {
+      ctx.reply("You need to be authorised");
+    }
+  })
+
+  telegraf.bot.command("getAuthCode", (ctx) => {
+    ctx.reply(`Actual authentication code: ${authCode.get()}`);
+  });
+}
+module.exports = auth;

+ 18 - 0
src/bot/index.js

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

+ 21 - 0
src/db/User.js

@@ -0,0 +1,21 @@
+//@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;

+ 2 - 1
src/db/index.js

@@ -3,7 +3,8 @@
 const sequelize = require("./sequelize");
 
 const models = {
-  App: require("./App.js")
+  App: require("./App.js"),
+  User: require("./User.js")
 };
 
 module.exports = {

+ 6 - 2
src/index.js

@@ -6,7 +6,8 @@ const chalk = require("chalk");
 
 const socketPathCon = require("./utils/socketPath");
 const connectionHandler = require("./connectionHandler");
-const db = require("./db");
+const init = require("./init");
+const prepareBot = require("./bot");
 
 const server = net.createServer(connectionHandler);
 
@@ -15,7 +16,10 @@ const socketPath = socketPathCon();
 //Main
 
 (async () => {
-  await db.sequelize.sync();
+
+  await init();
+
+  prepareBot();
 
   server.listen(path.resolve(socketPath), () => {
     console.log(`Server is listening on ${socketPath}`);

+ 14 - 0
src/init.js

@@ -0,0 +1,14 @@
+//@flow
+const db = require("./db");
+const bot = require("./telegraf");
+
+async function init() {
+  try {
+    await db.sequelize.sync();
+    await bot.init();
+  } catch (e) {
+    console.log(e.message);
+    process.exit(-1);
+  }
+}
+module.exports = init;

+ 18 - 0
src/telegraf.js

@@ -0,0 +1,18 @@
+//@flow
+
+const Telegraf = require("telegraf");
+
+const returned: {
+  [string]: any
+} = {
+  bot: undefined,
+  async init() {
+    if (typeof process.env.TELEGRAM_TOKEN === "undefined") {
+      throw new Error("Telegram token not found");
+    }
+    const token = process.env.TELEGRAM_TOKEN;
+    this.bot = new Telegraf(token);
+  }
+};
+
+module.exports = returned;