@neteasecloudmusicapienhanced/api 4.31.0 → 4.32.1
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 +21 -21
- package/README.MD +248 -251
- package/app.js +18 -18
- package/data/china_ip_ranges.txt +4147 -4147
- package/data/deviceid.txt +24641 -24641
- package/generateConfig.js +24 -24
- package/interface.d.ts +1843 -1836
- package/main.js +63 -63
- package/module/activate_init_profile.js +9 -9
- package/module/aidj_content_rcmd.js +28 -28
- package/module/album.js +6 -6
- package/module/album_detail.js +12 -12
- package/module/album_detail_dynamic.js +12 -12
- package/module/album_list.js +16 -16
- package/module/album_list_style.js +15 -15
- package/module/album_new.js +11 -11
- package/module/album_newest.js +6 -6
- package/module/album_privilege.js +9 -9
- package/module/album_songsaleboard.js +19 -19
- package/module/album_sub.js +10 -10
- package/module/album_sublist.js +11 -11
- package/module/api.js +21 -21
- package/module/artist_album.js +15 -15
- package/module/artist_desc.js +9 -9
- package/module/artist_detail.js +10 -10
- package/module/artist_detail_dynamic.js +9 -9
- package/module/artist_fans.js +11 -11
- package/module/artist_follow_count.js +13 -13
- package/module/artist_list.js +33 -33
- package/module/artist_mv.js +12 -12
- package/module/artist_new_mv.js +12 -12
- package/module/artist_new_song.js +12 -12
- package/module/artist_songs.js +12 -12
- package/module/artist_sub.js +11 -11
- package/module/artist_sublist.js +11 -11
- package/module/artist_top_song.js +8 -8
- package/module/artist_video.js +15 -15
- package/module/artists.js +6 -6
- package/module/audio_match.js +19 -19
- package/module/avatar_upload.js +22 -22
- package/module/banner.js +16 -16
- package/module/batch.js +12 -12
- package/module/broadcast_category_region_get.js +11 -11
- package/module/broadcast_channel_collect_list.js +12 -12
- package/module/broadcast_channel_currentinfo.js +13 -13
- package/module/broadcast_channel_list.js +13 -13
- package/module/broadcast_sub.js +12 -12
- package/module/calendar.js +8 -8
- package/module/captcha_sent.js +11 -11
- package/module/captcha_verify.js +11 -11
- package/module/cellphone_existence_check.js +10 -10
- package/module/check_music.js +30 -30
- package/module/cloud.js +164 -164
- package/module/cloud_import.js +39 -39
- package/module/cloud_lyric_get.js +11 -11
- package/module/cloud_match.js +13 -13
- package/module/cloud_upload_complete.js +72 -72
- package/module/cloud_upload_token.js +111 -111
- package/module/cloudsearch.js +13 -13
- package/module/comment.js +30 -30
- package/module/comment_album.js +16 -16
- package/module/comment_dj.js +16 -16
- package/module/comment_event.js +15 -15
- package/module/comment_floor.js +16 -16
- package/module/comment_hot.js +18 -18
- package/module/comment_hug_list.js +20 -20
- package/module/comment_info_list.js +30 -30
- package/module/comment_like.js +20 -20
- package/module/comment_music.js +16 -16
- package/module/comment_mv.js +16 -16
- package/module/comment_new.js +37 -37
- package/module/comment_playlist.js +16 -16
- package/module/{comment_delete.js → comment_report.js} +11 -10
- package/module/comment_video.js +16 -16
- package/module/countries_code_list.js +6 -6
- package/module/creator_authinfo_get.js +6 -6
- package/module/daily_signin.js +16 -16
- package/module/digitalAlbum_detail.js +13 -13
- package/module/digitalAlbum_ordering.js +22 -22
- package/module/digitalAlbum_purchased.js +15 -15
- package/module/digitalAlbum_sales.js +13 -13
- package/module/djRadio_top.js +15 -15
- package/module/dj_banner.js +6 -6
- package/module/dj_category_excludehot.js +10 -10
- package/module/dj_category_recommend.js +10 -10
- package/module/dj_catelist.js +6 -6
- package/module/dj_detail.js +9 -9
- package/module/dj_difm_all_style_channel.js +9 -9
- package/module/dj_difm_channel_subscribe.js +9 -9
- package/module/dj_difm_channel_unsubscribe.js +9 -9
- package/module/dj_difm_playing_tracks_list.js +11 -11
- package/module/dj_difm_subscribe_channels_get.js +13 -13
- package/module/dj_hot.js +10 -10
- package/module/dj_paygift.js +15 -15
- package/module/dj_personalize_recommend.js +12 -12
- package/module/dj_program.js +12 -12
- package/module/dj_program_detail.js +9 -9
- package/module/dj_program_toplist.js +10 -10
- package/module/dj_program_toplist_hours.js +13 -13
- package/module/dj_radio_hot.js +11 -11
- package/module/dj_recommend.js +6 -6
- package/module/dj_recommend_type.js +32 -32
- package/module/dj_sub.js +10 -10
- package/module/dj_sublist.js +11 -11
- package/module/dj_subscriber.js +12 -12
- package/module/dj_today_perfered.js +13 -13
- package/module/dj_toplist.js +14 -14
- package/module/dj_toplist_hours.js +10 -10
- package/module/dj_toplist_newcomer.js +9 -9
- package/module/dj_toplist_pay.js +9 -9
- package/module/dj_toplist_popular.js +10 -10
- package/module/eapi_decrypt.js +27 -27
- package/module/event.js +10 -10
- package/module/event_del.js +9 -9
- package/module/event_forward.js +11 -11
- package/module/fanscenter_basicinfo_age_get.js +6 -6
- package/module/fanscenter_basicinfo_gender_get.js +10 -10
- package/module/fanscenter_basicinfo_province_get.js +10 -10
- package/module/fanscenter_overview_get.js +6 -6
- package/module/fanscenter_trend_list.js +10 -10
- package/module/fm_trash.js +11 -11
- package/module/follow.js +11 -11
- package/module/get_userids.js +7 -7
- package/module/history_recommend_songs.js +11 -11
- package/module/history_recommend_songs_detail.js +13 -13
- package/module/homepage_block_page.js +8 -8
- package/module/homepage_dragon_ball.js +10 -10
- package/module/hot_topic.js +10 -10
- package/module/hug_comment.js +16 -16
- package/module/inner_version.js +16 -16
- package/module/like.js +13 -13
- package/module/likelist.js +9 -9
- package/module/listen_data_realtime_report.js +11 -11
- package/module/listen_data_report.js +12 -12
- package/module/listen_data_today_song.js +9 -9
- package/module/listen_data_total.js +9 -9
- package/module/listen_data_year_report.js +9 -9
- package/module/listentogether_accept.js +13 -13
- package/module/listentogether_end.js +9 -9
- package/module/listentogether_heatbeat.js +12 -12
- package/module/listentogether_play_command.js +21 -21
- package/module/listentogether_room_check.js +9 -9
- package/module/listentogether_room_create.js +9 -9
- package/module/listentogether_status.js +10 -10
- package/module/listentogether_sync_list_command.js +26 -26
- package/module/listentogether_sync_playlist_get.js +13 -13
- package/module/login.js +41 -41
- package/module/login_cellphone.js +40 -40
- package/module/login_qr_check.js +29 -29
- package/module/login_qr_create.js +30 -30
- package/module/login_qr_key.js +19 -19
- package/module/login_refresh.js +21 -21
- package/module/login_status.js +21 -21
- package/module/logout.js +6 -6
- package/module/lyric.js +14 -14
- package/module/lyric_new.js +17 -17
- package/module/mlog_music_rcmd.js +13 -13
- package/module/mlog_to_video.js +13 -13
- package/module/mlog_url.js +11 -11
- package/module/msg_comments.js +17 -17
- package/module/msg_forwards.js +11 -11
- package/module/msg_notices.js +10 -10
- package/module/msg_private.js +11 -11
- package/module/msg_private_history.js +12 -12
- package/module/msg_recentcontact.js +11 -11
- package/module/music_first_listen_info.js +13 -13
- package/module/musician_cloudbean.js +7 -7
- package/module/musician_cloudbean_obtain.js +14 -14
- package/module/musician_data_overview.js +11 -11
- package/module/musician_play_trend.js +14 -14
- package/module/musician_sign.js +7 -7
- package/module/musician_tasks.js +11 -11
- package/module/musician_tasks_new.js +11 -11
- package/module/musician_vip_tasks.js +11 -11
- package/module/mv_all.js +16 -16
- package/module/mv_detail.js +9 -9
- package/module/mv_detail_info.js +14 -14
- package/module/mv_exclusive_rcmd.js +10 -10
- package/module/mv_first.js +12 -12
- package/module/mv_sub.js +11 -11
- package/module/mv_sublist.js +15 -15
- package/module/mv_url.js +14 -14
- package/module/nickname_check.js +7 -7
- package/module/personal_fm.js +6 -6
- package/module/personal_fm_mode.js +14 -14
- package/module/personalized.js +16 -16
- package/module/personalized_djprogram.js +10 -10
- package/module/personalized_mv.js +6 -6
- package/module/personalized_newsong.js +15 -15
- package/module/personalized_privatecontent.js +10 -10
- package/module/personalized_privatecontent_list.js +15 -15
- package/module/pl_count.js +6 -6
- package/module/playlist_category_list.js +11 -11
- package/module/playlist_catlist.js +6 -6
- package/module/playlist_cover_update.js +32 -32
- package/module/playlist_create.js +11 -11
- package/module/playlist_delete.js +9 -9
- package/module/playlist_desc_update.js +10 -10
- package/module/playlist_detail.js +11 -11
- package/module/playlist_detail_dynamic.js +11 -11
- package/module/playlist_detail_rcmd_get.js +11 -11
- package/module/playlist_highquality_tags.js +10 -10
- package/module/playlist_hot.js +6 -6
- package/module/playlist_import_name_task_create.js +62 -62
- package/module/playlist_import_task_status.js +11 -11
- package/module/playlist_mylike.js +12 -12
- package/module/playlist_name_update.js +10 -10
- package/module/playlist_order_update.js +13 -13
- package/module/playlist_privacy.js +10 -10
- package/module/playlist_subscribe.js +14 -14
- package/module/playlist_subscribers.js +11 -11
- package/module/playlist_tags_update.js +10 -10
- package/module/playlist_track_add.js +16 -16
- package/module/playlist_track_all.js +31 -31
- package/module/playlist_track_delete.js +20 -20
- package/module/playlist_tracks.js +45 -45
- package/module/playlist_update.js +13 -13
- package/module/playlist_update_playcount.js +9 -9
- package/module/playlist_video_recent.js +9 -9
- package/module/playmode_intelligence_list.js +13 -13
- package/module/playmode_song_vector.js +8 -8
- package/module/program_recommend.js +15 -15
- package/module/radio_sport_get.js +9 -0
- package/module/rebind.js +16 -16
- package/module/recent_listen_list.js +7 -7
- package/module/recommend_resource.js +10 -10
- package/module/recommend_songs.js +13 -11
- package/module/recommend_songs_dislike.js +14 -14
- package/module/record_recent_album.js +11 -11
- package/module/record_recent_dj.js +11 -11
- package/module/record_recent_playlist.js +11 -11
- package/module/record_recent_song.js +11 -11
- package/module/record_recent_video.js +11 -11
- package/module/record_recent_voice.js +11 -11
- package/module/register_anonimous.js +53 -52
- package/module/register_cellphone.js +15 -15
- package/module/related_allvideo.js +14 -14
- package/module/related_playlist.js +32 -32
- package/module/resource_like.js +14 -14
- package/module/sati_resource_list.js +11 -0
- package/module/sati_resource_list_more.js +13 -0
- package/module/sati_resource_sub.js +10 -0
- package/module/sati_resource_sub_list.js +7 -0
- package/module/sati_tag_list.js +7 -0
- package/module/sati_timescene_resources_get.js +13 -0
- package/module/scrobble.js +26 -26
- package/module/search.js +21 -21
- package/module/search_default.js +6 -6
- package/module/search_hot.js +9 -9
- package/module/search_hot_detail.js +6 -6
- package/module/search_match.js +18 -18
- package/module/search_multimatch.js +14 -14
- package/module/search_suggest.js +14 -14
- package/module/search_suggest_pc.js +13 -13
- package/module/send_album.js +12 -12
- package/module/send_playlist.js +12 -12
- package/module/send_song.js +12 -12
- package/module/send_text.js +11 -11
- package/module/setting.js +7 -7
- package/module/share_resource.js +11 -11
- package/module/sheet_list.js +9 -9
- package/module/sheet_preview.js +8 -8
- package/module/sign_happy_info.js +5 -5
- package/module/signin_progress.js +13 -13
- package/module/simi_artist.js +12 -12
- package/module/simi_mv.js +9 -9
- package/module/simi_playlist.js +15 -15
- package/module/simi_song.js +15 -15
- package/module/simi_user.js +11 -11
- package/module/song_chorus.js +11 -11
- package/module/song_copyright_rcmd.js +9 -0
- package/module/song_creators.js +9 -0
- package/module/song_detail.js +11 -11
- package/module/song_downlist.js +11 -11
- package/module/song_download_url.js +10 -10
- package/module/song_download_url_v1.js +13 -13
- package/module/song_dynamic_cover.js +9 -9
- package/module/song_like.js +12 -12
- package/module/song_like_check.js +9 -9
- package/module/song_lyrics_mark.js +9 -9
- package/module/song_lyrics_mark_add.js +12 -12
- package/module/song_lyrics_mark_del.js +9 -9
- package/module/song_lyrics_mark_user_page.js +14 -14
- package/module/song_monthdownlist.js +11 -11
- package/module/song_music_detail.js +9 -9
- package/module/song_order_update.js +12 -12
- package/module/song_purchased.js +14 -14
- package/module/song_red_count.js +9 -9
- package/module/song_singledownlist.js +11 -11
- package/module/song_url.js +26 -26
- package/module/song_url_match.js +38 -38
- package/module/song_url_ncmget.js +5 -5
- package/module/song_url_v1.js +57 -57
- package/module/song_url_v1_302.js +53 -53
- package/module/song_wiki_summary.js +8 -8
- package/module/starpick_comments_summary.js +12 -12
- package/module/style_album.js +16 -16
- package/module/style_artist.js +16 -16
- package/module/style_detail.js +9 -9
- package/module/style_list.js +7 -7
- package/module/style_playlist.js +16 -16
- package/module/style_preference.js +11 -11
- package/module/style_song.js +12 -12
- package/module/summary_annual.js +12 -12
- package/module/threshold_detail_get.js +10 -10
- package/module/top_album.js +22 -22
- package/module/top_artists.js +11 -11
- package/module/top_list.js +20 -20
- package/module/top_mv.js +12 -12
- package/module/top_playlist.js +22 -22
- package/module/top_playlist_highquality.js +16 -16
- package/module/top_song.js +16 -16
- package/module/topic_detail.js +7 -7
- package/module/topic_detail_event_hot.js +7 -7
- package/module/topic_sublist.js +11 -11
- package/module/toplist.js +6 -6
- package/module/toplist_artist.js +12 -12
- package/module/toplist_detail.js +6 -6
- package/module/toplist_detail_v2.js +6 -6
- package/module/ugc_album_get.js +8 -8
- package/module/ugc_artist_get.js +8 -8
- package/module/ugc_artist_search.js +10 -10
- package/module/ugc_detail.js +17 -17
- package/module/ugc_mv_get.js +8 -8
- package/module/ugc_song_get.js +8 -8
- package/module/ugc_user_devote.js +6 -6
- package/module/user_account.js +5 -5
- package/module/user_audio.js +9 -9
- package/module/user_binding.js +9 -9
- package/module/user_bindingcellphone.js +15 -15
- package/module/user_cloud.js +10 -10
- package/module/user_cloud_del.js +9 -9
- package/module/user_cloud_detail.js +10 -10
- package/module/user_comment_history.js +15 -15
- package/module/user_detail.js +15 -15
- package/module/user_detail_new.js +20 -20
- package/module/user_dj.js +14 -14
- package/module/user_event.js +12 -12
- package/module/user_follow_mixed.js +23 -23
- package/module/user_followeds.js +17 -17
- package/module/user_follows.js +15 -15
- package/module/user_level.js +7 -7
- package/module/user_medal.js +11 -11
- package/module/user_mutualfollow_get.js +9 -9
- package/module/user_playlist.js +12 -12
- package/module/user_playlist_collect.js +14 -14
- package/module/user_playlist_create.js +14 -14
- package/module/user_record.js +10 -10
- package/module/user_replacephone.js +14 -14
- package/module/user_social_status.js +11 -11
- package/module/user_social_status_edit.js +16 -16
- package/module/user_social_status_rcmd.js +5 -5
- package/module/user_social_status_support.js +5 -5
- package/module/user_subcount.js +6 -6
- package/module/user_update.js +15 -15
- package/module/verify_getQr.js +39 -39
- package/module/verify_qrcodestatus.js +12 -12
- package/module/video_category_list.js +15 -15
- package/module/video_detail.js +13 -13
- package/module/video_detail_info.js +14 -14
- package/module/video_group.js +16 -16
- package/module/video_group_list.js +11 -11
- package/module/video_sub.js +14 -14
- package/module/video_timeline_all.js +17 -17
- package/module/video_timeline_recommend.js +13 -13
- package/module/video_url.js +10 -10
- package/module/vip_growthpoint.js +11 -11
- package/module/vip_growthpoint_details.js +14 -14
- package/module/vip_growthpoint_get.js +13 -13
- package/module/vip_info.js +12 -12
- package/module/vip_info_v2.js +12 -12
- package/module/vip_sign.js +7 -11
- package/module/vip_sign_info.js +11 -11
- package/module/vip_tasks.js +11 -11
- package/module/vip_timemachine.js +17 -17
- package/module/voice_delete.js +7 -7
- package/module/voice_detail.js +7 -7
- package/module/voice_lyric.js +7 -7
- package/module/voice_upload.js +200 -200
- package/module/voicelist_detail.js +11 -11
- package/module/voicelist_list.js +13 -13
- package/module/voicelist_list_search.js +14 -14
- package/module/voicelist_my_created.js +13 -13
- package/module/voicelist_search.js +11 -11
- package/module/voicelist_trans.js +15 -15
- package/module/weblog.js +10 -10
- package/module/yunbei.js +6 -6
- package/module/yunbei_expense.js +8 -8
- package/module/yunbei_info.js +5 -5
- package/module/yunbei_rcmd_song.js +17 -17
- package/module/yunbei_rcmd_song_history.js +16 -16
- package/module/yunbei_receipt.js +8 -8
- package/module/yunbei_sign.js +5 -5
- package/module/yunbei_task_finish.js +12 -12
- package/module/yunbei_tasks.js +9 -9
- package/module/yunbei_tasks_todo.js +9 -9
- package/module/yunbei_today.js +5 -5
- package/package.json +8 -8
- package/plugins/songUpload.js +109 -109
- package/plugins/upload.js +35 -35
- package/public/api.html +222 -193
- package/public/audio_match_demo/afp.js +1626 -1626
- package/public/audio_match_demo/afp.wasm.js +5 -5
- package/public/audio_match_demo/index.html +367 -367
- package/public/audio_match_demo/rec.js +49 -49
- package/public/avatar_update.html +326 -326
- package/public/cloud.html +578 -578
- package/public/docs/_coverpage.md +13 -13
- package/public/docs/home.md +5318 -5218
- package/public/docs/index.html +129 -47
- package/public/docs/logo.svg +6 -6
- package/public/docs/netease.png +0 -0
- package/public/docs/sw.js +90 -90
- package/public/eapi_decrypt.html +264 -226
- package/public/home.html +40 -40
- package/public/index.html +124 -124
- package/public/listen_together_host.html +552 -552
- package/public/login.html +219 -219
- package/public/playlist_cover_update.html +323 -323
- package/public/playlist_import.html +416 -416
- package/public/qrlogin-nocookie.html +199 -199
- package/public/qrlogin.html +199 -199
- package/public/static/2169.png +0 -0
- package/public/static/neteaselogo.png +0 -0
- package/public/unblock_test.html +153 -153
- package/public/voice_upload.html +326 -326
- package/server.js +454 -435
- package/util/apicache.js +836 -836
- package/util/client-sign.js +169 -169
- package/util/config.json +20 -20
- package/util/crypto.js +153 -135
- package/util/fileHelper.js +88 -88
- package/util/index.js +233 -233
- package/util/logger.js +42 -42
- package/util/memory-cache.js +71 -71
- package/util/option.js +14 -14
- package/util/request.js +367 -368
- package/module/comment_add.js +0 -15
- package/module/comment_reply.js +0 -13
package/util/fileHelper.js
CHANGED
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const crypto = require('crypto')
|
|
3
|
-
const logger = require('./logger')
|
|
4
|
-
|
|
5
|
-
function isTempFile(file) {
|
|
6
|
-
return !!(file && file.tempFilePath)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async function getFileSize(file) {
|
|
10
|
-
if (isTempFile(file)) {
|
|
11
|
-
const stats = await fs.promises.stat(file.tempFilePath)
|
|
12
|
-
return stats.size
|
|
13
|
-
}
|
|
14
|
-
return file.data ? file.data.byteLength : file.size || 0
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async function getFileMd5(file) {
|
|
18
|
-
if (file.md5) {
|
|
19
|
-
return file.md5
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (isTempFile(file)) {
|
|
23
|
-
return new Promise((resolve, reject) => {
|
|
24
|
-
const hash = crypto.createHash('md5')
|
|
25
|
-
const stream = fs.createReadStream(file.tempFilePath)
|
|
26
|
-
stream.on('data', (chunk) => hash.update(chunk))
|
|
27
|
-
stream.on('end', () => resolve(hash.digest('hex')))
|
|
28
|
-
stream.on('error', reject)
|
|
29
|
-
})
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (file.data) {
|
|
33
|
-
return crypto.createHash('md5').update(file.data).digest('hex')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
throw new Error('无法计算文件MD5: 缺少文件数据')
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function getUploadData(file) {
|
|
40
|
-
if (isTempFile(file)) {
|
|
41
|
-
return fs.createReadStream(file.tempFilePath)
|
|
42
|
-
}
|
|
43
|
-
return file.data
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function cleanupTempFile(filePath) {
|
|
47
|
-
if (!filePath) return
|
|
48
|
-
try {
|
|
49
|
-
await fs.promises.unlink(filePath)
|
|
50
|
-
} catch (e) {
|
|
51
|
-
logger.info('临时文件清理失败:', e.message)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async function readFileChunk(filePath, offset, length) {
|
|
56
|
-
const fd = await fs.promises.open(filePath, 'r')
|
|
57
|
-
const buffer = Buffer.alloc(length)
|
|
58
|
-
await fd.read(buffer, 0, length, offset)
|
|
59
|
-
await fd.close()
|
|
60
|
-
return buffer
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function getFileExtension(filename) {
|
|
64
|
-
if (!filename) return 'mp3'
|
|
65
|
-
if (filename.includes('.')) {
|
|
66
|
-
return filename.split('.').pop().toLowerCase()
|
|
67
|
-
}
|
|
68
|
-
return 'mp3'
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function sanitizeFilename(filename) {
|
|
72
|
-
if (!filename) return 'unknown'
|
|
73
|
-
return filename
|
|
74
|
-
.replace(/\.[^.]+$/, '')
|
|
75
|
-
.replace(/\s/g, '')
|
|
76
|
-
.replace(/\./g, '_')
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
module.exports = {
|
|
80
|
-
isTempFile,
|
|
81
|
-
getFileSize,
|
|
82
|
-
getFileMd5,
|
|
83
|
-
getUploadData,
|
|
84
|
-
cleanupTempFile,
|
|
85
|
-
readFileChunk,
|
|
86
|
-
getFileExtension,
|
|
87
|
-
sanitizeFilename,
|
|
88
|
-
}
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const crypto = require('crypto')
|
|
3
|
+
const logger = require('./logger')
|
|
4
|
+
|
|
5
|
+
function isTempFile(file) {
|
|
6
|
+
return !!(file && file.tempFilePath)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async function getFileSize(file) {
|
|
10
|
+
if (isTempFile(file)) {
|
|
11
|
+
const stats = await fs.promises.stat(file.tempFilePath)
|
|
12
|
+
return stats.size
|
|
13
|
+
}
|
|
14
|
+
return file.data ? file.data.byteLength : file.size || 0
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function getFileMd5(file) {
|
|
18
|
+
if (file.md5) {
|
|
19
|
+
return file.md5
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (isTempFile(file)) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const hash = crypto.createHash('md5')
|
|
25
|
+
const stream = fs.createReadStream(file.tempFilePath)
|
|
26
|
+
stream.on('data', (chunk) => hash.update(chunk))
|
|
27
|
+
stream.on('end', () => resolve(hash.digest('hex')))
|
|
28
|
+
stream.on('error', reject)
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (file.data) {
|
|
33
|
+
return crypto.createHash('md5').update(file.data).digest('hex')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
throw new Error('无法计算文件MD5: 缺少文件数据')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getUploadData(file) {
|
|
40
|
+
if (isTempFile(file)) {
|
|
41
|
+
return fs.createReadStream(file.tempFilePath)
|
|
42
|
+
}
|
|
43
|
+
return file.data
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function cleanupTempFile(filePath) {
|
|
47
|
+
if (!filePath) return
|
|
48
|
+
try {
|
|
49
|
+
await fs.promises.unlink(filePath)
|
|
50
|
+
} catch (e) {
|
|
51
|
+
logger.info('临时文件清理失败:', e.message)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function readFileChunk(filePath, offset, length) {
|
|
56
|
+
const fd = await fs.promises.open(filePath, 'r')
|
|
57
|
+
const buffer = Buffer.alloc(length)
|
|
58
|
+
await fd.read(buffer, 0, length, offset)
|
|
59
|
+
await fd.close()
|
|
60
|
+
return buffer
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getFileExtension(filename) {
|
|
64
|
+
if (!filename) return 'mp3'
|
|
65
|
+
if (filename.includes('.')) {
|
|
66
|
+
return filename.split('.').pop().toLowerCase()
|
|
67
|
+
}
|
|
68
|
+
return 'mp3'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function sanitizeFilename(filename) {
|
|
72
|
+
if (!filename) return 'unknown'
|
|
73
|
+
return filename
|
|
74
|
+
.replace(/\.[^.]+$/, '')
|
|
75
|
+
.replace(/\s/g, '')
|
|
76
|
+
.replace(/\./g, '_')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = {
|
|
80
|
+
isTempFile,
|
|
81
|
+
getFileSize,
|
|
82
|
+
getFileMd5,
|
|
83
|
+
getUploadData,
|
|
84
|
+
cleanupTempFile,
|
|
85
|
+
readFileChunk,
|
|
86
|
+
getFileExtension,
|
|
87
|
+
sanitizeFilename,
|
|
88
|
+
}
|
package/util/index.js
CHANGED
|
@@ -1,233 +1,233 @@
|
|
|
1
|
-
const logger = require('./logger')
|
|
2
|
-
const fs = require('fs')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
|
|
5
|
-
// IP地址转换函数
|
|
6
|
-
function ipToInt(ip) {
|
|
7
|
-
const parts = ip.split('.').map(Number)
|
|
8
|
-
const a = (parts[0] << 24) >>> 0
|
|
9
|
-
const b = parts[1] << 16
|
|
10
|
-
const c = parts[2] << 8
|
|
11
|
-
const d = parts[3]
|
|
12
|
-
return a + b + c + d
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function intToIp(int) {
|
|
16
|
-
return [
|
|
17
|
-
(int >>> 24) & 0xff,
|
|
18
|
-
(int >>> 16) & 0xff,
|
|
19
|
-
(int >>> 8) & 0xff,
|
|
20
|
-
int & 0xff,
|
|
21
|
-
].join('.')
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// 解析CIDR格式的IP段
|
|
25
|
-
function parseCIDR(cidr) {
|
|
26
|
-
const [ipStr, prefixLengthStr] = cidr.split('/')
|
|
27
|
-
const prefixLength = parseInt(prefixLengthStr, 10)
|
|
28
|
-
|
|
29
|
-
const ipInt = ipToInt(ipStr)
|
|
30
|
-
const mask = (0xffffffff << (32 - prefixLength)) >>> 0
|
|
31
|
-
const start = (ipInt & mask) >>> 0
|
|
32
|
-
const end = (start | (~mask >>> 0)) >>> 0
|
|
33
|
-
const count = end - start + 1
|
|
34
|
-
|
|
35
|
-
return { start, end, count, cidr }
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// 从china_ip_ranges.txt加载中国IP段(CIDR格式)
|
|
39
|
-
const chinaIPRanges = (function loadChinaIPRanges() {
|
|
40
|
-
try {
|
|
41
|
-
const filePath = path.join(__dirname, '../data/china_ip_ranges.txt')
|
|
42
|
-
const content = fs.readFileSync(filePath, 'utf-8')
|
|
43
|
-
const lines = content
|
|
44
|
-
.split('\n')
|
|
45
|
-
.filter((line) => line.trim() && !line.startsWith('#'))
|
|
46
|
-
|
|
47
|
-
const arr = []
|
|
48
|
-
let total = 0
|
|
49
|
-
|
|
50
|
-
for (let i = 0; i < lines.length; i++) {
|
|
51
|
-
const line = lines[i].trim()
|
|
52
|
-
if (!line) continue
|
|
53
|
-
|
|
54
|
-
const range = parseCIDR(line)
|
|
55
|
-
arr.push(range)
|
|
56
|
-
total += range.count
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// 按IP段大小排序,提高随机选择效率
|
|
60
|
-
arr.sort((a, b) => b.count - a.count)
|
|
61
|
-
|
|
62
|
-
// attach total for convenience
|
|
63
|
-
arr.totalCount = total
|
|
64
|
-
|
|
65
|
-
logger.info(
|
|
66
|
-
`Loaded ${arr.length} Chinese IP ranges from china_ip_ranges.txt, total ${total} IPs`,
|
|
67
|
-
)
|
|
68
|
-
return arr
|
|
69
|
-
} catch (error) {
|
|
70
|
-
logger.error('Failed to load china_ip_ranges.txt:', error.message)
|
|
71
|
-
// 返回空数组,generateRandomChineseIP会使用兜底逻辑
|
|
72
|
-
return { totalCount: 0 }
|
|
73
|
-
}
|
|
74
|
-
})()
|
|
75
|
-
const floor = Math.floor
|
|
76
|
-
const random = Math.random
|
|
77
|
-
const keys = Object.keys
|
|
78
|
-
|
|
79
|
-
// 预编译encodeURIComponent以减少查找开销
|
|
80
|
-
const encode = encodeURIComponent
|
|
81
|
-
|
|
82
|
-
module.exports = {
|
|
83
|
-
toBoolean(val) {
|
|
84
|
-
if (typeof val === 'boolean') return val
|
|
85
|
-
if (val === '') return val
|
|
86
|
-
return val === 'true' || val == '1'
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
cookieToJson(cookie) {
|
|
90
|
-
if (!cookie) return {}
|
|
91
|
-
let cookieArr = cookie.split(';')
|
|
92
|
-
let obj = {}
|
|
93
|
-
|
|
94
|
-
// 优化:使用for循环替代forEach,性能更好
|
|
95
|
-
for (let i = 0, len = cookieArr.length; i < len; i++) {
|
|
96
|
-
let item = cookieArr[i]
|
|
97
|
-
let arr = item.split('=')
|
|
98
|
-
// 优化:使用严格等于
|
|
99
|
-
if (arr.length === 2) {
|
|
100
|
-
obj[arr[0].trim()] = arr[1].trim()
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return obj
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
cookieObjToString(cookie) {
|
|
107
|
-
// 优化:使用预绑定的keys函数和for循环
|
|
108
|
-
const cookieKeys = keys(cookie)
|
|
109
|
-
const result = []
|
|
110
|
-
|
|
111
|
-
// 优化:使用for循环和预分配数组
|
|
112
|
-
for (let i = 0, len = cookieKeys.length; i < len; i++) {
|
|
113
|
-
const key = cookieKeys[i]
|
|
114
|
-
result[i] = `${encode(key)}=${encode(cookie[key])}`
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return result.join('; ')
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
getRandom(num) {
|
|
121
|
-
// 优化:简化随机数生成逻辑
|
|
122
|
-
// 原逻辑看起来有问题,这里保持原意但优化性能
|
|
123
|
-
var randomValue = random()
|
|
124
|
-
var floorValue = floor(randomValue * 9 + 1)
|
|
125
|
-
var powValue = Math.pow(10, num - 1)
|
|
126
|
-
var randomNum = floor((randomValue + floorValue) * powValue)
|
|
127
|
-
return randomNum
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
generateRandomChineseIP() {
|
|
131
|
-
// 从预定义的中国 IP 段中按权重随机选择一个段,然后在该段内生成随机 IP
|
|
132
|
-
const total = chinaIPRanges.totalCount || 0
|
|
133
|
-
if (!total) {
|
|
134
|
-
// 兜底:回退到旧逻辑(随机 116.x 前缀)
|
|
135
|
-
const fallback = `116.${getRandomInt(25, 94)}.${generateIPSegment()}.${generateIPSegment()}`
|
|
136
|
-
logger.info('Generated Random Chinese IP (fallback):', fallback)
|
|
137
|
-
return fallback
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// 选择一个全局随机偏移([0, total))
|
|
141
|
-
let offset = Math.floor(random() * total)
|
|
142
|
-
let chosen = null
|
|
143
|
-
for (let i = 0; i < chinaIPRanges.length; i++) {
|
|
144
|
-
const seg = chinaIPRanges[i]
|
|
145
|
-
if (offset < seg.count) {
|
|
146
|
-
chosen = seg
|
|
147
|
-
break
|
|
148
|
-
}
|
|
149
|
-
offset -= seg.count
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// 如果没有选中(理论上不应该发生),回退到最后一个段
|
|
153
|
-
if (!chosen) chosen = chinaIPRanges[chinaIPRanges.length - 1]
|
|
154
|
-
|
|
155
|
-
// 在段内随机生成一个 IP(使用段真实的数值范围)
|
|
156
|
-
const segSize = chosen.end - chosen.start + 1
|
|
157
|
-
const ipInt = chosen.start + Math.floor(random() * segSize)
|
|
158
|
-
const ip = intToIp(ipInt)
|
|
159
|
-
logger.info('Generated Random Chinese IP:', ip, 'from CIDR:', chosen.cidr)
|
|
160
|
-
return ip
|
|
161
|
-
},
|
|
162
|
-
// 生成chainId的函数
|
|
163
|
-
generateChainId(cookie) {
|
|
164
|
-
const version = 'v1'
|
|
165
|
-
const randomNum = Math.floor(Math.random() * 1e6)
|
|
166
|
-
const deviceId =
|
|
167
|
-
getCookieValue(cookie, 'sDeviceId') || 'unknown-' + randomNum
|
|
168
|
-
const platform = 'web'
|
|
169
|
-
const action = 'login'
|
|
170
|
-
const timestamp = Date.now()
|
|
171
|
-
|
|
172
|
-
return `${version}_${deviceId}_${platform}_${action}_${timestamp}`
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
generateDeviceId() {
|
|
176
|
-
const hexChars = '0123456789ABCDEF'
|
|
177
|
-
const chars = []
|
|
178
|
-
for (let i = 0; i < 52; i++) {
|
|
179
|
-
const randomIndex = Math.floor(Math.random() * hexChars.length)
|
|
180
|
-
chars.push(hexChars[randomIndex])
|
|
181
|
-
}
|
|
182
|
-
return chars.join('')
|
|
183
|
-
},
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// 优化:预先绑定函数
|
|
187
|
-
function getRandomInt(min, max) {
|
|
188
|
-
// 优化:简化计算
|
|
189
|
-
return floor(random() * (max - min + 1)) + min
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// 优化:预先绑定generateIPSegment函数引用
|
|
193
|
-
function generateIPSegment() {
|
|
194
|
-
// 优化:内联常量
|
|
195
|
-
return getRandomInt(1, 255)
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// 进一步优化版本(如果需要更高性能):
|
|
199
|
-
/*
|
|
200
|
-
const cookieToJsonOptimized = (function() {
|
|
201
|
-
// 预编译trim函数
|
|
202
|
-
const trim = String.prototype.trim
|
|
203
|
-
|
|
204
|
-
return function(cookie) {
|
|
205
|
-
if (!cookie) return {}
|
|
206
|
-
|
|
207
|
-
const cookieArr = cookie.split(';')
|
|
208
|
-
const obj = {}
|
|
209
|
-
|
|
210
|
-
for (let i = 0, len = cookieArr.length; i < len; i++) {
|
|
211
|
-
const item = cookieArr[i]
|
|
212
|
-
const eqIndex = item.indexOf('=')
|
|
213
|
-
|
|
214
|
-
if (eqIndex > 0 && eqIndex < item.length - 1) {
|
|
215
|
-
const key = trim.call(item.substring(0, eqIndex))
|
|
216
|
-
const value = trim.call(item.substring(eqIndex + 1))
|
|
217
|
-
obj[key] = value
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
return obj
|
|
221
|
-
}
|
|
222
|
-
})()
|
|
223
|
-
*/
|
|
224
|
-
|
|
225
|
-
// 用于从cookie字符串中获取指定值的辅助函数
|
|
226
|
-
function getCookieValue(cookieStr, name) {
|
|
227
|
-
if (!cookieStr) return ''
|
|
228
|
-
|
|
229
|
-
const cookies = '; ' + cookieStr
|
|
230
|
-
const parts = cookies.split('; ' + name + '=')
|
|
231
|
-
if (parts.length === 2) return parts.pop().split(';').shift()
|
|
232
|
-
return ''
|
|
233
|
-
}
|
|
1
|
+
const logger = require('./logger')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
|
|
5
|
+
// IP地址转换函数
|
|
6
|
+
function ipToInt(ip) {
|
|
7
|
+
const parts = ip.split('.').map(Number)
|
|
8
|
+
const a = (parts[0] << 24) >>> 0
|
|
9
|
+
const b = parts[1] << 16
|
|
10
|
+
const c = parts[2] << 8
|
|
11
|
+
const d = parts[3]
|
|
12
|
+
return a + b + c + d
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function intToIp(int) {
|
|
16
|
+
return [
|
|
17
|
+
(int >>> 24) & 0xff,
|
|
18
|
+
(int >>> 16) & 0xff,
|
|
19
|
+
(int >>> 8) & 0xff,
|
|
20
|
+
int & 0xff,
|
|
21
|
+
].join('.')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 解析CIDR格式的IP段
|
|
25
|
+
function parseCIDR(cidr) {
|
|
26
|
+
const [ipStr, prefixLengthStr] = cidr.split('/')
|
|
27
|
+
const prefixLength = parseInt(prefixLengthStr, 10)
|
|
28
|
+
|
|
29
|
+
const ipInt = ipToInt(ipStr)
|
|
30
|
+
const mask = (0xffffffff << (32 - prefixLength)) >>> 0
|
|
31
|
+
const start = (ipInt & mask) >>> 0
|
|
32
|
+
const end = (start | (~mask >>> 0)) >>> 0
|
|
33
|
+
const count = end - start + 1
|
|
34
|
+
|
|
35
|
+
return { start, end, count, cidr }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 从china_ip_ranges.txt加载中国IP段(CIDR格式)
|
|
39
|
+
const chinaIPRanges = (function loadChinaIPRanges() {
|
|
40
|
+
try {
|
|
41
|
+
const filePath = path.join(__dirname, '../data/china_ip_ranges.txt')
|
|
42
|
+
const content = fs.readFileSync(filePath, 'utf-8')
|
|
43
|
+
const lines = content
|
|
44
|
+
.split('\n')
|
|
45
|
+
.filter((line) => line.trim() && !line.startsWith('#'))
|
|
46
|
+
|
|
47
|
+
const arr = []
|
|
48
|
+
let total = 0
|
|
49
|
+
|
|
50
|
+
for (let i = 0; i < lines.length; i++) {
|
|
51
|
+
const line = lines[i].trim()
|
|
52
|
+
if (!line) continue
|
|
53
|
+
|
|
54
|
+
const range = parseCIDR(line)
|
|
55
|
+
arr.push(range)
|
|
56
|
+
total += range.count
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 按IP段大小排序,提高随机选择效率
|
|
60
|
+
arr.sort((a, b) => b.count - a.count)
|
|
61
|
+
|
|
62
|
+
// attach total for convenience
|
|
63
|
+
arr.totalCount = total
|
|
64
|
+
|
|
65
|
+
logger.info(
|
|
66
|
+
`Loaded ${arr.length} Chinese IP ranges from china_ip_ranges.txt, total ${total} IPs`,
|
|
67
|
+
)
|
|
68
|
+
return arr
|
|
69
|
+
} catch (error) {
|
|
70
|
+
logger.error('Failed to load china_ip_ranges.txt:', error.message)
|
|
71
|
+
// 返回空数组,generateRandomChineseIP会使用兜底逻辑
|
|
72
|
+
return { totalCount: 0 }
|
|
73
|
+
}
|
|
74
|
+
})()
|
|
75
|
+
const floor = Math.floor
|
|
76
|
+
const random = Math.random
|
|
77
|
+
const keys = Object.keys
|
|
78
|
+
|
|
79
|
+
// 预编译encodeURIComponent以减少查找开销
|
|
80
|
+
const encode = encodeURIComponent
|
|
81
|
+
|
|
82
|
+
module.exports = {
|
|
83
|
+
toBoolean(val) {
|
|
84
|
+
if (typeof val === 'boolean') return val
|
|
85
|
+
if (val === '') return val
|
|
86
|
+
return val === 'true' || val == '1'
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
cookieToJson(cookie) {
|
|
90
|
+
if (!cookie) return {}
|
|
91
|
+
let cookieArr = cookie.split(';')
|
|
92
|
+
let obj = {}
|
|
93
|
+
|
|
94
|
+
// 优化:使用for循环替代forEach,性能更好
|
|
95
|
+
for (let i = 0, len = cookieArr.length; i < len; i++) {
|
|
96
|
+
let item = cookieArr[i]
|
|
97
|
+
let arr = item.split('=')
|
|
98
|
+
// 优化:使用严格等于
|
|
99
|
+
if (arr.length === 2) {
|
|
100
|
+
obj[arr[0].trim()] = arr[1].trim()
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return obj
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
cookieObjToString(cookie) {
|
|
107
|
+
// 优化:使用预绑定的keys函数和for循环
|
|
108
|
+
const cookieKeys = keys(cookie)
|
|
109
|
+
const result = []
|
|
110
|
+
|
|
111
|
+
// 优化:使用for循环和预分配数组
|
|
112
|
+
for (let i = 0, len = cookieKeys.length; i < len; i++) {
|
|
113
|
+
const key = cookieKeys[i]
|
|
114
|
+
result[i] = `${encode(key)}=${encode(cookie[key])}`
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return result.join('; ')
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
getRandom(num) {
|
|
121
|
+
// 优化:简化随机数生成逻辑
|
|
122
|
+
// 原逻辑看起来有问题,这里保持原意但优化性能
|
|
123
|
+
var randomValue = random()
|
|
124
|
+
var floorValue = floor(randomValue * 9 + 1)
|
|
125
|
+
var powValue = Math.pow(10, num - 1)
|
|
126
|
+
var randomNum = floor((randomValue + floorValue) * powValue)
|
|
127
|
+
return randomNum
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
generateRandomChineseIP() {
|
|
131
|
+
// 从预定义的中国 IP 段中按权重随机选择一个段,然后在该段内生成随机 IP
|
|
132
|
+
const total = chinaIPRanges.totalCount || 0
|
|
133
|
+
if (!total) {
|
|
134
|
+
// 兜底:回退到旧逻辑(随机 116.x 前缀)
|
|
135
|
+
const fallback = `116.${getRandomInt(25, 94)}.${generateIPSegment()}.${generateIPSegment()}`
|
|
136
|
+
logger.info('Generated Random Chinese IP (fallback):', fallback)
|
|
137
|
+
return fallback
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 选择一个全局随机偏移([0, total))
|
|
141
|
+
let offset = Math.floor(random() * total)
|
|
142
|
+
let chosen = null
|
|
143
|
+
for (let i = 0; i < chinaIPRanges.length; i++) {
|
|
144
|
+
const seg = chinaIPRanges[i]
|
|
145
|
+
if (offset < seg.count) {
|
|
146
|
+
chosen = seg
|
|
147
|
+
break
|
|
148
|
+
}
|
|
149
|
+
offset -= seg.count
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// 如果没有选中(理论上不应该发生),回退到最后一个段
|
|
153
|
+
if (!chosen) chosen = chinaIPRanges[chinaIPRanges.length - 1]
|
|
154
|
+
|
|
155
|
+
// 在段内随机生成一个 IP(使用段真实的数值范围)
|
|
156
|
+
const segSize = chosen.end - chosen.start + 1
|
|
157
|
+
const ipInt = chosen.start + Math.floor(random() * segSize)
|
|
158
|
+
const ip = intToIp(ipInt)
|
|
159
|
+
logger.info('Generated Random Chinese IP:', ip, 'from CIDR:', chosen.cidr)
|
|
160
|
+
return ip
|
|
161
|
+
},
|
|
162
|
+
// 生成chainId的函数
|
|
163
|
+
generateChainId(cookie) {
|
|
164
|
+
const version = 'v1'
|
|
165
|
+
const randomNum = Math.floor(Math.random() * 1e6)
|
|
166
|
+
const deviceId =
|
|
167
|
+
getCookieValue(cookie, 'sDeviceId') || 'unknown-' + randomNum
|
|
168
|
+
const platform = 'web'
|
|
169
|
+
const action = 'login'
|
|
170
|
+
const timestamp = Date.now()
|
|
171
|
+
|
|
172
|
+
return `${version}_${deviceId}_${platform}_${action}_${timestamp}`
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
generateDeviceId() {
|
|
176
|
+
const hexChars = '0123456789ABCDEF'
|
|
177
|
+
const chars = []
|
|
178
|
+
for (let i = 0; i < 52; i++) {
|
|
179
|
+
const randomIndex = Math.floor(Math.random() * hexChars.length)
|
|
180
|
+
chars.push(hexChars[randomIndex])
|
|
181
|
+
}
|
|
182
|
+
return chars.join('')
|
|
183
|
+
},
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 优化:预先绑定函数
|
|
187
|
+
function getRandomInt(min, max) {
|
|
188
|
+
// 优化:简化计算
|
|
189
|
+
return floor(random() * (max - min + 1)) + min
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 优化:预先绑定generateIPSegment函数引用
|
|
193
|
+
function generateIPSegment() {
|
|
194
|
+
// 优化:内联常量
|
|
195
|
+
return getRandomInt(1, 255)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 进一步优化版本(如果需要更高性能):
|
|
199
|
+
/*
|
|
200
|
+
const cookieToJsonOptimized = (function() {
|
|
201
|
+
// 预编译trim函数
|
|
202
|
+
const trim = String.prototype.trim
|
|
203
|
+
|
|
204
|
+
return function(cookie) {
|
|
205
|
+
if (!cookie) return {}
|
|
206
|
+
|
|
207
|
+
const cookieArr = cookie.split(';')
|
|
208
|
+
const obj = {}
|
|
209
|
+
|
|
210
|
+
for (let i = 0, len = cookieArr.length; i < len; i++) {
|
|
211
|
+
const item = cookieArr[i]
|
|
212
|
+
const eqIndex = item.indexOf('=')
|
|
213
|
+
|
|
214
|
+
if (eqIndex > 0 && eqIndex < item.length - 1) {
|
|
215
|
+
const key = trim.call(item.substring(0, eqIndex))
|
|
216
|
+
const value = trim.call(item.substring(eqIndex + 1))
|
|
217
|
+
obj[key] = value
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return obj
|
|
221
|
+
}
|
|
222
|
+
})()
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
// 用于从cookie字符串中获取指定值的辅助函数
|
|
226
|
+
function getCookieValue(cookieStr, name) {
|
|
227
|
+
if (!cookieStr) return ''
|
|
228
|
+
|
|
229
|
+
const cookies = '; ' + cookieStr
|
|
230
|
+
const parts = cookies.split('; ' + name + '=')
|
|
231
|
+
if (parts.length === 2) return parts.pop().split(';').shift()
|
|
232
|
+
return ''
|
|
233
|
+
}
|