Telegram Integration Custom App

Telegram Integration For Frappe & Erpnext to sending fast Telegram notifications for more productivity.

It still needs some improvements and bug fix or adds more features.
And I would be grateful if we could add it to the core of the system, and I will do the work necessary to do that with some guidance and help from the community.

Main features

  • Sending custom notification by Telegram Bots to users, employees, customers, and Telegram group chat.
  • Sending Telegram direct messages from any form view.
  • Multiple Telegram Bots channels.

How to Install

Install App

  1. ./env/bin/pip install python-telegram-bot --upgrade

  2. bench get-app erpnext_telegram_integration https://github.com/yrestom/erpnext_telegram.git

  3. bench install-app erpnext_telegram_integration

  4. bench build

  5. bench restart

  6. Create a new Telegram bot in BotFather

    For more reference :

  7. Get Telegram Bot Token from BotFather

In Erpnext Telegram Integration

  1. Go to → Telegram Settings → New
    Enter Telegram Bot Token
  2. Go to → Telegram User Settings → New
    to setup and define a new user setting
    1. choose party
    2. choose Telegram User
    3. choose Telegram Settings
    4. if is a group check “Is Group Chat”
    5. press “Generate Telegram Token”
    6. copy “Telegram Token” and past it in the Telegram Bot
      or if is a Group Chat past in the group after add the Bot
    7. press “Get Chat ID”
      if everything is ok it will get the chat ID
    8. press Save
  3. Go to → Telegram Notification → New
    Here you can configure various notifications in your system to remind you of important activities.
    As the original Erpnext Notification
  4. Also, you can send directly a Telegram message from any form view by going to the Menu and click “Send To Telegram”.

Dependencies

  1. Frappe
  2. python-telegram-bot

License

MIT

38 Likes

Hi,

im interested with the idea for telegram bot, would like to try your app soon.
is it possible for bot to do some inputs based on a chat command?
example : /payment $100 Indra
so the bot will create a payment for that customer

thanks for the great module

Of course, it is possible, the bot can be made to handle any scenarios we want.
Currently, the app only sends notifications.

any plan to develop it? let me know if you interested too, so we could discuss it, i would like to support the project.
thanks

I am willing to develop and take this further if someone is able to support. My ideas are -

  1. Bot to create SO/PO/JOB Application/ other doctype
  2. Polling/survey integration app for erpnext
  3. Make payment using payment gateways and send payment request wth link to pay
  4. Project should have a checkbox, if selected system should create a telegram channel for every project and add the given users automatically
1 Like

Certainly there is a development plan, currently I am considering adding SMS support, where a friend suggested the idea to me and I liked it.
I am also interested in this idea, only I will need a clear vision of how it works.

Hi , I am trying to test this integration, but I get this error “ValueError: Document for field "field_order" attached to child table of "Telegram Notification" must be a dict or BaseDocument, not type 'unicode' (enabled)” when I run bench install-app erpnext_telegram_integration.

please advise. Thank you

Hi, can you provide me the version of Frappe and Erpnext you use and the full error log?

Thanks

Yeah sure. By the way, the administrative_communcations app also has the same error.

administrative_communications 0.0.1
erpnext 11.1.72
erpnext_telegram_integration 0.0.1
frappe 11.1.64

Full error trace for erpnext_telegram_integration -

HEY! USE SCREEN [frappe@ERP frappe-bench]$ bench --site main.promatics.ng install-app erpnext_telegram_integration

Installing erpnext_telegram_integration...
Traceback (most recent call last):
  File "/usr/lib64/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib64/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/bench_helper.py", line 97, in <module>
    main()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/bench_helper.py", line 18, in main
    click.Group(commands=commands)(prog_name='bench')
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/commands/__init__.py", line 25, in _func
    ret = f(frappe._dict(ctx.obj), *args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/commands/site.py", line 168, in install_app
    _install_app(app, verbose=context.verbose)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/installer.py", line 145, in install_app
    sync_for(name, force=True, sync_everything=True, verbose=verbose, reset_permissions=True)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/sync.py", line 56, in sync_for
    reset_permissions=reset_permissions, for_sync=True)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/modules/import_file.py", line 65, in import_file_by_path
    ignore_version=ignore_version, reset_permissions=reset_permissions)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/modules/import_file.py", line 100, in import_doc
    doc = frappe.get_doc(docdict)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 734, in get_doc
    doc = frappe.model.document.get_doc(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 69, in get_doc
    return controller(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 113, in __init__
    super(Document, self).__init__(kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 54, in __init__
    self.update(d)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 77, in update
    self.set(key, value)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 124, in set
    self.extend(key, value)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 161, in extend
    self.append(key, v)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 155, in append
    self.name, str(type(value))[1:-1], value)
ValueError: Document for field "field_order" attached to child table of "Telegram Notification" must be a dict or BaseDocument, not type 'unicode' (enabled)
HEY! USE SCREEN [frappe@ERP frappe-bench]$

Full error trace for administrative_communications -

HEY! USE SCREEN -bash-4.2# su frappe
HEY! USE SCREEN [frappe@ERP root]$ cd ~/frappe-bench
HEY! USE SCREEN [frappe@ERP frappe-bench]$ bench --site main.promatics.ng install-app administrative_communications

Installing administrative_communications...
Traceback (most recent call last):
  File "/usr/lib64/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib64/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/bench_helper.py", line 97, in <module>
    main()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/bench_helper.py", line 18, in main
    click.Group(commands=commands)(prog_name='bench')
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/frappe/frappe-bench/env/lib/python2.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/commands/__init__.py", line 25, in _func
    ret = f(frappe._dict(ctx.obj), *args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/commands/site.py", line 168, in install_app
    _install_app(app, verbose=context.verbose)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/installer.py", line 145, in install_app
    sync_for(name, force=True, sync_everything=True, verbose=verbose, reset_permissions=True)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/sync.py", line 56, in sync_for
    reset_permissions=reset_permissions, for_sync=True)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/modules/import_file.py", line 65, in import_file_by_path
    ignore_version=ignore_version, reset_permissions=reset_permissions)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/modules/import_file.py", line 100, in import_doc
    doc = frappe.get_doc(docdict)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 734, in get_doc
    doc = frappe.model.document.get_doc(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 69, in get_doc
    return controller(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 113, in __init__
    super(Document, self).__init__(kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 54, in __init__
    self.update(d)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 77, in update
    self.set(key, value)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 124, in set
    self.extend(key, value)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 161, in extend
    self.append(key, v)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 155, in append
    self.name, str(type(value))[1:-1], value)
ValueError: Document for field "field_order" attached to child table of "AC Log" must be a dict or BaseDocument, not type 'unicode' (transaction_type)
HEY! USE SCREEN [frappe@ERP frappe-bench]$

Sorry, I did not test compatibility with version 11, it was tested and working with version 12 and Python 3.6 .

welp, Okay thanks

Hi, I tested with v12 and it’s been amazing. Thank you, and welldone!

1 Like

Hi, I tested this in one of my VM for v12, and it works great.
But when I wanted to install the app on my production machine which also runs version 12, I run into this error when doing bench install-app
Traceback (most recent call last):
File “/usr/lib/python3.6/runpy.py”, line 193, in _run_module_as_main
main”, mod_spec)
File “/usr/lib/python3.6/runpy.py”, line 85, in _run_code
exec(code, run_globals)
File “/home/erpnext/bench/apps/frappe/frappe/utils/bench_helper.py”, line 97, in
main()
File “/home/erpnext/bench/apps/frappe/frappe/utils/bench_helper.py”, line 18, in main
click.Group(commands=commands)(prog_name=‘bench’)
File “/home/erpnext/bench/env/lib/python3.6/site-packages/click/core.py”, line 764, in call
return self.main(*args, **kwargs)
File “/home/erpnext/bench/env/lib/python3.6/site-packages/click/core.py”, line 717, in main
rv = self.invoke(ctx)
File “/home/erpnext/bench/env/lib/python3.6/site-packages/click/core.py”, line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File “/home/erpnext/bench/env/lib/python3.6/site-packages/click/core.py”, line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File “/home/erpnext/bench/env/lib/python3.6/site-packages/click/core.py”, line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File “/home/erpnext/bench/env/lib/python3.6/site-packages/click/core.py”, line 555, in invoke
return callback(*args, **kwargs)
File “/home/erpnext/bench/env/lib/python3.6/site-packages/click/decorators.py”, line 17, in new_func
return f(get_current_context(), *args, **kwargs)
File “/home/erpnext/bench/apps/frappe/frappe/commands/init.py”, line 25, in _func
ret = f(frappe._dict(ctx.obj), *args, **kwargs)
File “/home/erpnext/bench/apps/frappe/frappe/commands/site.py”, line 179, in install_app
_install_app(app, verbose=context.verbose)
File “/home/erpnext/bench/apps/frappe/frappe/installer.py”, line 51, in install_app
frappe.clear_cache()
File “/home/erpnext/bench/apps/frappe/frappe/init.py”, line 582, in clear_cache
frappe.cache_manager.clear_user_cache()
File “/home/erpnext/bench/apps/frappe/frappe/cache_manager.py”, line 42, in clear_user_cache
clear_global_cache()
File “/home/erpnext/bench/apps/frappe/frappe/cache_manager.py”, line 48, in clear_global_cache
clear_website_cache()
File “/home/erpnext/bench/apps/frappe/frappe/website/render.py”, line 301, in clear_cache
for method in frappe.get_hooks(“website_clear_cache”):
File “/home/erpnext/bench/apps/frappe/frappe/init.py”, line 958, in get_hooks
hooks = _dict(cache().get_value(“app_hooks”, load_app_hooks))
File “/home/erpnext/bench/apps/frappe/frappe/utils/redis_wrapper.py”, line 79, in get_value
val = generator()
File “/home/erpnext/bench/apps/frappe/frappe/init.py”, line 932, in load_app_hooks
for app in [app_name] if app_name else get_installed_apps(sort=True):
File “/home/erpnext/bench/apps/frappe/frappe/init.py”, line 896, in get_installed_apps
installed = json.loads(db.get_global(“installed_apps”) or “[]”)
File “/home/erpnext/bench/apps/frappe/frappe/database/database.py”, line 702, in get_global
return self.get_default(key, user)
File “/home/erpnext/bench/apps/frappe/frappe/database/database.py”, line 706, in get_default
d = self.get_defaults(key, parent)
File “/home/erpnext/bench/apps/frappe/frappe/database/database.py”, line 724, in get_defaults
defaults = frappe.defaults.get_defaults(parent)
File “/home/erpnext/bench/apps/frappe/frappe/defaults.py”, line 77, in get_defaults
globald = get_defaults_for()
File “/home/erpnext/bench/apps/frappe/frappe/defaults.py”, line 204, in get_defaults_for
where parent = %s order by creation"“”, (parent,), as_dict=1)
File “/home/erpnext/bench/apps/frappe/frappe/database/database.py”, line 122, in sql
self.connect()
File “/home/erpnext/bench/apps/frappe/frappe/database/database.py”, line 75, in connect
self._conn = self.get_connection()
File “/home/erpnext/bench/apps/frappe/frappe/database/mariadb/database.py”, line 90, in get_connection
local_infile = frappe.conf.local_infile)
File “/home/erpnext/bench/env/lib/python3.6/site-packages/pymysql/init.py”, line 94, in Connect
return Connection(*args, **kwargs)
File “/home/erpnext/bench/env/lib/python3.6/site-packages/pymysql/connections.py”, line 325, in init
self.connect()
File “/home/erpnext/bench/env/lib/python3.6/site-packages/pymysql/connections.py”, line 599, in connect
self._request_authentication()
File “/home/erpnext/bench/env/lib/python3.6/site-packages/pymysql/connections.py”, line 861, in _request_authentication
auth_packet = self._read_packet()
File “/home/erpnext/bench/env/lib/python3.6/site-packages/pymysql/connections.py”, line 684, in _read_packet
packet.check_error()
File “/home/erpnext/bench/env/lib/python3.6/site-packages/pymysql/protocol.py”, line 220, in check_error
err.raise_mysql_exception(self._data)
File “/home/erpnext/bench/env/lib/python3.6/site-packages/pymysql/err.py”, line 109, in raise_mysql_exception
raise errorclass(errno, errval)
pymysql.err.OperationalError: (1045, “Access denied for user ‘erpnext’@‘localhost’ (using password: NO)”)

Any idea how I can resolve this?

I have found the solution to my problem and would like to post it here for the community.

If you’re running your instance with the DSN Multitenant On, you will have to specify the site when installing this app. Use this command:

bench --site mysite.com install-app erpnext_telegram_integration

Thanks for the awesome work.

1 Like

I’m loving this app so much. Thank you for putting the time and effort into making this possible.

There is one thing I notice so far: html tags do not work in the message. Is this the default behaviour?

Again, thanks for the awesome work.

Thank you for trying the app, and I am glad that you like it.
I have made the app to support the basic features of the Telegram, then I added SMS alerts and date alerts to it.

@youssef huv generated telegram token but while getting chart id not able to generate id shows " telegram.error.TimedOut: Timed out" .

@arokia have you create a Telegram bot from BotFather ?

@youssef yep created in android telegram and got access API also while clicking get chart id am getting timed out error.

And have you copied telegram token in your bot?