import os import json from openai import OpenAI from dotenv import load_dotenv load_dotenv() # Setup OpenRouter Client client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key=os.getenv("OPENROUTER_API_KEY"), ) # Load data pool with open('bot_data_pool.json', 'r') as f: data_pool = json.load(f) DATA_SOURCE = os.getenv("DATA_SOURCE", "AI").upper() USED_DATA_FILE = "used_data.txt" def load_used_data(): """Loads all used names, services, and jobs into a dictionary of sets to prevent duplicates""" used = {"names": set(), "services": set(), "jobs": set()} if os.path.exists(USED_DATA_FILE): with open(USED_DATA_FILE, "r", encoding="utf-8") as f: for line in f: line = line.strip() if ":" in line: parts = line.split(":", 1) key = parts[0].strip().lower() val = parts[1].strip().lower() if key in used: used[key].add(val) return used def save_used_item(item_type, val): """Saves a single used item to our persistent text tracking file""" val_clean = val.strip() if not val_clean: return with open(USED_DATA_FILE, "a", encoding="utf-8") as f: f.write(f"{item_type}:{val_clean}\n") def generate_from_pool(): """Mengambil data secara acak langsung dari data pool dengan memfilter data yang sudah dipakai""" import random used = load_used_data() # Filter available unique names available_names = [n for n in data_pool['names'] if n.strip().lower() not in used['names']] if not available_names: available_names = data_pool['names'] # Fallback if pool is depleted name1 = random.choice(available_names) # Select unique name2 available_names_for_2 = [n for n in available_names if n != name1] if not available_names_for_2: available_names_for_2 = [n for n in data_pool['names'] if n != name1] name2 = random.choice(available_names_for_2) # Filter unique service titles available_services = [ s for s in data_pool['service_titles'] if s.strip().lower() not in used['services'] and s.strip().lower() not in used['jobs'] ] if not available_services: available_services = data_pool['service_titles'] title = random.choice(available_services) # Select random addresses addr1 = random.choice(data_pool['addresses']) addr2 = random.choice(data_pool['addresses']) return { "akun1": { "nama_lengkap": name1, "email": f"{name1.lower().replace(' ', '.')}@gmail.com", "nama_bisnis": name1, "deskripsi_bisnis": f"Penyedia jasa {title} profesional dan terpercaya.", "lokasi": { "lat": str(-6.2088 + (random.random() * 0.1)), "lng": str(106.8456 + (random.random() * 0.1)), "alamat": addr1, "radius": "50" }, "identitas": { "tipe": "KTP", "nomor": str(random.randint(1000000000000000, 9999999999999999)) } }, "akun2": { "nama_lengkap": name2, "email": f"{name2.lower().replace(' ', '.')}@gmail.com" }, "layanan": { "judul": title, "deskripsi": f"Saya menawarkan layanan {title} dengan hasil kualitas terbaik. Pengalaman sudah lebih dari 3 tahun di bidang ini.", "harga": random.choice([50000, 75000, 100000, 150000, 200000, 500000]) }, "review": { "rating": "5", "komentar": random.choice([ "Sangat puas dengan hasilnya!", "Kerja cepat dan rapi, mantap.", "Sangat direkomendasikan untuk jasa ini.", "Komunikasi baik dan hasil sesuai ekspektasi.", "Terima kasih banyak, sangat membantu." ]) } } def generate_bot_data(): """Menghasilkan data bot berdasarkan DATA_SOURCE (AI atau POOL) dengan jaminan tanpa duplikat""" if DATA_SOURCE == "POOL": data = generate_from_pool() # Save pool data to tracking log save_used_item("names", data["akun1"]["nama_lengkap"]) save_used_item("names", data["akun2"]["nama_lengkap"]) if "layanan" in data and "judul" in data["layanan"]: save_used_item("services", data["layanan"]["judul"]) save_used_item("jobs", data["layanan"]["judul"]) return data import random used = load_used_data() # Filter only active/fresh items to send in prompt context used_names_str = ", ".join(list(used['names'])[:100]) # Last 100 names to keep prompt lightweight used_services_str = ", ".join(list(used['services'])[:100]) names_sample = str(random.sample(data_pool['names'], min(15, len(data_pool['names'])))) service_titles_sample = str(random.sample(data_pool['service_titles'], min(10, len(data_pool['service_titles'])))) job_titles_sample = str(random.sample(data_pool['job_titles'], min(10, len(data_pool['job_titles'])))) addresses_sample = str(random.sample(data_pool['addresses'], min(10, len(data_pool['addresses'])))) # Jika mode AI prompt = f""" Anda adalah asisten AI yang bertugas men-generate data JSON untuk simulasi marketplace jasa (Microjob). GUIDELINE PENAMAAN (Wajib Diikuti): - Nama Orang: Gunakan referensi seperti {names_sample}... (Hanya nama asli orang Indonesia). - Nama Bisnis: HARUS sama dengan Nama Lengkap orang tersebut (Jangan gunakan tambahan 'Design', 'Solusi', dll). - Judul Layanan: Gunakan pola seperti {service_titles_sample}... - Judul Job: Gunakan pola seperti {job_titles_sample}... - Alamat: Gunakan referensi pola seperti {addresses_sample}... ATURAN ANTI-DUPLIKASI (PENTING!): - JANGAN GUNAKAN NAMA BERIKUT KARENA SUDAH PERNAH DIGUNAKAN (DUPLIKAT): {used_names_str if used_names_str else 'Belum ada'} - JANGAN GUNAKAN JUDUL LAYANAN ATAU JUDUL JOB BERIKUT KARENA SUDAH PERNAH DIGUNAKAN (DUPLIKAT): {used_services_str if used_services_str else 'Belum ada'} Aturan Tambahan: 1. JANGAN gunakan nama artis, tokoh publik, atau selebriti. 2. JANGAN ada kata 'bot' di data manapun. 3. Output harus valid JSON. Struktur JSON: {{ "akun1": {{ "nama_lengkap": "Nama asli orang Indonesia yang realistis (Hanya nama orang biasa, misal: Budi Santoso, Siti Aminah)", "email": "Email pribadi realistis berdasarkan nama", "nama_bisnis": "Gunakan nama orang saja (Hanya nama, jangan gunakan tambahan 'Solusi Digital', 'Design', 'Jasa', dll)", "deskripsi_bisnis": "Deskripsi singkat tentang keahlian atau layanan yang ditawarkan", "lokasi": {{ "lat": "Latitude acak di area perkotaan Indonesia (misal: Jakarta, Bandung, atau Surabaya)", "lng": "Longitude acak di area perkotaan Indonesia", "alamat": "Alamat lengkap realistis di Indonesia", "radius": "Angka radius layanan dalam KM (antara 10-100)" }}, "identitas": {{ "tipe": "KTP", "nomor": "16 digit angka KTP acak yang valid secara format" }} }}, "akun2": {{ "nama_lengkap": "Nama asli pembeli Indonesia yang realistis (Hanya nama orang biasa)", "email": "Email pribadi realistis berdasarkan nama" }}, "layanan": {{ "judul": "Judul jasa yang ditawarkan (HARUS Unik dan Kreatif)", "deskripsi": "Deskripsi lengkap layanan tersebut", "harga": 50000 }}, "review": {{ "rating": 5, "komentar": "Komentar positif dari pembeli" }} }} Berikan HANYA JSON output tanpa teks lain. """ max_retries = 5 attempt = 0 while attempt < max_retries: try: response = client.chat.completions.create( model="google/gemini-3-flash-preview", messages=[ {"role": "system", "content": "You output only valid JSON."}, {"role": "user", "content": prompt} ] ) content = response.choices[0].message.content.strip() # Strip markdown backticks if present if content.startswith("```"): content = content.split("```")[1] if content.startswith("json"): content = content[4:] content = content.split("```")[0].strip() data = json.loads(content) # Commit successfully generated items to our local used data file save_used_item("names", data["akun1"]["nama_lengkap"]) save_used_item("names", data["akun2"]["nama_lengkap"]) if "layanan" in data and "judul" in data["layanan"]: save_used_item("services", data["layanan"]["judul"]) save_used_item("jobs", data["layanan"]["judul"]) return data except Exception as e: attempt += 1 print(f"Error generating AI data (Attempt {attempt}/{max_retries}): {e}") if attempt < max_retries: import time time.sleep(3) else: print("Max retries reached. AI generation failed.") raise e if __name__ == "__main__": print(generate_bot_data())