Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
anasty17
GitHub Repository: anasty17/mirror-leech-telegram-bot
Path: blob/master/bot/modules/search.py
1628 views
1
from httpx import AsyncClient
2
from html import escape
3
from urllib.parse import quote
4
5
from .. import LOGGER
6
from ..core.config_manager import Config
7
from ..core.torrent_manager import TorrentManager
8
from ..helper.ext_utils.bot_utils import new_task
9
from ..helper.ext_utils.status_utils import get_readable_file_size
10
from ..helper.ext_utils.telegraph_helper import telegraph
11
from ..helper.telegram_helper.button_build import ButtonMaker
12
from ..helper.telegram_helper.message_utils import edit_message, send_message
13
14
PLUGINS = []
15
SITES = None
16
TELEGRAPH_LIMIT = 300
17
18
19
async def initiate_search_tools():
20
qb_plugins = await TorrentManager.qbittorrent.search.plugins()
21
if qb_plugins:
22
names = [plugin.name for plugin in qb_plugins]
23
await TorrentManager.qbittorrent.search.uninstall_plugin(names)
24
PLUGINS.clear()
25
if Config.SEARCH_PLUGINS:
26
await TorrentManager.qbittorrent.search.install_plugin(Config.SEARCH_PLUGINS)
27
28
if Config.SEARCH_API_LINK:
29
global SITES
30
try:
31
async with AsyncClient() as client:
32
response = await client.get(f"{Config.SEARCH_API_LINK}/api/v1/sites")
33
data = response.json()
34
SITES = {
35
str(site): str(site).capitalize() for site in data["supported_sites"]
36
}
37
SITES["all"] = "All"
38
except Exception as e:
39
LOGGER.error(
40
f"{e} Can't fetching sites from SEARCH_API_LINK make sure use latest version of API"
41
)
42
SITES = None
43
44
45
async def search(key, site, message, method):
46
if method.startswith("api"):
47
if method == "apisearch":
48
LOGGER.info(f"API Searching: {key} from {site}")
49
if site == "all":
50
api = f"{Config.SEARCH_API_LINK}/api/v1/all/search?query={key}&limit={Config.SEARCH_LIMIT}"
51
else:
52
api = f"{Config.SEARCH_API_LINK}/api/v1/search?site={site}&query={key}&limit={Config.SEARCH_LIMIT}"
53
elif method == "apitrend":
54
LOGGER.info(f"API Trending from {site}")
55
if site == "all":
56
api = f"{Config.SEARCH_API_LINK}/api/v1/all/trending?limit={Config.SEARCH_LIMIT}"
57
else:
58
api = f"{Config.SEARCH_API_LINK}/api/v1/trending?site={site}&limit={Config.SEARCH_LIMIT}"
59
elif method == "apirecent":
60
LOGGER.info(f"API Recent from {site}")
61
if site == "all":
62
api = f"{Config.SEARCH_API_LINK}/api/v1/all/recent?limit={Config.SEARCH_LIMIT}"
63
else:
64
api = f"{Config.SEARCH_API_LINK}/api/v1/recent?site={site}&limit={Config.SEARCH_LIMIT}"
65
try:
66
async with AsyncClient() as client:
67
response = await client.get(api)
68
search_results = response.json()
69
if "error" in search_results or search_results["total"] == 0:
70
await edit_message(
71
message,
72
f"No result found for <i>{key}</i>\nTorrent Site:- <i>{SITES.get(site)}</i>",
73
)
74
return
75
msg = f"<b>Found {min(search_results['total'], TELEGRAPH_LIMIT)}</b>"
76
if method == "apitrend":
77
msg += f" <b>trending result(s)\nTorrent Site:- <i>{SITES.get(site)}</i></b>"
78
elif method == "apirecent":
79
msg += (
80
f" <b>recent result(s)\nTorrent Site:- <i>{SITES.get(site)}</i></b>"
81
)
82
else:
83
msg += f" <b>result(s) for <i>{key}</i>\nTorrent Site:- <i>{SITES.get(site)}</i></b>"
84
search_results = search_results["data"]
85
except Exception as e:
86
await edit_message(message, str(e))
87
return
88
else:
89
LOGGER.info(f"PLUGINS Searching: {key} from {site}")
90
search = await TorrentManager.qbittorrent.search.start(
91
pattern=key, plugins=[site], category="all"
92
)
93
search_id = search.id
94
while True:
95
result_status = await TorrentManager.qbittorrent.search.status(search_id)
96
status = result_status[0].status
97
if status != "Running":
98
break
99
dict_search_results = await TorrentManager.qbittorrent.search.results(
100
id=search_id, limit=TELEGRAPH_LIMIT
101
)
102
search_results = dict_search_results.results
103
total_results = dict_search_results.total
104
if total_results == 0:
105
await edit_message(
106
message,
107
f"No result found for <i>{key}</i>\nTorrent Site:- <i>{site.capitalize()}</i>",
108
)
109
return
110
msg = f"<b>Found {min(total_results, TELEGRAPH_LIMIT)}</b>"
111
msg += f" <b>result(s) for <i>{key}</i>\nTorrent Site:- <i>{site.capitalize()}</i></b>"
112
await TorrentManager.qbittorrent.search.delete(search_id)
113
link = await get_result(search_results, key, message, method)
114
buttons = ButtonMaker()
115
buttons.url_button("🔎 VIEW", link)
116
button = buttons.build_menu(1)
117
await edit_message(message, msg, button)
118
119
120
async def get_result(search_results, key, message, method):
121
telegraph_content = []
122
if method == "apirecent":
123
msg = "<h4>API Recent Results</h4>"
124
elif method == "apisearch":
125
msg = f"<h4>API Search Result(s) For {key}</h4>"
126
elif method == "apitrend":
127
msg = "<h4>API Trending Results</h4>"
128
else:
129
msg = f"<h4>PLUGINS Search Result(s) For {key}</h4>"
130
for index, result in enumerate(search_results, start=1):
131
if method.startswith("api"):
132
try:
133
if "name" in result.keys():
134
msg += f"<code><a href='{result['url']}'>{escape(result['name'])}</a></code><br>"
135
if "torrents" in result.keys():
136
for subres in result["torrents"]:
137
msg += f"<b>Quality: </b>{subres['quality']} | <b>Type: </b>{subres['type']} | "
138
msg += f"<b>Size: </b>{subres['size']}<br>"
139
if "torrent" in subres.keys():
140
msg += f"<a href='{subres['torrent']}'>Direct Link</a><br>"
141
elif "magnet" in subres.keys():
142
msg += "<b>Share Magnet to</b> "
143
msg += f"<a href='http://t.me/share/url?url={subres['magnet']}'>Telegram</a><br>"
144
msg += "<br>"
145
else:
146
msg += f"<b>Size: </b>{result['size']}<br>"
147
try:
148
msg += f"<b>Seeders: </b>{result['seeders']} | <b>Leechers: </b>{result['leechers']}<br>"
149
except:
150
pass
151
if "torrent" in result.keys():
152
msg += f"<a href='{result['torrent']}'>Direct Link</a><br><br>"
153
elif "magnet" in result.keys():
154
msg += "<b>Share Magnet to</b> "
155
msg += f"<a href='http://t.me/share/url?url={quote(result['magnet'])}'>Telegram</a><br><br>"
156
else:
157
msg += "<br>"
158
except:
159
continue
160
else:
161
msg += f"<a href='{result.descrLink}'>{escape(result.fileName)}</a><br>"
162
msg += f"<b>Size: </b>{get_readable_file_size(result.fileSize)}<br>"
163
msg += f"<b>Seeders: </b>{result.nbSeeders} | <b>Leechers: </b>{result.nbLeechers}<br>"
164
link = result.fileUrl
165
if link.startswith("magnet:"):
166
msg += f"<b>Share Magnet to</b> <a href='http://t.me/share/url?url={quote(link)}'>Telegram</a><br><br>"
167
else:
168
msg += f"<a href='{link}'>Direct Link</a><br><br>"
169
170
if len(msg.encode("utf-8")) > 39000:
171
telegraph_content.append(msg)
172
msg = ""
173
174
if index == TELEGRAPH_LIMIT:
175
break
176
177
if msg != "":
178
telegraph_content.append(msg)
179
180
await edit_message(
181
message, f"<b>Creating</b> {len(telegraph_content)} <b>Telegraph pages.</b>"
182
)
183
path = [
184
(
185
await telegraph.create_page(
186
title="Mirror-leech-bot Torrent Search", content=content
187
)
188
)["path"]
189
for content in telegraph_content
190
]
191
if len(path) > 1:
192
await edit_message(
193
message, f"<b>Editing</b> {len(telegraph_content)} <b>Telegraph pages.</b>"
194
)
195
await telegraph.edit_telegraph(path, telegraph_content)
196
return f"https://telegra.ph/{path[0]}"
197
198
199
def api_buttons(user_id, method):
200
buttons = ButtonMaker()
201
for data, name in SITES.items():
202
buttons.data_button(name, f"torser {user_id} {data} {method}")
203
buttons.data_button("Cancel", f"torser {user_id} cancel")
204
return buttons.build_menu(2)
205
206
207
async def plugin_buttons(user_id):
208
buttons = ButtonMaker()
209
if not PLUGINS:
210
pl = await TorrentManager.qbittorrent.search.plugins()
211
for i in pl:
212
PLUGINS.append(i.name)
213
for siteName in PLUGINS:
214
buttons.data_button(
215
siteName.capitalize(), f"torser {user_id} {siteName} plugin"
216
)
217
buttons.data_button("All", f"torser {user_id} all plugin")
218
buttons.data_button("Cancel", f"torser {user_id} cancel")
219
return buttons.build_menu(2)
220
221
222
@new_task
223
async def torrent_search(_, message):
224
user_id = message.from_user.id
225
buttons = ButtonMaker()
226
key = message.text.split()
227
if SITES is None and not Config.SEARCH_PLUGINS:
228
await send_message(
229
message, "No API link or search PLUGINS added for this function"
230
)
231
elif len(key) == 1 and SITES is None:
232
await send_message(message, "Send a search key along with command")
233
elif len(key) == 1:
234
buttons.data_button("Trending", f"torser {user_id} apitrend")
235
buttons.data_button("Recent", f"torser {user_id} apirecent")
236
buttons.data_button("Cancel", f"torser {user_id} cancel")
237
button = buttons.build_menu(2)
238
await send_message(message, "Send a search key along with command", button)
239
elif SITES is not None and Config.SEARCH_PLUGINS:
240
buttons.data_button("Api", f"torser {user_id} apisearch")
241
buttons.data_button("Plugins", f"torser {user_id} plugin")
242
buttons.data_button("Cancel", f"torser {user_id} cancel")
243
button = buttons.build_menu(2)
244
await send_message(message, "Choose tool to search:", button)
245
elif SITES is not None:
246
button = api_buttons(user_id, "apisearch")
247
await send_message(message, "Choose site to search | API:", button)
248
else:
249
button = await plugin_buttons(user_id)
250
await send_message(message, "Choose site to search | Plugins:", button)
251
252
253
@new_task
254
async def torrent_search_update(_, query):
255
user_id = query.from_user.id
256
message = query.message
257
key = message.reply_to_message.text.split(maxsplit=1)
258
key = key[1].strip() if len(key) > 1 else None
259
data = query.data.split()
260
if user_id != int(data[1]):
261
await query.answer("Not Yours!", show_alert=True)
262
elif data[2].startswith("api"):
263
await query.answer()
264
button = api_buttons(user_id, data[2])
265
await edit_message(message, "Choose site:", button)
266
elif data[2] == "plugin":
267
await query.answer()
268
button = await plugin_buttons(user_id)
269
await edit_message(message, "Choose site:", button)
270
elif data[2] != "cancel":
271
await query.answer()
272
site = data[2]
273
method = data[3]
274
if method.startswith("api"):
275
if key is None:
276
if method == "apirecent":
277
endpoint = "Recent"
278
elif method == "apitrend":
279
endpoint = "Trending"
280
await edit_message(
281
message,
282
f"<b>Listing {endpoint} Items...\nTorrent Site:- <i>{SITES.get(site)}</i></b>",
283
)
284
else:
285
await edit_message(
286
message,
287
f"<b>Searching for <i>{key}</i>\nTorrent Site:- <i>{SITES.get(site)}</i></b>",
288
)
289
else:
290
await edit_message(
291
message,
292
f"<b>Searching for <i>{key}</i>\nTorrent Site:- <i>{site.capitalize()}</i></b>",
293
)
294
await search(key, site, message, method)
295
else:
296
await query.answer()
297
await edit_message(message, "Search has been canceled!")
298
299