Source code for library.phases.phases_implementation.dev_ops.slackBot.bot

import os
from dotenv import load_dotenv
from slack_bolt import App
import logging
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError



[docs] class SlackBot: def __init__(self): load_dotenv() self.app = App( token=os.environ["SLACK_BOT_TOKEN"], signing_secret=os.environ["SLACK_SIGNING_SECRET"] )
[docs] def get_channel_id_by_name(self, channel_name): """Finds channel ID from channel name.""" if not channel_name: print("Channel name cannot be empty.") return None # Remove leading '#' if present clean_channel_name = channel_name.lstrip('#') try: # Using cursor-based pagination for potentially many channels cursor = None while True: result = self.app.client.conversations_list( types="public_channel,private_channel", limit=200, # Fetch in batches cursor=cursor ) if not result['ok']: print(f"Error fetching channels: {result['error']}") return None channels = result.get('channels', []) for channel in channels: if channel.get('name') == clean_channel_name: print(f"Found channel '{clean_channel_name}' with ID: {channel['id']}") return channel['id'] cursor = result.get('response_metadata', {}).get('next_cursor') if not cursor: break # No more pages print(f"Channel '{clean_channel_name}' not found.") return None except SlackApiError as e: print(f"Slack API error fetching channels: {e.response['error']}") return None except Exception as e: print(f"Unexpected error fetching channels: {e}", exc_info=True) return None
[docs] def send_message(self, text: str, channel: str): assert channel is not None, "Channel is required" try: resp = self.app.client.chat_postMessage(channel=channel, text=text) print("Message sent:", resp["ts"]) except Exception as e: print("Error sending message:", e)
[docs] def send_file(self, file_path: str, channel: str, title: str = None, initial_comment: str = None): """ Uploads a file to Slack using files_upload_v2 and shares it. """ if not channel: print("Channel name is required to send a file.") return None # Indicate failure if not os.path.isfile(file_path): print(f"File not found: {file_path}") return None # Indicate failure channel_id = self.get_channel_id_by_name(channel) if not channel_id: print(f"Failed to find channel ID for '{channel}'. Cannot send file.") return None # Indicate failure file_name = title or os.path.basename(file_path) try: print(f"Uploading and sharing '{file_name}' to channel {channel_id} using files_upload_v2...") # Use files_upload_v2 for direct upload and sharing response = self.app.client.files_upload_v2( channel=channel_id, file=file_path, filename=file_name, title=file_name, initial_comment=(initial_comment if initial_comment else f"Here's the file: {file_name}") ) file_info = response.get('file') if file_info: print(f"File '{file_name}' (ID: {file_info.get('id', 'N/A')}) successfully uploaded and shared to channel {channel_id}.") return file_info else: print(f"files_upload_v2 succeeded but returned no file info. Response: {response}") return None except SlackApiError as e: print(f"Slack API error during file send (files_upload_v2): {e.response['error']}") print(f"Full error response: {e.response}") return None except Exception as e: print(f"Unexpected error sending file: {e}", exc_info=True) return None