feat(chalice): refactored
This commit is contained in:
parent
19922f206b
commit
6fd3aba5e6
7 changed files with 216 additions and 55 deletions
49
api/chalicelib/core/collaboration_base.py
Normal file
49
api/chalicelib/core/collaboration_base.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
from abc import ABC, abstractmethod
|
||||
import requests
|
||||
from decouple import config
|
||||
from datetime import datetime
|
||||
|
||||
import schemas
|
||||
from chalicelib.core import webhook
|
||||
|
||||
|
||||
class BaseCollaboration(ABC):
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def add(cls, tenant_id, data: schemas.AddCollaborationSchema):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def say_hello(cls, url):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def send_raw(cls, tenant_id, webhook_id, body):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def send_batch(cls, tenant_id, webhook_id, attachments):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def __share(cls, tenant_id, integration_id, fallback, pretext, title, title_link, text):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def share_session(cls, tenant_id, project_id, session_id, user, comment, integration_id=None):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def share_error(cls, tenant_id, project_id, error_id, user, comment, integration_id=None):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def __get(cls, tenant_id, integration_id=None):
|
||||
pass
|
||||
121
api/chalicelib/core/collaboration_msteams.py
Normal file
121
api/chalicelib/core/collaboration_msteams.py
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import requests
|
||||
from decouple import config
|
||||
from datetime import datetime
|
||||
|
||||
import schemas
|
||||
from chalicelib.core import webhook
|
||||
from chalicelib.core.collaboration_base import BaseCollaboration
|
||||
|
||||
|
||||
class MSTeams(BaseCollaboration):
|
||||
@classmethod
|
||||
def add(cls, tenant_id, data: schemas.AddCollaborationSchema):
|
||||
if cls.say_hello(data.url):
|
||||
return webhook.add(tenant_id=tenant_id,
|
||||
endpoint=data.url,
|
||||
webhook_type="msteams",
|
||||
name=data.name)
|
||||
return None
|
||||
# https://messagecardplayground.azurewebsites.net
|
||||
@classmethod
|
||||
def say_hello(cls, url):
|
||||
r = requests.post(
|
||||
url=url,
|
||||
json={
|
||||
"@type": "MessageCard",
|
||||
"@context": "https://schema.org/extensions",
|
||||
"summary": "Hello message",
|
||||
"title": "Welcome to OpenReplay"
|
||||
})
|
||||
if r.status_code != 200:
|
||||
print("MSTeams integration failed")
|
||||
print(r.text)
|
||||
return False
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def send_raw(cls, tenant_id, webhook_id, body):
|
||||
integration = cls.__get(tenant_id=tenant_id, integration_id=webhook_id)
|
||||
if integration is None:
|
||||
return {"errors": ["slack integration not found"]}
|
||||
try:
|
||||
r = requests.post(
|
||||
url=integration["endpoint"],
|
||||
json=body,
|
||||
timeout=5)
|
||||
if r.status_code != 200:
|
||||
print(f"!! issue sending slack raw; webhookId:{webhook_id} code:{r.status_code}")
|
||||
print(r.text)
|
||||
return None
|
||||
except requests.exceptions.Timeout:
|
||||
print(f"!! Timeout sending slack raw webhookId:{webhook_id}")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"!! Issue sending slack raw webhookId:{webhook_id}")
|
||||
print(str(e))
|
||||
return None
|
||||
return {"data": r.text}
|
||||
|
||||
@classmethod
|
||||
def send_batch(cls, tenant_id, webhook_id, attachments):
|
||||
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)}")
|
||||
for i in range(0, len(attachments), 100):
|
||||
r = requests.post(
|
||||
url=integration["endpoint"],
|
||||
json={"attachments": attachments[i:i + 100]})
|
||||
if r.status_code != 200:
|
||||
print("!!!! something went wrong")
|
||||
print(r)
|
||||
print(r.text)
|
||||
|
||||
@classmethod
|
||||
def __share(cls, tenant_id, integration_id, fallback, pretext, title, title_link, text):
|
||||
integration = cls.__get(tenant_id=tenant_id, integration_id=integration_id)
|
||||
if integration is None:
|
||||
return {"errors": ["slack integration not found"]}
|
||||
r = requests.post(
|
||||
url=integration["endpoint"],
|
||||
json={
|
||||
"attachments": [
|
||||
{
|
||||
"fallback": fallback,
|
||||
"pretext": pretext,
|
||||
"title": title,
|
||||
"title_link": title_link,
|
||||
"text": text,
|
||||
"ts": datetime.now().timestamp()
|
||||
}
|
||||
]
|
||||
})
|
||||
return r.text
|
||||
|
||||
@classmethod
|
||||
def share_session(cls, tenant_id, project_id, session_id, user, comment, integration_id=None):
|
||||
args = {"fallback": f"{user} has shared the below session!",
|
||||
"pretext": f"{user} has shared the below session!",
|
||||
"title": f"{config('SITE_URL')}/{project_id}/session/{session_id}",
|
||||
"title_link": f"{config('SITE_URL')}/{project_id}/session/{session_id}",
|
||||
"text": comment}
|
||||
return {"data": cls.__share(tenant_id, integration_id, **args)}
|
||||
|
||||
@classmethod
|
||||
def share_error(cls, tenant_id, project_id, error_id, user, comment, integration_id=None):
|
||||
args = {"fallback": f"{user} has shared the below error!",
|
||||
"pretext": f"{user} has shared the below error!",
|
||||
"title": f"{config('SITE_URL')}/{project_id}/errors/{error_id}",
|
||||
"title_link": f"{config('SITE_URL')}/{project_id}/errors/{error_id}",
|
||||
"text": comment}
|
||||
return {"data": cls.__share(tenant_id, integration_id, **args)}
|
||||
|
||||
@classmethod
|
||||
def __get(cls, tenant_id, integration_id=None):
|
||||
if integration_id is not None:
|
||||
return webhook.get(tenant_id=tenant_id, webhook_id=integration_id)
|
||||
|
||||
integrations = webhook.get_by_type(tenant_id=tenant_id, webhook_type="slack")
|
||||
if integrations is None or len(integrations) == 0:
|
||||
return None
|
||||
return integrations[0]
|
||||
|
|
@ -1,19 +1,20 @@
|
|||
import requests
|
||||
from decouple import config
|
||||
from datetime import datetime
|
||||
|
||||
import schemas
|
||||
from chalicelib.core import webhook
|
||||
from chalicelib.core.collaboration_base import BaseCollaboration
|
||||
|
||||
|
||||
class Slack:
|
||||
class Slack(BaseCollaboration):
|
||||
@classmethod
|
||||
def add_channel(cls, tenant_id, **args):
|
||||
url = args["url"]
|
||||
name = args["name"]
|
||||
if cls.say_hello(url):
|
||||
def add(cls, tenant_id, data: schemas.AddCollaborationSchema):
|
||||
if cls.say_hello(data.url):
|
||||
return webhook.add(tenant_id=tenant_id,
|
||||
endpoint=url,
|
||||
endpoint=data.url,
|
||||
webhook_type="slack",
|
||||
name=name)
|
||||
name=data.name)
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
|
|
@ -34,37 +35,6 @@ class Slack:
|
|||
return False
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def send_text_attachments(cls, tenant_id, webhook_id, text, **args):
|
||||
integration = cls.__get(tenant_id=tenant_id, integration_id=webhook_id)
|
||||
if integration is None:
|
||||
return {"errors": ["slack integration not found"]}
|
||||
try:
|
||||
r = requests.post(
|
||||
url=integration["endpoint"],
|
||||
json={
|
||||
"attachments": [
|
||||
{
|
||||
"text": text,
|
||||
"ts": datetime.now().timestamp(),
|
||||
**args
|
||||
}
|
||||
]
|
||||
},
|
||||
timeout=5)
|
||||
if r.status_code != 200:
|
||||
print(f"!! issue sending slack text attachments; webhookId:{webhook_id} code:{r.status_code}")
|
||||
print(r.text)
|
||||
return None
|
||||
except requests.exceptions.Timeout:
|
||||
print(f"!! Timeout sending slack text attachments webhookId:{webhook_id}")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"!! Issue sending slack text attachments webhookId:{webhook_id}")
|
||||
print(str(e))
|
||||
return None
|
||||
return {"data": r.text}
|
||||
|
||||
@classmethod
|
||||
def send_raw(cls, tenant_id, webhook_id, body):
|
||||
integration = cls.__get(tenant_id=tenant_id, integration_id=webhook_id)
|
||||
|
|
@ -104,7 +74,7 @@ class Slack:
|
|||
print(r.text)
|
||||
|
||||
@classmethod
|
||||
def __share_to_slack(cls, tenant_id, integration_id, fallback, pretext, title, title_link, text):
|
||||
def __share(cls, tenant_id, integration_id, fallback, pretext, title, title_link, text):
|
||||
integration = cls.__get(tenant_id=tenant_id, integration_id=integration_id)
|
||||
if integration is None:
|
||||
return {"errors": ["slack integration not found"]}
|
||||
|
|
@ -131,7 +101,7 @@ class Slack:
|
|||
"title": f"{config('SITE_URL')}/{project_id}/session/{session_id}",
|
||||
"title_link": f"{config('SITE_URL')}/{project_id}/session/{session_id}",
|
||||
"text": comment}
|
||||
return {"data": cls.__share_to_slack(tenant_id, integration_id, **args)}
|
||||
return {"data": cls.__share(tenant_id, integration_id, **args)}
|
||||
|
||||
@classmethod
|
||||
def share_error(cls, tenant_id, project_id, error_id, user, comment, integration_id=None):
|
||||
|
|
@ -140,12 +110,7 @@ class Slack:
|
|||
"title": f"{config('SITE_URL')}/{project_id}/errors/{error_id}",
|
||||
"title_link": f"{config('SITE_URL')}/{project_id}/errors/{error_id}",
|
||||
"text": comment}
|
||||
return {"data": cls.__share_to_slack(tenant_id, integration_id, **args)}
|
||||
|
||||
@classmethod
|
||||
def has_slack(cls, tenant_id):
|
||||
integration = cls.__get(tenant_id=tenant_id)
|
||||
return not (integration is None or len(integration) == 0)
|
||||
return {"data": cls.__share(tenant_id, integration_id, **args)}
|
||||
|
||||
@classmethod
|
||||
def __get(cls, tenant_id, integration_id=None):
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from chalicelib.core import log_tool_rollbar, sourcemaps, events, sessions_assig
|
|||
log_tool_newrelic, announcements, log_tool_bugsnag, weekly_report, integration_jira_cloud, integration_github, \
|
||||
assist, mobile, signup, tenants, boarding, notifications, webhook, users, \
|
||||
custom_metrics, saved_search, integrations_global
|
||||
from chalicelib.core.collaboration_msteams import MSTeams
|
||||
from chalicelib.core.collaboration_slack import Slack
|
||||
from chalicelib.utils import helper, captcha
|
||||
from or_dependencies import OR_context
|
||||
|
|
@ -948,6 +949,32 @@ def get_limits(context: schemas.CurrentContext = Depends(OR_context)):
|
|||
}
|
||||
|
||||
|
||||
@app.post('/integrations/msteams', tags=['integrations'])
|
||||
def add_msteams_integration(data: schemas.AddCollaborationSchema,
|
||||
context: schemas.CurrentContext = Depends(OR_context)):
|
||||
n = MSTeams.add(tenant_id=context.tenant_id, data=data)
|
||||
if n is None:
|
||||
return {
|
||||
"errors": ["We couldn't send you a test message on your Microsoft Teams channel. Please verify your webhook url."]
|
||||
}
|
||||
return {"data": n}
|
||||
|
||||
|
||||
@app.post('/integrations/msteams/{integrationId}', tags=['integrations'])
|
||||
def edit_msteams_integration(integrationId: int, data: schemas.EditCollaborationSchema = Body(...),
|
||||
context: schemas.CurrentContext = Depends(OR_context)):
|
||||
if len(data.url) > 0:
|
||||
old = webhook.get(tenant_id=context.tenant_id, webhook_id=integrationId)
|
||||
if old["endpoint"] != data.url:
|
||||
if not Slack.say_hello(data.url):
|
||||
return {
|
||||
"errors": [
|
||||
"We couldn't send you a test message on your Slack channel. Please verify your webhook url."]
|
||||
}
|
||||
return {"data": webhook.update(tenant_id=context.tenant_id, webhook_id=integrationId,
|
||||
changes={"name": data.name, "endpoint": data.url})}
|
||||
|
||||
|
||||
@public_app.get('/', tags=["health"])
|
||||
@public_app.post('/', tags=["health"])
|
||||
@public_app.put('/', tags=["health"])
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ def get_project(projectId: int, context: schemas.CurrentContext = Depends(OR_con
|
|||
|
||||
@app.post('/integrations/slack', tags=['integrations'])
|
||||
@app.put('/integrations/slack', tags=['integrations'])
|
||||
def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentContext = Depends(OR_context)):
|
||||
n = Slack.add_channel(tenant_id=context.tenant_id, url=data.url, name=data.name)
|
||||
def add_slack_integration(data: schemas.AddCollaborationSchema, context: schemas.CurrentContext = Depends(OR_context)):
|
||||
n = Slack.add(tenant_id=context.tenant_id, data=data)
|
||||
if n is None:
|
||||
return {
|
||||
"errors": ["We couldn't send you a test message on your Slack channel. Please verify your webhook url."]
|
||||
|
|
@ -81,7 +81,7 @@ def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentConte
|
|||
|
||||
|
||||
@app.post('/integrations/slack/{integrationId}', tags=['integrations'])
|
||||
def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = Body(...),
|
||||
def edit_slack_integration(integrationId: int, data: schemas.EditCollaborationSchema = Body(...),
|
||||
context: schemas.CurrentContext = Depends(OR_context)):
|
||||
if len(data.url) > 0:
|
||||
old = webhook.get(tenant_id=context.tenant_id, webhook_id=integrationId)
|
||||
|
|
|
|||
|
|
@ -78,14 +78,13 @@ class CurrentContext(CurrentAPIContext):
|
|||
_transform_email = validator('email', pre=True, allow_reuse=True)(transform_email)
|
||||
|
||||
|
||||
class AddSlackSchema(BaseModel):
|
||||
class AddCollaborationSchema(BaseModel):
|
||||
name: str = Field(...)
|
||||
url: HttpUrl = Field(...)
|
||||
|
||||
|
||||
class EditSlackSchema(BaseModel):
|
||||
class EditCollaborationSchema(AddCollaborationSchema):
|
||||
name: Optional[str] = Field(None)
|
||||
url: HttpUrl = Field(...)
|
||||
|
||||
|
||||
class CreateNotificationSchema(BaseModel):
|
||||
|
|
|
|||
|
|
@ -75,8 +75,8 @@ def get_project(projectId: int, context: schemas.CurrentContext = Depends(OR_con
|
|||
|
||||
@app.post('/integrations/slack', tags=['integrations'])
|
||||
@app.put('/integrations/slack', tags=['integrations'])
|
||||
def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentContext = Depends(OR_context)):
|
||||
n = Slack.add_channel(tenant_id=context.tenant_id, url=data.url, name=data.name)
|
||||
def add_slack_client(data: schemas.AddCollaborationSchema, context: schemas.CurrentContext = Depends(OR_context)):
|
||||
n = Slack.add(tenant_id=context.tenant_id, data=data)
|
||||
if n is None:
|
||||
return {
|
||||
"errors": ["We couldn't send you a test message on your Slack channel. Please verify your webhook url."]
|
||||
|
|
@ -85,7 +85,7 @@ def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentConte
|
|||
|
||||
|
||||
@app.post('/integrations/slack/{integrationId}', tags=['integrations'])
|
||||
def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = Body(...),
|
||||
def edit_slack_integration(integrationId: int, data: schemas.EditCollaborationSchema = Body(...),
|
||||
context: schemas.CurrentContext = Depends(OR_context)):
|
||||
if len(data.url) > 0:
|
||||
old = webhook.get(tenant_id=context.tenant_id, webhook_id=integrationId)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue