@weroperking/invenio-scraper 1.0.0
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.
- package/LICENSE +15 -0
- package/README.md +407 -0
- package/dist/__fixtures__/download-avatar.json +126 -0
- package/dist/__fixtures__/download-merlin-s1e1.json +90 -0
- package/dist/__fixtures__/search-titanic.json +245 -0
- package/dist/__fixtures__/stream-merlin-s1e1.json +32 -0
- package/dist/__fixtures__/stream-titanic.json +41 -0
- package/dist/constants.d.ts +14 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +22 -0
- package/dist/constants.js.map +1 -0
- package/dist/details.d.ts +20 -0
- package/dist/details.d.ts.map +1 -0
- package/dist/details.js +273 -0
- package/dist/details.js.map +1 -0
- package/dist/details.test.d.ts +2 -0
- package/dist/details.test.d.ts.map +1 -0
- package/dist/details.test.js +65 -0
- package/dist/details.test.js.map +1 -0
- package/dist/download.d.ts +35 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/download.js +258 -0
- package/dist/download.js.map +1 -0
- package/dist/download.test.d.ts +2 -0
- package/dist/download.test.d.ts.map +1 -0
- package/dist/download.test.js +202 -0
- package/dist/download.test.js.map +1 -0
- package/dist/errors.d.ts +31 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +53 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +10 -0
- package/dist/index.test.js.map +1 -0
- package/dist/logger.d.ts +10 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +15 -0
- package/dist/logger.js.map +1 -0
- package/dist/search.d.ts +4 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +102 -0
- package/dist/search.js.map +1 -0
- package/dist/search.test.d.ts +2 -0
- package/dist/search.test.d.ts.map +1 -0
- package/dist/search.test.js +67 -0
- package/dist/search.test.js.map +1 -0
- package/dist/series.d.ts +15 -0
- package/dist/series.d.ts.map +1 -0
- package/dist/series.js +111 -0
- package/dist/series.js.map +1 -0
- package/dist/series.test.d.ts +2 -0
- package/dist/series.test.d.ts.map +1 -0
- package/dist/series.test.js +78 -0
- package/dist/series.test.js.map +1 -0
- package/dist/session.d.ts +64 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +417 -0
- package/dist/session.js.map +1 -0
- package/dist/session.test.d.ts +2 -0
- package/dist/session.test.d.ts.map +1 -0
- package/dist/session.test.js +111 -0
- package/dist/session.test.js.map +1 -0
- package/dist/stream.d.ts +17 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +118 -0
- package/dist/stream.js.map +1 -0
- package/dist/stream.test.d.ts +2 -0
- package/dist/stream.test.d.ts.map +1 -0
- package/dist/stream.test.js +77 -0
- package/dist/stream.test.js.map +1 -0
- package/dist/types.d.ts +293 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
{
|
|
2
|
+
"code": 0,
|
|
3
|
+
"message": "ok",
|
|
4
|
+
"data": {
|
|
5
|
+
"pager": {
|
|
6
|
+
"hasMore": true,
|
|
7
|
+
"nextPage": "2",
|
|
8
|
+
"page": "1",
|
|
9
|
+
"perPage": 5,
|
|
10
|
+
"totalCount": 146
|
|
11
|
+
},
|
|
12
|
+
"items": [
|
|
13
|
+
{
|
|
14
|
+
"subjectId": "5390197429792821032",
|
|
15
|
+
"subjectType": 1,
|
|
16
|
+
"title": "Titanic",
|
|
17
|
+
"description": "",
|
|
18
|
+
"releaseDate": "1997-12-19",
|
|
19
|
+
"duration": 11640,
|
|
20
|
+
"genre": "Drama,Romance",
|
|
21
|
+
"cover": {
|
|
22
|
+
"url": "https://pbcdnw.aoneroom.com/image/2025/11/01/0e68a08216fe532db1eef333150967fc.jpg",
|
|
23
|
+
"width": 2015,
|
|
24
|
+
"height": 3000,
|
|
25
|
+
"size": 658291,
|
|
26
|
+
"format": "jpg",
|
|
27
|
+
"thumbnail": "",
|
|
28
|
+
"blurHash": "eWGbP8WA%g%Mbc^jt7oet7Rk4mt7IURjWVIVWBoga|t7kXWVt7t7ae",
|
|
29
|
+
"gif": null,
|
|
30
|
+
"avgHueLight": "#7b6d66",
|
|
31
|
+
"avgHueDark": "#665d58",
|
|
32
|
+
"id": "0"
|
|
33
|
+
},
|
|
34
|
+
"countryName": "United States",
|
|
35
|
+
"imdbRatingValue": "7.9",
|
|
36
|
+
"subtitles": "English,Español,Filipino,Français,Indonesian,Kiswahili,Malay,Português,Türkçe,tiếng Việt,Русский,اَلْعَرَبِيَّةُ,اُردُو,فارسی,هَرْشٜن هَوْس,বাংলা,ਪੰਜਾਬੀ,ภาษาไทย,中文",
|
|
37
|
+
"ops": "{\"rid\":\"78da1270-16a0-4bff-9919-716405fd6237\",\"trace_id\":\"0a21c8a117630285974220a9cf22ce59\",\"search_abt\":\"668,681,708\"}",
|
|
38
|
+
"hasResource": true,
|
|
39
|
+
"trailer": null,
|
|
40
|
+
"detailPath": "titanic-m7a9yt0abq6",
|
|
41
|
+
"staffList": [],
|
|
42
|
+
"appointmentCnt": 0,
|
|
43
|
+
"appointmentDate": "",
|
|
44
|
+
"corner": "",
|
|
45
|
+
"imdbRatingCount": 1361765,
|
|
46
|
+
"stills": {
|
|
47
|
+
"url": "https://pbcdnw.aoneroom.com/image/2023/03/22/d8085f7ab010fcb349cdb44bfbab0ee6.jpg",
|
|
48
|
+
"width": 1920,
|
|
49
|
+
"height": 1080,
|
|
50
|
+
"size": 101214,
|
|
51
|
+
"format": "jpg",
|
|
52
|
+
"thumbnail": "",
|
|
53
|
+
"blurHash": "e88;0#$MNGn~ob%1RkofofR*0MNbxakCR-bcofRjRjxZIpW.R*aeof",
|
|
54
|
+
"gif": null,
|
|
55
|
+
"avgHueLight": "#43382b",
|
|
56
|
+
"avgHueDark": "#43382b",
|
|
57
|
+
"id": "0"
|
|
58
|
+
},
|
|
59
|
+
"postTitle": "Great"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"subjectId": "206379412718240440",
|
|
63
|
+
"subjectType": 1,
|
|
64
|
+
"title": "Titanic",
|
|
65
|
+
"description": "",
|
|
66
|
+
"releaseDate": "1950-02-07",
|
|
67
|
+
"duration": 5100,
|
|
68
|
+
"genre": "Action,Drama,History",
|
|
69
|
+
"cover": {
|
|
70
|
+
"url": "https://pbcdnw.aoneroom.com/image/2025/10/31/cf578939e4f6a057826ab6742d6d4df5.jpg",
|
|
71
|
+
"width": 434,
|
|
72
|
+
"height": 551,
|
|
73
|
+
"size": 51008,
|
|
74
|
+
"format": "jpg",
|
|
75
|
+
"thumbnail": "",
|
|
76
|
+
"blurHash": "eQK,a0xuPoxutm}=$jwJX7XSK$WY#8rqR%%39aTKwInObbj=S2NGeT",
|
|
77
|
+
"gif": null,
|
|
78
|
+
"avgHueLight": "#997861",
|
|
79
|
+
"avgHueDark": "#665245",
|
|
80
|
+
"id": "0"
|
|
81
|
+
},
|
|
82
|
+
"countryName": "Germany",
|
|
83
|
+
"imdbRatingValue": "6.1",
|
|
84
|
+
"subtitles": "English,Filipino,Français,Indonesian,Português,Русский,اَلْعَرَبِيَّةُ,اُردُو,বাংলা,ਪੰਜਾਬੀ",
|
|
85
|
+
"ops": "{\"rid\":\"78da1270-16a0-4bff-9919-716405fd6237\",\"trace_id\":\"0a21c8a117630285974220a9cf22ce59\",\"search_abt\":\"668,681,708\"}",
|
|
86
|
+
"hasResource": true,
|
|
87
|
+
"trailer": null,
|
|
88
|
+
"detailPath": "titanic-kGoZgiDdff",
|
|
89
|
+
"staffList": [],
|
|
90
|
+
"appointmentCnt": 0,
|
|
91
|
+
"appointmentDate": "",
|
|
92
|
+
"corner": "",
|
|
93
|
+
"imdbRatingCount": 1996,
|
|
94
|
+
"stills": null,
|
|
95
|
+
"postTitle": "Trailer-Titanic"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"subjectId": "7070560136179630776",
|
|
99
|
+
"subjectType": 1,
|
|
100
|
+
"title": "Titanic",
|
|
101
|
+
"description": "",
|
|
102
|
+
"releaseDate": "1953-07-13",
|
|
103
|
+
"duration": 5880,
|
|
104
|
+
"genre": "Drama,History,Romance",
|
|
105
|
+
"cover": {
|
|
106
|
+
"url": "https://pbcdnw.aoneroom.com/image/2025/10/31/f7490f93da896cf3c1548f25d401d518.jpg",
|
|
107
|
+
"width": 335,
|
|
108
|
+
"height": 500,
|
|
109
|
+
"size": 54390,
|
|
110
|
+
"format": "jpg",
|
|
111
|
+
"thumbnail": "",
|
|
112
|
+
"blurHash": "eNJQ_@$%krX9%M8ws,ShRjbITfofs-ozt6awRkxaoft6RjWXNdWAWB",
|
|
113
|
+
"gif": null,
|
|
114
|
+
"avgHueLight": "#998576",
|
|
115
|
+
"avgHueDark": "#665b53",
|
|
116
|
+
"id": "0"
|
|
117
|
+
},
|
|
118
|
+
"countryName": "United States",
|
|
119
|
+
"imdbRatingValue": "7.0",
|
|
120
|
+
"subtitles": "English,Filipino,Français,Indonesian,Português,Русский,اَلْعَرَبِيَّةُ,اُردُو,বাংলা,ਪੰਜਾਬੀ,中文",
|
|
121
|
+
"ops": "{\"rid\":\"78da1270-16a0-4bff-9919-716405fd6237\",\"trace_id\":\"0a21c8a117630285974220a9cf22ce59\",\"search_abt\":\"668,681,708\"}",
|
|
122
|
+
"hasResource": true,
|
|
123
|
+
"trailer": null,
|
|
124
|
+
"detailPath": "titanic-QOuOQeUejq8",
|
|
125
|
+
"staffList": [],
|
|
126
|
+
"appointmentCnt": 0,
|
|
127
|
+
"appointmentDate": "",
|
|
128
|
+
"corner": "",
|
|
129
|
+
"imdbRatingCount": 8085,
|
|
130
|
+
"stills": null,
|
|
131
|
+
"postTitle": "Titanic (1953)"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"subjectId": "6832221541099783208",
|
|
135
|
+
"subjectType": 1,
|
|
136
|
+
"title": "Titanic II",
|
|
137
|
+
"description": "",
|
|
138
|
+
"releaseDate": "2010-08-24",
|
|
139
|
+
"duration": 5400,
|
|
140
|
+
"genre": "Action,Adventure,Drama",
|
|
141
|
+
"cover": {
|
|
142
|
+
"url": "https://pbcdnw.aoneroom.com/image/2025/11/02/2ee5f12364ade6aefbbe2a5c653a6476.jpg",
|
|
143
|
+
"width": 462,
|
|
144
|
+
"height": 650,
|
|
145
|
+
"size": 77675,
|
|
146
|
+
"format": "jpg",
|
|
147
|
+
"thumbnail": "",
|
|
148
|
+
"blurHash": "eCF?Osxb00x]Di8_M_NFozjZtSWAIARiW:IAt7-;V@R*jYtRbIkCxu",
|
|
149
|
+
"gif": null,
|
|
150
|
+
"avgHueLight": "#748486",
|
|
151
|
+
"avgHueDark": "#5c6566",
|
|
152
|
+
"id": "0"
|
|
153
|
+
},
|
|
154
|
+
"countryName": "United States",
|
|
155
|
+
"imdbRatingValue": "1.7",
|
|
156
|
+
"subtitles": "English,Filipino,Français,Indonesian,Português,Русский,اَلْعَرَبِيَّةُ,اُردُو,বাংলা,ਪੰਜਾਬੀ,中文",
|
|
157
|
+
"ops": "{\"rid\":\"78da1270-16a0-4bff-9919-716405fd6237\",\"trace_id\":\"0a21c8a117630285974220a9cf22ce59\",\"search_abt\":\"668,681,708\"}",
|
|
158
|
+
"hasResource": true,
|
|
159
|
+
"trailer": null,
|
|
160
|
+
"detailPath": "titanic-ii-EscvgC7EH88",
|
|
161
|
+
"staffList": [],
|
|
162
|
+
"appointmentCnt": 0,
|
|
163
|
+
"appointmentDate": "",
|
|
164
|
+
"corner": "",
|
|
165
|
+
"imdbRatingCount": 13635,
|
|
166
|
+
"stills": {
|
|
167
|
+
"url": "https://pbcdnw.aoneroom.com/image/2023/05/23/fb7ae2fa3ff777d33773f29c89319e3d.jpg",
|
|
168
|
+
"width": 1024,
|
|
169
|
+
"height": 682,
|
|
170
|
+
"size": 43900,
|
|
171
|
+
"format": "jpg",
|
|
172
|
+
"thumbnail": "",
|
|
173
|
+
"blurHash": "eA7nXb9F9w~AE5-VM{SO$%NIEMxExuIUxuIpxCxuInt7NIs.s,NHt7",
|
|
174
|
+
"gif": null,
|
|
175
|
+
"avgHueLight": "#29372e",
|
|
176
|
+
"avgHueDark": "#2c3730",
|
|
177
|
+
"id": "0"
|
|
178
|
+
},
|
|
179
|
+
"postTitle": "What a ridiculous excuse for a film"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"subjectId": "6130486831974072568",
|
|
183
|
+
"subjectType": 1,
|
|
184
|
+
"title": "Titanic 666",
|
|
185
|
+
"description": "",
|
|
186
|
+
"releaseDate": "2022-04-15",
|
|
187
|
+
"duration": 5460,
|
|
188
|
+
"genre": "Horror,Thriller",
|
|
189
|
+
"cover": {
|
|
190
|
+
"url": "https://pbcdnw.aoneroom.com/image/2025/11/02/77cce90c859f6c4bf2855605c73fe5d5.jpg",
|
|
191
|
+
"width": 1920,
|
|
192
|
+
"height": 2560,
|
|
193
|
+
"size": 819349,
|
|
194
|
+
"format": "jpg",
|
|
195
|
+
"thumbnail": "",
|
|
196
|
+
"blurHash": "eCAm-ytS00jZM{~Ca}EMozM{-pV?R+ozNG%gf6eoj]RPpJfkeSayWA",
|
|
197
|
+
"gif": null,
|
|
198
|
+
"avgHueLight": "#455058",
|
|
199
|
+
"avgHueDark": "#495258",
|
|
200
|
+
"id": "0"
|
|
201
|
+
},
|
|
202
|
+
"countryName": "United States",
|
|
203
|
+
"imdbRatingValue": "3.3",
|
|
204
|
+
"subtitles": "English,Filipino,Français,Indonesian,Kiswahili,Português,Русский,اَلْعَرَبِيَّةُ,اُردُو,هَرْشٜن هَوْس,বাংলা,ਪੰਜਾਬੀ,中文",
|
|
205
|
+
"ops": "{\"rid\":\"78da1270-16a0-4bff-9919-716405fd6237\",\"trace_id\":\"0a21c8a117630285974220a9cf22ce59\",\"search_abt\":\"668,681,708\"}",
|
|
206
|
+
"hasResource": true,
|
|
207
|
+
"trailer": null,
|
|
208
|
+
"detailPath": "titanic-666-ytQYEx4HRi7",
|
|
209
|
+
"staffList": [],
|
|
210
|
+
"appointmentCnt": 0,
|
|
211
|
+
"appointmentDate": "",
|
|
212
|
+
"corner": "",
|
|
213
|
+
"imdbRatingCount": 4701,
|
|
214
|
+
"stills": {
|
|
215
|
+
"url": "https://pbcdnw.aoneroom.com/image/2022/11/22/70f7dd4de1b81e1a83d3bbba0801d5e4.jpg",
|
|
216
|
+
"width": 1092,
|
|
217
|
+
"height": 528,
|
|
218
|
+
"size": 120354,
|
|
219
|
+
"format": "jpg",
|
|
220
|
+
"thumbnail": "",
|
|
221
|
+
"blurHash": "eNE.@I$$afn%t6~WsTa}tQoe%Loet7RkRj?aM{t7t7WB-:V@WBt7s:",
|
|
222
|
+
"gif": null,
|
|
223
|
+
"avgHueLight": "#78746a",
|
|
224
|
+
"avgHueDark": "#66635a",
|
|
225
|
+
"id": "0"
|
|
226
|
+
},
|
|
227
|
+
"postTitle": "Not up to Asylum standards."
|
|
228
|
+
}
|
|
229
|
+
],
|
|
230
|
+
"counts": [
|
|
231
|
+
{
|
|
232
|
+
"subjectType": 0,
|
|
233
|
+
"name": "All",
|
|
234
|
+
"num": 0
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"subjectType": 1,
|
|
238
|
+
"name": "Movies",
|
|
239
|
+
"num": 0
|
|
240
|
+
}
|
|
241
|
+
],
|
|
242
|
+
"url": "",
|
|
243
|
+
"referer": ""
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"code": 0,
|
|
3
|
+
"message": "ok",
|
|
4
|
+
"data": {
|
|
5
|
+
"streams": [
|
|
6
|
+
{
|
|
7
|
+
"format": "MP4",
|
|
8
|
+
"id": "6137440414628036776",
|
|
9
|
+
"url": "https://bcdnw.hakunaymatata.com/bt/a4eeb6aa317742ea2ddea90a770450b7.mp4?sign=d34b9add50aa8f3feb086f03d412e16d&t=1763025873",
|
|
10
|
+
"resolutions": "360",
|
|
11
|
+
"size": "127075023",
|
|
12
|
+
"duration": 2652,
|
|
13
|
+
"codecName": "h264"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"format": "MP4",
|
|
17
|
+
"id": "7798793688104550480",
|
|
18
|
+
"url": "https://bcdnw.hakunaymatata.com/resource/a1498e259db8f8e1a0b8c0c0e054d898.mp4?sign=fae1a09585e7a09797049f6157503733&t=1763025566",
|
|
19
|
+
"resolutions": "480",
|
|
20
|
+
"size": "588771202",
|
|
21
|
+
"duration": 2652,
|
|
22
|
+
"codecName": "h264"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"freeNum": 6,
|
|
26
|
+
"limited": false,
|
|
27
|
+
"limitedCode": "",
|
|
28
|
+
"dash": [],
|
|
29
|
+
"hls": [],
|
|
30
|
+
"hasResource": true
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"code": 0,
|
|
3
|
+
"message": "ok",
|
|
4
|
+
"data": {
|
|
5
|
+
"streams": [
|
|
6
|
+
{
|
|
7
|
+
"format": "MP4",
|
|
8
|
+
"id": "4645687748723180736",
|
|
9
|
+
"url": "https://bcdnw.hakunaymatata.com/resource/8f5faef179e8906a2e50b3b6ffb2fb4c.mp4?sign=e711b619a98698faf961fcbfe32bee0e&t=1763026761",
|
|
10
|
+
"resolutions": "480",
|
|
11
|
+
"size": "874797261",
|
|
12
|
+
"duration": 11687,
|
|
13
|
+
"codecName": "h264"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"format": "MP4",
|
|
17
|
+
"id": "8689459235262005880",
|
|
18
|
+
"url": "https://bcdnw.hakunaymatata.com/resource/ed322112b874e19b0c6af6239c6fdf0b.mp4?sign=58677e8952fe354e24fccae2a704560c&t=1763027663",
|
|
19
|
+
"resolutions": "720",
|
|
20
|
+
"size": "2097433997",
|
|
21
|
+
"duration": 11687,
|
|
22
|
+
"codecName": "h264"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"format": "MP4",
|
|
26
|
+
"id": "834314734957724416",
|
|
27
|
+
"url": "https://bcdnw.hakunaymatata.com/resource/51f86f8256537ccbbdbacdf1a679961e.mp4?sign=9adc4bc891563ed6d79d2b9999f05f51&t=1763028461",
|
|
28
|
+
"resolutions": "1080",
|
|
29
|
+
"size": "4134165328",
|
|
30
|
+
"duration": 11687,
|
|
31
|
+
"codecName": "h264"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"freeNum": 6,
|
|
35
|
+
"limited": false,
|
|
36
|
+
"limitedCode": "",
|
|
37
|
+
"dash": [],
|
|
38
|
+
"hls": [],
|
|
39
|
+
"hasResource": true
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const DEFAULT_PROTOCOL = "https";
|
|
2
|
+
export declare const MIRROR_HOSTS: readonly ["h5.aoneroom.com", "movieboxapp.in", "moviebox.pk", "moviebox.ph", "moviebox.id", "v.moviebox.ph", "netnaija.video"];
|
|
3
|
+
export declare const ENV_HOST_KEY = "MOVIEBOX_API_HOST";
|
|
4
|
+
export declare const ENV_PROXY_KEY = "MOVIEBOX_API_PROXY";
|
|
5
|
+
export declare const ITEM_DETAILS_PATH = "/detail";
|
|
6
|
+
export declare const APP_INFO_PATH = "/wefeed-h5-bff/app/get-latest-app-pkgs";
|
|
7
|
+
export declare const DEFAULT_REQUEST_HEADERS: {
|
|
8
|
+
readonly Accept: "application/json";
|
|
9
|
+
readonly 'Accept-Language': "en-US,en;q=0.5";
|
|
10
|
+
readonly 'X-Client-Info': "{\"timezone\":\"Africa/Nairobi\"}";
|
|
11
|
+
readonly 'User-Agent': "moviebox-js-sdk/preview";
|
|
12
|
+
readonly 'Content-Type': "application/json";
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,eAAO,MAAM,YAAY,gIAQf,CAAC;AAEX,eAAO,MAAM,YAAY,sBAAsB,CAAC;AAChD,eAAO,MAAM,aAAa,uBAAuB,CAAC;AAElD,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAE3C,eAAO,MAAM,aAAa,2CAA2C,CAAC;AAEtE,eAAO,MAAM,uBAAuB;;;;;;CAM1B,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const DEFAULT_PROTOCOL = 'https';
|
|
2
|
+
export const MIRROR_HOSTS = [
|
|
3
|
+
'h5.aoneroom.com',
|
|
4
|
+
'movieboxapp.in',
|
|
5
|
+
'moviebox.pk',
|
|
6
|
+
'moviebox.ph',
|
|
7
|
+
'moviebox.id',
|
|
8
|
+
'v.moviebox.ph',
|
|
9
|
+
'netnaija.video'
|
|
10
|
+
];
|
|
11
|
+
export const ENV_HOST_KEY = 'MOVIEBOX_API_HOST';
|
|
12
|
+
export const ENV_PROXY_KEY = 'MOVIEBOX_API_PROXY';
|
|
13
|
+
export const ITEM_DETAILS_PATH = '/detail';
|
|
14
|
+
export const APP_INFO_PATH = '/wefeed-h5-bff/app/get-latest-app-pkgs';
|
|
15
|
+
export const DEFAULT_REQUEST_HEADERS = {
|
|
16
|
+
Accept: 'application/json',
|
|
17
|
+
'Accept-Language': 'en-US,en;q=0.5',
|
|
18
|
+
'X-Client-Info': '{"timezone":"Africa/Nairobi"}',
|
|
19
|
+
'User-Agent': 'moviebox-js-sdk/preview',
|
|
20
|
+
'Content-Type': 'application/json'
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,aAAa;IACb,aAAa;IACb,eAAe;IACf,gBAAgB;CACR,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG,mBAAmB,CAAC;AAChD,MAAM,CAAC,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAElD,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAE3C,MAAM,CAAC,MAAM,aAAa,GAAG,wCAAwC,CAAC;AAEtE,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,kBAAkB;IAC1B,iBAAiB,EAAE,gBAAgB;IACnC,eAAe,EAAE,+BAA+B;IAChD,YAAY,EAAE,yBAAyB;IACvC,cAAc,EAAE,kBAAkB;CAC1B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MovieboxSession } from './session.js';
|
|
2
|
+
import type { MovieDetails, MovieDownloadOption, MovieSubtitleOption, RawDownloadableFilesResponse, RawDownloadableMedia, RawMovieSubject, RawNuxtDetailState, RawSeriesSubject } from './types.js';
|
|
3
|
+
interface GetMovieDetailsParams {
|
|
4
|
+
detailPath: string;
|
|
5
|
+
subjectId?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function getMovieDetails(session: MovieboxSession, params: GetMovieDetailsParams): Promise<MovieDetails>;
|
|
8
|
+
export declare function normalizeDownloadOptions(downloads: RawDownloadableMedia[] | undefined): MovieDownloadOption[];
|
|
9
|
+
export declare function normalizeCaptions(captions: RawDownloadableFilesResponse['captions']): MovieSubtitleOption[];
|
|
10
|
+
export declare function selectBest(downloads: MovieDownloadOption[]): MovieDownloadOption | null;
|
|
11
|
+
export declare function selectWorst(downloads: MovieDownloadOption[]): MovieDownloadOption | null;
|
|
12
|
+
export declare function resolveRating(subject: RawMovieSubject | RawSeriesSubject): number | null;
|
|
13
|
+
export declare function splitDelimited(value: string | string[]): string[];
|
|
14
|
+
export declare function extractNuxtState(html: string): RawNuxtDetailState;
|
|
15
|
+
export declare function resolveNuxtPayload(payload: unknown): Record<string, unknown>;
|
|
16
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
17
|
+
export declare function toNumber(value: unknown): number;
|
|
18
|
+
export declare function normalizeDetailPath(detailPath: string): string;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=details.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"details.d.ts","sourceRoot":"","sources":["../src/details.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,4BAA4B,EAC5B,oBAAoB,EAGpB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,UAAU,qBAAqB;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,YAAY,CAAC,CAoCvB;AAkED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,SAAS,GAAG,mBAAmB,EAAE,CAc7G;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,4BAA4B,CAAC,UAAU,CAAC,GAAG,mBAAmB,EAAE,CAa3G;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,GAAG,IAAI,CAKvF;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,GAAG,IAAI,CAKxF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAYxF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,CAQjE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAwBjE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuF5E;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAW/C;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAY9D"}
|
package/dist/details.js
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { ITEM_DETAILS_PATH } from './constants.js';
|
|
2
|
+
import { MovieboxApiError } from './errors.js';
|
|
3
|
+
export async function getMovieDetails(session, params) {
|
|
4
|
+
const normalizedPath = normalizeDetailPath(params.detailPath);
|
|
5
|
+
const html = await session.fetchHtml(normalizedPath, {
|
|
6
|
+
headers: {
|
|
7
|
+
Accept: 'text/html,application/xhtml+xml'
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
const nuxtState = extractNuxtState(html);
|
|
11
|
+
const resData = nuxtState.resData;
|
|
12
|
+
if (!resData) {
|
|
13
|
+
throw new MovieboxApiError('Moviebox detail page did not include expected resData payload.');
|
|
14
|
+
}
|
|
15
|
+
const subject = resData.subject;
|
|
16
|
+
if (!subject?.subjectId) {
|
|
17
|
+
throw new MovieboxApiError('Movie detail state is missing subject information.');
|
|
18
|
+
}
|
|
19
|
+
const subjectId = params.subjectId ?? subject.subjectId;
|
|
20
|
+
const downloadData = await session.fetchJson('/wefeed-h5-bff/web/subject/download', {
|
|
21
|
+
searchParams: {
|
|
22
|
+
subjectId,
|
|
23
|
+
se: 0,
|
|
24
|
+
ep: 0
|
|
25
|
+
},
|
|
26
|
+
headers: {
|
|
27
|
+
Referer: session.buildUrl(`/movies/${subject.detailPath}`)
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return normalizeMovieDetails(resData, downloadData);
|
|
31
|
+
}
|
|
32
|
+
function normalizeMovieDetails(resData, downloads) {
|
|
33
|
+
const metadata = resData.metadata;
|
|
34
|
+
const subject = resData.subject;
|
|
35
|
+
const releaseDate = subject.releaseDate ?? null;
|
|
36
|
+
const releaseYear = releaseDate ? parseInt(releaseDate.slice(0, 4), 10) || null : null;
|
|
37
|
+
const durationSource = subject.duration;
|
|
38
|
+
const parsedDuration = typeof durationSource === 'number'
|
|
39
|
+
? durationSource
|
|
40
|
+
: durationSource
|
|
41
|
+
? parseInt(durationSource, 10)
|
|
42
|
+
: undefined;
|
|
43
|
+
const resolvedDurationSeconds = typeof subject.durationSeconds === 'number'
|
|
44
|
+
? subject.durationSeconds
|
|
45
|
+
: typeof parsedDuration === 'number' && Number.isFinite(parsedDuration)
|
|
46
|
+
? parsedDuration
|
|
47
|
+
: null;
|
|
48
|
+
const durationSeconds = resolvedDurationSeconds ?? null;
|
|
49
|
+
const durationLabel = durationSource != null ? String(durationSource) : durationSeconds !== null ? String(durationSeconds) : null;
|
|
50
|
+
const posterUrl = subject.cover?.url ?? null;
|
|
51
|
+
const backdropUrl = metadata?.image ?? null;
|
|
52
|
+
const rating = resolveRating(subject);
|
|
53
|
+
const ratingCount = subject.imdbRatingCount ?? null;
|
|
54
|
+
const genres = subject.genre ?? [];
|
|
55
|
+
const availableSubtitleLanguages = splitDelimited(subject.subtitles ?? '')
|
|
56
|
+
.map((entry) => entry.trim())
|
|
57
|
+
.filter(Boolean);
|
|
58
|
+
const downloadOptions = normalizeDownloadOptions(downloads.downloads);
|
|
59
|
+
const captions = normalizeCaptions(downloads.captions ?? []);
|
|
60
|
+
const bestDownload = selectBest(downloadOptions);
|
|
61
|
+
const worstDownload = selectWorst(downloadOptions);
|
|
62
|
+
return {
|
|
63
|
+
id: subject.subjectId,
|
|
64
|
+
detailPath: subject.detailPath,
|
|
65
|
+
title: subject.title,
|
|
66
|
+
synopsis: subject.description,
|
|
67
|
+
releaseDate,
|
|
68
|
+
releaseYear,
|
|
69
|
+
durationSeconds,
|
|
70
|
+
durationLabel,
|
|
71
|
+
genres,
|
|
72
|
+
posterUrl,
|
|
73
|
+
backdropUrl,
|
|
74
|
+
rating,
|
|
75
|
+
ratingCount,
|
|
76
|
+
country: subject.countryName ?? null,
|
|
77
|
+
hasResource: Boolean(subject.hasResource ?? downloads.hasResource),
|
|
78
|
+
availableSubtitleLanguages,
|
|
79
|
+
downloads: downloadOptions,
|
|
80
|
+
bestDownload,
|
|
81
|
+
worstDownload,
|
|
82
|
+
captions
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export function normalizeDownloadOptions(downloads) {
|
|
86
|
+
if (!downloads?.length) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
return downloads
|
|
90
|
+
.map((media) => ({
|
|
91
|
+
id: media.id,
|
|
92
|
+
resolution: media.resolution,
|
|
93
|
+
quality: `${media.resolution}p`,
|
|
94
|
+
sizeBytes: toNumber(media.size),
|
|
95
|
+
url: media.url
|
|
96
|
+
}))
|
|
97
|
+
.sort((a, b) => a.resolution - b.resolution);
|
|
98
|
+
}
|
|
99
|
+
export function normalizeCaptions(captions) {
|
|
100
|
+
if (!captions?.length) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
return captions.map((caption) => ({
|
|
104
|
+
id: caption.id,
|
|
105
|
+
languageCode: caption.lan,
|
|
106
|
+
language: caption.lanName,
|
|
107
|
+
sizeBytes: toNumber(caption.size),
|
|
108
|
+
delay: caption.delay,
|
|
109
|
+
url: caption.url
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
export function selectBest(downloads) {
|
|
113
|
+
if (!downloads.length) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return downloads.reduce((best, current) => (current.resolution > best.resolution ? current : best));
|
|
117
|
+
}
|
|
118
|
+
export function selectWorst(downloads) {
|
|
119
|
+
if (!downloads.length) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
return downloads.reduce((worst, current) => (current.resolution < worst.resolution ? current : worst));
|
|
123
|
+
}
|
|
124
|
+
export function resolveRating(subject) {
|
|
125
|
+
if (typeof subject.imdbRatingValue === 'number') {
|
|
126
|
+
return subject.imdbRatingValue;
|
|
127
|
+
}
|
|
128
|
+
if (typeof subject.imdbRate === 'number') {
|
|
129
|
+
return subject.imdbRate;
|
|
130
|
+
}
|
|
131
|
+
if (typeof subject.imdbRate === 'string') {
|
|
132
|
+
const parsed = parseFloat(subject.imdbRate);
|
|
133
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
export function splitDelimited(value) {
|
|
138
|
+
if (!value) {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
141
|
+
if (Array.isArray(value)) {
|
|
142
|
+
return value.map((entry) => entry.trim()).filter(Boolean);
|
|
143
|
+
}
|
|
144
|
+
return value.split(',').map((entry) => entry.trim());
|
|
145
|
+
}
|
|
146
|
+
export function extractNuxtState(html) {
|
|
147
|
+
const marker = '__NUXT_DATA__';
|
|
148
|
+
const markerIndex = html.indexOf(marker);
|
|
149
|
+
if (markerIndex === -1) {
|
|
150
|
+
throw new MovieboxApiError('Unable to locate __NUXT_DATA__ script block.');
|
|
151
|
+
}
|
|
152
|
+
const scriptOpen = html.lastIndexOf('<script', markerIndex);
|
|
153
|
+
if (scriptOpen === -1) {
|
|
154
|
+
throw new MovieboxApiError('Malformed __NUXT_DATA__ script block.');
|
|
155
|
+
}
|
|
156
|
+
const scriptStart = html.indexOf('>', scriptOpen);
|
|
157
|
+
const scriptEnd = html.indexOf('</script>', scriptStart);
|
|
158
|
+
if (scriptStart === -1 || scriptEnd === -1) {
|
|
159
|
+
throw new MovieboxApiError('Malformed __NUXT_DATA__ script block.');
|
|
160
|
+
}
|
|
161
|
+
const jsonText = html.slice(scriptStart + 1, scriptEnd).trim();
|
|
162
|
+
if (!jsonText) {
|
|
163
|
+
throw new MovieboxApiError('Moviebox detail page provided an empty nuxt payload.');
|
|
164
|
+
}
|
|
165
|
+
const parsed = JSON.parse(jsonText);
|
|
166
|
+
const normalized = resolveNuxtPayload(parsed);
|
|
167
|
+
return normalized;
|
|
168
|
+
}
|
|
169
|
+
export function resolveNuxtPayload(payload) {
|
|
170
|
+
if (!Array.isArray(payload)) {
|
|
171
|
+
throw new MovieboxApiError('Unexpected Nuxt payload format.');
|
|
172
|
+
}
|
|
173
|
+
const numericCache = new Map();
|
|
174
|
+
const visitedObjects = new WeakSet();
|
|
175
|
+
const resolveValue = (value) => {
|
|
176
|
+
if (typeof value === 'number' && Number.isInteger(value) && value >= 0 && value < payload.length) {
|
|
177
|
+
if (numericCache.has(value)) {
|
|
178
|
+
return numericCache.get(value);
|
|
179
|
+
}
|
|
180
|
+
const resolved = resolveValue(payload[value]);
|
|
181
|
+
numericCache.set(value, resolved);
|
|
182
|
+
return resolved;
|
|
183
|
+
}
|
|
184
|
+
if (Array.isArray(value)) {
|
|
185
|
+
if (visitedObjects.has(value)) {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
visitedObjects.add(value);
|
|
189
|
+
const resolvedArray = value.map((entry) => resolveValue(entry));
|
|
190
|
+
visitedObjects.delete(value);
|
|
191
|
+
return resolvedArray;
|
|
192
|
+
}
|
|
193
|
+
if (isRecord(value)) {
|
|
194
|
+
if (visitedObjects.has(value)) {
|
|
195
|
+
return {};
|
|
196
|
+
}
|
|
197
|
+
visitedObjects.add(value);
|
|
198
|
+
const resolved = {};
|
|
199
|
+
for (const [key, inner] of Object.entries(value)) {
|
|
200
|
+
resolved[key] = resolveValue(inner);
|
|
201
|
+
}
|
|
202
|
+
visitedObjects.delete(value);
|
|
203
|
+
return resolved;
|
|
204
|
+
}
|
|
205
|
+
return value;
|
|
206
|
+
};
|
|
207
|
+
const extracts = [];
|
|
208
|
+
for (const entry of payload) {
|
|
209
|
+
if (isRecord(entry)) {
|
|
210
|
+
const resolvedEntry = {};
|
|
211
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
212
|
+
resolvedEntry[key] = resolveValue(value);
|
|
213
|
+
}
|
|
214
|
+
extracts.push(resolvedEntry);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (extracts.length === 0) {
|
|
218
|
+
throw new MovieboxApiError('Unable to resolve Nuxt payload entries.');
|
|
219
|
+
}
|
|
220
|
+
const firstExtract = extracts[0];
|
|
221
|
+
if (!isRecord(firstExtract) || !Object.prototype.hasOwnProperty.call(firstExtract, 'state')) {
|
|
222
|
+
throw new MovieboxApiError('Nuxt state did not include expected structure.');
|
|
223
|
+
}
|
|
224
|
+
const stateUnknown = firstExtract['state'];
|
|
225
|
+
if (!Array.isArray(stateUnknown)) {
|
|
226
|
+
throw new MovieboxApiError('Nuxt state payload is not an array.');
|
|
227
|
+
}
|
|
228
|
+
const stateArray = stateUnknown;
|
|
229
|
+
const targetRaw = stateArray[1];
|
|
230
|
+
if (!isRecord(targetRaw)) {
|
|
231
|
+
throw new MovieboxApiError('Nuxt state missing detail payload.');
|
|
232
|
+
}
|
|
233
|
+
const normalized = {};
|
|
234
|
+
const resolvedTarget = resolveValue(targetRaw);
|
|
235
|
+
if (!isRecord(resolvedTarget)) {
|
|
236
|
+
throw new MovieboxApiError('Nuxt state payload is not a record.');
|
|
237
|
+
}
|
|
238
|
+
for (const [key, value] of Object.entries(resolvedTarget)) {
|
|
239
|
+
if (key.startsWith('$s')) {
|
|
240
|
+
normalized[key.slice(2)] = value;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return normalized;
|
|
244
|
+
}
|
|
245
|
+
export function isRecord(value) {
|
|
246
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
247
|
+
}
|
|
248
|
+
export function toNumber(value) {
|
|
249
|
+
if (typeof value === 'number') {
|
|
250
|
+
return value;
|
|
251
|
+
}
|
|
252
|
+
if (typeof value === 'string') {
|
|
253
|
+
const parsed = parseInt(value, 10);
|
|
254
|
+
if (Number.isFinite(parsed)) {
|
|
255
|
+
return parsed;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return 0;
|
|
259
|
+
}
|
|
260
|
+
export function normalizeDetailPath(detailPath) {
|
|
261
|
+
if (!detailPath) {
|
|
262
|
+
throw new MovieboxApiError('A detailPath is required.');
|
|
263
|
+
}
|
|
264
|
+
if (detailPath.startsWith('http')) {
|
|
265
|
+
const url = new URL(detailPath);
|
|
266
|
+
return url.pathname + (url.search ?? '');
|
|
267
|
+
}
|
|
268
|
+
if (detailPath.startsWith(ITEM_DETAILS_PATH)) {
|
|
269
|
+
return detailPath.startsWith('/') ? detailPath : `/${detailPath}`;
|
|
270
|
+
}
|
|
271
|
+
return `${ITEM_DETAILS_PATH}/${detailPath}`;
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=details.js.map
|