|
1 | 1 | import { randomBytes, randomUUID as cryptoRandomUUID } from "node:crypto"; |
2 | 2 | import * as zlib from "node:zlib"; |
3 | 3 | import { CLIENT_LOG3_DOMAIN } from "./config"; |
| 4 | +import { createPlaybackLogContext } from "./playLog"; |
4 | 5 | import { fetchWithProxy } from "@main/utils/proxy"; |
5 | 6 |
|
6 | 7 | interface NeteaseLogRecord { |
@@ -43,22 +44,6 @@ interface NcblContext { |
43 | 44 | processId: number; |
44 | 45 | } |
45 | 46 |
|
46 | | -interface NcblSong { |
47 | | - id: number; |
48 | | - name: string; |
49 | | - artist: string; |
50 | | - bitrate: number; |
51 | | - level: string; |
52 | | - vip: boolean; |
53 | | - time: number; |
54 | | -} |
55 | | - |
56 | | -interface NcblSource { |
57 | | - id: string; |
58 | | - type: string; |
59 | | - name: string; |
60 | | -} |
61 | | - |
62 | 47 | interface UploadResult { |
63 | 48 | success: boolean; |
64 | 49 | fileName: string; |
@@ -224,144 +209,43 @@ const buildRecord = ({ time, action, data }: NeteaseLogRecord): string => { |
224 | 209 | export const buildRecords = (records: NeteaseLogRecord[]): string => |
225 | 210 | records.map(buildRecord).join(""); |
226 | 211 |
|
227 | | -export const buildPlv = ( |
228 | | - ctx: NcblContext, |
229 | | - song: NcblSong, |
230 | | - source: NcblSource, |
231 | | -): Record<string, unknown> => { |
232 | | - const now = Date.now(); |
233 | | - return { |
234 | | - mode: "circulation", |
235 | | - download: 0, |
236 | | - alg: "", |
237 | | - status: "front", |
238 | | - id: String(song.id), |
239 | | - bitrate: song.bitrate, |
240 | | - type: "song", |
241 | | - is_listentogether: 0, |
242 | | - source: source.name, |
243 | | - is_heart: 0, |
244 | | - resource_ratio: "", |
245 | | - resource_time: song.time, |
246 | | - musiceffect_id: "", |
247 | | - app_mode: 2, |
248 | | - bitrate_level: song.level, |
249 | | - _addrefer: `[F:63][${now}#933#${ctx.app.version}#${ctx.app.versionCode}#c9156c3][e][2][23][cell_pc_songlist_song:2|page_pc_songlist_songflow|page_mine_like_music][${song.id}:song:x:x|:::|${source.id}:list::]`, |
250 | | - _multirefers: [ |
251 | | - "[F:26][s][18][_ai]", |
252 | | - "[F:26][s][12][_ai]", |
253 | | - `[F:63][${now}#933#${ctx.app.version}#${ctx.app.versionCode}#c9156c3][e][2][8][cell_pc_main_tab_entrance:6|page_pc_main_tab][我喜欢的音乐:spm::|:::]`, |
254 | | - "[F:26][s][5][_ai]", |
255 | | - "[F:26][s][0][_ai]", |
256 | | - ], |
257 | | - vipType: ctx.auth.vipType, |
258 | | - fee: 1, |
259 | | - file: 4, |
260 | | - rightSource: 0, |
261 | | - sourceId: source.id, |
262 | | - sourcetype: source.type, |
263 | | - libra_abt: "", |
264 | | - channel: ctx.app.channel, |
265 | | - curStartChannel: "", |
266 | | - }; |
267 | | -}; |
268 | | - |
269 | | -export const buildPld = ( |
270 | | - ctx: NcblContext, |
271 | | - song: NcblSong, |
272 | | - source: NcblSource, |
273 | | - played: number, |
274 | | -): Record<string, unknown> => { |
275 | | - const now = Date.now(); |
| 212 | +export const extractContext = (cookieObj: Record<string, string>): NcblContext => { |
| 213 | + const playbackLog = createPlaybackLogContext(cookieObj); |
276 | 214 | return { |
277 | | - mode: "circulation", |
278 | | - download: 0, |
279 | | - alg: "", |
280 | | - status: "front", |
281 | | - id: String(song.id), |
282 | | - time: played, |
283 | | - type: "song", |
284 | | - is_listentogether: 0, |
285 | | - source: source.name, |
286 | | - is_heart: 0, |
287 | | - realtime: played, |
288 | | - resource_ratio: "", |
289 | | - resource_time: song.time, |
290 | | - musiceffect_id: "1001", |
291 | | - app_mode: 1, |
292 | | - lyriceffect: "default", |
293 | | - displayMode: "classic", |
294 | | - bitrate: song.bitrate, |
295 | | - bitrate_level: song.level, |
296 | | - _addrefer: `[F:63][${now}#616#${ctx.app.version}#${ctx.app.versionCode}#c9156c3][e][2][92][btn_pc_cover_play|cell_pc_songlist_song:6|page_pc_songlist_songflow|page_mine_like_music][:::|${song.id}:song:x:x|:::|${source.id}:list::]`, |
297 | | - _multirefers: [ |
298 | | - "[F:26][s][87][_ai]", |
299 | | - "[F:26][s][81][_ai]", |
300 | | - "[F:26][s][75][_ai]", |
301 | | - "[F:26][s][69][_ai]", |
302 | | - "[F:26][s][63][_ai]", |
303 | | - ], |
304 | | - vipType: ctx.auth.vipType, |
305 | | - fee: 8, |
306 | | - file: 4, |
307 | | - rightSource: 0, |
308 | | - sourceId: source.id, |
309 | | - sourcetype: source.type, |
310 | | - end: "interrupt", |
311 | | - libra_abt: "", |
312 | | - channel: ctx.app.channel, |
313 | | - curStartChannel: "", |
| 215 | + app: { |
| 216 | + id: cookieObj.appid || "", |
| 217 | + urs: "", |
| 218 | + pid: "", |
| 219 | + nsm: cookieObj.WEVNSM || "1.0.0", |
| 220 | + cid: cookieObj.WNMCID || `${randomBytes(3).toString("hex")}.${Date.now()}.01.0`, |
| 221 | + channel: playbackLog.app.channel, |
| 222 | + version: playbackLog.app.version, |
| 223 | + versionCode: playbackLog.app.versionCode, |
| 224 | + buildCode: cookieObj.buildver || "", |
| 225 | + buildType: "release", |
| 226 | + packageId: "", |
| 227 | + }, |
| 228 | + device: { |
| 229 | + id: cookieObj.deviceId || cookieObj.sDeviceId || "", |
| 230 | + ti: cookieObj.NMTID || "", |
| 231 | + sign: cookieObj.clientSign || "", |
| 232 | + model: cookieObj.mode || cookieObj.mobilename || "", |
| 233 | + nnid: cookieObj._ntes_nnid || ",", |
| 234 | + nuid: cookieObj._ntes_nuid || "", |
| 235 | + csrf: cookieObj.__csrf || "", |
| 236 | + systemType: cookieObj.os || "pc", |
| 237 | + systemVersion: cookieObj.osver || "Microsoft-Windows-10-Professional-build-19045-64bit", |
| 238 | + }, |
| 239 | + auth: { |
| 240 | + token: cookieObj.MUSIC_U || "", |
| 241 | + sessionId: cookieObj["JSESSIONID-WYYY"] || "", |
| 242 | + vipType: playbackLog.auth.vipType, |
| 243 | + }, |
| 244 | + startTime: Date.now(), |
| 245 | + processId: Math.floor(Math.random() * 90000) + 10000, |
314 | 246 | }; |
315 | 247 | }; |
316 | 248 |
|
317 | | -export const parseCookie = (cookie: unknown): Record<string, string> => { |
318 | | - if (cookie && typeof cookie === "object") return cookie as Record<string, string>; |
319 | | - if (typeof cookie !== "string") return {}; |
320 | | - const obj: Record<string, string> = {}; |
321 | | - for (const part of cookie.split(";")) { |
322 | | - const idx = part.indexOf("="); |
323 | | - if (idx <= 0) continue; |
324 | | - const key = part.substring(0, idx).trim(); |
325 | | - const val = part.substring(idx + 1).trim(); |
326 | | - if (key) obj[key] = val; |
327 | | - } |
328 | | - return obj; |
329 | | -}; |
330 | | - |
331 | | -export const extractContext = (cookieObj: Record<string, string>): NcblContext => ({ |
332 | | - app: { |
333 | | - id: cookieObj.appid || "", |
334 | | - urs: "", |
335 | | - pid: "", |
336 | | - nsm: cookieObj.WEVNSM || "1.0.0", |
337 | | - cid: cookieObj.WNMCID || `${randomBytes(3).toString("hex")}.${Date.now()}.01.0`, |
338 | | - channel: cookieObj.channel || "netease", |
339 | | - version: cookieObj.appver || "3.1.35", |
340 | | - versionCode: cookieObj.versioncode || "205293", |
341 | | - buildCode: cookieObj.buildver || "", |
342 | | - buildType: "release", |
343 | | - packageId: "", |
344 | | - }, |
345 | | - device: { |
346 | | - id: cookieObj.deviceId || cookieObj.sDeviceId || "", |
347 | | - ti: cookieObj.NMTID || "", |
348 | | - sign: cookieObj.clientSign || "", |
349 | | - model: cookieObj.mode || cookieObj.mobilename || "", |
350 | | - nnid: cookieObj._ntes_nnid || ",", |
351 | | - nuid: cookieObj._ntes_nuid || "", |
352 | | - csrf: cookieObj.__csrf || "", |
353 | | - systemType: cookieObj.os || "pc", |
354 | | - systemVersion: cookieObj.osver || "Microsoft-Windows-10-Professional-build-19045-64bit", |
355 | | - }, |
356 | | - auth: { |
357 | | - token: cookieObj.MUSIC_U || "", |
358 | | - sessionId: cookieObj["JSESSIONID-WYYY"] || "", |
359 | | - vipType: cookieObj.vipType || "", |
360 | | - }, |
361 | | - startTime: Date.now(), |
362 | | - processId: Math.floor(Math.random() * 90000) + 10000, |
363 | | -}); |
364 | | - |
365 | 249 | const randomHexId = (): string => cryptoRandomUUID().replace(/-/g, ""); |
366 | 250 |
|
367 | 251 | export const buildMultipart = ( |
|
0 commit comments