mirror of
https://github.com/hemna/aprsd-telegram-plugin.git
synced 2025-07-29 12:02:25 -04:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
55b54b33e6 | |||
646f99b9fe | |||
a4dfb1393d | |||
9f87a8fec9 | |||
827832ae33 | |||
25e18a55d2 |
@ -1,6 +1,11 @@
|
|||||||
CHANGES
|
CHANGES
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
v0.1.3
|
||||||
|
------
|
||||||
|
|
||||||
|
* remove trace
|
||||||
|
|
||||||
v0.1.2
|
v0.1.2
|
||||||
------
|
------
|
||||||
|
|
||||||
|
33
README.rst
33
README.rst
@ -32,20 +32,33 @@ You can install *aprsd-telegram-plugin* via pip_ from PyPI_:
|
|||||||
$ pip install aprsd-telegram-plugin
|
$ pip install aprsd-telegram-plugin
|
||||||
|
|
||||||
|
|
||||||
Now edit your aprsd.yml config file and add the plugin
|
Now edit your aprsd.conf config file and add the plugin
|
||||||
|
|
||||||
.. code:: yaml
|
.. code:: ini
|
||||||
|
|
||||||
aprsd:
|
|
||||||
enabled_plugins:
|
|
||||||
- aprsd_telegram_plugin.telegram.TelegramChatPlugin
|
|
||||||
|
|
||||||
services:
|
[DEFAULT]
|
||||||
telegram:
|
enabled_plugins = aprsd_telegram_plugin.telegram.TelegramChatPlugin
|
||||||
apiKey: <Your Telegram bot APIkey>
|
|
||||||
shortcuts:
|
|
||||||
'wb': hemna6969
|
|
||||||
|
|
||||||
|
[aprsd_telegram_plugin]
|
||||||
|
|
||||||
|
#
|
||||||
|
# From aprsd_telegram_plugin.conf
|
||||||
|
#
|
||||||
|
|
||||||
|
# Callsign allowed to use Telegram! For example, if you set this to
|
||||||
|
# WB4BOR then anycallsign starting with WB4BOR will be allowed to use
|
||||||
|
# this.This way WB4BOR-1 can use this instance. (string value)
|
||||||
|
#callsign = <None>
|
||||||
|
|
||||||
|
# Your telegram apiKeyInformation for creating your api keys is here:
|
||||||
|
# https://core.telegram.org/api/obtaining_api_id (string value)
|
||||||
|
#apiKey = <None>
|
||||||
|
|
||||||
|
# List of shortcuts for sending telegram messages For Example:
|
||||||
|
# wb=hemna6969,cl=craigerl
|
||||||
|
# Means use 'wb' to send a telegram message to hemna6969 (list value)
|
||||||
|
#shortcuts = <None>
|
||||||
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
|
6
aprsd_telegram_plugin/conf/__init__.py
Normal file
6
aprsd_telegram_plugin/conf/__init__.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from aprsd_telegram_plugin.conf import telegram
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
telegram.register_opts(CONF)
|
80
aprsd_telegram_plugin/conf/opts.py
Normal file
80
aprsd_telegram_plugin/conf/opts.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# Copyright 2015 OpenStack Foundation
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""
|
||||||
|
This is the single point of entry to generate the sample configuration
|
||||||
|
file for Nova. It collects all the necessary info from the other modules
|
||||||
|
in this package. It is assumed that:
|
||||||
|
|
||||||
|
* every other module in this package has a 'list_opts' function which
|
||||||
|
return a dict where
|
||||||
|
* the keys are strings which are the group names
|
||||||
|
* the value of each key is a list of config options for that group
|
||||||
|
* the nova.conf package doesn't have further packages with config options
|
||||||
|
* this module is only used in the context of sample file generation
|
||||||
|
"""
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import importlib
|
||||||
|
import os
|
||||||
|
import pkgutil
|
||||||
|
|
||||||
|
|
||||||
|
LIST_OPTS_FUNC_NAME = "list_opts"
|
||||||
|
|
||||||
|
|
||||||
|
def _tupleize(dct):
|
||||||
|
"""Take the dict of options and convert to the 2-tuple format."""
|
||||||
|
return [(key, val) for key, val in dct.items()]
|
||||||
|
|
||||||
|
|
||||||
|
def list_opts():
|
||||||
|
opts = collections.defaultdict(list)
|
||||||
|
module_names = _list_module_names()
|
||||||
|
imported_modules = _import_modules(module_names)
|
||||||
|
_append_config_options(imported_modules, opts)
|
||||||
|
return _tupleize(opts)
|
||||||
|
|
||||||
|
|
||||||
|
def _list_module_names():
|
||||||
|
module_names = []
|
||||||
|
package_path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
for _, modname, ispkg in pkgutil.iter_modules(path=[package_path]):
|
||||||
|
if modname == "opts" or ispkg:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
module_names.append(modname)
|
||||||
|
return module_names
|
||||||
|
|
||||||
|
|
||||||
|
def _import_modules(module_names):
|
||||||
|
imported_modules = []
|
||||||
|
for modname in module_names:
|
||||||
|
mod = importlib.import_module("aprsd_telegram_plugin.conf." + modname)
|
||||||
|
if not hasattr(mod, LIST_OPTS_FUNC_NAME):
|
||||||
|
msg = "The module 'aprsd_telegram_plugin.conf.%s' should have a '%s' "\
|
||||||
|
"function which returns the config options." % \
|
||||||
|
(modname, LIST_OPTS_FUNC_NAME)
|
||||||
|
raise Exception(msg)
|
||||||
|
else:
|
||||||
|
imported_modules.append(mod)
|
||||||
|
return imported_modules
|
||||||
|
|
||||||
|
|
||||||
|
def _append_config_options(imported_modules, config_options):
|
||||||
|
for mod in imported_modules:
|
||||||
|
configs = mod.list_opts()
|
||||||
|
for key, val in configs.items():
|
||||||
|
config_options[key].extend(val)
|
44
aprsd_telegram_plugin/conf/telegram.py
Normal file
44
aprsd_telegram_plugin/conf/telegram.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
|
||||||
|
telegram_group = cfg.OptGroup(
|
||||||
|
name="aprsd_telegram_plugin",
|
||||||
|
title="APRSD Telegram Plugin settings",
|
||||||
|
)
|
||||||
|
|
||||||
|
telegram_opts = [
|
||||||
|
cfg.StrOpt(
|
||||||
|
"callsign",
|
||||||
|
help="Callsign allowed to use Telegram! "
|
||||||
|
"For example, if you set this to WB4BOR then any"
|
||||||
|
"callsign starting with WB4BOR will be allowed to use this."
|
||||||
|
"This way WB4BOR-1 can use this instance.",
|
||||||
|
),
|
||||||
|
cfg.StrOpt(
|
||||||
|
"apiKey",
|
||||||
|
help="Your telegram apiKey"
|
||||||
|
"Information for creating your api keys is here: "
|
||||||
|
"https://core.telegram.org/api/obtaining_api_id",
|
||||||
|
),
|
||||||
|
cfg.ListOpt(
|
||||||
|
"shortcuts",
|
||||||
|
help="List of shortcuts for sending telegram messages "
|
||||||
|
"For Example: wb=hemna6969,cl=craigerl\n"
|
||||||
|
"Means use 'wb' to send a telegram message to hemna6969",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
ALL_OPTS = (
|
||||||
|
telegram_opts
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def register_opts(cfg):
|
||||||
|
cfg.register_group(telegram_group)
|
||||||
|
cfg.register_opts(ALL_OPTS, group=telegram_group)
|
||||||
|
|
||||||
|
|
||||||
|
def list_opts():
|
||||||
|
return {
|
||||||
|
telegram_group.name: ALL_OPTS,
|
||||||
|
}
|
@ -3,12 +3,18 @@ import logging
|
|||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from aprsd import messaging, objectstore, plugin, threads
|
from aprsd import conf # noqa
|
||||||
|
from aprsd import packets, plugin, threads
|
||||||
|
from aprsd.threads import tx
|
||||||
|
from aprsd.utils import objectstore
|
||||||
|
from oslo_config import cfg
|
||||||
from telegram.ext import Filters, MessageHandler, Updater
|
from telegram.ext import Filters, MessageHandler, Updater
|
||||||
|
|
||||||
import aprsd_telegram_plugin
|
import aprsd_telegram_plugin
|
||||||
|
from aprsd_telegram_plugin import conf # noqa
|
||||||
|
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger("APRSD")
|
LOG = logging.getLogger("APRSD")
|
||||||
|
|
||||||
|
|
||||||
@ -23,17 +29,15 @@ class TelegramUsers(objectstore.ObjectStoreMixin):
|
|||||||
"""
|
"""
|
||||||
_instance = None
|
_instance = None
|
||||||
data = {}
|
data = {}
|
||||||
config = None
|
|
||||||
_shortcuts = {}
|
_shortcuts = {}
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
cls._instance = super().__new__(cls)
|
cls._instance = super().__new__(cls)
|
||||||
cls._instance.lock = threading.Lock()
|
cls._instance.lock = threading.Lock()
|
||||||
cls._instance.config = kwargs["config"]
|
|
||||||
cls._instance.data = {}
|
cls._instance.data = {}
|
||||||
if kwargs["config"].exists("services.telegram.shortcuts"):
|
if CONF.aprsd_telegram_plugin.shortcuts:
|
||||||
cls._instance._shortcuts = kwargs["config"].get("services.telegram.shortcuts")
|
cls._instance._shortcuts = CONF.aprsd_telegram_plugin.shortcuts
|
||||||
else:
|
else:
|
||||||
cls._instance._shortcuts = None
|
cls._instance._shortcuts = None
|
||||||
cls._instance._init_store()
|
cls._instance._init_store()
|
||||||
@ -87,16 +91,14 @@ class TelegramChatPlugin(plugin.APRSDRegexCommandPluginBase):
|
|||||||
def setup(self):
|
def setup(self):
|
||||||
self.enabled = True
|
self.enabled = True
|
||||||
# Do some checks here?
|
# Do some checks here?
|
||||||
try:
|
if not CONF.aprsd_telegram_plugin.apiKey:
|
||||||
self.config.check_option(["services", "telegram", "apiKey"])
|
LOG.error(f"Failed to find config telegram:apiKey")
|
||||||
except Exception as ex:
|
|
||||||
LOG.error(f"Failed to find config telegram:apiKey {ex}")
|
|
||||||
self.enabled = False
|
self.enabled = False
|
||||||
return
|
return
|
||||||
|
|
||||||
token = self.config.get("services.telegram.apiKey")
|
token = CONF.aprsd_telegram_plugin.apiKey
|
||||||
|
|
||||||
self.users = TelegramUsers(config=self.config)
|
self.users = TelegramUsers()
|
||||||
self.users.load()
|
self.users.load()
|
||||||
|
|
||||||
# self.bot = telegram.Bot(token=token)
|
# self.bot = telegram.Bot(token=token)
|
||||||
@ -131,8 +133,8 @@ class TelegramChatPlugin(plugin.APRSDRegexCommandPluginBase):
|
|||||||
# LOG.info(f"Text {update.message.text}")
|
# LOG.info(f"Text {update.message.text}")
|
||||||
# LOG.info(f"Chat {update.message.chat}")
|
# LOG.info(f"Chat {update.message.chat}")
|
||||||
# LOG.info(f"From {update.message.from.username} : ")
|
# LOG.info(f"From {update.message.from.username} : ")
|
||||||
fromcall = self.config.get("aprs.login")
|
fromcall = CONF.aprs_network.login
|
||||||
tocall = self.config.get("ham.callsign")
|
tocall = CONF.aprsd_telegram_plugin.callsign
|
||||||
|
|
||||||
if update.message.chat.type == "private":
|
if update.message.chat.type == "private":
|
||||||
LOG.info(f"Username {update.message.chat.username} - ID {update.message.chat.id}")
|
LOG.info(f"Username {update.message.chat.username} - ID {update.message.chat.id}")
|
||||||
@ -143,33 +145,41 @@ class TelegramChatPlugin(plugin.APRSDRegexCommandPluginBase):
|
|||||||
self.users[update.message.chat.username] = update.message.chat.id
|
self.users[update.message.chat.username] = update.message.chat.id
|
||||||
# LOG.debug(self.users)
|
# LOG.debug(self.users)
|
||||||
# LOG.info(f"{message}")
|
# LOG.info(f"{message}")
|
||||||
msg = messaging.TextMessage(fromcall, tocall, message)
|
pkt = packets.MessagePacket(
|
||||||
msg.send()
|
from_call=fromcall,
|
||||||
|
to_call=tocall,
|
||||||
|
message_text=message,
|
||||||
|
)
|
||||||
|
tx.send(pkt)
|
||||||
elif update.message.chat.type == "group":
|
elif update.message.chat.type == "group":
|
||||||
group_name = "noidea"
|
group_name = "noidea"
|
||||||
message = "TelegramGroup({}): {}".format(
|
message = "TelegramGroup({}): {}".format(
|
||||||
group_name,
|
group_name,
|
||||||
update.message.text,
|
update.message.text,
|
||||||
)
|
)
|
||||||
msg = messaging.TextMessage(fromcall, tocall, message)
|
pkt = packets.MessagePacket(
|
||||||
msg.send()
|
from_call=fromcall,
|
||||||
|
to_call=tocall,
|
||||||
|
message_text=message,
|
||||||
|
)
|
||||||
|
tx.send(pkt)
|
||||||
|
|
||||||
def create_threads(self):
|
def create_threads(self):
|
||||||
if self.enabled:
|
if self.enabled:
|
||||||
LOG.info("Starting TelegramThread")
|
LOG.info("Starting TelegramThread")
|
||||||
return TelegramThread(self.config, self.updater)
|
return TelegramThread(self.updater)
|
||||||
|
|
||||||
def process(self, packet):
|
def process(self, packet):
|
||||||
"""This is called when a received packet matches self.command_regex."""
|
"""This is called when a received packet matches self.command_regex."""
|
||||||
LOG.info("TelegramChatPlugin Plugin")
|
LOG.info("TelegramChatPlugin Plugin")
|
||||||
|
|
||||||
from_callsign = packet.get("from")
|
from_callsign = packet.from_call
|
||||||
message = packet.get("message_text", None)
|
message = packet.message_text
|
||||||
|
|
||||||
if self.enabled:
|
if self.enabled:
|
||||||
# Now we can process
|
# Now we can process
|
||||||
# Only allow aprsd owner to use this.
|
# Only allow aprsd owner to use this.
|
||||||
mycall = self.config["ham"]["callsign"]
|
mycall = CONF.aprsd_telegram_plugin.callsign
|
||||||
|
|
||||||
# Only allow the owner of aprsd to send a tweet
|
# Only allow the owner of aprsd to send a tweet
|
||||||
if not from_callsign.startswith(mycall):
|
if not from_callsign.startswith(mycall):
|
||||||
@ -196,23 +206,22 @@ class TelegramChatPlugin(plugin.APRSDRegexCommandPluginBase):
|
|||||||
text=msg,
|
text=msg,
|
||||||
)
|
)
|
||||||
|
|
||||||
return messaging.NULL_MESSAGE
|
return packets.NULL_MESSAGE
|
||||||
else:
|
else:
|
||||||
LOG.warning("TelegramChatPlugin is disabled.")
|
LOG.warning("TelegramChatPlugin is disabled.")
|
||||||
return messaging.NULL_MESSAGE
|
return packets.NULL_MESSAGE
|
||||||
|
|
||||||
|
|
||||||
class TelegramThread(threads.APRSDThread):
|
class TelegramThread(threads.APRSDThread):
|
||||||
def __init__(self, config, updater):
|
def __init__(self, updater):
|
||||||
super().__init__(self.__class__.__name__)
|
super().__init__(self.__class__.__name__)
|
||||||
self.config = config
|
|
||||||
self.past = datetime.datetime.now()
|
self.past = datetime.datetime.now()
|
||||||
self.updater = updater
|
self.updater = updater
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.thread_stop = True
|
self.thread_stop = True
|
||||||
self.updater.stop()
|
self.updater.stop()
|
||||||
TelegramUsers(config=self.config).save()
|
TelegramUsers().save()
|
||||||
|
|
||||||
def loop(self):
|
def loop(self):
|
||||||
"""We have to loop, so we can stop the thread upon CTRL-C"""
|
"""We have to loop, so we can stop the thread upon CTRL-C"""
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
pbr
|
pbr
|
||||||
aprsd>=2.4.0
|
aprsd>=3.0.0
|
||||||
python-telegram-bot
|
python-telegram-bot<20.0
|
||||||
|
oslo.config
|
||||||
|
@ -19,6 +19,10 @@ description_file =
|
|||||||
README.rst
|
README.rst
|
||||||
summary = Ham Radio APRS APRSD plugin for Telegram IM service
|
summary = Ham Radio APRS APRSD plugin for Telegram IM service
|
||||||
|
|
||||||
|
[options.entry_points]
|
||||||
|
oslo.config.opts =
|
||||||
|
aprsd_telegram_plugin.conf = aprsd_telegram_plugin.conf.opts:list_opts
|
||||||
|
|
||||||
[global]
|
[global]
|
||||||
setup-hooks =
|
setup-hooks =
|
||||||
pbr.hooks.setup_hook
|
pbr.hooks.setup_hook
|
||||||
|
Loading…
x
Reference in New Issue
Block a user