├── requirements.txt
├── config.json
├── _bot.py
├── utils
├── password_generator.py
├── set_root_password_script.py
├── localizer.py
└── db.py
├── main.py
├── modules
├── __init__.py
├── delete_account.py
├── manage_droplets.py
├── manage_accounts.py
├── batch_test_delete_accounts.py
├── start.py
├── account_detail.py
├── batch_test_accounts.py
├── add_account.py
├── list_droplets.py
├── droplet_detail.py
├── droplet_actions.py
└── create_droplet.py
├── README.MD
├── bot.py
└── start
/requirements.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FighterTunnel/DigitalOcean-TeleBot/HEAD/requirements.txt
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "BOT": {
3 | "NAME": "NAMA STORE",
4 | "TOKEN": "BOT TOKEN",
5 | "ADMINS": [ID TELEGRAM
6 | ]
7 | }
8 | }
--------------------------------------------------------------------------------
/_bot.py:
--------------------------------------------------------------------------------
1 | from os import environ
2 |
3 | import telebot
4 |
5 | bot_token = environ.get('bot_token')
6 |
7 | bot = telebot.TeleBot(token=bot_token)
8 |
--------------------------------------------------------------------------------
/utils/password_generator.py:
--------------------------------------------------------------------------------
1 | from random import choice
2 |
3 |
4 | def password_generator():
5 | a = 'QWERTYUIOPASDFGHJKLZXCVBNM'
6 | b = 'qwertyuiopasdfghjklzxcvbnm'
7 | c = '1234567890'
8 |
9 | p = ''
10 | for i in range(3):
11 | p += choice(a)
12 | p += choice(b)
13 | p += choice(c)
14 |
15 | return p
16 |
--------------------------------------------------------------------------------
/utils/set_root_password_script.py:
--------------------------------------------------------------------------------
1 | def set_root_password_script(password: str):
2 | return '#!/bin/bash\n' \
3 | f'echo root:{password} | sudo chpasswd root\n' \
4 | 'sudo sed -i "s/^.*PermitRootLogin.*/PermitRootLogin yes/g" /etc/ssh/sshd_config\n' \
5 | 'sudo sed -i "s/^.*PasswordAuthentication.*/PasswordAuthentication yes/g" /etc/ssh/sshd_config\n' \
6 | 'sudo systemctl restart sshd\n'
7 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | def parse_config():
2 | import json
3 | from os import environ
4 |
5 | config = json.load(open('config.json', 'r', encoding='utf-8'))
6 | environ['bot_name'] = config['BOT']['NAME']
7 | environ['bot_token'] = config['BOT']['TOKEN']
8 | environ['bot_admins'] = json.dumps(config['BOT']['ADMINS'])
9 |
10 |
11 | def start_bot():
12 | from bot import bot
13 |
14 | bot.polling(none_stop=True)
15 |
16 |
17 | if __name__ == '__main__':
18 | parse_config()
19 | start_bot()
20 |
--------------------------------------------------------------------------------
/modules/__init__.py:
--------------------------------------------------------------------------------
1 | from .start import start
2 | from .add_account import add_account
3 | from .manage_accounts import manage_accounts
4 | from .batch_test_accounts import batch_test_accounts
5 | from .account_detail import account_detail
6 | from .manage_droplets import manage_droplets
7 | from .delete_account import delete_account
8 | from .batch_test_delete_accounts import batch_test_delete_accounts
9 | from .create_droplet import create_droplet
10 | from .list_droplets import list_droplets
11 | from .droplet_detail import droplet_detail
12 | from .droplet_actions import droplet_actions
13 |
--------------------------------------------------------------------------------
/utils/localizer.py:
--------------------------------------------------------------------------------
1 | def localize_region(slug: str):
2 | regions = [
3 | {'slug': 'nyc1', 'name': 'New York 1'}, {'slug': 'nyc2', 'name': 'New York 2'}, {'slug': 'nyc3', 'name': 'New York 3'},
4 | {'slug': 'sfo1', 'name': 'San Fransisco 1'}, {'slug': 'sfo2', 'name': 'San Fransisco 2'}, {'slug': 'sfo3', 'name': 'San Fransisco 3'},
5 | {'slug': 'ams2', 'name': 'Amsterdam 2'}, {'slug': 'ams3', 'name': 'Amsterdam 3'},
6 | {'slug': 'sgp1', 'name': 'Singapura 1'}, {'slug': 'lon1', 'name': 'London 1'},
7 | {'slug': 'fra1', 'name': 'Perancis 1'}, {'slug': 'blr1', 'name': 'Bandolore 1'},
8 | {'slug': 'tor1', 'name': 'Toronto 1'},
9 | ]
10 |
11 | for region in regions:
12 | if region['slug'] == slug:
13 | return region['name']
14 |
15 | return slug
16 |
--------------------------------------------------------------------------------
/modules/delete_account.py:
--------------------------------------------------------------------------------
1 | from telebot.types import CallbackQuery
2 |
3 | from _bot import bot
4 | from utils.db import AccountsDB
5 |
6 |
7 | def delete_account(call: CallbackQuery, data: dict):
8 | doc_id = data['doc_id'][0]
9 |
10 | try:
11 | AccountsDB().remove(doc_id=doc_id)
12 | except Exception as e:
13 | bot.edit_message_text(
14 | text=f'{call.message.html_text}\n\n'
15 | f'⚠️ Terjadi kesalahan saat menghapus akun: {str(e)}',
16 | chat_id=call.from_user.id,
17 | message_id=call.message.message_id,
18 | parse_mode='HTML'
19 | )
20 | return
21 |
22 | bot.edit_message_text(
23 | text=f'{call.message.html_text}\n\n'
24 | f'✅ Akun berhasil dihapus',
25 | chat_id=call.from_user.id,
26 | message_id=call.message.message_id,
27 | parse_mode='HTML'
28 | )
29 |
--------------------------------------------------------------------------------
/utils/db.py:
--------------------------------------------------------------------------------
1 | from tinydb import TinyDB, where
2 | from datetime import datetime
3 |
4 | db_file = 'db.json'
5 |
6 |
7 | class AccountsDB:
8 |
9 | def __init__(self):
10 | db = TinyDB(db_file)
11 | self.accounts = db.table('Accounts')
12 |
13 | def save(self, email: str, token: str, remarks: str = ''):
14 | email = email.strip()
15 | token = token.strip()
16 | date = datetime.today().strftime('%Y-%m-%d')
17 |
18 | if self.accounts.get(where('token') == token):
19 | raise Exception('Token Exists')
20 | else:
21 | self.accounts.insert({
22 | 'email': email,
23 | 'token': token,
24 | 'remarks': remarks,
25 | 'date': date
26 | })
27 |
28 | def all(self):
29 | return self.accounts.all()
30 |
31 | def get(self, doc_id: int):
32 | return self.accounts.get(doc_id=int(doc_id))
33 |
34 | def remove(self, doc_id: int):
35 | self.accounts.remove(doc_ids=[int(doc_id)])
36 |
--------------------------------------------------------------------------------
/modules/manage_droplets.py:
--------------------------------------------------------------------------------
1 | from typing import Union
2 |
3 | from telebot.types import (
4 | Message,
5 | CallbackQuery,
6 | InlineKeyboardMarkup,
7 | InlineKeyboardButton,
8 | )
9 |
10 | from _bot import bot
11 | from utils.db import AccountsDB
12 |
13 |
14 | def manage_droplets(d: Union[Message, CallbackQuery]):
15 | t = 'Manajer VPS\n\n'
16 | markup = InlineKeyboardMarkup()
17 |
18 | accounts = AccountsDB().all()
19 |
20 | if len(accounts) == 0:
21 | markup.row(
22 | InlineKeyboardButton(
23 | text='➕ Tambah Akun',
24 | callback_data='add_account'
25 | )
26 | )
27 |
28 | bot.send_message(
29 | text=f'{t}'
30 | f'⚠️ Tidak ada akun yang tersedia',
31 | chat_id=d.from_user.id,
32 | reply_markup=markup,
33 | parse_mode='HTML'
34 | )
35 | return
36 |
37 | for account in accounts:
38 | markup.add(
39 | InlineKeyboardButton(
40 | text=f'📧 {account["email"]}',
41 | callback_data=f'list_droplets?doc_id={account.doc_id}'
42 | )
43 | )
44 |
45 | bot.send_message(
46 | text=f'{t}'
47 | f'🔢 Pilih akun yang ingin dikelola',
48 | chat_id=d.from_user.id,
49 | parse_mode='HTML',
50 | reply_markup=markup
51 | )
52 |
--------------------------------------------------------------------------------
/modules/manage_accounts.py:
--------------------------------------------------------------------------------
1 | from typing import Union
2 |
3 | from telebot.types import (
4 | Message,
5 | CallbackQuery,
6 | InlineKeyboardMarkup,
7 | InlineKeyboardButton,
8 | )
9 |
10 | from _bot import bot
11 | from utils.db import AccountsDB
12 |
13 |
14 | def manage_accounts(d: Union[Message, CallbackQuery]):
15 | t = 'Manajer Akun\n\n'
16 | markup = InlineKeyboardMarkup()
17 |
18 | accounts = AccountsDB().all()
19 |
20 | if len(accounts) == 0:
21 | t += '⚠️ Tidak ada akun yang tersedia'
22 | markup.row(
23 | InlineKeyboardButton(
24 | text='➕ Tambahkan Akun Baru',
25 | callback_data='add_account'
26 | )
27 | )
28 |
29 | bot.send_message(
30 | text=t,
31 | chat_id=d.from_user.id,
32 | reply_markup=markup,
33 | parse_mode='HTML'
34 | )
35 | return
36 |
37 | markup.row(
38 | InlineKeyboardButton(
39 | text='🛠️ Uji Batch Akun',
40 | callback_data='batch_test_accounts'
41 | )
42 | )
43 |
44 | for account in accounts:
45 | markup.row(
46 | InlineKeyboardButton(
47 | text=f'📧 {account.get("email", "error")}',
48 | callback_data=f'account_detail?doc_id={account.doc_id}'
49 | )
50 | )
51 |
52 | bot.send_message(
53 | text=t,
54 | chat_id=d.from_user.id,
55 | reply_markup=markup,
56 | parse_mode='HTML'
57 | )
58 |
--------------------------------------------------------------------------------
/modules/batch_test_delete_accounts.py:
--------------------------------------------------------------------------------
1 | from telebot.types import CallbackQuery
2 |
3 | import digitalocean
4 | from digitalocean import DataReadError
5 |
6 | from _bot import bot
7 | from utils.db import AccountsDB
8 |
9 |
10 | def batch_test_delete_accounts(call: CallbackQuery):
11 | bot.edit_message_text(
12 | text=f'{call.message.html_text}\n\n'
13 | f'🔄 Menghapus Akun Gagal...',
14 | chat_id=call.from_user.id,
15 | message_id=call.message.message_id,
16 | parse_mode='HTML'
17 | )
18 |
19 | accounts_db = AccountsDB()
20 |
21 | accounts = accounts_db.all()
22 | for account in accounts:
23 | try:
24 | digitalocean.Balance().get_object(api_token=account['token'])
25 | except DataReadError:
26 | try:
27 | accounts_db.remove(doc_id=account.doc_id)
28 | except Exception as e:
29 | bot.edit_message_text(
30 | text=f'{call.message.html_text}\n\n'
31 | f'⚠️ Kesalahan saat menghapus akun: {str(e)}',
32 | chat_id=call.from_user.id,
33 | message_id=call.message.message_id,
34 | parse_mode='HTML'
35 | )
36 | return
37 |
38 | bot.edit_message_text(
39 | text=f'{call.message.html_text}\n\n'
40 | f'✅ Akun gagal telah dihapus',
41 | chat_id=call.from_user.id,
42 | message_id=call.message.message_id,
43 | parse_mode='HTML'
44 | )
45 |
--------------------------------------------------------------------------------
/modules/start.py:
--------------------------------------------------------------------------------
1 | from os import environ
2 |
3 | from telebot.types import (
4 | Message,
5 | InlineKeyboardMarkup,
6 | InlineKeyboardButton,
7 | )
8 |
9 | from _bot import bot
10 |
11 | bot_name = environ.get('bot_name', 'Asisten DigitalOcean')
12 |
13 |
14 | def start(d: Message):
15 | markup = InlineKeyboardMarkup(row_width=2)
16 | markup.add(
17 | InlineKeyboardButton(
18 | text='➕ Tambah akun',
19 | callback_data='add_account'
20 | ),
21 | InlineKeyboardButton(
22 | text='⚙️ Kelola akun',
23 | callback_data='manage_accounts'
24 | ),
25 | InlineKeyboardButton(
26 | text='💧 Buat droplets',
27 | callback_data='create_droplet'
28 | ),
29 | InlineKeyboardButton(
30 | text='🛠️ Kelola droplets',
31 | callback_data='manage_droplets'
32 | ),
33 | )
34 | t = f'Selamat Datang {bot_name} 👋\n\n' \
35 | 'Anda dapat mengelola akun DigitalOcean, membuat instance, dll.\n\n' \
36 | 'Perintah cepat:\n' \
37 | '/start - Memulai bot\n' \
38 | '/add_do - Tambah akun\n' \
39 | '/sett_do - Kelola akun\n' \
40 | '/bath_do - Uji batch akun\n' \
41 | '/add_vps - Buat droplets\n' \
42 | '/sett_vps - Kelola droplets\n' \
43 | ' \n' \
44 | 'Dev: @yha_bot 👨💻\n' \
45 | 'Support: @fightertunnell 🛡️'
46 | bot.send_message(
47 | text=t,
48 | chat_id=d.from_user.id,
49 | parse_mode='HTML',
50 | reply_markup=markup
51 | )
52 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # ☁ `Digitalocean-bot`
2 |
3 | 
4 |
5 | ### 🚚 Telegram Bot untuk Digital Ocean
6 |
7 | ### 🔖 Fungsi Utama
8 |
9 | + Mengelola akun Digital Ocean, memeriksa saldo akun, dan melakukan pengujian akun dalam batch dengan cepat dan akurat.
10 | + Membuat dan mengelola mesin virtual dengan mudah dan efisien, memberikan Anda kendali penuh atas infrastruktur cloud Anda.
11 |
12 | ### 🪂 Lingkungan
13 |
14 | + Bot ini dirancang untuk bekerja di berbagai lingkungan, memastikan fleksibilitas dan kompatibilitas yang tinggi.
15 |
16 | ### 😻 Tahapan Penggunaan
17 |
18 | 1. **Clone Proyek**: `git clone` proyek ini ke lokal untuk memulai petualangan Anda.
19 | 2. **Instal Ketergantungan**: Jalankan `pip3 install -r requirements.txt` untuk menginstal ketergantungan yang diperlukan dan pastikan semuanya siap.
20 | 3. **Buat Bot**: Buat bot baru melalui [@botfather](https://t.me/botfather) dan catat `token` yang diberikan untuk menghubungkan bot Anda.
21 | 4. **Edit Konfigurasi**: Edit file `config.json` untuk mengisi konfigurasi yang relevan dengan akun Anda dan sesuaikan dengan kebutuhan Anda.
22 | 5. **Jalankan Bot**: Jalankan `python3 main.py` untuk memulai bot dan nikmati kemudahan pengelolaan Digital Ocean Anda dengan antarmuka yang ramah pengguna!
23 |
24 | ### 🤖 Identitas Bot
25 |
26 | + **Nama Bot**: DigitalOcean Manager Bot
27 | + **Deskripsi**: Bot ini membantu Anda mengelola akun DigitalOcean, memeriksa saldo, membuat dan mengelola droplet, serta memberikan informasi detail tentang akun dan droplet Anda.
28 | + **Versi**: 1.0.0
29 | + **Bahasa Pemrograman**: Python
30 | + **Perpustakaan Utama**: `pyTelegramBotAPI`, `digitalocean`
31 | + **Lisensi**: MIT License
32 |
--------------------------------------------------------------------------------
/modules/account_detail.py:
--------------------------------------------------------------------------------
1 | from telebot.types import (
2 | CallbackQuery,
3 | InlineKeyboardMarkup,
4 | InlineKeyboardButton,
5 | )
6 |
7 | import digitalocean
8 | from digitalocean import DataReadError
9 |
10 | from _bot import bot
11 | from utils.db import AccountsDB
12 |
13 |
14 | def account_detail(call: CallbackQuery, data: dict):
15 | doc_id = data['doc_id'][0]
16 | t = 'ℹ️ Informasi Akun\n\n'
17 |
18 | account = AccountsDB().get(doc_id=doc_id)
19 |
20 | msg = bot.send_message(
21 | text=f'{t}'
22 | f'📧 Email: {account["email"]}\n\n'
23 | f'🔄 Mendapatkan informasi...',
24 | chat_id=call.from_user.id,
25 | parse_mode='HTML'
26 | )
27 |
28 | t += f'📧 Email: {account["email"]}\n' \
29 | f'💬 Komentar: {account["remarks"]}\n' \
30 | f'📅 Tanggal Ditambahkan: {account["date"]}\n' \
31 | f'🔑 Token: {account["token"]}\n\n'
32 | markup = InlineKeyboardMarkup()
33 | markup.row(
34 | InlineKeyboardButton(
35 | text='🗑️ Hapus Akun',
36 | callback_data=f'delete_account?doc_id={account.doc_id}'
37 | )
38 | )
39 |
40 | try:
41 | account_balance = digitalocean.Balance().get_object(api_token=account['token'])
42 |
43 | t += f'💰 Saldo Akun: {account_balance.account_balance}\n' \
44 | f'📊 Penggunaan Bulan Ini: {account_balance.month_to_date_usage}\n' \
45 | f'📅 Tanggal Penagihan: {account_balance.generated_at.split("T")[0]}'
46 |
47 | except DataReadError as e:
48 | t += f'⚠️ Kesalahan Mendapatkan Tagihan: {e}'
49 | except Exception as e:
50 | t += f'⚠️ Kesalahan: {e}'
51 |
52 | bot.edit_message_text(
53 | text=t,
54 | chat_id=call.from_user.id,
55 | message_id=msg.message_id,
56 | parse_mode='HTML',
57 | reply_markup=markup
58 | )
59 |
--------------------------------------------------------------------------------
/bot.py:
--------------------------------------------------------------------------------
1 | import json
2 | import logging
3 | import traceback
4 | from os import environ
5 | from typing import Union
6 | import urllib.parse as urlparse
7 | from urllib.parse import parse_qs
8 |
9 | import telebot
10 | from telebot.types import CallbackQuery, Message
11 |
12 | from _bot import bot
13 | # noinspection PyUnresolvedReferences
14 | from modules import *
15 |
16 | bot_admins = json.loads(environ.get('bot_admins'))
17 |
18 | logger = telebot.logger
19 | telebot.logger.setLevel(logging.INFO)
20 |
21 | command_dict = {
22 | '/start': 'start',
23 |
24 | '/add_do': 'add_account',
25 | '/sett_do': 'manage_accounts',
26 | '/bath_do': 'batch_test_accounts',
27 |
28 | '/add_vps': 'create_droplet',
29 | '/sett_vps': 'manage_droplets',
30 | }
31 |
32 |
33 | @bot.message_handler(content_types=['text'])
34 | def text_handler(m: Message):
35 | try:
36 | logger.info(m)
37 |
38 | if m.from_user.id not in bot_admins:
39 | bot.send_message(
40 | text='🚫 Anda tidak memiliki izin untuk menggunakan bot ini.',
41 | chat_id=m.from_user.id
42 | )
43 | return
44 |
45 | if m.text in command_dict.keys():
46 | globals()[command_dict[m.text]](m)
47 |
48 | except Exception as e:
49 | traceback.print_exc()
50 | handle_exception(m, e)
51 |
52 |
53 | @bot.callback_query_handler(func=lambda call: True)
54 | def callback_query_handler(call: CallbackQuery):
55 | try:
56 | logger.info(call)
57 |
58 | if call.from_user.id not in bot_admins:
59 | bot.send_message(
60 | text='🚫 Anda tidak memiliki izin untuk menggunakan bot ini.',
61 | chat_id=call.from_user.id
62 | )
63 | return
64 |
65 | callback_data = urlparse.urlparse(call.data)
66 | func_name = callback_data.path
67 | data = parse_qs(callback_data.query)
68 | if func_name in globals():
69 | args = [call]
70 | if len(data.keys()) > 0:
71 | args.append(data)
72 |
73 | globals()[func_name](*args)
74 |
75 | except Exception as e:
76 | traceback.print_exc()
77 | handle_exception(call, e)
78 |
79 |
80 | def handle_exception(d: Union[Message, CallbackQuery], e):
81 | bot.send_message(
82 | text=f'❌ Terjadi kesalahan\n'
83 | f'{e}',
84 | chat_id=d.from_user.id,
85 | parse_mode='HTML'
86 | )
87 |
--------------------------------------------------------------------------------
/modules/batch_test_accounts.py:
--------------------------------------------------------------------------------
1 | import json
2 | from typing import Union
3 |
4 | from telebot.types import (
5 | Message,
6 | CallbackQuery,
7 | InlineKeyboardMarkup,
8 | InlineKeyboardButton,
9 | )
10 |
11 | import digitalocean
12 | from digitalocean import DataReadError
13 |
14 | from _bot import bot
15 | from utils.db import AccountsDB
16 |
17 |
18 | def batch_test_accounts(d: Union[Message, CallbackQuery]):
19 | t = '🔍 Akun Tes Batch\n\n'
20 | markup = InlineKeyboardMarkup()
21 |
22 | msg = bot.send_message(
23 | text=f'{t}'
24 | f'🔄 Sedang Menguji...',
25 | chat_id=d.from_user.id,
26 | parse_mode='HTML',
27 | )
28 |
29 | accounts = AccountsDB().all()
30 | checked_accounts = []
31 | failed_accounts = []
32 |
33 | for account in accounts:
34 | try:
35 | account_balance = digitalocean.Balance().get_object(api_token=account['token'])
36 | account_balance.email = account['email']
37 |
38 | checked_accounts.append(account_balance)
39 |
40 | except DataReadError:
41 | failed_accounts.append(account['email'])
42 | except Exception as e:
43 | bot.edit_message_text(
44 | text=f'{t}'
45 | f'⚠️ Kesalahan saat memeriksa akun: {str(e)}',
46 | chat_id=d.from_user.id,
47 | message_id=msg.message_id,
48 | parse_mode='HTML'
49 | )
50 | return
51 |
52 | t += f'Total {len(accounts)} Akun\n\n'
53 |
54 | if checked_accounts:
55 | t += f'✅ Tes Berhasil {len(checked_accounts)} akun:\n'
56 | for account_balance in checked_accounts:
57 | t += f'{account_balance.email} | Saldo: {account_balance.account_balance}\n'
58 | t += '\n'
59 |
60 | if failed_accounts:
61 | t += f'❌ Tes Gagal {len(failed_accounts)} akun:\n'
62 | for email in failed_accounts:
63 | t += f'{email}\n'
64 | markup.add(
65 | InlineKeyboardButton(
66 | text='🗑️ Hapus Akun Gagal',
67 | callback_data=json.dumps({
68 | 't': 'batch_test_delete_accounts'
69 | })
70 | )
71 | )
72 |
73 | bot.edit_message_text(
74 | text=t,
75 | chat_id=d.from_user.id,
76 | message_id=msg.message_id,
77 | parse_mode='HTML',
78 | reply_markup=markup
79 | )
80 |
--------------------------------------------------------------------------------
/start:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | while true; do
3 | read -p "Masukkan bot token: " bot_token
4 | if [[ -n "$bot_token" ]]; then
5 | break
6 | else
7 | echo "Bot token tidak boleh kosong. Silakan coba lagi."
8 | fi
9 | done
10 |
11 | while true; do
12 | read -p "Masukkan bot admin ID: " bot_admin_id
13 | if [[ "$bot_admin_id" =~ ^[0-9]+$ ]]; then
14 | break
15 | else
16 | echo "Bot admin ID harus berupa angka. Silakan coba lagi."
17 | fi
18 | done
19 |
20 | while true; do
21 | read -p "Masukkan nama store: " nama_store
22 | if [[ -n "$nama_store" ]]; then
23 | break
24 | else
25 | echo "Nama store tidak boleh kosong. Silakan coba lagi."
26 | fi
27 | done
28 |
29 | apt update -y
30 |
31 | if ! command -v python3 &> /dev/null
32 | then
33 | apt install python3 -y
34 | else
35 | echo "python3 sudah terinstal"
36 | fi
37 |
38 | if ! command -v pip3 &> /dev/null
39 | then
40 | apt install python3-pip -y
41 | else
42 | echo "pip3 sudah terinstal"
43 | fi
44 |
45 | if [ ! -d "/root/DigitalOcean-TeleBot" ]; then
46 | git clone https://github.com/FighterTunnel/DigitalOcean-TeleBot.git
47 | else
48 | echo "Repository sudah ada"
49 | fi
50 |
51 | if [ -f "/root/DigitalOcean-TeleBot/requirements.txt" ]; then
52 | pip3 install -r /root/DigitalOcean-TeleBot/requirements.txt
53 | else
54 | echo "File requirements.txt tidak ditemukan"
55 | fi
56 |
57 |
58 | SERVICE_NAME="do"
59 | SERVICE_FILE="/etc/systemd/system/$SERVICE_NAME.service"
60 | if [ -f "/root/DigitalOcean-TeleBot/config.json" ]; then
61 | rm /root/DigitalOcean-TeleBot/config.json
62 | fi
63 |
64 | cat < /root/DigitalOcean-TeleBot/config.json
65 | {
66 | "BOT": {
67 | "NAME": "$nama_store",
68 | "TOKEN": "$bot_token",
69 | "ADMINS": [$bot_admin_id]
70 | }
71 | }
72 | EOT
73 | if [ ! -f "$SERVICE_FILE" ]; then
74 | echo "[Unit]
75 | Description=My Python Service
76 | After=network.target
77 |
78 | [Service]
79 | ExecStart=/usr/bin/python3 /root/DigitalOcean-TeleBot/main.py
80 | WorkingDirectory=/root/DigitalOcean-TeleBot
81 | StandardOutput=inherit
82 | StandardError=inherit
83 | Restart=always
84 | User=root
85 |
86 | [Install]
87 | WantedBy=multi-user.target" > $SERVICE_FILE
88 |
89 |
90 | systemctl daemon-reload
91 |
92 |
93 | systemctl enable $SERVICE_NAME
94 |
95 |
96 | systemctl start $SERVICE_NAME
97 |
98 |
99 | systemctl restart $SERVICE_NAME
100 | else
101 | echo "Service $SERVICE_NAME sudah ada"
102 | fi
103 |
104 | echo "Service $SERVICE_NAME telah diinstal"
105 |
--------------------------------------------------------------------------------
/modules/add_account.py:
--------------------------------------------------------------------------------
1 | from typing import Union
2 |
3 | from telebot.types import (
4 | Message,
5 | CallbackQuery
6 | )
7 |
8 | import digitalocean
9 | from digitalocean import DataReadError
10 |
11 | from _bot import bot
12 | from utils.db import AccountsDB
13 | from .start import start
14 |
15 |
16 | def add_account(d: Union[Message, CallbackQuery]):
17 | t = '🔑 Tambahkan Akun DigitalOcean\n\n' \
18 | 'Masukkan Token DigitalOcean Ambil Disini perhatikan dalam copy paste\n\n' \
19 | 'Contoh:\n' \
20 | 'token123:Komentarxxx\n' \
21 | 'token345\n\n' \
22 | '/cancel untuk membatalkan'
23 |
24 | msg = bot.send_message(
25 | text=t,
26 | chat_id=d.from_user.id,
27 | parse_mode='HTML',
28 | disable_web_page_preview=True
29 | )
30 |
31 | bot.register_next_step_handler(msg, add_account_next_step_handler)
32 |
33 |
34 | def add_account_next_step_handler(m: Message):
35 | if m.text == '/cancel':
36 | start(m)
37 | return
38 |
39 | msg = bot.send_message(
40 | text='🔄 Menambahkan akun...',
41 | chat_id=m.from_user.id
42 | )
43 |
44 | accounts = m.text.split('\n')
45 | added_accounts = []
46 | failed_accounts = []
47 |
48 | for account in accounts:
49 | if ':' in account:
50 | token = account.split(':')[0]
51 | remarks = account.split(':')[1]
52 | else:
53 | token = account
54 | remarks = ''
55 |
56 | try:
57 | email = digitalocean.Account().get_object(
58 | api_token=token
59 | ).email
60 |
61 | AccountsDB().save(
62 | email=email,
63 | token=token,
64 | remarks=remarks
65 | )
66 |
67 | added_accounts.append(email)
68 |
69 | except DataReadError:
70 | failed_accounts.append(account)
71 | except Exception as e:
72 | bot.edit_message_text(
73 | text=f'⚠️ Kesalahan saat menambahkan akun: {str(e)}',
74 | chat_id=m.from_user.id,
75 | message_id=msg.message_id,
76 | parse_mode='HTML'
77 | )
78 | return
79 |
80 | t = f'📊 Total {len(accounts)} akun\n\n'
81 |
82 | if added_accounts:
83 | t += f'✅ Berhasil menambahkan {len(added_accounts)} akun:\n'
84 | for added_account in added_accounts:
85 | t += f'{added_account}\n'
86 | t += '\n'
87 |
88 | if failed_accounts:
89 | t += f'❌ Gagal menambahkan {len(failed_accounts)} akun:\n'
90 | for failed_account in failed_accounts:
91 | t += f'{failed_account}\n'
92 |
93 | bot.edit_message_text(
94 | text=t,
95 | chat_id=m.from_user.id,
96 | message_id=msg.message_id,
97 | parse_mode='HTML'
98 | )
99 |
--------------------------------------------------------------------------------
/modules/list_droplets.py:
--------------------------------------------------------------------------------
1 | from telebot.types import (
2 | CallbackQuery,
3 | InlineKeyboardMarkup,
4 | InlineKeyboardButton,
5 | )
6 |
7 | import digitalocean
8 |
9 | from _bot import bot
10 | from utils.db import AccountsDB
11 | from utils.localizer import localize_region
12 |
13 |
14 | def list_droplets(call: CallbackQuery, data: dict):
15 | doc_id = data['doc_id'][0]
16 | t = '🔧 VPS Manager\n\n'
17 |
18 | try:
19 | account = AccountsDB().get(doc_id=doc_id)
20 | except Exception as e:
21 | bot.edit_message_text(
22 | text=f'{t}'
23 | '⚠️ Kesalahan saat mengambil akun: '
24 | f'{str(e)}',
25 | chat_id=call.from_user.id,
26 | message_id=call.message.message_id,
27 | parse_mode='HTML'
28 | )
29 | return
30 |
31 | bot.edit_message_text(
32 | text=f'{t}'
33 | f'👤 Akun: {account["email"]}\n\n'
34 | '📄 Detail VPS...',
35 | chat_id=call.from_user.id,
36 | message_id=call.message.message_id,
37 | parse_mode='HTML'
38 | )
39 |
40 | try:
41 | droplets = digitalocean.Manager(token=account['token']).get_all_droplets()
42 | except Exception as e:
43 | bot.edit_message_text(
44 | text=f'{t}'
45 | f'👤 Akun: {account["email"]}\n\n'
46 | '⚠️ Kesalahan saat mengambil droplets: '
47 | f'{str(e)}',
48 | chat_id=call.from_user.id,
49 | message_id=call.message.message_id,
50 | parse_mode='HTML'
51 | )
52 | return
53 |
54 | markup = InlineKeyboardMarkup()
55 |
56 | if len(droplets) == 0:
57 | markup.add(
58 | InlineKeyboardButton(
59 | text='➕ Buat instance',
60 | callback_data=f'create_droplet?nf=select_region&doc_id={account.doc_id}'
61 | )
62 | )
63 |
64 | bot.edit_message_text(
65 | text=f'{t}'
66 | f'👤 Akun: {account["email"]}\n\n'
67 | '⚠️ Tidak ada instance',
68 | chat_id=call.from_user.id,
69 | message_id=call.message.message_id,
70 | parse_mode='HTML',
71 | reply_markup=markup
72 | )
73 | return
74 |
75 | for droplet in droplets:
76 | markup.row(
77 | InlineKeyboardButton(
78 | text=f'{droplet.name} ({localize_region(droplet.region["slug"])}) ({droplet.size_slug})',
79 | callback_data=f'droplet_detail?doc_id={account.doc_id}&droplet_id={droplet.id}'
80 | )
81 | )
82 |
83 | bot.edit_message_text(
84 | text=f'{t}'
85 | f'👤 Akun: {account["email"]}\n\n'
86 | '🔢 Pilih instance',
87 | chat_id=call.from_user.id,
88 | message_id=call.message.message_id,
89 | parse_mode='HTML',
90 | reply_markup=markup
91 | )
92 |
--------------------------------------------------------------------------------
/modules/droplet_detail.py:
--------------------------------------------------------------------------------
1 | from telebot.types import (
2 | CallbackQuery,
3 | InlineKeyboardMarkup,
4 | InlineKeyboardButton,
5 | )
6 |
7 | import digitalocean
8 |
9 | from _bot import bot
10 | from utils.db import AccountsDB
11 | from utils.localizer import localize_region
12 |
13 |
14 | def droplet_detail(call: CallbackQuery, data: dict):
15 | doc_id = data['doc_id'][0]
16 | droplet_id = data['droplet_id'][0]
17 | t = 'Informasi Server\n\n'
18 |
19 | try:
20 | account = AccountsDB().get(doc_id=doc_id)
21 | except Exception as e:
22 | bot.edit_message_text(
23 | text=f'{t}'
24 | '⚠️ Kesalahan saat mengambil akun: '
25 | f'{str(e)}',
26 | chat_id=call.from_user.id,
27 | message_id=call.message.message_id,
28 | parse_mode='HTML'
29 | )
30 | return
31 |
32 | bot.edit_message_text(
33 | text=f'{t}'
34 | f'Akun: {account["email"]}\n\n'
35 | 'Mengambil informasi instan...',
36 | chat_id=call.from_user.id,
37 | message_id=call.message.message_id,
38 | parse_mode='HTML'
39 | )
40 |
41 | try:
42 | droplet = digitalocean.Droplet().get_object(
43 | api_token=account['token'],
44 | droplet_id=droplet_id
45 | )
46 | except Exception as e:
47 | bot.edit_message_text(
48 | text=f'{t}'
49 | f'Akun: {account["email"]}\n\n'
50 | '⚠️ Kesalahan saat mengambil informasi droplet: '
51 | f'{str(e)}',
52 | chat_id=call.from_user.id,
53 | message_id=call.message.message_id,
54 | parse_mode='HTML'
55 | )
56 | return
57 | markup = InlineKeyboardMarkup()
58 | markup.row(
59 | InlineKeyboardButton(
60 | text='🗑️ Hapus',
61 | callback_data=f'droplet_actions?doc_id={doc_id}&droplet_id={droplet_id}&a=delete'
62 | ),
63 | )
64 | power_buttons = []
65 | if droplet.status == 'active':
66 | power_buttons.extend([
67 | InlineKeyboardButton(
68 | text='🛑 Matikan',
69 | callback_data=f'droplet_actions?doc_id={doc_id}&droplet_id={droplet_id}&a=shutdown'
70 | ),
71 | InlineKeyboardButton(
72 | text='🔄 Restart',
73 | callback_data=f'droplet_actions?doc_id={doc_id}&droplet_id={droplet_id}&a=reboot'
74 | ),
75 | ])
76 | power_buttons.extend([
77 | InlineKeyboardButton(
78 | text='🔨 Rebuild',
79 | callback_data=f'droplet_actions?doc_id={doc_id}&droplet_id={droplet_id}&a=rebuild'
80 | ),
81 | InlineKeyboardButton(
82 | text='🔑 Reset Password',
83 | callback_data=f'droplet_actions?doc_id={doc_id}&droplet_id={droplet_id}&a=reset_password'
84 | )
85 | ])
86 | else:
87 | power_buttons.append(
88 | InlineKeyboardButton(
89 | text='⚡ Nyalakan',
90 | callback_data=f'droplet_actions?doc_id={doc_id}&droplet_id={droplet_id}&a=power_on'
91 | )
92 | )
93 | markup.row(*power_buttons[:2])
94 | markup.row(*power_buttons[2:])
95 | markup.row(
96 | InlineKeyboardButton(
97 | text='🔄 Refresh',
98 | callback_data=f'droplet_detail?doc_id={account.doc_id}&droplet_id={droplet_id}'
99 | ),
100 | InlineKeyboardButton(
101 | text='🔙 Kembali',
102 | callback_data=f'list_droplets?doc_id={account.doc_id}'
103 | )
104 | )
105 |
106 | bot.edit_message_text(
107 | text=f'{t}'
108 | f'👤 Akun: {account["email"]}\n'
109 | f'🏷️ Nama: {droplet.name}\n'
110 | f'📏 Model: {droplet.size_slug}\n'
111 | f'🌍 Wilayah: {localize_region(droplet.region["slug"])}\n'
112 | f'💻 Sistem Operasi: {droplet.image["distribution"]} {droplet.image["name"]}\n'
113 | f'💾 Hard Disk: {droplet.disk} GB\n'
114 | f'🌐 IP Publik: {droplet.ip_address}\n'
115 | f'🔒 IP Privat: {droplet.private_ip_address}\n'
116 | f'📊 Status: {droplet.status}\n'
117 | f'📅 Dibuat pada: {droplet.created_at.split("T")[0]}\n',
118 | chat_id=call.from_user.id,
119 | message_id=call.message.message_id,
120 | parse_mode='HTML',
121 | reply_markup=markup
122 | )
123 |
--------------------------------------------------------------------------------
/modules/droplet_actions.py:
--------------------------------------------------------------------------------
1 | from telebot.types import CallbackQuery
2 |
3 | import digitalocean
4 |
5 | from _bot import bot
6 | from utils.db import AccountsDB
7 |
8 |
9 | def droplet_actions(call: CallbackQuery, data: dict):
10 | doc_id = data['doc_id'][0]
11 | droplet_id = data['droplet_id'][0]
12 | action = data['a'][0]
13 |
14 | try:
15 | account = AccountsDB().get(doc_id=doc_id)
16 | droplet = digitalocean.Droplet(
17 | token=account['token'],
18 | id=droplet_id
19 | )
20 | except Exception as e:
21 | bot.edit_message_text(
22 | text=f'⚠️ Kesalahan saat mengambil akun atau droplet: {str(e)}',
23 | chat_id=call.from_user.id,
24 | message_id=call.message.message_id,
25 | parse_mode='HTML'
26 | )
27 | return
28 |
29 | if action in globals():
30 | globals()[action](call, droplet)
31 |
32 |
33 | def delete(call: CallbackQuery, droplet: digitalocean.Droplet):
34 | bot.edit_message_text(
35 | text=f'{call.message.html_text}\n\n'
36 | '🔄 Menghapus droplet...',
37 | chat_id=call.from_user.id,
38 | message_id=call.message.message_id,
39 | parse_mode='HTML'
40 | )
41 |
42 | try:
43 | droplet.load()
44 | droplet.destroy()
45 | except Exception as e:
46 | bot.edit_message_text(
47 | text=f'⚠️ Kesalahan saat menghapus droplet: {str(e)}',
48 | chat_id=call.from_user.id,
49 | message_id=call.message.message_id,
50 | parse_mode='HTML'
51 | )
52 | return
53 |
54 | bot.edit_message_text(
55 | text=f'{call.message.html_text}\n\n'
56 | f'✅ Droplet telah dihapus',
57 | chat_id=call.from_user.id,
58 | message_id=call.message.message_id,
59 | parse_mode='HTML'
60 | )
61 |
62 |
63 | def shutdown(call: CallbackQuery, droplet: digitalocean.Droplet):
64 | bot.edit_message_text(
65 | text=f'{call.message.html_text}\n\n'
66 | '🔄 Mematikan droplet, silakan segarkan nanti',
67 | chat_id=call.from_user.id,
68 | message_id=call.message.message_id,
69 | reply_markup=call.message.reply_markup,
70 | parse_mode='HTML'
71 | )
72 |
73 | try:
74 | droplet.load()
75 | droplet.shutdown()
76 | except Exception as e:
77 | bot.edit_message_text(
78 | text=f'⚠️ Kesalahan saat mematikan droplet: {str(e)}',
79 | chat_id=call.from_user.id,
80 | message_id=call.message.message_id,
81 | parse_mode='HTML'
82 | )
83 |
84 |
85 | def reboot(call: CallbackQuery, droplet: digitalocean.Droplet):
86 | bot.edit_message_text(
87 | text=f'{call.message.html_text}\n\n'
88 | '🔄 Merestart droplet, silakan segarkan nanti',
89 | chat_id=call.from_user.id,
90 | message_id=call.message.message_id,
91 | reply_markup=call.message.reply_markup,
92 | parse_mode='HTML'
93 | )
94 |
95 | try:
96 | droplet.load()
97 | droplet.reboot()
98 | except Exception as e:
99 | bot.edit_message_text(
100 | text=f'⚠️ Kesalahan saat merestart droplet: {str(e)}',
101 | chat_id=call.from_user.id,
102 | message_id=call.message.message_id,
103 | parse_mode='HTML'
104 | )
105 |
106 |
107 | def power_on(call: CallbackQuery, droplet: digitalocean.Droplet):
108 | bot.edit_message_text(
109 | text=f'{call.message.html_text}\n\n'
110 | '🔄 Menyalakan droplet, silakan segarkan nanti',
111 | chat_id=call.from_user.id,
112 | message_id=call.message.message_id,
113 | reply_markup=call.message.reply_markup,
114 | parse_mode='HTML'
115 | )
116 |
117 | try:
118 | droplet.load()
119 | droplet.power_on()
120 | except Exception as e:
121 | bot.edit_message_text(
122 | text=f'⚠️ Kesalahan saat menyalakan droplet: {str(e)}',
123 | chat_id=call.from_user.id,
124 | message_id=call.message.message_id,
125 | parse_mode='HTML'
126 | )
127 | def rebuild(call: CallbackQuery, droplet: digitalocean.Droplet):
128 | bot.edit_message_text(
129 | text=f'{call.message.html_text}\n\n'
130 | '🔄 Membangun ulang droplet, silakan segarkan nanti',
131 | chat_id=call.from_user.id,
132 | message_id=call.message.message_id,
133 | reply_markup=call.message.reply_markup,
134 | parse_mode='HTML'
135 | )
136 |
137 | try:
138 | droplet.load()
139 | droplet.rebuild()
140 |
141 | except Exception as e:
142 | bot.edit_message_text(
143 | text=f'⚠️ Kesalahan saat membangun ulang droplet: {str(e)}',
144 | chat_id=call.from_user.id,
145 | message_id=call.message.message_id,
146 | parse_mode='HTML'
147 | )
148 | return
149 |
150 | bot.edit_message_text(
151 | text=f'{call.message.html_text}\n\n'
152 | f'✅ Droplet telah dibangun ulang\n'
153 | f'🔑 Password baru dikirim ke email',
154 | chat_id=call.from_user.id,
155 | message_id=call.message.message_id,
156 | parse_mode='HTML'
157 | )
158 | def reset_password(call: CallbackQuery, droplet: digitalocean.Droplet):
159 | bot.edit_message_text(
160 | text=f'{call.message.html_text}\n\n'
161 | '🔄 Mereset password droplet, silakan segarkan nanti',
162 | chat_id=call.from_user.id,
163 | message_id=call.message.message_id,
164 | reply_markup=call.message.reply_markup,
165 | parse_mode='HTML'
166 | )
167 |
168 | try:
169 | droplet.load()
170 | droplet.reset_root_password()
171 | except Exception as e:
172 | bot.edit_message_text(
173 | text=f'⚠️ Kesalahan saat mereset password droplet: {str(e)}',
174 | chat_id=call.from_user.id,
175 | message_id=call.message.message_id,
176 | parse_mode='HTML'
177 | )
178 | return
179 |
180 | bot.edit_message_text(
181 | text=f'{call.message.html_text}\n\n'
182 | f'✅ Password droplet telah direset\n'
183 | f'🔑 Password baru dikirim ke email',
184 | chat_id=call.from_user.id,
185 | message_id=call.message.message_id,
186 | parse_mode='HTML'
187 | )
--------------------------------------------------------------------------------
/modules/create_droplet.py:
--------------------------------------------------------------------------------
1 | from typing import Union
2 | from time import sleep
3 |
4 | from telebot.types import (
5 | Message,
6 | CallbackQuery,
7 | InlineKeyboardMarkup,
8 | InlineKeyboardButton,
9 | )
10 |
11 | import digitalocean
12 |
13 | from _bot import bot
14 | from utils.db import AccountsDB
15 | from utils.localizer import localize_region
16 | from utils.set_root_password_script import set_root_password_script
17 | from utils.password_generator import password_generator
18 |
19 | user_dict = {}
20 |
21 | t = '🚀 Buat Instance\n\n'
22 |
23 |
24 | def create_droplet(d: Union[Message, CallbackQuery], data: dict = None):
25 | data = data or {}
26 | next_func = data.get('nf', ['select_account'])[0]
27 | if next_func in globals():
28 | data.pop('nf', None)
29 | args = [d]
30 | if len(data.keys()) > 0:
31 | args.append(data)
32 |
33 | globals()[next_func](*args)
34 |
35 |
36 | def select_account(d: Union[Message, CallbackQuery]):
37 | accounts = AccountsDB().all()
38 | markup = InlineKeyboardMarkup()
39 | for account in accounts:
40 | markup.add(
41 | InlineKeyboardButton(
42 | text=account['email'],
43 | callback_data=f'create_droplet?nf=select_region&doc_id={account.doc_id}'
44 | )
45 | )
46 |
47 | bot.send_message(
48 | text=f'{t}'
49 | '👤 Pilih Akun',
50 | chat_id=d.from_user.id,
51 | parse_mode='HTML',
52 | reply_markup=markup
53 | )
54 |
55 |
56 | def select_region(call: CallbackQuery, data: dict):
57 | doc_id = data['doc_id'][0]
58 |
59 | account = AccountsDB().get(doc_id=doc_id)
60 | user_dict[call.from_user.id] = {
61 | 'account': account
62 | }
63 |
64 | _t = t + f'👤 Akun: {account["email"]}\n\n'
65 |
66 | bot.edit_message_text(
67 | text=f'{_t}'
68 | f'🌍 Mengambil daftar Wilayah...',
69 | chat_id=call.from_user.id,
70 | message_id=call.message.message_id,
71 | parse_mode='HTML'
72 | )
73 |
74 | try:
75 | regions = digitalocean.Manager(token=account['token']).get_all_regions()
76 | except Exception as e:
77 | bot.edit_message_text(
78 | text=f'{_t}'
79 | '⚠️ Kesalahan saat mengambil Wilayah: '
80 | f'{str(e)}',
81 | chat_id=call.from_user.id,
82 | message_id=call.message.message_id,
83 | parse_mode='HTML'
84 | )
85 | return
86 |
87 | markup = InlineKeyboardMarkup(row_width=2)
88 | buttons = []
89 | for region in regions:
90 | if region.available:
91 | buttons.append(
92 | InlineKeyboardButton(
93 | text=localize_region(slug=region.slug),
94 | callback_data=f'create_droplet?nf=select_size®ion={region.slug}'
95 | )
96 | )
97 | markup.add(*buttons)
98 |
99 | bot.edit_message_text(
100 | text=f'{_t}'
101 | f'🌍 Pilih Wilayah',
102 | chat_id=call.from_user.id,
103 | message_id=call.message.message_id,
104 | reply_markup=markup,
105 | parse_mode='HTML'
106 | )
107 |
108 |
109 | def select_size(call: CallbackQuery, data: dict):
110 | region_slug = data['region'][0]
111 |
112 | user_dict[call.from_user.id].update({
113 | 'region_slug': region_slug
114 | })
115 |
116 | _t = t + f'👤 Akun: {user_dict[call.from_user.id]["account"]["email"]}\n' \
117 | f'🌍 Wilayah: {region_slug}\n\n'
118 |
119 | bot.edit_message_text(
120 | text=f'{_t}'
121 | f'📏 Mengambil daftar Ukuran...',
122 | chat_id=call.from_user.id,
123 | message_id=call.message.message_id,
124 | parse_mode='HTML'
125 | )
126 |
127 | try:
128 | sizes = digitalocean.Manager(token=user_dict[call.from_user.id]['account']['token']).get_all_sizes()
129 | except Exception as e:
130 | bot.edit_message_text(
131 | text=f'{_t}'
132 | '⚠️ Kesalahan saat mengambil Ukuran: '
133 | f'{str(e)}',
134 | chat_id=call.from_user.id,
135 | message_id=call.message.message_id,
136 | parse_mode='HTML'
137 | )
138 | return
139 |
140 | markup = InlineKeyboardMarkup(row_width=2)
141 | buttons = []
142 | for size in sizes:
143 | if region_slug in size.regions:
144 | buttons.append(
145 | InlineKeyboardButton(
146 | text=size.slug,
147 | callback_data=f'create_droplet?nf=select_os&size={size.slug}'
148 | )
149 | )
150 | markup.add(*buttons)
151 | markup.row(
152 | InlineKeyboardButton(
153 | text='⬅️ Sebelumnya',
154 | callback_data=f'create_droplet?nf=select_region&doc_id={user_dict[call.from_user.id]["account"].doc_id}'
155 | )
156 | )
157 |
158 | bot.edit_message_text(
159 | text=f'{_t}'
160 | f'📏 Pilih Ukuran',
161 | chat_id=call.from_user.id,
162 | message_id=call.message.message_id,
163 | reply_markup=markup,
164 | parse_mode='HTML'
165 | )
166 |
167 |
168 | def select_os(d: Union[Message, CallbackQuery], data: dict):
169 | size_slug = data['size'][0]
170 |
171 | user_dict[d.from_user.id].update({
172 | 'size_slug': size_slug
173 | })
174 |
175 | _t = t + f'👤 Akun: {user_dict[d.from_user.id]["account"]["email"]}\n' \
176 | f'🌍 Wilayah: {user_dict[d.from_user.id]["region_slug"]}\n' \
177 | f'📏 Ukuran: {size_slug}\n\n'
178 |
179 | def get_os_markup():
180 | try:
181 | images = digitalocean.Manager(token=user_dict[d.from_user.id]['account']['token']).get_distro_images()
182 | except Exception as e:
183 | bot.edit_message_text(
184 | text=f'{_t}'
185 | '⚠️ Kesalahan saat mengambil OS: '
186 | f'{str(e)}',
187 | chat_id=d.from_user.id,
188 | message_id=d.message.message_id,
189 | parse_mode='HTML'
190 | )
191 | return InlineKeyboardMarkup()
192 |
193 | markup = InlineKeyboardMarkup(row_width=2)
194 | buttons = []
195 | for image in images:
196 | if image.distribution in ['Ubuntu', 'CentOS', 'Debian'] \
197 | and image.public \
198 | and image.status == 'available' \
199 | and user_dict[d.from_user.id]["region_slug"] in image.regions:
200 | buttons.append(
201 | InlineKeyboardButton(
202 | text=f'{image.distribution} {image.name}',
203 | callback_data=f'create_droplet?nf=get_name&image={image.slug}'
204 | )
205 | )
206 | markup.add(*buttons)
207 | markup.row(
208 | InlineKeyboardButton(
209 | text='⬅️ Sebelumnya',
210 | callback_data=f'create_droplet?nf=select_size®ion={user_dict[d.from_user.id]["region_slug"]}'
211 | )
212 | )
213 |
214 | return markup
215 |
216 | if type(d) == Message:
217 | msg = bot.send_message(
218 | text=f'{_t}'
219 | f'🖼️ Mengambil daftar OS...',
220 | chat_id=d.from_user.id,
221 | parse_mode='HTML'
222 | )
223 | bot.edit_message_text(
224 | text=f'{_t}'
225 | f'🖼️ Pilih OS',
226 | chat_id=d.from_user.id,
227 | message_id=msg.message_id,
228 | reply_markup=get_os_markup(),
229 | parse_mode='HTML'
230 | )
231 |
232 | elif type(d) == CallbackQuery:
233 | bot.edit_message_text(
234 | text=f'{_t}'
235 | f'🖼️ Mengambil daftar OS...',
236 | chat_id=d.from_user.id,
237 | message_id=d.message.message_id,
238 | parse_mode='HTML'
239 | )
240 | bot.edit_message_text(
241 | text=f'{_t}'
242 | f'🖼️ Pilih OS',
243 | chat_id=d.from_user.id,
244 | message_id=d.message.message_id,
245 | reply_markup=get_os_markup(),
246 | parse_mode='HTML'
247 | )
248 |
249 |
250 | def get_name(call: CallbackQuery, data: dict):
251 | image_slug = data['image'][0]
252 |
253 | user_dict[call.from_user.id].update({
254 | 'image_slug': image_slug
255 | })
256 |
257 | _t = t + f'👤 Akun: {user_dict[call.from_user.id]["account"]["email"]}\n' \
258 | f'🌍 Wilayah: {user_dict[call.from_user.id]["region_slug"]}\n' \
259 | f'📏 Ukuran: {user_dict[call.from_user.id]["size_slug"]}\n' \
260 | f'🖼️ OS: {image_slug}\n\n'
261 |
262 | msg = bot.edit_message_text(
263 | text=f'{_t}'
264 | '📝 Harap balas dengan Nama Instance, contoh: FighterTunnel\n\n'
265 | '/back ⬅️ Sebelumnya',
266 | chat_id=call.from_user.id,
267 | message_id=call.message.message_id,
268 | parse_mode='HTML'
269 | )
270 | bot.register_next_step_handler(msg, ask_create)
271 |
272 |
273 | def ask_create(m: Message):
274 | if m.text == '/back':
275 | select_os(m, data={'size': [user_dict[m.from_user.id]["size_slug"]]})
276 | return
277 |
278 | _t = t + f'👤 Akun: {user_dict[m.from_user.id]["account"]["email"]}\n' \
279 | f'🌍 Wilayah: {user_dict[m.from_user.id]["region_slug"]}\n' \
280 | f'📏 Ukuran: {user_dict[m.from_user.id]["size_slug"]}\n' \
281 | f'🖼️ OS: {user_dict[m.from_user.id]["image_slug"]}\n' \
282 | f'📝 Nama: {m.text}\n\n'
283 | markup = InlineKeyboardMarkup(row_width=2)
284 | markup.add(
285 | InlineKeyboardButton(
286 | text='⬅️ Sebelumnya',
287 | callback_data=f'create_droplet?nf=get_name&image={user_dict[m.from_user.id]["image_slug"]}'
288 | ),
289 | InlineKeyboardButton(
290 | text='❌ Membatalkan',
291 | callback_data='create_droplet?nf=cancel_create'
292 | ),
293 | )
294 | markup.row(
295 | InlineKeyboardButton(
296 | text='✅ Buat',
297 | callback_data=f'create_droplet?nf=confirm_create&name={m.text}'
298 | )
299 | )
300 |
301 | bot.send_message(
302 | text=_t,
303 | chat_id=m.from_user.id,
304 | reply_markup=markup,
305 | parse_mode='HTML'
306 | )
307 |
308 |
309 | def cancel_create(call: CallbackQuery):
310 | bot.edit_message_text(
311 | text=f'{call.message.html_text}\n\n'
312 | '❌ Membatalkan',
313 | chat_id=call.from_user.id,
314 | message_id=call.message.message_id,
315 | parse_mode='HTML'
316 | )
317 |
318 |
319 | def confirm_create(call: CallbackQuery, data: dict):
320 | droplet_name = data['name'][0]
321 | password = password_generator()
322 |
323 | bot.edit_message_text(
324 | text=f'{call.message.html_text}\n\n'
325 | '🔄 Membuat Instance...',
326 | chat_id=call.from_user.id,
327 | message_id=call.message.message_id,
328 | parse_mode='HTML'
329 | )
330 | try:
331 | droplet = digitalocean.Droplet(
332 | token=user_dict[call.from_user.id]['account']['token'],
333 | name=droplet_name,
334 | region=user_dict[call.from_user.id]['region_slug'],
335 | image=user_dict[call.from_user.id]['image_slug'],
336 | size_slug=user_dict[call.from_user.id]['size_slug'],
337 | user_data=set_root_password_script(password)
338 | )
339 | droplet.create()
340 |
341 | droplet_actions = droplet.get_actions()
342 | for action in droplet_actions:
343 | while action.status != 'completed':
344 | sleep(3)
345 | action.load()
346 | droplet.load()
347 |
348 | # Menunggu IP address siap
349 | while not droplet.ip_address:
350 | sleep(3)
351 | droplet.load()
352 | except Exception as e:
353 | bot.edit_message_text(
354 | text=f'{call.message.html_text}\n\n'
355 | '⚠️ Kesalahan saat membuat Instance: '
356 | f'{str(e)}',
357 | chat_id=call.from_user.id,
358 | message_id=call.message.message_id,
359 | parse_mode='HTML'
360 | )
361 | return
362 |
363 | markup = InlineKeyboardMarkup()
364 | markup.row(
365 | InlineKeyboardButton(
366 | text='🔍 Periksa Detailnya',
367 | callback_data=f'droplet_detail?'
368 | f'doc_id={user_dict[call.from_user.id]["account"].doc_id}&'
369 | f'droplet_id={droplet.id}'
370 | )
371 | )
372 |
373 | bot.edit_message_text(
374 | text=f'{call.message.html_text}\n'
375 | f'🌐 IP: {droplet.ip_address}\n'
376 | f'🔑 Kata Sandi: {password}\n\n'
377 | '✅ Pembuatan Server Selesai',
378 | chat_id=call.from_user.id,
379 | reply_markup=markup,
380 | message_id=call.message.message_id,
381 | parse_mode='HTML'
382 | )
383 |
--------------------------------------------------------------------------------