oncall-engine/engine/apps/slack/utils.py

108 lines
3.4 KiB
Python
Raw Permalink Normal View History

import datetime
import enum
import typing
from apps.slack.client import SlackClient
from apps.slack.errors import (
SlackAPIChannelArchivedError,
SlackAPIChannelNotFoundError,
SlackAPIInvalidAuthError,
SlackAPITokenError,
)
if typing.TYPE_CHECKING:
from apps.user_management.models import Organization
class SlackDateFormat(enum.StrEnum):
"""
https://api.slack.com/reference/surfaces/formatting#date-formatting
"""
DATE_NUM = "date_num"
"""
Displayed as `2014-02-18`. It will include leading zeros before the month and date and is
probably best for more technical integrations that require a developer-friendly date format.
"""
DATE = "date"
"""
Displayed as `February 18th, 2014`. The year will be omitted if the date is less than six months in the past or future.
"""
DATE_SHORT = "date_short"
"""
Displayed as `Feb 18, 2014`. The year will be omitted if the date is less than six months in the past or future.
"""
DATE_LONG = "date_long"
"""
Displayed as `Tuesday, February 18th, 2014`. The year will be omitted if the date is less than six months in the past or future.
"""
DATE_PRETTY = "date_pretty"
"""
Displays the same as `{date}` but uses "yesterday", "today", or "tomorrow" where appropriate.
"""
DATE_SHORT_PRETTY = "date_short_pretty"
"""
Displays the same as `{date_short}` but uses "yesterday", "today", or "tomorrow" where appropriate.
"""
DATE_LONG_PRETTY = "date_long_pretty"
"""
Displays the same as `{date_long}` but uses "yesterday", "today", or "tomorrow" where appropriate.
"""
TIME = "time"
"""
Displayed as `6:39 AM` or `6:39 PM` in 12-hour format. If the client is set to show 24-hour format, it is displayed as `06:39` or `18:39`.
"""
TIME_SECS = "time_secs"
"""
Displayed as `6:39:45 AM` `6:39:42 PM` in 12-hour format. In 24-hour format it is displayed as `06:39:45` or `18:39:42`.
"""
def post_message_to_channel(organization: "Organization", channel_id: str, text: str) -> None:
if not organization.slack_team_identity:
return
attempt to address some `SlackAPIRatelimitError` exceptions (#3820) # Which issue(s) this PR fixes Closes https://github.com/grafana/oncall-private/issues/2515 Attempts to address some `SlackAPIRatelimitError` exceptions seen in the following tasks: - `apps.slack.tasks.post_slack_rate_limit_message` ([logs](https://ops.grafana-ops.net/explore?schemaVersion=1&panes=%7B%22qhs%22:%7B%22datasource%22:%22000000193%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%23%20%7Bcluster%3D~%5C%22prod-%28us-central-0%7Ceu-west-0%29%5C%22,%20namespace%3D%5C%22amixr-prod%5C%22,%20job%3D~%5C%22amixr-prod%2Famixr-engine-celery-retry%2A%5C%22%7D%5Cn%7Bcluster%3D~%5C%22prod-%28us-central-0%7Ceu-west-0%29%5C%22,%20namespace%3D%5C%22amixr-prod%5C%22%7D%20%7C%3D%20%5C%22apps.slack.tasks.post_slack_rate_limit_message%5C%22%20%7C%3D%20%5C%22retry%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22000000193%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-7d%22,%22to%22:%22now%22%7D%7D%7D&orgId=1)) - `alerts.tasks.notify_user.perform_notification` ([logs](https://ops.grafana-ops.net/explore?schemaVersion=1&panes=%7B%22qhs%22:%7B%22datasource%22:%22000000193%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bcluster%3D~%5C%22prod-%28us-central-0%7Ceu-west-0%29%5C%22,%20namespace%3D%5C%22amixr-prod%5C%22%7D%20%7C%3D%20%5C%22SlackAPIRatelimitError%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22000000193%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-7d%22,%22to%22:%22now%22%7D%7D%7D&orgId=1)) ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [ ] Documentation added (or `pr:no public docs` PR label added if not required) - [ ] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required)
2024-02-01 14:47:12 -05:00
slack_client = SlackClient(organization.slack_team_identity, enable_ratelimit_retry=True)
try:
slack_client.chat_postMessage(channel=channel_id, text=text)
except (
SlackAPITokenError,
SlackAPIInvalidAuthError,
SlackAPIChannelNotFoundError,
SlackAPIChannelArchivedError,
):
pass
def _format_datetime_to_slack(timestamp: float, format: str) -> str:
fallback = datetime.datetime.fromtimestamp(timestamp, datetime.UTC).strftime("%Y-%m-%d %H:%M (UTC)")
return f"<!date^{int(timestamp)}^{format}|{fallback}>"
def format_datetime_to_slack(timestamp: float, format: SlackDateFormat = SlackDateFormat.DATE_SHORT) -> str:
"""
See the docs [here](https://api.slack.com/reference/surfaces/formatting#date-formatting) for
more information
"""
return _format_datetime_to_slack(timestamp, f"{{{format}}}")
def format_datetime_to_slack_with_time(timestamp: float, format: SlackDateFormat = SlackDateFormat.DATE_SHORT) -> str:
"""
See the docs [here](https://api.slack.com/reference/surfaces/formatting#date-formatting) for
more information
"""
return _format_datetime_to_slack(timestamp, f"{{{format}}} {{time}}")
def get_populate_slack_channel_task_id_key(slack_team_identity_id: str) -> str:
return f"SLACK_CHANNELS_TASK_ID_TEAM_{slack_team_identity_id}"