migrated all pawprint work
This commit is contained in:
1
artery/veins/slack/core/__init__.py
Normal file
1
artery/veins/slack/core/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Slack core
|
||||
37
artery/veins/slack/core/auth.py
Normal file
37
artery/veins/slack/core/auth.py
Normal file
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
Slack credentials authentication for Slack vein.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from fastapi import Header, HTTPException
|
||||
from .config import settings
|
||||
|
||||
|
||||
@dataclass
|
||||
class SlackCredentials:
|
||||
token: str
|
||||
|
||||
|
||||
async def get_slack_credentials(
|
||||
x_slack_token: str | None = Header(None),
|
||||
) -> SlackCredentials:
|
||||
"""
|
||||
Dependency that extracts Slack token from headers or falls back to config.
|
||||
|
||||
- Header provided → per-request token (web demo)
|
||||
- No header → use .env token (API/standalone)
|
||||
"""
|
||||
# Use header if provided
|
||||
if x_slack_token and x_slack_token.strip():
|
||||
return SlackCredentials(token=x_slack_token.strip())
|
||||
|
||||
# Fall back to config (prefer bot token, then user token)
|
||||
if settings.slack_bot_token:
|
||||
return SlackCredentials(token=settings.slack_bot_token)
|
||||
if settings.slack_user_token:
|
||||
return SlackCredentials(token=settings.slack_user_token)
|
||||
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail="Missing credentials: provide X-Slack-Token header, or configure in .env",
|
||||
)
|
||||
30
artery/veins/slack/core/client.py
Normal file
30
artery/veins/slack/core/client.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
Slack connection client using slack_sdk.
|
||||
"""
|
||||
|
||||
from slack_sdk import WebClient
|
||||
from slack_sdk.errors import SlackApiError
|
||||
|
||||
|
||||
class SlackClientError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_client(token: str) -> WebClient:
|
||||
"""Create a Slack WebClient with the given token."""
|
||||
return WebClient(token=token)
|
||||
|
||||
|
||||
def test_auth(client: WebClient) -> dict:
|
||||
"""Test authentication and return user/bot info."""
|
||||
try:
|
||||
response = client.auth_test()
|
||||
return {
|
||||
"ok": response["ok"],
|
||||
"user": response.get("user"),
|
||||
"user_id": response.get("user_id"),
|
||||
"team": response.get("team"),
|
||||
"team_id": response.get("team_id"),
|
||||
}
|
||||
except SlackApiError as e:
|
||||
raise SlackClientError(f"Auth failed: {e.response['error']}")
|
||||
22
artery/veins/slack/core/config.py
Normal file
22
artery/veins/slack/core/config.py
Normal file
@@ -0,0 +1,22 @@
|
||||
"""
|
||||
Slack credentials loaded from .env file.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
ENV_FILE = Path(__file__).parent.parent / ".env"
|
||||
|
||||
|
||||
class SlackConfig(BaseSettings):
|
||||
slack_bot_token: str | None = None # xoxb-... Bot token
|
||||
slack_user_token: str | None = None # xoxp-... User token (optional, for user-level actions)
|
||||
api_port: int = 8002
|
||||
|
||||
model_config = {
|
||||
"env_file": ENV_FILE,
|
||||
"env_file_encoding": "utf-8",
|
||||
}
|
||||
|
||||
|
||||
settings = SlackConfig()
|
||||
Reference in New Issue
Block a user