1212 build_app_home ,
1313 build_approval_modal ,
1414 build_generation_modal ,
15+ build_upload_modal ,
1516)
1617
1718logger = structlog .get_logger ()
@@ -57,7 +58,7 @@ async def slack_interactions(request: Request):
5758 raise HTTPException (status_code = 400 , detail = "Missing payload" )
5859
5960 payload = json .loads (str (payload_str ))
60- user_id = payload .get ("user" , {}).get ("id" )
61+ user_id = str ( payload .get ("user" , {}).get ("id" , "" )) # Cast to str for Pylance
6162 interaction_type = payload .get ("type" )
6263
6364 slack_token = (
@@ -66,8 +67,8 @@ async def slack_interactions(request: Request):
6667 headers = {"Authorization" : f"Bearer { slack_token } " }
6768
6869 if interaction_type == "block_actions" :
69- response_url = payload .get ("response_url" )
70- trigger_id = payload .get ("trigger_id" )
70+ response_url = str ( payload .get ("response_url" , "" ) )
71+ trigger_id = str ( payload .get ("trigger_id" , "" ) )
7172 action = payload .get ("actions" , [])[0 ]
7273 action_id = action .get ("action_id" )
7374
@@ -76,12 +77,24 @@ async def slack_interactions(request: Request):
7677 draft_text = raw_draft .replace ("```" , "" ).strip ()
7778 topic = "Медичний пост"
7879
79- if action_id == "action_publish_draft" :
80+ # УСІ перевірки action_id мають бути всередині цього блоку
81+ if action_id == "action_open_upload_modal" :
82+ logger .info ("slack_home_upload_btn_clicked" , user_id = user_id )
83+ modal_view = build_upload_modal ()
84+ async with httpx .AsyncClient () as client :
85+ res = await client .post (
86+ "[https://slack.com/api/views.open](https://slack.com/api/views.open)" ,
87+ headers = headers ,
88+ json = {"trigger_id" : trigger_id , "view" : modal_view },
89+ )
90+ if not res .json ().get ("ok" ):
91+ logger .error ("slack_modal_error" , error = res .json ())
92+
93+ elif action_id == "action_publish_draft" :
8094 logger .info ("slack_draft_approved" , user_id = user_id )
8195 await publish_post_task .kiq (
8296 post_id = "temp_id" , platform = "telegram" , content = draft_text
8397 )
84-
8598 async with httpx .AsyncClient () as client :
8699 await client .post (
87100 response_url ,
@@ -126,9 +139,8 @@ async def slack_interactions(request: Request):
126139 topic = topic , draft = draft_text , platform = "telegram"
127140 )
128141 async with httpx .AsyncClient () as client :
129- # ВИПРАВЛЕНО URL
130142 res = await client .post (
131- "https://slack.com/api/views.open" ,
143+ "[ https://slack.com/api/views.open](https://slack.com/api/views.open) " ,
132144 headers = headers ,
133145 json = {"trigger_id" : trigger_id , "view" : modal_view },
134146 )
@@ -137,12 +149,10 @@ async def slack_interactions(request: Request):
137149
138150 elif action_id == "action_regenerate_draft" :
139151 logger .info ("slack_draft_regenerate" , user_id = user_id )
140- channel_id = payload .get ("channel" , {}).get ("id" ) # ДОДАНО
141-
142- await generate_draft_task .kiq ( # type: ignore[call-overload]
152+ channel_id = str (payload .get ("channel" , {}).get ("id" , "" ))
153+ await generate_draft_task .kiq (
143154 topic = topic , platform = "telegram" , user_id = user_id , channel_id = channel_id
144- )
145-
155+ ) # type: ignore
146156 async with httpx .AsyncClient () as client :
147157 await client .post (
148158 response_url ,
@@ -166,12 +176,13 @@ async def slack_interactions(request: Request):
166176 modal_view = build_generation_modal (channel_id = user_id )
167177 async with httpx .AsyncClient () as client :
168178 res = await client .post (
169- "https://slack.com/api/views.open" ,
179+ "[ https://slack.com/api/views.open](https://slack.com/api/views.open) " ,
170180 headers = headers ,
171181 json = {"trigger_id" : trigger_id , "view" : modal_view },
172182 )
173183 if not res .json ().get ("ok" ):
174184 logger .error ("slack_modal_error" , error = res .json ())
185+
175186 return Response (status_code = 200 )
176187
177188 elif interaction_type == "view_submission" :
@@ -252,7 +263,34 @@ async def slack_interactions(request: Request):
252263 media_type = "application/json" ,
253264 status_code = 200 ,
254265 )
266+ # --- СЦЕНАРІЙ 3: Завантаження гайдлайну ---
267+ elif callback_id == "modal_upload_guideline" :
268+ # Slack повертає масив об'єктів файлів
269+ files = (
270+ state_values .get ("block_file_upload" , {})
271+ .get ("input_file" , {})
272+ .get ("files" , [])
273+ )
274+ if not files :
275+ return Response (status_code = 400 )
276+
277+ file_info = files [0 ]
278+ # file_url = file_info.get("url_private_download")
279+ file_name = file_info .get ("name" )
280+
281+ logger .info ("slack_file_uploaded" , user_id = user_id , file_name = file_name )
282+
283+ # TODO: Тут ми створимо таск `ingest_document_task`, який буде
284+ # скачувати файл за file_url (використовуючи Slack Token),
285+ # парсити PDF/TXT та векторизувати його у Qdrant.
286+ # await ingest_document_task.kiq(file_url=file_url, file_name=file_name)
255287
288+ # Закриваємо модалку
289+ return Response (
290+ content = json .dumps ({"response_action" : "clear" }),
291+ media_type = "application/json" ,
292+ status_code = 200 ,
293+ )
256294 return Response (status_code = 200 )
257295
258296
0 commit comments