@@ -22,6 +22,7 @@ def connect_slack(args, token):
2222 system .print_error (args , f"Failed to connect to Slack with error: { e .response ['error' ]} " )
2323 return None
2424
25+
2526def check_slack_messages (args , client , patterns , profile_name , channel_types , channel_ids = None , limit_mins = 60 , archived_channels = False ):
2627 results = []
2728 try :
@@ -39,12 +40,26 @@ def check_slack_messages(args, client, patterns, profile_name, channel_types, ch
3940 system .print_info (args , f"Current Time: { current_time_readable } " )
4041 system .print_info (args , f"Fetching messages from the last { limit_mins } minutes (Oldest Time: { oldest_time_readable } , Unix: { int (oldest_time )} )" )
4142
43+ # Helper function to handle rate limits
44+ hawk_args = args
45+ def rate_limit_retry (func , * args , ** kwargs ):
46+ while True :
47+ try :
48+ return func (* args , ** kwargs )
49+ except SlackApiError as e :
50+ if e .response ["error" ] == "ratelimited" :
51+ retry_after = int (e .response .headers .get ("Retry-After" , 1 ))
52+ system .print_info (hawk_args , f"Rate limited. Retrying after { retry_after } seconds..." )
53+ time .sleep (retry_after )
54+ else :
55+ raise
56+
4257 # Get all channels of specified types
4358 channels = []
4459
4560 if not channel_ids :
4661 system .print_info (args , "Getting all channels because no channel_ids provided" )
47-
62+
4863 # Pagination logic to fetch all non-archived channels
4964 cursor = None
5065 while True :
@@ -53,17 +68,19 @@ def check_slack_messages(args, client, patterns, profile_name, channel_types, ch
5368 system .print_debug (args , f"Considering archived channels, you may want to set archived_channels to False" )
5469 else :
5570 system .print_debug (args , f"Skipping archived channels, you may want to set archived_channels to True" )
56- response = client .conversations_list (
57- types = channel_types ,
58- limit = 1000 ,
59- cursor = cursor ,
71+
72+ response = rate_limit_retry (
73+ client .conversations_list ,
74+ types = channel_types ,
75+ limit = 1000 ,
76+ cursor = cursor ,
6077 exclude_archived = not archived_channels
6178 )
6279 channels .extend (response .get ("channels" , []))
63-
80+
6481 # Update the cursor for the next batch
6582 cursor = response .get ("response_metadata" , {}).get ("next_cursor" )
66-
83+
6784 if not cursor : # Break the loop if there are no more channels to fetch
6885 break
6986 except SlackApiError as e :
@@ -73,14 +90,11 @@ def check_slack_messages(args, client, patterns, profile_name, channel_types, ch
7390 system .print_info (args , "Getting channels by channel_ids" )
7491 for channel_id in channel_ids :
7592 try :
76- channel = client .conversations_info (channel = channel_id )["channel" ]
77- ## if archived_channels is set to True, include archived channels
93+ channel = rate_limit_retry (client .conversations_info , channel = channel_id )["channel" ]
7894 if archived_channels or not channel .get ("is_archived" ):
79- system .print_debug (args , f"Considering archived channels, you may want to set archived_channels to False" )
8095 channels .append (channel )
8196 else :
8297 system .print_debug (args , f"Skipping archived channel: { channel_id } " )
83-
8498 except SlackApiError as e :
8599 system .print_error (args , f"Failed to fetch channel with id { channel_id } with error: { e .response ['error' ]} " )
86100
@@ -95,7 +109,7 @@ def check_slack_messages(args, client, patterns, profile_name, channel_types, ch
95109
96110 # Get messages from the channel within the time range
97111 system .print_info (args , f"Checking messages in channel { channel_name } ({ channel_id } )" )
98- messages = client .conversations_history ( channel = channel_id , oldest = oldest_time )["messages" ]
112+ messages = rate_limit_retry ( client .conversations_history , channel = channel_id , oldest = oldest_time )["messages" ]
99113 for message in messages :
100114 user = message .get ("user" , "" )
101115 text = message .get ("text" )
@@ -106,7 +120,7 @@ def check_slack_messages(args, client, patterns, profile_name, channel_types, ch
106120 file_addr = download_file (args , client , file , folder_path )
107121 if file_addr :
108122 system .print_debug (args , f"Checking file: { file_addr } " )
109- matches = system .read_match_strings (args , file_addr , 'slack' )
123+ matches = system .read_match_strings (args , file_addr , 'slack' )
110124 if matches :
111125 for match in matches :
112126 results .append ({
@@ -120,7 +134,7 @@ def check_slack_messages(args, client, patterns, profile_name, channel_types, ch
120134 'message_link' : workspace_url + f"/archives/{ channel_id } /p{ message_ts .replace ('.' , '' )} " ,
121135 'data_source' : 'slack'
122136 })
123-
137+
124138 # Check main message for matches
125139 if text :
126140 matches = system .match_strings (args , text )
@@ -140,7 +154,7 @@ def check_slack_messages(args, client, patterns, profile_name, channel_types, ch
140154
141155 if "thread_ts" in message :
142156 thread_ts = message ["thread_ts" ]
143- replies = client .conversations_replies ( channel = channel_id , ts = thread_ts , oldest = oldest_time )["messages" ]
157+ replies = rate_limit_retry ( client .conversations_replies , channel = channel_id , ts = thread_ts , oldest = oldest_time )["messages" ]
144158 for reply in replies :
145159 if reply ["ts" ] != thread_ts : # Skip the parent message
146160 reply_user = reply .get ("user" , "" )
@@ -153,7 +167,7 @@ def check_slack_messages(args, client, patterns, profile_name, channel_types, ch
153167 file_addr = download_file (args , client , file , folder_path )
154168 if file_addr :
155169 system .print_debug (args , f"Checking file: { file_addr } " )
156- matches = system .read_match_strings (args , file_addr , 'slack' )
170+ matches = system .read_match_strings (args , file_addr , 'slack' )
157171 if matches :
158172 for match in matches :
159173 results .append ({
@@ -192,6 +206,7 @@ def check_slack_messages(args, client, patterns, profile_name, channel_types, ch
192206
193207
194208
209+
195210def download_file (args , client , file_info , folder_path ) -> str :
196211 try :
197212 # Ensure the folder exists
0 commit comments