Update app.py
Browse files
app.py
CHANGED
|
@@ -15,7 +15,7 @@ SCRATCH_API_BASE = "https://scratch.mit.edu"
|
|
| 15 |
CLOUD_DATA_URL = f"{SCRATCH_API_BASE}/projects/{PROJECT_ID}/cloud_data"
|
| 16 |
CLOUD_VAR_URL = f"{SCRATCH_API_BASE}/cloud/variable"
|
| 17 |
|
| 18 |
-
# ==================== FULL PROXY LIST
|
| 19 |
PROXY_LIST = [
|
| 20 |
"http://8.219.97.248:80",
|
| 21 |
"http://38.158.83.233:999",
|
|
@@ -155,91 +155,106 @@ proxy_rotator = ProxyRotator(PROXY_LIST)
|
|
| 155 |
|
| 156 |
# ==================== AI CALL WITH PROXY ROTATION ====================
|
| 157 |
def call_ai(prompt):
|
|
|
|
| 158 |
for attempt in range(len(PROXY_LIST)):
|
| 159 |
proxy = proxy_rotator.get_next_proxy()
|
|
|
|
|
|
|
| 160 |
try:
|
| 161 |
response = requests.post(AI_URL, json={"prompt": prompt}, proxies=proxy, timeout=30)
|
| 162 |
if response.status_code == 200:
|
| 163 |
-
|
|
|
|
|
|
|
| 164 |
else:
|
|
|
|
| 165 |
proxy_rotator.mark_proxy_failed(proxy)
|
| 166 |
except Exception as e:
|
|
|
|
| 167 |
proxy_rotator.mark_proxy_failed(proxy)
|
|
|
|
| 168 |
try:
|
| 169 |
response = requests.post(AI_URL, json={"prompt": prompt}, timeout=30)
|
| 170 |
if response.status_code == 200:
|
| 171 |
return response.json().get("response", "Sorry, no response.")
|
| 172 |
-
except:
|
| 173 |
-
|
| 174 |
return "Error: Could not reach AI service."
|
| 175 |
|
| 176 |
-
# ==================== SCRATCH CLOUD VARIABLE FUNCTIONS
|
| 177 |
def get_cloud_variable(variable_name):
|
| 178 |
-
"""Fetch all cloud variables and return the value of the named variable."""
|
| 179 |
cookies = {"scratchsessionid": SCRATCH_SESSION_ID}
|
|
|
|
| 180 |
try:
|
| 181 |
resp = requests.get(CLOUD_DATA_URL, cookies=cookies, timeout=10)
|
|
|
|
| 182 |
if resp.status_code == 200:
|
| 183 |
data = resp.json()
|
|
|
|
| 184 |
return data.get(variable_name, "0")
|
| 185 |
else:
|
| 186 |
-
print(f"[HTTP]
|
| 187 |
return None
|
| 188 |
except Exception as e:
|
| 189 |
-
print(f"[HTTP]
|
| 190 |
return None
|
| 191 |
|
| 192 |
def set_cloud_variable(variable_name, value):
|
| 193 |
-
"""Set a cloud variable via Scratch's HTTP API."""
|
| 194 |
cookies = {"scratchsessionid": SCRATCH_SESSION_ID}
|
| 195 |
-
payload = {
|
| 196 |
-
|
| 197 |
-
"value": value,
|
| 198 |
-
"project_id": PROJECT_ID
|
| 199 |
-
}
|
| 200 |
try:
|
| 201 |
resp = requests.put(CLOUD_VAR_URL, json=payload, cookies=cookies, timeout=10)
|
|
|
|
| 202 |
if resp.status_code == 200:
|
| 203 |
return True
|
| 204 |
else:
|
| 205 |
-
print(f"[HTTP]
|
| 206 |
return False
|
| 207 |
except Exception as e:
|
| 208 |
-
print(f"[HTTP]
|
| 209 |
return False
|
| 210 |
|
| 211 |
# ==================== BRIDGE WORKER ====================
|
| 212 |
def bridge_worker():
|
| 213 |
-
print("[BRIDGE] Starting HTTP-only bridge...")
|
| 214 |
print(f"[BRIDGE] Project ID: {PROJECT_ID}")
|
| 215 |
-
|
| 216 |
if not SCRATCH_SESSION_ID:
|
| 217 |
print("[BRIDGE] ERROR: SCRATCH_SESSION_ID environment variable not set.")
|
| 218 |
return
|
|
|
|
| 219 |
|
| 220 |
last_prompt = "0"
|
| 221 |
while True:
|
| 222 |
try:
|
|
|
|
| 223 |
current = get_cloud_variable("prompt")
|
| 224 |
if current is None:
|
|
|
|
| 225 |
time.sleep(2)
|
| 226 |
continue
|
|
|
|
| 227 |
if current != last_prompt and current != "0":
|
| 228 |
-
print(f"[BRIDGE] New prompt: {current}")
|
| 229 |
decoded = decode_text(current)
|
| 230 |
print(f"[BRIDGE] Decoded: {decoded}")
|
| 231 |
ai_response = call_ai(decoded)
|
| 232 |
print(f"[BRIDGE] AI response: {ai_response[:100]}...")
|
| 233 |
encoded_response = encode_text(ai_response)
|
|
|
|
| 234 |
success = set_cloud_variable("response", encoded_response)
|
| 235 |
if success:
|
| 236 |
print("[BRIDGE] Response sent to Scratch")
|
| 237 |
else:
|
| 238 |
print("[BRIDGE] Failed to send response")
|
| 239 |
last_prompt = current
|
|
|
|
|
|
|
| 240 |
time.sleep(2)
|
| 241 |
except Exception as e:
|
| 242 |
-
print(f"[BRIDGE]
|
|
|
|
|
|
|
| 243 |
time.sleep(5)
|
| 244 |
|
| 245 |
# ==================== FLASK APP ====================
|
|
@@ -247,7 +262,7 @@ app = Flask(__name__)
|
|
| 247 |
|
| 248 |
@app.route('/')
|
| 249 |
def health():
|
| 250 |
-
return "Scratch AI Bridge is running with
|
| 251 |
|
| 252 |
if __name__ == '__main__':
|
| 253 |
print("[MAIN] Starting bridge thread...")
|
|
|
|
| 15 |
CLOUD_DATA_URL = f"{SCRATCH_API_BASE}/projects/{PROJECT_ID}/cloud_data"
|
| 16 |
CLOUD_VAR_URL = f"{SCRATCH_API_BASE}/cloud/variable"
|
| 17 |
|
| 18 |
+
# ==================== FULL PROXY LIST ====================
|
| 19 |
PROXY_LIST = [
|
| 20 |
"http://8.219.97.248:80",
|
| 21 |
"http://38.158.83.233:999",
|
|
|
|
| 155 |
|
| 156 |
# ==================== AI CALL WITH PROXY ROTATION ====================
|
| 157 |
def call_ai(prompt):
|
| 158 |
+
print(f"[AI] Calling AI with prompt: {prompt[:50]}...")
|
| 159 |
for attempt in range(len(PROXY_LIST)):
|
| 160 |
proxy = proxy_rotator.get_next_proxy()
|
| 161 |
+
proxy_url = proxy.get("http", "")
|
| 162 |
+
print(f"[AI] Attempt {attempt+1} using proxy {proxy_url}")
|
| 163 |
try:
|
| 164 |
response = requests.post(AI_URL, json={"prompt": prompt}, proxies=proxy, timeout=30)
|
| 165 |
if response.status_code == 200:
|
| 166 |
+
result = response.json().get("response", "Sorry, no response.")
|
| 167 |
+
print(f"[AI] Success, response length {len(result)}")
|
| 168 |
+
return result
|
| 169 |
else:
|
| 170 |
+
print(f"[AI] Proxy {proxy_url} returned {response.status_code}")
|
| 171 |
proxy_rotator.mark_proxy_failed(proxy)
|
| 172 |
except Exception as e:
|
| 173 |
+
print(f"[AI] Proxy {proxy_url} error: {e}")
|
| 174 |
proxy_rotator.mark_proxy_failed(proxy)
|
| 175 |
+
print("[AI] All proxies failed, trying direct...")
|
| 176 |
try:
|
| 177 |
response = requests.post(AI_URL, json={"prompt": prompt}, timeout=30)
|
| 178 |
if response.status_code == 200:
|
| 179 |
return response.json().get("response", "Sorry, no response.")
|
| 180 |
+
except Exception as e:
|
| 181 |
+
print(f"[AI] Direct call error: {e}")
|
| 182 |
return "Error: Could not reach AI service."
|
| 183 |
|
| 184 |
+
# ==================== SCRATCH CLOUD VARIABLE FUNCTIONS ====================
|
| 185 |
def get_cloud_variable(variable_name):
|
|
|
|
| 186 |
cookies = {"scratchsessionid": SCRATCH_SESSION_ID}
|
| 187 |
+
print(f"[HTTP] Fetching cloud variable '{variable_name}'...")
|
| 188 |
try:
|
| 189 |
resp = requests.get(CLOUD_DATA_URL, cookies=cookies, timeout=10)
|
| 190 |
+
print(f"[HTTP] GET {CLOUD_DATA_URL} -> status {resp.status_code}")
|
| 191 |
if resp.status_code == 200:
|
| 192 |
data = resp.json()
|
| 193 |
+
print(f"[HTTP] Cloud data received: {data}")
|
| 194 |
return data.get(variable_name, "0")
|
| 195 |
else:
|
| 196 |
+
print(f"[HTTP] Failed: {resp.status_code} - {resp.text[:200]}")
|
| 197 |
return None
|
| 198 |
except Exception as e:
|
| 199 |
+
print(f"[HTTP] Exception: {e}")
|
| 200 |
return None
|
| 201 |
|
| 202 |
def set_cloud_variable(variable_name, value):
|
|
|
|
| 203 |
cookies = {"scratchsessionid": SCRATCH_SESSION_ID}
|
| 204 |
+
payload = {"name": variable_name, "value": value, "project_id": PROJECT_ID}
|
| 205 |
+
print(f"[HTTP] Setting cloud variable '{variable_name}' to '{value[:50]}...'")
|
|
|
|
|
|
|
|
|
|
| 206 |
try:
|
| 207 |
resp = requests.put(CLOUD_VAR_URL, json=payload, cookies=cookies, timeout=10)
|
| 208 |
+
print(f"[HTTP] PUT {CLOUD_VAR_URL} -> status {resp.status_code}")
|
| 209 |
if resp.status_code == 200:
|
| 210 |
return True
|
| 211 |
else:
|
| 212 |
+
print(f"[HTTP] Failed to set: {resp.status_code} - {resp.text[:200]}")
|
| 213 |
return False
|
| 214 |
except Exception as e:
|
| 215 |
+
print(f"[HTTP] Exception: {e}")
|
| 216 |
return False
|
| 217 |
|
| 218 |
# ==================== BRIDGE WORKER ====================
|
| 219 |
def bridge_worker():
|
| 220 |
+
print("[BRIDGE] Starting HTTP-only bridge with verbose logging...")
|
| 221 |
print(f"[BRIDGE] Project ID: {PROJECT_ID}")
|
|
|
|
| 222 |
if not SCRATCH_SESSION_ID:
|
| 223 |
print("[BRIDGE] ERROR: SCRATCH_SESSION_ID environment variable not set.")
|
| 224 |
return
|
| 225 |
+
print(f"[BRIDGE] Session ID present (length {len(SCRATCH_SESSION_ID)})")
|
| 226 |
|
| 227 |
last_prompt = "0"
|
| 228 |
while True:
|
| 229 |
try:
|
| 230 |
+
print("[BRIDGE] Polling cloud variable 'prompt'...")
|
| 231 |
current = get_cloud_variable("prompt")
|
| 232 |
if current is None:
|
| 233 |
+
print("[BRIDGE] Got None, waiting...")
|
| 234 |
time.sleep(2)
|
| 235 |
continue
|
| 236 |
+
print(f"[BRIDGE] Current prompt value: '{current}'")
|
| 237 |
if current != last_prompt and current != "0":
|
| 238 |
+
print(f"[BRIDGE] New prompt detected: {current}")
|
| 239 |
decoded = decode_text(current)
|
| 240 |
print(f"[BRIDGE] Decoded: {decoded}")
|
| 241 |
ai_response = call_ai(decoded)
|
| 242 |
print(f"[BRIDGE] AI response: {ai_response[:100]}...")
|
| 243 |
encoded_response = encode_text(ai_response)
|
| 244 |
+
print(f"[BRIDGE] Encoded response length: {len(encoded_response)}")
|
| 245 |
success = set_cloud_variable("response", encoded_response)
|
| 246 |
if success:
|
| 247 |
print("[BRIDGE] Response sent to Scratch")
|
| 248 |
else:
|
| 249 |
print("[BRIDGE] Failed to send response")
|
| 250 |
last_prompt = current
|
| 251 |
+
else:
|
| 252 |
+
print("[BRIDGE] No change, sleeping...")
|
| 253 |
time.sleep(2)
|
| 254 |
except Exception as e:
|
| 255 |
+
print(f"[BRIDGE] Unexpected error: {e}")
|
| 256 |
+
import traceback
|
| 257 |
+
traceback.print_exc()
|
| 258 |
time.sleep(5)
|
| 259 |
|
| 260 |
# ==================== FLASK APP ====================
|
|
|
|
| 262 |
|
| 263 |
@app.route('/')
|
| 264 |
def health():
|
| 265 |
+
return "Scratch AI Bridge is running with verbose logging."
|
| 266 |
|
| 267 |
if __name__ == '__main__':
|
| 268 |
print("[MAIN] Starting bridge thread...")
|