MASSJ77 commited on
Commit
4521a27
Β·
verified Β·
1 Parent(s): 19eca0b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -49
app.py CHANGED
@@ -1,8 +1,10 @@
1
  import cv2
2
  import torch
3
  import requests
 
 
4
  from PIL import Image
5
- from fastapi import FastAPI, Header, HTTPException
6
  from supabase import create_client
7
  from transformers import AutoImageProcessor, AutoModelForImageClassification
8
  import os
@@ -10,16 +12,7 @@ import os
10
  app = FastAPI()
11
 
12
  # ===============================
13
- # ΰ€Έΰ₯ΰ€°ΰ€•ΰ₯ΰ€·ΰ€Ύ (API Key Protection)
14
- # ===============================
15
- API_TOKEN = os.getenv("API_TOKEN")
16
-
17
- def verify_key(x_api_key: str):
18
- if API_TOKEN and x_api_key != API_TOKEN:
19
- raise HTTPException(status_code=403, detail="Unauthorized")
20
-
21
- # ===============================
22
- # Supabase
23
  # ===============================
24
  SUPABASE_URL = os.getenv("SUPABASE_URL")
25
  SUPABASE_KEY = os.getenv("SUPABASE_KEY")
@@ -27,7 +20,7 @@ SUPABASE_KEY = os.getenv("SUPABASE_KEY")
27
  supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
28
 
29
  # ===============================
30
- # Load Model (only once)
31
  # ===============================
32
  model_name = "AdamCodd/vit-base-nsfw-detector"
33
 
@@ -35,7 +28,7 @@ processor = AutoImageProcessor.from_pretrained(model_name)
35
  model = AutoModelForImageClassification.from_pretrained(model_name)
36
 
37
  # ===============================
38
- # Image check
39
  # ===============================
40
  def check_image(url):
41
  try:
@@ -47,11 +40,13 @@ def check_image(url):
47
 
48
  probs = torch.softmax(outputs.logits, dim=1)
49
  return "explicit" if probs[0][1] > 0.5 else "safe"
50
- except:
 
 
51
  return "safe"
52
 
53
  # ===============================
54
- # Video check
55
  # ===============================
56
  def check_video(url, frame_sample_rate=30):
57
  try:
@@ -81,45 +76,92 @@ def check_video(url, frame_sample_rate=30):
81
  cap.release()
82
  return "safe"
83
 
84
- except:
 
85
  return "safe"
86
 
87
  # ===============================
88
- # πŸ”₯ MAIN ENDPOINT (like /recommend/all)
89
  # ===============================
90
- @app.get("/moderate/all")
91
- async def moderate_all(x_api_key: str = Header(None)):
92
-
93
- verify_key(x_api_key)
94
-
95
- results = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
- # Images
98
- img_posts = supabase.table("posts").select("*").execute().data
99
- for post in img_posts:
100
- result = check_image(post["image_url"])
101
-
102
- results.append({
103
- "id": post["id"],
104
- "type": "image",
105
- "url": post["image_url"],
106
- "result": result
107
- })
108
-
109
- # Videos
110
- vid_posts = supabase.table("trendz").select("*").execute().data
111
- for post in vid_posts:
112
- result = check_video(post["video_url"])
113
-
114
- results.append({
115
- "id": post["id"],
116
- "type": "video",
117
- "url": post["video_url"],
118
- "result": result
119
- })
120
 
 
 
 
 
 
121
  return {
122
- "status": "success",
123
- "count": len(results),
124
- "data": results
125
  }
 
1
  import cv2
2
  import torch
3
  import requests
4
+ import threading
5
+ import time
6
  from PIL import Image
7
+ from fastapi import FastAPI
8
  from supabase import create_client
9
  from transformers import AutoImageProcessor, AutoModelForImageClassification
10
  import os
 
12
  app = FastAPI()
13
 
14
  # ===============================
15
+ # πŸ—„ Supabase Setup
 
 
 
 
 
 
 
 
 
16
  # ===============================
17
  SUPABASE_URL = os.getenv("SUPABASE_URL")
18
  SUPABASE_KEY = os.getenv("SUPABASE_KEY")
 
20
  supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
21
 
22
  # ===============================
23
+ # πŸ€– Load NSFW Model (once)
24
  # ===============================
25
  model_name = "AdamCodd/vit-base-nsfw-detector"
26
 
 
28
  model = AutoModelForImageClassification.from_pretrained(model_name)
29
 
30
  # ===============================
31
+ # πŸ–Ό Image Check
32
  # ===============================
33
  def check_image(url):
34
  try:
 
40
 
41
  probs = torch.softmax(outputs.logits, dim=1)
42
  return "explicit" if probs[0][1] > 0.5 else "safe"
43
+
44
+ except Exception as e:
45
+ print("Image error:", e)
46
  return "safe"
47
 
48
  # ===============================
49
+ # πŸŽ₯ Video Check
50
  # ===============================
51
  def check_video(url, frame_sample_rate=30):
52
  try:
 
76
  cap.release()
77
  return "safe"
78
 
79
+ except Exception as e:
80
+ print("Video error:", e)
81
  return "safe"
82
 
83
  # ===============================
84
+ # πŸ” BACKGROUND WORKER (EVERY 5 MIN)
85
  # ===============================
86
+ def moderation_worker():
87
+ while True:
88
+ try:
89
+ print("πŸš€ Running moderation job...")
90
+
91
+ # ===============================
92
+ # πŸ–Ό Process Images (Batch)
93
+ # ===============================
94
+ img_posts = supabase.table("posts") \
95
+ .select("*") \
96
+ .limit(10) \
97
+ .execute().data
98
+
99
+ for post in img_posts:
100
+ existing = supabase.table("content_moderation") \
101
+ .select("id") \
102
+ .eq("post_id", post["id"]) \
103
+ .eq("post_type", "image") \
104
+ .execute()
105
+
106
+ if len(existing.data) == 0:
107
+ result = check_image(post["image_url"])
108
+
109
+ supabase.table("content_moderation").insert({
110
+ "post_id": post["id"],
111
+ "post_type": "image",
112
+ "file_url": post["image_url"],
113
+ "result": result
114
+ }).execute()
115
+
116
+ print(f"βœ… IMAGE {post['id']} β†’ {result}")
117
+
118
+ # ===============================
119
+ # πŸŽ₯ Process Videos (Batch)
120
+ # ===============================
121
+ vid_posts = supabase.table("trendz") \
122
+ .select("*") \
123
+ .limit(5) \
124
+ .execute().data
125
+
126
+ for post in vid_posts:
127
+ existing = supabase.table("content_moderation") \
128
+ .select("id") \
129
+ .eq("post_id", post["id"]) \
130
+ .eq("post_type", "video") \
131
+ .execute()
132
+
133
+ if len(existing.data) == 0:
134
+ result = check_video(post["video_url"])
135
+
136
+ supabase.table("content_moderation").insert({
137
+ "post_id": post["id"],
138
+ "post_type": "video",
139
+ "file_url": post["video_url"],
140
+ "result": result
141
+ }).execute()
142
+
143
+ print(f"πŸŽ₯ VIDEO {post['id']} β†’ {result}")
144
+
145
+ except Exception as e:
146
+ print("❌ Worker error:", e)
147
+
148
+ # ⏱ Run every 5 minutes
149
+ time.sleep(300)
150
 
151
+ # ===============================
152
+ # πŸš€ START WORKER ON STARTUP
153
+ # ===============================
154
+ @app.on_event("startup")
155
+ def start_worker():
156
+ thread = threading.Thread(target=moderation_worker, daemon=True)
157
+ thread.start()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
159
+ # ===============================
160
+ # 🌐 HEALTH CHECK ENDPOINT
161
+ # ===============================
162
+ @app.get("/")
163
+ def health():
164
  return {
165
+ "status": "running",
166
+ "message": "NSFW moderation running every 5 minutes"
 
167
  }