File size: 7,169 Bytes
d65c869 0b536a4 3b4cd75 d604648 2e56a78 d65c869 3b4cd75 12a915d df9b297 12a915d cf5e82d 12a915d 0b536a4 e649e62 0b536a4 12a915d d65c869 d585e26 12a915d d65c869 1d5598d d65c869 d585e26 d65c869 12a915d d65c869 12a915d d65c869 d585e26 5103788 d1227cc 12a915d d1227cc d65c869 0b536a4 12a915d 9cdbb21 12a915d cf5e82d 0b536a4 2c514b7 0b536a4 e649e62 0b536a4 12a915d 2c514b7 0b536a4 12a915d 0b536a4 12a915d 0b536a4 cf5e82d 9cdbb21 e649e62 9cdbb21 12a915d 2c514b7 0b536a4 9181bd5 1ccae7f d65c869 12a915d 4d5e864 2e56a78 df9b297 12a915d 2e56a78 0b536a4 3b4cd75 d65c869 cf5e82d 2e56a78 12a915d cf5e82d 12a915d cf5e82d 27687e2 cf5e82d 27687e2 cf5e82d 308ddeb cf5e82d d65c869 cf5e82d 2c514b7 308ddeb d65c869 3b4cd75 d604648 d65c869 d604648 12a915d d65c869 d604648 d1227cc d604648 d1227cc d604648 | 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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | import threading
import time
import os
import random
import requests
from flask import Flask
import scratchattach as sa
# ==================== CONFIGURATION ====================
PROJECT_ID = "1298553820" # Your Scratch project ID
SCRATCH_USER = os.environ.get("SCRATCH_USER")
SCRATCH_PASS = os.environ.get("SCRATCH_PASS")
AI_URL = "https://16dvnk-scratch-ai.hf.space/generate" # Updated AI endpoint
# ==================== PROXY LIST (same as before) ====================
PROXY_LIST = [
"http://8.219.97.248:80",
"http://38.158.83.233:999",
"http://102.68.128.216:8080",
"http://8.243.126.136:8801",
"http://45.236.66.163:8520",
"http://103.155.167.62:8080",
"http://119.92.71.40:8080",
"http://103.144.146.5:8080",
"http://36.91.220.132:8080",
"http://41.254.48.192:1976"
]
# ==================== ENCODING / DECODING ====================
def encode_for_scratch(text):
encoded = []
for ch in text[:250]:
if 'a' <= ch <= 'z':
code = ord(ch) - ord('a') + 1
encoded.append(str(code).zfill(2))
elif 'A' <= ch <= 'Z':
code = ord(ch) - ord('A') + 28 # Uppercase range
encoded.append(str(code).zfill(2))
elif ch == ' ':
encoded.append("27")
else:
encoded.append("99")
return "".join(encoded)
def decode_from_scratch(encoded):
result = []
i = 0
while i < len(encoded):
if i + 1 < len(encoded) and encoded[i:i+2].isdigit():
num = int(encoded[i:i+2])
if 1 <= num <= 26:
result.append(chr(num + 96)) # lowercase
elif 28 <= num <= 53:
result.append(chr(num - 28 + 65)) # uppercase
elif num == 27:
result.append(' ')
elif num == 99:
result.append('?')
else:
result.append('?')
i += 2
else:
result.append('?')
i += 1
return "".join(result)
# ==================== PROXY ROTATOR ====================
class ProxyRotator:
def __init__(self, proxies):
self.proxies = proxies
self.current_index = 0
self.failed_proxies = set()
def get_next_proxy(self):
if len(self.failed_proxies) >= len(self.proxies):
self.failed_proxies.clear()
attempts = 0
while attempts < len(self.proxies):
proxy = self.proxies[self.current_index % len(self.proxies)]
self.current_index += 1
if proxy not in self.failed_proxies:
return {"http": proxy, "https": proxy}
self.failed_proxies.clear()
proxy = self.proxies[self.current_index % len(self.proxies)]
self.current_index += 1
return {"http": proxy, "https": proxy}
def mark_proxy_failed(self, proxy_url):
if isinstance(proxy_url, dict):
proxy_url = proxy_url.get("http", "")
self.failed_proxies.add(proxy_url)
proxy_rotator = ProxyRotator(PROXY_LIST)
# ==================== AI CALL WITH PROXY ROTATION ====================
def call_ai(prompt):
print(f"[AI] Sending prompt: {prompt[:50]}...")
for attempt in range(min(5, len(PROXY_LIST))):
proxy = proxy_rotator.get_next_proxy()
proxy_url = proxy.get("http", "")
try:
response = requests.post(AI_URL, json={"prompt": prompt}, proxies=proxy, timeout=5)
if response.status_code == 200:
data = response.json()
# Try common response keys
result = data.get("response") or data.get("text") or data.get("output") or "(no reply)"
print(f"[AI] Success (proxy {proxy_url})")
return result
else:
print(f"[AI] Proxy {proxy_url} returned {response.status_code}")
proxy_rotator.mark_proxy_failed(proxy)
except Exception as e:
print(f"[AI] Proxy {proxy_url} error: {e}")
proxy_rotator.mark_proxy_failed(proxy)
# Fallback direct
try:
response = requests.post(AI_URL, json={"prompt": prompt}, timeout=5)
if response.status_code == 200:
data = response.json()
result = data.get("response") or data.get("text") or data.get("output") or "(no reply)"
return result
except Exception as e:
print(f"[AI] Direct call error: {e}")
return "Error: Could not reach AI service."
ai_text = call_ai(user_prompt)
print(f"[DEBUG] Raw AI response: {ai_text}") # <-- add this
# ==================== BRIDGE WORKER ====================
def bridge_worker():
print("[BRIDGE] Starting bridge with corrected encoding/decoding")
print(f"[BRIDGE] Project ID: {PROJECT_ID}")
if not SCRATCH_USER or not SCRATCH_PASS:
print("[BRIDGE] ERROR: SCRATCH_USER and SCRATCH_PASS environment variables missing")
return
while True:
try:
print(f"[BRIDGE] Logging in as {SCRATCH_USER}...")
session = sa.login(SCRATCH_USER, SCRATCH_PASS)
print("[BRIDGE] Login successful. Connecting to cloud...")
cloud = session.connect_cloud(PROJECT_ID)
print(f"[BRIDGE] Connected to project {PROJECT_ID}")
# Set up event listener for cloud variable changes
events = cloud.events()
print("[BRIDGE] Event listener active. Waiting for 'prompt' changes...")
@events.event
def on_set(activity):
if activity.var == "prompt" and activity.value != "0":
print(f"[EVENT] Received encoded prompt: {activity.value}")
# Decode the prompt (from Scratch format)
user_prompt = decode_from_scratch(activity.value)
print(f"[EVENT] Decoded prompt: {user_prompt}")
# Get AI response
ai_text = call_ai(user_prompt)
print(f"[EVENT] AI response: {ai_text[:100]}...")
# Encode the AI response for Scratch
encoded_response = encode_for_scratch(ai_text)
# Send back to Scratch
cloud.set_var("response", encoded_response)
print("[EVENT] Response sent to Scratch")
events.start()
# Keep the thread alive
while True:
time.sleep(0.3)
except Exception as e:
print(f"[BRIDGE] Error: {e}")
import traceback
traceback.print_exc()
print("[BRIDGE] Reconnecting in 0.3 seconds...")
time.sleep(0.3)
# ==================== FLASK APP ====================
app = Flask(__name__)
@app.route('/')
def health():
return "Scratch AI Bridge is running (fixed encoding)."
if __name__ == '__main__':
print("[MAIN] Starting bridge thread...")
thread = threading.Thread(target=bridge_worker, daemon=True)
thread.start()
print("[MAIN] Starting Flask server...")
app.run(host='0.0.0.0', port=7860) |