apksearch 1.2.7__tar.gz → 1.3.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.
- {apksearch-1.2.7 → apksearch-1.3.1}/PKG-INFO +4 -3
- {apksearch-1.2.7 → apksearch-1.3.1}/README.md +1 -1
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/__init__.py +9 -1
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/cli.py +9 -1
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/sites/apkpure.py +59 -1
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/sites/aptoide.py +19 -3
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch.egg-info/PKG-INFO +4 -3
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch.egg-info/SOURCES.txt +0 -1
- {apksearch-1.2.7 → apksearch-1.3.1}/pyproject.toml +1 -1
- {apksearch-1.2.7 → apksearch-1.3.1}/tests/test_apkfab.py +2 -2
- apksearch-1.2.7/tests/test_apkcombo.py +0 -38
- {apksearch-1.2.7 → apksearch-1.3.1}/LICENSE +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/__main__.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/sites/__init__.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/sites/apkad.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/sites/apkcombo.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/sites/apkfab.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/sites/apkmirror.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch/sites/appteka.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch.egg-info/dependency_links.txt +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch.egg-info/entry_points.txt +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch.egg-info/requires.txt +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/apksearch.egg-info/top_level.txt +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/setup.cfg +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/tests/test_apkmirror.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/tests/test_apkpure.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/tests/test_appteka.py +0 -0
- {apksearch-1.2.7 → apksearch-1.3.1}/tests/test_aptoide.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: apksearch
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.3.1
|
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,7 @@ 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
|
+
Dynamic: license-file
|
52
53
|
|
53
54
|
<h1 align="center">apksearch</h1>
|
54
55
|
|
@@ -186,7 +187,7 @@ pytest
|
|
186
187
|
## Acknowledgements
|
187
188
|
|
188
189
|
- [APKUpdater](https://github.com/rumboalla/apkupdater) for APKMirror API.
|
189
|
-
|
190
|
+
~~- [apkeep](https://github.com/EFForg/apkeep) for APKPure API.~~ (not used anymore)
|
190
191
|
|
191
192
|
## License
|
192
193
|
|
@@ -134,7 +134,7 @@ pytest
|
|
134
134
|
## Acknowledgements
|
135
135
|
|
136
136
|
- [APKUpdater](https://github.com/rumboalla/apkupdater) for APKMirror API.
|
137
|
-
|
137
|
+
~~- [apkeep](https://github.com/EFForg/apkeep) for APKPure API.~~ (not used anymore)
|
138
138
|
|
139
139
|
## License
|
140
140
|
|
@@ -6,4 +6,12 @@ from .sites.apkfab import APKFab
|
|
6
6
|
from .sites.apkad import APKad
|
7
7
|
from .sites.aptoide import Aptoide
|
8
8
|
|
9
|
-
__all__ = [
|
9
|
+
__all__ = [
|
10
|
+
"APKPure",
|
11
|
+
"APKMirror",
|
12
|
+
"AppTeka",
|
13
|
+
"APKCombo",
|
14
|
+
"APKFab",
|
15
|
+
"APKad",
|
16
|
+
"Aptoide",
|
17
|
+
]
|
@@ -1,7 +1,15 @@
|
|
1
1
|
import argparse
|
2
2
|
|
3
3
|
from collections.abc import Callable
|
4
|
-
from apksearch import
|
4
|
+
from apksearch import (
|
5
|
+
APKPure,
|
6
|
+
APKMirror,
|
7
|
+
AppTeka,
|
8
|
+
APKCombo,
|
9
|
+
APKFab,
|
10
|
+
APKad,
|
11
|
+
Aptoide,
|
12
|
+
)
|
5
13
|
from requests.exceptions import ConnectionError, ConnectTimeout
|
6
14
|
|
7
15
|
# Color codes
|
@@ -32,6 +32,19 @@ class APKPure:
|
|
32
32
|
self.cdn_url = "https://d.cdnpure.com/b/APK/"
|
33
33
|
self.cdn_version = "?version="
|
34
34
|
self.search_url = self.base_url + "/search?q="
|
35
|
+
self.api_url = "https://tapi.pureapk.com/v3/get_app_his_version"
|
36
|
+
self.api_headers = {
|
37
|
+
"User-Agent-WebView": "Mozilla/5.0 (Linux; Android 13; Pixel 5 Build/TQ3A.230901.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.122 Safari/537.36",
|
38
|
+
"User-Agent": "Dalvik/2.1.0 (Linux; U; Android 13; Pixel 5 Build/TQ3A.230901.001); APKPure/3.20.34 (Aegon)",
|
39
|
+
"Ual-Access-Businessid": "projecta",
|
40
|
+
"Ual-Access-ProjectA": """{"device_info":{"abis":["x86_64","arm64-v8a","x86","armeabi-v7a","armeabi"],"android_id":"50f838123d9a9c94","brand":"google","country":"United States","country_code":"US","imei":"","language":"en-US","manufacturer":"Google","mode":"Pixel 5","os_ver":"33","os_ver_name":"13","platform":1,"product":"redfin","screen_height":1080,"screen_width":1920},"host_app_info":{"build_no":"468","channel":"","md5":"6756e53158d6f6c013650a40d8f1147b","pkg_name":"com.apkpure.aegon","sdk_ver":"3.20.34","version_code":3203427,"version_name":"3.20.34"}}""",
|
41
|
+
"Ual-Access-ExtInfo": """{"ext_info":"{\"gaid\":\"\",\"oaid\":\"\"}","lbs_info":{"accuracy":0.0,"city":"","city_code":0,"country":"","country_code":"","district":"","latitude":0.0,"longitude":0.0,"province":"","street":""}}""",
|
42
|
+
"Ual-Access-Sequence": "",
|
43
|
+
"Ual-Access-Nonce": "21448252",
|
44
|
+
"Ual-Access-Timestamp": "1738560597165",
|
45
|
+
"Connection": "Keep-Alive",
|
46
|
+
"Accept-Encoding": "gzip",
|
47
|
+
}
|
35
48
|
self.headers = {
|
36
49
|
"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
50
|
"accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
|
@@ -52,6 +65,40 @@ class APKPure:
|
|
52
65
|
}
|
53
66
|
self.session = requests.Session()
|
54
67
|
|
68
|
+
def _api_search(self) -> None | tuple[str, list[tuple[str, str]]]:
|
69
|
+
"""
|
70
|
+
Attempts to fetch app information using API.
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
None: If API request fails or no data found
|
74
|
+
tuple[str, list[tuple[str, str]]]: App title and list of (version, download_url) tuples
|
75
|
+
"""
|
76
|
+
try:
|
77
|
+
params = {"package_name": self.pkg_name, "hl": "en"}
|
78
|
+
response = self.session.get(
|
79
|
+
self.api_url, headers=self.api_headers, params=params
|
80
|
+
)
|
81
|
+
data = response.json()
|
82
|
+
|
83
|
+
if not data.get("version_list"):
|
84
|
+
return None
|
85
|
+
|
86
|
+
versions_info = []
|
87
|
+
title = None
|
88
|
+
|
89
|
+
for version in data["version_list"]:
|
90
|
+
version_name = version["version_name"]
|
91
|
+
if not title:
|
92
|
+
title = version["title"]
|
93
|
+
if version.get("asset", {}).get("urls"):
|
94
|
+
download_url = version["asset"]["urls"][0]
|
95
|
+
versions_info.append((version_name, download_url))
|
96
|
+
|
97
|
+
return (title, versions_info) if title and versions_info else None
|
98
|
+
|
99
|
+
except Exception:
|
100
|
+
return None
|
101
|
+
|
55
102
|
def search_apk(self) -> None | tuple[str, str]:
|
56
103
|
"""
|
57
104
|
Searches for the APK on APKPure and returns the title and link if found.
|
@@ -83,7 +130,7 @@ class APKPure:
|
|
83
130
|
try:
|
84
131
|
location = response.headers.get("Location")
|
85
132
|
except AttributeError:
|
86
|
-
|
133
|
+
location = None
|
87
134
|
if location:
|
88
135
|
if location == "https://apkpure.com":
|
89
136
|
return None
|
@@ -97,6 +144,13 @@ class APKPure:
|
|
97
144
|
if content:
|
98
145
|
apk_title = content.split("filename=")[1].strip('"').split("_")[0]
|
99
146
|
return apk_title, location
|
147
|
+
|
148
|
+
api_result = self._api_search()
|
149
|
+
if api_result:
|
150
|
+
title, versions = api_result
|
151
|
+
if versions:
|
152
|
+
return title, versions[0][1]
|
153
|
+
|
100
154
|
return None
|
101
155
|
|
102
156
|
def find_versions(self, apk_link: str) -> list[tuple[str, str]]:
|
@@ -110,6 +164,10 @@ class APKPure:
|
|
110
164
|
list[tuple[str, str]]: A list of tuples, where each tuple contains the version number
|
111
165
|
and its corresponding download link. If no versions are found, an empty list is returned.
|
112
166
|
"""
|
167
|
+
api_result = self._api_search()
|
168
|
+
if api_result:
|
169
|
+
return api_result[1]
|
170
|
+
|
113
171
|
versions_info = []
|
114
172
|
if apk_link.startswith(self.base_url):
|
115
173
|
url = apk_link + "/versions"
|
@@ -29,7 +29,7 @@ class Aptoide:
|
|
29
29
|
def __init__(self, pkg_name: str):
|
30
30
|
self.pkg_name = pkg_name
|
31
31
|
self.api_url = "https://ws75.aptoide.com/api/7"
|
32
|
-
self.search_url = f"{self.api_url}/apps/search
|
32
|
+
self.search_url = f"{self.api_url}/apps/search"
|
33
33
|
self.headers = {
|
34
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
35
|
"accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
|
@@ -48,6 +48,20 @@ class Aptoide:
|
|
48
48
|
"upgrade-insecure-requests": "1",
|
49
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
50
|
}
|
51
|
+
self.params = {
|
52
|
+
"cdn": "web",
|
53
|
+
"q": "bXlDUFU9YXJtNjQtdjhhLGFybWVhYmktdjdhLGFybWVhYmkmbGVhbmJhY2s9MA",
|
54
|
+
"aab": "1",
|
55
|
+
"mature": "false",
|
56
|
+
"language": "en_US",
|
57
|
+
"country": "US",
|
58
|
+
"not_apk_tags": "",
|
59
|
+
"query": self.pkg_name,
|
60
|
+
"limit": "1",
|
61
|
+
"offset": "0",
|
62
|
+
"origin": "SITE",
|
63
|
+
"store_name": "aptoide-web",
|
64
|
+
}
|
51
65
|
self.session = requests.Session()
|
52
66
|
|
53
67
|
def search_apk(self) -> None | tuple[str, str]:
|
@@ -59,8 +73,10 @@ class Aptoide:
|
|
59
73
|
tuple[str, str]: A tuple containing the title and link of the matching APK if found.
|
60
74
|
"""
|
61
75
|
pkg_name = self.pkg_name
|
62
|
-
url = self.search_url
|
63
|
-
response: requests.Response = self.session.get(
|
76
|
+
url = self.search_url
|
77
|
+
response: requests.Response = self.session.get(
|
78
|
+
url, headers=self.headers, params=self.params
|
79
|
+
)
|
64
80
|
data = response.json()
|
65
81
|
if data and data["info"]["status"] == "OK":
|
66
82
|
lis = data["datalist"]["list"]
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: apksearch
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.3.1
|
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,7 @@ 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
|
+
Dynamic: license-file
|
52
53
|
|
53
54
|
<h1 align="center">apksearch</h1>
|
54
55
|
|
@@ -186,7 +187,7 @@ pytest
|
|
186
187
|
## Acknowledgements
|
187
188
|
|
188
189
|
- [APKUpdater](https://github.com/rumboalla/apkupdater) for APKMirror API.
|
189
|
-
|
190
|
+
~~- [apkeep](https://github.com/EFForg/apkeep) for APKPure API.~~ (not used anymore)
|
190
191
|
|
191
192
|
## License
|
192
193
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "apksearch"
|
7
|
-
version = "1.
|
7
|
+
version = "1.3.1"
|
8
8
|
description = "Search for apks on varius websites"
|
9
9
|
authors = [{ name = "Abhi", email = "allinoneallinone00@gmail.com" }]
|
10
10
|
license = { file = "LICENSE" }
|
@@ -2,7 +2,7 @@ from apksearch.sites.apkfab import APKFab
|
|
2
2
|
|
3
3
|
|
4
4
|
def test_search_apk():
|
5
|
-
query = "com.
|
5
|
+
query = "com.facebook.katana"
|
6
6
|
apkfab = APKFab(query)
|
7
7
|
result = apkfab.search_apk()
|
8
8
|
|
@@ -14,7 +14,7 @@ def test_search_apk():
|
|
14
14
|
|
15
15
|
|
16
16
|
def test_find_versions():
|
17
|
-
query = "com.
|
17
|
+
query = "com.facebook.katana"
|
18
18
|
apkfab = APKFab(query)
|
19
19
|
result = apkfab.search_apk()
|
20
20
|
|
@@ -1,38 +0,0 @@
|
|
1
|
-
from apksearch.sites.apkcombo import APKCombo
|
2
|
-
|
3
|
-
|
4
|
-
def test_search_apk():
|
5
|
-
query = "com.roblox.client"
|
6
|
-
apkcombo = APKCombo(query)
|
7
|
-
result = apkcombo.search_apk()
|
8
|
-
|
9
|
-
assert result is not None, "No APK found for the query."
|
10
|
-
assert isinstance(result, tuple), "Result should be a tuple."
|
11
|
-
assert len(result) == 2, "Tuple should contain two elements."
|
12
|
-
assert isinstance(result[0], str), "First element of the tuple should be a string."
|
13
|
-
assert isinstance(result[1], str), "Second element of the tuple should be a string."
|
14
|
-
|
15
|
-
|
16
|
-
def test_find_versions():
|
17
|
-
query = "com.roblox.client"
|
18
|
-
apkcombo = APKCombo(query)
|
19
|
-
result = apkcombo.search_apk()
|
20
|
-
|
21
|
-
if result:
|
22
|
-
apk_link = result[1]
|
23
|
-
versions = apkcombo.find_versions(apk_link)
|
24
|
-
|
25
|
-
assert isinstance(versions, list), "Versions should be a list."
|
26
|
-
assert len(versions) > 0, "No versions found."
|
27
|
-
assert all(
|
28
|
-
isinstance(version, tuple) for version in versions
|
29
|
-
), "Each version should be a tuple."
|
30
|
-
assert all(
|
31
|
-
len(version) == 2 for version in versions
|
32
|
-
), "Each version tuple should contain two elements."
|
33
|
-
assert all(
|
34
|
-
isinstance(version[0], str) for version in versions
|
35
|
-
), "First element of each version tuple should be a string."
|
36
|
-
assert all(
|
37
|
-
isinstance(version[1], str) for version in versions
|
38
|
-
), "Second element of each version tuple should be a string."
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|