3030from sentry .integrations .slack .unfurl .handlers import link_handlers , match_link
3131from sentry .integrations .slack .unfurl .types import LinkType , UnfurlableUrl
3232from sentry .integrations .slack .views .link_identity import build_linking_url
33- from sentry .integrations .utils .metrics import IntegrationEventLifecycle
3433from sentry .organizations .services .organization import organization_service
3534
3635from .base import SlackDMEndpoint
@@ -160,82 +159,89 @@ def on_message(self, request: Request, slack_request: SlackDMRequest) -> Respons
160159
161160 return self .respond ()
162161
163- def on_link_shared (
164- self , request : Request , slack_request : SlackDMRequest , lifecycle : IntegrationEventLifecycle
165- ) -> bool :
162+ def on_link_shared (self , request : Request , slack_request : SlackDMRequest ) -> bool :
166163 """Returns true on success"""
167164 matches : MutableMapping [LinkType , list [UnfurlableUrl ]] = defaultdict (list )
168165 links_seen = set ()
169166
170167 data = slack_request .data .get ("event" , {})
171168
169+ ois = integration_service .get_organization_integrations (
170+ integration_id = slack_request .integration .id , limit = 1
171+ )
172+ organization_id = ois [0 ].organization_id if len (ois ) > 0 else None
173+ organization_context = (
174+ organization_service .get_organization_by_id (
175+ id = organization_id ,
176+ user_id = None ,
177+ include_projects = False ,
178+ include_teams = False ,
179+ )
180+ if organization_id
181+ else None
182+ )
183+ organization = organization_context .organization if organization_context else None
184+
172185 logger_params = {
173186 "integration_id" : slack_request .integration .id ,
174187 "team_id" : slack_request .team_id ,
175188 "channel_id" : slack_request .channel_id ,
176189 "user_id" : slack_request .user_id ,
177190 "channel" : slack_request .channel_id ,
191+ "organization_id" : organization_id ,
178192 ** data ,
179193 }
180194
181195 # An unfurl may have multiple links to unfurl
182196 for item in data .get ("links" , []):
183- try :
184- url = item ["url" ]
185- except Exception :
186- _logger .exception ("parse-link-error" , extra = {** logger_params , "url" : url })
187- continue
188-
189- link_type , args = match_link (url )
190-
191- # Link can't be unfurled
192- if link_type is None or args is None :
193- continue
194-
195- ois = integration_service .get_organization_integrations (
196- integration_id = slack_request .integration .id , limit = 1
197- )
198- organization_id = ois [0 ].organization_id if len (ois ) > 0 else None
199- organization_context = (
200- organization_service .get_organization_by_id (
201- id = organization_id , user_id = None , include_projects = False , include_teams = False
202- )
203- if organization_id
204- else None
205- )
206- organization = organization_context .organization if organization_context else None
207- logger_params ["organization_id" ] = organization_id
208-
209- if (
210- organization
211- and link_type == LinkType .DISCOVER
212- and not slack_request .has_identity
213- and features .has ("organizations:discover-basic" , organization , actor = request .user )
214- ):
197+ with MessagingInteractionEvent (
198+ interaction_type = MessagingInteractionType .PROCESS_SHARED_LINK ,
199+ spec = SlackMessagingSpec (),
200+ ).capture () as lifecycle :
215201 try :
216- analytics .record (
217- SlackIntegrationChartUnfurl (
218- organization_id = organization .id ,
219- unfurls_count = 0 ,
220- )
202+ url = item ["url" ]
203+ except Exception :
204+ lifecycle .record_failure ("Failed to parse link" , extra = {** logger_params })
205+ continue
206+
207+ link_type , args = match_link (url )
208+
209+ # Link can't be unfurled
210+ if link_type is None or args is None :
211+ lifecycle .record_halt ("Unfurlable link" , extra = {"url" : url })
212+ continue
213+
214+ if (
215+ organization
216+ and link_type == LinkType .DISCOVER
217+ and not slack_request .has_identity
218+ and features .has (
219+ "organizations:discover-basic" , organization , actor = request .user
221220 )
222- except Exception as e :
223- sentry_sdk .capture_exception (e )
221+ ):
222+ try :
223+ analytics .record (
224+ SlackIntegrationChartUnfurl (
225+ organization_id = organization .id ,
226+ unfurls_count = 0 ,
227+ )
228+ )
229+ except Exception as e :
230+ sentry_sdk .capture_exception (e )
224231
225- self .prompt_link (slack_request )
226- return True
232+ self .prompt_link (slack_request )
233+ lifecycle .record_halt ("Discover link requires identity" , extra = {"url" : url })
234+ return True
227235
228- # Don't unfurl the same thing multiple times
229- seen_marker = hash (orjson .dumps ((link_type , list (args ))).decode ())
230- if seen_marker in links_seen :
231- continue
236+ # Don't unfurl the same thing multiple times
237+ seen_marker = hash (orjson .dumps ((link_type , list (args ))).decode ())
238+ if seen_marker in links_seen :
239+ continue
232240
233- links_seen .add (seen_marker )
234- matches [link_type ].append (UnfurlableUrl (url = url , args = args ))
241+ links_seen .add (seen_marker )
242+ matches [link_type ].append (UnfurlableUrl (url = url , args = args ))
235243
236244 if not matches :
237- lifecycle .add_extras (logger_params )
238- lifecycle .record_failure ("No matches found" )
239245 return False
240246
241247 # Unfurl each link type
@@ -251,8 +257,6 @@ def on_link_shared(
251257 )
252258
253259 if not results :
254- lifecycle .add_extras (logger_params )
255- lifecycle .record_failure ("No unfurls generated" )
256260 return False
257261
258262 # XXX(isabella): we use our message builders to create the blocks for each link to be
@@ -262,21 +266,24 @@ def on_link_shared(
262266 if "text" in link_info :
263267 del link_info ["text" ]
264268
265- payload = {"channel" : data ["channel" ], "ts" : data ["message_ts" ], "unfurls" : results }
266-
267- client = SlackSdkClient (integration_id = slack_request .integration .id )
268- try :
269- client .chat_unfurl (
270- channel = data ["channel" ],
271- ts = data ["message_ts" ],
272- unfurls = payload ["unfurls" ],
273- )
274- except SlackApiError as e :
275- lifecycle .add_extras (logger_params )
276- if options .get ("slack.log-unfurl-payload" , False ):
277- lifecycle .add_extra ("unfurls" , payload ["unfurls" ])
278- lifecycle .record_failure (e )
279- return False
269+ with MessagingInteractionEvent (
270+ interaction_type = MessagingInteractionType .UNFURL_LINK ,
271+ spec = SlackMessagingSpec (),
272+ ).capture () as lifecycle :
273+ payload = {"channel" : data ["channel" ], "ts" : data ["message_ts" ], "unfurls" : results }
274+ client = SlackSdkClient (integration_id = slack_request .integration .id )
275+ try :
276+ client .chat_unfurl (
277+ channel = data ["channel" ],
278+ ts = data ["message_ts" ],
279+ unfurls = payload ["unfurls" ],
280+ )
281+ except SlackApiError as e :
282+ lifecycle .add_extras (logger_params )
283+ if options .get ("slack.log-unfurl-payload" , False ):
284+ lifecycle .add_extra ("unfurls" , payload ["unfurls" ])
285+ lifecycle .record_failure (e )
286+ return False
280287
281288 return True
282289
@@ -291,12 +298,8 @@ def post(self, request: Request) -> Response:
291298 if slack_request .is_challenge ():
292299 return self .on_url_verification (request , slack_request .data )
293300 if slack_request .type == "link_shared" :
294- with MessagingInteractionEvent (
295- interaction_type = MessagingInteractionType .UNFURL_LINK ,
296- spec = SlackMessagingSpec (),
297- ).capture () as lifecycle :
298- if self .on_link_shared (request , slack_request , lifecycle ):
299- return self .respond ()
301+ if self .on_link_shared (request , slack_request ):
302+ return self .respond ()
300303
301304 if slack_request .type == "message" :
302305 if slack_request .is_bot ():
0 commit comments