mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-04-29 12:10:24 +00:00
feat: schedule and webhook triggers (#823)
Co-authored-by: Douglas <douglas.ym.lai@gmail.com> Co-authored-by: a7m-1st <ahmed.jimi.awelkair500@gmail.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Tong Chen <web_chentong@163.com>
This commit is contained in:
parent
c8f6f7e63c
commit
4fb2e5db9a
200 changed files with 24538 additions and 2126 deletions
135
server/app/controller/trigger/slack_controller.py
Normal file
135
server/app/controller/trigger/slack_controller.py
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlmodel import Session, select, and_
|
||||
from typing import Optional, List
|
||||
import logging
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.model.config.config import Config
|
||||
from app.type.config_group import ConfigGroup
|
||||
from app.component.auth import Auth, auth_must
|
||||
from app.component.database import session
|
||||
|
||||
logger = logging.getLogger("server_slack_controller")
|
||||
|
||||
|
||||
class SlackChannelOut(BaseModel):
|
||||
"""Output model for Slack channels."""
|
||||
id: str
|
||||
name: str
|
||||
is_private: bool = False
|
||||
is_member: bool = False
|
||||
num_members: Optional[int] = None
|
||||
|
||||
|
||||
class SlackChannelsResponse(BaseModel):
|
||||
"""Response model for Slack channels list."""
|
||||
channels: List[SlackChannelOut]
|
||||
has_credentials: bool
|
||||
|
||||
|
||||
router = APIRouter(prefix="/trigger/slack", tags=["Slack Integration"])
|
||||
|
||||
|
||||
@router.get("/channels", name="get slack channels")
|
||||
def get_slack_channels(
|
||||
session: Session = Depends(session),
|
||||
auth: Auth = Depends(auth_must)
|
||||
) -> SlackChannelsResponse:
|
||||
"""
|
||||
Get list of Slack channels for the authenticated user.
|
||||
|
||||
This endpoint fetches channels from the user's Slack workspace using their
|
||||
stored credentials. Requires SLACK_BOT_TOKEN to be configured in user configs.
|
||||
"""
|
||||
user_id = auth.user.id
|
||||
|
||||
# Get Slack credentials from config
|
||||
configs = session.exec(
|
||||
select(Config).where(
|
||||
and_(
|
||||
Config.user_id == int(user_id),
|
||||
Config.config_group == ConfigGroup.SLACK.value
|
||||
)
|
||||
)
|
||||
).all()
|
||||
|
||||
credentials = {config.config_name: config.config_value for config in configs}
|
||||
bot_token = credentials.get("SLACK_BOT_TOKEN")
|
||||
|
||||
if not bot_token:
|
||||
logger.warning("Slack credentials not found", extra={"user_id": user_id})
|
||||
return SlackChannelsResponse(channels=[], has_credentials=False)
|
||||
|
||||
try:
|
||||
from slack_sdk import WebClient
|
||||
from slack_sdk.errors import SlackApiError
|
||||
|
||||
client = WebClient(token=bot_token)
|
||||
|
||||
# Fetch all channels (public and private the bot has access to)
|
||||
channels = []
|
||||
cursor = None
|
||||
|
||||
while True:
|
||||
response = client.conversations_list(
|
||||
types="public_channel,private_channel",
|
||||
cursor=cursor,
|
||||
limit=200
|
||||
)
|
||||
|
||||
for channel in response.get("channels", []):
|
||||
channels.append(SlackChannelOut(
|
||||
id=channel.get("id"),
|
||||
name=channel.get("name"),
|
||||
is_private=channel.get("is_private", False),
|
||||
is_member=channel.get("is_member", False),
|
||||
num_members=channel.get("num_members")
|
||||
))
|
||||
|
||||
# Check for pagination
|
||||
cursor = response.get("response_metadata", {}).get("next_cursor")
|
||||
if not cursor:
|
||||
break
|
||||
|
||||
logger.info("Slack channels fetched", extra={
|
||||
"user_id": user_id,
|
||||
"channel_count": len(channels)
|
||||
})
|
||||
|
||||
return SlackChannelsResponse(channels=channels, has_credentials=True)
|
||||
|
||||
except ImportError:
|
||||
logger.error("slack_sdk not installed")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Slack SDK not installed on server"
|
||||
)
|
||||
except SlackApiError as e:
|
||||
logger.error("Slack API error", extra={
|
||||
"user_id": user_id,
|
||||
"error": str(e)
|
||||
})
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Slack API error: {e.response.get('error', 'Unknown error')}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("Error fetching Slack channels", extra={
|
||||
"user_id": user_id,
|
||||
"error": str(e)
|
||||
}, exc_info=True)
|
||||
raise HTTPException(status_code=500, detail="Failed to fetch Slack channels")
|
||||
Loading…
Add table
Add a link
Reference in a new issue