Compare commits

...

6 Commits

Author SHA1 Message Date
Hemna 6eadbd0555 fixed pep8 error 2023-01-10 11:48:51 -05:00
Hemna 4637038b8b fixed requirements.txt 2022-12-29 15:24:00 -05:00
Hemna d51347f48e Update for aprsd 3.0.0
This patch updates for using the oslo_config style CONF
and declares the plugin config vars
2022-12-29 14:44:34 -05:00
Hemna 185d40a06e Update for aprsd 2.7.0 2022-12-20 17:23:08 -05:00
Hemna 295e35aa06 remove trace 2022-12-20 17:23:08 -05:00
Walter A. Boring IV 06d3664586
Create FUNDING.yml 2021-12-14 11:00:11 -05:00
10 changed files with 250 additions and 36 deletions

12
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: wb4bor
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
Hemna <waboring@hemna.com>

18
ChangeLog Normal file
View File

@ -0,0 +1,18 @@
CHANGES
=======
v0.3.0
------
* Added PBR Version
v0.2.0
------
* Updated command to 'tw' from 't'. Added Help
* First working version that tweets!
v0.1.0
------
* Initial commit

View File

@ -21,7 +21,7 @@ docs: build
cp Changelog docs/changelog.rst
tox -edocs
clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
clean: clean-build clean-pyc clean-test clean-dev ## remove all build, test, coverage and Python artifacts
clean-build: ## remove build artifacts
rm -fr build/
@ -42,6 +42,10 @@ clean-test: ## remove test and coverage artifacts
rm -fr htmlcov/
rm -fr .pytest_cache
clean-dev:
rm -rf $(VENVDIR)
rm Makefile.venv
coverage: ## check code coverage quickly with the default Python
coverage run --source aprsd_twitter_plugin setup.py test
coverage report -m

View File

@ -0,0 +1,7 @@
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,17 +1,24 @@
import logging
import tweepy
from aprsd import messaging, plugin, trace
from aprsd import conf # noqa
from aprsd import plugin
from oslo_config import cfg
import aprsd_twitter_plugin
from aprsd_twitter_plugin import conf # noqa
CONF = cfg.CONF
LOG = logging.getLogger("APRSD")
class SendTweetPlugin(plugin.APRSDRegexCommandPluginBase):
version = "1.0"
version = aprsd_twitter_plugin.__version__
# 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 ?
command_name = "tweet"
@ -28,33 +35,52 @@ class SendTweetPlugin(plugin.APRSDRegexCommandPluginBase):
# Do some checks here?
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.
if not self.config.exists("services.twitter.apiKey"):
LOG.error("No services.twitter.apiKey exists. Plugin Disabled.")
if not CONF.aprsd_twitter_plugin.apiKey:
LOG.error(
"No aprsd_twitter_plugin.apiKey is set!."
" Plugin Disabled.",
)
self.enabled = False
if not self.config.exists("services.twitter.apiKey_secret"):
LOG.error("No services.twitter.apiKey_secret exists. Plugin Disabled.")
if not CONF.aprsd_twitter_plugin.apiKey_secret:
LOG.error(
"No aprsd_twitter_plugin.apiKey_secret is set."
" Plugin Disabled.",
)
self.enabled = False
if not self.config.exists("services.twitter.access_token"):
LOG.error("No services.twitter.access_token exists. Plugin Disabled.")
if not CONF.aprsd_twitter_plugin.access_token:
LOG.error(
"No aprsd_twitter_plugin.access_token exists."
" Plugin Disabled.",
)
self.enabled = False
if not self.config.exists("services.twitter.access_token_secret"):
LOG.error("No services.twitter.access_token_secret exists. Plugin Disabled.")
if not CONF.aprsd_twitter_plugin.access_token_secret:
LOG.error(
"No aprsd_twitter_plugin.access_token_secret exists."
" Plugin Disabled.",
)
self.enabled = False
def _create_client(self):
"""Create the twitter client object."""
auth = tweepy.OAuthHandler(
self.config.get("services.twitter.apiKey"),
self.config.get("services.twitter.apiKey_secret"),
CONF.aprsd_twitter_plugin.apiKey,
CONF.aprsd_twitter_plugin.apiKey_secret,
)
auth.set_access_token(
self.config.get("services.twitter.access_token"),
self.config.get("services.twitter.access_token_secret"),
CONF.aprsd_twitter_plugin.access_token,
CONF.aprsd_twitter_plugin.access_token_secret,
)
api = tweepy.API(
@ -72,36 +98,37 @@ class SendTweetPlugin(plugin.APRSDRegexCommandPluginBase):
return api
@trace.trace
def process(self, packet):
"""This is called when a received packet matches self.command_regex."""
LOG.info("SendTweetPlugin Plugin")
from_callsign = packet.get("from")
message = packet.get("message_text", None)
from_callsign = packet.from_call
message = packet.message_text
message = message.split(" ")
del message[0]
message = " ".join(message)
if self.enabled:
# Now we can process
mycall = self.config["ham"]["callsign"]
# Now we can process
auth_call = CONF.aprsd_twitter_plugin.callsign
# Only allow the owner of aprsd to send a tweet
if not from_callsign.startswith(mycall):
return "Unauthorized"
# Only allow the owner of aprsd to send a tweet
if not from_callsign.startswith(auth_call):
return f"{from_callsign} not authorized to tweet!"
client = self._create_client()
if not client:
LOG.error("No twitter client!!")
return "Failed to Auth"
client = self._create_client()
if not client:
LOG.error("No twitter client!!")
return "Failed to Auth"
# Now lets tweet!
client.update_status(message)
if CONF.aprsd_twitter_plugin.add_aprs_hashtag:
message += (
" #aprs #aprsd #hamradio "
"https://github.com/hemna/aprsd-twitter-plugin"
)
return "Tweet sent!"
else:
LOG.warning("SendTweetPlugin is disabled.")
return messaging.NULL_MESSAGE
# Now lets tweet!
client.update_status(message)
return "Tweet sent!"

View File

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

View File

@ -19,6 +19,10 @@ description_file =
README.rst
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]
setup-hooks =
pbr.hooks.setup_hook
@ -38,3 +42,6 @@ upload-dir = doc/build/html
[mypy]
ignore_missing_imports = True
strict = True
[bdist_wheel]
universal = 1