From 5bee21cfa9b5b2aea705137fd4b70250471ed811 Mon Sep 17 00:00:00 2001 From: Ovidiu Pacurar Date: Tue, 12 Aug 2025 10:54:17 +0300 Subject: [PATCH 1/4] Process file share --- slackbot/__init__.py | 2 +- slackbot/base.py | 16 +++++++ slackbot/management/commands/run_bot.py | 57 +++++++++++++++++++++++++ testapp/testapp/slack.py | 13 ++++++ 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/slackbot/__init__.py b/slackbot/__init__.py index ff83e31..bfa88ba 100644 --- a/slackbot/__init__.py +++ b/slackbot/__init__.py @@ -1,6 +1,6 @@ from functools import lru_cache -__version__ = "0.1.7" +__version__ = "0.1.8" @lru_cache diff --git a/slackbot/base.py b/slackbot/base.py index 2c6a72f..b738dc0 100644 --- a/slackbot/base.py +++ b/slackbot/base.py @@ -70,6 +70,22 @@ def handle(self, message, user=None, channel=None, ts=None, raw=None) -> Optiona """ raise NotImplementedError("abstract method") + def process_file(self, files, message, user=None, channel=None, ts=None, raw=None) -> Optional[Union[int, tuple[int, int]]]: + """ + Handle file share events. Override this method to process file uploads. + + :param files: List of file objects from Slack + :param message: Optional text message accompanying the files + :param user: User ID who uploaded the files + :param channel: Channel where files were uploaded + :param ts: Timestamp of the event + :param raw: Raw event data from Slack + + :return: None, self.STOP, self.PROCESSED, or tuple PROCESSED,STOP + """ + # Default implementation falls back to regular message processing + return self.handle(message, user=user, channel=channel, ts=ts, raw=raw) + class NoMatchSlackCommand(Exception): pass diff --git a/slackbot/management/commands/run_bot.py b/slackbot/management/commands/run_bot.py index cae007f..e4b55a3 100644 --- a/slackbot/management/commands/run_bot.py +++ b/slackbot/management/commands/run_bot.py @@ -118,6 +118,61 @@ def handle_message_really(self, **payload): return processed_at_least_one + def handle_file_share(self, **payload): + """ + Handle file share events (when users upload files) + """ + event = payload.get("event") + + channel = event.get("channel") + user = event.get("user") + ts = event.get("event_ts", event.get("ts", "")) + + if not channel: + return False + + # Don't process bot's own file uploads + if user == self.my_id: + return False + + # Get file information + files = event.get("files", []) + message = event.get("text", "") + + # Log the file share event + self.stdout.write(f"File share event: User {user} uploaded {len(files)} file(s) in channel {channel}") + if message: + self.stdout.write(f"Message: {message}") + + # Process files through processors + processed_at_least_one = False + for p in self.processors: + try: + # Call a new method for file processing if it exists + if hasattr(p, 'process_file'): + r = p.process_file(files, message, user=user, channel=channel, ts=ts, raw=event) + if r: + if not isinstance(r, tuple): + r = (r,) + if MessageProcessor.PROCESSED in r: + processed_at_least_one = True + if MessageProcessor.STOP in r: + break + else: + # Fallback to regular message processing for backward compatibility + r = p.process(message, user=user, channel=channel, ts=ts, raw=event) + if r: + if not isinstance(r, tuple): + r = (r,) + if MessageProcessor.PROCESSED in r: + processed_at_least_one = True + if MessageProcessor.STOP in r: + break + except Exception as e: + self.log_exception("Processor failed for file share event: %s %s", files, str(e)) + + return processed_at_least_one + def set_up(self, **payload): data = self.web.auth_test() self.my_id = data.get("user_id") @@ -139,6 +194,8 @@ def process(self, client: SocketModeClient, req: SocketModeRequest): if event["type"] == "message" and event.get("subtype") is None: return self.handle_message(**req.payload) + elif event["type"] == "message" and event.get("subtype") == "file_share": + return self.handle_file_share(**req.payload) def process_reaction(self, client: SocketModeClient, req: SocketModeRequest): if req.type == "events_api": diff --git a/testapp/testapp/slack.py b/testapp/testapp/slack.py index 3d8a35e..31ff863 100644 --- a/testapp/testapp/slack.py +++ b/testapp/testapp/slack.py @@ -35,3 +35,16 @@ def handle(self, message, user=None, channel=None, ts=None, raw=None): else: self.post_message(channel=channel, text=f'Nothing for you to see :no_entry:', thread_ts=ts) return self.PROCESSED + + def process_file(self, files, message, user=None, channel=None, ts=None, raw=None): + """ + Handle file uploads - this will now be called when users upload files! + """ + + # You can now process the files here + for file_info in files: + file_name = file_info.get('name', 'Unknown') + file_type = file_info.get('mimetype', 'Unknown') + file_size = file_info.get('size', 0) + + return self.PROCESSED From 3ca931c18ed5bdf92932a45f38df7ce8aac04e5e Mon Sep 17 00:00:00 2001 From: Ovidiu Pacurar Date: Tue, 12 Aug 2025 11:01:47 +0300 Subject: [PATCH 2/4] reformat with black --- slackbot/base.py | 8 +++++--- slackbot/management/commands/run_bot.py | 14 +++++++------- testapp/testapp/slack.py | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/slackbot/base.py b/slackbot/base.py index b738dc0..6481ee0 100644 --- a/slackbot/base.py +++ b/slackbot/base.py @@ -70,17 +70,19 @@ def handle(self, message, user=None, channel=None, ts=None, raw=None) -> Optiona """ raise NotImplementedError("abstract method") - def process_file(self, files, message, user=None, channel=None, ts=None, raw=None) -> Optional[Union[int, tuple[int, int]]]: + def process_file( + self, files, message, user=None, channel=None, ts=None, raw=None + ) -> Optional[Union[int, tuple[int, int]]]: """ Handle file share events. Override this method to process file uploads. - + :param files: List of file objects from Slack :param message: Optional text message accompanying the files :param user: User ID who uploaded the files :param channel: Channel where files were uploaded :param ts: Timestamp of the event :param raw: Raw event data from Slack - + :return: None, self.STOP, self.PROCESSED, or tuple PROCESSED,STOP """ # Default implementation falls back to regular message processing diff --git a/slackbot/management/commands/run_bot.py b/slackbot/management/commands/run_bot.py index e4b55a3..aff40a5 100644 --- a/slackbot/management/commands/run_bot.py +++ b/slackbot/management/commands/run_bot.py @@ -123,27 +123,27 @@ def handle_file_share(self, **payload): Handle file share events (when users upload files) """ event = payload.get("event") - + channel = event.get("channel") user = event.get("user") ts = event.get("event_ts", event.get("ts", "")) - + if not channel: return False - + # Don't process bot's own file uploads if user == self.my_id: return False - + # Get file information files = event.get("files", []) message = event.get("text", "") - + # Log the file share event self.stdout.write(f"File share event: User {user} uploaded {len(files)} file(s) in channel {channel}") if message: self.stdout.write(f"Message: {message}") - + # Process files through processors processed_at_least_one = False for p in self.processors: @@ -170,7 +170,7 @@ def handle_file_share(self, **payload): break except Exception as e: self.log_exception("Processor failed for file share event: %s %s", files, str(e)) - + return processed_at_least_one def set_up(self, **payload): diff --git a/testapp/testapp/slack.py b/testapp/testapp/slack.py index 31ff863..7b8e0e0 100644 --- a/testapp/testapp/slack.py +++ b/testapp/testapp/slack.py @@ -40,7 +40,7 @@ def process_file(self, files, message, user=None, channel=None, ts=None, raw=Non """ Handle file uploads - this will now be called when users upload files! """ - + # You can now process the files here for file_info in files: file_name = file_info.get('name', 'Unknown') From 710ebf0f8dee4a3765821350feec957d71cabd74 Mon Sep 17 00:00:00 2001 From: Ovidiu Pacurar Date: Tue, 12 Aug 2025 11:11:33 +0300 Subject: [PATCH 3/4] reformat --- slackbot/management/commands/run_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slackbot/management/commands/run_bot.py b/slackbot/management/commands/run_bot.py index aff40a5..b12b189 100644 --- a/slackbot/management/commands/run_bot.py +++ b/slackbot/management/commands/run_bot.py @@ -149,7 +149,7 @@ def handle_file_share(self, **payload): for p in self.processors: try: # Call a new method for file processing if it exists - if hasattr(p, 'process_file'): + if hasattr(p, "process_file"): r = p.process_file(files, message, user=user, channel=channel, ts=ts, raw=event) if r: if not isinstance(r, tuple): From 44899e02192d11c60f36c2fc3252b8f2d43ab973 Mon Sep 17 00:00:00 2001 From: Ovidiu Pacurar Date: Tue, 12 Aug 2025 11:58:22 +0300 Subject: [PATCH 4/4] Reformat --- slackbot/management/commands/run_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slackbot/management/commands/run_bot.py b/slackbot/management/commands/run_bot.py index 1561ce9..54373fa 100644 --- a/slackbot/management/commands/run_bot.py +++ b/slackbot/management/commands/run_bot.py @@ -192,7 +192,7 @@ def process(self, client: SocketModeClient, req: SocketModeRequest): event = req.payload["event"] - if event["type"] == "message" and (event.get("subtype") is None or event.get("subtype") == "file_share") : + if event["type"] == "message" and (event.get("subtype") is None or event.get("subtype") == "file_share"): return self.handle_message(**req.payload) elif event["type"] == "message" and event.get("subtype") == "file_share": return self.handle_file_share(**req.payload)