diff options
author | Magnus Hagander | 2020-05-18 14:37:06 +0000 |
---|---|---|
committer | Magnus Hagander | 2020-05-18 14:37:06 +0000 |
commit | da947f59e4b30671da0fd666cdf503b40c1fcf5c (patch) | |
tree | 3f8bb1ba55f90300328f9be62ecadde2c720ae05 /postgresqleu/util/oauthapps.py | |
parent | ab6723636735c1fa8be9dfc07c56410a3ac0e644 (diff) |
Complete overhaul of social media integrations
* Remove the hard-coded twitter implementation and replace it with an
infrastructure for pluggable implementations.
* Separate out "social media broadcasting" (public twitter posts) from
"private notifications" (DMs) and invent "private broadcasting"
(notifications sent only to attendees of a conference) and
"organisation notifications" (sent to organisers).
* Add the concept of a Messaging Provider that's configured on a
Conference Series, which maps to a twitter account (or similar in
other providers). Replace "incoming twitter active" flag on a
conference with a setting on this messaging provider for "route
messages to conference". This way the messaging doesn't have to be
reconfigured for each new conference in a series, and we also
automatically avoid the risk of having two conferences getting the
same input.
* For each conference in a series, the individual Messaging Providers
can be enabled or disabled for the different functionality, and
individual channels be configured when applicable.
* Add implementations of Twitter (updated, social broadcasting and
private messaging support), Mastodon (social broadcasting and private
messaging) and Telegram (attendee boadcasts, private notifications,
and organisation broadcasts)
* Add webhook support for Twitter and Telegram, making for much faster
reactions to incoming messages.
* Hardcoded news twitter post accounts, and replaced with
MessagingProviders per above that are not attached to a conference.
* Add a daemon that listens to PostgreSQL notifications and sends out
broadcasts and notifications for quicker action (if not enabled, a
scheduled task will send them out every 10 minutes like before)
* In making broadcast posts, add support for the fact that different
providers have different max length of posts (e.g. Twitter currently has
280 and Mastodon 500), and also roughly account for the effects of
URL shorterners on posts.
* Add a button to registration dashboards to send DMs to attendees that
have configured notification.
* Send "private broadcasts" ahead of any talks to keep people posted of
talks. For now this is always enabled if a channel is set up for
private broadcasts, we may want to consider making it more
configurable in the future.
There are still a lot of tables and files referring Twitter in the tree,
and some of those will be renamed in a future commit to make tracking of
changes easier.
Fixes #29
Fixes #13
Diffstat (limited to 'postgresqleu/util/oauthapps.py')
-rw-r--r-- | postgresqleu/util/oauthapps.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/postgresqleu/util/oauthapps.py b/postgresqleu/util/oauthapps.py new file mode 100644 index 00000000..89f77b8b --- /dev/null +++ b/postgresqleu/util/oauthapps.py @@ -0,0 +1,79 @@ +from django.apps import apps +from django.conf import settings +from django.db.models.signals import post_save, post_delete + +import requests + +# Wrapper that caches oauth information, since it very rearely updates + + +class OAuthProviders(object): + def __init__(self): + self._providers = None + + @property + def providers(self): + if not self._providers: + mod = apps.get_app_config('util').get_model('OAuthApplication') + self._providers = {a.baseurl: a for a in mod.objects.all()} + return self._providers + + def invalidate_cache(self): + self._providers = None + + +providers = OAuthProviders() + + +def get_oauth_client(baseurl): + return providers.providers[baseurl].client + + +def get_oauth_secret(baseurl): + return providers.providers[baseurl].secret + + +def has_oauth_data(baseurl): + return baseurl in providers.providers + + +def _mastodon_oauth_maker(baseurl): + # Mastodon allows automatic creation of apps + r = requests.post('{}/api/v1/apps'.format(baseurl), data={ + 'client_name': settings.ORG_SHORTNAME, + 'redirect_uris': 'urn:ietf:wg:oauth:2.0:oob', + 'scopes': 'read write:statuses write:media', + }) + r.raise_for_status() + j = r.json() + return (j['client_id'], j['client_secret']) + + +_oauth_application_choices = { + 'mastodon': ('https://mastodon.social', 0, _mastodon_oauth_maker), + 'twitter': ('https://api.twitter.com', 1, None), +} + + +def oauth_application_choices(): + for n, m in _oauth_application_choices.items(): + # If the provider is "locked" to a baseurl and that baseurl is already added, + # then don't show it in the list. + if not (m[1] and m[0] in providers.providers): + yield (n, n, m[0], m[1]) + + +def oauth_application_create(app, baseurl): + if _oauth_application_choices.get(app, None): + if _oauth_application_choices[app][2]: + return _oauth_application_choices[app][2](baseurl) + return (None, None) + + +def _invalidate_cache(**kwargs): + providers.invalidate_cache() + + +def connect_oauth_signals(): + post_save.connect(_invalidate_cache, sender=apps.get_app_config('util').get_model('OAuthApplication')) + post_delete.connect(_invalidate_cache, sender=apps.get_app_config('util').get_model('OAuthApplication')) |