diff --git a/api/chalicelib/core/alerts.py b/api/chalicelib/core/alerts.py index da6211687..7da05c2ee 100644 --- a/api/chalicelib/core/alerts.py +++ b/api/chalicelib/core/alerts.py @@ -1,9 +1,14 @@ import json import logging import time +from datetime import datetime + +from decouple import config import schemas -from chalicelib.core import notifications, slack, webhook +from chalicelib.core import notifications, webhook +from chalicelib.core.collaboration_msteams import MSTeams +from chalicelib.core.collaboration_slack import Slack from chalicelib.utils import pg_client, helper, email_helper from chalicelib.utils.TimeUTC import TimeUTC @@ -95,7 +100,7 @@ def process_notifications(data): for c in n["options"].pop("message"): if c["type"] not in full: full[c["type"]] = [] - if c["type"] in ["slack", "email"]: + if c["type"] in ["slack", "msteams", "email"]: full[c["type"]].append({ "notification": n, "destination": c["value"] @@ -107,13 +112,21 @@ def process_notifications(data): for t in full.keys(): for i in range(0, len(full[t]), BATCH_SIZE): notifications_list = full[t][i:i + BATCH_SIZE] + if notifications_list is None or len(notifications_list) == 0: + break if t == "slack": try: - slack.send_batch(notifications_list=notifications_list) + send_to_slack_batch(notifications_list=notifications_list) except Exception as e: logging.error("!!!Error while sending slack notifications batch") logging.error(str(e)) + elif t == "msteams": + try: + send_to_msteams_batch(notifications_list=notifications_list) + except Exception as e: + logging.error("!!!Error while sending msteams notifications batch") + logging.error(str(e)) elif t == "email": try: send_by_email_batch(notifications_list=notifications_list) @@ -149,16 +162,60 @@ def send_by_email_batch(notifications_list): time.sleep(1) +def send_to_slack_batch(notifications_list): + webhookId_map = {} + for n in notifications_list: + if n.get("destination") not in webhookId_map: + webhookId_map[n.get("destination")] = {"tenantId": n["notification"]["tenantId"], "batch": []} + webhookId_map[n.get("destination")]["batch"].append({"text": n["notification"]["description"] \ + + f"\n<{config('SITE_URL')}{n['notification']['buttonUrl']}|{n['notification']['buttonText']}>", + "title": n["notification"]["title"], + "title_link": n["notification"]["buttonUrl"], + "ts": datetime.now().timestamp()}) + for batch in webhookId_map.keys(): + Slack.send_batch(tenant_id=webhookId_map[batch]["tenantId"], webhook_id=batch, + attachments=webhookId_map[batch]["batch"]) + + +def send_to_msteams_batch(notifications_list): + webhookId_map = {} + for n in notifications_list: + if n.get("destination") not in webhookId_map: + webhookId_map[n.get("destination")] = {"tenantId": n["notification"]["tenantId"], "batch": []} + + link = f"[{n['notification']['buttonText']}]({config('SITE_URL')}{n['notification']['buttonUrl']})" + webhookId_map[n.get("destination")]["batch"].append({"type": "ColumnSet", + "style": "emphasis", + "separator": True, + "bleed": True, + "columns": [{ + "width": "stretch", + "items": [ + {"type": "TextBlock", + "text": n["notification"]["title"], + "style": "heading", + "size": "Large"}, + {"type": "TextBlock", + "spacing": "small", + "text": n["notification"]["description"], + "wrap": True}, + {"type": "TextBlock", + "spacing": "small", + "text": link} + ] + }]}) + for batch in webhookId_map.keys(): + MSTeams.send_batch(tenant_id=webhookId_map[batch]["tenantId"], webhook_id=batch, + attachments=webhookId_map[batch]["batch"]) + + def delete(project_id, alert_id): with pg_client.PostgresClient() as cur: cur.execute( - cur.mogrify("""\ - UPDATE public.alerts - SET - deleted_at = timezone('utc'::text, now()), - active = FALSE - WHERE - alert_id = %(alert_id)s AND project_id=%(project_id)s;""", + cur.mogrify(""" UPDATE public.alerts + SET deleted_at = timezone('utc'::text, now()), + active = FALSE + WHERE alert_id = %(alert_id)s AND project_id=%(project_id)s;""", {"alert_id": alert_id, "project_id": project_id}) ) return {"data": {"state": "success"}} diff --git a/api/chalicelib/core/collaboration_msteams.py b/api/chalicelib/core/collaboration_msteams.py index f903f8c4f..17a69da03 100644 --- a/api/chalicelib/core/collaboration_msteams.py +++ b/api/chalicelib/core/collaboration_msteams.py @@ -1,3 +1,5 @@ +import json + import requests from decouple import config @@ -17,6 +19,7 @@ class MSTeams(BaseCollaboration): return None # https://messagecardplayground.azurewebsites.net + # https://adaptivecards.io/designer/ @classmethod def say_hello(cls, url): r = requests.post( @@ -58,15 +61,33 @@ class MSTeams(BaseCollaboration): @classmethod def send_batch(cls, tenant_id, webhook_id, attachments): - # TODO: change this integration = cls.__get(tenant_id=tenant_id, integration_id=webhook_id) if integration is None: - return {"errors": ["slack integration not found"]} - print(f"====> sending slack batch notification: {len(attachments)}") + return {"errors": ["msteams integration not found"]} + print(f"====> sending msteams batch notification: {len(attachments)}") for i in range(0, len(attachments), 100): + print(json.dumps({"type": "message", + "attachments": [ + {"contentType": "application/vnd.microsoft.card.adaptive", + "contentUrl": None, + "content": { + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "version": "1.2", + "body": attachments[i:i + 100]}} + ]})) r = requests.post( url=integration["endpoint"], - json={"attachments": attachments[i:i + 100]}) + json={"type": "message", + "attachments": [ + {"contentType": "application/vnd.microsoft.card.adaptive", + "contentUrl": None, + "content": { + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "version": "1.2", + "body": attachments[i:i + 100]}} + ]}) if r.status_code != 200: print("!!!! something went wrong") print(r) @@ -86,7 +107,7 @@ class MSTeams(BaseCollaboration): "content": { "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", - "version": "1.2", + "version": "1.5", "body": [attachement]}} ] }) @@ -99,11 +120,16 @@ class MSTeams(BaseCollaboration): link = f"{config('SITE_URL')}/{project_id}/session/{session_id}" link = f"[{link}]({link})" args = {"type": "ColumnSet", + "style": "emphasis", + "separator": True, + "bleed": True, "columns": [{ "width": "stretch", "items": [ {"type": "TextBlock", - "text": title}, + "text": title, + "style": "heading", + "size": "Large"}, {"type": "TextBlock", "spacing": "small", "text": link} @@ -126,11 +152,16 @@ class MSTeams(BaseCollaboration): link = f"{config('SITE_URL')}/{project_id}/errors/{error_id}" link = f"[{link}]({link})" args = {"type": "ColumnSet", + "style": "emphasis", + "separator": True, + "bleed": True, "columns": [{ "width": "stretch", "items": [ {"type": "TextBlock", - "text": title}, + "text": title, + "style": "heading", + "size": "Large"}, {"type": "TextBlock", "spacing": "small", "text": link} diff --git a/api/chalicelib/core/slack.py b/api/chalicelib/core/slack.py deleted file mode 100644 index 76bf40163..000000000 --- a/api/chalicelib/core/slack.py +++ /dev/null @@ -1,21 +0,0 @@ -from datetime import datetime -from decouple import config - -from chalicelib.core.collaboration_slack import Slack - - -def send_batch(notifications_list): - if notifications_list is None or len(notifications_list) == 0: - return - webhookId_map = {} - for n in notifications_list: - if n.get("destination") not in webhookId_map: - webhookId_map[n.get("destination")] = {"tenantId": n["notification"]["tenantId"], "batch": []} - webhookId_map[n.get("destination")]["batch"].append({"text": n["notification"]["description"] \ - + f"\n<{config('SITE_URL')}{n['notification']['buttonUrl']}|{n['notification']['buttonText']}>", - "title": n["notification"]["title"], - "title_link": n["notification"]["buttonUrl"], - "ts": datetime.now().timestamp()}) - for batch in webhookId_map.keys(): - Slack.send_batch(tenant_id=webhookId_map[batch]["tenantId"], webhook_id=batch, - attachments=webhookId_map[batch]["batch"]) diff --git a/api/routers/core.py b/api/routers/core.py index cf7e918d7..ac7634c25 100644 --- a/api/routers/core.py +++ b/api/routers/core.py @@ -117,7 +117,7 @@ def integration_notify(projectId: int, integration: str, webhookId: int, source: if source == "sessions": return MSTeams.share_session(session_id=sourceId, **args) elif source == "errors": - return Slack.share_error(error_id=sourceId, **args) + return MSTeams.share_error(error_id=sourceId, **args) return {"data": None} diff --git a/ee/api/.gitignore b/ee/api/.gitignore index ee23eb7ff..7d179e8c2 100644 --- a/ee/api/.gitignore +++ b/ee/api/.gitignore @@ -214,7 +214,6 @@ Pipfile /chalicelib/core/sessions_metas.py /chalicelib/core/sessions_mobs.py #exp /chalicelib/core/significance.py -/chalicelib/core/slack.py /chalicelib/core/socket_ios.py /chalicelib/core/sourcemaps.py /chalicelib/core/sourcemaps_parser.py diff --git a/ee/api/clean.sh b/ee/api/clean.sh index 314321b83..4e72038ed 100755 --- a/ee/api/clean.sh +++ b/ee/api/clean.sh @@ -36,7 +36,6 @@ rm -rf ./chalicelib/core/sessions_assignments.py rm -rf ./chalicelib/core/sessions_metas.py rm -rf ./chalicelib/core/sessions_mobs.py #exp rm -rf ./chalicelib/core/significance.py -rm -rf ./chalicelib/core/slack.py rm -rf ./chalicelib/core/socket_ios.py rm -rf ./chalicelib/core/sourcemaps.py rm -rf ./chalicelib/core/sourcemaps_parser.py