plexflow 0.0.64__py3-none-any.whl → 0.0.66__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.
- plexflow/core/torrents/auto/auto_torrents.py +4 -4
- plexflow/core/torrents/providers/ext/ext.py +1 -1
- plexflow/core/torrents/providers/therarbg/therarbg.py +4 -4
- plexflow/core/torrents/providers/tpb/tpb.py +10 -8
- plexflow/core/torrents/providers/yts/yts.py +14 -7
- plexflow/utils/antibot/human_like_requests.py +10 -0
- plexflow/utils/api/context/http.py +32 -5
- plexflow/utils/api/rest/plexful.py +64 -0
- plexflow/utils/api/rest/url_builder.py +9 -0
- plexflow/utils/llm/mistral.py +139 -0
- plexflow/utils/pubsub/produce.py +22 -1
- plexflow/utils/strings/json_extract.py +434 -0
- plexflow/utils/subtitle/search.py +1 -0
- plexflow/utils/torrent/extract/common.py +1 -0
- plexflow/utils/torrent/files.py +49 -5
- plexflow/utils/torrent/hash.py +7 -1
- plexflow/utils/transcribe/speech2text.py +83 -17
- plexflow/utils/video/audio.py +98 -0
- plexflow/utils/video/subtitle.py +32 -61
- {plexflow-0.0.64.dist-info → plexflow-0.0.66.dist-info}/METADATA +6 -4
- {plexflow-0.0.64.dist-info → plexflow-0.0.66.dist-info}/RECORD +23 -18
- {plexflow-0.0.64.dist-info → plexflow-0.0.66.dist-info}/entry_points.txt +3 -0
- {plexflow-0.0.64.dist-info → plexflow-0.0.66.dist-info}/WHEEL +0 -0
@@ -0,0 +1,434 @@
|
|
1
|
+
import json
|
2
|
+
import re
|
3
|
+
|
4
|
+
def extract_json_from_string(text):
|
5
|
+
"""
|
6
|
+
Extracts JSON objects from a string. Handles multiple JSON objects
|
7
|
+
and ignores invalid JSON parts.
|
8
|
+
|
9
|
+
Args:
|
10
|
+
text: The input string potentially containing JSON.
|
11
|
+
|
12
|
+
Returns:
|
13
|
+
A list of dictionaries, where each dictionary represents a
|
14
|
+
valid JSON object found in the string. Returns an empty list
|
15
|
+
if no valid JSON is found.
|
16
|
+
"""
|
17
|
+
|
18
|
+
json_objects = []
|
19
|
+
# Regular expression to find potential JSON objects (improved)
|
20
|
+
# This looks for curly braces and square brackets to identify
|
21
|
+
# potential JSON structures. It's not perfect, but it's a reasonable
|
22
|
+
# starting point.
|
23
|
+
json_matches = re.finditer(r"\[.*?\]|\{.*?\}", text, re.DOTALL) # DOTALL makes . match newlines
|
24
|
+
|
25
|
+
for match in json_matches:
|
26
|
+
try:
|
27
|
+
json_object = json.loads(match.group(0)) # Attempt to parse
|
28
|
+
json_objects.append(json_object)
|
29
|
+
except json.JSONDecodeError:
|
30
|
+
# If parsing fails, it wasn't valid JSON, so we ignore it.
|
31
|
+
pass # or print(f"Invalid JSON found: {match.group(0)}") for debugging
|
32
|
+
|
33
|
+
return json_objects
|
34
|
+
|
35
|
+
|
36
|
+
if __name__ == "__main__":
|
37
|
+
raw = """
|
38
|
+
Sure, here is the JSON representation of the parsed torrents with the specified fields:
|
39
|
+
|
40
|
+
```json
|
41
|
+
[
|
42
|
+
{
|
43
|
+
"title": "Wicked.2024.UHD.BluRay.2160p.TrueHD.Atmos.7.1.DV.HEVC.REMUX-FraMeSToR",
|
44
|
+
"category": "Movies : 4K UHD",
|
45
|
+
"language": "English",
|
46
|
+
"size": "77.22 GB",
|
47
|
+
"seeds": 2,
|
48
|
+
"peers": 1856,
|
49
|
+
"date": "30/01/25 06:17",
|
50
|
+
"uploader": "JackONeill:_verified_uploader:",
|
51
|
+
"S/L": "[214/399]"
|
52
|
+
},
|
53
|
+
{
|
54
|
+
"title": "Wicked.2024.1080p.Bluray.DDP7.1.HEVC.x265-BluBirD",
|
55
|
+
"category": "Movies : HD",
|
56
|
+
"language": "English",
|
57
|
+
"size": "6.63 GB",
|
58
|
+
"seeds": 0,
|
59
|
+
"peers": 537,
|
60
|
+
"date": "29/01/25 23:57",
|
61
|
+
"uploader": "Nick007:_trusted_uploader:",
|
62
|
+
"S/L": "[419/70]"
|
63
|
+
},
|
64
|
+
{
|
65
|
+
"title": "Wicked.2024.1080p.BluRay.AAC5.1 [YTS]",
|
66
|
+
"category": "Movies : HD",
|
67
|
+
"language": "English",
|
68
|
+
"size": "2.95 GB",
|
69
|
+
"seeds": 0,
|
70
|
+
"peers": 396,
|
71
|
+
"date": "29/01/25 22:00",
|
72
|
+
"uploader": "indexFroggy:_trusted_uploader:",
|
73
|
+
"S/L": "[679/217]"
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"title": "Wicked.2024.1080p.WEBRip.x265.10bit.AAC5.1 [YTS]",
|
77
|
+
"category": "Movies : HD",
|
78
|
+
"language": "English",
|
79
|
+
"size": "2.70 GB",
|
80
|
+
"seeds": 1,
|
81
|
+
"peers": 3757,
|
82
|
+
"date": "29/01/25 20:09",
|
83
|
+
"uploader": "indexFroggy:_trusted_uploader:",
|
84
|
+
"S/L": "[3,483/574]"
|
85
|
+
},
|
86
|
+
{
|
87
|
+
"title": "Wicked.2024.720p.BluRay [YTS]",
|
88
|
+
"category": "Movies : HD",
|
89
|
+
"language": "English",
|
90
|
+
"size": "1.44 GB",
|
91
|
+
"seeds": 0,
|
92
|
+
"peers": 337,
|
93
|
+
"date": "29/01/25 20:00",
|
94
|
+
"uploader": "indexFroggy:_trusted_uploader:",
|
95
|
+
"S/L": "[305/178]"
|
96
|
+
},
|
97
|
+
{
|
98
|
+
"title": "Wicked.2024.1080p.Blu-ray.Remux.AVC.TrueHD.Atmos.7.1-CiNEPHiLES",
|
99
|
+
"category": "Movies : HD",
|
100
|
+
"language": "English",
|
101
|
+
"size": "31.79 GB",
|
102
|
+
"seeds": 0,
|
103
|
+
"peers": 593,
|
104
|
+
"date": "29/01/25 15:01",
|
105
|
+
"uploader": "JackONeill:_verified_uploader:",
|
106
|
+
"S/L": "[111/40]"
|
107
|
+
},
|
108
|
+
{
|
109
|
+
"title": "Wicked.(2024).1080p.DS4K.10bit.AMZN.WEBRip.DDP.5.1.Atmos.x265-DE3PM.",
|
110
|
+
"category": "Movies : HD",
|
111
|
+
"language": "Hindi",
|
112
|
+
"size": "6.06 GB",
|
113
|
+
"seeds": 0,
|
114
|
+
"peers": 933,
|
115
|
+
"date": "15/01/25 05:43",
|
116
|
+
"uploader": "DE3PM:_verified_uploader:",
|
117
|
+
"S/L": "[28/20]"
|
118
|
+
},
|
119
|
+
{
|
120
|
+
"title": "Wicked.2024.2160p.WEB-DL.DDP5.1.Atmos.DV.H.265.MP4",
|
121
|
+
"category": "Movies : 4K UHD",
|
122
|
+
"language": "English",
|
123
|
+
"size": "28.52 GB",
|
124
|
+
"seeds": 2,
|
125
|
+
"peers": 1991,
|
126
|
+
"date": "11/01/25 11:16",
|
127
|
+
"uploader": "VarroaD:_verified_uploader:",
|
128
|
+
"S/L": "[27/32]"
|
129
|
+
},
|
130
|
+
{
|
131
|
+
"title": "Wicked (2024) DS4K 1080p MA WEBRip AV1 Opus 5.1 [RAV1NE]",
|
132
|
+
"category": "Movies : HD",
|
133
|
+
"language": "English",
|
134
|
+
"size": "3.19 GB",
|
135
|
+
"seeds": 1,
|
136
|
+
"peers": 1886,
|
137
|
+
"date": "06/01/25 15:26",
|
138
|
+
"uploader": "RAV1NE:_trusted_uploader:",
|
139
|
+
"S/L": "[147/33]"
|
140
|
+
},
|
141
|
+
{
|
142
|
+
"title": "Wicked.2024.1080p.WEBRip.AAC5.1 [YTS]",
|
143
|
+
"category": "Movies : HD",
|
144
|
+
"language": "English",
|
145
|
+
"size": "2.95 GB",
|
146
|
+
"seeds": 0,
|
147
|
+
"peers": 8320,
|
148
|
+
"date": "05/01/25 19:26",
|
149
|
+
"uploader": "indexFroggy:_trusted_uploader:",
|
150
|
+
"S/L": "[817/135]"
|
151
|
+
},
|
152
|
+
{
|
153
|
+
"title": "Wicked.2024.720p.WEBRip [YTS]",
|
154
|
+
"category": "Movies : HD",
|
155
|
+
"language": "English",
|
156
|
+
"size": "1.44 GB",
|
157
|
+
"seeds": 0,
|
158
|
+
"peers": 1881,
|
159
|
+
"date": "05/01/25 17:23",
|
160
|
+
"uploader": "indexFroggy:_trusted_uploader:",
|
161
|
+
"S/L": "[36/157]"
|
162
|
+
},
|
163
|
+
{
|
164
|
+
"title": "Wicked.2024.DUAL-AUDiO.SPA-ENG.2160p.WEB-DL.DV.DDP5.1.HDR10Plus.H.265-DMnT",
|
165
|
+
"category": "Movies : 4K UHD",
|
166
|
+
"language": "Other / Multiple",
|
167
|
+
"size": "28.84 GB",
|
168
|
+
"seeds": 0,
|
169
|
+
"peers": 1557,
|
170
|
+
"date": "04/01/25 17:25",
|
171
|
+
"uploader": "outr0x:_trusted_uploader:",
|
172
|
+
"S/L": "[40/106]"
|
173
|
+
},
|
174
|
+
{
|
175
|
+
"title": "Wicked.2024.DUAL-AUDiO.SPA-ENG.1080p.WEB-DL.DDP5.1.H.264-DMnT",
|
176
|
+
"category": "Movies : HD",
|
177
|
+
"language": "Other / Multiple",
|
178
|
+
"size": "11.81 GB",
|
179
|
+
"seeds": 0,
|
180
|
+
"peers": 657,
|
181
|
+
"date": "04/01/25 17:24",
|
182
|
+
"uploader": "outr0x:_trusted_uploader:",
|
183
|
+
"S/L": "[40/79]"
|
184
|
+
},
|
185
|
+
{
|
186
|
+
"title": "Wicked.2024.1080p.MA.WEB-DL.DDP5.1.Atmos.H.264-FLUX.mkv",
|
187
|
+
"category": "Movies : HD",
|
188
|
+
"language": "English",
|
189
|
+
"size": "9.70 GB",
|
190
|
+
"seeds": 0,
|
191
|
+
"peers": 1985,
|
192
|
+
"date": "03/01/25 08:31",
|
193
|
+
"uploader": "platypusp:_trusted_uploader:",
|
194
|
+
"S/L": "[86/17]"
|
195
|
+
},
|
196
|
+
{
|
197
|
+
"title": "Wicked.2024.2160p.WEBRip.x265.10bit.AAC5.1 [YTS]",
|
198
|
+
"category": "Movies : 4K UHD",
|
199
|
+
"language": "English",
|
200
|
+
"size": "7.20 GB",
|
201
|
+
"seeds": 0,
|
202
|
+
"peers": 6310,
|
203
|
+
"date": "03/01/25 04:43",
|
204
|
+
"uploader": "indexFroggy:_trusted_uploader:",
|
205
|
+
"S/L": "[1,418/260]"
|
206
|
+
},
|
207
|
+
{
|
208
|
+
"title": "Wicked (2024) 1080p WEBDL H264 Subs - LoZio .mkv",
|
209
|
+
"category": "Movies : HD",
|
210
|
+
"language": "English",
|
211
|
+
"size": "4.22 GB",
|
212
|
+
"seeds": 1,
|
213
|
+
"peers": 1614,
|
214
|
+
"date": "01/01/25 15:19",
|
215
|
+
"uploader": "LoZio:_trusted_uploader:",
|
216
|
+
"S/L": "[53/14]"
|
217
|
+
},
|
218
|
+
{
|
219
|
+
"title": "Wicked.2024.1080p.AMZN.WEB-DL.x264.ESubs.[2.4GB].[MP4]",
|
220
|
+
"category": "Movies : HD",
|
221
|
+
"language": "English",
|
222
|
+
"size": "2.45 GB",
|
223
|
+
"seeds": 0,
|
224
|
+
"peers": 4747,
|
225
|
+
"date": "01/01/25 04:24",
|
226
|
+
"uploader": "cutee143:_trusted_uploader:",
|
227
|
+
"S/L": "[137/92]"
|
228
|
+
},
|
229
|
+
{
|
230
|
+
"title": "Wicked.2024.720p.AMZN.WEB-DL.x264.ESubs.[1.3GB].[MP4]",
|
231
|
+
"category": "Movies : HD",
|
232
|
+
"language": "English",
|
233
|
+
"size": "1.32 GB",
|
234
|
+
"seeds": 1,
|
235
|
+
"peers": 7919,
|
236
|
+
"date": "31/12/24 19:56",
|
237
|
+
"uploader": "cutee143:_trusted_uploader:",
|
238
|
+
"S/L": "[348/197]"
|
239
|
+
},
|
240
|
+
{
|
241
|
+
"title": "Wicked. 2024. 1080P. AMZN WEB-DL. DDP5.1. HEVC-X265. POOTLED.mkv",
|
242
|
+
"category": "Movies : HD",
|
243
|
+
"language": "English",
|
244
|
+
"size": "4.49 GB",
|
245
|
+
"seeds": 0,
|
246
|
+
"peers": 2323,
|
247
|
+
"date": "31/12/24 17:58",
|
248
|
+
"uploader": "Pootle:_trusted_uploader:",
|
249
|
+
"S/L": "[39/21]"
|
250
|
+
},
|
251
|
+
{
|
252
|
+
"title": "Wicked 2024 1080p WEB-DL HEVC x265 5.1 BONE",
|
253
|
+
"category": "Movies : HD",
|
254
|
+
"language": "English",
|
255
|
+
"size": "1.99 GB",
|
256
|
+
"seeds": 7,
|
257
|
+
"peers": 16187,
|
258
|
+
"date": "31/12/24 17:32",
|
259
|
+
"uploader": "B0NE:_trusted_uploader::_sitefriend:",
|
260
|
+
"S/L": "[430/361]"
|
261
|
+
},
|
262
|
+
{
|
263
|
+
"title": "Wicked 2024 720p AMZN WEBRip English Hindi AAC 5.1 ESubs x264 - mkvAnime.mkv",
|
264
|
+
"category": "Movies : HD",
|
265
|
+
"language": "Hindi",
|
266
|
+
"size": "1.69 GB",
|
267
|
+
"seeds": 0,
|
268
|
+
"peers": 685,
|
269
|
+
"date": "31/12/24 16:15",
|
270
|
+
"uploader": "LOKiHD:_verified_uploader::_sitefriend:",
|
271
|
+
"S/L": "[1/21]"
|
272
|
+
},
|
273
|
+
{
|
274
|
+
"title": "Wicked.2024.Hybrid.2160p.WEB-DL.DV.HDR.DDP5.1.H265-AOC",
|
275
|
+
"category": "Movies : 4K UHD",
|
276
|
+
"language": "English",
|
277
|
+
"size": "28.89 GB",
|
278
|
+
"seeds": 3,
|
279
|
+
"peers": 10753,
|
280
|
+
"date": "31/12/24 15:58",
|
281
|
+
"uploader": "atomicfusion:_trusted_uploader:",
|
282
|
+
"S/L": "[561/825]"
|
283
|
+
},
|
284
|
+
{
|
285
|
+
"title": "Wicked.2024.2160p.WEB-DL.DDP5.1.SDR.H265-AOC",
|
286
|
+
"category": "Movies : 4K UHD",
|
287
|
+
"language": "English",
|
288
|
+
"size": "17.91 GB",
|
289
|
+
"seeds": 2,
|
290
|
+
"peers": 5464,
|
291
|
+
"date": "31/12/24 15:58",
|
292
|
+
"uploader": "atomicfusion:_trusted_uploader:",
|
293
|
+
"S/L": "[210/194]"
|
294
|
+
},
|
295
|
+
{
|
296
|
+
"title": "Wicked.2024.1080p.WEB-DL.x264.6CH.Dual.YG⭐",
|
297
|
+
"category": "Movies : HD",
|
298
|
+
"language": "Spanish",
|
299
|
+
"size": "3.55 GB",
|
300
|
+
"seeds": 0,
|
301
|
+
"peers": 5581,
|
302
|
+
"date": "31/12/24 13:12",
|
303
|
+
"uploader": "yerisan710:_trusted_uploader::_sitefriend:",
|
304
|
+
"S/L": "[185/236]"
|
305
|
+
},
|
306
|
+
{
|
307
|
+
"title": "Wicked.2024.1080p.WEB-DL.H.264.Dual.YG⭐",
|
308
|
+
"category": "Movies : HD",
|
309
|
+
"language": "Spanish",
|
310
|
+
"size": "5.13 GB",
|
311
|
+
"seeds": 0,
|
312
|
+
"peers": 3355,
|
313
|
+
"date": "31/12/24 13:12",
|
314
|
+
"uploader": "yerisan710:_trusted_uploader::_sitefriend:",
|
315
|
+
"S/L": "[54/212]"
|
316
|
+
},
|
317
|
+
{
|
318
|
+
"title": "Wicked.2024.2160p.WEB-DL.DDP5.1.Atmos.DV.HDR.H.265-FLUX",
|
319
|
+
"category": "Movies : 4K UHD",
|
320
|
+
"language": "English",
|
321
|
+
"size": "28.54 GB",
|
322
|
+
"seeds": 9,
|
323
|
+
"peers": 23364,
|
324
|
+
"date": "31/12/24 08:33",
|
325
|
+
"uploader": "JackONeill:_verified_uploader:",
|
326
|
+
"S/L": "[371/304]"
|
327
|
+
},
|
328
|
+
{
|
329
|
+
"title": "Wicked.2024.1080p.AMZN.WEB-DL.DUAL.DDP5.1.H.264-KyoGo.mkv",
|
330
|
+
"category": "Movies : HD",
|
331
|
+
"language": "English",
|
332
|
+
"size": "12.10 GB",
|
333
|
+
"seeds": 28,
|
334
|
+
"peers": 193474,
|
335
|
+
"date": "31/12/24 06:11",
|
336
|
+
"uploader": "platypusp:_trusted_uploader:",
|
337
|
+
"S/L": "[236/50]"
|
338
|
+
},
|
339
|
+
{
|
340
|
+
"title": "Wicked.2024.1080p.WEBRip.10Bit.DDP5.1.x265-Asiimov",
|
341
|
+
"category": "Movies : HD",
|
342
|
+
"language": "English",
|
343
|
+
"size": "2.52 GB",
|
344
|
+
"seeds": 12,
|
345
|
+
"peers": 45545,
|
346
|
+
"date": "31/12/24 04:19",
|
347
|
+
"uploader": "Nick007:_trusted_uploader:",
|
348
|
+
"S/L": "[5,016/1,943]"
|
349
|
+
},
|
350
|
+
{
|
351
|
+
"title": "Wicked: Part 1 (2024) 1080p CAMRip V2 Hindi HQ Dubbed x264 - 1XBET",
|
352
|
+
"category": "Movies : CAM/TS",
|
353
|
+
"language": "Hindi",
|
354
|
+
"size": "3.99 GB",
|
355
|
+
"seeds": 0,
|
356
|
+
"peers": 3312,
|
357
|
+
"date": "27/11/24 11:13",
|
358
|
+
"uploader": "1XCinema:_trusted_uploader:",
|
359
|
+
"S/L": "[13/93]"
|
360
|
+
},
|
361
|
+
{
|
362
|
+
"title": "Wicked.2024.1080p.TELESYNC.x264.AC3-AOC",
|
363
|
+
"category": "Movies : CAM/TS",
|
364
|
+
"language": "English",
|
365
|
+
"size": "3.67 GB",
|
366
|
+
"seeds": 3,
|
367
|
+
"peers": 10596,
|
368
|
+
"date": "25/11/24 10:01",
|
369
|
+
"uploader": "atomicfusion:_trusted_uploader:",
|
370
|
+
"S/L": "[144/82]"
|
371
|
+
},
|
372
|
+
{
|
373
|
+
"title": "Wicked.2024.1080p.TELESYNC.LTE.Version.x264.COLLECTiVE",
|
374
|
+
"category": "Movies : CAM/TS",
|
375
|
+
"language": "English",
|
376
|
+
"size": "4.10 GB",
|
377
|
+
"seeds": 12,
|
378
|
+
"peers": 18064,
|
379
|
+
"date": "24/11/24 20:30",
|
380
|
+
"uploader": "will1869:_trusted_uploader::_sitefriend:",
|
381
|
+
"S/L": "[600/349]"
|
382
|
+
},
|
383
|
+
{
|
384
|
+
"title": "Wicked.2024.1080p.TELESYNC.x264.COLLECTiVE",
|
385
|
+
"category": "Movies : CAM/TS",
|
386
|
+
"language": "English",
|
387
|
+
"size": "18.79 GB",
|
388
|
+
"seeds": 3,
|
389
|
+
"peers": 6257,
|
390
|
+
"date": "24/11/24 20:26",
|
391
|
+
"uploader": "will1869:_trusted_uploader::_sitefriend:",
|
392
|
+
"S/L": "[44/33]"
|
393
|
+
},
|
394
|
+
{
|
395
|
+
"title": "Wicked (2024) 1080p CAMRip English x264 - 1XBET",
|
396
|
+
"category": "Movies : CAM/TS",
|
397
|
+
"language": "English",
|
398
|
+
"size": "3.99 GB",
|
399
|
+
"seeds": 1,
|
400
|
+
"peers": 3729,
|
401
|
+
"date": "23/11/24 08:50",
|
402
|
+
"uploader": "1XCinema:_trusted_uploader:",
|
403
|
+
"S/L": "[17/28]"
|
404
|
+
},
|
405
|
+
{
|
406
|
+
"title": "Wicked.Part.I.2024.HDCAM.c1nem4.x264-SUNSCREEN[TGx]",
|
407
|
+
"category": "Movies : CAM/TS",
|
408
|
+
"language": "English",
|
409
|
+
"size": "996.37 MB",
|
410
|
+
"seeds": 28,
|
411
|
+
"peers": 75067,
|
412
|
+
"date": "23/11/24 05:26",
|
413
|
+
"uploader": "TGxMovies:_trusted_uploader:",
|
414
|
+
"S/L": "[248/313]"
|
415
|
+
},
|
416
|
+
{
|
417
|
+
"title": "Wicked.Part.I.2024.720p.HDCAM-C1NEM4",
|
418
|
+
"category": "Movies : CAM/TS",
|
419
|
+
"language": "English",
|
420
|
+
"size": "2.21 GB",
|
421
|
+
"seeds": 1,
|
422
|
+
"peers": 3421,
|
423
|
+
"date": "23/11/24 04:34",
|
424
|
+
"uploader": "TGxMovies:_trusted_uploader:",
|
425
|
+
"S/L": "[50/51]"
|
426
|
+
}
|
427
|
+
]
|
428
|
+
```
|
429
|
+
|
430
|
+
This JSON representation includes all the specified fields along with the additional fields like `uploader` and `S/L`.
|
431
|
+
"""
|
432
|
+
|
433
|
+
|
434
|
+
print(extract_json_from_string(raw))
|
plexflow/utils/torrent/files.py
CHANGED
@@ -4,28 +4,72 @@ from pathlib import Path
|
|
4
4
|
from typing import Optional
|
5
5
|
|
6
6
|
class TorrentFile(BaseModel):
|
7
|
+
"""
|
8
|
+
A model representing a torrent file.
|
9
|
+
|
10
|
+
Attributes:
|
11
|
+
name (Optional[str]): The name of the torrent file.
|
12
|
+
size (Optional[str]): The size of the torrent file as a string.
|
13
|
+
"""
|
7
14
|
name: Optional[str]
|
8
15
|
size: Optional[str]
|
9
16
|
|
10
17
|
@property
|
11
|
-
def size_bytes(self):
|
18
|
+
def size_bytes(self) -> Optional[int]:
|
19
|
+
"""
|
20
|
+
Get the size of the torrent file in bytes.
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
Optional[int]: The size in bytes, or None if the size is not available.
|
24
|
+
"""
|
12
25
|
return next(iter(parse_size(self.size)), None) if self.size else None
|
13
26
|
|
14
27
|
@property
|
15
|
-
def size_human(self):
|
28
|
+
def size_human(self) -> Optional[str]:
|
29
|
+
"""
|
30
|
+
Get the human-readable size of the torrent file.
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
Optional[str]: The human-readable size, or None if the size is not available.
|
34
|
+
"""
|
16
35
|
return self.size
|
17
|
-
|
36
|
+
|
18
37
|
@property
|
19
|
-
def extension(self):
|
38
|
+
def extension(self) -> Optional[str]:
|
39
|
+
"""
|
40
|
+
Get the file extension of the torrent file.
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
Optional[str]: The file extension, or None if the name is not available.
|
44
|
+
"""
|
20
45
|
return Path(self.name).suffix.lstrip('.') if self.name else None
|
21
46
|
|
22
47
|
def __str__(self) -> str:
|
48
|
+
"""
|
49
|
+
Get a string representation of the torrent file.
|
50
|
+
|
51
|
+
Returns:
|
52
|
+
str: A string representation of the torrent file.
|
53
|
+
"""
|
23
54
|
return f"{self.name} [({self.size_human})][{self.extension}][{self.size_bytes} bytes]"
|
24
|
-
|
55
|
+
|
25
56
|
def __repr__(self) -> str:
|
57
|
+
"""
|
58
|
+
Get a string representation of the torrent file for debugging.
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
str: A string representation of the torrent file.
|
62
|
+
"""
|
26
63
|
return self.__str__()
|
27
64
|
|
28
65
|
class TorrentSubtitle(BaseModel):
|
66
|
+
"""
|
67
|
+
A model representing a torrent subtitle.
|
68
|
+
|
69
|
+
Attributes:
|
70
|
+
language (Optional[str]): The language of the subtitle.
|
71
|
+
name (Optional[str]): The name of the subtitle file.
|
72
|
+
"""
|
29
73
|
language: Optional[str]
|
30
74
|
name: Optional[str]
|
31
75
|
|
plexflow/utils/torrent/hash.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import re
|
2
|
+
from bs4 import BeautifulSoup
|
2
3
|
|
3
4
|
def extract_hash(s: str):
|
4
5
|
"""
|
@@ -87,4 +88,9 @@ def extract_magnet(text: str):
|
|
87
88
|
# Find all matches of the pattern in the input string
|
88
89
|
for match in re.finditer(pattern, text, re.IGNORECASE):
|
89
90
|
# Yield each match
|
90
|
-
yield match.group(0)
|
91
|
+
yield match.group(0)
|
92
|
+
|
93
|
+
|
94
|
+
def extract_magnet_from_html(html: str):
|
95
|
+
soup = BeautifulSoup(html, 'html.parser')
|
96
|
+
return soup.find_all('a', href=re.compile(r'magnet:\?xt=urn:btih:[A-Fa-f0-9]+'))
|
@@ -1,40 +1,106 @@
|
|
1
|
-
import
|
1
|
+
import os
|
2
|
+
from groq import Groq
|
3
|
+
from pathlib import Path
|
4
|
+
from groq import Groq
|
2
5
|
|
3
|
-
def transcribe_audio(file_path, model: str = 'medium'):
|
6
|
+
# def transcribe_audio(file_path, model: str = 'medium'):
|
7
|
+
# """
|
8
|
+
# Transcribes an audio file using the Whisper model.
|
9
|
+
|
10
|
+
# Args:
|
11
|
+
# file_path (str): The path to the audio file to transcribe.
|
12
|
+
|
13
|
+
# Returns:
|
14
|
+
# str: The transcription of the audio file.
|
15
|
+
|
16
|
+
# Raises:
|
17
|
+
# FileNotFoundError: If the audio file does not exist.
|
18
|
+
# Exception: If there is an error loading the model or transcribing the audio.
|
19
|
+
|
20
|
+
# Example:
|
21
|
+
# >>> transcribe_audio('path/to/your/audio/file.mp3')
|
22
|
+
# 'This is the transcribed text from your audio file.'
|
23
|
+
|
24
|
+
# Note:
|
25
|
+
# This function assumes that you have the Whisper model available locally.
|
26
|
+
# """
|
27
|
+
# try:
|
28
|
+
# # Check if the file exists
|
29
|
+
# with open(file_path, 'rb') as f:
|
30
|
+
# pass
|
31
|
+
# except FileNotFoundError as e:
|
32
|
+
# raise e
|
33
|
+
|
34
|
+
# try:
|
35
|
+
# # Load the Whisper model
|
36
|
+
# model = whisper.load_model(model)
|
37
|
+
|
38
|
+
# # Transcribe the audio
|
39
|
+
# result = model.transcribe(file_path)
|
40
|
+
|
41
|
+
# return result["text"]
|
42
|
+
# except Exception as e:
|
43
|
+
# raise e
|
44
|
+
|
45
|
+
def transcribe_audio_groq(file_path: Path, model: str = 'distil-whisper-large-v3-en', prompt: str = None, **kwargs):
|
4
46
|
"""
|
5
|
-
Transcribes an audio file using the
|
47
|
+
Transcribes an audio file using the Groq model.
|
6
48
|
|
7
49
|
Args:
|
8
|
-
file_path (
|
50
|
+
file_path (Path): The path to the audio file to transcribe.
|
51
|
+
model (str): The model to use for transcription.
|
9
52
|
|
10
53
|
Returns:
|
11
54
|
str: The transcription of the audio file.
|
12
55
|
|
13
56
|
Raises:
|
14
57
|
FileNotFoundError: If the audio file does not exist.
|
15
|
-
Exception: If there is an error
|
58
|
+
Exception: If there is an error with the Groq client or transcribing the audio.
|
16
59
|
|
17
60
|
Example:
|
18
|
-
>>>
|
61
|
+
>>> transcribe_audio_groq(Path('path/to/your/audio/file.m4a'))
|
19
62
|
'This is the transcribed text from your audio file.'
|
20
63
|
|
21
64
|
Note:
|
22
|
-
This function assumes that you have the
|
65
|
+
This function assumes that you have the Groq client properly configured.
|
23
66
|
"""
|
24
67
|
try:
|
25
68
|
# Check if the file exists
|
26
|
-
|
27
|
-
|
28
|
-
except FileNotFoundError as e:
|
29
|
-
raise e
|
69
|
+
if not file_path.exists():
|
70
|
+
raise FileNotFoundError(f"No such file: '{file_path}'")
|
30
71
|
|
31
|
-
|
32
|
-
# Load the Whisper model
|
33
|
-
model = whisper.load_model(model)
|
72
|
+
print("GROQ_API_KEY:", os.environ.get("GROQ_API_KEY"))
|
34
73
|
|
35
|
-
#
|
36
|
-
|
74
|
+
# Initialize the Groq client
|
75
|
+
client = Groq()
|
37
76
|
|
38
|
-
|
77
|
+
# Open the audio file
|
78
|
+
with file_path.open("rb") as file:
|
79
|
+
# Create a transcription of the audio file
|
80
|
+
transcription = client.audio.transcriptions.create(
|
81
|
+
file=(str(file_path), file.read()), # Required audio file
|
82
|
+
model=model, # Required model to use for transcription
|
83
|
+
prompt=prompt, # Optional
|
84
|
+
response_format=kwargs.get("response_format", "json"), # Optional
|
85
|
+
language=kwargs.get("language", "en"), # Optional
|
86
|
+
temperature=0.0 # Optional
|
87
|
+
)
|
88
|
+
return transcription
|
39
89
|
except Exception as e:
|
40
90
|
raise e
|
91
|
+
|
92
|
+
|
93
|
+
def groq_inference(audio, **kwargs) -> dict:
|
94
|
+
client = Groq()
|
95
|
+
|
96
|
+
with open(audio, "rb") as file:
|
97
|
+
transcription = client.audio.transcriptions.create(
|
98
|
+
file=(audio, file.read()),
|
99
|
+
model="whisper-large-v3",
|
100
|
+
# prompt="Kingdom of the Planet of the Apes: Many years after the reign of Caesar, a young ape goes on a journey that will lead him to question everything he's been taught $
|
101
|
+
response_format="verbose_json", # Optional
|
102
|
+
language="en", # Optional
|
103
|
+
temperature=1.0, # Optional
|
104
|
+
timestamp_granularities=["word"], # Optional
|
105
|
+
)
|
106
|
+
return transcription
|