gadisk820 commited on
Commit
be15620
Β·
verified Β·
1 Parent(s): afa97a6

Upload 8 files

Browse files
Files changed (7) hide show
  1. .dockerignore +21 -0
  2. .env +15 -0
  3. Dockerfile +79 -0
  4. README.md +4 -4
  5. app.py +820 -0
  6. docker-compose.yml +22 -0
  7. requirements.txt +3 -0
.dockerignore ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.pyd
5
+ .Python
6
+ env/
7
+ venv/
8
+ .venv/
9
+ env.bak/
10
+ venv.bak/
11
+ *.log
12
+ logs/
13
+ data/
14
+ *.db
15
+ .DS_Store
16
+ .git/
17
+ .gitignore
18
+ .vscode/
19
+ .idea/
20
+ *.md
21
+ docker-compose.override.yml
.env ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Email configuration
2
+ EMAIL=gi2h27@gmail.com
3
+
4
+ # Faucet configuration
5
+ MAX_CLAIMS=100000
6
+ COOLDOWN_OVERRIDE=5
7
+
8
+ # Proxy settings (jika perlu)
9
+ HTTP_PROXY=
10
+ HTTPS_PROXY=
11
+ NO_PROXY=localhost,127.0.0.1
12
+
13
+ # Solver settings
14
+ SOLVER_URL=https://gi2h-xxx.hf.space
15
+ SOLVER_KEY=00000000000000000000#0000000000000000000#000000000000000000#
Dockerfile ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ============================================
2
+ # DOCKERFILE YANG PASTI BERJALAN - TANPA APT-KEY
3
+ # ============================================
4
+ FROM python:3.9-slim
5
+
6
+ # 1. Install system dependencies
7
+ RUN apt-get update && apt-get install -y \
8
+ curl \
9
+ wget \
10
+ gnupg \
11
+ ca-certificates \
12
+ xz-utils \
13
+ && rm -rf /var/lib/apt/lists/*
14
+
15
+ # 2. Install Chrome tanpa apt-key (cara baru)
16
+ RUN mkdir -p /etc/apt/keyrings \
17
+ && wget -q -O - https://dl.google.com/linux/linux_signing_key.pub > /tmp/google.pub \
18
+ && gpg --dearmor < /tmp/google.pub > /etc/apt/keyrings/google-chrome.gpg \
19
+ && echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list \
20
+ && apt-get update \
21
+ && apt-get install -y google-chrome-stable \
22
+ && rm -rf /var/lib/apt/lists/* \
23
+ && rm /tmp/google.pub
24
+
25
+ WORKDIR /app
26
+
27
+ # 3. Copy Python requirements
28
+ COPY requirements.txt .
29
+
30
+ # 4. Install Python dependencies
31
+ RUN pip install --no-cache-dir --upgrade pip && \
32
+ pip install --no-cache-dir -r requirements.txt
33
+
34
+ # 5. Install Node.js
35
+ RUN mkdir -p /etc/apt/keyrings \
36
+ && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
37
+ && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \
38
+ && apt-get update \
39
+ && apt-get install -y nodejs \
40
+ && rm -rf /var/lib/apt/lists/*
41
+
42
+ # 6. Copy Api folder dan install dependencies
43
+ COPY Api/ /app/Api/
44
+ WORKDIR /app/Api
45
+ RUN npm install --omit=dev
46
+ WORKDIR /app
47
+
48
+ # 7. Copy Python aplikasi
49
+ COPY app.py .
50
+
51
+ # 8. Buat startup script yang sesuai dengan struktur
52
+ RUN echo '#!/bin/bash\n\
53
+ \n\
54
+ echo "πŸ€– STARTING FAUCET BOT"\n\
55
+ echo "======================"\n\
56
+ \n\
57
+ # Start API dari folder Api\n\
58
+ echo "Starting Node.js API..."\n\
59
+ cd /app/Api\n\
60
+ node Api.js &\n\
61
+ \n\
62
+ # Wait for API to start\n\
63
+ echo "Waiting for API to start..."\n\
64
+ sleep 5\n\
65
+ \n\
66
+ # Start Python Bot\n\
67
+ echo "Starting Python Bot..."\n\
68
+ cd /app\n\
69
+ python3 app.py\n\
70
+ ' > /start.sh && chmod +x /start.sh
71
+
72
+ # 9. Health check untuk API (sesuaikan port dengan Api.js)
73
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
74
+ CMD curl -f http://localhost:3000/ || exit 1
75
+
76
+ # 10. Expose port untuk API (sesuaikan dengan Api.js)
77
+ EXPOSE 3000
78
+
79
+ CMD ["/start.sh"]
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
- title: Gadis
3
- emoji: 😻
4
- colorFrom: green
5
- colorTo: red
6
  sdk: docker
7
  pinned: false
8
  ---
 
1
  ---
2
+ title: Auto
3
+ emoji: πŸ“‰
4
+ colorFrom: pink
5
+ colorTo: gray
6
  sdk: docker
7
  pinned: false
8
  ---
app.py ADDED
@@ -0,0 +1,820 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ FAUCET BOT TRUMP COIN
4
+ Auto claim untuk coin: TRUMP saja
5
+ Dengan fitur cookies management dan relogin setiap 6 jam
6
+ """
7
+
8
+ import requests
9
+ import json
10
+ import time
11
+ import re
12
+ import sys
13
+ import os
14
+ from datetime import datetime, timedelta
15
+
16
+ class Color:
17
+ """Class untuk warna terminal"""
18
+ PURPLE = '\033[95m'
19
+ CYAN = '\033[96m'
20
+ BLUE = '\033[94m'
21
+ GREEN = '\033[92m'
22
+ YELLOW = '\033[93m'
23
+ RED = '\033[91m'
24
+ BOLD = '\033[1m'
25
+ END = '\033[0m'
26
+
27
+ class TrumpFaucetBot:
28
+ def __init__(self, email):
29
+ self.email = email
30
+ self.base_url = "https://litecoin.freepepecoin.com"
31
+ self.solver_url = "https://gi2h-xxx.hf.space"
32
+ self.solver_key = "00000000000000000000#0000000000000000000#000000000000000000#"
33
+
34
+ # File cookies
35
+ self.cookies_file = "cookies.json"
36
+ self.last_login_time = 0
37
+ self.relogin_interval = 6 * 3600 # 6 jam dalam detik
38
+
39
+ # Konfigurasi coin - HANYA TRUMP
40
+ self.coins = {
41
+ 'TRUMP': {
42
+ 'name': 'Trumpcoin',
43
+ 'url_path': '/faucet/TRUMP',
44
+ 'default_cooldown': 10, # 10 detik
45
+ 'cooldown': 10,
46
+ 'last_claim': 0,
47
+ 'success_count': 0,
48
+ 'total_claims': 0,
49
+ 'total_rewards': 0
50
+ }
51
+ }
52
+
53
+ self.session = requests.Session()
54
+ self.setup_headers()
55
+
56
+ # Statistik
57
+ self.total_cycles = 0
58
+ self.stats_file = "stats.json"
59
+ self.load_stats()
60
+
61
+ # Load cookies jika ada
62
+ self.load_cookies()
63
+
64
+ # Logging
65
+ self.log_dir = "logs"
66
+ os.makedirs(self.log_dir, exist_ok=True)
67
+
68
+ def setup_headers(self):
69
+ """Set headers untuk meniru browser"""
70
+ self.session.headers.update({
71
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36',
72
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
73
+ 'Accept-Language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7',
74
+ 'Accept-Encoding': 'gzip, deflate, br',
75
+ 'Connection': 'keep-alive',
76
+ 'Upgrade-Insecure-Requests': '1',
77
+ 'sec-ch-ua': '"Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144"',
78
+ 'sec-ch-ua-mobile': '?0',
79
+ 'sec-ch-ua-platform': '"Windows"',
80
+ })
81
+
82
+ def save_cookies(self):
83
+ """Simpan cookies ke file"""
84
+ try:
85
+ cookies_dict = requests.utils.dict_from_cookiejar(self.session.cookies)
86
+ with open(self.cookies_file, 'w') as f:
87
+ json.dump({
88
+ 'cookies': cookies_dict,
89
+ 'saved_at': datetime.now().isoformat(),
90
+ 'email': self.email
91
+ }, f, indent=2)
92
+ print(f"{Color.GREEN}βœ“ Cookies disimpan ke {self.cookies_file}{Color.END}")
93
+ return True
94
+ except Exception as e:
95
+ print(f"{Color.YELLOW}⚠️ Gagal menyimpan cookies: {e}{Color.END}")
96
+ return False
97
+
98
+ def load_cookies(self):
99
+ """Load cookies dari file"""
100
+ try:
101
+ if os.path.exists(self.cookies_file):
102
+ with open(self.cookies_file, 'r') as f:
103
+ data = json.load(f)
104
+ cookies_dict = data.get('cookies', {})
105
+
106
+ # Buat cookies jar dari dictionary
107
+ cookies_jar = requests.utils.cookiejar_from_dict(cookies_dict)
108
+ self.session.cookies = cookies_jar
109
+
110
+ print(f"{Color.GREEN}βœ“ Cookies dimuat dari {self.cookies_file}{Color.END}")
111
+ print(f"{Color.CYAN}πŸͺ Jumlah cookies: {len(cookies_dict)}{Color.END}")
112
+
113
+ # Update last login time
114
+ saved_time = data.get('saved_at')
115
+ if saved_time:
116
+ try:
117
+ saved_dt = datetime.fromisoformat(saved_time)
118
+ self.last_login_time = saved_dt.timestamp()
119
+ except:
120
+ self.last_login_time = time.time()
121
+ else:
122
+ self.last_login_time = time.time()
123
+
124
+ return True
125
+ else:
126
+ print(f"{Color.YELLOW}⚠️ File cookies tidak ditemukan{Color.END}")
127
+ return False
128
+ except Exception as e:
129
+ print(f"{Color.YELLOW}⚠️ Gagal memuat cookies: {e}{Color.END}")
130
+ return False
131
+
132
+ def update_cookies(self):
133
+ """Update cookies setelah claim sukses"""
134
+ return self.save_cookies()
135
+
136
+ def check_login_status(self):
137
+ """Cek status login dengan cookies"""
138
+ try:
139
+ response = self.session.get(
140
+ f'{self.base_url}/dashboard',
141
+ timeout=30,
142
+ allow_redirects=True
143
+ )
144
+
145
+ if response.status_code == 200 and f"Welcome, <b>{self.email}</b>" in response.text:
146
+ print(f"{Color.GREEN}βœ… Login status valid dengan cookies{Color.END}")
147
+ return True
148
+ else:
149
+ print(f"{Color.YELLOW}⚠️ Cookies expired atau login diperlukan{Color.END}")
150
+ return False
151
+ except Exception as e:
152
+ print(f"{Color.YELLOW}⚠️ Error cek login status: {e}{Color.END}")
153
+ return False
154
+
155
+ def need_relogin(self):
156
+ """Cek apakah perlu relogin (setiap 6 jam)"""
157
+ current_time = time.time()
158
+ if self.last_login_time == 0:
159
+ return True
160
+
161
+ time_since_login = current_time - self.last_login_time
162
+ if time_since_login >= self.relogin_interval:
163
+ hours = int(time_since_login // 3600)
164
+ minutes = int((time_since_login % 3600) // 60)
165
+ print(f"{Color.YELLOW}⏰ Sudah {hours} jam {minutes} menit sejak login terakhir{Color.END}")
166
+ return True
167
+
168
+ return False
169
+
170
+ def print_banner(self):
171
+ """Menampilkan banner khusus TRUMP"""
172
+ banner = f"""
173
+ {Color.PURPLE}{Color.BOLD}
174
+ ╔══════════════════════════════════════════════════════════════╗
175
+ β•‘ TRUMP FAUCET BOT V2.0 β•‘
176
+ β•‘ (Dengan Cookies Management) β•‘
177
+ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
178
+ {Color.END}
179
+ {Color.CYAN}Email: {self.email}{Color.END}
180
+ {Color.CYAN}Base URL: {self.base_url}{Color.END}
181
+ {Color.CYAN}Coin: TRUMP (Trumpcoin){Color.END}
182
+ {Color.CYAN}Relogin Interval: Setiap 6 jam{Color.END}
183
+ """
184
+ print(banner)
185
+ self.print_coin_table()
186
+
187
+ def print_coin_table(self):
188
+ """Print tabel informasi coin (hanya TRUMP)"""
189
+ coin_symbol = 'TRUMP'
190
+ coin_data = self.coins[coin_symbol]
191
+
192
+ current_time = time.time()
193
+ time_since_last = current_time - coin_data['last_claim']
194
+ remaining = coin_data['cooldown'] - time_since_last
195
+
196
+ if coin_data['last_claim'] == 0:
197
+ status = f"{Color.GREEN}READY{Color.END}"
198
+ elif remaining <= 0:
199
+ status = f"{Color.GREEN}READY{Color.END}"
200
+ else:
201
+ mins = int(remaining // 60)
202
+ secs = int(remaining % 60)
203
+ status = f"{Color.YELLOW}WAIT {mins:02d}:{secs:02d}{Color.END}"
204
+
205
+ print(f"{Color.BLUE}╔══════════════════════════════════════════════════════════╗{Color.END}")
206
+ print(f"{Color.BLUE}β•‘ TRUMP STATUS β•‘{Color.END}")
207
+ print(f"{Color.BLUE}╠═══════════╦══════════════╦════════════════╦══════════════╣{Color.END}")
208
+ print(f"{Color.BLUE}β•‘ Coin β•‘ Default β•‘ Current β•‘ Status β•‘{Color.END}")
209
+ print(f"{Color.BLUE}╠═══════════╬══════════════╬════════════════╬══════════════╣{Color.END}")
210
+ print(f"β•‘ {coin_symbol:^9} β•‘ {coin_data['default_cooldown']:>6} sec β•‘ {coin_data['cooldown']:>6} sec β•‘ {status:^12} β•‘")
211
+ print(f"{Color.BLUE}β•šβ•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•{Color.END}")
212
+ print()
213
+
214
+ def save_stats(self):
215
+ """Simpan statistik ke file"""
216
+ stats = {
217
+ 'last_update': datetime.now().isoformat(),
218
+ 'last_login_time': self.last_login_time,
219
+ 'total_cycles': self.total_cycles,
220
+ 'coins': self.coins,
221
+ 'email': self.email
222
+ }
223
+
224
+ try:
225
+ with open(self.stats_file, 'w') as f:
226
+ json.dump(stats, f, indent=2)
227
+ except Exception as e:
228
+ print(f"{Color.YELLOW}⚠️ Gagal menyimpan statistik: {e}{Color.END}")
229
+
230
+ def load_stats(self):
231
+ """Load statistik dari file"""
232
+ try:
233
+ if os.path.exists(self.stats_file):
234
+ with open(self.stats_file, 'r') as f:
235
+ stats = json.load(f)
236
+ self.total_cycles = stats.get('total_cycles', 0)
237
+ self.last_login_time = stats.get('last_login_time', 0)
238
+
239
+ # Load data coin per coin
240
+ saved_coins = stats.get('coins', {})
241
+ for coin_symbol in self.coins.keys():
242
+ if coin_symbol in saved_coins:
243
+ self.coins[coin_symbol].update(saved_coins[coin_symbol])
244
+
245
+ except Exception as e:
246
+ print(f"{Color.YELLOW}⚠️ Gagal load statistik: {e}{Color.END}")
247
+
248
+ def get_recaptcha_token(self):
249
+ """Mendapatkan token reCAPTCHA dari solver"""
250
+ print(f"{Color.CYAN}[1/3] Meminta token reCAPTCHA...{Color.END}")
251
+
252
+ headers = {
253
+ "Content-Type": "application/json",
254
+ "key": self.solver_key
255
+ }
256
+
257
+ data = {
258
+ "type": "recaptcha3",
259
+ "domain": self.base_url,
260
+ "siteKey": "6LcbMB0sAAAAAAxsy76NqLNBhHfzZO8E4jLJ8XNl"
261
+ }
262
+
263
+ try:
264
+ # Submit task
265
+ response = requests.post(
266
+ f"{self.solver_url}/solve",
267
+ headers=headers,
268
+ json=data,
269
+ timeout=30
270
+ )
271
+
272
+ result = response.json()
273
+ if "taskId" not in result:
274
+ print(f"{Color.RED}❌ Gagal mendapatkan Task ID{Color.END}")
275
+ return None
276
+
277
+ task_id = result["taskId"]
278
+ print(f"{Color.GREEN}βœ“ Task ID: {task_id}{Color.END}")
279
+
280
+ # Polling untuk hasil
281
+ for i in range(30):
282
+ time.sleep(2)
283
+
284
+ poll_data = {"taskId": task_id}
285
+ poll_response = requests.post(
286
+ f"{self.solver_url}/solve",
287
+ headers=headers,
288
+ json=poll_data,
289
+ timeout=30
290
+ )
291
+
292
+ poll_result = poll_response.json()
293
+
294
+ if poll_result.get("status") == "done":
295
+ print(f"{Color.GREEN}βœ“ reCAPTCHA solved!{Color.END}")
296
+ token = poll_result.get("token") or poll_result.get("solution", {}).get("token")
297
+ if token:
298
+ return token
299
+
300
+ elif poll_result.get("status") == "error":
301
+ print(f"{Color.RED}❌ Error dari solver{Color.END}")
302
+ return None
303
+
304
+ print(f"{Color.RED}❌ Timeout{Color.END}")
305
+ return None
306
+
307
+ except Exception as e:
308
+ print(f"{Color.RED}❌ Error: {e}{Color.END}")
309
+ return None
310
+
311
+ def login(self):
312
+ """Login ke website untuk mendapatkan cookies"""
313
+ print(f"{Color.CYAN}[1/4] Login process...{Color.END}")
314
+
315
+ # Dapatkan token reCAPTCHA untuk login
316
+ recaptcha_token = self.get_recaptcha_token()
317
+ if not recaptcha_token:
318
+ print(f"{Color.RED}❌ Gagal mendapatkan token reCAPTCHA untuk login{Color.END}")
319
+ return False
320
+
321
+ # Persiapkan data login
322
+ headers = {
323
+ 'Content-Type': 'application/x-www-form-urlencoded',
324
+ 'Origin': self.base_url,
325
+ 'Referer': f'{self.base_url}/',
326
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
327
+ }
328
+
329
+ data = {
330
+ 'address': self.email,
331
+ 'g-recaptcha-response': recaptcha_token
332
+ }
333
+
334
+ try:
335
+ print(f"{Color.CYAN}[2/4] Mengirim data login...{Color.END}")
336
+ response = self.session.post(
337
+ f'{self.base_url}/',
338
+ headers=headers,
339
+ data=data,
340
+ timeout=30,
341
+ allow_redirects=True
342
+ )
343
+
344
+ print(f"{Color.CYAN}βœ“ Response status: {response.status_code}{Color.END}")
345
+
346
+ # Cek apakah login berhasil
347
+ if f"Welcome, <b>{self.email}</b>" in response.text:
348
+ print(f"{Color.GREEN}βœ… Login berhasil!{Color.END}")
349
+
350
+ # Update waktu login terakhir
351
+ self.last_login_time = time.time()
352
+
353
+ # Simpan cookies
354
+ self.save_cookies()
355
+
356
+ return True
357
+ else:
358
+ print(f"{Color.RED}❌ Login gagal!{Color.END}")
359
+ return False
360
+
361
+ except Exception as e:
362
+ print(f"{Color.RED}❌ Error login: {e}{Color.END}")
363
+ return False
364
+
365
+ def relogin_if_needed(self):
366
+ """Relogin jika diperlukan (setiap 6 jam)"""
367
+ if self.need_relogin():
368
+ print(f"{Color.YELLOW}πŸ”„ Waktunya relogin (setiap 6 jam)...{Color.END}")
369
+ return self.login()
370
+ return True
371
+
372
+ def get_csrf_token(self, coin_symbol):
373
+ """Ambil CSRF token dari halaman faucet untuk coin tertentu"""
374
+ coin_data = self.coins[coin_symbol]
375
+ print(f"{Color.CYAN}[2/4] Mengambil CSRF token untuk {coin_symbol}...{Color.END}")
376
+
377
+ headers = {
378
+ 'Referer': f'{self.base_url}/dashboard',
379
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
380
+ }
381
+
382
+ try:
383
+ # Batasi redirects
384
+ self.session.max_redirects = 5
385
+
386
+ response = self.session.get(
387
+ f'{self.base_url}{coin_data["url_path"]}',
388
+ headers=headers,
389
+ timeout=30,
390
+ allow_redirects=True
391
+ )
392
+
393
+ print(f"{Color.CYAN}βœ“ Response status: {response.status_code}{Color.END}")
394
+
395
+ if response.status_code != 200:
396
+ print(f"{Color.RED}❌ Gagal akses faucet {coin_symbol}: {response.status_code}{Color.END}")
397
+ return None
398
+
399
+ # Cari CSRF token dengan regex
400
+ csrf_pattern = r'name="csrf_token" value="([a-f0-9]{64})"'
401
+ match = re.search(csrf_pattern, response.text)
402
+
403
+ if match:
404
+ csrf_token = match.group(1)
405
+ print(f"{Color.GREEN}βœ“ CSRF token ditemukan: {csrf_token[:16]}...{Color.END}")
406
+ return csrf_token
407
+ else:
408
+ print(f"{Color.RED}❌ CSRF token tidak ditemukan{Color.END}")
409
+ return None
410
+
411
+ except requests.exceptions.TooManyRedirects:
412
+ print(f"{Color.RED}❌ Redirect loop terdeteksi!{Color.END}")
413
+ print(f"{Color.YELLOW}⚠️ Mungkin session expired atau belum login{Color.END}")
414
+ return None
415
+ except Exception as e:
416
+ print(f"{Color.RED}❌ Error: {e}{Color.END}")
417
+ return None
418
+
419
+ def extract_cooldown_from_response(self, response_text):
420
+ """Ekstrak waktu cooldown dari HTML response"""
421
+ try:
422
+ # Pola pencarian cooldown
423
+ patterns = [
424
+ r'cooldown.*?(\d+)\s*(minute|min|second|sec|hour|hr)',
425
+ r'wait.*?(\d+)\s*(minute|min|second|sec|hour|hr)',
426
+ r'timer.*?(\d+)\s*(minute|min|second|sec|hour|hr)',
427
+ r'(\d+)\s*(minute|min|second|sec|hour|hr).*?cooldown',
428
+ r'(\d+)\s*(minute|min|second|sec|hour|hr).*?wait'
429
+ ]
430
+
431
+ for pattern in patterns:
432
+ matches = re.findall(pattern, response_text, re.IGNORECASE)
433
+ if matches:
434
+ for match in matches:
435
+ value = int(match[0])
436
+ unit = match[1].lower()
437
+
438
+ # Konversi ke detik
439
+ if 'hour' in unit or 'hr' in unit:
440
+ return value * 3600
441
+ elif 'minute' in unit or 'min' in unit:
442
+ return value * 60
443
+ elif 'second' in unit or 'sec' in unit:
444
+ return value
445
+
446
+ return None # Tidak ditemukan cooldown
447
+
448
+ except Exception as e:
449
+ print(f"{Color.YELLOW}⚠️ Error extracting cooldown: {e}{Color.END}")
450
+ return None
451
+
452
+ def claim_coin(self, coin_symbol):
453
+ """Klaim faucet untuk coin tertentu"""
454
+ coin_data = self.coins[coin_symbol]
455
+
456
+ print(f"\n{Color.BLUE}{'═' * 50}{Color.END}")
457
+ print(f"{Color.BOLD}πŸͺ™ CLAIMING {coin_symbol} ({coin_data['name']}){Color.END}")
458
+ print(f"{Color.BLUE}{'═' * 50}{Color.END}")
459
+
460
+ # 1. Ambil CSRF token
461
+ csrf_token = self.get_csrf_token(coin_symbol)
462
+ if not csrf_token:
463
+ print(f"{Color.RED}❌ Gagal mendapatkan CSRF token untuk {coin_symbol}{Color.END}")
464
+ return False, None
465
+
466
+ # 2. Dapatkan token reCAPTCHA untuk claim
467
+ print(f"{Color.CYAN}[3/4] Meminta token reCAPTCHA untuk claim...{Color.END}")
468
+ recaptcha_token = self.get_recaptcha_token()
469
+ if not recaptcha_token:
470
+ print(f"{Color.RED}❌ Gagal mendapatkan token reCAPTCHA untuk claim{Color.END}")
471
+ return False, None
472
+
473
+ # 3. Persiapkan data claim
474
+ headers = {
475
+ 'Content-Type': 'application/x-www-form-urlencoded',
476
+ 'Origin': self.base_url,
477
+ 'Referer': f'{self.base_url}{coin_data["url_path"]}',
478
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
479
+ }
480
+
481
+ data = {
482
+ 'currency': coin_symbol,
483
+ 'csrf_token': csrf_token,
484
+ 'g-recaptcha-response': recaptcha_token,
485
+ 'claim': ''
486
+ }
487
+
488
+ try:
489
+ print(f"{Color.CYAN}[4/4] Mengirim claim untuk {coin_symbol}...{Color.END}")
490
+ response = self.session.post(
491
+ f'{self.base_url}{coin_data["url_path"]}',
492
+ headers=headers,
493
+ data=data,
494
+ timeout=30,
495
+ allow_redirects=True
496
+ )
497
+
498
+ print(f"{Color.CYAN}βœ“ Response status: {response.status_code}{Color.END}")
499
+
500
+ # Cek apakah claim berhasil
501
+ success_keywords = [
502
+ 'successfully', 'claimed', 'reward',
503
+ 'thank you', 'you received', 'has been added',
504
+ 'congratulation'
505
+ ]
506
+
507
+ response_lower = response.text.lower()
508
+ success = any(keyword in response_lower for keyword in success_keywords)
509
+
510
+ if success:
511
+ print(f"{Color.GREEN}βœ… Claim {coin_symbol} berhasil!{Color.END}")
512
+
513
+ # Cari jumlah reward
514
+ reward_patterns = [
515
+ r'(\d+\.?\d*)\s*' + re.escape(coin_symbol),
516
+ r'claimed\s*:\s*(\d+\.?\d*)',
517
+ r'reward\s*:\s*(\d+\.?\d*)',
518
+ r'you received.*?(\d+\.?\d*)',
519
+ r'(\d+\.?\d*)\s*coins?'
520
+ ]
521
+
522
+ for pattern in reward_patterns:
523
+ match = re.search(pattern, response.text, re.IGNORECASE)
524
+ if match:
525
+ reward = float(match.group(1))
526
+ coin_data['total_rewards'] += reward
527
+ print(f"{Color.GREEN}πŸ’° Reward: {reward} {coin_symbol}{Color.END}")
528
+ break
529
+
530
+ # Update statistik
531
+ coin_data['success_count'] += 1
532
+
533
+ # Update cookies setelah claim sukses
534
+ self.update_cookies()
535
+
536
+ else:
537
+ print(f"{Color.RED}❌ Claim {coin_symbol} gagal!{Color.END}")
538
+
539
+ # Cek error message
540
+ error_keywords = ['error', 'failed', 'try again', 'cooldown', 'already claimed', 'wait']
541
+ for keyword in error_keywords:
542
+ if keyword in response_lower:
543
+ print(f"{Color.YELLOW}⚠️ Pesan: {keyword}{Color.END}")
544
+ break
545
+
546
+ # Update total claims
547
+ coin_data['total_claims'] += 1
548
+ coin_data['last_claim'] = time.time()
549
+
550
+ # Ekstrak cooldown dari response
551
+ extracted_cooldown = self.extract_cooldown_from_response(response.text)
552
+ if extracted_cooldown:
553
+ coin_data['cooldown'] = extracted_cooldown
554
+ print(f"{Color.CYAN}⏰ Cooldown terdeteksi: {extracted_cooldown} detik{Color.END}")
555
+ else:
556
+ # Gunakan default cooldown
557
+ coin_data['cooldown'] = coin_data['default_cooldown']
558
+ print(f"{Color.CYAN}⏰ Menggunakan default cooldown: {coin_data['default_cooldown']} detik{Color.END}")
559
+
560
+ # Simpan statistik
561
+ self.save_stats()
562
+
563
+ return success, response.text
564
+
565
+ except Exception as e:
566
+ print(f"{Color.RED}❌ Error saat claim {coin_symbol}: {e}{Color.END}")
567
+ return False, str(e)
568
+
569
+ def show_cooldown_timer(self, seconds, coin_symbol):
570
+ """Tampilkan timer countdown untuk coin tertentu"""
571
+ print(f"\n{Color.YELLOW}⏰ Cooldown {coin_symbol}: {seconds} detik{Color.END}")
572
+ print(f"{Color.CYAN}{'─' * 50}{Color.END}")
573
+
574
+ for i in range(seconds):
575
+ remaining = seconds - i
576
+ progress = int((i / seconds) * 50)
577
+
578
+ # Format waktu
579
+ if remaining >= 3600:
580
+ time_str = f"{remaining//3600:02d}:{(remaining%3600)//60:02d}:{remaining%60:02d}"
581
+ elif remaining >= 60:
582
+ time_str = f"{remaining//60:02d}:{remaining%60:02d}"
583
+ else:
584
+ time_str = f"00:{remaining:02d}"
585
+
586
+ # Progress bar
587
+ bar = 'β–ˆ' * progress + 'β–‘' * (50 - progress)
588
+ percent = (i / seconds) * 100
589
+
590
+ sys.stdout.write(f'\r{Color.GREEN}[{bar}]{Color.END} {time_str} ({percent:.1f}%)')
591
+ sys.stdout.flush()
592
+
593
+ # Check every second if we should interrupt
594
+ try:
595
+ time.sleep(1)
596
+ except KeyboardInterrupt:
597
+ print(f"\n\n{Color.YELLOW}⚠️ Timer dihentikan{Color.END}")
598
+ return
599
+
600
+ print(f"\n{Color.GREEN}βœ… Cooldown {coin_symbol} selesai!{Color.END}")
601
+
602
+ def get_next_available_coin(self):
603
+ """Cari coin yang sudah siap di-claim (hanya TRUMP)"""
604
+ coin_symbol = 'TRUMP'
605
+ coin_data = self.coins[coin_symbol]
606
+ current_time = time.time()
607
+
608
+ time_since_last = current_time - coin_data['last_claim']
609
+
610
+ # Jika belum pernah di-claim atau cooldown sudah selesai
611
+ if coin_data['last_claim'] == 0 or time_since_last >= coin_data['cooldown']:
612
+ return coin_symbol, 0 # 0 detik waiting
613
+
614
+ # Hitung waktu tunggu
615
+ wait_time = coin_data['cooldown'] - time_since_last
616
+ return coin_symbol, max(0, wait_time)
617
+
618
+ def print_statistics(self):
619
+ """Tampilkan statistik khusus TRUMP"""
620
+ print(f"\n{Color.PURPLE}{Color.BOLD}πŸ“Š TRUMP STATISTIK LENGKAP{Color.END}")
621
+
622
+ coin_symbol = 'TRUMP'
623
+ coin_data = self.coins[coin_symbol]
624
+
625
+ claims = coin_data['total_claims']
626
+ success = coin_data['success_count']
627
+ rewards = coin_data['total_rewards']
628
+
629
+ if claims > 0:
630
+ success_rate = (success / claims) * 100
631
+ rate_str = f"{success_rate:.1f}%"
632
+ else:
633
+ rate_str = "0%"
634
+
635
+ print(f"{Color.BLUE}╔══════════════════════════════════════════════════════════╗{Color.END}")
636
+ print(f"{Color.BLUE}β•‘ TRUMP STATS β•‘{Color.END}")
637
+ print(f"{Color.BLUE}╠═══════════╦══════════╦══════════╦══════════╦══════════════╣{Color.END}")
638
+ print(f"{Color.BLUE}β•‘ Coin β•‘ Claims β•‘ Success β•‘ Reward β•‘ Success Rateβ•‘{Color.END}")
639
+ print(f"{Color.BLUE}╠═══════════╬══════════╬══════════╬══════════╬══════════════╣{Color.END}")
640
+ print(f"β•‘ {coin_symbol:^9} β•‘ {claims:^8} β•‘ {success:^8} β•‘ {rewards:^8.4f} β•‘ {rate_str:^12} β•‘")
641
+ print(f"{Color.BLUE}β•šβ•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•{Color.END}")
642
+
643
+ # Tampilkan info login
644
+ if self.last_login_time > 0:
645
+ last_login_dt = datetime.fromtimestamp(self.last_login_time)
646
+ time_since_login = time.time() - self.last_login_time
647
+ hours_since = int(time_since_login // 3600)
648
+ minutes_since = int((time_since_login % 3600) // 60)
649
+
650
+ print(f"{Color.CYAN}πŸͺ Last Login: {last_login_dt.strftime('%Y-%m-%d %H:%M:%S')}{Color.END}")
651
+ print(f"{Color.CYAN}⏰ Since Login: {hours_since} jam {minutes_since} menit yang lalu{Color.END}")
652
+
653
+ print(f"{Color.CYAN}πŸ”„ Total Cycles: {self.total_cycles}{Color.END}")
654
+ print(f"{Color.CYAN}πŸ• Waktu Sekarang: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}{Color.END}")
655
+
656
+ def run(self, max_cycles=100000):
657
+ """Jalankan bot dengan infinite loop khusus TRUMP"""
658
+ self.print_banner()
659
+
660
+ # Cek cookies terlebih dahulu
661
+ print(f"{Color.CYAN}[1/3] Memeriksa cookies...{Color.END}")
662
+ if self.load_cookies():
663
+ print(f"{Color.CYAN}[2/3] Memeriksa status login...{Color.END}")
664
+ if self.check_login_status():
665
+ print(f"{Color.GREEN}βœ… Login valid dengan cookies yang ada{Color.END}")
666
+ else:
667
+ print(f"{Color.YELLOW}⚠️ Cookies tidak valid, melakukan login...{Color.END}")
668
+ if not self.login():
669
+ print(f"{Color.RED}❌ Gagal login, coba lagi dalam 60 detik...{Color.END}")
670
+ time.sleep(60)
671
+ return
672
+ else:
673
+ # Jika tidak ada cookies, lakukan login
674
+ print(f"{Color.CYAN}[2/3] Melakukan login...{Color.END}")
675
+ if not self.login():
676
+ print(f"{Color.RED}❌ Gagal login, coba lagi dalam 60 detik...{Color.END}")
677
+ time.sleep(60)
678
+ return
679
+
680
+ print(f"{Color.GREEN}{'='*60}{Color.END}")
681
+ print(f"{Color.BOLD}πŸš€ MEMULAI TRUMP FAUCET BOT DENGAN COOKIES{Color.END}")
682
+ print(f"{Color.GREEN}{'='*60}{Color.END}")
683
+
684
+ try:
685
+ while self.total_cycles < max_cycles:
686
+ self.total_cycles += 1
687
+
688
+ print(f"\n{Color.CYAN}{'═' * 60}{Color.END}")
689
+ print(f"{Color.BOLD}πŸ”„ CYCLE #{self.total_cycles}{Color.END}")
690
+ print(f"{Color.CYAN}{'═' * 60}{Color.END}")
691
+
692
+ # Cek apakah perlu relogin (setiap 6 jam)
693
+ if not self.relogin_if_needed():
694
+ print(f"{Color.YELLOW}⚠️ Relogin gagal, tunggu 1 menit...{Color.END}")
695
+ time.sleep(60)
696
+ continue
697
+
698
+ # Update tabel status coin
699
+ self.print_coin_table()
700
+
701
+ # Cari coin yang siap di-claim (selalu TRUMP)
702
+ next_coin, wait_time = self.get_next_available_coin()
703
+
704
+ if wait_time > 0:
705
+ # Tunggu sampai coin siap
706
+ print(f"{Color.YELLOW}⏳ TRUMP dalam cooldown...{Color.END}")
707
+ print(f"{Color.YELLOW}⏳ Menunggu {wait_time:.0f} detik untuk {next_coin}...{Color.END}")
708
+
709
+ # Countdown tunggu
710
+ for i in range(int(wait_time)):
711
+ if i % 10 == 0: # Update setiap 10 detik
712
+ remaining = wait_time - i
713
+ mins = int(remaining // 60)
714
+ secs = int(remaining % 60)
715
+ sys.stdout.write(f'\r⏳ Menunggu: {mins:02d}:{secs:02d} ...')
716
+ sys.stdout.flush()
717
+ time.sleep(1)
718
+ print()
719
+
720
+ # Claim coin yang tersedia (selalu TRUMP)
721
+ success, response = self.claim_coin(next_coin)
722
+
723
+ if not success:
724
+ # Jika gagal, coba login ulang
725
+ print(f"{Color.YELLOW}⚠️ Claim TRUMP gagal, coba login ulang...{Color.END}")
726
+ if self.login():
727
+ continue
728
+ else:
729
+ print(f"{Color.RED}❌ Gagal login ulang, tunggu 5 menit...{Color.END}")
730
+ time.sleep(300)
731
+
732
+ # Tampilkan statistik setelah setiap claim
733
+ self.print_statistics()
734
+
735
+ # Simpan statistik
736
+ self.save_stats()
737
+
738
+ # Tunggu sebentar sebelum cek coin berikutnya
739
+ time.sleep(2)
740
+
741
+ except KeyboardInterrupt:
742
+ print(f"\n\n{Color.YELLOW}⚠️ Bot dihentikan oleh user{Color.END}")
743
+ except Exception as e:
744
+ print(f"\n{Color.RED}❌ Error tidak terduga: {e}{Color.END}")
745
+ print(f"{Color.YELLOW}⚠️ Restart dalam 30 detik...{Color.END}")
746
+ time.sleep(30)
747
+ return False
748
+
749
+ finally:
750
+ # Tampilkan statistik akhir
751
+ print(f"\n{Color.PURPLE}{'='*60}{Color.END}")
752
+ print(f"{Color.BOLD}🏁 STATISTIK AKHIR TRUMP{Color.END}")
753
+ print(f"{Color.PURPLE}{'='*60}{Color.END}")
754
+ self.print_statistics()
755
+ self.save_stats()
756
+
757
+ return True
758
+
759
+ def main():
760
+ """Fungsi utama dengan infinite loop untuk Docker (khusus TRUMP)"""
761
+ print(f"{Color.CYAN}πŸš€ Starting TRUMP Faucet Bot with Cookies Management{Color.END}")
762
+
763
+ # Konfigurasi dari environment variables atau default
764
+ EMAIL = os.getenv('EMAIL', 'gadisk820@gmail.com')
765
+ MAX_CYCLES = int(os.getenv('MAX_CYCLES', '100000'))
766
+
767
+ print(f"{Color.CYAN}πŸ“§ Email: {EMAIL}{Color.END}")
768
+ print(f"{Color.CYAN}πŸ” Max Cycles: {MAX_CYCLES}{Color.END}")
769
+ print(f"{Color.CYAN}⏰ Timezone: {os.getenv('TZ', 'Asia/Jakarta')}{Color.END}")
770
+ print(f"{Color.CYAN}πŸͺ Cookies Management: Enabled{Color.END}")
771
+ print(f"{Color.CYAN}πŸ”„ Relogin Interval: Every 6 hours{Color.END}\n")
772
+
773
+ consecutive_failures = 0
774
+ max_consecutive_failures = 5
775
+
776
+ while True:
777
+ try:
778
+ bot = TrumpFaucetBot(EMAIL)
779
+ success = bot.run(max_cycles=MAX_CYCLES)
780
+
781
+ if success:
782
+ consecutive_failures = 0
783
+ print(f"{Color.GREEN}βœ… Cycle completed successfully{Color.END}")
784
+ else:
785
+ consecutive_failures += 1
786
+ print(f"{Color.RED}❌ Cycle failed ({consecutive_failures}/{max_consecutive_failures}){Color.END}")
787
+
788
+ if consecutive_failures >= max_consecutive_failures:
789
+ print(f"{Color.RED}⚠️ Too many consecutive failures, waiting 5 minutes...{Color.END}")
790
+ time.sleep(300) # Tunggu 5 menit
791
+ consecutive_failures = 0
792
+
793
+ # Tunggu sebentar sebelum restart cycle
794
+ print(f"{Color.CYAN}⏳ Restarting in 10 seconds...{Color.END}")
795
+ time.sleep(10)
796
+
797
+ except KeyboardInterrupt:
798
+ print(f"\n{Color.YELLOW}πŸ‘‹ Bot stopped by user{Color.END}")
799
+ break
800
+ except Exception as e:
801
+ print(f"{Color.RED}⚠️ Unexpected error: {e}{Color.END}")
802
+ print(f"{Color.CYAN}⏳ Restarting in 30 seconds...{Color.END}")
803
+ time.sleep(30)
804
+
805
+ if __name__ == "__main__":
806
+ # Install dependencies jika diperlukan
807
+ try:
808
+ import requests
809
+ except ImportError:
810
+ print("Menginstall requests...")
811
+ import subprocess
812
+ subprocess.check_call(["pip", "install", "requests"])
813
+
814
+ # Jalankan
815
+ try:
816
+ main()
817
+ except KeyboardInterrupt:
818
+ print(f"\n\n{Color.YELLOW}πŸ‘‹ Sampai jumpa!{Color.END}")
819
+ except Exception as e:
820
+ print(f"\n{Color.RED}❌ Error: {e}{Color.END}")
docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ multi-coin-bot:
5
+ build: .
6
+ container_name: multi-coin-faucet-bot
7
+ restart: unless-stopped
8
+ volumes:
9
+ - ./logs:/app/logs
10
+ - ./data:/app/data
11
+ environment:
12
+ - TZ=Asia/Jakarta
13
+ - EMAIL=gi2h27@gmail.com
14
+ - MAX_CYCLES=100000
15
+ - SOLVER_URL=https://gi2h-xxx.hf.space
16
+ - SOLVER_KEY=00000000000000000000#0000000000000000000#000000000000000000#
17
+ - PYTHONUNBUFFERED=1
18
+ logging:
19
+ driver: "json-file"
20
+ options:
21
+ max-size: "10m"
22
+ max-file: "3"
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ requests==2.31.0
2
+ colorama==0.4.6
3
+ python-dotenv==1.0.0