Outline key api ကို Telegram Bot နဲ့ချတ်ဆက်ပြီး Outline key server အများကြီး ထည့်ပြီး key အလွယ်ကူဆုံးထုတ်နည်း
Ubuntu 24.04 • dotenv + dotpy
သတိ: .env ကိုပြင်တဲ့ အခါမှာ ရှေ့မှာ server name ထည့်ပြီး (:)ခံပြီး api ကို မှန်ကန်အောင်ထည့်ဖို့ လိုပါတယ် နောက်ထပ် server များထပ်ထည့်ရင်
အောက်တကြောင်းလုံးဝ မဆင်းပဲ comma ခံပြီး server name နဲ့ api ကို ဆက်ထည့်သွားရပါမယ်။ Domain သုံးမယ်ဆို ထိုနည်းတူပါပဲ
Goal: VPS အသစ်မှာ bot ကနေကြိုကတဲ့ server ကနေ key ထုတ်လို့ရဖို့ပါပဲ
vps ကို update လုပ်ပြိး လိုအပ်တဲ့ app များထည့်သင်းပါ
VPS Environment ပြင်ဆင်ခြင်း အရင်ဆုံး VPS အသစ်ကို Update လုပ်ပြီး လိုအပ်တဲ့ Python Environment တည်ဆောက်ပါ။
sudo apt update && sudo apt upgrade -y
sudo apt install python3 python3-pip nano -y
Library များ Install လုပ်ခြင်း Bot အလုပ်လုပ်ဖို့ လိုအပ်တဲ့ Python Library ၃ ခုကို သွင်းပါ။
pip3 install pyTelegramBotAPI python-dotenv requests
Project Folder နှင့် ဖိုင်များ တည်ဆောက်ခြင်း ဖိုင်တွေကို စနစ်တကျရှိအောင် folder တစ်ခုထဲမှာ ထည့်ပါမယ်။
mkdir ~/outline-bot && cd ~/outline-bot
.env ဖိုင်ဆောက်ခြင်း
nano .env
အောက်က စာတွေကို ပြင်ဆင်ပြီး ထည့် save ပါ
BOT_TOKEN=Telegram bot token ထည့်ပါ
SERVERS=SG-1:https://178.xxx.16.73:XXX57/LL.........(ယခုလို Outline api ထည့်ပါ),(serverများထပ်ထည့်လိုပါက ကော်မာခံ မိမိပေးလိုသောနာမည်ထည့်)SG-2:https://143.xxx.198.249:xxxxx/LLYTUJHG.........
DOMAINS=SG-1:outline.yourdomain.com,SG-2:sg2.another-domain.net
Ctrl+O enter Ctrl+X နှိပ်ပြီး save
outline_bot.py ဖိုင်ဆောက်ခြင်း
nano outline_bot.py
အောက်က စာများကူးထည့်ပါ
import os
import telebot
import requests
import re
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
from dotenv import load_dotenv
load_dotenv()
BOT_TOKEN = os.getenv('BOT_TOKEN')
ADMIN_ID = 5XXXXXX(မိမိ Telegram Id ထည့်ပါ)
bot = telebot.TeleBot(BOT_TOKEN)
# Servers နှင့် Domains စာရင်းများကို Dictionary ပြောင်းခြင်း
servers_raw = os.getenv('SERVERS').split(',')
SERVERS = {s.split(':')[0]: ":".join(s.split(':')[1:]) for s in servers_raw}
domains_raw = os.getenv('DOMAINS', '').split(',')
SERVER_DOMAINS = {d.split(':')[0]: d.split(':')[1] for d in domains_raw if ':' in d}
user_states = {}
def is_admin(chat_id):
return chat_id == ADMIN_ID
def bytes_to_gb(bytes_val):
return round(bytes_val / (1024**3), 2)
# IP ကို Domain နှင့် အစားထိုးပေးသည့် function
def replace_with_domain(access_url, server_name):
domain = SERVER_DOMAINS.get(server_name)
if domain:
return re.sub(r'@\[?([a-zA-Z0-9\.-]+)\]?:', f'@{domain}:', access_url)
return access_url
def get_server_markup(action):
markup = InlineKeyboardMarkup()
for name in SERVERS.keys():
markup.add(InlineKeyboardButton(name, callback_data=f"{action}:{name}"))
return markup
@bot.message_handler(commands=['start'])
def welcome(message):
if not is_admin(message.chat.id): return
bot.reply_to(message, "🌟 Multi-Server Outline Bot\nPrefix: 🇸🇬_Good_Speed_Server\n/newkey, /list, /del command များကို သုံးနိုင်ပါသည်။")
@bot.message_handler(commands=['newkey'])
def ask_newkey(message):
if not is_admin(message.chat.id): return
args = message.text.split()
if len(args) < 3:
bot.reply_to(message, "⚠️ format: `/newkey [Name] [GB]`")
return
user_states[message.chat.id] = {'name': args[1], 'gb': int(args[2])}
bot.send_message(message.chat.id, "ဘယ် Server မှာ Key ထုတ်မလဲ ရွေးပါ-", reply_markup=get_server_markup("create"))
@bot.message_handler(commands=['list'])
def ask_list(message):
if not is_admin(message.chat.id): return
bot.send_message(message.chat.id, "ဘယ် Server ရဲ့ စာရင်းကို ကြည့်မလဲ-", reply_markup=get_server_markup("list"))
@bot.message_handler(commands=['del'])
def ask_delete(message):
if not is_admin(message.chat.id): return
args = message.text.split()
if len(args) < 2:
bot.reply_to(message, "⚠️ format: `/del [ID]`")
return
user_states[message.chat.id] = {'del_id': args[1]}
bot.send_message(message.chat.id, f"ID {args[1]} ကို ဘယ် Server ကနေ ဖျက်မလဲ ရွေးပါ-", reply_markup=get_server_markup("confirm_del"))
@bot.callback_query_handler(func=lambda call: True)
def handle_query(call):
action, server_name = call.data.split(':')
api_url = SERVERS.get(server_name)
if action == "create":
state = user_states.get(call.message.chat.id)
if not state: return
# နာမည်ပေးစနစ်သစ်: 🇸🇬_Good_Speed_Server-[Name]
full_name = f"🇸🇬_Good_Speed_Server-{state['name']}"
bot.edit_message_text(f"⏳ {server_name} မှာ Key ထုတ်နေပါတယ်...", call.message.chat.id, call.message.message_id)
try:
bytes_limit = state['gb'] * 1024 * 1024 * 1024
res = requests.post(f"{api_url}/access-keys", verify=False).json()
k_id = res.get('id')
# Domain link ပြောင်းခြင်း
original_url = res.get('accessUrl')
domain_url = replace_with_domain(original_url, server_name)
requests.put(f"{api_url}/access-keys/{k_id}/name", data={'name': full_name}, verify=False)
requests.put(f"{api_url}/access-keys/{k_id}/data-limit", json={"limit": {"bytes": bytes_limit}}, verify=False)
final_link = f"{domain_url}#{full_name}"
bot.send_message(call.message.chat.id, f"✅ **Key Created!**\n🏰 Server: {server_name}\n👤 Name: {full_name}\n🆔 ID: {k_id}\n\n`{final_link}`", parse_mode='Markdown')
except Exception as e:
bot.send_message(call.message.chat.id, f"❌ Error: {e}")
elif action == "list":
bot.edit_message_text(f"📋 {server_name} စာရင်းယူနေပါတယ်...", call.message.chat.id, call.message.message_id)
try:
keys = requests.get(f"{api_url}/access-keys", verify=False).json()
usage = requests.get(f"{api_url}/metrics/transfer", verify=False).json().get('bytesTransferredByUserId', {})
report = f"🏰 **{server_name} Key List**\n\n"
total = 0
for k in keys.get('accessKeys', []):
u = usage.get(str(k.get('id')), 0)
total += u
d_url = replace_with_domain(k.get('accessUrl'), server_name)
report += f"🆔 {k.get('id')} | 👤 {k.get('name')}\n📊 {bytes_to_gb(u)} / {bytes_to_gb(k.get('dataLimit', {}).get('bytes', 0))} GB\n🔗 `{d_url}#{k.get('name')}`\n\n"
report += f"➖➖➖➖➖➖\n☁️ Total Server Usage: {bytes_to_gb(total)} GB"
bot.send_message(call.message.chat.id, report, parse_mode='Markdown')
except Exception as e:
bot.send_message(call.message.chat.id, f"❌ Error: {e}")
elif action == "confirm_del":
state = user_states.get(call.message.chat.id)
if not state: return
del_id = state['del_id']
bot.edit_message_text(f"🔍 {server_name} မှာ ID {del_id} ကို စစ်ဆေးနေပါတယ်...", call.message.chat.id, call.message.message_id)
try:
keys = requests.get(f"{api_url}/access-keys", verify=False).json()
usage = requests.get(f"{api_url}/metrics/transfer", verify=False).json().get('bytesTransferredByUserId', {})
target_key = next((k for k in keys.get('accessKeys', []) if str(k.get('id')) == str(del_id)), None)
if target_key:
confirm_msg = (f"⚠️ **Key ဖျက်ရန် သေချာပါသလား?**\n\n"
f"🏰 Server: {server_name}\n"
f"👤 Name: {target_key.get('name')}\n"
f"📊 Usage: {bytes_to_gb(usage.get(str(del_id), 0))} GB\n\n"
f"ဖျက်မည်ဆိုပါက 'Confirm Delete' ကို နှိပ်ပါ။")
markup = InlineKeyboardMarkup()
markup.add(InlineKeyboardButton("✅ Confirm Delete", callback_data=f"final_del:{server_name}"),
InlineKeyboardButton("❌ Cancel", callback_data="cancel_del:x"))
bot.send_message(call.message.chat.id, confirm_msg, reply_markup=markup, parse_mode='Markdown')
else:
bot.send_message(call.message.chat.id, f"❌ ID {del_id} ကို {server_name} မှာ ရှာမတွေ့ပါ။")
except Exception as e:
bot.send_message(call.message.chat.id, f"❌ Error: {e}")
elif action == "final_del":
state = user_states.get(call.message.chat.id)
if not state: return
del_id = state['del_id']
try:
res = requests.delete(f"{api_url}/access-keys/{del_id}", verify=False)
if res.status_code == 204:
bot.edit_message_text(f"🗑️ {server_name} မှ ID {del_id} ကို ဖျက်ပြီးပါပြီ။", call.message.chat.id, call.message.message_id)
else:
bot.edit_message_text("❌ ဖျက်လို့ မရနိုင်ပါ။", call.message.chat.id, call.message.message_id)
except Exception as e:
bot.send_message(call.message.chat.id, f"❌ Error: {e}")
elif action == "cancel_del":
bot.edit_message_text("❌ လုပ်ဆောင်ချက်ကို ပယ်ဖျက်လိုက်ပါပြီ။", call.message.chat.id, call.message.message_id)
bot.polling()
Systemd Service အဖြစ် သတ်မှတ်ခြင်း (Auto-run) VPS ပိတ်သွားရင်တောင် Bot ပြန်ပွင့်လာဖို့အတွက် Service ဖိုင် ဆောက်ရပါမယ်။
sudo nano /etc/systemd/system/outlinebot.service
အောက်က code များကူးထည့်ပါ (မိမိတည်ဆောက်ထားတဲ့ bot file location နဲ့ နာမည် တူရပါမယ်
[Unit] Description=Outline Multi-Server Bot After=network.target [Service] User=root WorkingDirectory=/root/outline-bot ExecStart=/usr/bin/python3 /root/outline-bot/outline_bot.py Restart=always RestartSec=5 [Install] WantedBy=multi-user.targetCtrl+O enter Ctrl+X နှိပ်ပြီး save
Service ကို စတင်ခြင်း:
sudo systemctl daemon-reload sudo systemctl enable outlinebot sudo systemctl start outlinebot
Goal: Bot မှာ start နှပ်ပြီး အလုပ်မလုပ်စမ်းသက်လို့ရပါပြီ
သတိ: server အသစ်ထည့်တိုင်း .env မှာ outline api ထပ်ထည့်ဖို့လိုပါတယ်။ .env ပြင်ပြီးတိုင်း bot ကို restart ပြန်လုပ်ပေးပါ