aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--slack/commands.py17
-rw-r--r--slack/error.py41
-rw-r--r--slack/python_compatibility.py4
-rw-r--r--slack/slack_workspace.py35
4 files changed, 73 insertions, 24 deletions
diff --git a/slack/commands.py b/slack/commands.py
index 5e6e40c..69b5952 100644
--- a/slack/commands.py
+++ b/slack/commands.py
@@ -1,5 +1,6 @@
from __future__ import annotations
+import json
import pprint
import re
from dataclasses import dataclass
@@ -8,7 +9,7 @@ from typing import Callable, Dict, List, Optional, Tuple
import weechat
-from slack.error import UncaughtError
+from slack.error import SlackRtmError, UncaughtError
from slack.log import print_error
from slack.python_compatibility import format_exception, removeprefix, removesuffix
from slack.shared import shared
@@ -262,11 +263,19 @@ def command_slack_workspace_del(
)
-def print_uncaught_error(error: UncaughtError, detailed: bool = False):
+def print_uncaught_error(
+ error: UncaughtError, detailed: bool, options: Dict[str, Optional[str]]
+):
weechat.prnt("", f" {error.id} ({error.time}): {error.exception}")
if detailed:
for line in format_exception(error.exception):
weechat.prnt("", f" {line}")
+ data = options.get("data", False) is None
+ if data:
+ if isinstance(error.exception, SlackRtmError):
+ weechat.prnt("", f" data: {json.dumps(error.exception.message_json)}")
+ else:
+ print_error("This error does not have any data")
@weechat_command("tasks|buffer|errors|error", split_all_args=True)
@@ -287,7 +296,7 @@ def command_slack_debug(
num = min(num_arg, len(shared.uncaught_errors))
weechat.prnt("", f"Last {num} errors:")
for error in shared.uncaught_errors[-num:]:
- print_uncaught_error(error)
+ print_uncaught_error(error, False, options)
elif args[0] == "error":
if len(args) > 1:
if args[1].isdecimal() and args[1] != "0":
@@ -311,7 +320,7 @@ def command_slack_debug(
else:
error = shared.uncaught_errors[-1]
weechat.prnt("", "Last error:")
- print_uncaught_error(error, True)
+ print_uncaught_error(error, True, options)
def completion_slack_workspaces_cb(
diff --git a/slack/error.py b/slack/error.py
index 8817759..c978584 100644
--- a/slack/error.py
+++ b/slack/error.py
@@ -5,10 +5,12 @@ from datetime import datetime
from typing import TYPE_CHECKING, Dict, Mapping, Sequence, Union
from uuid import uuid4
+from slack.python_compatibility import format_exception_only
from slack.shared import shared
if TYPE_CHECKING:
from slack_api.slack_common import SlackErrorResponse
+ from slack_rtm.slack_rtm_message import SlackRtmMessage
from slack.slack_workspace import SlackWorkspace
@@ -51,6 +53,22 @@ class SlackApiError(Exception):
self.response = response
+class SlackRtmError(Exception):
+ def __init__(
+ self,
+ workspace: SlackWorkspace,
+ exception: BaseException,
+ message_json: SlackRtmMessage,
+ ):
+ super().__init__(
+ f"{self.__class__.__name__}: workspace={workspace}, exception=`{format_exception_only_str(exception)}`"
+ )
+ super().with_traceback(exception.__traceback__)
+ self.workspace = workspace
+ self.exception = exception
+ self.message_json = message_json
+
+
class SlackError(Exception):
def __init__(self, workspace: SlackWorkspace, error: str):
super().__init__(
@@ -70,22 +88,35 @@ class UncaughtError:
self.time = datetime.now()
+def format_exception_only_str(exc: BaseException) -> str:
+ return format_exception_only(exc)[-1].strip()
+
+
def store_and_format_exception(e: BaseException):
uncaught_error = UncaughtError(e)
shared.uncaught_errors.append(uncaught_error)
- stack_msg = f"(run /slack debug error {uncaught_error.id} for stack trace)"
+ stack_msg_command = f"/slack debug error {uncaught_error.id}"
+ stack_msg = f"run `{stack_msg_command}` for the stack trace"
if isinstance(e, HttpError):
return (
f"Error calling URL {e.url}: return code: {e.return_code}, "
- f"http status code: {e.http_status_code}, error: {e.error} {stack_msg}"
+ f"http status code: {e.http_status_code}, error: {e.error} ({stack_msg})"
)
elif isinstance(e, SlackApiError):
return (
f"Error from Slack API method {e.method} with params {e.params} for workspace "
- f"{e.workspace.name}: {e.response} {stack_msg}"
+ f"{e.workspace.name}: {e.response} ({stack_msg})"
+ )
+ elif isinstance(e, SlackRtmError):
+ return (
+ f"Error while handling Slack event of type '{e.message_json['type']}' for workspace "
+ f"{e.workspace.name}: {format_exception_only_str(e.exception)} ({stack_msg}, "
+ f"run `{stack_msg_command} -data` for the event data)"
)
elif isinstance(e, SlackError):
- return f"Error occurred in workspace {e.workspace.name}: {e.error} {stack_msg}"
+ return (
+ f"Error occurred in workspace {e.workspace.name}: {e.error} ({stack_msg})"
+ )
else:
- return f"Unknown error occurred: {e.__class__.__name__}: {e} {stack_msg}"
+ return f"Unknown error occurred: {format_exception_only_str(e)} ({stack_msg})"
diff --git a/slack/python_compatibility.py b/slack/python_compatibility.py
index e96b8af..8aa8a84 100644
--- a/slack/python_compatibility.py
+++ b/slack/python_compatibility.py
@@ -18,5 +18,9 @@ def removesuffix(self: str, suffix: str) -> str:
return self[:]
+def format_exception_only(exc: BaseException) -> List[str]:
+ return traceback.format_exception_only(type(exc), exc)
+
+
def format_exception(exc: BaseException) -> List[str]:
return traceback.format_exception(type(exc), exc, exc.__traceback__)
diff --git a/slack/slack_workspace.py b/slack/slack_workspace.py
index 638a17b..51e4a89 100644
--- a/slack/slack_workspace.py
+++ b/slack/slack_workspace.py
@@ -15,7 +15,8 @@ from websocket import (
create_connection,
)
-from slack.error import SlackError
+from slack.error import SlackError, SlackRtmError, store_and_format_exception
+from slack.log import print_error
from slack.proxy import Proxy
from slack.shared import shared
from slack.slack_api import SlackApi
@@ -262,21 +263,25 @@ class SlackWorkspace:
run_async(self._ws_recv(json.loads(recv_data.decode())))
async def _ws_recv(self, data: SlackRtmMessage):
- if data["type"] == "message":
- if "subtype" in data and data["subtype"] == "message_changed":
- pass
- elif "subtype" in data and data["subtype"] == "message_deleted":
- pass
- elif "subtype" in data and data["subtype"] == "message_replied":
- pass
+ try:
+ if data["type"] == "message":
+ if "subtype" in data and data["subtype"] == "message_changed":
+ pass
+ elif "subtype" in data and data["subtype"] == "message_deleted":
+ pass
+ elif "subtype" in data and data["subtype"] == "message_replied":
+ pass
+ else:
+ channel_id = data["channel"]
+ if channel_id in self.open_conversations:
+ channel = self.open_conversations[channel_id]
+ message = SlackMessage(channel, data)
+ await channel.add_message(message)
else:
- channel_id = data["channel"]
- if channel_id in self.open_conversations:
- channel = self.open_conversations[channel_id]
- message = SlackMessage(channel, data)
- await channel.add_message(message)
- else:
- weechat.prnt("", f"\t{self.name} received: {json.dumps(data)}")
+ weechat.prnt("", f"\t{self.name} received: {json.dumps(data)}")
+ except Exception as e:
+ slack_error = SlackRtmError(self, e, data)
+ print_error(store_and_format_exception(slack_error))
def ping(self):
if not self.is_connected: