-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor slackbridge.py to wsgi.py. Add config loader classes.
If you use the PORTAL_n_SIDE_n env config or the slackbridgeconf.py style config, you need only replace your reference to slackbridge.py to wsgi.py. However, you may now start using an inifile for configuration. See sample.ini for an example. Configuration loading is done in the following order: - environment (PORTAL_n_SIDE_n_...) - if that was not found, load inifile (./slackbridge.ini or the filename found in SLACKBRIDGE_INIFILE env) If slackbridgeconf.py is found, it is loaded as well. Expect this to change in future commits. If you're replacing your CONFIG-style slackbridge conf with either the INI or ENV style config, you can use testconfig.py to compare the output. The old CONFIG-style config was write only, so a double-check to see if you made any mistakes in the new INI or ENV config is highly recommended. Touches issue #12.
- Loading branch information
Showing
11 changed files
with
250 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,11 @@ __pycache__ | |
|
||
*.orig | ||
*.rej | ||
*.swp | ||
|
||
# Config files | ||
/slackbridge.ini | ||
/slackbridgeconf.py | ||
|
||
# Heroku stuff | ||
/.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,16 +2,19 @@ [email protected] | |
WEB_CONCURRENCY=3 | ||
|
||
# CivicTechTO Slack | ||
PORTAL_1_SIDE_A_WEBHOOK_OUT_TOKEN=xxxxxxxxxxxx | ||
PORTAL_1_SIDE_A_WEBHOOK_IN_URL=https://hooks.slack.com/services/xxxxxxxxxxxx | ||
# (GROUP_NAME is what we call them using @GROUP_NAME) | ||
PORTAL_1_SIDE_A_WEBHOOK_OUT_TOKEN=xxxxxxxxxxx1 | ||
PORTAL_1_SIDE_A_WEBHOOK_IN_URL=https://hooks.slack.com/services/xxxxxxxxxxx1 | ||
PORTAL_1_SIDE_A_CHANNEL_NAME=portal-yowcivictech | ||
PORTAL_1_SIDE_A_GROUP_NAME=yowcivictech | ||
PORTAL_1_SIDE_A_WEB_API_TOKEN=xxxxxxxxxxxx | ||
PORTAL_1_SIDE_A_WEB_API_TOKEN=xoxp-xxxxxxxxxxx1 | ||
|
||
# YOWCivicTech Slack | ||
PORTAL_1_SIDE_B_WEBHOOK_OUT_TOKEN=xxxxxxxxxxxx | ||
PORTAL_1_SIDE_B_WEBHOOK_IN_URL=https://hooks.slack.com/services/xxxxxxxxxxxx | ||
PORTAL_1_SIDE_B_WEBHOOK_OUT_TOKEN=xxxxxxxxxxx2 | ||
PORTAL_1_SIDE_B_WEBHOOK_IN_URL=https://hooks.slack.com/services/xxxxxxxxxxx2 | ||
PORTAL_1_SIDE_B_CHANNEL_NAME=portal-civictechto | ||
PORTAL_1_SIDE_B_GROUP_NAME=civictechto | ||
PORTAL_1_SIDE_B_WEB_API_TOKEN=xxxxxxxxxxxx | ||
# (WEB_API_TOKEN is allowed to be empty) | ||
PORTAL_1_SIDE_B_WEB_API_TOKEN= | ||
|
||
# Can increment portal number and add another set... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
; SlackBridge slackbridge.ini configuration file. | ||
; | ||
; ONLY WORKS WITH PYTHON3! | ||
; | ||
; Comments are valid after ';', even on the same line. Values may span | ||
; multiple lines, as long as indentation is used. Value reuse: [DEFAULT] | ||
; VAL=X [section1] key = ${VAL}YZ. | ||
; | ||
; Sections should contain L.webhook_in_url, L.webhook_out_token, | ||
; L.channel, L.peername and optionally L.webapi_token; twice, for L | ||
; being A and B. | ||
; | ||
; Example: | ||
; | ||
; [DEFAULT] | ||
; WEBHOOK_IN_URL = https://hooks.slack.com/services | ||
; WEBHOOK_IN_URL_OSSO = ${WEBHOOK_IN_URL}/X/Y/Z | ||
; WEBAPI_TOKEN_OSSO = xoxp-token-token-token | ||
; | ||
; [company1-osso] | ||
; A.webhook_in_url = | ||
; ${WEBHOOK_IN_URL}/AAAAAAAAA/BBBBBBBBB/cccccccccccccccccccccccc | ||
; A.webhook_out_token = dddddddddddddddddddddddd | ||
; A.channel = CXXXXXXXX | ||
; A.peername = osso | ||
; A.webapi_token = | ||
; | ||
; B.webhook_in_url = ${WEBHOOK_IN_URL_OSSO} | ||
; B.webhook_out_token = eeeeeeeeeeeeeeeeeeeeeeee | ||
; B.channel = #shared-company1 | ||
; B.peername = company1 | ||
; B.webapi_token = ${WEBAPI_TOKEN_OSSO} |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from . import env, ini | ||
from .ini import load as ini_load | ||
|
||
|
||
def load(): | ||
for mod in (env, ini): | ||
try: | ||
configs = mod.load() | ||
except StopIteration: | ||
pass | ||
else: | ||
return configs | ||
|
||
raise StopIteration() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
class BridgeEndConfig(object): | ||
""" | ||
All settings are mandatory, except the WEBAPI_TOKEN. However, it is | ||
preferred to have access to a limited user to supply info about | ||
@USERS, @CHANNELS, Avatars and the list of people online. | ||
Use a "Bot user" (single channel guest) in your #shared-peername | ||
channel for limited access. | ||
""" | ||
# From Slack to us: | ||
# '0123ABCDabcdefghijklmnop' | ||
WEBHOOK_OUT_TOKEN = None | ||
# From us to Slack: | ||
# 'https://hooks.slack.com/services/xxxxxxxxxxx' | ||
WEBHOOK_IN_URL = None | ||
# What channel name we use when writing to Slack: | ||
# 'C012345ZYX' or '#shared-peername' | ||
CHANNEL = None | ||
# The "@mention" to @channel only the other side: | ||
# 'othercompany' | ||
PEERNAME = None | ||
# WebAPI token for information gathering: | ||
# 'xoxp-0123456789-0123456789-0123456789-abcdef' | ||
WEBAPI_TOKEN = None | ||
|
||
|
||
class BridgeConfig(object): | ||
def __init__(self, name, side_a, side_b): | ||
self.NAME = name | ||
self.SIDE_A = side_a | ||
self.SIDE_B = side_b | ||
|
||
def __str__(self): | ||
return '<{}: {}->@{}, {}->@{}>'.format( | ||
self.NAME, self.SIDE_A.CHANNEL, self.SIDE_A.PEERNAME, | ||
self.SIDE_B.CHANNEL, self.SIDE_B.PEERNAME) | ||
|
||
|
||
class BridgeConfigs(object): | ||
""" | ||
Settings object holding all of the settings to be consumed by actual | ||
constructors of the actual slack communication. | ||
""" | ||
def __init__(self): | ||
self._pairs = [] | ||
|
||
def __len__(self): | ||
return len(self._pairs) # also for boolean check | ||
|
||
def add_config(self, bridgeconfig): | ||
self._pairs.append(bridgeconfig) | ||
|
||
def to_config_dict(self): | ||
""" | ||
Convert settings into old-style CONFIG dict. | ||
""" | ||
ret = {} | ||
for pair in self._pairs: | ||
for our, their in ( | ||
(pair.SIDE_A, pair.SIDE_B), (pair.SIDE_B, pair.SIDE_A)): | ||
ret[our.WEBHOOK_OUT_TOKEN] = { | ||
'iwh_url': their.WEBHOOK_IN_URL, | ||
'iwh_update': { | ||
'channel': their.CHANNEL, | ||
'_atchannel': our.PEERNAME, | ||
}, | ||
'owh_linked': their.WEBHOOK_OUT_TOKEN, | ||
} | ||
if our.WEBAPI_TOKEN: | ||
ret[our.WEBHOOK_OUT_TOKEN]['wa_token'] = our.WEBAPI_TOKEN | ||
|
||
return ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from os import environ as env | ||
|
||
from .data import BridgeConfig, BridgeConfigs, BridgeEndConfig | ||
|
||
|
||
def load(): | ||
configs = BridgeConfigs() | ||
try: | ||
idx = 1 | ||
|
||
while True: | ||
pair = [] | ||
for L in 'AB': | ||
end = BridgeEndConfig() | ||
end.WEBHOOK_OUT_TOKEN = env[ | ||
'PORTAL_{}_SIDE_{}_WEBHOOK_OUT_TOKEN'.format(idx, L)] | ||
end.WEBHOOK_IN_URL = env[ | ||
'PORTAL_{}_SIDE_{}_WEBHOOK_IN_URL'.format(idx, L)] | ||
end.CHANNEL = env[ | ||
'PORTAL_{}_SIDE_{}_CHANNEL_NAME'.format(idx, L)] | ||
end.PEERNAME = env[ # GROUP_NAME is "them", i.e. peername | ||
'PORTAL_{}_SIDE_{}_GROUP_NAME'.format(idx, L)] | ||
end.WEBAPI_TOKEN = env[ | ||
'PORTAL_{}_SIDE_{}_WEB_API_TOKEN'.format(idx, L)] | ||
pair.append(end) | ||
|
||
name = '{}-{}'.format(pair[1].PEERNAME, pair[0].PEERNAME) | ||
configs.add_config(BridgeConfig(name, *pair)) | ||
idx += 1 | ||
except KeyError: | ||
# Stop at first keyerror. | ||
pass | ||
|
||
if not len(configs): | ||
raise StopIteration('No SlackBridge config found in ENV') | ||
|
||
return configs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
from os import environ | ||
|
||
from .data import BridgeConfig, BridgeConfigs, BridgeEndConfig | ||
|
||
|
||
class BridgeConfigsFromIni(BridgeConfigs): | ||
def __init__(self, inifile): | ||
self._res = BridgeConfigs() | ||
self._ini = inifile | ||
self._load() | ||
|
||
def get(self): | ||
return self._res | ||
|
||
def _load(self): | ||
for section in self._ini.sections(): | ||
self._load_section(section, self._ini[section]) | ||
|
||
def _load_section(self, name, section): | ||
pair = [] | ||
for L in 'AB': | ||
def get(key): | ||
return section['{}.{}'.format(L, key)].strip() | ||
|
||
end = BridgeEndConfig() | ||
end.WEBHOOK_IN_URL = get('webhook_in_url') | ||
end.WEBHOOK_OUT_TOKEN = get('webhook_out_token') | ||
end.CHANNEL = get('channel') | ||
end.PEERNAME = get('peername') | ||
end.WEBAPI_TOKEN = get('webapi_token') | ||
pair.append(end) | ||
|
||
self._res.add_config(BridgeConfig(name, *pair)) | ||
|
||
|
||
def configs_from_inifile(inifile): | ||
try: | ||
from configparser import ConfigParser, ExtendedInterpolation | ||
except ImportError: | ||
import errno | ||
raise IOError( | ||
errno.ENOENT, | ||
'Missing ConfigParser and ExtendedInterpolation: ' | ||
'please use python3+') | ||
else: | ||
parser = ConfigParser( | ||
allow_no_value=False, # don't allow "key" without "=" | ||
delimiters=('=',), # inifile "=" between key and value | ||
comment_prefixes=(';',), # only ';' for comments (fixes #channel) | ||
inline_comment_prefixes=(';',), # comments after lines | ||
interpolation=ExtendedInterpolation(), | ||
empty_lines_in_values=False) # empty line means new key | ||
parser.read_file(inifile) | ||
return BridgeConfigsFromIni(parser).get() | ||
|
||
|
||
def load(): | ||
filename = environ.get('SLACKBRIDGE_INIFILE', './slackbridge.ini') | ||
with open(filename) as inifile: | ||
return configs_from_inifile(inifile) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Example script to check that your config still looks like it did | ||
# before upgrading. Compare it with the output of your COFIG dict before | ||
# updating to the new-style config. | ||
from pprint import pprint | ||
from slackbridge.config.auto import load | ||
|
||
configs = load() | ||
CONFIG = configs.to_config_dict() | ||
pprint(CONFIG) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters