fuo-qqmusic 1.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fuo-qqmusic might be problematic. Click here for more details.

fuo_qqmusic/schemas.py ADDED
@@ -0,0 +1,359 @@
1
+ import logging
2
+
3
+ from marshmallow import Schema, fields, post_load, EXCLUDE
4
+ from feeluown.library import (
5
+ SongModel,
6
+ BriefAlbumModel,
7
+ BriefArtistModel,
8
+ ArtistModel,
9
+ AlbumModel,
10
+ PlaylistModel,
11
+ BriefPlaylistModel,
12
+ UserModel,
13
+ VideoModel,
14
+ )
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class BaseSchema(Schema):
20
+ source = fields.Str(missing="qqmusic")
21
+
22
+ class Meta:
23
+ unknown = EXCLUDE
24
+
25
+
26
+ SOURCE = "qqmusic"
27
+ Schema = BaseSchema
28
+
29
+
30
+ def get_cover(mid, type_):
31
+ """获取专辑、歌手封面
32
+
33
+ :param type_: 专辑: 2,歌手:1
34
+ """
35
+ return f'http://y.gtimg.cn/music/photo_new/T00{type_}R800x800M000{mid}.jpg'
36
+
37
+
38
+ def create_model(model_cls, data, fields_to_cache=None):
39
+ """
40
+ maybe this function should be provided by feeluown
41
+
42
+ :param fields_to_cache: list of fields name to be cached
43
+ """
44
+ if fields_to_cache is not None:
45
+ cache_data = {}
46
+ for field in fields_to_cache:
47
+ value = data.pop(field)
48
+ if value is not None:
49
+ cache_data[field] = value
50
+ model = model_cls(**data)
51
+ for field, value in cache_data.items():
52
+ model.cache_set(field, value)
53
+ else:
54
+ model = model_cls(**data)
55
+ return model
56
+
57
+
58
+ def pop_album_from_data(data):
59
+ album_id = data.pop("albumid")
60
+ album_mid = data.pop("albummid")
61
+ album_name = data.pop("albumname")
62
+ album_data = {
63
+ "identifier": album_id,
64
+ "source": SOURCE,
65
+ "mid": album_mid,
66
+ "name": album_name,
67
+ }
68
+ return create_model(BriefAlbumModel, album_data, ["mid"])
69
+
70
+
71
+ class _SongArtistSchema(Schema):
72
+ identifier = fields.Int(data_key="id", required=True)
73
+ name = fields.Str(data_key="name", required=True)
74
+
75
+ @post_load
76
+ def create_model(self, data, **kwargs):
77
+ return BriefArtistModel(**data)
78
+
79
+
80
+ class _SongAlbumSchema(Schema):
81
+ identifier = fields.Int(data_key="id", required=True)
82
+ name = fields.Str(data_key="name", required=True)
83
+
84
+ @post_load
85
+ def create_model(self, data, **kwargs):
86
+ return BriefAlbumModel(**data)
87
+
88
+
89
+ class QQSongSchema(Schema):
90
+ identifier = fields.Int(data_key="id", required=True)
91
+ mid = fields.Str(data_key="mid", required=True)
92
+ duration = fields.Float(data_key="interval", required=True)
93
+ title = fields.Str(data_key="title", required=True)
94
+ artists = fields.List(fields.Nested("_SongArtistSchema"), data_key="singer")
95
+ album = fields.Nested("_SongAlbumSchema", required=True)
96
+ files = fields.Dict(data_key="file", missing={})
97
+ mv = fields.Dict(required=True)
98
+
99
+ @post_load
100
+ def create_model(self, data, **kwargs):
101
+ song = SongModel(
102
+ identifier=data["identifier"],
103
+ source=SOURCE,
104
+ duration=data["duration"] * 1000,
105
+ title=data["title"],
106
+ artists=data.get("artists", []),
107
+ album=data["album"],
108
+ )
109
+ song.cache_set("mid", data["mid"])
110
+ song.cache_set("media_id", data["files"]["media_mid"])
111
+ song.cache_set("mv_id", data["mv"].get("vid", 0))
112
+ # 记录有哪些资源文件, 没有权限的用户依然获取不到
113
+ quality_suffix = []
114
+ files = data["files"]
115
+ if files.get("size_flac"): # has key and value is not empty
116
+ quality_suffix.append(("shq", "F000", 800, "flac"))
117
+ elif files.get("size_ape"):
118
+ quality_suffix.append(("shq", "A000", 800, "ape"))
119
+ if files.get("size_320") or files.get("size_320mp3"):
120
+ quality_suffix.append(("hq", "M800", 320, "ape"))
121
+ if files.get("size_aac") or files.get("size_192aac"):
122
+ quality_suffix.append(("sq", "C600", 192, "m4a"))
123
+ if files.get("size_128") or files.get("size_128mp3"):
124
+ quality_suffix.append(("lq", "M500", 128, "mp3"))
125
+ song.cache_set("quality_suffix", quality_suffix)
126
+ return song
127
+
128
+
129
+ class _ArtistSongSchema(Schema):
130
+ value = fields.Nested(QQSongSchema, data_key="songInfo")
131
+
132
+ @post_load
133
+ def create_model(self, data, **kwargs):
134
+ return data["value"]
135
+
136
+
137
+ class _BriefArtistSchema(Schema):
138
+ identifier = fields.Int(data_key="singerID", required=True)
139
+ mid = fields.Str(data_key="singerMID", required=True)
140
+ name = fields.Str(data_key="singerName", required=True)
141
+
142
+ @post_load
143
+ def create_model(self, data, **kwargs):
144
+ return create_model(BriefArtistModel, data, ["mid"])
145
+
146
+
147
+ class SearchArtistSchema(_BriefArtistSchema):
148
+ pic_url = fields.Str(data_key="singerPic", required=True)
149
+
150
+ @post_load
151
+ def create_model(self, data, **kwargs):
152
+ data['hot_songs'] = []
153
+ data['description'] = ''
154
+ data['aliases'] = []
155
+ return create_model(ArtistModel, data, ["mid"])
156
+
157
+
158
+ class _BriefAlbumSchema(Schema):
159
+ identifier = fields.Int(data_key="albumID", required=True)
160
+ mid = fields.Str(data_key="albumMID", required=True)
161
+ name = fields.Str(data_key="albumName", required=True)
162
+
163
+ @post_load
164
+ def create_model(self, data, **kwargs):
165
+ return create_model(BriefAlbumModel, data, ["mid"])
166
+
167
+
168
+ class SearchAlbumSchema(_BriefAlbumSchema):
169
+ cover = fields.Str(data_key="albumPic", required=True)
170
+ released = fields.Str(data_key="publicTime", required=True)
171
+ song_count = fields.Int(required=True)
172
+ artists = fields.List(fields.Nested(_SongArtistSchema),
173
+ data_key="singer_list",
174
+ required=True)
175
+ @post_load
176
+ def create_model(self, data, **kwargs):
177
+ data['description'] = ''
178
+ data['songs'] = []
179
+ return create_model(AlbumModel, data, ['mid'])
180
+
181
+
182
+ class _BriefPlaylistSchema(Schema):
183
+ identifier = fields.Int(data_key="dissid", required=True)
184
+ name = fields.Str(data_key="dissname", required=True)
185
+ cover = fields.Str(data_key="imgurl", required=True)
186
+
187
+ @post_load
188
+ def create_model(self, data, **kwargs):
189
+ data['description'] = ''
190
+ return create_model(PlaylistModel, **data)
191
+
192
+
193
+ class PlaylistUserSchema(Schema):
194
+ identifier = fields.Str(data_key="creator_uin", required=True)
195
+ mid = fields.Str(data_key="encrypt_uin", required=True)
196
+ name = fields.Str(required=True)
197
+ avatar_url = fields.Str(required=True, data_key="avatarUrl")
198
+
199
+ @post_load
200
+ def create_model(self, data, **kwargs):
201
+ return create_model(UserModel, data, ['mid'])
202
+
203
+
204
+ class SearchPlaylistSchema(_BriefPlaylistSchema):
205
+ creator = fields.Nested("PlaylistUserSchema", required=True)
206
+ description = fields.Str(data_key="introduction", required=True)
207
+ play_count = fields.Int(data_key="listennum", required=True)
208
+
209
+ @post_load
210
+ def create_model(self, data, **kwargs):
211
+ return create_model(PlaylistModel, data)
212
+
213
+
214
+ class QQArtistSchema(Schema):
215
+ """歌手详情 Schema、歌曲歌手简要信息 Schema"""
216
+
217
+ identifier = fields.Int(data_key="singer_id", required=True)
218
+ mid = fields.Str(data_key="singer_mid", required=True)
219
+ name = fields.Str(data_key="singer_name", required=True)
220
+
221
+ description = fields.Str(data_key="SingerDesc", missing="")
222
+ hot_songs = fields.List(
223
+ fields.Nested(_ArtistSongSchema), data_key="list", missing=list
224
+ )
225
+
226
+ @post_load
227
+ def create_model(self, data, **kwargs):
228
+ data["pic_url"] = get_cover(data['mid'], 1)
229
+ data["aliases"] = []
230
+ return create_model(ArtistModel, data, ["mid"])
231
+
232
+
233
+ class QQAlbumSchema(Schema):
234
+ album_info = fields.Dict(data_key="getAlbumInfo", required=True)
235
+ album_desc = fields.Dict(data_key="getAlbumDesc", required=True)
236
+ # 非中文专辑会把专辑的中文翻译加进去, 为保持前后一致此外去掉翻译文字
237
+ artist_info = fields.Dict(data_key="getSingerInfo", required=True)
238
+
239
+ # 有的专辑歌曲列表为 null,比如:fuo://qqmusic/albums/8623
240
+ songs = fields.List(
241
+ fields.Nested(QQSongSchema), data_key="getSongInfo", allow_none=True
242
+ )
243
+
244
+ @post_load
245
+ def create_model(self, data, **kwargs):
246
+ singer_name = data["artist_info"]["Fsinger_name"]
247
+ artist = BriefArtistModel(
248
+ identifier=data["artist_info"]["Fsinger_id"],
249
+ source=SOURCE,
250
+ # split('/'):有的专辑有个多歌手,只有第一个才是正确的专辑艺人
251
+ # split('('):有的非中文歌手拥有别名在括号里
252
+ name=singer_name.split("/")[0].split("(")[0].strip(),
253
+ )
254
+ # 非中文专辑会把专辑的中文翻译加进去, 为保持前后一致此外去掉括号里的中文翻译
255
+ if data["songs"]:
256
+ album_name = data["songs"][0].album.name
257
+ else:
258
+ album_name = data["album_info"]["Falbum_name"]
259
+ mid = data["album_info"]["Falbum_mid"]
260
+ album = AlbumModel(
261
+ identifier=data["album_info"]["Falbum_id"],
262
+ source=SOURCE,
263
+ name=album_name,
264
+ description=data["album_desc"]["Falbum_desc"],
265
+ songs=data["songs"] or [],
266
+ artists=[artist],
267
+ cover=get_cover(mid, 2)
268
+ )
269
+ album.cache_set("mid", mid)
270
+ return album
271
+
272
+
273
+ class QQPlaylistSchema(Schema):
274
+ identifier = fields.Int(required=True, data_key="dissid")
275
+ name = fields.Str(required=True, data_key="dissname")
276
+ cover = fields.Str(required=True, data_key="logo")
277
+ # songs field maybe null, though it can't be null in model
278
+ songs = fields.List(
279
+ fields.Nested(QQSongSchema), data_key="songlist", allow_none=True
280
+ )
281
+
282
+ @post_load
283
+ def create_model(self, data, **kwargs):
284
+ fields_to_cache = []
285
+ if data.get('songs') is not None:
286
+ fields_to_cache = ['songs']
287
+ data['description'] = ''
288
+ return create_model(PlaylistModel, data, fields_to_cache)
289
+
290
+
291
+ class _UserArtistSchema(Schema):
292
+ other_infos = fields.Dict(data_key="OtherInfo", required=True)
293
+ mid = fields.Str(data_key="MID", required=True)
294
+ name = fields.Str(data_key="Name", required=True)
295
+
296
+ @post_load
297
+ def create_model(self, data, **kwargs):
298
+ data["identifier"] = data.pop("other_infos")["SingerID"]
299
+ return create_model(BriefArtistModel, data, ['mid'])
300
+
301
+
302
+ class _UserAlbumSchema(Schema):
303
+ identifier = fields.Int(data_key="albumid", required=True)
304
+ mid = fields.Str(data_key="albummid", required=True)
305
+ name = fields.Str(data_key="albumname", required=True)
306
+
307
+ @post_load
308
+ def create_model(self, data, **kwargs):
309
+ return create_model(BriefAlbumModel, data, ["mid"])
310
+
311
+
312
+ class _UserPlaylistSchema(Schema):
313
+ identifier = fields.Int(data_key="dissid", required=True)
314
+ name = fields.Str(data_key="title", required=True)
315
+
316
+ @post_load
317
+ def create_model(self, data, **kwargs):
318
+ return create_model(BriefPlaylistModel, data)
319
+
320
+
321
+ class QQUserSchema(Schema):
322
+ creator = fields.Dict(required=True)
323
+ mydiss = fields.Dict(required=True)
324
+
325
+ @post_load
326
+ def create_model(self, data, **kwargs):
327
+ creator = data["creator"]
328
+ playlists_data = data["mydiss"]["list"]
329
+ schema = _UserPlaylistSchema()
330
+ playlists = []
331
+ for each in playlists_data:
332
+ playlist = schema.load(each)
333
+ playlists.append(playlist)
334
+ data = dict(
335
+ identifier=creator["uin"],
336
+ source=SOURCE,
337
+ mid=creator["encrypt_uin"],
338
+ name=creator["nick"],
339
+ fav_pid=creator["fav_pid"],
340
+ avatar_url=creator["headpic"],
341
+ playlists=playlists,
342
+ )
343
+ return create_model(UserModel, data, ['mid', 'fav_pid', 'playlists'])
344
+
345
+
346
+ class SearchMVSchema(Schema):
347
+ # 使用 mv_id 字段的话,目前拿不到播放 url,用 v_id 比较合适
348
+ identifier = fields.Str(data_key="v_id", required=True)
349
+ title = fields.Str(data_key="mv_name", required=True)
350
+ artists = fields.List(fields.Nested("_SongArtistSchema"),
351
+ data_key="singer_list",
352
+ required=True)
353
+ duration = fields.Int(required=True)
354
+ cover = fields.Str(data_key="mv_pic_url", required=True)
355
+ play_count = fields.Int(required=True)
356
+
357
+ @post_load
358
+ def create_model(self, data, **kwargs):
359
+ return create_model(VideoModel, data)
@@ -0,0 +1,19 @@
1
+ Metadata-Version: 2.1
2
+ Name: fuo_qqmusic
3
+ Version: 1.0.5
4
+ Summary: feeluown qqmusic plugin
5
+ Home-page: https://github.com/feeluown/feeluown-qqmusic
6
+ Author: Cosven
7
+ Author-email: yinshaowen241@gmail.com
8
+ Keywords: feeluown,plugin,qqmusic
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Programming Language :: Python :: 3.5
11
+ Classifier: Programming Language :: Python :: 3.6
12
+ Classifier: Programming Language :: Python :: 3.7
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Requires-Dist: feeluown (>=4.1.3)
17
+ Requires-Dist: requests
18
+ Requires-Dist: marshmallow (>=3.0)
19
+
@@ -0,0 +1,13 @@
1
+ fuo_qqmusic/__init__.py,sha256=YxZHAp5Qaye5B5V8GBPyxqnEUe-FcwUv6TiF_29qBEs,537
2
+ fuo_qqmusic/api.py,sha256=w_anRMxAqL9FaMJVRmZ3A_uV4rzr7_S_1xMjZf-uovY,23597
3
+ fuo_qqmusic/consts.py,sha256=9VFc9yE6z6c0IzK03PQTEO0JqgXi37RahEvZRP-A4Dk,185
4
+ fuo_qqmusic/excs.py,sha256=SBcER_wESjvui6a0Li1dX5utep4ouDS7HaTXqXPOQiA,160
5
+ fuo_qqmusic/provider.py,sha256=JmQtjPVPsaZ1n12phJDd_Ll3Y83RfaHb5S6i0d1xrjw,15669
6
+ fuo_qqmusic/provider_ui.py,sha256=UKmzK6SImyWZe_wtkjcfXH_gy2XXbcnnI4Er0fICM6I,3197
7
+ fuo_qqmusic/schemas.py,sha256=Sbka-YuK3UTn26CbfwOb0ZfB6XmiJHW-ibCLThj49VQ,12128
8
+ fuo_qqmusic/assets/icon.svg,sha256=o48VTiHroJU6S2g8LbxfnK25G2QW3d1XtQZKoL3ZMGA,1216
9
+ fuo_qqmusic-1.0.5.dist-info/METADATA,sha256=EgB-48xvBBqTnxxGYFAjK3rqBpaYK6hS5Csvdx5ubAM,675
10
+ fuo_qqmusic-1.0.5.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
11
+ fuo_qqmusic-1.0.5.dist-info/entry_points.txt,sha256=XUL7UwcsLZEuEbBJIcsFemC3BiYb7dSTiXB9r6SJ5zY,39
12
+ fuo_qqmusic-1.0.5.dist-info/top_level.txt,sha256=Qn_g3dRwtoVZgVPZ9uRehspXi62T-E1x9_kLIdYFic4,12
13
+ fuo_qqmusic-1.0.5.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (72.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [fuo.plugins_v1]
2
+ qqmusic = fuo_qqmusic
@@ -0,0 +1 @@
1
+ fuo_qqmusic