Spaces:
Sleeping
Sleeping
debug3
Browse files
app.py
CHANGED
|
@@ -228,43 +228,29 @@ class SupabaseAsyncInstallationStore(AsyncInstallationStore):
|
|
| 228 |
# Initialize installation store
|
| 229 |
installation_store = SupabaseAsyncInstallationStore(supabase)
|
| 230 |
|
| 231 |
-
# Custom authorize function with token rotation
|
| 232 |
-
async def async_authorize(enterprise_id, team_id, user_id):
|
| 233 |
-
"""Custom authorization with automatic token rotation."""
|
| 234 |
-
logger.info(f"Authorizing request for team: {team_id}")
|
| 235 |
-
|
| 236 |
-
# Try to find installation (will auto-rotate if needed)
|
| 237 |
-
installation = await installation_store.async_find_installation(
|
| 238 |
-
enterprise_id=enterprise_id,
|
| 239 |
-
team_id=team_id,
|
| 240 |
-
user_id=user_id
|
| 241 |
-
)
|
| 242 |
-
|
| 243 |
-
if installation:
|
| 244 |
-
return AuthorizeResult(
|
| 245 |
-
enterprise_id=enterprise_id or installation.enterprise_id,
|
| 246 |
-
team_id=team_id,
|
| 247 |
-
user_id=user_id or installation.user_id,
|
| 248 |
-
bot_token=installation.bot_token,
|
| 249 |
-
bot_user_id=installation.bot_user_id,
|
| 250 |
-
)
|
| 251 |
-
|
| 252 |
-
logger.warning(f"No installation found for team {team_id}")
|
| 253 |
-
return None
|
| 254 |
-
|
| 255 |
# Initialize Bolt Async App with OAuth
|
|
|
|
|
|
|
| 256 |
app = AsyncApp(
|
| 257 |
signing_secret=SLACK_SIGNING_SECRET,
|
| 258 |
installation_store=installation_store,
|
| 259 |
-
authorize
|
| 260 |
oauth_settings=AsyncOAuthSettings(
|
| 261 |
client_id=SLACK_CLIENT_ID,
|
| 262 |
client_secret=SLACK_CLIENT_SECRET,
|
| 263 |
scopes=[
|
| 264 |
-
|
| 265 |
-
"
|
| 266 |
-
"chat:write",
|
| 267 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
],
|
| 269 |
install_path="/slack/install",
|
| 270 |
redirect_uri_path="/slack/oauth_redirect",
|
|
@@ -468,6 +454,39 @@ async def handle_mention(event, say):
|
|
| 468 |
logger.error(f"Error answering query '{user_query}': {e}")
|
| 469 |
await say(f"❌ Error: {str(e)}")
|
| 470 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 471 |
# --- FastAPI Routes ---
|
| 472 |
handler = AsyncSlackRequestHandler(app)
|
| 473 |
|
|
|
|
| 228 |
# Initialize installation store
|
| 229 |
installation_store = SupabaseAsyncInstallationStore(supabase)
|
| 230 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
# Initialize Bolt Async App with OAuth
|
| 232 |
+
# Note: When using oauth_settings, authorization is handled automatically
|
| 233 |
+
# The installation_store's async_find_installation method handles token rotation
|
| 234 |
app = AsyncApp(
|
| 235 |
signing_secret=SLACK_SIGNING_SECRET,
|
| 236 |
installation_store=installation_store,
|
| 237 |
+
# DO NOT use 'authorize' when using 'oauth_settings' - they conflict
|
| 238 |
oauth_settings=AsyncOAuthSettings(
|
| 239 |
client_id=SLACK_CLIENT_ID,
|
| 240 |
client_secret=SLACK_CLIENT_SECRET,
|
| 241 |
scopes=[
|
| 242 |
+
# Core required scopes
|
| 243 |
+
"app_mentions:read", # Listen when bot is @mentioned
|
| 244 |
+
"chat:write", # Send messages as the bot
|
| 245 |
+
"files:read", # Read uploaded files
|
| 246 |
+
"channels:read", # View basic channel info
|
| 247 |
+
# DM support (recommended)
|
| 248 |
+
"im:read", # View DM info
|
| 249 |
+
"im:write", # Send DMs
|
| 250 |
+
"im:history", # Read DM messages
|
| 251 |
+
# Optional: for private channels
|
| 252 |
+
# "groups:read", # View private channel info
|
| 253 |
+
# "channels:history", # Read channel message history
|
| 254 |
],
|
| 255 |
install_path="/slack/install",
|
| 256 |
redirect_uri_path="/slack/oauth_redirect",
|
|
|
|
| 454 |
logger.error(f"Error answering query '{user_query}': {e}")
|
| 455 |
await say(f"❌ Error: {str(e)}")
|
| 456 |
|
| 457 |
+
@app.event("message")
|
| 458 |
+
async def handle_message(event, say):
|
| 459 |
+
"""Handles direct messages to the bot."""
|
| 460 |
+
# Only respond to DMs (not channel messages)
|
| 461 |
+
if event.get("channel_type") == "im":
|
| 462 |
+
text = event.get("text", "").strip()
|
| 463 |
+
|
| 464 |
+
if not text:
|
| 465 |
+
return
|
| 466 |
+
|
| 467 |
+
# Don't respond to bot's own messages
|
| 468 |
+
if event.get("bot_id"):
|
| 469 |
+
return
|
| 470 |
+
|
| 471 |
+
try:
|
| 472 |
+
if await is_table_empty():
|
| 473 |
+
await say("📚 My knowledge base is empty. Please share PDF or DOCX files in a channel where I'm present!")
|
| 474 |
+
return
|
| 475 |
+
|
| 476 |
+
results = await search_documents(text, match_count=5)
|
| 477 |
+
|
| 478 |
+
if not results:
|
| 479 |
+
await say("🔍 I couldn't find relevant information. Try asking about uploaded documents.")
|
| 480 |
+
return
|
| 481 |
+
|
| 482 |
+
context = " ".join([doc["content"] for doc in results])
|
| 483 |
+
answer = await answer_question(text, context)
|
| 484 |
+
|
| 485 |
+
await say(f"💡 **Answer:** {answer}\n\n_Found from {len(results)} document chunks._")
|
| 486 |
+
except Exception as e:
|
| 487 |
+
logger.error(f"Error in DM handler: {e}")
|
| 488 |
+
await say(f"❌ Error: {str(e)}")
|
| 489 |
+
|
| 490 |
# --- FastAPI Routes ---
|
| 491 |
handler = AsyncSlackRequestHandler(app)
|
| 492 |
|