amjadyt 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- amjadyt-0.0.1/PKG-INFO +40 -0
- amjadyt-0.0.1/README.md +30 -0
- amjadyt-0.0.1/pyproject.toml +17 -0
- amjadyt-0.0.1/setup.cfg +4 -0
- amjadyt-0.0.1/src/amjadyt/__init__.py +0 -0
- amjadyt-0.0.1/src/amjadyt/func.py +460 -0
- amjadyt-0.0.1/src/amjadyt.egg-info/PKG-INFO +40 -0
- amjadyt-0.0.1/src/amjadyt.egg-info/SOURCES.txt +8 -0
- amjadyt-0.0.1/src/amjadyt.egg-info/dependency_links.txt +1 -0
- amjadyt-0.0.1/src/amjadyt.egg-info/top_level.txt +1 -0
amjadyt-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: amjadyt
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Kumpulan fungsi untuk scriping
|
|
5
|
+
Author-email: Solihul Amjad <amjadyt348@anda.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Requires-Python: >=3.7
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# Functions Untuk Scripting
|
|
12
|
+
# Fitur
|
|
13
|
+
- class Requests
|
|
14
|
+
- class Functions
|
|
15
|
+
- class Display
|
|
16
|
+
- class Baypas captcha Multibot & xevil
|
|
17
|
+
- Baypas Icon Captcha
|
|
18
|
+
- html scrap (menggunakan BeautifulSoup)
|
|
19
|
+
|
|
20
|
+
# Example
|
|
21
|
+
#### Cara Import
|
|
22
|
+
```from class import*```
|
|
23
|
+
#### Requests
|
|
24
|
+
```response = Requests.curl('https://example.com')```
|
|
25
|
+
#### Functions
|
|
26
|
+
```Functions.setConfig('nama_data')```
|
|
27
|
+
#### Baypas Captcha
|
|
28
|
+
panggil function menu api dulu sebelum memanggil class Baypas Captch
|
|
29
|
+
###### Example
|
|
30
|
+
function menu api
|
|
31
|
+
```HOST_CAP,API_CAP = Functions.menu_api()`
|
|
32
|
+
lalu panggil function Baypas Captcha nya
|
|
33
|
+
cap = Captcha.Recaptchav2(sitekey,pageurl)```
|
|
34
|
+
#### Baypass Icon Captcha
|
|
35
|
+
###### Example
|
|
36
|
+
```baypas = IconBypass(host, headers)```
|
|
37
|
+
```icon = baypas.icon_bypass(iconToken)```
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
amjadyt-0.0.1/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Functions Untuk Scripting
|
|
2
|
+
# Fitur
|
|
3
|
+
- class Requests
|
|
4
|
+
- class Functions
|
|
5
|
+
- class Display
|
|
6
|
+
- class Baypas captcha Multibot & xevil
|
|
7
|
+
- Baypas Icon Captcha
|
|
8
|
+
- html scrap (menggunakan BeautifulSoup)
|
|
9
|
+
|
|
10
|
+
# Example
|
|
11
|
+
#### Cara Import
|
|
12
|
+
```from class import*```
|
|
13
|
+
#### Requests
|
|
14
|
+
```response = Requests.curl('https://example.com')```
|
|
15
|
+
#### Functions
|
|
16
|
+
```Functions.setConfig('nama_data')```
|
|
17
|
+
#### Baypas Captcha
|
|
18
|
+
panggil function menu api dulu sebelum memanggil class Baypas Captch
|
|
19
|
+
###### Example
|
|
20
|
+
function menu api
|
|
21
|
+
```HOST_CAP,API_CAP = Functions.menu_api()`
|
|
22
|
+
lalu panggil function Baypas Captcha nya
|
|
23
|
+
cap = Captcha.Recaptchav2(sitekey,pageurl)```
|
|
24
|
+
#### Baypass Icon Captcha
|
|
25
|
+
###### Example
|
|
26
|
+
```baypas = IconBypass(host, headers)```
|
|
27
|
+
```icon = baypas.icon_bypass(iconToken)```
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "amjadyt"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name="Solihul Amjad", email="amjadyt348@anda.com" },
|
|
10
|
+
]
|
|
11
|
+
description = "Kumpulan fungsi untuk scriping"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.7"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
]
|
amjadyt-0.0.1/setup.cfg
ADDED
|
File without changes
|
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# module python
|
|
2
|
+
import requests
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import time
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
import base64
|
|
9
|
+
import random
|
|
10
|
+
from urllib.parse import urlparse
|
|
11
|
+
from typing import Dict, Union, List, Optional, Tuple
|
|
12
|
+
from bs4 import BeautifulSoup
|
|
13
|
+
|
|
14
|
+
class Colors:
|
|
15
|
+
DASAR = '\x1b[0m'
|
|
16
|
+
TEBAL = '\x1b[1m'
|
|
17
|
+
GARIS = '\x1b[4m'
|
|
18
|
+
GERAK = '\x1b[5m'
|
|
19
|
+
# Warna Teks
|
|
20
|
+
MERAH = '\x1b[31;1m'
|
|
21
|
+
HIJAU = '\x1b[32;1m'
|
|
22
|
+
KUNING = '\x1b[33;1m'
|
|
23
|
+
BIRU = '\x1b[34;1m'
|
|
24
|
+
UNGU = '\x1b[35;1m'
|
|
25
|
+
CYAN = '\x1b[36;1m'
|
|
26
|
+
PUTIH = '\x1b[37;1m'
|
|
27
|
+
# Warna Background
|
|
28
|
+
BG_M = '\x1b[41;1m'
|
|
29
|
+
BG_H = '\x1b[42;1m'
|
|
30
|
+
BG_K = '\x1b[43;1m'
|
|
31
|
+
BG_B = '\x1b[44;1m'
|
|
32
|
+
BG_U = '\x1b[45;1m'
|
|
33
|
+
BG_C = '\x1b[46;1m'
|
|
34
|
+
BG_P = '\x1b[47;1m'
|
|
35
|
+
|
|
36
|
+
DATA_FILE = 'data.json'
|
|
37
|
+
|
|
38
|
+
class Requests:
|
|
39
|
+
@staticmethod
|
|
40
|
+
def curl(url, method='GET', data=None, headers=None, cookies_file='cookie.txt'):
|
|
41
|
+
while True:
|
|
42
|
+
session = requests.Session()
|
|
43
|
+
try:
|
|
44
|
+
with open(cookies_file, 'r') as f:
|
|
45
|
+
cookies = {}
|
|
46
|
+
for line in f.readlines():
|
|
47
|
+
name, value = line.strip().split('=')
|
|
48
|
+
cookies[name] = value
|
|
49
|
+
session.cookies.update(cookies)
|
|
50
|
+
except FileNotFoundError:
|
|
51
|
+
pass
|
|
52
|
+
try:
|
|
53
|
+
if method.upper() == 'GET':
|
|
54
|
+
response = session.get(url, headers=headers)
|
|
55
|
+
elif method.upper() == 'POST':
|
|
56
|
+
response = session.post(url, data=data, headers=headers)
|
|
57
|
+
else:
|
|
58
|
+
raise ValueError('Metode tidak didukung')
|
|
59
|
+
response.raise_for_status()
|
|
60
|
+
except requests.exceptions.RequestException as e:
|
|
61
|
+
print(f"Koneksi terputus Mencoba lagi...")
|
|
62
|
+
time.sleep(5)
|
|
63
|
+
continue
|
|
64
|
+
with open(cookies_file, 'w') as f:
|
|
65
|
+
for cookie in session.cookies.items():
|
|
66
|
+
f.write(f"{cookie[0]}={cookie[1]}\n")
|
|
67
|
+
return response.text
|
|
68
|
+
class Display:
|
|
69
|
+
@staticmethod
|
|
70
|
+
def menu(no: Union[int, str], name: str) -> None:
|
|
71
|
+
print(f'{Colors.PUTIH}[{Colors.KUNING}{no}{Colors.PUTIH}] {Colors.PUTIH}{name}')
|
|
72
|
+
@staticmethod
|
|
73
|
+
def succes(msg: str) -> None:
|
|
74
|
+
print(f'{Colors.PUTIH}[{Colors.HIJAU}✓{Colors.PUTIH}] {Colors.HIJAU}{msg}{Colors.DASAR}')
|
|
75
|
+
@staticmethod
|
|
76
|
+
def error(msg: str) -> None:
|
|
77
|
+
print(f'{Colors.PUTIH}[{Colors.MERAH}!{Colors.PUTIH}] {Colors.MERAH}{msg}{Colors.DASAR}')
|
|
78
|
+
@staticmethod
|
|
79
|
+
def title(name: str, length: int = 44, pad_char: str = " ") -> None:
|
|
80
|
+
padded_name = name.center(length, pad_char)
|
|
81
|
+
print(f'{Colors.BG_B}{Colors.PUTIH}{padded_name}{Colors.DASAR}')
|
|
82
|
+
@staticmethod
|
|
83
|
+
def line(length: int = 44) -> None:
|
|
84
|
+
print(f'{Colors.CYAN}-'*length)
|
|
85
|
+
class Functions:
|
|
86
|
+
@staticmethod
|
|
87
|
+
def setConfig(key: str, value: Optional[str] = None) -> str:
|
|
88
|
+
config = {}
|
|
89
|
+
if os.path.exists(DATA_FILE):
|
|
90
|
+
try:
|
|
91
|
+
with open(DATA_FILE, 'r') as f:
|
|
92
|
+
config = json.load(f)
|
|
93
|
+
except (json.JSONDecodeError, IOError):
|
|
94
|
+
config = {}
|
|
95
|
+
if value is None:
|
|
96
|
+
if key in config:
|
|
97
|
+
return config[key]
|
|
98
|
+
value = input(f'--[>] Input {key}: ')
|
|
99
|
+
config[key] = value
|
|
100
|
+
try:
|
|
101
|
+
with open(DATA_FILE, 'w') as f:
|
|
102
|
+
json.dump(config, f, indent=4)
|
|
103
|
+
except IOError as e:
|
|
104
|
+
Display.error(f"Gagal menyimpan konfigurasi: {e}")
|
|
105
|
+
return value
|
|
106
|
+
@staticmethod
|
|
107
|
+
def menu_api() -> Tuple[str, str]:
|
|
108
|
+
Display.menu(1, 'Multibot')
|
|
109
|
+
Display.menu(2, 'Xevil')
|
|
110
|
+
Display.line()
|
|
111
|
+
options = {
|
|
112
|
+
1: {"host": "api.multibot.in", "apikey": "apikey-multibot"},
|
|
113
|
+
2: {"host": "api.sctg.xyz", "apikey": "apikey-xevil"}
|
|
114
|
+
}
|
|
115
|
+
while True:
|
|
116
|
+
try:
|
|
117
|
+
cap = int(input(f'{Colors.HIJAU}--Input Number: {Colors.PUTIH}'))
|
|
118
|
+
if cap in options:
|
|
119
|
+
break
|
|
120
|
+
Display.error('Pilihan tidak valid. Silakan coba lagi.')
|
|
121
|
+
except ValueError:
|
|
122
|
+
Display.error('Input harus angka. Silakan coba lagi.')
|
|
123
|
+
host = options[cap]["host"]
|
|
124
|
+
api_key = Functions.setConfig(options[cap]["apikey"])
|
|
125
|
+
return host, api_key
|
|
126
|
+
@staticmethod
|
|
127
|
+
def Tmr(tmr: int) -> None:
|
|
128
|
+
while tmr > 0:
|
|
129
|
+
mins, secs = divmod(tmr, 60)
|
|
130
|
+
timeformat = f'\033[1;97m\033[1;93m•\033[1;97m Wait \033[1;92m{mins:02d}:{secs:02d}'
|
|
131
|
+
print(f"{timeformat}", end='\r')
|
|
132
|
+
time.sleep(1)
|
|
133
|
+
tmr -= 1
|
|
134
|
+
print(" " * 30, end='\r') # Clear line
|
|
135
|
+
@staticmethod
|
|
136
|
+
def prosesBypasIcon(icontoken,host,h):
|
|
137
|
+
if icontoken:
|
|
138
|
+
while True:
|
|
139
|
+
amjad = IconBypass(host,h)
|
|
140
|
+
icon = amjad.icon_bypass(icontoken)
|
|
141
|
+
if not icon:
|
|
142
|
+
print(f'\r{Colors.PUTIH}--[{Colors.MERAH}!{Colors.PUTIH}] Bypas Gagal !\r',end='')
|
|
143
|
+
time.sleep(2)
|
|
144
|
+
continue
|
|
145
|
+
print(f'\r{Colors.PUTIH}--[{Colors.HIJAU}✓{Colors.PUTIH}] Bypas Succes\r',end='')
|
|
146
|
+
time.sleep(2)
|
|
147
|
+
return icon
|
|
148
|
+
class Captcha:
|
|
149
|
+
@staticmethod
|
|
150
|
+
def get_in(data: Dict) -> str:
|
|
151
|
+
url = f'http://{HOST_CAP}/in.php?'
|
|
152
|
+
params = {'key': API_CAP}
|
|
153
|
+
params.update(data)
|
|
154
|
+
try:
|
|
155
|
+
res = requests.get(url, params=params, timeout=30).json()
|
|
156
|
+
return res.get('request', '')
|
|
157
|
+
except (requests.RequestException, json.JSONDecodeError) as e:
|
|
158
|
+
Display.error(f"Gagal mendapatkan captcha ID: {e}")
|
|
159
|
+
raise
|
|
160
|
+
|
|
161
|
+
@staticmethod
|
|
162
|
+
def get_res(api_id: str) -> Dict:
|
|
163
|
+
url = f'http://{HOST_CAP}/res.php?key={API_CAP}&json=1&id={api_id}'
|
|
164
|
+
try:
|
|
165
|
+
res = requests.get(url, timeout=30)
|
|
166
|
+
return res.json()
|
|
167
|
+
except (requests.RequestException, json.JSONDecodeError) as e:
|
|
168
|
+
Display.error(f"Gagal mendapatkan hasil captcha: {e}")
|
|
169
|
+
return {'request': 'ERROR', 'error': str(e)}
|
|
170
|
+
|
|
171
|
+
@staticmethod
|
|
172
|
+
def Filter(method: str) -> str:
|
|
173
|
+
method_map = {
|
|
174
|
+
'userrecaptcha': 'RecaptchaV2',
|
|
175
|
+
'hcaptcha': 'Hcaptcha',
|
|
176
|
+
'turnstile': 'Turnstile'
|
|
177
|
+
}
|
|
178
|
+
return method_map.get(method, method)
|
|
179
|
+
|
|
180
|
+
@staticmethod
|
|
181
|
+
def getResult(data: Dict) -> str:
|
|
182
|
+
method_value = data.get('method', '')
|
|
183
|
+
cap_type = Captcha.Filter(method_value)
|
|
184
|
+
max_attempts = 60
|
|
185
|
+
try:
|
|
186
|
+
captcha_id = Captcha.get_in(data)
|
|
187
|
+
for _ in range(max_attempts):
|
|
188
|
+
res = Captcha.get_res(captcha_id)
|
|
189
|
+
if res.get('request') == 'CAPCHA_NOT_READY':
|
|
190
|
+
print(f"\rBaypas {cap_type}", end='')
|
|
191
|
+
time.sleep(1)
|
|
192
|
+
continue
|
|
193
|
+
if res.get('request') == 'ERROR':
|
|
194
|
+
raise Exception(res.get('error', 'Unknown error'))
|
|
195
|
+
Display.succes(f'Baypas {cap_type} sukses')
|
|
196
|
+
time.sleep(2)
|
|
197
|
+
print(" " * 30, end='\r') # Clear line
|
|
198
|
+
return res.get('request', '')
|
|
199
|
+
raise Exception("Captcha tidak selesai dalam waktu yang ditentukan")
|
|
200
|
+
except Exception as e:
|
|
201
|
+
Display.error(f"Gagal bypass captcha: {e}")
|
|
202
|
+
raise
|
|
203
|
+
|
|
204
|
+
@staticmethod
|
|
205
|
+
def Recaptchav2(sitekey: str, pageurl: str) -> str:
|
|
206
|
+
data = {
|
|
207
|
+
'method': 'userrecaptcha',
|
|
208
|
+
'sitekey': sitekey,
|
|
209
|
+
'pageurl': pageurl,
|
|
210
|
+
'json': 1
|
|
211
|
+
}
|
|
212
|
+
return Captcha.getResult(data)
|
|
213
|
+
|
|
214
|
+
@staticmethod
|
|
215
|
+
def Hcaptcha(sitekey: str, pageurl: str) -> str:
|
|
216
|
+
data = {
|
|
217
|
+
'method': 'hcaptcha',
|
|
218
|
+
'sitekey': sitekey,
|
|
219
|
+
'pageurl': pageurl,
|
|
220
|
+
'json': 1
|
|
221
|
+
}
|
|
222
|
+
return Captcha.getResult(data)
|
|
223
|
+
|
|
224
|
+
@staticmethod
|
|
225
|
+
def Turnstile(sitekey: str, pageurl: str) -> str:
|
|
226
|
+
data = {
|
|
227
|
+
'method': 'turnstile',
|
|
228
|
+
'sitekey': sitekey,
|
|
229
|
+
'pageurl': pageurl,
|
|
230
|
+
'json': 1
|
|
231
|
+
}
|
|
232
|
+
return Captcha.getResult(data)
|
|
233
|
+
class HtmlScrap:
|
|
234
|
+
def __init__(self):
|
|
235
|
+
self._captcha_pattern = re.compile(r'class=["\']([^"\']+)["\'][^>]*data-sitekey=["\']([^"\']+)["\'][^>]*>')
|
|
236
|
+
self._input_pattern = re.compile(r'<input[^>]*name=["\'](.*?)["\'][^>]*value=["\'](.*?)["\'][^>]*>')
|
|
237
|
+
self._limit_pattern = re.compile(r'(\d{1,})\/(\d{1,})')
|
|
238
|
+
self._security_patterns = {
|
|
239
|
+
'cloudflare': re.compile(r'Just a moment...'),
|
|
240
|
+
'firewall': re.compile(r'Firewall'),
|
|
241
|
+
'locked': re.compile(r'Locked')
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
def _scrap(self, pattern: re.Pattern, html: str) -> List[Tuple[str, ...]]:
|
|
245
|
+
return pattern.findall(html)
|
|
246
|
+
|
|
247
|
+
def get_captcha(self, html: str) -> Dict[str, str]:
|
|
248
|
+
matches = self._scrap(self._captcha_pattern, html)
|
|
249
|
+
return {match[0]: match[1] for match in matches}
|
|
250
|
+
|
|
251
|
+
def get_inputs(self, html: str, form_index: int = 1) -> Dict[str, str]:
|
|
252
|
+
forms = html.split('<form')
|
|
253
|
+
if len(forms) <= form_index:
|
|
254
|
+
return {}
|
|
255
|
+
form_content = forms[form_index]
|
|
256
|
+
matches = self._scrap(self._input_pattern, form_content)
|
|
257
|
+
return {name: value for name, value in matches}
|
|
258
|
+
|
|
259
|
+
def get_limits(self, html: str) -> List[Tuple[str, str]]:
|
|
260
|
+
return self._scrap(self._limit_pattern, html)
|
|
261
|
+
|
|
262
|
+
def check_security(self, html: str) -> Dict[str, bool]:
|
|
263
|
+
return {name: bool(pattern.search(html)) for name, pattern in self._security_patterns.items()}
|
|
264
|
+
|
|
265
|
+
def parse_responses(self, html: str) -> Dict[str, Union[str, bool, None]]:
|
|
266
|
+
result = {
|
|
267
|
+
'success': None,
|
|
268
|
+
'warning': None,
|
|
269
|
+
'unset': False,
|
|
270
|
+
'exit': False
|
|
271
|
+
}
|
|
272
|
+
if 'icon: \'success\',' in html:
|
|
273
|
+
success_part = html.split("icon: 'success',")[1]
|
|
274
|
+
if "html: '" in success_part:
|
|
275
|
+
success_msg = success_part.split("html: '")[1].split("'")[0]
|
|
276
|
+
result['success'] = re.sub('<[^<]+?>', '', success_msg)
|
|
277
|
+
return result
|
|
278
|
+
warning_msg = None
|
|
279
|
+
if 'html: \'' in html:
|
|
280
|
+
warning_msg = html.split("html: '")[1].split("'")[0]
|
|
281
|
+
error_conditions = [
|
|
282
|
+
('<div class="alert text-center alert-danger"><i class="fas fa-exclamation-circle"></i> Your account',
|
|
283
|
+
lambda: html.split('Your account')[1].split('</div>')[0], True),
|
|
284
|
+
('invalid amount', "You are sending an invalid amount", True),
|
|
285
|
+
('Shortlink in order to claim from the faucet!', warning_msg, True),
|
|
286
|
+
('sufficient funds', "Sufficient funds", True)
|
|
287
|
+
]
|
|
288
|
+
for condition, message, exit_flag in error_conditions:
|
|
289
|
+
if condition in html:
|
|
290
|
+
result['warning'] = message() if callable(message) else message
|
|
291
|
+
result['exit'] = exit_flag
|
|
292
|
+
return result
|
|
293
|
+
result['warning'] = warning_msg or "Not Found"
|
|
294
|
+
return result
|
|
295
|
+
|
|
296
|
+
def get_title(self, html: str) -> str:
|
|
297
|
+
title_parts = html.split('<title>')
|
|
298
|
+
if len(title_parts) > 1:
|
|
299
|
+
return title_parts[1].split('</title>')[0]
|
|
300
|
+
return ""
|
|
301
|
+
|
|
302
|
+
def scrape_all(self, html: str, form_index: int = 1) -> Dict[str, Union[str, bool, Dict, List]]:
|
|
303
|
+
return {
|
|
304
|
+
'title': self.get_title(html),
|
|
305
|
+
**self.check_security(html),
|
|
306
|
+
'captcha': self.get_captcha(html),
|
|
307
|
+
'input': self.get_inputs(html, form_index) or self.get_inputs(html, 2),
|
|
308
|
+
'faucet': self.get_limits(html),
|
|
309
|
+
'response': self.parse_responses(html)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
@staticmethod
|
|
313
|
+
def bs_get_forms(html: str) -> List[Dict[str, Union[str, Dict[str, str]]]]:
|
|
314
|
+
soup = BeautifulSoup(html, 'html.parser')
|
|
315
|
+
forms = []
|
|
316
|
+
for form in soup.find_all('form'):
|
|
317
|
+
form_data = {
|
|
318
|
+
'action': form.get('action', ''),
|
|
319
|
+
'method': form.get('method', 'get').upper(),
|
|
320
|
+
'inputs': {}
|
|
321
|
+
}
|
|
322
|
+
for input_tag in form.find_all('input'):
|
|
323
|
+
name = input_tag.get('name')
|
|
324
|
+
if name:
|
|
325
|
+
form_data['inputs'][name] = input_tag.get('value', '')
|
|
326
|
+
forms.append(form_data)
|
|
327
|
+
return forms
|
|
328
|
+
|
|
329
|
+
@staticmethod
|
|
330
|
+
def bs_get_links(html: str, base_url: str = '') -> List[Dict[str, str]]:
|
|
331
|
+
soup = BeautifulSoup(html, 'html.parser')
|
|
332
|
+
links = []
|
|
333
|
+
for a in soup.find_all('a', href=True):
|
|
334
|
+
href = a['href']
|
|
335
|
+
if base_url and not href.startswith(('http://', 'https://')):
|
|
336
|
+
href = base_url + href
|
|
337
|
+
links.append({
|
|
338
|
+
'text': a.get_text(strip=True),
|
|
339
|
+
'href': href
|
|
340
|
+
})
|
|
341
|
+
return links
|
|
342
|
+
class IconBypass:
|
|
343
|
+
def __init__(self, host, headers):
|
|
344
|
+
self.host = host
|
|
345
|
+
self.headers = headers
|
|
346
|
+
def widget_id(self):
|
|
347
|
+
import uuid
|
|
348
|
+
return str(uuid.uuid4())
|
|
349
|
+
def msg(self, text, j=10):
|
|
350
|
+
symbols = ['-', '/', '|', '\\']
|
|
351
|
+
for i in range(j, 0, -1):
|
|
352
|
+
for n, s in enumerate(symbols):
|
|
353
|
+
print(f" [{s}] {text} {'➤' * n}", end='\r')
|
|
354
|
+
time.sleep(0.1)
|
|
355
|
+
print(" " * 30, end='\r')
|
|
356
|
+
def icon_bypass(self, token):
|
|
357
|
+
try:
|
|
358
|
+
# Persiapan header
|
|
359
|
+
icon_header = self.headers.copy()
|
|
360
|
+
icon_header.update({
|
|
361
|
+
'origin': self.host,
|
|
362
|
+
'x-iconcaptcha-token': token,
|
|
363
|
+
'x-requested-with': 'XMLHttpRequest',
|
|
364
|
+
'content-type': 'application/x-www-form-urlencoded'
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
# --- STEP 1: LOAD CAPTCHA ---
|
|
368
|
+
self.msg("Loading captcha", 3)
|
|
369
|
+
timestamp = int(time.time() * 1000)
|
|
370
|
+
widget_id = self.widget_id()
|
|
371
|
+
payload = {
|
|
372
|
+
"widgetId": widget_id,
|
|
373
|
+
"action": "LOAD",
|
|
374
|
+
"theme": "light",
|
|
375
|
+
"token": token,
|
|
376
|
+
"timestamp": timestamp,
|
|
377
|
+
"initTimestamp": timestamp - 2000
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
# Encode payload
|
|
381
|
+
data = {
|
|
382
|
+
"payload": base64.b64encode(
|
|
383
|
+
json.dumps(payload).encode('utf-8')
|
|
384
|
+
).decode('utf-8')
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
# Kirim request
|
|
388
|
+
response = Requests.curl(
|
|
389
|
+
self.host + "icaptcha/req",
|
|
390
|
+
method='POST',
|
|
391
|
+
headers=icon_header,
|
|
392
|
+
data=data
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
# Handle response
|
|
396
|
+
try:
|
|
397
|
+
decoded = base64.b64decode(response).decode('utf-8')
|
|
398
|
+
response_data = json.loads(decoded)
|
|
399
|
+
except:
|
|
400
|
+
print("Invalid response format:", response.text[:200])
|
|
401
|
+
return None
|
|
402
|
+
|
|
403
|
+
if 'identifier' not in response_data:
|
|
404
|
+
print("No identifier in response")
|
|
405
|
+
return None
|
|
406
|
+
|
|
407
|
+
challenge_id = response_data['identifier']
|
|
408
|
+
|
|
409
|
+
# --- STEP 2: SEND SELECTION ---
|
|
410
|
+
self.msg("Solving captcha", 3)
|
|
411
|
+
timestamp = int(time.time() * 1000)
|
|
412
|
+
payload = {
|
|
413
|
+
"widgetId": widget_id,
|
|
414
|
+
"challengeId": challenge_id,
|
|
415
|
+
"action": "SELECTION",
|
|
416
|
+
"x": random.randint(150, 170), # Koordinat acak di area tengah
|
|
417
|
+
"y": random.randint(20, 30),
|
|
418
|
+
"width": 320,
|
|
419
|
+
"token": token,
|
|
420
|
+
"timestamp": timestamp,
|
|
421
|
+
"initTimestamp": timestamp - 2000
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
data = {
|
|
425
|
+
"payload": base64.b64encode(
|
|
426
|
+
json.dumps(payload).encode('utf-8')
|
|
427
|
+
).decode('utf-8')
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
response = Requests.curl(
|
|
431
|
+
self.host + "icaptcha/req",
|
|
432
|
+
method='POST',
|
|
433
|
+
headers=icon_header,
|
|
434
|
+
data=data
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
try:
|
|
438
|
+
decoded = base64.b64decode(response).decode('utf-8')
|
|
439
|
+
response_data = json.loads(decoded)
|
|
440
|
+
except:
|
|
441
|
+
print("Invalid response format:", response.text[:200])
|
|
442
|
+
return None
|
|
443
|
+
|
|
444
|
+
if not response_data.get('completed', False):
|
|
445
|
+
return None
|
|
446
|
+
|
|
447
|
+
# --- STEP 3: RETURN RESULT ---
|
|
448
|
+
return {
|
|
449
|
+
"captcha": "icaptcha",
|
|
450
|
+
"_iconcaptcha-token": token,
|
|
451
|
+
"ic-rq": 1,
|
|
452
|
+
"ic-wid": payload["widgetId"],
|
|
453
|
+
"ic-cid": challenge_id,
|
|
454
|
+
"ic-hp": '',
|
|
455
|
+
"human_move": 1
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
except Exception as e:
|
|
459
|
+
print(f"Error in bypass: {str(e)}")
|
|
460
|
+
return None
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: amjadyt
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Kumpulan fungsi untuk scriping
|
|
5
|
+
Author-email: Solihul Amjad <amjadyt348@anda.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Requires-Python: >=3.7
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# Functions Untuk Scripting
|
|
12
|
+
# Fitur
|
|
13
|
+
- class Requests
|
|
14
|
+
- class Functions
|
|
15
|
+
- class Display
|
|
16
|
+
- class Baypas captcha Multibot & xevil
|
|
17
|
+
- Baypas Icon Captcha
|
|
18
|
+
- html scrap (menggunakan BeautifulSoup)
|
|
19
|
+
|
|
20
|
+
# Example
|
|
21
|
+
#### Cara Import
|
|
22
|
+
```from class import*```
|
|
23
|
+
#### Requests
|
|
24
|
+
```response = Requests.curl('https://example.com')```
|
|
25
|
+
#### Functions
|
|
26
|
+
```Functions.setConfig('nama_data')```
|
|
27
|
+
#### Baypas Captcha
|
|
28
|
+
panggil function menu api dulu sebelum memanggil class Baypas Captch
|
|
29
|
+
###### Example
|
|
30
|
+
function menu api
|
|
31
|
+
```HOST_CAP,API_CAP = Functions.menu_api()`
|
|
32
|
+
lalu panggil function Baypas Captcha nya
|
|
33
|
+
cap = Captcha.Recaptchav2(sitekey,pageurl)```
|
|
34
|
+
#### Baypass Icon Captcha
|
|
35
|
+
###### Example
|
|
36
|
+
```baypas = IconBypass(host, headers)```
|
|
37
|
+
```icon = baypas.icon_bypass(iconToken)```
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
amjadyt
|