Rolaficus commited on
Commit
79eb0b7
·
verified ·
1 Parent(s): 4c5a5e4

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +40 -83
main.py CHANGED
@@ -1,25 +1,16 @@
1
  from fastapi import FastAPI, Request, Header, HTTPException
2
  from pydantic import BaseModel
3
- from typing import Optional, Any, Dict, List
4
- import httpx
5
  import os
6
- import socket
7
- from urllib.parse import urlparse
8
 
9
  app = FastAPI()
10
 
11
- # --- Configuration & Cleaning ---
12
- def get_clean_env(key):
13
- val = os.environ.get(key)
14
- if val:
15
- # Remove whitespace, single quotes, and double quotes
16
- return val.strip().strip("'").strip('"')
17
- return None
18
 
19
- DISCORD_WEBHOOK_URL = get_clean_env("DISCORD_WEBHOOK_URL")
20
- WEBHOOK_SECRET = get_clean_env("WEBHOOK_SECRET")
21
-
22
- # --- Pydantic Models ---
23
  class HFRepo(BaseModel):
24
  type: str
25
  name: str
@@ -37,114 +28,80 @@ class HFPayload(BaseModel):
37
  comment: Optional[Dict[str, Any]] = None
38
  webhook: Optional[Dict[str, Any]] = None
39
 
40
- @app.on_event("startup")
41
- async def startup_event():
42
- print("--- STARTUP DIAGNOSTICS ---")
43
- # 1. Check if Variable Exists
44
- if DISCORD_WEBHOOK_URL:
45
- # Mask the URL for safety in logs
46
- masked = DISCORD_WEBHOOK_URL[:8] + "..." + DISCORD_WEBHOOK_URL[-4:]
47
- print(f"INFO: Webhook URL loaded: {masked}")
48
-
49
- # 2. Extract Hostname
50
- try:
51
- parsed = urlparse(DISCORD_WEBHOOK_URL)
52
- hostname = parsed.hostname
53
- if not hostname:
54
- print("ERROR: Could not extract hostname from URL. Is the format 'https://...'?")
55
- else:
56
- print(f"DEBUG: Hostname extracted: '{hostname}'")
57
-
58
- # 3. Test DNS Resolution (The "Network Doctor")
59
- try:
60
- # Note: socket.gethostbyname is blocking, but okay for a quick startup check
61
- ip = socket.gethostbyname(hostname)
62
- print(f"SUCCESS: DNS resolved {hostname} to {ip}")
63
- except socket.gaierror as e:
64
- print(f"CRITICAL FAILURE: Could not resolve {hostname}. Error: {e}")
65
- print("-> This means the URL is wrong OR the container has no internet access.")
66
- except Exception as e:
67
- print(f"ERROR parsing URL: {e}")
68
- else:
69
- print("WARNING: No DISCORD_WEBHOOK_URL found. Discord messages will not be sent.")
70
- print("---------------------------")
71
-
72
  @app.get("/")
73
  def home():
74
  return {"status": "Webhook listener is running"}
75
 
76
  @app.post("/webhook")
77
- async def handle_webhook(
78
  payload: HFPayload,
79
  x_webhook_secret: Optional[str] = Header(None)
80
  ):
81
  # 1. Security Check
82
- if WEBHOOK_SECRET and x_webhook_secret != WEBHOOK_SECRET:
83
- print(f"Unauthorized access attempt. Header: {x_webhook_secret}")
84
- raise HTTPException(status_code=401, detail="Invalid Secret")
 
85
 
86
- # 2. Format for Discord
87
  embed = build_discord_embed(payload)
88
 
89
  # 3. Send to Discord
90
  if DISCORD_WEBHOOK_URL:
91
- print(f"Sending notification for {payload.repo.name}...")
 
 
92
  try:
93
- # Added a timeout to prevent hanging
94
- async with httpx.AsyncClient(timeout=10.0) as client:
95
- resp = await client.post(
96
- DISCORD_WEBHOOK_URL,
97
- json={"embeds": [embed]}
98
- )
99
- resp.raise_for_status()
100
- print(f"Sent to Discord: {resp.status_code}")
101
- except httpx.ConnectError as e:
102
- print(f"CONNECTION ERROR: Could not connect to Discord. Check DNS/Network. Details: {e}")
103
- return {"message": "Connection Failed", "error": str(e)}
104
  except Exception as e:
105
- print(f"ERROR connecting to Discord: {e}")
106
  return {"message": "Error sending to Discord", "error": str(e)}
107
 
108
  return {"message": "Processed"}
109
 
110
  def build_discord_embed(data: HFPayload):
 
111
  repo_name = data.repo.name
112
  repo_url = data.repo.url.get('web', '')
113
  event_scope = data.event.scope
114
  event_action = data.event.action
115
 
116
- # Default Color (Grey)
117
- color = 0x95a5a6
 
 
 
 
118
  title = f"Update on {repo_name}"
119
- description = f"**Action:** {event_action}\n**Scope:** {event_scope}"
120
 
121
- # Customize based on event type
122
- if event_scope.startswith("repo.content"):
123
- # Code/Model update (Blue)
124
- color = 0x3498db
125
  title = f"New Commit to {repo_name}"
126
- description = "Model/Dataset files have been updated."
127
 
128
- elif event_scope.startswith("discussion"):
129
- # Discussion/PR (Green)
130
- color = 0x2ecc71
131
- disc_title = data.discussion.get('title', 'No Title') if data.discussion else "Unknown"
132
- title = f"Discussion Update: {disc_title}"
133
 
134
  if data.comment:
135
  content = data.comment.get('content', '')
136
  if len(content) > 200:
137
  content = content[:200] + "..."
138
- description = f"**New Comment** on {repo_name}:\n> {content}"
139
  else:
140
- description = f"Discussion status: **{event_action}**"
141
 
142
  return {
143
  "title": title,
144
  "description": description,
145
  "url": repo_url,
146
  "color": color,
147
- "footer": {
148
- "text": "Hugging Face Webhook"
149
- }
150
  }
 
1
  from fastapi import FastAPI, Request, Header, HTTPException
2
  from pydantic import BaseModel
3
+ from typing import Optional, Any, Dict
4
+ import requests
5
  import os
 
 
6
 
7
  app = FastAPI()
8
 
9
+ # --- Configuration ---
10
+ DISCORD_WEBHOOK_URL = os.environ.get("DISCORD_WEBHOOK_URL")
11
+ WEBHOOK_SECRET = os.environ.get("WEBHOOK_SECRET")
 
 
 
 
12
 
13
+ # --- Models ---
 
 
 
14
  class HFRepo(BaseModel):
15
  type: str
16
  name: str
 
28
  comment: Optional[Dict[str, Any]] = None
29
  webhook: Optional[Dict[str, Any]] = None
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  @app.get("/")
32
  def home():
33
  return {"status": "Webhook listener is running"}
34
 
35
  @app.post("/webhook")
36
+ def handle_webhook(
37
  payload: HFPayload,
38
  x_webhook_secret: Optional[str] = Header(None)
39
  ):
40
  # 1. Security Check
41
+ if WEBHOOK_SECRET:
42
+ if not x_webhook_secret or x_webhook_secret.strip() != WEBHOOK_SECRET.strip():
43
+ print("Auth Failed")
44
+ raise HTTPException(status_code=401, detail="Invalid Secret")
45
 
46
+ # 2. Build Embed
47
  embed = build_discord_embed(payload)
48
 
49
  # 3. Send to Discord
50
  if DISCORD_WEBHOOK_URL:
51
+ # Clean the URL just in case
52
+ url = DISCORD_WEBHOOK_URL.strip().strip("'").strip('"')
53
+
54
  try:
55
+ print(f"Sending to Discord: {payload.repo.name} -> {payload.event.action}")
56
+ # requests is synchronous and handles DNS/Proxies much better in containers
57
+ resp = requests.post(url, json={"embeds": [embed]}, timeout=10)
58
+ resp.raise_for_status()
59
+ print("Success: Message sent.")
 
 
 
 
 
 
60
  except Exception as e:
61
+ print(f"Error sending to Discord: {e}")
62
  return {"message": "Error sending to Discord", "error": str(e)}
63
 
64
  return {"message": "Processed"}
65
 
66
  def build_discord_embed(data: HFPayload):
67
+ # Basic data extraction
68
  repo_name = data.repo.name
69
  repo_url = data.repo.url.get('web', '')
70
  event_scope = data.event.scope
71
  event_action = data.event.action
72
 
73
+ # Colors
74
+ COLOR_BLUE = 0x3498db
75
+ COLOR_GREEN = 0x2ecc71
76
+ COLOR_GREY = 0x95a5a6
77
+
78
+ color = COLOR_GREY
79
  title = f"Update on {repo_name}"
80
+ description = f"Action: {event_action}\nScope: {event_scope}"
81
 
82
+ # Smart Formatting
83
+ if "repo.content" in event_scope:
84
+ color = COLOR_BLUE
 
85
  title = f"New Commit to {repo_name}"
86
+ description = f"The repository content has been updated.\n[View Changes]({repo_url})"
87
 
88
+ elif "discussion" in event_scope:
89
+ color = COLOR_GREEN
90
+ disc_title = data.discussion.get('title', 'Discussion') if data.discussion else "Discussion"
91
+ title = f"Discussion: {disc_title}"
 
92
 
93
  if data.comment:
94
  content = data.comment.get('content', '')
95
  if len(content) > 200:
96
  content = content[:200] + "..."
97
+ description = f"**New Comment:**\n{content}\n\n[View Discussion]({repo_url})"
98
  else:
99
+ description = f"Discussion status updated: **{event_action}**"
100
 
101
  return {
102
  "title": title,
103
  "description": description,
104
  "url": repo_url,
105
  "color": color,
106
+ "footer": {"text": "Hugging Face Webhooks"}
 
 
107
  }