Skip to content

Commit

Permalink
First version working
Browse files Browse the repository at this point in the history
  • Loading branch information
hemna committed Oct 25, 2021
1 parent 375037d commit 754ff73
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 84 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hemna <[email protected]>
7 changes: 7 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CHANGES
=======

v0.1.0
------

* Initial commit
79 changes: 50 additions & 29 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,20 @@ aprsd-telegram-plugin

|pre-commit|

.. |PyPI| image:: https://img.shields.io/pypi/v/aprsd-telegram-plugin.svg
:target: https://pypi.org/project/aprsd-telegram-plugin/
:alt: PyPI
.. |Status| image:: https://img.shields.io/pypi/status/aprsd-telegram-plugin.svg
:target: https://pypi.org/project/aprsd-telegram-plugin/
:alt: Status
.. |Python Version| image:: https://img.shields.io/pypi/pyversions/aprsd-telegram-plugin
:target: https://pypi.org/project/aprsd-telegram-plugin
:alt: Python Version
.. |License| image:: https://img.shields.io/pypi/l/aprsd-telegram-plugin
:target: https://opensource.org/licenses/MIT
:alt: License
.. |Read the Docs| image:: https://img.shields.io/readthedocs/aprsd-telegram-plugin/latest.svg?label=Read%20the%20Docs
:target: https://aprsd-telegram-plugin.readthedocs.io/
:alt: Read the documentation at https://aprsd-telegram-plugin.readthedocs.io/
.. |Tests| image:: https://github.com/hemna/aprsd-telegram-plugin/workflows/Tests/badge.svg
:target: https://github.com/hemna/aprsd-telegram-plugin/actions?workflow=Tests
:alt: Tests
.. |Codecov| image:: https://codecov.io/gh/hemna/aprsd-telegram-plugin/branch/main/graph/badge.svg
:target: https://codecov.io/gh/hemna/aprsd-telegram-plugin
:alt: Codecov
.. |pre-commit| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white
:target: https://github.com/pre-commit/pre-commit
:alt: pre-commit


Features
--------

* TODO

* Have a 2 way chat with users of Telegram messenger `http://telegram.org`

Requirements
------------

* TODO

* You have to create a telegram bot and start the bot
* Telegram users have to add that bot and then /start
* Telegram user can then message the bot
* Only after a telegram user has successfully completed the above
can you then message a telegram user from an APRS enabled HAM Radio.

Installation
------------
Expand All @@ -55,6 +32,22 @@ You can install *aprsd-telegram-plugin* via pip_ from PyPI_:
$ pip install aprsd-telegram-plugin
Now edit your aprsd.yml config file and add the plugin

.. code:: yaml
aprsd:
enabled_plugins:
- aprsd_telegram_plugin.telegram.TelegramChatPlugin
services:
telegram:
apiKey: <Your Telegram bot APIkey>
shortcuts:
'wb': hemna6969
Usage
-----

Expand Down Expand Up @@ -97,3 +90,31 @@ This project was generated from `@hemna`_'s `APRSD Plugin Python Cookiecutter`_
.. github-only
.. _Contributor Guide: CONTRIBUTING.rst
.. _Usage: https://aprsd-telegram-plugin.readthedocs.io/en/latest/usage.html


.. badges
.. |PyPI| image:: https://img.shields.io/pypi/v/aprsd-telegram-plugin.svg
:target: https://pypi.org/project/aprsd-telegram-plugin/
:alt: PyPI
.. |Status| image:: https://img.shields.io/pypi/status/aprsd-telegram-plugin.svg
:target: https://pypi.org/project/aprsd-telegram-plugin/
:alt: Status
.. |Python Version| image:: https://img.shields.io/pypi/pyversions/aprsd-telegram-plugin
:target: https://pypi.org/project/aprsd-telegram-plugin
:alt: Python Version
.. |License| image:: https://img.shields.io/pypi/l/aprsd-telegram-plugin
:target: https://opensource.org/licenses/MIT
:alt: License
.. |Read the Docs| image:: https://img.shields.io/readthedocs/aprsd-telegram-plugin/latest.svg?label=Read%20the%20Docs
:target: https://aprsd-telegram-plugin.readthedocs.io/
:alt: Read the documentation at https://aprsd-telegram-plugin.readthedocs.io/
.. |Tests| image:: https://github.com/hemna/aprsd-telegram-plugin/workflows/Tests/badge.svg
:target: https://github.com/hemna/aprsd-telegram-plugin/actions?workflow=Tests
:alt: Tests
.. |Codecov| image:: https://codecov.io/gh/hemna/aprsd-telegram-plugin/branch/main/graph/badge.svg
:target: https://codecov.io/gh/hemna/aprsd-telegram-plugin
:alt: Codecov
.. |pre-commit| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white
:target: https://github.com/pre-commit/pre-commit
:alt: pre-commit
54 changes: 0 additions & 54 deletions aprsd_telegram_plugin/aprsd_telegram_plugin.py

This file was deleted.

210 changes: 210 additions & 0 deletions aprsd_telegram_plugin/telegram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import datetime
import logging
import threading

from aprsd import messaging, objectstore, plugin, threads, trace
from telegram.ext import Filters, MessageHandler, Updater


LOG = logging.getLogger("APRSD")


class TelegramUsers(objectstore.ObjectStoreMixin):
"""Class to automatically store telegram user ids between starts.
Telegram doesn't provide an API for looking up an userid from
username, so we have to save it off for better user experience.
Unfortunately, we can't get the userid, until the telegram user
sends a message to the bot FIRST.
"""
_instance = None
data = {}
config = None
_shortcuts = {}

def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.lock = threading.Lock()
cls._instance.config = kwargs["config"]
cls._instance.data = {}
if kwargs["config"].exists("services.telegram.shortcuts"):
cls._instance._shortcuts = kwargs["config"].get("services.telegram.shortcuts")
else:
cls._instance._shortcuts = None
cls._instance._init_store()
return cls._instance

def __getitem__(self, item):
with self.lock:
if item in self._shortcuts:
item = self._shortcuts[item]
return self.data[item]

def __setitem__(self, item, value):
with self.lock:
self.data[item] = value

def __delitem__(self, item):
del self.data[item]

def __contains__(self, item):
if item in self._shortcuts:
item = self._shortcuts[item]

if item in self.data:
return True
else:
return False

def get_shortcuts(self):
return self._shortcuts


class TelegramChatPlugin(plugin.APRSDRegexCommandPluginBase):

version = "1.0"
# Look for any command that starts with w or W
command_regex = "^[tT][gG]"
# the command is for ?
command_name = "telegram"

enabled = False
users = None

def help(self):
_help = [
"telegram: Chat with a user on telegram Messenger.",
"telegram: username has to message you first."
"tg: Send tg <shortcut/username> <message>",
]
return _help

def setup(self):
self.enabled = True
# Do some checks here?
try:
self.config.check_option(["services", "telegram", "apiKey"])
except Exception as ex:
LOG.error(f"Failed to find config telegram:apiKey {ex}")
self.enabled = False
return

token = self.config.get("services.telegram.apiKey")

self.users = TelegramUsers(config=self.config)
self.users.load()

# self.bot = telegram.Bot(token=token)
# LOG.info(self.bot.get_me())
self.updater = Updater(
token=token,
use_context=True,
persistence=False,
)
self.dispatcher = self.updater.dispatcher
self.dispatcher.add_handler(
MessageHandler(
Filters.text & (~Filters.command),
self.message_handler,
),
)

def message_handler(self, update, context):
"""This is called when a telegram users texts the bot."""
LOG.info(f"{self.__class__.__name__}: Got message {update.message.text}")
# LOG.info(f"Text {update.message.text}")
# LOG.info(f"Chat {update.message.chat}")
# LOG.info(f"From {update.message.from.username} : ")
fromcall = self.config.get("aprs.login")
tocall = self.config.get("ham.callsign")

if update.message.chat.type == "private":
LOG.info(f"Username {update.message.chat.username} - ID {update.message.chat.id}")
message = "Telegram({}): {}".format(
update.message.chat.username,
update.message.text,
)
self.users[update.message.chat.username] = update.message.chat.id
# LOG.debug(self.users)
# LOG.info(f"{message}")
msg = messaging.TextMessage(fromcall, tocall, message)
msg.send()
elif update.message.chat.type == "group":
group_name = "noidea"
message = "TelegramGroup({}): {}".format(
group_name,
update.message.text,
)
msg = messaging.TextMessage(fromcall, tocall, message)
msg.send()

def create_threads(self):
if self.enabled:
return TelegramThread(self.config, self.updater)

@trace.trace
def process(self, packet):
"""This is called when a received packet matches self.command_regex."""
LOG.info("TelegramChatPlugin Plugin")

from_callsign = packet.get("from")
message = packet.get("message_text", None)

if self.enabled:
# Now we can process
# Only allow aprsd owner to use this.
mycall = self.config["ham"]["callsign"]

# Only allow the owner of aprsd to send a tweet
if not from_callsign.startswith(mycall):
return "Unauthorized"

# Always should have format of
# <command> <username> <message>
parts = message.split(" ")
LOG.info(parts)

if len(parts) < 3:
return "invalid request"
# parts[0] is the command
username = parts[1]
msg = " ".join(parts[2:])
if username not in self.users:
# Unfortunately there is no way to lookup a user ID
# from a username right now.
return f"Need a message from {username} first"

bot = self.updater.bot
bot.sendMessage(
chat_id=self.users[username],
text=msg,
)

return messaging.NULL_MESSAGE
else:
LOG.warning("TelegramChatPlugin is disabled.")
return messaging.NULL_MESSAGE


class TelegramThread(threads.APRSDThread):
def __init__(self, config, updater):
super().__init__(self.__class__.__name__)
self.config = config
self.past = datetime.datetime.now()
self.updater = updater

def stop(self):
self.thread_stop = True
self.updater.stop()
TelegramUsers(config=self.config).save()

def loop(self):
"""We have to loop, so we can stop the thread upon CTRL-C"""
self.updater.start_polling(
timeout=2,
drop_pending_updates=True,
)
# so we can continue looping
return True
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pbr
aprsd>=2.2.0
aprsd>=2.4.0
python-telegram-bot

0 comments on commit 754ff73

Please sign in to comment.