fuo-qqmusic 1.0.7__py3-none-any.whl → 1.0.9__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/api.py CHANGED
@@ -287,6 +287,34 @@ class API(object):
287
287
  resp = requests.get(url, params=params)
288
288
  return resp.json()['data']
289
289
 
290
+ def playlist_remove_songs(self, playlist_id, song_id_list):
291
+ payload = {
292
+ 'req_0': {
293
+ 'method': 'DelSonglist',
294
+ 'module': 'music.musicasset.PlaylistDetailWrite',
295
+ 'param': {
296
+ 'dirId': playlist_id, # int
297
+ 'v_songInfo': [{'songId': int(song_id), 'songType': 0} for song_id in song_id_list]
298
+ }
299
+ }
300
+ }
301
+ js = self.rpc(payload)
302
+ return js['req_0']['code'] == 0
303
+
304
+ def playlist_add_songs(self, playlist_id, song_id_list):
305
+ payload = {
306
+ 'req_0': {
307
+ 'method': 'AddSonglist',
308
+ 'module': 'music.musicasset.PlaylistDetailWrite',
309
+ 'param': {
310
+ 'dirId': int(playlist_id), # int
311
+ 'v_songInfo': [{'songId': int(song_id), 'songType': 0} for song_id in song_id_list]
312
+ }
313
+ }
314
+ }
315
+ js = self.rpc(payload)
316
+ return js['req_0']['code'] == 0
317
+
290
318
  def playlist_detail(self, pid, offset=0, limit=50):
291
319
  url = api_base_url + '/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg'
292
320
  params = {
@@ -319,6 +347,7 @@ class API(object):
319
347
  resp = requests.get(url, params=params, headers=self._headers,
320
348
  cookies=self._cookies, timeout=self._timeout)
321
349
  js = resp.json()
350
+ logger.debug(f"user detail response: {js}")
322
351
  if js['code'] != 0:
323
352
  raise CodeShouldBe0(js)
324
353
  return js['data']
@@ -438,6 +467,7 @@ class API(object):
438
467
  def rpc(self, payload):
439
468
  if 'comm' not in payload:
440
469
  payload['comm'] = self.get_common_params()
470
+ logger.debug(f"rpc payload: {payload}")
441
471
  data_str = json.dumps(payload, ensure_ascii=False)
442
472
  params = {
443
473
  '_': int(round(time.time() * 1000)),
@@ -448,6 +478,7 @@ class API(object):
448
478
  resp = requests.get(url, params=params, headers=self._headers,
449
479
  cookies=self._cookies, timeout=self._timeout)
450
480
  js = resp.json()
481
+ logger.debug(f"rpc response json: {js}")
451
482
  CodeShouldBe0.check(js)
452
483
  return js
453
484
 
fuo_qqmusic/provider.py CHANGED
@@ -4,6 +4,7 @@ from feeluown.excs import ModelNotFound
4
4
  from feeluown.library import (
5
5
  AbstractProvider,
6
6
  BriefSongModel,
7
+ BriefPlaylistModel,
7
8
  PlaylistModel,
8
9
  Collection,
9
10
  CollectionType,
@@ -280,6 +281,22 @@ class QQProvider(AbstractProvider, ProviderV2):
280
281
  data = self.api.playlist_detail(int(identifier), limit=1000)
281
282
  return _deserialize(data, QQPlaylistSchema)
282
283
 
284
+ def playlist_add_song(self, playlist, song):
285
+ # FIXME: 目前 playlist 相关接口用的都是 diss 结构体,而这里需要一个 dirid。
286
+ # 平台方也提供了 dir 相关的接口,我大胆猜测,diss 是一套老接口。
287
+ playlist._cache.pop("songs", None)
288
+ dirid = self._get_dirid_by_playlist_id(playlist.identifier)
289
+ return self.api.playlist_add_songs(dirid, [song.identifier])
290
+
291
+ def playlist_remove_song(self, playlist, song):
292
+ playlist._cache.pop("songs", None)
293
+ dirid = self._get_dirid_by_playlist_id(playlist.identifier)
294
+ return self.api.playlist_remove_songs(dirid, [song.identifier])
295
+
296
+ def _get_dirid_by_playlist_id(self, playlist_id):
297
+ data = self.api.playlist_detail(int(playlist_id), limit=1)
298
+ return data["dirid"]
299
+
283
300
  def playlist_create_songs_rd(self, playlist):
284
301
  songs = self._model_cache_get_or_fetch(playlist, "songs")
285
302
  return create_reader(songs)
@@ -381,7 +398,13 @@ class QQProvider(AbstractProvider, ProviderV2):
381
398
  if user is None:
382
399
  return []
383
400
  playlists = self._model_cache_get_or_fetch(user, "playlists")
384
- return playlists
401
+ fav_pid = self._model_cache_get_or_fetch(user, "fav_pid")
402
+ my_love = BriefPlaylistModel(
403
+ source=SOURCE,
404
+ identifier=str(fav_pid),
405
+ name='我喜欢'
406
+ )
407
+ return [my_love] + playlists
385
408
 
386
409
  def current_user_fav_create_songs_rd(self):
387
410
  user = self.get_current_user()
@@ -415,6 +438,9 @@ class QQProvider(AbstractProvider, ProviderV2):
415
438
  return create_reader([])
416
439
  mid = self._model_cache_get_or_fetch(user, "mid")
417
440
  playlists = self.api.user_favorite_playlists(user.identifier, mid)
441
+ # HACK: 给 playlist 加一个 disstid 字段,这样可以兼容 QQPlaylistSchema
442
+ for playlist in playlists:
443
+ playlist["disstid"] = playlist["dissid"]
418
444
  return [_deserialize(playlist, QQPlaylistSchema) for playlist in playlists]
419
445
 
420
446
  def has_current_user(self):
@@ -1,16 +1,15 @@
1
- import json
2
1
  import logging
3
2
  import os
4
3
 
4
+ from PyQt5.QtWidgets import QMenu
5
+
5
6
  from feeluown.utils.dispatch import Signal
6
7
  from feeluown.utils.aio import run_fn
7
- from feeluown.consts import DATA_DIR
8
8
  from feeluown.gui.widgets.login import CookiesLoginDialog, InvalidCookies
9
9
  from feeluown.gui.provider_ui import AbstractProviderUi
10
10
  from feeluown.app.gui_app import GuiApp
11
11
 
12
12
  from .provider import provider
13
- from .excs import QQIOError
14
13
  from .login import read_cookies, write_cookies
15
14
 
16
15
  logger = logging.getLogger(__name__)
@@ -29,7 +28,7 @@ class ProviderUI(AbstractProviderUi):
29
28
  return os.path.join(os.path.dirname(__file__), 'assets', 'icon.svg')
30
29
 
31
30
  def login_or_go_home(self):
32
- if provider._user is None:
31
+ if not provider.has_current_user():
33
32
  # According to #14, we have two ways to login:
34
33
  # 1. the default way, as the code shows
35
34
  # 2. a way for VIP user(maybe):
@@ -39,8 +38,9 @@ class ProviderUI(AbstractProviderUi):
39
38
  #
40
39
  # - keys: ['skey']
41
40
  url = os.getenv('FUO_QQMUSIC_LOGIN_URL', 'https://y.qq.com')
42
- keys = os.getenv('FUO_QQMUSIC_LOGIN_COOKIE_KEYS', 'qqmusic_key').split(',')
43
- self._dialog = LoginDialog(url, keys)
41
+ keys_str = os.getenv('FUO_QQMUSIC_LOGIN_COOKIE_KEYS',
42
+ 'qqmusic_key,wxuin|qqmusic_key,uin')
43
+ self._dialog = LoginDialog(url, [keys.split(',') for keys in keys_str.split('|')])
44
44
  self._dialog.login_succeed.connect(self.on_login_succeed)
45
45
  self._dialog.show()
46
46
  self._dialog.autologin()
@@ -52,10 +52,19 @@ class ProviderUI(AbstractProviderUi):
52
52
  def login_event(self):
53
53
  return self._login_event
54
54
 
55
+ def context_menu_add_items(self, menu: QMenu):
56
+ action = menu.addAction('重新登录')
57
+ action.triggered.connect(self._re_login)
58
+
55
59
  def on_login_succeed(self):
56
60
  del self._dialog
57
61
  self.login_event.emit(self, 1)
58
62
 
63
+ def _re_login(self):
64
+ provider.auth(None)
65
+ self.login_or_go_home()
66
+
67
+
59
68
 
60
69
  class LoginDialog(CookiesLoginDialog):
61
70
 
fuo_qqmusic/schemas.py CHANGED
@@ -271,7 +271,7 @@ class QQAlbumSchema(Schema):
271
271
 
272
272
 
273
273
  class QQPlaylistSchema(Schema):
274
- identifier = fields.Int(required=True, data_key="dissid")
274
+ identifier = fields.Int(required=True, data_key="disstid")
275
275
  name = fields.Str(required=True, data_key="dissname")
276
276
  cover = fields.Str(required=True, data_key="logo")
277
277
  # songs field maybe null, though it can't be null in model
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fuo_qqmusic
3
- Version: 1.0.7
3
+ Version: 1.0.9
4
4
  Summary: feeluown qqmusic plugin
5
5
  Home-page: https://github.com/feeluown/feeluown-qqmusic
6
6
  Author: Cosven
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.7
13
13
  Classifier: Programming Language :: Python :: 3.8
14
14
  Classifier: Programming Language :: Python :: 3.9
15
15
  Classifier: Programming Language :: Python :: 3 :: Only
16
- Requires-Dist: feeluown>=4.1.3
16
+ Requires-Dist: feeluown>=4.1.13
17
17
  Requires-Dist: requests
18
18
  Requires-Dist: marshmallow<4.0.0,>=3.0
19
19
  Dynamic: author
@@ -0,0 +1,14 @@
1
+ fuo_qqmusic/__init__.py,sha256=YxZHAp5Qaye5B5V8GBPyxqnEUe-FcwUv6TiF_29qBEs,537
2
+ fuo_qqmusic/api.py,sha256=vzsPBhoivJs_LA_L8g7gR49o3jqtH_xpt3LInrBWBfI,28548
3
+ fuo_qqmusic/consts.py,sha256=9VFc9yE6z6c0IzK03PQTEO0JqgXi37RahEvZRP-A4Dk,185
4
+ fuo_qqmusic/excs.py,sha256=SBcER_wESjvui6a0Li1dX5utep4ouDS7HaTXqXPOQiA,160
5
+ fuo_qqmusic/login.py,sha256=zNPPncKl1Pr8uYBbLrdPlVJyKBsNfS2FotRfn9l3LEA,542
6
+ fuo_qqmusic/provider.py,sha256=S3gcS0od5nF-7_YLZ_VFGRSpycr4LMH31sexqDFvO_0,20270
7
+ fuo_qqmusic/provider_ui.py,sha256=MTjobwbkb3XGmZujE5XZBdRJEOsEeNPWnr55jIR5xg4,2662
8
+ fuo_qqmusic/schemas.py,sha256=bS6PgqAypCo-4I11_iVyu_ZgBXxmkoVQ9cRIQDymjlc,12129
9
+ fuo_qqmusic/assets/icon.svg,sha256=o48VTiHroJU6S2g8LbxfnK25G2QW3d1XtQZKoL3ZMGA,1216
10
+ fuo_qqmusic-1.0.9.dist-info/METADATA,sha256=ECCEvYtYEhlr8KF6cEn55z4xGIG3wk619gvxEMAwJiE,811
11
+ fuo_qqmusic-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
+ fuo_qqmusic-1.0.9.dist-info/entry_points.txt,sha256=XUL7UwcsLZEuEbBJIcsFemC3BiYb7dSTiXB9r6SJ5zY,39
13
+ fuo_qqmusic-1.0.9.dist-info/top_level.txt,sha256=Qn_g3dRwtoVZgVPZ9uRehspXi62T-E1x9_kLIdYFic4,12
14
+ fuo_qqmusic-1.0.9.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- fuo_qqmusic/__init__.py,sha256=YxZHAp5Qaye5B5V8GBPyxqnEUe-FcwUv6TiF_29qBEs,537
2
- fuo_qqmusic/api.py,sha256=yDT6iyq9ZdkRQkqDI96uFE3ctbh7HseUU8NVsuu3jBM,27381
3
- fuo_qqmusic/consts.py,sha256=9VFc9yE6z6c0IzK03PQTEO0JqgXi37RahEvZRP-A4Dk,185
4
- fuo_qqmusic/excs.py,sha256=SBcER_wESjvui6a0Li1dX5utep4ouDS7HaTXqXPOQiA,160
5
- fuo_qqmusic/login.py,sha256=zNPPncKl1Pr8uYBbLrdPlVJyKBsNfS2FotRfn9l3LEA,542
6
- fuo_qqmusic/provider.py,sha256=QUw5VvLaKodVVaKp2lPuSm8z1edXy5qUdmlzpE5Ldds,19025
7
- fuo_qqmusic/provider_ui.py,sha256=K70BjKvlx4h6gVYqeHOZhP68nnUWH2_mFbUK3jjvJ5U,2366
8
- fuo_qqmusic/schemas.py,sha256=Sbka-YuK3UTn26CbfwOb0ZfB6XmiJHW-ibCLThj49VQ,12128
9
- fuo_qqmusic/assets/icon.svg,sha256=o48VTiHroJU6S2g8LbxfnK25G2QW3d1XtQZKoL3ZMGA,1216
10
- fuo_qqmusic-1.0.7.dist-info/METADATA,sha256=U6tM7hrztEL-AjtHR_R2U-MkOrPauHrgc54LemZGj8g,810
11
- fuo_qqmusic-1.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
- fuo_qqmusic-1.0.7.dist-info/entry_points.txt,sha256=XUL7UwcsLZEuEbBJIcsFemC3BiYb7dSTiXB9r6SJ5zY,39
13
- fuo_qqmusic-1.0.7.dist-info/top_level.txt,sha256=Qn_g3dRwtoVZgVPZ9uRehspXi62T-E1x9_kLIdYFic4,12
14
- fuo_qqmusic-1.0.7.dist-info/RECORD,,