Update app.py
Browse files
app.py
CHANGED
|
@@ -85,39 +85,39 @@ def get_ranges_with_count():
|
|
| 85 |
|
| 86 |
date = get_search_date()
|
| 87 |
print(f"\nπ AMBIL RANGE - Tanggal: {date}")
|
| 88 |
-
print(f"π€ POST ke: {GET_RANGE_URL}")
|
| 89 |
|
| 90 |
r = session.post(GET_RANGE_URL, data={
|
| 91 |
"_token": csrf_token,
|
| 92 |
"from": date,
|
| 93 |
"to": date
|
| 94 |
-
}, timeout=
|
| 95 |
-
|
| 96 |
-
print(f"π Response status: {r.status_code}")
|
| 97 |
-
print(f"π Response preview: {r.text[:200]}")
|
| 98 |
|
| 99 |
soup = BeautifulSoup(r.text, "html.parser")
|
| 100 |
ranges_data = []
|
|
|
|
| 101 |
items = soup.select(".item")
|
| 102 |
-
print(f"π¦
|
| 103 |
|
| 104 |
-
for
|
| 105 |
try:
|
| 106 |
-
|
| 107 |
-
if
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
|
| 114 |
count_p = item.select_one(".col-3 .mb-0.pb-0")
|
| 115 |
count = 0
|
| 116 |
if count_p:
|
| 117 |
-
count_text = count_p.get_text(strip=True)
|
| 118 |
-
print(f" Count text: '{count_text}'")
|
| 119 |
try:
|
| 120 |
-
count = int(
|
| 121 |
except:
|
| 122 |
count = 0
|
| 123 |
|
|
@@ -125,10 +125,10 @@ def get_ranges_with_count():
|
|
| 125 |
"name": rng,
|
| 126 |
"count": count
|
| 127 |
})
|
| 128 |
-
print(f"
|
| 129 |
|
| 130 |
except Exception as e:
|
| 131 |
-
print(f" β Error parse
|
| 132 |
continue
|
| 133 |
|
| 134 |
return ranges_data
|
|
@@ -144,54 +144,62 @@ def get_numbers_with_count(rng):
|
|
| 144 |
|
| 145 |
date = get_search_date()
|
| 146 |
print(f"\n π AMBIL NOMOR: {rng}")
|
| 147 |
-
print(f" π€ POST ke: {GET_NUMBER_URL}")
|
| 148 |
|
| 149 |
r = session.post(GET_NUMBER_URL, data={
|
| 150 |
"_token": csrf_token,
|
| 151 |
"start": date,
|
| 152 |
"end": date,
|
| 153 |
"range": rng
|
| 154 |
-
}, timeout=
|
| 155 |
-
|
| 156 |
-
print(f" π Status: {r.status_code}")
|
| 157 |
|
| 158 |
-
if r.status_code != 200:
|
| 159 |
-
print(f" β Gagal! Status: {r.status_code}")
|
| 160 |
-
return []
|
| 161 |
-
|
| 162 |
soup = BeautifulSoup(r.text, "html.parser")
|
| 163 |
numbers_data = []
|
| 164 |
|
| 165 |
-
|
| 166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
count
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
if p_tag:
|
| 181 |
-
try:
|
| 182 |
-
count = int(p_tag.get_text(strip=True))
|
| 183 |
-
except:
|
| 184 |
-
count = 0
|
| 185 |
-
|
| 186 |
-
numbers_data.append({
|
| 187 |
-
"number": num,
|
| 188 |
-
"count": count
|
| 189 |
-
})
|
| 190 |
-
print(f" β
{mask_number(num)} - {count} SMS")
|
| 191 |
-
|
| 192 |
-
except Exception as e:
|
| 193 |
-
print(f" β Error: {e}")
|
| 194 |
-
continue
|
| 195 |
|
| 196 |
return numbers_data
|
| 197 |
|
|
@@ -210,58 +218,40 @@ def get_sms_fast(rng, number):
|
|
| 210 |
if cache_key in sms_cache:
|
| 211 |
timestamp, results = sms_cache[cache_key]
|
| 212 |
if time.time() - timestamp < 5:
|
| 213 |
-
print(f" πΎ Cache hit: {len(results)} SMS")
|
| 214 |
return results
|
| 215 |
|
| 216 |
-
parts = rng.split()
|
| 217 |
-
range_name = parts[0] + " " + parts[1] if len(parts) >= 2 else rng
|
| 218 |
-
|
| 219 |
print(f" π¨ AMBIL SMS: {mask_number(number)}")
|
| 220 |
-
print(f" π€
|
| 221 |
|
| 222 |
r = session.post(GET_SMS_URL, data={
|
| 223 |
"_token": csrf_token,
|
| 224 |
"start": date,
|
| 225 |
"end": date,
|
| 226 |
"Number": number,
|
| 227 |
-
"Range":
|
| 228 |
}, timeout=30)
|
| 229 |
|
| 230 |
-
print(f" π Status: {r.status_code}")
|
| 231 |
-
|
| 232 |
-
if r.status_code != 200:
|
| 233 |
-
print(f" β Gagal! Status: {r.status_code}")
|
| 234 |
-
return []
|
| 235 |
-
|
| 236 |
soup = BeautifulSoup(r.text, "html.parser")
|
| 237 |
results = []
|
|
|
|
| 238 |
cards = soup.select("div.card.card-body")
|
| 239 |
-
print(f" π¦ Ditemukan {len(cards)} SMS cards")
|
| 240 |
|
| 241 |
-
for
|
| 242 |
try:
|
| 243 |
service = "UNKNOWN"
|
| 244 |
service_div = card.select_one("div.col-sm-4")
|
| 245 |
if service_div:
|
| 246 |
raw = service_div.get_text(strip=True)
|
| 247 |
service = map_service(raw)
|
| 248 |
-
print(f" Card {idx}: Service = {service}")
|
| 249 |
|
| 250 |
msg_p = card.find("p", class_="mb-0 pb-0")
|
| 251 |
if msg_p:
|
| 252 |
sms = msg_p.get_text(strip=True)
|
| 253 |
-
print(f" SMS: {sms[:50]}...")
|
| 254 |
otp = extract_otp(sms)
|
| 255 |
if otp:
|
| 256 |
results.append((service, sms, otp))
|
| 257 |
print(f" β
OTP: {otp} - {service}")
|
| 258 |
-
|
| 259 |
-
print(f" β οΈ Tidak ada OTP dalam SMS")
|
| 260 |
-
else:
|
| 261 |
-
print(f" β Tidak ada msg_p")
|
| 262 |
-
|
| 263 |
-
except Exception as e:
|
| 264 |
-
print(f" β Error parse card {idx}: {e}")
|
| 265 |
continue
|
| 266 |
|
| 267 |
sms_cache[cache_key] = (time.time(), results)
|
|
@@ -273,11 +263,17 @@ def get_sms_fast(rng, number):
|
|
| 273 |
|
| 274 |
def extract_otp(text):
|
| 275 |
if not text: return None
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
if m:
|
| 280 |
return m.group(0).replace("-", "").replace(" ", "")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
return None
|
| 282 |
|
| 283 |
def clean_country(rng):
|
|
@@ -312,7 +308,6 @@ def add_otp_log(country, number, service, otp, sms):
|
|
| 312 |
}
|
| 313 |
otp_logs.appendleft(log_entry)
|
| 314 |
broadcast_sse(log_entry)
|
| 315 |
-
print(f" π OTP TERSIMPAN DI DASHBOARD: {otp} - {service}")
|
| 316 |
return log_entry
|
| 317 |
|
| 318 |
def broadcast_sse(data):
|
|
@@ -576,10 +571,6 @@ def main():
|
|
| 576 |
print(f"β³ Login gagal, percobaan ke-{login_attempts}/5...")
|
| 577 |
time.sleep(3)
|
| 578 |
|
| 579 |
-
if not LOGIN_SUCCESS:
|
| 580 |
-
print("\nβββ GAGAL LOGIN! BOT TIDAK BISA JALAN βββ")
|
| 581 |
-
print("π‘ CEK USERNAME/PASSWORD!")
|
| 582 |
-
|
| 583 |
last_cleanup = time.time()
|
| 584 |
loop_count = 0
|
| 585 |
|
|
@@ -606,87 +597,58 @@ def main():
|
|
| 606 |
ranges_data = get_ranges_with_count()
|
| 607 |
|
| 608 |
if not ranges_data:
|
| 609 |
-
print("β οΈ TIDAK ADA DATA RANGE!
|
| 610 |
time.sleep(5)
|
| 611 |
continue
|
| 612 |
|
| 613 |
-
print(f"\nπ RANGES DITEMUKAN: {len(ranges_data)}")
|
| 614 |
-
|
| 615 |
for range_item in ranges_data:
|
| 616 |
rng = range_item["name"]
|
| 617 |
current_count = range_item["count"]
|
| 618 |
prev_count = range_counter.get(rng, 0)
|
| 619 |
|
| 620 |
-
print(f"\n π RANGE: {rng}")
|
| 621 |
-
print(f" Current: {current_count} | Previous: {prev_count}")
|
| 622 |
-
|
| 623 |
if current_count > prev_count:
|
| 624 |
country = clean_country(rng)
|
| 625 |
-
print(f"
|
| 626 |
-
print(f"
|
| 627 |
range_counter[rng] = current_count
|
| 628 |
|
| 629 |
numbers_data = get_numbers_with_count(rng)
|
| 630 |
|
| 631 |
-
|
| 632 |
-
|
|
|
|
|
|
|
|
|
|
| 633 |
|
| 634 |
-
|
| 635 |
-
|
| 636 |
-
num_count
|
| 637 |
-
key =
|
| 638 |
-
prev_num_count = sms_counter.get(key, 0)
|
| 639 |
|
| 640 |
-
|
|
|
|
| 641 |
|
| 642 |
-
|
| 643 |
-
|
| 644 |
-
|
| 645 |
-
|
| 646 |
-
|
| 647 |
-
|
| 648 |
-
|
| 649 |
-
|
| 650 |
-
print(f" π¦ {len(new_sms)} SMS BARU DITEMUKAN!")
|
| 651 |
-
|
| 652 |
-
for service, sms, otp in new_sms:
|
| 653 |
-
if otp:
|
| 654 |
-
sms_id = f"{rng}-{num}-{otp}"
|
| 655 |
-
if sms_id not in sent_cache:
|
| 656 |
-
masked = mask_number(num)
|
| 657 |
-
sent_cache.add(sms_id)
|
| 658 |
-
add_otp_log(country, masked, service, otp, sms)
|
| 659 |
-
print(f" β
OTP: {otp} - {service} (DITAMBAHKAN KE DASHBOARD)")
|
| 660 |
-
else:
|
| 661 |
-
print(f" βοΈ OTP {otp} sudah ada di cache")
|
| 662 |
-
else:
|
| 663 |
-
print(f" β οΈ SMS tanpa OTP")
|
| 664 |
-
else:
|
| 665 |
-
print(f" β οΈ TIDAK ADA SMS BARU (semua sudah diproses)")
|
| 666 |
-
else:
|
| 667 |
-
print(f" βοΈ Tidak ada SMS baru untuk nomor ini")
|
| 668 |
-
else:
|
| 669 |
-
print(f" β οΈ TIDAK ADA NOMOR dengan SMS di range {country}")
|
| 670 |
|
| 671 |
-
print(f"
|
| 672 |
time.sleep(0.5)
|
| 673 |
-
else:
|
| 674 |
-
print(f" βοΈ RANGE TIDAK BERUBAH (count sama: {current_count})")
|
| 675 |
|
| 676 |
-
print("\nβ³ Tidur
|
| 677 |
-
time.sleep(
|
| 678 |
|
| 679 |
except Exception as e:
|
| 680 |
-
print(f"
|
| 681 |
-
|
| 682 |
-
print("β³ Coba lagi dalam 5 detik...")
|
| 683 |
-
time.sleep(5)
|
| 684 |
|
| 685 |
if __name__ == "__main__":
|
| 686 |
try:
|
| 687 |
main()
|
| 688 |
except KeyboardInterrupt:
|
| 689 |
-
print("\nπ BOT STOPPED")
|
| 690 |
-
except Exception as e:
|
| 691 |
-
print(f"\nπ₯ FATAL ERROR: {e}")
|
| 692 |
-
time.sleep(5)
|
|
|
|
| 85 |
|
| 86 |
date = get_search_date()
|
| 87 |
print(f"\nπ AMBIL RANGE - Tanggal: {date}")
|
|
|
|
| 88 |
|
| 89 |
r = session.post(GET_RANGE_URL, data={
|
| 90 |
"_token": csrf_token,
|
| 91 |
"from": date,
|
| 92 |
"to": date
|
| 93 |
+
}, timeout=15)
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
soup = BeautifulSoup(r.text, "html.parser")
|
| 96 |
ranges_data = []
|
| 97 |
+
|
| 98 |
items = soup.select(".item")
|
| 99 |
+
print(f"π¦ Total items: {len(items)}")
|
| 100 |
|
| 101 |
+
for item in items:
|
| 102 |
try:
|
| 103 |
+
card = item.select_one(".card[onclick]")
|
| 104 |
+
if card:
|
| 105 |
+
onclick = card.get("onclick", "")
|
| 106 |
+
match = re.search(r"getDetials\('(.+?)'\)", onclick)
|
| 107 |
+
if match:
|
| 108 |
+
rng = match.group(1)
|
| 109 |
+
else:
|
| 110 |
+
name_div = item.select_one(".col-sm-4")
|
| 111 |
+
rng = name_div.get_text(strip=True) if name_div else "UNKNOWN"
|
| 112 |
+
else:
|
| 113 |
+
name_div = item.select_one(".col-sm-4")
|
| 114 |
+
rng = name_div.get_text(strip=True) if name_div else "UNKNOWN"
|
| 115 |
|
| 116 |
count_p = item.select_one(".col-3 .mb-0.pb-0")
|
| 117 |
count = 0
|
| 118 |
if count_p:
|
|
|
|
|
|
|
| 119 |
try:
|
| 120 |
+
count = int(count_p.get_text(strip=True))
|
| 121 |
except:
|
| 122 |
count = 0
|
| 123 |
|
|
|
|
| 125 |
"name": rng,
|
| 126 |
"count": count
|
| 127 |
})
|
| 128 |
+
print(f" β
{rng} - {count} SMS")
|
| 129 |
|
| 130 |
except Exception as e:
|
| 131 |
+
print(f" β Error parse: {e}")
|
| 132 |
continue
|
| 133 |
|
| 134 |
return ranges_data
|
|
|
|
| 144 |
|
| 145 |
date = get_search_date()
|
| 146 |
print(f"\n π AMBIL NOMOR: {rng}")
|
|
|
|
| 147 |
|
| 148 |
r = session.post(GET_NUMBER_URL, data={
|
| 149 |
"_token": csrf_token,
|
| 150 |
"start": date,
|
| 151 |
"end": date,
|
| 152 |
"range": rng
|
| 153 |
+
}, timeout=15)
|
|
|
|
|
|
|
| 154 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
soup = BeautifulSoup(r.text, "html.parser")
|
| 156 |
numbers_data = []
|
| 157 |
|
| 158 |
+
# METHOD 1: Extract dari onclick attribute
|
| 159 |
+
for div in soup.find_all("div", onclick=True):
|
| 160 |
+
onclick = div.get("onclick", "")
|
| 161 |
+
match = re.search(r"getDetialsNumber\w+\('(\d+)',\s*'(\d+)'\)", onclick)
|
| 162 |
+
if match:
|
| 163 |
+
num = match.group(1)
|
| 164 |
+
id_number = match.group(2)
|
| 165 |
+
|
| 166 |
+
parent = div.find_parent("div", class_="card")
|
| 167 |
+
count = 0
|
| 168 |
+
if parent:
|
| 169 |
+
p_tag = parent.find("p", class_="mb-0 pb-0")
|
| 170 |
+
if p_tag:
|
| 171 |
+
try:
|
| 172 |
+
count = int(p_tag.get_text(strip=True))
|
| 173 |
+
except:
|
| 174 |
+
count = 0
|
| 175 |
+
|
| 176 |
+
numbers_data.append({
|
| 177 |
+
"number": num,
|
| 178 |
+
"count": count
|
| 179 |
+
})
|
| 180 |
+
print(f" β
{mask_number(num)} - {count} SMS")
|
| 181 |
|
| 182 |
+
# METHOD 2: Extract dari teks div
|
| 183 |
+
if len(numbers_data) == 0:
|
| 184 |
+
for div in soup.find_all("div", class_="col-sm-4"):
|
| 185 |
+
text = div.get_text(strip=True)
|
| 186 |
+
if re.match(r'^\d{10,}$', text):
|
| 187 |
+
num = text
|
| 188 |
+
parent = div.find_parent("div", class_="card")
|
| 189 |
+
count = 0
|
| 190 |
+
if parent:
|
| 191 |
+
p_tag = parent.find("p", class_="mb-0 pb-0")
|
| 192 |
+
if p_tag:
|
| 193 |
+
try:
|
| 194 |
+
count = int(p_tag.get_text(strip=True))
|
| 195 |
+
except:
|
| 196 |
+
count = 0
|
| 197 |
|
| 198 |
+
numbers_data.append({
|
| 199 |
+
"number": num,
|
| 200 |
+
"count": count
|
| 201 |
+
})
|
| 202 |
+
print(f" β
{mask_number(num)} - {count} SMS")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
|
| 204 |
return numbers_data
|
| 205 |
|
|
|
|
| 218 |
if cache_key in sms_cache:
|
| 219 |
timestamp, results = sms_cache[cache_key]
|
| 220 |
if time.time() - timestamp < 5:
|
|
|
|
| 221 |
return results
|
| 222 |
|
|
|
|
|
|
|
|
|
|
| 223 |
print(f" π¨ AMBIL SMS: {mask_number(number)}")
|
| 224 |
+
print(f" π€ Range: '{rng}'")
|
| 225 |
|
| 226 |
r = session.post(GET_SMS_URL, data={
|
| 227 |
"_token": csrf_token,
|
| 228 |
"start": date,
|
| 229 |
"end": date,
|
| 230 |
"Number": number,
|
| 231 |
+
"Range": rng
|
| 232 |
}, timeout=30)
|
| 233 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
soup = BeautifulSoup(r.text, "html.parser")
|
| 235 |
results = []
|
| 236 |
+
|
| 237 |
cards = soup.select("div.card.card-body")
|
|
|
|
| 238 |
|
| 239 |
+
for card in cards:
|
| 240 |
try:
|
| 241 |
service = "UNKNOWN"
|
| 242 |
service_div = card.select_one("div.col-sm-4")
|
| 243 |
if service_div:
|
| 244 |
raw = service_div.get_text(strip=True)
|
| 245 |
service = map_service(raw)
|
|
|
|
| 246 |
|
| 247 |
msg_p = card.find("p", class_="mb-0 pb-0")
|
| 248 |
if msg_p:
|
| 249 |
sms = msg_p.get_text(strip=True)
|
|
|
|
| 250 |
otp = extract_otp(sms)
|
| 251 |
if otp:
|
| 252 |
results.append((service, sms, otp))
|
| 253 |
print(f" β
OTP: {otp} - {service}")
|
| 254 |
+
except:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
continue
|
| 256 |
|
| 257 |
sms_cache[cache_key] = (time.time(), results)
|
|
|
|
| 263 |
|
| 264 |
def extract_otp(text):
|
| 265 |
if not text: return None
|
| 266 |
+
|
| 267 |
+
# Cari pola 3 digit - 3 digit (530-736)
|
| 268 |
+
m = re.search(r"\b(\d{3}[- ]?\d{3})\b", text)
|
| 269 |
if m:
|
| 270 |
return m.group(0).replace("-", "").replace(" ", "")
|
| 271 |
+
|
| 272 |
+
# Cari pola 4-6 digit biasa
|
| 273 |
+
m = re.search(r"\b(\d{4,6})\b", text)
|
| 274 |
+
if m:
|
| 275 |
+
return m.group(0)
|
| 276 |
+
|
| 277 |
return None
|
| 278 |
|
| 279 |
def clean_country(rng):
|
|
|
|
| 308 |
}
|
| 309 |
otp_logs.appendleft(log_entry)
|
| 310 |
broadcast_sse(log_entry)
|
|
|
|
| 311 |
return log_entry
|
| 312 |
|
| 313 |
def broadcast_sse(data):
|
|
|
|
| 571 |
print(f"β³ Login gagal, percobaan ke-{login_attempts}/5...")
|
| 572 |
time.sleep(3)
|
| 573 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 574 |
last_cleanup = time.time()
|
| 575 |
loop_count = 0
|
| 576 |
|
|
|
|
| 597 |
ranges_data = get_ranges_with_count()
|
| 598 |
|
| 599 |
if not ranges_data:
|
| 600 |
+
print("β οΈ TIDAK ADA DATA RANGE!")
|
| 601 |
time.sleep(5)
|
| 602 |
continue
|
| 603 |
|
|
|
|
|
|
|
| 604 |
for range_item in ranges_data:
|
| 605 |
rng = range_item["name"]
|
| 606 |
current_count = range_item["count"]
|
| 607 |
prev_count = range_counter.get(rng, 0)
|
| 608 |
|
|
|
|
|
|
|
|
|
|
| 609 |
if current_count > prev_count:
|
| 610 |
country = clean_country(rng)
|
| 611 |
+
print(f"\nπ₯ RANGE BERUBAH: {country}")
|
| 612 |
+
print(f" π {prev_count} β {current_count} SMS (baru: {current_count - prev_count})")
|
| 613 |
range_counter[rng] = current_count
|
| 614 |
|
| 615 |
numbers_data = get_numbers_with_count(rng)
|
| 616 |
|
| 617 |
+
for number_item in numbers_data:
|
| 618 |
+
num = number_item["number"]
|
| 619 |
+
num_count = number_item["count"]
|
| 620 |
+
key = f"{rng}-{num}"
|
| 621 |
+
prev_num_count = sms_counter.get(key, 0)
|
| 622 |
|
| 623 |
+
if num_count > prev_num_count:
|
| 624 |
+
print(f" π± Nomor: {mask_number(num)}")
|
| 625 |
+
print(f" π¨ {prev_num_count} β {num_count} SMS (baru: {num_count - prev_num_count})")
|
| 626 |
+
sms_counter[key] = num_count
|
|
|
|
| 627 |
|
| 628 |
+
all_sms = get_sms_fast(rng, num)
|
| 629 |
+
new_sms = all_sms[prev_num_count:]
|
| 630 |
|
| 631 |
+
for service, sms, otp in new_sms:
|
| 632 |
+
if otp:
|
| 633 |
+
sms_id = f"{rng}-{num}-{otp}"
|
| 634 |
+
if sms_id not in sent_cache:
|
| 635 |
+
masked = mask_number(num)
|
| 636 |
+
sent_cache.add(sms_id)
|
| 637 |
+
add_otp_log(country, masked, service, otp, sms)
|
| 638 |
+
print(f" β
OTP: {otp} - {service}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 639 |
|
| 640 |
+
print(f" β
Selesai proses {country}")
|
| 641 |
time.sleep(0.5)
|
|
|
|
|
|
|
| 642 |
|
| 643 |
+
print("\nβ³ Tidur 2 detik...")
|
| 644 |
+
time.sleep(2)
|
| 645 |
|
| 646 |
except Exception as e:
|
| 647 |
+
print(f"β Error: {e}")
|
| 648 |
+
time.sleep(3)
|
|
|
|
|
|
|
| 649 |
|
| 650 |
if __name__ == "__main__":
|
| 651 |
try:
|
| 652 |
main()
|
| 653 |
except KeyboardInterrupt:
|
| 654 |
+
print("\nπ BOT STOPPED")
|
|
|
|
|
|
|
|
|