Giter VIP home page Giter VIP logo

airgram's Introduction

Airgram

This is a wrapper for Telegram Database library written in TypeScript.

Airgram

  • Code style. TDLib follows a different coding convention than best practices in TypeScript or JavaScript. Airgram fixes it.
  • Methods. Each API method has convenient wrapper with description and JSDoc documentation.
  • Type checking. Airgram is a true TypeScript library. Everything has strict typings, so take full advantage of type checking and code completion.
  • Flexibility. Airgram relies on middleware. This gives a high degree of freedom. You can modify requests, save responses, perform any actions in the data flow.
  • Data models. You can extend standard TDLib objects and add some computed properties or whatever you want.
  • Use everywhere. Airgram is an environment agnostic library. It will work in the browser as well as in Node.js. You can write Telegram client or use it for a Telegram bot backend.

NPM Version TDLib js-standard-style NPM

Installation

Node.js

  1. Build TDLib library according the instruction.
  2. Install node-gyp
  3. Install Airgram:
# TDLib 1.8.0:
npm install airgram

# TDLib 1.7.2:
npm install [email protected]

Web

# TDLib 1.8.0:
npm install @airgram/web

# TDLib 1.7.2:
npm install @airgram/[email protected]

Check out webpack config example.

Getting started

import { Airgram, Auth, prompt, toObject } from 'airgram'

const airgram = new Airgram({
  apiId: process.env.APP_ID,
  apiHash: process.env.APP_HASH
})

airgram.use(new Auth({
  code: () => prompt(`Please enter the secret code:\n`),
  phoneNumber: () => prompt(`Please enter your phone number:\n`)
}))

void (async () => {
  const me = toObject(await airgram.api.getMe())
  console.log(`[me]`, me)
})

// Getting all updates
airgram.use((ctx, next) => {
  if ('update' in ctx) {
    console.log(`[all updates][${ctx._}]`, JSON.stringify(ctx.update))
  }
  return next()
})

// Getting new messages
airgram.on('updateNewMessage', async ({ update }, next) => {
  const { message } = update
  console.log('[new message]', message)
  return next()
})

Documentation

Guides and API-reference are available here.

Old version

If you are interested in v1.*, follow to corresponding branch.

License

The source code is licensed under GPL v3. License is available here.

airgram's People

Contributors

dependabot[bot] avatar esindger avatar jumoog avatar khrj avatar ktjd123 avatar oktaysenkan avatar serjan-nasredin avatar volodalexey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

airgram's Issues

api getme fetching very slowly after 4 times

πŸ› Bug Report

Current Behavior
get me api is fetching very slowly after 4 times of fetch after program starts

Input Code

  • REPL or Repo link if applicable:
 for (let i = 0; i < users.length; i += 1) {
    const user = users[i];

    const airgram = new Airgram({
      apiId: 476408,
      apiHash: 'da45ac9f71cb62bccb756e7f0b1a10b9',
      logVerbosityLevel: 1,
      databaseDirectory: `./db/${user.phoneNumber}`,
    });
    const auth = new Auth(airgram);

    await auth.use({
      code: '000000',
      phoneNumber: user.phoneNumber,
    });

    await airgram.api
      .getMe()
      .then(async (res) => {
        console.log('logged in true: ', res.firstName, res.lastName);
        user.alive = true;
        user.lastUsed = new Date();
        await user.save();
      })
      .catch(async () => {
        console.log('logged in false : ', user.phoneNumber);
        user.alive = false;
        await user.save();
      });

    console.log(i);
  }

result is

logged in true:  μ„±λ―Ό κΉ€
0
logged in true:  Phone For dev
1
logged in true:  κΉ€ λ­μ‹œκ°±μ΄
2
logged in true:  κ·Έλƒ₯ μ‚¬λžŒ
3

and then takes like minuts

Expected behavior/code
fetch fast. I'm not sure if this is happening to other apis.

Environment

  • Airgram version: 1.0.3
  • Node/npm version: v10, 6.9.0
  • Language: JS

Possible Solution
Maybe bottleneck is happening somewhere

JsonProvider undefined

πŸ› Bug Report

Current Behavior
JsonProvider returns undefined.

Input Code

const airgram = require('airgram');
const { JsonProvider } = airgram;

Expected behavior/code
In the docs it's given JsonProvider has been used, but when I try to use the same code it returns undefined

Environment

  • Airgram version: 1.0.3
  • Node/npm version: v10.15.3 / 6.4.1
  • Language: JavaScript

Possible Solution

Additional context/Screenshots
Add any other context about the problem here. If applicable, add screenshots to help explain.

run command as soon as connected

I want to start a command but I want it to be started as soon as the connection is established to telegram servers.
Where should I put this code into?
Its like this:

(async function () {
  airgram.client.messages.getDialogs({
    flags: 0,
    limit: 30,
    offset_date: 0,
    offset_id: 0,
    offset_peer: { _: 'inputPeerEmpty' },
  }).then((dialogs) => {
    if (dialogs._ == "messages.dialogs") {
      console.log(dialogs)
    }
    console.info(dialogs)
  }).catch((error) => {
    console.error(error)
  })
})();

How to send string as a callback data (using Airgram as a bot)?

I can send string as a callback data using Telegram bot API.
In node-telegram-bot-api:

reply_markup: {
      inline_keyboard: [
        [
          {
            text: 'Edit Text',
            callback_data: 'edit'
          }
        ]
      ]
    }

In Telegraf:

Telegraf.Extra.Markup.callbackButton('Add 10', 'add:10')

I want to send string as a callback data in Airgram too, however in typescript I see only number[]:

export interface KeyboardButtonCallback {
    _: 'keyboardButtonCallback';
    text: string;
    data: number[];
}

How can I send string as a data?

Second question.
I send inline keyboard with callback data:

messages.sendMessage({
    flags: 4,
    peer: { _: 'inputPeerChat', chat_id },
    message: text,
    random_id: String(randomId),
    reply_markup: {
      _: 'replyInlineMarkup',
      rows: [
        {
          _: 'keyboardButtonRow', buttons: [
            { _: 'keyboardButtonCallback', text: 'Callback', data: [ 123 ] }
          ]
        }
      ]
    }
  })

And I subscribe to receive this callback data:

  updates.on("updateBotCallbackQuery", (ctx: ag.UpdateContext, next) => {
    if (ctx.update._ === 'updateBotCallbackQuery') {
      console.log(ctx.update.data)
    }
  })

And in console I see that callback data is Uint8Array [ 123 ]. Why it is so?

channels.getMessages throws Error: Invalid vector object "Vector<int>"

Hello I'm just starting out with this library, I am using

const messages = await airgram.client.channels.getMessages({
    channel: {
      _: 'inputChannel',
      access_hash: '5890566463672636056',
      channel_id: 1224265728
    },
    limit: 10
  })

  console.log('Messages are here', messages)

This returns me

[channels.getMessages]: Invalid vector object "Vector" {}
(node:18638) UnhandledPromiseRejectionWarning: Error: Invalid vector object "Vector"
at MtpSerializer.storeObject (/home/ashwin/work/bl/airgram/node_modules/airgram/base/MtpSerializer.js:189:19)
at MtpSerializer.storeMethod (/home/ashwin/work/bl/airgram/node_modules/airgram/base/MtpSerializer.js:146:18)
at MtpClient.serializeRequest (/home/ashwin/work/bl/airgram/node_modules/airgram/base/MtpClient.js:218:37)
at /home/ashwin/work/bl/airgram/node_modules/airgram/base/MtpClient.js:131:28
at new Promise ()
at MtpClient.callApi (/home/ashwin/work/bl/airgram/node_modules/airgram/base/MtpClient.js:130:16)
at MtpRequest.execute (/home/ashwin/work/bl/airgram/node_modules/airgram/base/MtpRequest.js:111:31)
at /home/ashwin/work/bl/airgram/node_modules/airgram/base/MtpRequest.js:100:56
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:18638) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise whichwas not handled with .catch(). (rejection id: 2)
(node:18638) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

From other examples I see id should be included as an array. But what does this id represent? I tried giving the channel id in that it returns messageEmpty

Expected array, got JsonObject

πŸ› Bug Report

Current Behavior

when I give js array as param, it throws Error It's JsonObject.

it would be nice if airgram takes cares of it and convert before processing params.

not just this api throws error, every api with array throws error.

Always appreciate your work. :)πŸ‘πŸ»

Input Code

const messagesArrayIds = [];
  for (let i = 0; i < messagesArray.length; i += 1) {
    messagesArrayIds.push(messagesArray[i].id);
  }

  console.log(typeof messagesArrayIds); //object
  console.log(messagesArrayIds); // [ 6291456, 5242880, 4194304, 3145728, 2097152, 1048576 ]

  await airgram.api.viewMessages({
    chatId: -1001291950877,
    messageIds: messagesArrayIds,
  });

Expected behavior/code

parse array from input params.

Environment

  • Airgram version: 1.0.1
  • Node/npm version: v10.16.0 / 6.9.0
  • Language: JavaScript

Possible Solution
parse array from input params.

Register new number

πŸš€ Feature Request

[ 1.0.3] TDLib version
[1.4 ] MTProto version

Is your feature request related to a problem? Please describe.
Register new number

Describe the solution you'd like
add method

How to send message to the Bot?

I am trying to send message to the bot:

airgram.client.messages.sendMessage({
    message: `/start`,
    peer: {
      _: 'inputPeerChat',
      chat_id: 123456789,
    },
    random_id: String(Date.now())
  })

In response I get PEER_ID_INVALID. Looks like using bot id as a chat id does not work.
How can I send message to the bot?

If bot considered as a InputPeerUser how do I get access_hash for it? My thoughts that bots are public at any time, so they do not require any access_hash isn't it?

TS Compile Error in airgram/helpers

Hello!
I recently came across your repo. It is really nice!
Finally I found simple and high-end solution for MTProto Mobile Protocol.
Repo with following link looks like is dead telegram-mtproto and has a lot of issues...
I can not compile your TypeScript example.
If I use this:
import { prompt } from 'airgram/helpers'
I get followin TS compile error:

.../node_modules/airgram/helpers/big-numbers.d.ts(1,42): error TS7016: Could not find a declaration file for module '../vendor/big-numbers'. '.../node_modules/airgram/vendor/big-numbers.js' implicitly has an 'any' type.
.../node_modules/airgram/helpers/numbers.d.ts(1,56): error TS7016: Could not find a declaration file for module '../vendor/leemon-bigInt'. '.../node_modules/airgram/vendor/leemon-bigInt.js' implicitly has an 'any' type.
TypeScript: 2 semantic errors

The only one solution is to use following:
const { prompt } = require('airgram/helpers');

My config ("typescript": "3.1.5"):

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
     "lib": ["es6"],
     "sourceMap": true,
     "outDir": "./dist",
    "strict": true,
    "esModuleInterop": false
  }
}

Can not use messages.getFullChat and messages.getChats

If I use messages.getDialogs() to retrive chat information - everything works.
If I use messages.getFullChat() or messages.getChats() - I get error:
Error: Phone number is not defined
Simple code to check:

const { auth } = airgram;

airgram.use(auth);

const dialogs = await airgram.client.messages.getDialogs({
  flags: 0,
  limit: 30,
  offset_date: 0,
  offset_id: 0,
  offset_peer: {_: 'inputPeerEmpty'},
});

const chat_id = dialogs.chats[0].id;

await Promise.all([
  airgram.client.messages.getFullChat({
    chat_id: chat_id,
  }),
  airgram.client.messages.getChats({
    id: [chat_id]
  })
]);

Am I missing something?

Example for getting chats list of "me".

πŸš€ Feature Request

[ 1.0.1] TDLib version
[ ] MTProto version

It would be nice if there is example of getting chat list of "me" in getting started section since I'm not able to find api method for it πŸ˜‚ and it would be same for others

Bad issue

Issue type:

[x] question
[ ] bug report
[ ] feature request
[ ] documentation issue

Airgram version:

[2.1.0] latest
[ ] @next
[ ] 1.1.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

problems with channels parse

Someone might have encountered a problem: I need to do a parsing of the telegram history of the channel using airgram and airgram.client.messages.getHistory ({}) in the parameters of which I specify the id and access hash of the desired channel. Part of the channels is processed normally, part of them returns with the error UnhandledPromiseRejectionWarning: RpcError: CODE # 400 CHANNEL_INVALID. Data (id and access hash are 100% correct). On this server crashes. What to do?


const dialogs = await airgram.client.messages.getHistory({
        peer: {_: 'inputPeerChannel', channel_id: 1234***910, access_hash: '123907933***888612'},
        offset: 0,
        limit: 200,
        max_id: 10000000000,
        min_id: 0
    })

Save auth in Web Airgram

Issue type:

[x] question
[ ] bug report
[ ] feature request
[ ] documentation issue

Airgram version:

[x] latest
[ ] @next
[ ] 1.1.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

How to save auth using Web Airgram?

Currently I'am execute:
setAuthenticationPhoneNumber
then
checkAuthenticationCode
then
checkAuthenticationPassword

Auth completed successfully. But when I reload page, auth disappears. What to do to not lose auth?

Error while auth

πŸ› Bug Report

Current Behavior
throws is_rsa_ok error

Input Code

  • REPL or Repo link if applicable:
this.airgram = new Airgram({
      apiId: id,
      apiHash: hash,
      databaseEncryptionKey: 'a'.repeat(32)
    })
    const auth = new Auth(this.airgram)
    auth.use({
      phoneNumber: () => prompt('phone'),
      code: () => prompt('code'),
      password: () => prompt('pass')
    })

Expected behavior/code
A clear and concise description of what you expected to happen (or code).

Environment

  • Airgram version: 1.0.3
  • Node/npm version: yarn 1.16.0 node 12.4.0
  • Language: TypeScript

Possible Solution

Additional context/Screenshots

[ 3][t 4][1560870536.568617344][Td.cpp:4380][#1][!Td][&td_requests]  Sending update: updateOption {
  name = "version"
  value = optionValueString {
    value = "1.4.0"
  }
}
[ 3][t 4][1560870536.568700314][Td.cpp:4380][#1][!Td][&td_requests]  Sending update: updateAuthorizationState {
  authorization_state = authorizationStateWaitTdlibParameters {
  }
}
[ 3][t 0][1560870536.569825411][Client.cpp:267][&td_requests]        Begin to wait for updates with timeout 10.000000
[ 3][t 0][1560870536.569866657][Client.cpp:273][&td_requests]        End to wait for updates, returning object 0 0x7f36941015a0
[ 3][t 4][1560870536.578877211][Td.cpp:3285][#1][!Td][&td_requests]  Receive request 1: getAuthorizationState {
}
[ 3][t 4][1560870536.578926325][Td.cpp:4395][#1][!Td][&td_requests]  Sending result for request 1: authorizationStateWaitTdlibParameters {
}
[ 3][t 0][1560870536.581164360][Client.cpp:267][&td_requests]        Begin to wait for updates with timeout 10.000000
[ 3][t 0][1560870536.589283705][Client.cpp:273][&td_requests]        End to wait for updates, returning object 0 0x7f3694101b40
[ 3][t 4][1560870536.581279278][Td.cpp:3285][#1][!Td][&td_requests]  Receive request 2: getAuthorizationState {
}
[ 3][t 4][1560870536.589330673][Td.cpp:4395][#1][!Td][&td_requests]  Sending result for request 2: authorizationStateWaitTdlibParameters {
}
[ 3][t 4][1560870536.591422796][Td.cpp:3285][#1][!Td][&td_requests]  Receive request 3: setTdlibParameters {
  parameters = tdlibParameters {
    use_test_dc = false
    database_directory = "./db"
    files_directory = ""
    use_file_database = false
    use_chat_info_database = false
    use_message_database = false
    use_secret_chats = false
    api_id = 21724
    api_hash = "3e0cb5efcd52300aec5994fdfc5bdc16"
    system_language_code = "en"
    device_model = "UNKNOWN DEVICE"
    system_version = "UNKNOWN VERSION"
    application_version = "0.1.0"
    enable_storage_optimizer = false
    ignore_file_names = false
  }
}
[ 3][t 4][1560870536.591681957][Binlog.cpp:371][#1][!Td]     Load: init encryption
[ 3][t 4][1560870536.591820240][Td.cpp:4380][#1][!Td][&td_requests]  Sending update: updateAuthorizationState {
  authorization_state = authorizationStateWaitEncryptionKey {
    is_encrypted = true
  }
}
[ 3][t 4][1560870536.591925621][Td.cpp:4395][#1][!Td][&td_requests]  Sending result for request 3: ok {
}
[ 3][t 0][1560870536.592147827][Client.cpp:267][&td_requests]        Begin to wait for updates with timeout 10.000000
[ 3][t 0][1560870536.592189789][Client.cpp:273][&td_requests]        End to wait for updates, returning object 1 0x7f3694101c10
[ 3][t 0][1560870536.593481302][Client.cpp:267][&td_requests]        Begin to wait for updates with timeout 10.000000
[ 3][t 0][1560870536.593518019][Client.cpp:273][&td_requests]        End to wait for updates, returning object 2 0x7f3694101cd0
[ 3][t 0][1560870536.594120264][Client.cpp:267][&td_requests]        Begin to wait for updates with timeout 10.000000
[ 3][t 0][1560870536.594145536][Client.cpp:273][&td_requests]        End to wait for updates, returning object 0 0x7f36941070a0
[ 3][t 0][1560870536.594805956][Client.cpp:267][&td_requests]        Begin to wait for updates with timeout 10.000000
[ 3][t 0][1560870536.594840050][Client.cpp:273][&td_requests]        End to wait for updates, returning object 3 0x7f36941070c0
[ 3][t 4][1560870536.594857216][Td.cpp:3285][#1][!Td][&td_requests]  Receive request 4: checkDatabaseEncryptionKey {
  encryption_key = bytes [24] { 69 A6 9A 69 A6 9A 69 A6 9A 69 A6 9A 69 A6 9A 69 A6 9A 69 A6 9A 69 A6 9A }
}
[ 3][t 0][1560870536.595154762][Client.cpp:267][&td_requests]        Begin to wait for updates with timeout 10.000000
[ 3][t 4][1560870536.595218420][Binlog.cpp:371][#1][!Td]     Load: init encryption
[ 3][t 4][1560870536.596918344][Td.cpp:3995][#1][!Td]        Successfully inited database in [database_directory:/home/ubuntu/tgstore/db/] and [files_directory:/home/ubuntu/tgstore/db/]
[ 3][t 4][1560870536.597064257][NetQueryDispatcher.cpp:274][#1][!Td] [main_dc_id:1]
[ 0][t 4][1560870536.597251892][PublicRsaKeyShared.cpp:24][#1][!Td][&r_rsa.is_ok()]  [Error : 0 : Cannot dup BIGNUM] -----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
-----END RSA PUBLIC KEY-----
Aborted (core dumped)

Can not send message as a bot

I want to implement e2e test (send message as a user and as a bot).
I created repo to reproduce the issue.

Looks like I can not send message as a bot, I get:

 console.error node_modules/airgram/base/Logger.js:105
console.error node_modules/airgram/base/Logger.js:105
    [messages.sendMessage]: "CODE#400 PEER_ID_INVALID"  {
      "stack": "CODE#400 PEER_ID_INVALID\n
at MtpClient.Object.<anonymous>.MtpClient.createError (.../node_modules/src/base/MtpClient.ts:283:12)\n
at MtpClient.Object.<anonymous>.MtpClient.handleResponse (...node_modules/src/base/MtpClient.ts:491:32)\n
at MtpClient.Object.<anonymous>.MtpClient.handleResponse (...node_modules/src/base/MtpClient.ts:410:14)\n
at MtpClient.Object.<anonymous>.MtpClient.handleResponse (...node_modules/src/base/MtpClient.ts:349:16)\n
at ...node_modules/src/base/MtpClient.ts:829:12\n
at <anonymous>\n
at process._tickCallback (internal/process/next_tick.js:189:7)"
    }

Aigram using WASM TDLib for Browser or Node?

πŸš€ Feature Request

[1.4.0] TDLib version

Is your feature request related to a problem? Please describe.
I do not want to compile TDLib on my own. Is it possible to use WASM version of TDLib.
According to this thread TDLib now supports WASM package named as tdweb. Is it possible to use new tdweb for airgram? (Probably make it by default - so each developer should not compile anything for quick start)

And as of using TDLib (WASM) is it possible to use Airgram for Browser? Related to this

So excellent DX would be: install airgram from npm (tdweb will be installed as WASM as peer dependency) - develop on TS - compile to JS for Browser or Node.

Is persistent store transferable to another project?

With my simple JSON store I performed authorization in one project. In JSON store (store.json) I have:

{
  "airgram:auth": {
    "phoneNumber": "...",
    "isRegistered": true,
    "phoneCodeHash": "...",
    "waitUntil": ...,
    "code": "...",
    "userId": ...
  },
  "airgram:mtp": {
    "dc2.authKey": "...",
    "dc2.serverSalt": "..."
  }
}

And inside this project I am able to send requests.
However if I want to use the same "authorization" for another project I copy (store.json) to another project. And any request from another project fails. I always get:

console.error node_modules/airgram/base/Logger.js:105
    [1] sendScheduledRequest() rpcError {
      "name": "RpcError",
      "type": "NETWORK_BAD_RESPONSE",
      "code": 406,
      "message": "CODE#406 NETWORK_BAD_RESPONSE",
      "url": "http://149.154.167.51:443/apiw1",
      "stack": "CODE#406 NETWORK_BAD_RESPONSE\n    at .../node_modules/src/base/MtpClient.ts:645:18\n    at <anonymous>\n    at process._tickCallback (internal/process/next_tick.js:189:7)"
    }

Is it possible to use the same authorization from another project (definitely not at the same time).
I assume that each airgram library generates its own unique key, however: why this key is not stored (or where can I find this key)?

Dynamic Linking Error

πŸ› Bug Report

Current Behavior
A clear and concise description of the behavior.

It throws dynamic link error

Input Code

  • REPL or Repo link if applicable
#!/usr/local/bin/node

import { Airgram, Auth, prompt } from 'airgram';

const airgram = new Airgram({ apiId: ****, apiHash: ****});

const auth = new Auth(airgram);

Expected behavior/code
A clear and concise description of what you expected to happen (or code).

should clean exit

Environment

  • Airgram version: 1.0.1
  • Node/npm version: v10.16.0/6.9.0
  • Language: [JavaScript/TypeScript] JS

Possible Solution

Additional context/Screenshots
Add any other context about the problem here. If applicable, add screenshots to help explain.

ERROR STACK

nodemon] restarting due to changes...
[nodemon] starting `babel-node src/index.js`
/Users/peter/Program/telegram-airgram/node_modules/ffi-napi/lib/dynamic_library.js:74
    throw new Error('Dynamic Linking Error: ' + err);
    ^

Error: Dynamic Linking Error: dlopen(/Users/peter/Program/telegram-airgram/libtdjson.dylib, 2): image not found
    at new DynamicLibrary (/Users/peter/Program/telegram-airgram/node_modules/ffi-napi/lib/dynamic_library.js:74:11)
    at Object.Library (/Users/peter/Program/telegram-airgram/node_modules/ffi-napi/lib/library.js:45:14)
    at new TdLib (/Users/peter/Program/telegram-airgram/node_modules/airgram/src/components/TdLib.ts:37:22)
    at new TdProxy (/Users/peter/Program/telegram-airgram/node_modules/airgram/src/components/TdProxy.ts:44:18)
    at new Airgram (/Users/peter/Program/telegram-airgram/node_modules/airgram/src/Airgram.ts:36:20)
    at Object.<anonymous> (/Users/peter/Program/telegram-airgram/src/index.js:6:17)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at Module._compile (/Users/peter/Program/telegram-airgram/node_modules/pirates/lib/index.js:99:24)
    at Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Object.newLoader [as .js] (/Users/peter/Program/telegram-airgram/node_modules/pirates/lib/index.js:104:7)
[nodemon] app crashed - waiting for file changes before starting...

tdweb peer dependency typescript error

πŸ› Bug Report

Current Behavior
typescript error for tdweb could not found declaration for tdweb

Input Code

  • REPL or Repo link if applicable:
node_modules/airgram/dist/components/TdWebProvider.d.ts(1,42): error TS7016: Could not find a declaration file for module 'tdweb'. '/Users/peter/Program/airgram-ts/node_modules/tdweb/dist/tdweb.js' implicitly has an 'any' type.
  Try `npm install @types/tdweb` if it exists or add a new declaration (.d.ts) file containing `declare module 'tdweb';

Expected behavior/code
tdweb should not be imported yet

Environment

  • Airgram version: 1.1.0-0
  • Node/npm version: node v10
  • Language: Typescript

Possible Solution
wait until @types/tdweb is ready then support tdweb.

How to access messageMediaPhoto files

Help Request

[1.3.0] TDLib version

Is your feature request related to a problem? Please describe.
Messages that have media type 'messageMediaPhoto' need to be downloaded from telegram, but I can't work out how to do this

Describe the solution you'd like
Provide either a method of passing the relevant Ids to a function to get the files (fs location, byte array, anything really).

Describe alternatives you've considered
At a loss as to where these could be, or how to access them

This may be a reach of for help more than a feature. All in all, the solution is solid, and got me from being super confused about how to access telegram messages (as a user) to a mostly functional system, thanks heaps. It is just these images that have me stumped.

example of a message with media;
{ "_": "message", "pFlags": {}, "flags": 776, "id": 6439, "from_id": 657548629, "to_id": { "_": "peerChannel", "channel_id": 1427901374 }, "reply_to_msg_id": 6419, "date": 1558604496, "message": "", "media": { "_": "messageMediaPhoto", "pFlags": {}, "flags": 3, "photo": { "_": "photo", "pFlags": {}, "flags": 0, "id": "5994591859571274276", "access_hash": "6690770160362851295", "date": 1558604496, "sizes": [ { "_": "photoSize", "type": "s", "location": { "_": "fileLocation", "dc_id": 4, "volume_id": "455007435", "local_id": 408707, "secret": "15825129130646710245" }, "w": 90, "h": 63, "size": 1162 }, { "_": "photoSize", "type": "m", "location": { "_": "fileLocation", "dc_id": 4, "volume_id": "455007435", "local_id": 408708, "secret": "6594452111418022976" }, "w": 320, "h": 223, "size": 15078 }, { "_": "photoSize", "type": "x", "location": { "_": "fileLocation", "dc_id": 4, "volume_id": "455007435", "local_id": 408709, "secret": "10595318245031848231" }, "w": 800, "h": 558, "size": 60643 }, { "_": "photoSize", "type": "y", "location": { "_": "fileLocation", "dc_id": 4, "volume_id": "455007435", "local_id": 408710, "secret": "10604790927550448698" }, "w": 1141, "h": 796, "size": 95949 } ] }, "caption": "Some Caption" } }

Update, using client.upload.getFile gets me closer, now I am just getting CODE#400 LOCATION_INVALID

Is Python required to install Airgram?

Issue type:

[x] question
[ ] bug report
[ ] feature request
[ ] documentation issue

Airgram version:

[x] latest

Steps to reproduce or a small repository showing the problem:

Python is not listed in the requirements. When installing, however, I get the error due to missing Python installation. Is there any way around this or is Python required to install Airgram?

$ yarn add airgram
yarn add v1.17.3
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
[1/2] ⠐ ref-napi
error ***\node_modules\ref-napi: Command failed.
Exit code: 1
Command: node-gyp rebuild
Arguments:
Directory: ***\node_modules\ref-napi
Output:
gyp info it worked if it ends with ok
gyp info using [email protected]
gyp info using [email protected] | win32 | x64
gyp ERR! find Python
gyp ERR! find Python Python is not set from command line or npm configuration
gyp ERR! find Python Python is not set from environment variable PYTHON

*** skipped for brevity ***

gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "***\\AppData\\Local\\Yarn\\Data\\global\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"
gyp ERR! cwd ***\node_modules\ref-napi
gyp ERR! node -v v10.15.3
gyp ERR! node-gyp -v v5.0.3
gyp ERR! not ok

Airgram throws error while long polling

Can you tell me why Airgram throws the following errors?

airgram error 15:16:24.504 [Client] [updateShort]: [38] handleUpdateChannelState() chat "1142964287" not found {} +0ms
airgram error 15:21:42.592 [Client] [updateShort]: [64] handleUpdateChannelState() chat "1083177497" not found {} +5m
airgram error 15:21:43.173 [Client] [updateShort]: [65] handleUpdateChannelState() chat "1083177497" not found {} +582ms
airgram error 15:26:08.761 [Client] [updates.channelDifferenceEmpty]: [85] handle() "updates.channelDifferenceEmpty" channel "undefined" not found {} +4m
airgram error 15:26:08.762 [Client] [updates.channelDifferenceEmpty]: [86] handle() "updates.channelDifferenceEmpty" channel "undefined" not found {} +2ms
airgram error 15:26:08.764 [Client] [updates.channelDifferenceEmpty]: [87] handle() "updates.channelDifferenceEmpty" channel "undefined" not found {} +1ms
airgram error 15:26:08.765 [Client] [updates.channelDifferenceEmpty]: [88] handle() "updates.channelDifferenceEmpty" channel "undefined" not found {} +1ms
airgram error 15:26:08.766 [Client] [updates.channelDifferenceEmpty]: [89] handle() "updates.channelDifferenceEmpty" channel "undefined" not found {} +1ms
airgram error 15:26:08.767 [Client] [updates.channelDifferenceTooLong]: [90] handle() "updates.channelDifferenceTooLong" channel "undefined" not found {} +1ms
airgram error 15:29:22.937 [UpdatesHandler] [98] handle() "updates.channelDifference" channel_id is undefined +3m
airgram error 15:31:17.437 [UpdatesHandler] [108] handle() "updates.channelDifference" channel_id is undefined +2m

The first 3 errors is related to the admin deleting the message from the channel I guess. I'm not sure about the others and why these are thrown.

Airgram has memory leak when polling enabled?

If I start updates in JEST test:

describe("Check", () => {
  const testConfig = createTestAppConfig();
  let airgram: Airgram;

  beforeAll(async () => {
    const airgram = new Airgram(testConfig.api_id, testConfig.api_hash);
    const { updates } = airgram;
    airgram.use(updates);
    await updates.startPolling();
  });

  it("check", async () => {
    await new Promise((resolve) => {
      setTimeout(resolve, 2000)
    })
    expect(true).toBe(true);
  })

  afterAll(async () => {
    await airgram.updates.stop();
    await airgram.destroy()
  })
});

After test JEST shows me that something is running:

Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.

If I comment out this airgram.updates.startPolling() - everything is ok.
If I run airgram.updates.stop() - does not work.
If I run airgram.destroy() - does not work.
Am I missing something, to destroy airgram?

unexpected end of json on entering chat

Issue type:

[ ] question
[v] bug report
[ ] feature request
[ ] documentation issue

Airgram version:

[ ] latest
[ ] @next
[v] `1.1.1

Steps to reproduce or a small repository showing the problem:

join chat using api

await airgram.api
        .joinChatByInviteLink({ inviteLink })
        .then(() => {
          console.log("user", user.phoneNumber, "joined chat");
        })
        .catch((err) => {
            console.error(err)
        });

Can not run tests in JEST

I created simple function to show that behaviour is not the same.
My simple module to send chat message foo.ts:

const promiseFinally = require('promise.prototype.finally');
promiseFinally.shim();
import 'reflect-metadata';
import Airgram, {ag, AuthDialog, TYPES} from "airgram";
import JSONStore from "./userApp/store";
import {prompt} from "airgram/helpers";

export default function () {
  const airgram = new Airgram({ id: ..., hash: '...' });

  airgram.bind<JSONStore<ag.AuthDoc>>(TYPES.AuthStore).to(JSONStore);
  airgram.bind<JSONStore<ag.MtpState>>(TYPES.MtpStateStore).to(JSONStore);

  const { auth, updates } = airgram;

  airgram.use(auth);
  airgram.use(updates);

  auth.use(new AuthDialog({
    firstName: '',
    lastName: '',
    phoneNumber: '...',
    code: () => prompt('Please input the secret code:'),
    samePhoneNumber: ({ phoneNumber }) => prompt(`Do you want to sign in with the "${phoneNumber}" phone number? Y/N`),
    continue: ({ phoneNumber }) => prompt(`Do you have the secret code for the "${phoneNumber}" and wish to continue? Y/N`)
  }));

  return airgram.client.messages.sendMessage({
    peer: { _: 'inputPeerChat', chat_id: 267089681 },
    message: 'TESTING...',
    random_id: Date.now(),
    flags: 0
  })
}

Then I created two use cases.
First one - simple module invoke foo.run.ts:

import foo from './foo'

foo().catch(err => {
  console.error(err);
  process.exit(1);
});

Second one - simple test with JEST foo.test.ts:

import foo from './foo'

describe("Check Foo", () => {

  test("Foo must send message", () => {
    jest.setTimeout(30000);
    expect.assertions(1);
    return foo().then(() => expect(true).toBe(true));
  });

});

Than I compile these three files into dist folder to avoid any misunderstanding TS->JS.
If I run node dist/foo.run.js - everything works each time:

callApi() "messages.sendMessage" {"peer":{"_":"inputPeerChat","chat_id":267089681},"message":"TESTING...","random_id":1541666751622,"flags":0}
[1] request() dc "2" "messages.sendMessage" {
 "peer": {
  "_": "inputPeerChat",
  "chat_id": 267089681
 },
 "message": "TESTING...",
 "random_id": 1541666751622,
 "flags": 0
} {"isFileTransfer":false,"mtp":{},"timeout":30}
[1] execute() response: {"_":"updateShortSentMessage","pFlags":{"out":true},"flags":514,"out":true,"id":121,"pts":257,"pts_count":1,"date":1541666751,"media":{"_":"messageMediaEmpty"}}
callApi() "updates.getState" undefined
[2] request() dc "2" "updates.getState" undefined {"isFileTransfer":false,"mtp":{},"timeout":30}
[1] prepareMtpMessage() {"_":"msgs_ack","msg_ids":["6621408280205314049","6621408280386803713"]} 6621408281323638820 6
[2] execute() response: {"_":"updates.state","pts":257,"qts":0,"date":1541666752,"seq":501,"unread_count":0}

If I run node node_modules/.bin/jest dist/foo.test.js - I alway get an error:

console.info node_modules/airgram/base/Logger.js:105
    callApi() "messages.sendMessage" {"peer":{"_":"inputPeerChat","chat_id":267089681},"message":"TESTING...","random_id":1541666793703,"flags":0}

  console.info node_modules/airgram/base/Logger.js:105
    [1] request() dc "2" "messages.sendMessage" {
     "peer": {
      "_": "inputPeerChat",
      "chat_id": 267089681
     },
     "message": "TESTING...",
     "random_id": 1541666793703,
     "flags": 0
    } {"isFileTransfer":false,"mtp":{},"timeout":30}

  console.error node_modules/airgram/base/Logger.js:105
    [1] sendScheduledRequest() rpcError {
      "name": "RpcError",
      "type": "NETWORK_BAD_RESPONSE",
      "code": 406,
      "message": "CODE#406 NETWORK_BAD_RESPONSE",
      "url": "http://149.154.167.51:443/apiw1",
      "stack": "CODE#406 NETWORK_BAD_RESPONSE\n    at /mnt/disk/js_projects/memory-manager-bot/node_modules/src/base/MtpClient.ts:645:18\n    at <anonymous>\n    at process._tickCallback (internal/process/next_tick.js:189:7)"
    }


 RUNS  dist/foo.test.js

Moreover - sometimes I could send message from test, sometimes - don't. But I always get an error (CODE#406) - that is unreliable behaviour for testing. Is there anything connected with additional JEST wrapping?

Frameworks support

Hey, is there way to integrate with Angular?
I installed the package, but during app serve receiving errors:

ERROR in ./node_modules/zlib/lib/zlib.js
Module not found: Error: Can't resolve './zlib_bindings' in 'C:\Users\YMechsheryakov\WebstormProjects\AigramClient\node_modules\zlib\l
ib'
ERROR in ./node_modules/readline/readline.js
Module not found: Error: Can't resolve 'fs' in 'C:\Users\YMechsheryakov\WebstormProjects\AigramClient\node_modules\readline'
ERROR in ./node_modules/require-directory/index.js
Module not found: Error: Can't resolve 'fs' in 'C:\Users\YMechsheryakov\WebstormProjects\AigramClient\node_modules\require-directory'
ERROR in ./node_modules/require-directory/index.js
Module not found: Error: Can't resolve 'path' in 'C:\Users\YMechsheryakov\WebstormProjects\AigramClient\node_modules\require-directory
'

How to get list of admins within a group

I have joined a group and I want to get list of all admins in the group. Thats a super group so it is a channel. How can I get that list?
I have tested this code but it says 400 CHANNEL_INVALID Which is not, cause I have joined it and I have copied the channel_id and access_hash from the dialogs.

airgram.client.channels.getParticipants({
  channel: {
    _: "inputChannel",
    channel_id: 1311111116,
    access_hash: 70232952222225240655,
  },
  filter: {
    _: "channelParticipantsAdmins",
  },
  limit: 10,
  offset: 0
})
  .then((valu) => {
    console.log(valu);
  })
  .catch((err) => {
    console.log(err);
    console.log(err.toString())
  })

Need Support for multi login in one program

πŸš€ Feature Request

[1.0.1 ] TDLib version
[ ] MTProto version

It would be nice if airgarm can handle multi login.

What i See is airgram can only store 1 auth information. it would be much nicer if it can handle multi login

Use Airgram for Bot?

Is it possible to use airgram for bot auth?
E.g. I want to use airgram for bot like so:
const botApp = new Airgram({ token: ... });
And for user like so:
const userApp = new Airgram({ id: ..., hash: ... });
In this case I can make advanced test cases, e.g. send message as user, receive message as bot. Because for now Telegram blocked usage of bot-to-bot messages: Bots can not see messages from other bots.

Can not send message

I didn't find any example, how to send simple text message.
This example is not clear. Official doc also didn't help me.
I tried following code:

airgram.client.messages.sendMessage({
  peer: { _: 'inputPeerChat', chat_id: -267089681},
  message: 'Hello',
  random_id: 1234567891025465,
  flags: 0
})
  .then((result) => {
    console.log('result', result)
  });

I tried a lot of chat Id's, no one work... However with other library, this chat id work.
In response I get:

[1] processMessageAck() Rpc error CODE#400 PEER_ID_INVALID {}

What is wrong in my example?

Add option for silencing logs of libtdjson.dylib

πŸš€ Feature Request

[1.0.1 ] TDLib version
[ ] MTProto version

Title is the content

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I have an issue when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen. Add any considered drawbacks.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Teachability, Documentation, Adoption, Migration Strategy
If you can, explain how users will be able to use this and possibly write out a version the docs.
Maybe a screenshot or design?

Authorization is not saved?

I implemented simple store to save everything into JSON file, according to Data store.

import * as fs from 'fs';
import {injectable} from "inversify";
import {ag} from "airgram";

@injectable()
export default class JSONStore<DocT> implements ag.Store<DocT> {
  static debug = true;
  static storePath = 'test.store.json';
  static storeEncoding = 'utf8';
  static state: { [index:string] : any } = {};
  static busy: Promise<any> | null = null;
  static initialized = false;
  load () : Promise<any> {
    if (JSONStore.busy) {
      return JSONStore.busy.then(() => this.load)
    }

    JSONStore.busy = new Promise((resolve, reject) => {
      fs.readFile(JSONStore.storePath, JSONStore.storeEncoding, (err, data) => {
        if (err) {
          if (err.code === 'ENOENT') {
            // skip
          } else {
            return reject(err)
          }
        }
        try {
          if (data) {
            JSONStore.state = JSON.parse(data)
          } else {
            JSONStore.state = {};
          }
        } catch (e) {
          return reject(e)
        }
        JSONStore.initialized = true;
        JSONStore.busy = null;
        JSONStore.debug && console.log('JSONStore load()', JSONStore.state);
        resolve(JSONStore.state)
      });
    });

    return JSONStore.busy;
  }

  save () : Promise<any> {
    if (JSONStore.busy) {
      return JSONStore.busy.then(() => this.save)
    }

    JSONStore.busy = new Promise((resolve, reject) => {
      let data = '';
      try {
        data = JSON.stringify(JSONStore.state)
      } catch (e) {
        return reject(e)
      }
      fs.writeFile(JSONStore.storePath, data, JSONStore.storeEncoding, (err) => {
        if (err) return reject(err);
        JSONStore.busy = null;
        JSONStore.debug && console.log('JSONStore save()', data);
        resolve();
      });
    });

    return JSONStore.busy
  }

  public async delete (id: string): Promise<void> {
    if (!JSONStore.initialized) {
      return this.load().then(() => this.delete(id))
    }
    delete JSONStore.state[id];
    JSONStore.debug && console.log('JSONStore delete()', id);
    return this.save()
  }

  public async get (key: string, field?: string): Promise<any> {
    if (!JSONStore.initialized) {
      return this.load().then(() => this.get(key, field))
    }
    JSONStore.debug && console.log('JSONStore get()', key, field);
    if (field) {
      return Promise.resolve(JSONStore.state[key] && JSONStore.state[key][field])
    }
    return Promise.resolve(JSONStore.state[key])
  }

  public async set (id: string, doc: Partial<DocT>): Promise<Partial<DocT>> {
    if (!JSONStore.initialized) {
      return this.load().then(() => this.set(id, doc))
    }
    JSONStore.debug && console.log('JSONStore set()', id, doc);
    if (JSONStore.state[id]) {
      Object.assign(JSONStore.state, {
        [id]: Object.assign(JSONStore.state[id], doc),
      });
    } else {
      Object.assign(JSONStore.state, {
        [id]: doc,
      });
    }
    return this.save()
  }
}

I connected this store:

airgram.bind<JSONStore<ag.AuthDoc>>(TYPES.AuthStore).to(JSONStore);
airgram.bind<JSONStore<ag.MtpState>>(TYPES.MtpStateStore).to(JSONStore);

const { auth } = airgram;
airgram.use(auth);
auth.use(new AuthDialog({ ... });
auth.login().catch((error: any) => {
  console.error(error);
  process.exit(1);
});

And after full login() workflow I get (in json file):

{
  "airgram:auth": {
    "phoneNumber": "...",
    "codeType": "auth.codeTypeSms",
    "isRegistered": true,
    "phoneCodeHash": "b5670...b3",
    "waitUntil": 1541339432314,
    "firstName": "Alexey",
    "lastName": "",
    "code": "83818",
    "samePhoneNumber": "Y",
    "continue": "Y"
  },
  "airgram:mtp": {
    "dc2.authKey": "0f297...9d37d9d",
    "dc2.serverSalt": "b99e...c7462"
  }
}

The problem is, when I run my app next time - I see that callApi() "auth.signIn" is performed each time.
And each time I see notification in Android Telegram App:

New login. Dear Alexey, we detected a login into your account from a new device on 04/11/2018 at 13:56:32 UTC.

Device: Web
Location: ..., ... (IP = XXX.XXX.XXX.XXX)

If this wasn't you, you can go to Settings > Privacy and Security > Active Sessions and terminate that session.

If you think that somebody logged in to your account against your will, you can enable Two-Step Verification in Privacy and Security settings.

Does it mean that something is not saved into Store?
Why I see this message each time? (Moreover I have to re-enter code after hour or so...)

However if you will try https://web.telegram.org - you will enter confirm code only once per month/year or so (I didn't enter code again since last year...)

LOCK does not get removed after nodemon closes

When I run the app and after a while I hit ctrl + c and app stops, It does not clean itself. It creates a file called LOCK in the data directory but it does not remove it on exit.
Causing errors like this one:

  airgram error   16:02:00.395 [Client] [getMtpClient]: IO error: lock /home/meee/files/projects/mk/telegram_group_manager/data/airgram/LOCK: Resource temporarily unavailable {} +0ms
  airgram error   16:02:00.399 [Client] [startPolling]: IO error: lock /home/meee/files/projects/mk/telegram_group_manager/data/airgram/LOCK: Resource temporarily unavailable {} +2ms

Resend Authentication Code Error

πŸ› Bug Report

Current Behavior
Resend Authentication Code with phone call error

Error msg, duplicate promt

the call is performs perfect but I see an error code

Input Code

airgram.on(UPDATE.updateAuthorizationState, async ({ update }, next) => {
    const { authorizationState } = update;
    if (authorizationState._ === AUTHORIZATION_STATE.authorizationStateWaitCode) {
      airgram.api.resendAuthenticationCode().then(() => {
      }).catch(err => {
        console.error(err);
      });
    }
    return next();
  });

  const auth = new Auth(airgram);

  await auth.use({
    code: () => prompt('Enter Code Pls'),
    phoneNumber,
    firstName: generateName(),
    lastName: '',
  });

  await airgram.api.getMe().then((res) => {
    console.log('Logged in user is', res.firstName, res.lastName);
  });

the error code is

{ TDLibError: Authentication code can't be resend
    at TdJsonClient.<anonymous> (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:140:45)
    at step (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:43:23)
    at Object.next (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:24:53)
    at /home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:18:71
    at new Promise (<anonymous>)
    at __awaiter (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:14:12)
    at TdJsonClient.handleResponse (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:124:16)
    at TdJsonClient.addToStack (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:174:22)
    at TdJsonClient.<anonymous> (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:227:28)
    at step (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:43:23)
    at Object.next (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:24:53)
    at fulfilled (/home/ubuntu/tele/node_modules/airgram/dist/components/TdJsonClient.js:15:58) code: 8, type: 'resendAuthenticationCode', name: 'TDLibError' }

Expected behavior/code
first promt should be closed and second resended code should be activated.

now it seems both of them is activated

Environment

  • Airgram version: 1.1.0-0
  • Node/npm version: node v10
  • Language: JS

Possible Solution
Close first prompt and solve error

Additional context/Screenshots
Add any other context about the problem here. If applicable, add screenshots to help explain.

Pinned message in chat stops bot to respond

I have telegram room with me (as a user) and bot. Bot has administration rights and can view all messages.
I use Airgram for bot in this room.
If I - as a user pin some message - then bot freezes itself and refuses to work futher. I do not see any error messages, and I do not see any update events in console too. Only restart bot helps...

Feature Request: Please provide support for socks/socks5 proxy

Hello and thanks for the great work.
As you know telegram is blocked in many countries do to political problems with the governments, countries like Iran, Russia, etc.
At this moment VPNs are all blocked in my country and I was using tor and torify to run airgram

torify yarn start

and I see that it hits some problems and it can not work through tor.
I wanted you to provide support for socks5 proxy (as the telegraf project does it) to help us bypass these limitations. Thanks in advanced.

Send message as a bot directly to the user (define user access_hash)?

I initialized bot:

const airgram = new Airgram({ id: ..., hash: ..., token: ... });
const { auth, updates } = airgram;
airgram.use(auth);
airgram.use(updates);

airgram.updates.on('updateNewMessage', someNewMessageHandler);

await airgram.updates.startPolling();

Then I run bot and listen to messages from users.
If user send direct message to the bot I see following in update:

{ _: 'message',
  pFlags: {},
  flags: 384,
  id: 564,
  from_id: 123456789,
  to_id: { _: 'peerUser', user_id: 999999999 },
  date: 1544611238,
  message: '/start',
  entities: [ { _: 'messageEntityBotCommand', offset: 0, length: 6 } ] }

where from_id - id of user that sent message
to_id.user_id - id of current bot

And I want to send some response message back to the user, however I can not do this:

// somewhere in someNewMessageHandler()
  ctx.client.messages.sendMessage({
    peer: { _: 'inputPeerUser', user_id: 123456789, access_hash: ... },
    message: 'response',
    random_id: Date.now(),
  })

because I do not know (as a bot) user access_hash. However user started conversation with bot first, so (as a bot) I must be able to get access_hash from this user.
I found answer to load dialogs, but as a bot I can not use this endpoint and I get:

ctx.client.messages.getDialogs()
...
processMessageAck() Rpc error CODE#400 BOT_METHOD_INVALID {}

How can I get user access_hash as a bot?

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'catch' of undefined

Issue type:
[v ] question
[v] bug report
[ ] feature request
[ ] documentation issue

(node:8257) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'catch' of undefined
    at TdJsonAirgram.Airgram.handleUpdate (/home/node/workspace/node_modules/@airgram/core/dist/Airgram.js:178:66)
    at TdJsonClient.Airgram._this.provider [as handleUpdate] (/home/node/workspace/node_modules/@airgram/core/dist/Airgram.js:82:62)
    at TdJsonClient.<anonymous> (/home/node/workspace/node_modules/airgram/dist/components/TdJsonClient.js:137:55)
    at step (/home/node/workspace/node_modules/airgram/dist/components/TdJsonClient.js:43:23)
    at Object.next (/home/node/workspace/node_modules/airgram/dist/components/TdJsonClient.js:24:53)
    at /home/node/workspace/node_modules/airgram/dist/components/TdJsonClient.js:18:71
    at new Promise (<anonymous>)
    at __awaiter (/home/node/workspace/node_modules/airgram/dist/components/TdJsonClient.js:14:12)
    at TdJsonClient.handleResponse (/home/node/workspace/node_modules/airgram/dist/components/TdJsonClient.js:120:16)
    at TdJsonClient.addToStack (/home/node/workspace/node_modules/airgram/dist/components/TdJsonClient.js:170:22)

Airgram version:
[ ] latest
[ ] @next
[v] 1.2.0

libtd version:
1.4

Steps to reproduce or a small repository showing the problem:

import { Airgram } from 'airgram';
import secrets from './utils/secrets';
const { TG_APP_ID, TG_APP_HASH } = secrets;


// tslint:disable-next-line: no-floating-promises
(async () => {
    try {
        const airgram = new Airgram({
            command: 'lib/libtdjson',
            apiId: Number(TG_APP_ID),
            apiHash: TG_APP_HASH,
            logVerbosityLevel: 2,
        });
          
        await airgram.api.setProfilePhoto({
            photo: {
                _: 'inputFileLocal',
                path: 'time_images/00-00.jpeg',
            }
        });
    } catch (error) {
        console.error(error);
    }
})();

Airgram on nwjs/electron

Issue type:

[ ] question
[x] bug report
[ ] feature request
[ ] documentation issue

Airgram version:

[x] latest
[ ] @next
[ ] 1.1.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

Hi there,
Anyone successfully use airgram in nwjs/electron? I used it perfectly in nodejs, but everytime i tried in nwjs, it's always failed.

Thanks.

How to provide additional arguments to Store constructor (InversifyJS) ?

At runtime I need to have two different stores. One for Bot and Another one for User.
Right now I am using two different stores for two instances, first and second.
However this ducplicates the code. What I need Is to provide some unique String to Store.
I think the same problem will be with another store implementation, e.g. provide two different connection strings for DB (for Bot and for User).
I assume that this problem can be solved with Inversify Factory.
But I do not control store container invocation. In your example you will also have code duplication in case of two Stores, right?
Is it possible to provide some unique string to Store class?

Comparison with TDLib?

I have three questions.

  1. Does this library depend on/require TDLib?
  2. Does this library have feature parity with TDLib yet?
  3. If not, which features are currently incomplete?

Feature Request: Telegram Bot API mode

I have a lot of difficulties to use telegraf or node-telegram-bot-api. Looks like these libraries are abandoned. Even my pull request to telegraf is hanging more than two month. These libraries are also not "True TypeScript" - they have just type declarations that is always outdated...
I see that "native" Telegram Bot API has more advantages for bots than "hardcore" MtProto (another example of limitaion in telethon ). Using "Telegram Bot API" you don't need storage implementation, encryption, etc...

Is it possible to make Aigram to have two use-cases:

  1. Airgram as MtProto (for user or for bot with a lot of limitations):
const airgram = new Airgram({
  mode: 'MtProto',
  id: ..., 
  hash: ...,
  token: ...,
})
  1. Airgram as Telegram Bot API (for bot only):
const airgram = new Airgram({
  mode: 'BotAPI',
  token: ...,
})
// in this case probably better to use something different like?
airgram.bot.sendMessage(...)
airgram.bot.on('text', ...)

How hard is it to implement in current architecture? Is it possible? Do you have such interest?

I feel that Airgram can be extremly popular because of this feature, because a lot of coders just need bot features.
As a disadvantage this might lead to a lot of support-features that Bot API has but MtProto does not.

Unexpected Token

πŸ› Bug Report

Current Behavior

throws error for unexpected token for almost every request at ubuntu 18 (seems not happening at mac)

Input Code

await airgram.api
      .getMe()
      .then(async (res) => {
        console.log('logged in : ', res.firstName, res.lastName);
        user.alive = true;
        user.lastUsed = new Date();
        await user.save();
      })
      .catch(async () => {
        console.log('logged in failed : ', user.phoneNumber);
        user.alive = false;
        await user.save();
      });

Error Code

(node:9667) UnhandledPromiseRejectionWarning: SyntaxError: Unexpected token Γ  in JSON at position 0
    at JSON.parse (<anonymous>)
    at TdProxy.<anonymous> (/home/ubuntu/tele/node_modules/airgram/dist/components/TdProxy.js:172:54)
    at step (/home/ubuntu/tele/node_modules/airgram/dist/components/TdProxy.js:43:23)
    at Object.next (/home/ubuntu/tele/node_modules/airgram/dist/components/TdProxy.js:24:53)
    at fulfilled (/home/ubuntu/tele/node_modules/airgram/dist/components/TdProxy.js:15:58)
(node:9667) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:9792) UnhandledPromiseRejectionWarning: SyntaxError: Unexpected token  in JSON at position 0
    at JSON.parse (<anonymous>)
    at TdProxy.<anonymous> (/home/ubuntu/tele/node_modules/airgram/dist/components/TdProxy.js:172:54)
    at step (/home/ubuntu/tele/node_modules/airgram/dist/components/TdProxy.js:43:23)
    at Object.next (/home/ubuntu/tele/node_modules/airgram/dist/components/TdProxy.js:24:53)
    at fulfilled (/home/ubuntu/tele/node_modules/airgram/dist/components/TdProxy.js:15:58)
(node:9792) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)

Every time the error log changes

Expected behavior/code
should not throw this error

Environment

  • Airgram version: 1.0.3
  • Node/npm version: 6.9.0
  • Language: JS

Possible Solution
validate JSON

Breaking old code

Issue type:

[ ] bug report

Airgram version:

[ ] @next

Steps to reproduce or a small repository showing the problem:
github.com/kolay-v/spotify2tg

@next breaking old code.

/home/kolay/spotify2tg/node_modules/airgram/dist/Airgram.js:79
            throw new Error('The `provider` option is required.' +
            ^

Error: The `provider` option is required.See: https://github.com/airgram/airgram/blob/master/README.md#providers
    at new Airgram (/home/kolay/spotify2tg/node_modules/airgram/dist/Airgram.js:79:19)
    at Object.<anonymous> (/home/kolay/spotify2tg/main.js:20:17)```

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.