apksearch 1.3.0__py3-none-any.whl → 1.3.5__py3-none-any.whl

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.
apksearch/__init__.py CHANGED
@@ -1,11 +1,10 @@
1
- from .sites.apkpure import APKPure
2
- from .sites.apkmirror import APKMirror
3
- from .sites.appteka import AppTeka
1
+ from .sites.apkad import APKad
4
2
  from .sites.apkcombo import APKCombo
5
3
  from .sites.apkfab import APKFab
6
- from .sites.apkad import APKad
4
+ from .sites.apkmirror import APKMirror
5
+ from .sites.apkpure import APKPure
6
+ from .sites.appteka import AppTeka
7
7
  from .sites.aptoide import Aptoide
8
- from .sites.apkmonk import APKMonk
9
8
 
10
9
  __all__ = [
11
10
  "APKPure",
@@ -15,5 +14,4 @@ __all__ = [
15
14
  "APKFab",
16
15
  "APKad",
17
16
  "Aptoide",
18
- "APKMonk",
19
17
  ]
apksearch/cli.py CHANGED
@@ -1,17 +1,17 @@
1
1
  import argparse
2
-
3
2
  from collections.abc import Callable
3
+
4
+ from requests.exceptions import ConnectionError, ConnectTimeout
5
+
4
6
  from apksearch import (
5
- APKPure,
6
- APKMirror,
7
- AppTeka,
7
+ APKad,
8
8
  APKCombo,
9
9
  APKFab,
10
- APKad,
10
+ APKMirror,
11
+ APKPure,
12
+ AppTeka,
11
13
  Aptoide,
12
- APKMonk,
13
14
  )
14
- from requests.exceptions import ConnectionError, ConnectTimeout
15
15
 
16
16
  # Color codes
17
17
  BOLD = "\033[1m"
@@ -22,7 +22,7 @@ NC = "\033[0m"
22
22
 
23
23
 
24
24
  def search(
25
- func: Callable[[str, str], object],
25
+ func: Callable[[str, str | None], object],
26
26
  pkg_name: str,
27
27
  version: str | None,
28
28
  log_err: bool = False,
@@ -31,7 +31,8 @@ def search(
31
31
  func(pkg_name, version)
32
32
  except Exception as exc:
33
33
  if log_err:
34
- print(f"Error in {func.__name__}: {exc}")
34
+ func_name = getattr(func, "__name__", func.__class__.__name__)
35
+ print(f"Error in {func_name}: {exc}")
35
36
  else:
36
37
  pass
37
38
 
@@ -91,16 +92,20 @@ def search_apkfab(pkg_name: str, version: str | None) -> None:
91
92
  def search_apkad(pkg_name: str, version: str | None) -> None:
92
93
  apkad = APKad(pkg_name)
93
94
  try:
94
- result_apkad: tuple[str, str] | None = apkad.search_apk()
95
+ result_apkad: tuple[str, list[tuple[str, str]]] | None = apkad.search_apk()
95
96
  except (ConnectionError, ConnectTimeout):
96
97
  result_apkad = None
97
98
  print(f"{RED}Failed to resolve 'api.apk.ad'!{NC}")
98
99
  if result_apkad:
99
- title, apk_link = result_apkad
100
+ title, apk_links = result_apkad
100
101
  print(f"{BOLD}APKAD:{NC} Found {GREEN}{title}{NC}") if title else None
101
- print(
102
- f" ╰─> {BOLD}Link: {YELLOW}{apk_link}{NC}"
103
- ) if not version else print(" ╰─> Doesn't support version search!")
102
+ if not version:
103
+ print(f" ╰─> {BOLD}Available APKs:{NC}")
104
+ for i, (filename, url) in enumerate(apk_links, 1):
105
+ print(f" {i}. {filename}")
106
+ print(f" ╰─> {BOLD}Download:{NC} {YELLOW}{url}{NC}")
107
+ else:
108
+ print(" ╰─> Doesn't support version search!")
104
109
  else:
105
110
  print(f"{BOLD}APKAD:{NC} No Results!")
106
111
 
@@ -142,7 +147,7 @@ def search_apkmirror(pkg_name: str, version: str | None) -> None:
142
147
  print(f"{BOLD}APKMirror:{NC} Found {GREEN}{title}{NC}") if title else None
143
148
  print(f" ╰─> {BOLD}Link: {YELLOW}{apk_link}{NC}") if not version else None
144
149
  if version:
145
- download_link = apkmirror.find_version(apk_link, version)
150
+ download_link = apkmirror.find_version(apk_link, version, title)
146
151
  if download_link:
147
152
  print(
148
153
  f" ╰─> {BOLD}Version: {GREEN}{version}{NC} - {YELLOW}{download_link}{NC}"
@@ -156,7 +161,7 @@ def search_apkmirror(pkg_name: str, version: str | None) -> None:
156
161
  def search_appteka(pkg_name: str, version: str | None) -> None:
157
162
  appteka = AppTeka(pkg_name)
158
163
  try:
159
- result_appteka: tuple[str, str] | None = appteka.search_apk(version)
164
+ result_appteka: tuple[str, str | None] | None = appteka.search_apk(version)
160
165
  except (ConnectionError, ConnectTimeout):
161
166
  result_appteka = None
162
167
  print(f"{RED}Failed to resolve 'appteka.store'!{NC}")
@@ -200,32 +205,6 @@ def search_aptoide(pkg_name: str, version: str | None) -> None:
200
205
  print(f"{BOLD}Aptoide:{NC} No Results!")
201
206
 
202
207
 
203
- def search_apkmonk(pkg_name: str, version: str | None) -> None:
204
- apkmonk = APKMonk(pkg_name)
205
- try:
206
- result_apkmonk: tuple[str, str] | None = apkmonk.search_apk()
207
- except (ConnectionError, ConnectTimeout):
208
- result_apkmonk = None
209
- print(f"{RED}Failed to resolve 'apkmonk.com'!{NC}")
210
- if result_apkmonk:
211
- title, apk_link = result_apkmonk
212
- print(f"{BOLD}APKMonk:{NC} Found {GREEN}{title}{NC}") if title else None
213
- print(f" ╰─> {BOLD}Link: {YELLOW}{apk_link}{NC}") if not version else None
214
- if version:
215
- versions: list[tuple[str, str]] = apkmonk.find_versions(apk_link)
216
- if versions:
217
- for version_tuple in versions:
218
- if version_tuple[0] == version:
219
- print(
220
- f" ╰─> {BOLD}Version: {GREEN}{version}{NC} - {YELLOW}{version_tuple[1]}{NC}"
221
- )
222
- break
223
- else:
224
- print(f"{BOLD}APKMonk:{NC} Version {RED}{version}{NC} not found!")
225
- else:
226
- print(f"{BOLD}APKMonk:{NC} No Results!")
227
-
228
-
229
208
  def main():
230
209
  parser = argparse.ArgumentParser(
231
210
  prog="APKSearch", description="Search for APKs on various websites"
@@ -235,28 +214,44 @@ def main():
235
214
  parser.add_argument(
236
215
  "--log_err", help="Enable error logs", action="store_true", required=False
237
216
  )
217
+ parser.add_argument(
218
+ "--sites",
219
+ nargs="+",
220
+ choices=[
221
+ "apkpure",
222
+ "apkmirror",
223
+ "aptoide",
224
+ "appteka",
225
+ "apkcombo",
226
+ "apkfab",
227
+ "apkad",
228
+ ],
229
+ help="Specify the sites to search on",
230
+ required=False,
231
+ )
238
232
  args = parser.parse_args()
239
233
 
240
234
  pkg_name = args.pkg_name
241
235
  version = args.version
242
236
  log_err = args.log_err
237
+ sites = args.sites
238
+
243
239
  print(f"{BOLD}Searching for {YELLOW}{pkg_name}{NC}...")
244
- # Initiate search on apkpure
245
- search(search_apkpure, pkg_name, version, log_err)
246
- # Initiate search on apkmirror
247
- search(search_apkmirror, pkg_name, version, log_err)
248
- # Initiate search on aptoide
249
- search(search_aptoide, pkg_name, version, log_err)
250
- # Initiate search on appteka
251
- search(search_appteka, pkg_name, version, log_err)
252
- # Initiate search on apkcombo
253
- search(search_apkcombo, pkg_name, version, log_err)
254
- # Initiate search on apkfab
255
- search(search_apkfab, pkg_name, version, log_err)
256
- # Initiate search on apkad
257
- search(search_apkad, pkg_name, version, log_err)
258
- # Initiate search on apmonk
259
- search(search_apkmonk, pkg_name, version, log_err)
240
+
241
+ if not sites or "apkpure" in sites:
242
+ search(search_apkpure, pkg_name, version, log_err)
243
+ if not sites or "apkmirror" in sites:
244
+ search(search_apkmirror, pkg_name, version, log_err)
245
+ if not sites or "aptoide" in sites:
246
+ search(search_aptoide, pkg_name, version, log_err)
247
+ if not sites or "appteka" in sites:
248
+ search(search_appteka, pkg_name, version, log_err)
249
+ if not sites or "apkcombo" in sites:
250
+ search(search_apkcombo, pkg_name, version, log_err)
251
+ if not sites or "apkfab" in sites:
252
+ search(search_apkfab, pkg_name, version, log_err)
253
+ if not sites or "apkad" in sites:
254
+ search(search_apkad, pkg_name, version, log_err)
260
255
 
261
256
 
262
257
  if __name__ == "__main__":
@@ -0,0 +1,10 @@
1
+ try:
2
+ from curl_cffi import requests
3
+
4
+ curl = True
5
+ except ImportError:
6
+ import requests
7
+
8
+ curl = False
9
+
10
+ __all__ = ["requests", "curl"]
apksearch/sites/apkad.py CHANGED
@@ -1,6 +1,9 @@
1
+ import base64
1
2
  import json
3
+
2
4
  from bs4 import BeautifulSoup
3
- import requests
5
+
6
+ from apksearch.sites import requests
4
7
 
5
8
 
6
9
  class APKad:
@@ -25,21 +28,19 @@ class APKad:
25
28
 
26
29
  def __init__(self, pkg_name: str):
27
30
  self.pkg_name = pkg_name
28
- self.base_url = "https://downloader.apk.ad"
29
- self.api_url = "https://api.apk.ad"
30
- self.search_url = (
31
- self.api_url
32
- + f"/get?hl=en&package={self.pkg_name}&device=phone&arch=arm64-v8a&vc=&device_id="
33
- )
31
+ self.base_url = "https://apkdownloader.pages.dev"
32
+ self.api_url = "https://api.mi9.com"
33
+ self.token_url = "https://token.mi9.com/"
34
+ self.search_url = self.api_url + "/get"
34
35
  self.headers = {
35
36
  "accept": "text/event-stream",
36
37
  "accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
37
38
  "cache-control": "no-cache",
38
39
  "dnt": "1",
39
- "origin": "https://downloader.apk.ad",
40
+ "origin": "https://apkdownloader.pages.dev",
40
41
  "pragma": "no-cache",
41
42
  "priority": "u=1, i",
42
- "referer": "https://downloader.apk.ad/",
43
+ "referer": "https://apkdownloader.pages.dev/",
43
44
  "sec-ch-ua": '"Microsoft Edge";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
44
45
  "sec-ch-ua-mobile": "?0",
45
46
  "sec-ch-ua-platform": '"Windows"',
@@ -50,60 +51,92 @@ class APKad:
50
51
  }
51
52
  self.session = requests.Session()
52
53
 
53
- def search_apk(self) -> None | tuple[str, str]:
54
+ def get_token(self) -> tuple[str, int] | None:
54
55
  """
55
- Searches for the APK on APKAD and returns the title and link if found.
56
+ Retrieves a token from the token endpoint.
56
57
 
57
58
  Returns:
58
- None: If no matching APK is found.
59
- tuple[str, str]: A tuple containing the title and link of the matching APK if found.
59
+ tuple[str, int]: A tuple containing the token and timestamp if successful.
60
+ None: If the token retrieval fails.
60
61
  """
61
- url = self.search_url
62
- response = self.session.get(url, headers=self.headers, stream=True)
63
- stream_response = ""
62
+ data = {
63
+ "package": self.pkg_name,
64
+ "device": "phone",
65
+ "arch": "arm64-v8a",
66
+ "vc": "",
67
+ "device_id": "",
68
+ "sdk": "default",
69
+ }
70
+ response = self.session.post(self.token_url, headers=self.headers, json=data)
71
+ if response.status_code == 200:
72
+ token_data = response.json()
73
+ if token_data.get("success"):
74
+ return token_data.get("token"), token_data.get("timestamp")
75
+ return None
76
+
77
+ def search_apk(self) -> None | tuple[str, list[tuple[str, str]]]:
78
+ token_tuple = self.get_token()
79
+ if not token_tuple:
80
+ return None
81
+
82
+ token, ts = token_tuple
83
+ data_json = json.dumps(
84
+ {
85
+ "hl": "en",
86
+ "package": self.pkg_name,
87
+ "device": "phone",
88
+ "arch": "arm64-v8a",
89
+ "vc": "",
90
+ "device_id": "",
91
+ "sdk": "default",
92
+ "timestamp": ts,
93
+ },
94
+ separators=(",", ":"),
95
+ )
96
+
97
+ data_b64 = base64.b64encode(data_json.encode("utf-8")).decode("utf-8")
98
+
99
+ params = {"token": token, "data": data_b64}
100
+
101
+ response = self.session.get(
102
+ self.search_url, headers=self.headers, params=params, stream=True
103
+ )
104
+
105
+ stream_response = None
64
106
  for line in response.iter_lines():
65
- if line:
66
- line_response = line.decode("utf-8")
67
- if '"progress":100' in line_response:
68
- line_response = line_response[6:]
69
- stream_response += line_response
70
- break
107
+ if not line:
108
+ continue
109
+ line_response = line.decode("utf-8")
110
+ if line_response.startswith("data: "):
111
+ payload = line_response[6:]
112
+ try:
113
+ j = json.loads(payload)
114
+ if j.get("progress") == 100 and j.get("html"):
115
+ stream_response = j
116
+ break
117
+ except json.JSONDecodeError:
118
+ continue
119
+
71
120
  if stream_response:
72
- data = json.loads(stream_response)
73
- html_body = data["html"]
121
+ html_body = stream_response["html"]
74
122
  soup = BeautifulSoup(html_body, "html.parser")
75
123
  if not soup:
76
124
  return None
125
+
77
126
  title = soup.find("li", {"class": "_title"})
78
- if title:
79
- title = title.text.strip()
80
- button = soup.find(
81
- "button", {"onclick": True, "id": "downloadButtonapk"}
82
- )["onclick"]
83
- if button:
84
- zip_args = [
85
- arg.strip("'")
86
- for arg in button.split("zip(")[1].split(")")[0].split(",")
87
- ]
88
- h = zip_args[0] # hash
89
- p = zip_args[-1] # type
90
- token = zip_args[1] # token
91
- ip = zip_args[2] # ip
92
- google_id = zip_args[3] # package_name
93
- t = zip_args[4] # time
94
- apk_url = f"https://zip.apk.ad/compress?h={h}&p={p}&token={token}&ip={ip}&google_id={google_id}&t={t}"
95
- apk_url_response = self.session.get(
96
- url=apk_url, headers=self.headers, stream=True
97
- )
98
- for line in apk_url_response.iter_lines():
99
- if line:
100
- line_response = line.decode("utf-8")
101
- if "File is ready for download." in line_response:
102
- line_response = json.loads(line_response)
103
- line_html = line_response["html"]
104
- line_soup = BeautifulSoup(line_html, "html.parser")
105
- download_link = line_soup.find("a")["href"]
106
- if download_link.endswith("\n"):
107
- download_link = download_link[:-1]
108
- return title, download_link
127
+ title = title.text.strip() if title else self.pkg_name
128
+
129
+ apk_files_div = soup.find("div", {"id": "apkslist"})
130
+ if not apk_files_div:
131
+ return None
132
+
133
+ apk_links: list[tuple[str, str]] = []
134
+ for a in apk_files_div.find_all("a", href=True):
135
+ link = a["href"].strip()
136
+ filename = a.find("span", {"class": "der_name"})
137
+ filename = filename.text.strip() if filename else link.split("/")[-1]
138
+ apk_links.append((filename, link))
139
+
140
+ return title, apk_links
141
+
109
142
  return None
@@ -1,5 +1,6 @@
1
1
  from bs4 import BeautifulSoup
2
- import requests
2
+
3
+ from apksearch.sites import requests
3
4
 
4
5
 
5
6
  class APKCombo:
@@ -27,7 +28,7 @@ class APKCombo:
27
28
 
28
29
  def __init__(self, pkg_name: str):
29
30
  self.pkg_name = pkg_name
30
- self.base_url = "https://apkcombo.app"
31
+ self.base_url = "https://apkcombo.com"
31
32
  self.search_url = self.base_url + "/search"
32
33
  self.headers = {
33
34
  "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",
@@ -37,7 +38,7 @@ class APKCombo:
37
38
  "dnt": "1",
38
39
  "pragma": "no-cache",
39
40
  "priority": "u=0, i",
40
- "referer": "https://apkcombo.app/",
41
+ "referer": "https://apkcombo.com/",
41
42
  "sec-ch-ua": '"Microsoft Edge";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
42
43
  "sec-ch-ua-mobile": "?0",
43
44
  "sec-ch-ua-platform": '"Windows"',
apksearch/sites/apkfab.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from bs4 import BeautifulSoup
2
- import requests
2
+
3
+ from apksearch.sites import requests, curl
3
4
 
4
5
 
5
6
  class APKFab:
@@ -59,7 +60,10 @@ class APKFab:
59
60
  """
60
61
  pkg_name = self.pkg_name
61
62
  url = self.search_url + pkg_name
62
- response: requests.Response = self.session.get(url, headers=self.headers)
63
+ params = {"headers": self.headers}
64
+ if curl:
65
+ params["impersonate"] = "chrome"
66
+ response: requests.Response = self.session.get(url, **params)
63
67
  soup = BeautifulSoup(response.text, "html.parser")
64
68
  search_result = soup.find("div", {"class": "search-white"})
65
69
  if search_result:
@@ -1,4 +1,6 @@
1
- import requests
1
+ import re
2
+
3
+ from apksearch.sites import requests
2
4
 
3
5
 
4
6
  class APKMirror:
@@ -59,7 +61,7 @@ class APKMirror:
59
61
  return title, apk_link
60
62
  return None
61
63
 
62
- def find_version(self, apk_link: str, version: str) -> str:
64
+ def find_version(self, apk_link: str, version: str, title: str) -> str | None:
63
65
  """
64
66
  Finds and returns the download link for the given APK link and version.
65
67
 
@@ -70,7 +72,8 @@ class APKMirror:
70
72
  Returns:
71
73
  str: The download link for the specified version of the APK.
72
74
  """
73
- name = apk_link.split("/")[-2]
75
+ name = re.sub(r"[(),]", "", title).lower().replace(" ", "-")
76
+ name = re.sub(r"-+", "-", name)
74
77
  version = version.replace(".", "-")
75
78
  url = apk_link + name + "-" + version + "-release"
76
79
  response = self.session.get(url, headers=self.headers)
@@ -1,6 +1,8 @@
1
1
  import re
2
+
2
3
  from bs4 import BeautifulSoup
3
- import requests
4
+
5
+ from apksearch.sites import requests
4
6
 
5
7
 
6
8
  class APKPure:
@@ -107,14 +109,6 @@ class APKPure:
107
109
  None: If no matching APK is found.
108
110
  tuple[str, str]: A tuple containing the title and link of the matching APK if found.
109
111
  """
110
- # Try API first
111
- api_result = self._api_search()
112
- if api_result:
113
- title, versions = api_result
114
- if versions:
115
- return title, versions[0][1]
116
-
117
- # Fall back to web scrapping
118
112
  pkg_name = self.pkg_name
119
113
  url = self.search_url + pkg_name
120
114
  response: requests.Response = self.session.get(url, headers=self.headers)
@@ -138,7 +132,7 @@ class APKPure:
138
132
  try:
139
133
  location = response.headers.get("Location")
140
134
  except AttributeError:
141
- return None
135
+ location = None
142
136
  if location:
143
137
  if location == "https://apkpure.com":
144
138
  return None
@@ -152,6 +146,13 @@ class APKPure:
152
146
  if content:
153
147
  apk_title = content.split("filename=")[1].strip('"').split("_")[0]
154
148
  return apk_title, location
149
+
150
+ api_result = self._api_search()
151
+ if api_result:
152
+ title, versions = api_result
153
+ if versions:
154
+ return title, versions[0][1]
155
+
155
156
  return None
156
157
 
157
158
  def find_versions(self, apk_link: str) -> list[tuple[str, str]]:
@@ -1,6 +1,8 @@
1
1
  import re
2
+
2
3
  from bs4 import BeautifulSoup
3
- import requests
4
+
5
+ from apksearch.sites import requests
4
6
 
5
7
 
6
8
  class AppTeka:
@@ -48,7 +50,7 @@ class AppTeka:
48
50
  }
49
51
  self.session = requests.Session()
50
52
 
51
- def search_apk(self, version: str = None) -> None | tuple[str, str]:
53
+ def search_apk(self, version: str | None = None) -> None | tuple[str, str | None]:
52
54
  """
53
55
  Searches for the APK on AppTeka and returns the title and link if found.
54
56
 
@@ -1,6 +1,8 @@
1
1
  import re
2
+
2
3
  from bs4 import BeautifulSoup
3
- import requests
4
+
5
+ from apksearch.sites import requests
4
6
 
5
7
 
6
8
  class Aptoide:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apksearch
3
- Version: 1.3.0
3
+ Version: 1.3.5
4
4
  Summary: Search for apks on varius websites
5
5
  Author-email: Abhi <allinoneallinone00@gmail.com>
6
6
  License: MIT License
@@ -49,6 +49,8 @@ Provides-Extra: dev
49
49
  Requires-Dist: pytest>=7.4.3; extra == "dev"
50
50
  Requires-Dist: black>=23.12.1; extra == "dev"
51
51
  Requires-Dist: flake8>=6.1.0; extra == "dev"
52
+ Provides-Extra: curl
53
+ Requires-Dist: curl_cffi>=0.12.1b1; extra == "curl"
52
54
  Dynamic: license-file
53
55
 
54
56
  <h1 align="center">apksearch</h1>
@@ -0,0 +1,17 @@
1
+ apksearch/__init__.py,sha256=PIO7B54j55_I5D7DEWcq_BVLK8Iwn48jB7uKjKhW83I,365
2
+ apksearch/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
3
+ apksearch/cli.py,sha256=gOvFyx35Byumt3VXct3gvwev0W5Nca2xfQulDd9CsYA,9582
4
+ apksearch/sites/__init__.py,sha256=IeT6HoIdeglXOkQuhfuZjlhADUI7L4bS2QIGG-zDgeM,147
5
+ apksearch/sites/apkad.py,sha256=UmVv4PL-L4SNJ5U4yERaRep-DG5V-QJ1A6hfy7DUwPQ,5072
6
+ apksearch/sites/apkcombo.py,sha256=WqiX9bt0Z8jx4JBkxyKzXrv32wxfZRKKO5RNn4Q74cw,4740
7
+ apksearch/sites/apkfab.py,sha256=DHnkDO96taEEvBxN8TVBW1flEqgAmkiU6MWcMUGJEFA,5623
8
+ apksearch/sites/apkmirror.py,sha256=slzj84w-WaiSQ9PjIC0EURceugbSC7u5bVgORDpVHtQ,3248
9
+ apksearch/sites/apkpure.py,sha256=7Ye9xNQylNj4RyqN8eG1cLqQjddvEOg1zVES1iFqmC4,8942
10
+ apksearch/sites/appteka.py,sha256=ivC8EQjy15HvLAQoqvOJQOso5Dv3Q3LTOnEc8OUXAc4,6409
11
+ apksearch/sites/aptoide.py,sha256=5_IkfYhEOvr2a1yxkEivqeO3PXPPj0HMwGefVBq95io,4839
12
+ apksearch-1.3.5.dist-info/licenses/LICENSE,sha256=Icu9iAY9cAaraq-HaAk8aWpXS1nE-3U_wfaOhN-HQUw,1061
13
+ apksearch-1.3.5.dist-info/METADATA,sha256=hj5WCRh0E8S6jK7e9JCZRJovOj0GU2YuIvkIca99hTg,8303
14
+ apksearch-1.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ apksearch-1.3.5.dist-info/entry_points.txt,sha256=FeAPgNPSU1tCwQNaKAmk6eQYbMHtsltcgeWSGUTxu0k,49
16
+ apksearch-1.3.5.dist-info/top_level.txt,sha256=VguZMODhlXWwDyJJNJms5syJ4EHmWSQOS45J9I5Cv5o,10
17
+ apksearch-1.3.5.dist-info/RECORD,,
@@ -1,108 +0,0 @@
1
- import re
2
- import requests
3
- from bs4 import BeautifulSoup
4
-
5
-
6
- class APKMonk:
7
- """
8
- This class provides methods to search for an APK on APKMonk based on package name,
9
- and to find available versions and their download links for a given APK link.
10
-
11
- Parameters:
12
- pkg_name (str): The package name of the APK to search for.
13
-
14
- Attributes:
15
- pkg_name (str): The package name of the APK to search for.
16
- base_url (str): The base URL of the APKMonk website.
17
- search_url (str): The URL used to search for APKs on APKMonk.
18
- headers (dict): The headers used for making HTTP requests.
19
- session (requests.Session): The session object used for making HTTP requests.
20
-
21
- Methods:
22
- search_apk() -> None | tuple[str, str]:
23
- Searches for the APK on APKMonk and returns the title and link if found.
24
-
25
- find_versions(apk_link: str) -> list[tuple[str, str]]:
26
- Finds and returns a list of versions and their download links for the given APK link.
27
- """
28
-
29
- def __init__(self, pkg_name: str):
30
- self.pkg_name = pkg_name
31
- self.base_url = "https://www.apkmonk.com"
32
- self.search_url = self.base_url + "/ssearch?q="
33
- self.headers = {
34
- "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",
35
- "accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
36
- "cache-control": "no-cache",
37
- "dnt": "1",
38
- "pragma": "no-cache",
39
- "priority": "u=0, i",
40
- "referer": "https://www.apkmonk.com/",
41
- "sec-ch-ua": '"Microsoft Edge";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
42
- "sec-ch-ua-mobile": "?0",
43
- "sec-ch-ua-platform": '"Windows"',
44
- "sec-fetch-dest": "document",
45
- "sec-fetch-mode": "navigate",
46
- "sec-fetch-site": "same-origin",
47
- "sec-fetch-user": "?1",
48
- "upgrade-insecure-requests": "1",
49
- "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0",
50
- }
51
- self.session = requests.Session()
52
-
53
- def search_apk(self) -> None | tuple[str, str]:
54
- """
55
- Searches for the APK on APKMonk and returns the title and link if found.
56
-
57
- Returns:
58
- None: If no matching APK is found.
59
- tuple[str, str]: A tuple containing the title and link of the matching APK if found.
60
- """
61
- pkg_name = self.pkg_name
62
- url = self.search_url + pkg_name
63
- response: requests.Response = self.session.get(url, headers=self.headers)
64
- soup = BeautifulSoup(response.text, "html.parser")
65
- search_results = soup.find("a", {"title": re.compile(".*apk$")})
66
- if search_results:
67
- link = search_results["href"]
68
- title = search_results.find("span", {"class": "af-title truncate"}).text
69
- if link == f"/app/{pkg_name}/":
70
- return title, f"{self.base_url}{link}"
71
- return None
72
-
73
- def find_versions(self, apk_link: str) -> list[tuple[str, str]]:
74
- """
75
- Finds and returns a list of versions and their download links for the given APK link.
76
-
77
- Parameters:
78
- apk_link (str): The link to the APK on the APKMonk website.
79
-
80
- Returns:
81
- list[tuple[str, str]]: A list of tuples, where each tuple contains the version number
82
- and its corresponding download link. If no versions are found, an empty list is returned.
83
- """
84
- versions_info = []
85
- if apk_link.startswith(self.base_url):
86
- url = apk_link
87
- response: requests.Response = self.session.get(url, headers=self.headers)
88
- soup = BeautifulSoup(response.text, "html.parser")
89
-
90
- version_header = soup.find(
91
- "div",
92
- {"class": "box-title"},
93
- text=re.compile("All Versions", re.IGNORECASE),
94
- )
95
-
96
- if version_header:
97
- versions_table = version_header.find_next("table", {"class": "striped"})
98
-
99
- if versions_table:
100
- rows = versions_table.find_all("tr")
101
- for row in rows:
102
- version_link = row.find("a", href=True)
103
- if version_link:
104
- version_number = version_link.text.strip()
105
- download_url = self.base_url + version_link["href"]
106
- versions_info.append((version_number, download_url))
107
-
108
- return versions_info
@@ -1,18 +0,0 @@
1
- apksearch/__init__.py,sha256=QvfqsYdMwBGKWiCEnADT1E1m74n5jjjSnrzvasbbZcs,415
2
- apksearch/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
3
- apksearch/cli.py,sha256=gpWmMXzcfGbLUnouSVUZzcxjP7ujWnf0sfqvdwkUIU8,10076
4
- apksearch/sites/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- apksearch/sites/apkad.py,sha256=x5nnI20Rj1LysZQc7-vFEbooxXb0vkmHzFpHoUvF_SA,4811
6
- apksearch/sites/apkcombo.py,sha256=AiJhSb0subQLb51dr8MQaxgeEZ77wI99InfigYfrcl4,4718
7
- apksearch/sites/apkfab.py,sha256=5f0fOBmQk0E30NcVE2cF80soJqI5ziOukU6_xMPtgFQ,5502
8
- apksearch/sites/apkmirror.py,sha256=IpS6r7ovM3g2dZrkR_a9zQpHy-jqrU2nJ3ykVkWxers,3127
9
- apksearch/sites/apkmonk.py,sha256=85bidRBz6RfZOaS9WEZfTXGnrMVsJEstMJT10XltWus,4657
10
- apksearch/sites/apkpure.py,sha256=iXZPzecdBy8JlJmC_yFCQrPi3hXnulRbqg7xCSd3Ppk,8975
11
- apksearch/sites/appteka.py,sha256=in04JYF043n0fUvBW1QQeXnNbYekGUIh4qeame951nA,6372
12
- apksearch/sites/aptoide.py,sha256=5RruPDwyo5z0E2XesX4Mi41ONdn26SxN0dH36eRolNQ,4816
13
- apksearch-1.3.0.dist-info/licenses/LICENSE,sha256=Icu9iAY9cAaraq-HaAk8aWpXS1nE-3U_wfaOhN-HQUw,1061
14
- apksearch-1.3.0.dist-info/METADATA,sha256=FXDYFNkHiFEupZa-Y7II6pla6inP8cF6oAjHpUlB_IA,8230
15
- apksearch-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- apksearch-1.3.0.dist-info/entry_points.txt,sha256=FeAPgNPSU1tCwQNaKAmk6eQYbMHtsltcgeWSGUTxu0k,49
17
- apksearch-1.3.0.dist-info/top_level.txt,sha256=VguZMODhlXWwDyJJNJms5syJ4EHmWSQOS45J9I5Cv5o,10
18
- apksearch-1.3.0.dist-info/RECORD,,