Update for aprsd 3.0.0

This patch updates for using the oslo_config style CONF
and declares the plugin config vars
This commit is contained in:
Hemna 2022-12-29 14:44:34 -05:00
parent 185d40a06e
commit d51347f48e
6 changed files with 209 additions and 31 deletions

View File

@ -0,0 +1,10 @@
import logging
from oslo_config import cfg
from aprsd_twitter_plugin.conf import twitter
CONF = cfg.CONF
twitter.register_opts(CONF)

View 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_twitter_plugin.conf." + modname)
if not hasattr(mod, LIST_OPTS_FUNC_NAME):
msg = "The module 'aprsd_twitter_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)

View File

@ -0,0 +1,57 @@
from oslo_config import cfg
twitter_group = cfg.OptGroup(
name="aprsd_twitter_plugin",
title="APRSD Twitter Plugin settings",
)
twitter_opts = [
cfg.StrOpt(
"callsign",
help="Callsign allowed to send tweets! "
"Any callsign starting with this will be allowed to tweet to"
"the configured twitter account. "
"For example, if you set this to WB4BOR then any"
"callsign starting with WB4BOR will be allowed to tweet."
"This way WB4BOR-1 can tweet from this instance.",
),
cfg.StrOpt(
"apiKey",
help="Your twitter apiKey"
"Information for creating your api keys is here: "
"https://developer.twitter.com/en/docs/authentication/oauth-1-0a/api-key-and-secret",
),
cfg.StrOpt(
"apiKey_secret",
help="Your twitter accounts apikey secret.",
),
cfg.StrOpt(
"access_token",
help="The twitter access_token for your Twitter account",
),
cfg.StrOpt(
"access_token_secret",
help="The twitter access token secret for your Twitter account",
),
cfg.BoolOpt(
"add_aprs_hashtag",
default=True,
help="Automatically add #aprs hash tag to every tweet?",
),
]
ALL_OPTS = (
twitter_opts
)
def register_opts(cfg):
cfg.register_group(twitter_group)
cfg.register_opts(ALL_OPTS, group=twitter_group)
def list_opts():
return {
twitter_group.name: ALL_OPTS,
}

View File

@ -1,11 +1,15 @@
import logging import logging
import tweepy import tweepy
from aprsd import packets, plugin from aprsd import conf # noqa
from aprsd import plugin
from oslo_config import cfg
import aprsd_twitter_plugin import aprsd_twitter_plugin
from aprsd_twitter_plugin import conf # noqa
CONF = cfg.CONF
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -13,7 +17,8 @@ class SendTweetPlugin(plugin.APRSDRegexCommandPluginBase):
version = aprsd_twitter_plugin.__version__ version = aprsd_twitter_plugin.__version__
# Look for any command that starts with tw or tW or TW or Tw # Look for any command that starts with tw or tW or TW or Tw
command_regex = "^[tT][wW]" # or case insensitive version of 'twitter'
command_regex = r"^([t][w]\s|twitter)"
# the command is for ? # the command is for ?
command_name = "tweet" command_name = "tweet"
@ -30,33 +35,52 @@ class SendTweetPlugin(plugin.APRSDRegexCommandPluginBase):
# Do some checks here? # Do some checks here?
self.enabled = True self.enabled = True
if not CONF.aprsd_twitter_plugin.callsign:
LOG.error(
"No aprsd_twitter_pligin.callsign is set."
" Callsign is needed to allow tweets!",
)
self.enabled = False
# Ensure the access token exists. # Ensure the access token exists.
if not self.config.exists("services.twitter.apiKey"): if not CONF.aprsd_twitter_plugin.apiKey:
LOG.error("No services.twitter.apiKey exists. Plugin Disabled.") LOG.error(
"No aprsd_twitter_plugin.apiKey is set!."
" Plugin Disabled.",
)
self.enabled = False self.enabled = False
if not self.config.exists("services.twitter.apiKey_secret"): if not CONF.aprsd_twitter_plugin.apiKey_secret:
LOG.error("No services.twitter.apiKey_secret exists. Plugin Disabled.") LOG.error(
"No aprsd_twitter_plugin.apiKey_secret is set."
" Plugin Disabled.",
)
self.enabled = False self.enabled = False
if not self.config.exists("services.twitter.access_token"): if not CONF.aprsd_twitter_plugin.access_token:
LOG.error("No services.twitter.access_token exists. Plugin Disabled.") LOG.error(
"No aprsd_twitter_plugin.access_token exists."
" Plugin Disabled.",
)
self.enabled = False self.enabled = False
if not self.config.exists("services.twitter.access_token_secret"): if not CONF.aprsd_twitter_plugin.access_token_secret:
LOG.error("No services.twitter.access_token_secret exists. Plugin Disabled.") LOG.error(
"No aprsd_twitter_plugin.access_token_secret exists."
" Plugin Disabled.",
)
self.enabled = False self.enabled = False
def _create_client(self): def _create_client(self):
"""Create the twitter client object.""" """Create the twitter client object."""
auth = tweepy.OAuthHandler( auth = tweepy.OAuthHandler(
self.config.get("services.twitter.apiKey"), CONF.aprsd_twitter_plugin.apiKey,
self.config.get("services.twitter.apiKey_secret"), CONF.aprsd_twitter_plugin.apiKey_secret,
) )
auth.set_access_token( auth.set_access_token(
self.config.get("services.twitter.access_token"), CONF.aprsd_twitter_plugin.access_token,
self.config.get("services.twitter.access_token_secret"), CONF.aprsd_twitter_plugin.access_token_secret,
) )
api = tweepy.API( api = tweepy.API(
@ -86,23 +110,25 @@ class SendTweetPlugin(plugin.APRSDRegexCommandPluginBase):
del message[0] del message[0]
message = " ".join(message) message = " ".join(message)
if self.enabled:
# Now we can process # Now we can process
mycall = self.config["ham"]["callsign"] auth_call = CONF.aprsd_twitter_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(auth_call):
return "Unauthorized" return f"{from_callsign} not authorized to tweet!"
client = self._create_client() client = self._create_client()
if not client: if not client:
LOG.error("No twitter client!!") LOG.error("No twitter client!!")
return "Failed to Auth" return "Failed to Auth"
if CONF.aprsd_twitter_plugin.add_aprs_hashtag:
message += (
" #aprs #aprsd #hamradio "
"https://github.com/hemna/aprsd-twitter-plugin"
)
# Now lets tweet! # Now lets tweet!
client.update_status(message) client.update_status(message)
return "Tweet sent!" return "Tweet sent!"
else:
LOG.warning("SendTweetPlugin is disabled.")
return packets.NULL_MESSAGE

View File

@ -1,3 +1,4 @@
pbr pbr
aprsd>=2.7.0 aprsd>=3.0.0
tweepy tweepy
oslo-config

View File

@ -19,6 +19,10 @@ description_file =
README.rst README.rst
summary = Python APRSD plugin to send tweets summary = Python APRSD plugin to send tweets
[options.entry_points]
oslo.config.opts =
aprsd_twitter_plugin.conf = aprsd_twitter_plugin.conf.opts:list_opts
[global] [global]
setup-hooks = setup-hooks =
pbr.hooks.setup_hook pbr.hooks.setup_hook