╔══════════════════════════════════════════════════╗ ║ CODE REPOSITORY ARCHIVE ║ ╠══════════════════════════════════════════════════╣ ║ Repository: Rdp ║ ║ Generated: 10/29/2026, 2:11:13 PM ║ ║ Files: 4 ║ ║ Description: Bot_rdp ║ ╚══════════════════════════════════════════════════╝ FILE SUMMARY ──────────────────────────────────────────────────── Total files: 4 Total size: 26264 characters Folder structure: Rdp/ Languages: - text: 2 files - image: 1 files - markdown: 1 files FILE CONTENTS ════════════════════════════════════════════════════ ┌── FILE 01: Rdp/install.sh │ Size: 4166 characters │ Language: text │ Created: 10/10/2026 └──────────────────────────────────────────────────── #!/bin/bash # install_bot.sh - GTN RDP STORE BOT - AUTO DOWNLOAD FROM CODEHUB # Link bot lu: https://codehub.vigilante.biz.id/raw/yn7drb6230nmv1wh877 # 1 FILE INSTALLER - auto download bot.py + qris.jpg BOT_URL="https://codehub.vigilante.biz.id/raw/rdp/rdp_bot.py" QRIS_URL="https://codehub.vigilante.biz.id/raw/rdp/qris.jpg" # <-- GANTI ID QRIS LU DISINI # Contoh: QRIS_URL="https://codehub.vigilante.biz.id/raw/abcd1234qris" echo -e "\033[1;33mInstalling GTN RDP Bot...\033[0m" echo -e "Downloading bot from: $BOT_URL" PYTHON_EXEC="/usr/bin/python3" if ! command -v $PYTHON_EXEC &> /dev/null; then echo "Installing Python3..." apt-get update apt-get install -y python3 python3-pip curl wget fi if ! $PYTHON_EXEC -m pip --version &> /dev/null; then apt-get install -y python3-pip fi echo "Installing python-telegram-bot & paramiko..." if ! $PYTHON_EXEC -m pip install python-telegram-bot paramiko --break-system-packages 2>/dev/null; then $PYTHON_EXEC -m pip install python-telegram-bot paramiko fi mkdir -p /etc/gtnrdp echo "Downloading bot.py to /usr/local/bin/gtnrdp_bot.py..." if command -v curl &> /dev/null; then curl -sSL "$BOT_URL" -o /usr/local/bin/gtnrdp_bot.py else wget -qO /usr/local/bin/gtnrdp_bot.py "$BOT_URL" fi if [ ! -s /usr/local/bin/gtnrdp_bot.py ]; then echo -e "\033[1;31m❌ Gagal download bot dari $BOT_URL\033[0m" if [ -f "gtnrdp_bot.py" ]; then cp gtnrdp_bot.py /usr/local/bin/gtnrdp_bot.py; elif [ -f "bot-rdp-zivpn-style-final.py" ]; then cp bot-rdp-zivpn-style-final.py /usr/local/bin/gtnrdp_bot.py; else echo "❌ File bot tidak ada!"; exit 1; fi fi chmod +x /usr/local/bin/gtnrdp_bot.py echo -e "\033[1;32m✅ Bot downloaded dari CodeHub!\033[0m" # === AUTO DOWNLOAD QRIS DARI CODEHUB === echo "Downloading QRIS..." if [[ "$QRIS_URL" != *"QRIS_ID_LU"* ]]; then echo "QRIS URL: $QRIS_URL" if command -v curl &> /dev/null; then curl -sSL "$QRIS_URL" -o /etc/gtnrdp/qris.jpg else wget -qO /etc/gtnrdp/qris.jpg "$QRIS_URL" fi if [ -s /etc/gtnrdp/qris.jpg ]; then echo -e "\033[1;32m✅ qris.jpg downloaded dari CodeHub!\033[0m" else echo -e "\033[1;31m❌ Gagal download QRIS\033[0m" fi else # Fallback kalau QRIS_URL belum diganti, cek file lokal if [ -f "qris.jpg" ]; then cp qris.jpg /etc/gtnrdp/qris.jpg echo "✅ qris.jpg copied dari lokal" else echo -e "\033[1;33m⚠️ QRIS_URL belum diganti, upload manual ke /etc/gtnrdp/qris.jpg\033[0m" echo -e "\033[1;33mAtau ganti QRIS_URL di install_bot.sh dengan link raw QRIS lu\033[0m" fi fi if [ ! -f "/etc/gtnrdp/bot_config.sh" ]; then echo -e "\033[1;33mBuat config /etc/gtnrdp/bot_config.sh\033[0m" read -p "Masukkan BOT TOKEN: " BOT_TOKEN read -p "Masukkan ADMIN CHAT_ID: " CHAT_ID echo "BOT_TOKEN=\"$BOT_TOKEN\"" > /etc/gtnrdp/bot_config.sh echo "CHAT_ID=\"$CHAT_ID\"" >> /etc/gtnrdp/bot_config.sh echo "Config saved!" else echo "Config sudah ada: /etc/gtnrdp/bot_config.sh" cat /etc/gtnrdp/bot_config.sh fi echo "Creating systemd service..." cat > /etc/systemd/system/gtnrdp-bot.service < RDP_INSTALL_URL" echo -e "\033[1;33mNOTE:\033[0m QRIS: /etc/gtnrdp/qris.jpg | Saldo: /etc/gtnrdp/resellers.json" ──────────────────────────────────────────────────────────── ┌── FILE 02: Rdp/rdp_bot.py │ Size: 20138 characters │ Language: text │ Created: 10/10/2026 └──────────────────────────────────────────────────── """ GTN RDP STORE - ADAPTED FROM ZIVPN BOT STYLE - Sistem admin kayak ZIVPN: CHAT_ID di /etc/zivpn/bot_config.sh - Role: Admin, Reseller, Member - Saldo manual via QRIS (qr.jpg) - Custom password RDP + Kelola RDP (ganti pass) - Harga 1k per RDP """ import logging, json, os, subprocess, time, asyncio, datetime, random, string, re, sys, html, paramiko, socket, shlex from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, InputFile from telegram.constants import ParseMode from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, CallbackQueryHandler, MessageHandler, filters, ConversationHandler # --- PATHS (pakai struktur sama kayak ZIVPN biar familiar) --- DIR_PATH = "/etc/gtnrdp" os.makedirs(DIR_PATH, exist_ok=True) RESELLER_DB = f"{DIR_PATH}/resellers.json" # saldo & role RDP_DB = f"{DIR_PATH}/rdp_list.json" BOT_CONFIG = f"{DIR_PATH}/bot_config.sh" QRIS_IMAGE = f"{DIR_PATH}/qris.jpg" # QR lu taro sini INCOME_DB = f"{DIR_PATH}/income_log.json" BOT_START_TIME = time.time() logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) logger = logging.getLogger(__name__) # Conversation States (SELECTING_ACTION, BUAT_IP, BUAT_SSH, BUAT_RDP_PASS, BUAT_WIN, GANTI_PASS_NEW, ADD_BAL_ID, ADD_BAL_AMOUNT, ADD_RESELLER, DEL_RESELLER, SET_PRICE) = range(11) # --- HELPERS (copy dari ZIVPN) --- def get_config_value(key): if not os.path.exists(BOT_CONFIG): return None try: with open(BOT_CONFIG, 'r') as f: content = f.read() pattern = r'^\s*(?:export\s+)?' + re.escape(key) + r'\s*=\s*(["\']?)(.*?)\1\s*$' m = re.search(pattern, content, re.MULTILINE) if m: return m.group(2).strip() except: pass return None def load_json(fp): if not os.path.exists(fp): return {} if 'reseller' in fp or 'rdp' in fp or 'income' in fp else [] try: with open(fp,'r') as f: return json.load(f) except: return {} def save_json(fp, data): with open(fp,'w') as f: json.dump(data, f, indent=4) def load_resellers(): if not os.path.exists(RESELLER_DB): return {} try: with open(RESELLER_DB,'r') as f: data=json.load(f) if isinstance(data, list): nd={} for rid in data: nd[str(rid)]={"balance":0,"role":"member"} save_json(RESELLER_DB, nd) return nd return data except: return {} def save_resellers(d): save_json(RESELLER_DB, d) def get_balance(uid): d=load_resellers() return d.get(str(uid),{}).get("balance",0) def update_balance(uid, amount): d=load_resellers() sid=str(uid) if sid not in d: d[sid]={"balance":0,"role":"member"} d[sid]["balance"]=d[sid].get("balance",0)+amount save_resellers(d) return d[sid]["balance"] def is_admin(uid): val=get_config_value("CHAT_ID") return str(uid)==str(val) def check_reseller(uid): d=load_resellers() return d.get(str(uid),{}).get("role")=="reseller" def get_price(): # Harga RDP - default 1000 cfg=load_json(f"{DIR_PATH}/settings.json") return cfg.get("rdp_price", 1000) def set_price(p): cfg=load_json(f"{DIR_PATH}/settings.json") if not isinstance(cfg, dict): cfg={} cfg["rdp_price"]=int(p) save_json(f"{DIR_PATH}/settings.json", cfg) def get_rdp_list(): return load_json(RDP_DB) def save_rdp_list(data): save_json(RDP_DB, data) def add_rdp_record(uid, ip, rdp_pass, ssh_pass, windows): data=get_rdp_list() if not isinstance(data, list): data=[] data.append({ "user_id": str(uid), "ip": ip, "rdp_pass": rdp_pass, "ssh_pass": ssh_pass, "windows": windows, "status": "installing", "created": datetime.datetime.now().strftime("%Y-%m-%d %H:%M") }) save_rdp_list(data) # === INI SCRIPT INDEPENDENT PUNYA LU - GANTI URL DISINI KALO PUNYA PRIVATE === RDP_INSTALL_URL = "https://raw.githubusercontent.com/Nizwarax/Rdp/main/reinstall.sh" # kalau punya script private, ganti jadi: RDP_INSTALL_URL = "http://sacrifice.web.id/rdp.sh" atau file lu sendiri def install_rdp_auto(ip, ssh_pass, windows, rdp_pass): try: s=paramiko.SSHClient(); s.set_missing_host_key_policy(paramiko.AutoAddPolicy()) s.connect(ip, username='root', password=ssh_pass, timeout=15, banner_timeout=15, auth_timeout=15) # fix quoting biar password ada $ " ` gak bikin shell error safe_rdp_pass = shlex.quote(rdp_pass) safe_win = shlex.quote(windows) # pakai shlex juga buat RDP_INSTALL_URL biar aman cmd = f"nohup bash -c 'curl -sSL {shlex.quote(RDP_INSTALL_URL)} -o /root/reinstall.sh || wget -qO /root/reinstall.sh {shlex.quote(RDP_INSTALL_URL)}; chmod +x /root/reinstall.sh; bash /root/reinstall.sh windows --image-name {safe_win} --password {safe_rdp_pass} --allow-ping' > /tmp/rdp.log 2>&1 &" s.exec_command(cmd); time.sleep(2); s.close() return True, "" except Exception as e: err = str(e) logger.error(f"RDP install fail {ip}: {err}") return False, err def check_rdp(ip): try: sock=socket.socket(); sock.settimeout(3) return sock.connect_ex((ip,3389))==0 except: return False def format_rupiah(v): try: return f"Rp {int(v):,.0f}".replace(",",".") except: return str(v) def get_uptime(): delta=int(time.time()-BOT_START_TIME) return f"{delta//3600}h {(delta%3600)//60}m" # --- MENU --- async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): user=update.effective_user uid=str(user.id) safe_name = f"@{user.username}" if user.username else html.escape(user.first_name) saldo=get_balance(uid) role="Admin" if is_admin(uid) else ("Reseller" if check_reseller(uid) else "Member") saldo_txt="∞" if is_admin(uid) else format_rupiah(saldo) price=format_rupiah(get_price()) text=( f"📦━━━━━━━━━━━━━━━━━━━📦\n" f" ✨ GTN RDP STORE ✨\n" f"📦━━━━━━━━━━━━━━━━━━━📦\n\n" f"🧭 info akun\n" f"┏━━━━━━━━━━━━━━━━━━━━━┓\n" f"┃ 💰 saldo: {saldo_txt}\n" f"┃ 👤 status: {role}\n" f"┃ 🌐 user: {safe_name}\n" f"┃ 🆔 id: {uid}\n" f"┃ ⏱️ uptime: {get_uptime()}\n" f"┗━━━━━━━━━━━━━━━━━━━━━┛\n\n" f"🎯 harga\n" f"┏━━━━━━━━━━━━━━━━━━━━━┓\n" f"┃ 🏷️ 1 RDP: {price}\n" f"┃ 🔐 custom pass: bisa\n" f"┃ ⚡ auto install: 15-20m\n" f"┗━━━━━━━━━━━━━━━━━━━━━┛\n" ) buttons=[ [InlineKeyboardButton("📦 Buat RDP Custom Pass", callback_data='buat_rdp')], [InlineKeyboardButton("📋 Kelola RDP Ku", callback_data='kelola_rdp'), InlineKeyboardButton("🔍 Cek RDP", callback_data='cek_rdp')], [InlineKeyboardButton("💰 Saldo Ku", callback_data='saldo'), InlineKeyboardButton("💳 Topup QRIS", callback_data='topup')], ] if is_admin(uid): buttons.append([InlineKeyboardButton("👑 Admin: Add Saldo", callback_data='admin_addsaldo'), InlineKeyboardButton("👥 List Saldo", callback_data='admin_listsaldo')]) buttons.append([InlineKeyboardButton("➕ Add Reseller", callback_data='admin_addreseller'), InlineKeyboardButton("📦 Semua RDP", callback_data='admin_allrdp')]) buttons.append([InlineKeyboardButton("🏷️ Set Harga RDP", callback_data='admin_setprice')]) rm=InlineKeyboardMarkup(buttons) if update.callback_query: await update.callback_query.edit_message_text(text, reply_markup=rm, parse_mode=ParseMode.HTML) else: await update.message.reply_text(text, reply_markup=rm, parse_mode=ParseMode.HTML) return SELECTING_ACTION # --- BUAT RDP FLOW (CUSTOM PASS) --- async def buat_rdp_start(update: Update, context: ContextTypes.DEFAULT_TYPE): await update.callback_query.answer() await update.callback_query.edit_message_text("📦 Buat RDP Custom\n\nMasukkan IP VPS target:", parse_mode=ParseMode.HTML) return BUAT_IP async def buat_ip(update: Update, context: ContextTypes.DEFAULT_TYPE): context.user_data['ip']=update.message.text.strip() await update.message.reply_text(f"IP: {context.user_data['ip']} ✅\n\nMasukkan Password SSH Root:", parse_mode=ParseMode.HTML) return BUAT_SSH async def buat_ssh(update: Update, context: ContextTypes.DEFAULT_TYPE): context.user_data['ssh']=update.message.text.strip() await update.message.reply_text("Masukkan Password RDP custom yang kamu mau:\nContoh: MyRdp2025!!\nKetik /default untuk pakai Rdp123@@", parse_mode=ParseMode.HTML) return BUAT_RDP_PASS async def buat_rdp_pass(update: Update, context: ContextTypes.DEFAULT_TYPE): rpass = "Rdp123@@" if update.message.text.strip()=="/default" else update.message.text.strip() context.user_data['rpass']=rpass kb=InlineKeyboardMarkup([ [InlineKeyboardButton("Server 2022", callback_data='win_2022'), InlineKeyboardButton("Server 2019", callback_data='win_2019')], [InlineKeyboardButton("Win 11 Pro", callback_data='win_11'), InlineKeyboardButton("Win 10 Pro", callback_data='win_10')] ]) await update.message.reply_text(f"Pass RDP: {rpass} ✅\n\nPilih Windows:", reply_markup=kb, parse_mode=ParseMode.HTML) return BUAT_WIN async def buat_win(update: Update, context: ContextTypes.DEFAULT_TYPE): q=update.callback_query await q.answer() wm={"win_2022":"Windows Server 2022 SERVERDATACENTER","win_2019":"Windows Server 2019 SERVERDATACENTER","win_11":"Windows 11 Pro","win_10":"Windows 10 Pro"} win=wm[q.data] ip=context.user_data['ip']; ssh=context.user_data['ssh']; rpass=context.user_data['rpass'] uid=update.effective_user.id price=get_price() saldo=get_balance(uid) if not is_admin(uid) and saldo < price: await q.edit_message_text(f"❌ Saldo kurang! Butuh {format_rupiah(price)}, saldo lu {format_rupiah(saldo)}\n\nTopup dulu via QRIS", parse_mode=ParseMode.HTML) return SELECTING_ACTION await q.edit_message_text(f"🔄 Install RDP di {ip}...\nWindows: {win}\nPass: {rpass} (custom)\n\nSedang proses...", parse_mode=ParseMode.HTML) ok, err = install_rdp_auto(ip, ssh, win, rpass) if ok: if not is_admin(uid): update_balance(uid, -price) # log income logs=load_json(INCOME_DB) if not isinstance(logs, list): logs=[] logs.append({"timestamp":int(time.time()),"user_id":str(uid),"username":update.effective_user.username or "", "amount":price, "ip":ip}) save_json(INCOME_DB, logs) add_rdp_record(uid, ip, rpass, ssh, win) await context.bot.send_message(chat_id=update.effective_chat.id, text=f"✅ RDP DIPROSES!\n\nIP: {ip}:3389\nUser: Administrator\nPass: {rpass} (custom)\nWin: {win}\n\nTunggu 15-20 menit\nCek: /cekrdp {ip}\nKelola: /kelolardp", parse_mode=ParseMode.HTML) else: # kasih error detail biar tau kenapa gagal await context.bot.send_message(chat_id=update.effective_chat.id, text=f"❌ Gagal install {ip}\n\nPenyebab: {html.escape(err)[:500]}\n\nCek:\n1. IP benar? ping {ip}\n2. SSH root aktif? coba ssh root@{ip}\n3. Pass SSH salah?\n4. Port 22 keblok firewall?\n5. Password RDP ada karakter aneh?", parse_mode=ParseMode.HTML) return await start(update, context) # --- KELOLA RDP --- async def kelola_rdp(update: Update, context: ContextTypes.DEFAULT_TYPE): q=update.callback_query; await q.answer() uid=str(update.effective_user.id) data=get_rdp_list() my=[x for x in data if x.get("user_id")==uid] if not my: await q.edit_message_text("Belum ada RDP. Buat dulu /buatrdp", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("🔙 Menu", callback_data='back')]])) return SELECTING_ACTION txt="📋 RDP Kamu:\n\n" kb=[] for i, r in enumerate(my[-10:]): txt+=f"{i+1}. {r['ip']}:3389 | {r['rdp_pass']} | {r['status']}\n" kb.append([InlineKeyboardButton(f"Ganti Pass {r['ip']}", callback_data=f"gp_{r['ip']}"), InlineKeyboardButton(f"Cek {r['ip']}", callback_data=f"ck_{r['ip']}")]) kb.append([InlineKeyboardButton("🔙 Menu", callback_data='back')]) await q.edit_message_text(txt, reply_markup=InlineKeyboardMarkup(kb), parse_mode=ParseMode.HTML) return SELECTING_ACTION async def cek_rdp_cb(update: Update, context: ContextTypes.DEFAULT_TYPE): q=update.callback_query; await q.answer() ip=q.data.replace('ck_','') ok=check_rdp(ip) await q.message.reply_text(f"{'🟢 AKTIF' if ok else '🟡 Installing / 🔴 Mati'} - {ip}:3389") async def ganti_pass_cb(update: Update, context: ContextTypes.DEFAULT_TYPE): q=update.callback_query; await q.answer() ip=q.data.replace('gp_','') context.user_data['gp_ip']=ip await q.message.reply_text(f"Masukkan password baru untuk RDP {ip}:") return GANTI_PASS_NEW async def ganti_pass_new(update: Update, context: ContextTypes.DEFAULT_TYPE): new_pass=update.message.text.strip() ip=context.user_data['gp_ip'] uid=str(update.effective_user.id) # cari ssh pass data=get_rdp_list() ssh_pass="" for r in data: if r['ip']==ip and r['user_id']==uid: ssh_pass=r['ssh_pass'] r['rdp_pass']=new_pass break save_rdp_list(data) # coba ganti via ssh jika windows sudah jadi try: s=paramiko.SSHClient(); s.set_missing_host_key_policy(paramiko.AutoAddPolicy()) s.connect(ip, username='Administrator', password=ssh_pass, timeout=10) s.exec_command(f"net user Administrator {shlex.quote(new_pass)}") s.close() await update.message.reply_text(f"✅ Password RDP {ip} diganti jadi {new_pass}", parse_mode=ParseMode.HTML) except: # jika belum jadi windows, update db aja, nanti pas install pakai pass baru? simpan aja await update.message.reply_text(f"✅ Password di database diganti jadi {new_pass}\nJika RDP masih installing, password baru akan aktif setelah install selesai (reinstall manual jika perlu)", parse_mode=ParseMode.HTML) return await start(update, context) # --- SALDO & TOPUP MANUAL (QR PUNYA LU) --- async def saldo_cb(update: Update, context: ContextTypes.DEFAULT_TYPE): q=update.callback_query; await q.answer() uid=str(update.effective_user.id) saldo=get_balance(uid) await q.message.reply_text(f"💰 Saldo: {format_rupiah(saldo)} ({saldo//get_price()} RDP)") async def topup_cb(update: Update, context: ContextTypes.DEFAULT_TYPE): q=update.callback_query; await q.answer() admin_uname="@Nizwara" # GANTI USERNAME LU uid=update.effective_user.id txt=( "💳 TOPUP MANUAL - QRIS PUNYA LU\n\n" "1. Scan QR dibawah ini\n" "2. Transfer sesuai nominal\n" "3. Kirim bukti ke Admin: "+admin_uname+"\n" f"4. Sertakan ID: {uid}\n\n" f"Harga: {format_rupiah(get_price())} / RDP\n" "10k = 10 RDP, 50k = 50 RDP\n\n" "Admin akan add saldo manual biar gak ada auto payment mencurigakan" ) if os.path.exists(QRIS_IMAGE): await context.bot.send_photo(chat_id=update.effective_chat.id, photo=open(QRIS_IMAGE,'rb'), caption=txt, parse_mode=ParseMode.HTML) else: await context.bot.send_message(chat_id=update.effective_chat.id, text=txt + "\n\n⚠️ QR belum ada di /etc/gtnrdp/qris.jpg", parse_mode=ParseMode.HTML) # --- ADMIN: ADD SALDO (MANUAL BIAR GAK CURIGA) --- async def admin_addsaldo_start(update: Update, context: ContextTypes.DEFAULT_TYPE): q=update.callback_query; await q.answer() if not is_admin(update.effective_user.id): return SELECTING_ACTION await q.edit_message_text("💰 Add Saldo Manual\n\nMasukkan ID Telegram User:", parse_mode=ParseMode.HTML) return ADD_BAL_ID async def add_bal_id(update: Update, context: ContextTypes.DEFAULT_TYPE): context.user_data['bal_id']=update.message.text.strip() await update.message.reply_text(f"Target ID: {context.user_data['bal_id']}\nMasukkan nominal (contoh 10000):", parse_mode=ParseMode.HTML) return ADD_BAL_AMOUNT async def add_bal_amount(update: Update, context: ContextTypes.DEFAULT_TYPE): try: amt=int(update.message.text.strip()) except: return ADD_BAL_AMOUNT tid=context.user_data['bal_id'] new_bal=update_balance(tid, amt) await update.message.reply_text(f"✅ Saldo Rp {amt} ditambah ke {tid}\nSaldo sekarang: {format_rupiah(new_bal)}", parse_mode=ParseMode.HTML) try: await context.bot.send_message(chat_id=int(tid), text=f"✅ Admin menambah saldo {format_rupiah(amt)}\nSaldo sekarang: {format_rupiah(new_bal)}") except: pass return await start(update, context) async def admin_listsaldo(update: Update, context: ContextTypes.DEFAULT_TYPE): q=update.callback_query; await q.answer() data=load_resellers() txt=f"👥 List Saldo ({len(data)})\n\n" for uid, info in sorted(data.items(), key=lambda x: x[1].get('balance',0), reverse=True)[:20]: txt+=f"ID {uid} - {format_rupiah(info.get('balance',0))} - {info.get('role','member')}\n" await q.edit_message_text(txt, parse_mode=ParseMode.HTML, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("🔙 Menu", callback_data='back')]])) async def admin_allrdp(update: Update, context: ContextTypes.DEFAULT_TYPE): q=update.callback_query; await q.answer() data=get_rdp_list() txt=f"📦 Semua RDP ({len(data)})\n\n" for r in data[-20:]: txt+=f"User {r['user_id']} | {r['ip']}:3389 | {r['rdp_pass']} | {r['status']}\n" await q.edit_message_text(txt[:4000], parse_mode=ParseMode.HTML, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("🔙 Menu", callback_data='back')]])) # --- MAIN --- def main(): token=get_config_value("BOT_TOKEN") if not token: print("BOT_TOKEN belum ada di /etc/gtnrdp/bot_config.sh") print("Buat file: echo 'BOT_TOKEN=123:ABC' > /etc/gtnrdp/bot_config.sh && echo 'CHAT_ID=ID_ADMIN_LU' >> /etc/gtnrdp/bot_config.sh") return app=ApplicationBuilder().token(token).build() conv=ConversationHandler( entry_points=[CommandHandler("start", start), CallbackQueryHandler(start, pattern='^back$')], states={ SELECTING_ACTION: [ CallbackQueryHandler(buat_rdp_start, pattern='^buat_rdp$'), CallbackQueryHandler(kelola_rdp, pattern='^kelola_rdp$'), CallbackQueryHandler(cek_rdp_cb, pattern='^ck_'), CallbackQueryHandler(ganti_pass_cb, pattern='^gp_'), CallbackQueryHandler(saldo_cb, pattern='^saldo$'), CallbackQueryHandler(topup_cb, pattern='^topup$'), CallbackQueryHandler(admin_addsaldo_start, pattern='^admin_addsaldo$'), CallbackQueryHandler(admin_listsaldo, pattern='^admin_listsaldo$'), CallbackQueryHandler(admin_allrdp, pattern='^admin_allrdp$'), CallbackQueryHandler(start, pattern='^back$'), ], BUAT_IP: [MessageHandler(filters.TEXT & ~filters.COMMAND, buat_ip)], BUAT_SSH: [MessageHandler(filters.TEXT & ~filters.COMMAND, buat_ssh)], BUAT_RDP_PASS: [ MessageHandler(filters.TEXT, buat_rdp_pass), # TEXT aja, biar /default ke-detect (sebelumnya ~COMMAND bikin /default gak masuk) CommandHandler("default", buat_rdp_pass) ], BUAT_WIN: [CallbackQueryHandler(buat_win, pattern='^win_')], GANTI_PASS_NEW: [MessageHandler(filters.TEXT & ~filters.COMMAND, ganti_pass_new)], ADD_BAL_ID: [MessageHandler(filters.TEXT & ~filters.COMMAND, add_bal_id)], ADD_BAL_AMOUNT: [MessageHandler(filters.TEXT & ~filters.COMMAND, add_bal_amount)], }, fallbacks=[CommandHandler("start", start)] ) app.add_handler(conv) print("GTN RDP Bot ZIVPN Style Running - Manual QR Topup - Custom Pass") app.run_polling() if __name__=='__main__': main() ──────────────────────────────────────────────────────────── ┌── FILE 03: Rdp/qris.jpg │ Size: 151496 characters │ Language: image │ Created: 10/10/2026 └──────────────────────────────────────────────────── [Binary file: qris.jpg • image/jpeg • 151496 bytes] ──────────────────────────────────────────────────────────── ┌── FILE 04: Rdp/README.md │ Size: 1960 characters │ Language: markdown │ Created: 10/10/2026 └──────────────────────────────────────────────────── # GTN RDP STORE BOT - ZIVPN Style Bot Telegram jualan RDP 1k, custom password, saldo manual QRIS, script independent. **Hosting CodeHub:** - Bot: `https://codehub.vigilante.biz.id/raw/rdp/rdp_bot.py` - Installer: `https://codehub.vigilante.biz.id/raw/rdp/install.sh` - QRIS: `https://codehub.vigilante.biz.id/raw/rdp/qris.jpg` --- ## 🚀 Install 1 Baris ```bash wget -O install.sh https://codehub.vigilante.biz.id/raw/rdp/install.sh && chmod +x install.sh && ./install.sh ``` Atau: ```bash curl -sSL https://codehub.vigilante.biz.id/raw/rdp/install.sh | bash ``` **Auto:** - Download `rdp_bot.py` → `/usr/local/bin/gtnrdp_bot.py` - Download `qris.jpg` → `/etc/gtnrdp/qris.jpg` - Buat service `gtnrdp-bot` --- ## ⚙️ Setup Input saat install: ``` BOT TOKEN: dari @BotFather ADMIN CHAT_ID: dari @userinfobot ``` Cek: ```bash systemctl status gtnrdp-bot journalctl -u gtnrdp-bot -f ``` ## 🎮 Flow User 1. `/start` → saldo & harga Rp 1.000 2. `💳 Topup QRIS` → scan QR → kirim bukti + ID ke admin 3. Admin: `👑 Add Saldo` → ID → 10000 4. `📦 Buat RDP Custom Pass` → IP → SSH Root → Password RDP Custom (`MyRdp2025!!` atau `/default`) → Pilih Windows 5. Proses 15-20m, cek `🔍 Cek RDP` Script RDP tetap independent punya lu di bot line 118: ```python RDP_INSTALL_URL = "https://raw.githubusercontent.com/Nizwarax/Rdp/main/reinstall.sh" ``` ## 📁 File - `/usr/local/bin/gtnrdp_bot.py` - bot - `/etc/gtnrdp/bot_config.sh` - TOKEN & CHAT_ID - `/etc/gtnrdp/qris.jpg` - QRIS - `/etc/gtnrdp/resellers.json` - saldo - `/etc/gtnrdp/rdp_list.json` - list RDP ## 🔧 Update ```bash curl -sSL https://codehub.vigilante.biz.id/raw/rdp/rdp_bot.py -o /usr/local/bin/gtnrdp_bot.py systemctl restart gtnrdp-bot ``` ## 📝 Link CodeHub Upload 3 file ke `rdp/` di CodeHub: - `rdp_bot.py` ← file `bot-rdp-zivpn-style-final.py` - `install.sh` ← file installer - `qris.jpg` ← QR lu Maka user install cukup 1 link: `https://codehub.vigilante.biz.id/raw/rdp/install.sh` ════════════════════════════════════════════════════════════ ARCHIVE COMPLETE - 4 files exported Location: Rdp/ Exported: 10/29/2026, 2:11:13 PM Source: CodeHub Repository ════════════════════════════════════════════════════════════