Fourstore commited on
Commit
99605e4
Β·
verified Β·
1 Parent(s): 8e7ed20

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -143
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=30)
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"πŸ“¦ Ditemukan {len(items)} item range")
103
 
104
- for idx, item in enumerate(items, 1):
105
  try:
106
- name_div = item.select_one(".col-sm-4")
107
- if not name_div:
108
- print(f" {idx}. ❌ Tidak ada name_div")
109
- continue
110
-
111
- rng = name_div.get_text(strip=True)
112
- print(f" {idx}. Nama range: {rng}")
 
 
 
 
 
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(count_text)
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" βœ… {rng} - {count} SMS")
129
 
130
  except Exception as e:
131
- print(f" ❌ Error parse item {idx}: {e}")
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=30)
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
- divs = soup.find_all("div", onclick=True)
166
- print(f" πŸ“¦ Ditemukan {len(divs)} div dengan onclick")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
- for div in divs:
169
- try:
170
- onclick = div.get("onclick", "")
171
- if "getDetialsNumber" in onclick:
172
- num = div.get_text(strip=True)
173
- print(f" Nomor ditemukan: {num}")
 
 
 
 
 
 
 
 
 
174
 
175
- if num and num.isdigit() and len(num) > 5:
176
- parent = div.find_parent("div", class_="card")
177
- count = 0
178
- if parent:
179
- p_tag = parent.find("p", class_="mb-0 pb-0")
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" πŸ“€ POST ke: {GET_SMS_URL}")
221
 
222
  r = session.post(GET_SMS_URL, data={
223
  "_token": csrf_token,
224
  "start": date,
225
  "end": date,
226
  "Number": number,
227
- "Range": range_name
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 idx, card in enumerate(cards, 1):
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
- else:
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
- m = re.search(r"\b(\d{4,6})\b", text)
277
- if not m:
278
- m = re.search(r"\b(\d{3}[- ]?\d{3})\b", text)
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! Cek session atau struktur HTML")
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" πŸ”₯πŸ”₯πŸ”₯ RANGE BERUBAH: {country} πŸ”₯πŸ”₯πŸ”₯")
626
- print(f" πŸ“Š {prev_count} β†’ {current_count} SMS (baru: {current_count - prev_count})")
627
  range_counter[rng] = current_count
628
 
629
  numbers_data = get_numbers_with_count(rng)
630
 
631
- if numbers_data:
632
- print(f" πŸ“ž Ditemukan {len(numbers_data)} nomor dengan SMS")
 
 
 
633
 
634
- for number_item in numbers_data:
635
- num = number_item["number"]
636
- num_count = number_item["count"]
637
- key = f"{rng}-{num}"
638
- prev_num_count = sms_counter.get(key, 0)
639
 
640
- print(f" πŸ“± Nomor: {mask_number(num)} - Count: {num_count} (prev: {prev_num_count})")
 
641
 
642
- if num_count > prev_num_count:
643
- print(f" πŸ“¨ {prev_num_count} β†’ {num_count} SMS (baru: {num_count - prev_num_count})")
644
- sms_counter[key] = num_count
645
-
646
- all_sms = get_sms_fast(rng, num)
647
- new_sms = all_sms[prev_num_count:]
648
-
649
- if new_sms:
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" βœ… Selesai proses {country}")
672
  time.sleep(0.5)
673
- else:
674
- print(f" ⏭️ RANGE TIDAK BERUBAH (count sama: {current_count})")
675
 
676
- print("\n⏳ Tidur 3 detik sebelum scan ulang...")
677
- time.sleep(3)
678
 
679
  except Exception as e:
680
- print(f"\n❌❌❌ ERROR UTAMA: {str(e)}")
681
- print(f"πŸ“‹ Tipe error: {type(e).__name__}")
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")