File size: 4,012 Bytes
d1ddfcd
 
74f2127
 
a5b6885
 
 
 
 
d1ddfcd
d026616
74f2127
 
d026616
 
 
 
 
 
74f2127
 
 
a5b6885
74f2127
 
 
 
 
 
a5b6885
74f2127
a5b6885
d1ddfcd
d026616
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d1ddfcd
 
 
 
a5b6885
2841ec3
2c85894
d026616
a5b6885
d1ddfcd
a5b6885
d1ddfcd
a5b6885
d026616
 
a5b6885
d026616
 
 
 
 
 
a5b6885
d026616
 
a5b6885
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
from fastapi import FastAPI, Request, Response
import os
import requests
import json
import logging

# Set up logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Configurations
SLACK_WEBHOOK_URL = os.environ.get("SLACK_WEBHOOK_URL")

MODEL_CATALOG_WEBHOOK = os.environ.get("MODEL_CATALOG_WEBHOOK")
MODEL_CATALOG_WEBHOOK_SECRET = os.environ.get("MODEL_CATALOG_WEBHOOK_SECRET")

SIMSHIP_WEBHOOK = os.environ.get("SIMSHIP_WEBHOOK")
SIMSHIP_WEBHOOK_SECRET = os.environ.get("SIMSHIP_WEBHOOK_SECRET")

def send_slack_message(message: str):
    """Send a message to Slack using webhook URL"""
    if not SLACK_WEBHOOK_URL:
        logger.warning(f"No Slack webhook URL configured. Message: {message}")
        return
    
    payload = {"text": message}
    try:
        response = requests.post(SLACK_WEBHOOK_URL, json=payload)
        response.raise_for_status()
        logger.info(f"Slack message sent successfully: {message}")
    except requests.exceptions.RequestException as e:
        logger.error(f"Failed to send Slack message: {e}")

def process_model_catalog_webhook(data: dict):
    """
    Process model catalog webhook
    """

    event = data.get("event", {})
    repo = data.get("repo", {})
    movedTo = data.get("movedTo", {})
    
    # repo name changed
    if (
        repo.get("type") == "model" and
        event.get("scope") == "repo" and
        event.get("action") == "move"
    ):
        message = f"πŸ”„ Model in the catalog renamed: {repo.get('name', '')} β†’ https://hf.co/{movedTo.get('name', '')}"
        send_slack_message(message)

    # repo deleted
    elif (
        repo.get("type") == "model" and
        event.get("scope") == "repo" and
        event.get("action") == "delete"
    ):
        message = f"πŸ—‘οΈ Model in the catalog deleted: https://hf.co/{repo.get('name', '')}"
        send_slack_message(message)

    # other events
    else:
        pass

def process_simship_webhook(data: dict):
    """
    Process simship webhook
    """
    event = data.get("event", {})
    repo = data.get("repo", {})
    updatedConfig = data.get("updatedConfig", {})
    
    # repo creation
    if (
        repo.get("type") == "model" and
        event.get("scope") == "repo" and
        event.get("action") == "create"
    ):
        message = f"πŸ†• SimShip Model created: https://hf.co/{repo.get('name', '')}"
        send_slack_message(message)

    # repo visibility update
    elif (
        repo.get("type") == "model" and
        event.get("scope") == "repo.config" and
        event.get("action") == "update" and
        updatedConfig.get("private") is False
    ):
        message = f"πŸ†• SimShip Model made public: https://hf.co/{repo.get('name', '')}"
        send_slack_message(message)

    # other events
    else:
        pass


app = FastAPI()

@app.post("/webhook")
async def webhook(request: Request):
    logger.info(f"Received webhook request from {request.client.host}")
    logger.info(f"{MODEL_CATALOG_WEBHOOK_SECRET}")
    logger.info(f"{request.headers.get('X-Webhook-Secret')}")
    if request.headers.get("X-Webhook-Secret") not in {MODEL_CATALOG_WEBHOOK_SECRET, SIMSHIP_WEBHOOK_SECRET}:
        logger.warning("Invalid webhook secret received")
        return Response("Invalid secret", status_code=401)
    
    data = await request.json()
    logger.info(f"Webhook payload: {json.dumps(data, indent=2)}")

    webhook_id = data.get("webhook", {}).get("id", None)
    
    if webhook_id == MODEL_CATALOG_WEBHOOK:
        logger.info("Processing model catalog webhook")
        process_model_catalog_webhook(data)
    elif webhook_id == SIMSHIP_WEBHOOK:
        logger.info("Processing simship webhook")
        process_simship_webhook(data)
    else:
        logger.warning("Invalid webhook ID received")
        return Response("Invalid webhook ID", status_code=401)
    
    return Response("Webhook notification received and processed!", status_code=200)