@neteasecloudmusicapienhanced/api 4.29.21 → 4.30.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.
@@ -4,36 +4,230 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>播客上传声音</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
16
+ min-height: 100vh;
17
+ background: #f5f5f5;
18
+ padding: 20px;
19
+ }
20
+
21
+ .container {
22
+ max-width: 900px;
23
+ margin: 0 auto;
24
+ background: white;
25
+ border-radius: 12px;
26
+ padding: 32px;
27
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
28
+ }
29
+
30
+ h1 {
31
+ font-size: 24px;
32
+ font-weight: 600;
33
+ color: #333;
34
+ margin-bottom: 24px;
35
+ }
36
+
37
+ .login-link {
38
+ display: block;
39
+ margin-bottom: 24px;
40
+ color: #666;
41
+ font-size: 14px;
42
+ text-decoration: none;
43
+ }
44
+
45
+ .login-link:hover {
46
+ color: #333;
47
+ text-decoration: underline;
48
+ }
49
+
50
+ .content {
51
+ display: flex;
52
+ gap: 24px;
53
+ flex-wrap: wrap;
54
+ }
55
+
56
+ .voice-list {
57
+ flex: 1;
58
+ min-width: 300px;
59
+ }
60
+
61
+ .voice-item {
62
+ padding: 12px 16px;
63
+ border: 1px solid #eee;
64
+ border-radius: 6px;
65
+ margin-bottom: 8px;
66
+ cursor: pointer;
67
+ transition: all 0.2s ease;
68
+ }
69
+
70
+ .voice-item:hover {
71
+ border-color: #333;
72
+ background: #f9f9f9;
73
+ }
74
+
75
+ .voice-item.active {
76
+ border-color: #333;
77
+ background: #f0f0f0;
78
+ }
79
+
80
+ .voice-header {
81
+ display: flex;
82
+ align-items: center;
83
+ gap: 12px;
84
+ }
85
+
86
+ .voice-cover {
87
+ width: 50px;
88
+ height: 50px;
89
+ border-radius: 4px;
90
+ object-fit: cover;
91
+ }
92
+
93
+ .voice-name {
94
+ font-size: 14px;
95
+ font-weight: 500;
96
+ color: #333;
97
+ }
98
+
99
+ .voice-tracks {
100
+ margin-top: 8px;
101
+ padding-left: 62px;
102
+ }
103
+
104
+ .voice-track {
105
+ font-size: 13px;
106
+ color: #666;
107
+ padding: 4px 0;
108
+ }
109
+
110
+ .upload-section {
111
+ flex: 1;
112
+ min-width: 300px;
113
+ }
114
+
115
+ .form-group {
116
+ margin-bottom: 16px;
117
+ }
118
+
119
+ label {
120
+ display: block;
121
+ font-size: 14px;
122
+ font-weight: 500;
123
+ color: #555;
124
+ margin-bottom: 8px;
125
+ }
126
+
127
+ input[type="text"], input[type="file"] {
128
+ width: 100%;
129
+ padding: 10px 14px;
130
+ border: 1px solid #ddd;
131
+ border-radius: 6px;
132
+ font-size: 14px;
133
+ outline: none;
134
+ }
135
+
136
+ input[type="text"]:focus {
137
+ border-color: #333;
138
+ }
139
+
140
+ .btn {
141
+ width: 100%;
142
+ padding: 12px;
143
+ background: #333;
144
+ color: white;
145
+ font-size: 15px;
146
+ font-weight: 500;
147
+ border: none;
148
+ border-radius: 6px;
149
+ cursor: pointer;
150
+ transition: background 0.2s ease;
151
+ }
152
+
153
+ .btn:hover {
154
+ background: #555;
155
+ }
156
+
157
+ .empty-state {
158
+ text-align: center;
159
+ padding: 40px 20px;
160
+ color: #999;
161
+ font-size: 14px;
162
+ }
163
+
164
+ .loading {
165
+ text-align: center;
166
+ padding: 20px;
167
+ color: #666;
168
+ }
169
+ </style>
7
170
  </head>
8
171
 
9
172
  <body>
10
- <div>
11
- <a href="/qrlogin-nocookie.html"> 如果没登录,请先登录 </a>
12
- </div>
13
- <div id="app">
14
- <ul>
15
- <li
16
- v-for="(item,index) in voicelist"
17
- @click="currentVoiceIndex=index"
18
- :class="{active:currentVoiceIndex===index}"
19
- >
20
- <img :src="item.coverUrl" style="width: 50px; width: 50px" />
21
- <ul>
22
- <li v-for="(item2,index) in item.voiceListData">
23
- {{item2.voiceName}}
24
- </li>
25
- </ul>
26
- {{item.voiceListName}}
27
- </li>
28
- </ul>
29
- <input v-model="songName" placeholder="请输入声音名称" />
30
- <input v-model="description" placeholder="请输入介绍" />
31
- <input type="file" name="songFile" />
32
- <button @click="submit">上传</button>
173
+ <div class="container">
174
+ <h1>播客上传声音</h1>
175
+ <a href="/qrlogin-nocookie.html" class="login-link">还没登录?点击登录</a>
176
+
177
+ <div class="content">
178
+ <div class="voice-list">
179
+ <h3 style="font-size: 16px; font-weight: 600; color: #333; margin-bottom: 16px;">选择播客列表</h3>
180
+ <div v-if="loading" class="loading">加载中...</div>
181
+ <div v-else-if="voicelist.length > 0">
182
+ <div
183
+ v-for="(item, index) in voicelist"
184
+ :key="index"
185
+ @click="currentVoiceIndex = index"
186
+ :class="{ active: currentVoiceIndex === index }"
187
+ class="voice-item"
188
+ >
189
+ <div class="voice-header">
190
+ <img :src="item.coverUrl" class="voice-cover" alt="cover" />
191
+ <span class="voice-name">{{ item.voiceListName }}</span>
192
+ </div>
193
+ <div class="voice-tracks" v-if="item.voiceListData">
194
+ <div
195
+ v-for="(item2, index2) in item.voiceListData"
196
+ :key="index2"
197
+ class="voice-track"
198
+ >
199
+ {{ item2.voiceName }}
200
+ </div>
201
+ </div>
202
+ </div>
203
+ </div>
204
+ <div v-else class="empty-state">暂无播客列表</div>
205
+ </div>
206
+
207
+ <div class="upload-section">
208
+ <h3 style="font-size: 16px; font-weight: 600; color: #333; margin-bottom: 16px;">上传声音</h3>
209
+ <div class="form-group">
210
+ <label for="songName">声音名称</label>
211
+ <input id="songName" v-model="songName" placeholder="请输入声音名称" />
212
+ </div>
213
+
214
+ <div class="form-group">
215
+ <label for="description">介绍</label>
216
+ <input id="description" v-model="description" placeholder="请输入介绍" />
217
+ </div>
218
+
219
+ <div class="form-group">
220
+ <label>选择文件</label>
221
+ <input type="file" name="songFile" accept="audio/*" />
222
+ </div>
223
+
224
+ <button class="btn" @click="submit">上传</button>
225
+ </div>
226
+ </div>
33
227
  </div>
34
228
 
35
229
  <script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
36
- <script src="https://fastly.jsdelivr.net/npm/vue"></script>
230
+ <script src="https://fastly.jsdelivr.net/npm/vue@3"></script>
37
231
  <script>
38
232
  Vue.createApp({
39
233
  data() {
@@ -43,6 +237,7 @@
43
237
  voicelist: [],
44
238
  cookieToken: '',
45
239
  currentVoiceIndex: 0,
240
+ loading: false,
46
241
  }
47
242
  },
48
243
  created() {
@@ -50,12 +245,6 @@
50
245
  },
51
246
  computed: {
52
247
  currentVoice() {
53
- // {
54
- // voiceListId: '',
55
- // coverImgId: '',
56
- // categoryId: '',
57
- // secondCategoryId: '',
58
- // }
59
248
  return this.voicelist[this.currentVoiceIndex]
60
249
  },
61
250
  },
@@ -63,27 +252,49 @@
63
252
  submit() {
64
253
  console.info('submit')
65
254
  const file = document.querySelector('input[type=file]').files[0]
255
+ if (!file) {
256
+ alert('请选择文件')
257
+ return
258
+ }
66
259
  this.upload(file)
67
260
  },
68
261
 
69
262
  async getData() {
70
- const res = await axios({
71
- url: `/voicelist/search?cookie=${localStorage.getItem('cookie')}`,
72
- })
263
+ this.loading = true
264
+ try {
265
+ const res = await axios({
266
+ url: `/voicelist/search?cookie=${localStorage.getItem('cookie')}`,
267
+ })
73
268
 
74
- console.info(res.data.data)
75
- this.voicelist = res.data.data.list
76
- this.voicelist.map(async (i) => {
77
- const res2 = await axios({
78
- url: `/voicelist/list?voiceListId=${i.voiceListId}&limit=5`,
269
+ console.info(res.data.data)
270
+ this.voicelist = res.data.data.list || []
271
+ this.voicelist.forEach(async (i) => {
272
+ try {
273
+ const res2 = await axios({
274
+ url: `/voicelist/list?voiceListId=${i.voiceListId}&limit=5`,
275
+ })
276
+ i.voiceListData = res2.data.data.list || []
277
+ console.info(res2)
278
+ } catch (err) {
279
+ console.error('获取播客详情失败:', err)
280
+ }
79
281
  })
80
- i.voiceListData = res2.data.data.list
81
- console.info(res2)
82
- })
282
+ } catch (err) {
283
+ console.error('获取播客列表失败:', err)
284
+ } finally {
285
+ this.loading = false
286
+ }
83
287
  },
288
+
84
289
  upload(file) {
290
+ if (!this.currentVoice) {
291
+ alert('请先选择播客列表')
292
+ return
293
+ }
294
+
85
295
  var formData = new FormData()
86
296
  formData.append('songFile', file)
297
+
87
298
  axios({
88
299
  method: 'post',
89
300
  url: `/voice/upload?time=${Date.now()}&cookie=${localStorage.getItem(
@@ -102,26 +313,14 @@
102
313
  })
103
314
  .then((res) => {
104
315
  alert(`${file.name} 上传成功`)
105
- if (currentIndx >= fileLength) {
106
- console.info('上传完毕')
107
- }
108
316
  })
109
- .catch(async (err) => {
110
- console.info(err)
317
+ .catch((err) => {
318
+ console.error('上传失败:', err)
319
+ alert('上传失败,请重试')
111
320
  })
112
321
  },
113
322
  },
114
- }).mount('#app')
323
+ }).mount('body')
115
324
  </script>
116
-
117
- <style>
118
- ul li {
119
- cursor: pointer;
120
- }
121
-
122
- ul li.active {
123
- color: red;
124
- }
125
- </style>
126
325
  </body>
127
326
  </html>
package/server.js CHANGED
@@ -235,7 +235,7 @@ async function consturctServer(moduleDefs) {
235
235
  if (ip == '::1') {
236
236
  ip = global.cnIp
237
237
  }
238
- logger.info('Requested from ip:', ip)
238
+ // logger.info('Requested from ip:', ip)
239
239
  obj[3] = {
240
240
  ...obj[3],
241
241
  ip,
@@ -166,4 +166,4 @@ class AdvancedClientSignGenerator {
166
166
  }
167
167
  }
168
168
 
169
- module.exports = AdvancedClientSignGenerator
169
+ module.exports = AdvancedClientSignGenerator
package/util/request.js CHANGED
@@ -194,11 +194,11 @@ const createRequest = (uri, data, options) => {
194
194
  // 根据加密方式处理
195
195
  switch (crypto) {
196
196
  case 'weapi':
197
- headers['Referer'] = DOMAIN
197
+ headers['Referer'] = options.domain || DOMAIN
198
198
  headers['User-Agent'] = options.ua || chooseUserAgent('weapi')
199
199
  data.csrf_token = csrfToken
200
200
  encryptData = encrypt.weapi(data)
201
- url = DOMAIN + '/weapi/' + uri.substr(5)
201
+ url = (options.domain || DOMAIN) + '/weapi/' + uri.substr(5)
202
202
  break
203
203
 
204
204
  case 'linuxapi':
@@ -206,10 +206,10 @@ const createRequest = (uri, data, options) => {
206
206
  options.ua || chooseUserAgent('linuxapi', 'linux')
207
207
  encryptData = encrypt.linuxapi({
208
208
  method: 'POST',
209
- url: DOMAIN + uri,
209
+ url: (options.domain || DOMAIN) + uri,
210
210
  params: data,
211
211
  })
212
- url = DOMAIN + '/api/linux/forward'
212
+ url = (options.domain || DOMAIN) + '/api/linux/forward'
213
213
  break
214
214
 
215
215
  case 'eapi':
@@ -249,9 +249,9 @@ const createRequest = (uri, data, options) => {
249
249
  : ENCRYPT_RESPONSE,
250
250
  )
251
251
  encryptData = encrypt.eapi(uri, data)
252
- url = API_DOMAIN + '/eapi/' + uri.substr(5)
252
+ url = (options.domain || API_DOMAIN) + '/eapi/' + uri.substr(5)
253
253
  } else if (crypto === 'api') {
254
- url = API_DOMAIN + uri
254
+ url = (options.domain || API_DOMAIN) + uri
255
255
  encryptData = data
256
256
  }
257
257
  break