server/func/webhooks: call webhooks asynchronously

This commit is contained in:
Shyam Sunder 2020-10-06 11:55:09 -04:00
parent eaa6107a6c
commit 143f633eaa
2 changed files with 35 additions and 31 deletions

View file

@ -4,6 +4,7 @@ import os
import urllib.error import urllib.error
import urllib.request import urllib.request
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from threading import Thread
from typing import Any, Dict, List from typing import Any, Dict, List
from youtube_dl import YoutubeDL from youtube_dl import YoutubeDL
@ -63,23 +64,31 @@ def _youtube_dl_wrapper(url: str) -> bytes:
) )
def post_to_webhooks(payload: Dict[str, Any]) -> List[int]: def post_to_webhooks(payload: Dict[str, Any]) -> List[Thread]:
return_list = [] threads = [
for webhook in config.config["webhooks"] or []: Thread(target=_post_to_webhook, args=(webhook, payload))
req = urllib.request.Request(webhook) for webhook in (config.config["webhooks"] or [])
req.data = json.dumps( ]
payload, for thread in threads:
default=lambda x: x.isoformat("T") + "Z", thread.daemon = False
).encode("utf-8") thread.start()
req.add_header("Content-Type", "application/json") return threads
try:
res = urllib.request.urlopen(req)
if not 200 <= res.status <= 299: def _post_to_webhook(webhook: str, payload: Dict[str, Any]) -> None:
logger.warning( req = urllib.request.Request(webhook)
f"Webhook {webhook} returned {res.status} {res.reason}" req.data = json.dumps(
) payload,
return_list.append(res.status) default=lambda x: x.isoformat("T") + "Z",
except urllib.error.URLError as e: ).encode("utf-8")
logger.error(f"Unable to call webhook {webhook}: {str(e)}") req.add_header("Content-Type", "application/json")
return_list.append(400) try:
return return_list res = urllib.request.urlopen(req)
if not 200 <= res.status <= 299:
logger.warning(
f"Webhook {webhook} returned {res.status} {res.reason}"
)
return res.status
except urllib.error.URLError as e:
logger.warning(f"Unable to call webhook {webhook}: {str(e)}")
return 400

View file

@ -122,10 +122,8 @@ def test_no_webhooks(config_injector):
], ],
) )
def test_single_webhook(config_injector, webhook, status_code): def test_single_webhook(config_injector, webhook, status_code):
config_injector({"webhooks": [webhook]}) ret = net._post_to_webhook(webhook, {"test_arg": "test_value"})
res = net.post_to_webhooks({"test_arg": "test_value"}) assert ret == status_code
assert len(res) == 1
assert res[0] == status_code
def test_multiple_webhooks(config_injector): def test_multiple_webhooks(config_injector):
@ -133,17 +131,14 @@ def test_multiple_webhooks(config_injector):
{ {
"webhooks": [ "webhooks": [
"https://postman-echo.com/post", "https://postman-echo.com/post",
"https://postman-echo.com/post", "https://postman-echo.com/get",
] ]
} }
) )
res = net.post_to_webhooks({"test_arg": "test_value"}) threads = net.post_to_webhooks({"test_arg": "test_value"})
assert len(res) == 2 assert len(threads) == 2
assert res[0] == 200
assert res[1] == 200
def test_malformed_webhooks(config_injector): def test_malformed_webhooks(config_injector):
config_injector({"webhooks": ["malformed_url"]})
with pytest.raises(ValueError): with pytest.raises(ValueError):
net.post_to_webhooks({"test_arg": "test_value"}) net._post_to_webhook("malformed_url", {"test_arg": "test_value"})