spotify-cmd 0.1.2__tar.gz → 0.1.4__tar.gz
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.
- {spotify-cmd-0.1.2/spotify_cmd.egg-info → spotify-cmd-0.1.4}/PKG-INFO +6 -5
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/README.md +4 -3
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/setup.py +2 -2
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4/spotify_cmd.egg-info}/PKG-INFO +6 -5
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/spotify_cmd.egg-info/SOURCES.txt +10 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/spotify_cmd.egg-info/requires.txt +1 -1
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_client/client.py +2 -30
- spotify-cmd-0.1.4/src/spotify_cmd_client/data_presenter.py +59 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_client/main.py +12 -2
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/main.py +2 -2
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/__init__.py +1 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/get_library_albums.py +18 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/get_library_playlists.py +16 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/presenters/__init__.py +7 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/presenters/albums_presenter.py +14 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/presenters/artists_presenter.py +14 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/presenters/collection_presenter.py +12 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/presenters/episodes_presenter.py +14 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/presenters/playlists_presenter.py +14 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/presenters/shows_presenter.py +14 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/presenters/tracks_presenter.py +14 -0
- spotify-cmd-0.1.4/src/spotify_cmd_daemon/operations/search.py +22 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/spotify_controller.py +9 -0
- spotify-cmd-0.1.2/src/spotify_cmd_daemon/operations/get_library_albums.py +0 -22
- spotify-cmd-0.1.2/src/spotify_cmd_daemon/operations/get_library_playlists.py +0 -21
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/LICENSE.md +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/setup.cfg +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/spotify_cmd.egg-info/dependency_links.txt +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/spotify_cmd.egg-info/entry_points.txt +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/spotify_cmd.egg-info/top_level.txt +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/__init__.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/common/__init__.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/common/config.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/common/socket_data_handler.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/common/socket_message.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_client/__init__.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/__init__.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/helpers/__init__.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/helpers/check_resource_existence.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/helpers/get_album.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/helpers/get_playlist.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/helpers/get_resource_from_library.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/helpers/get_resource_uri.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/next_track.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/pause_playback.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/previous_track.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/resume_playback.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/set_shuffle.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/set_volume.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/start_playback.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/validators/__init__.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/validators/validate_resource_uri.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/validators/validate_volume_percent.py +0 -0
- {spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/socket_server.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: spotify-cmd
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Command line Spotify client
|
|
5
5
|
Home-page: https://github.com/ciembor/spotify-cmd
|
|
6
6
|
Author: Maciej Ciemborowicz
|
|
@@ -25,11 +25,11 @@ License-File: LICENSE.md
|
|
|
25
25
|
Requires-Dist: argparse==1.4.0
|
|
26
26
|
Requires-Dist: configparser==5.0.2
|
|
27
27
|
Requires-Dist: spotipy==2.23.0
|
|
28
|
-
Requires-Dist: daemon==1
|
|
28
|
+
Requires-Dist: python-daemon==3.0.1
|
|
29
29
|
|
|
30
|
-
# 💚 spotify-cmd v0.1.
|
|
30
|
+
# 💚 spotify-cmd v0.1.3
|
|
31
31
|
|
|
32
|
-
`spotify-cmd` is a Spotify client that allows controlling the playback of albums and playlists from a
|
|
32
|
+
`spotify-cmd` is a Spotify client that allows controlling the playback of **albums and playlists from a user's library** (based on names or Spotify URIs) and individual tracks (based solely on Spotify URIs). The application is intended for use with [spotifyd](https://github.com/Spotifyd/spotifyd), but it works with any Spotify-enabled device.
|
|
33
33
|
|
|
34
34
|
## Installation
|
|
35
35
|
|
|
@@ -71,6 +71,7 @@ socket_buffer_size = 1024
|
|
|
71
71
|
* `play`, `pause`, `next`, `previous`: Controls playback.
|
|
72
72
|
* `set shuffle <on|off>`: Toggles shuffle mode.
|
|
73
73
|
* `set volume <0-100>`: Sets the volume level.
|
|
74
|
+
* `find <search_type> <query>`: Searches for items on Spotify. Acceptable search types are `album`, `artist`, `playlist`, `track`, `episode`, and `show`.
|
|
74
75
|
|
|
75
76
|
## Output Format
|
|
76
77
|
|
|
@@ -99,7 +100,7 @@ Developers can create interfaces for `spotify-cmd-daemon` using `/tmp/spotify-cm
|
|
|
99
100
|
* Displaying tracks from specific albums or playlists.
|
|
100
101
|
* MPRIS D-Bus interface support to reduce server queries.
|
|
101
102
|
* `spotify-cmd-ui`: A ncurses-based UI for track display and control, working with the same daemon.
|
|
102
|
-
* Search functionality.
|
|
103
|
+
* ~~Search functionality.~~ [Done in 0.1.4]
|
|
103
104
|
* Support for other resource types like artists.
|
|
104
105
|
|
|
105
106
|
## License
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# 💚 spotify-cmd v0.1.
|
|
1
|
+
# 💚 spotify-cmd v0.1.3
|
|
2
2
|
|
|
3
|
-
`spotify-cmd` is a Spotify client that allows controlling the playback of albums and playlists from a
|
|
3
|
+
`spotify-cmd` is a Spotify client that allows controlling the playback of **albums and playlists from a user's library** (based on names or Spotify URIs) and individual tracks (based solely on Spotify URIs). The application is intended for use with [spotifyd](https://github.com/Spotifyd/spotifyd), but it works with any Spotify-enabled device.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -42,6 +42,7 @@ socket_buffer_size = 1024
|
|
|
42
42
|
* `play`, `pause`, `next`, `previous`: Controls playback.
|
|
43
43
|
* `set shuffle <on|off>`: Toggles shuffle mode.
|
|
44
44
|
* `set volume <0-100>`: Sets the volume level.
|
|
45
|
+
* `find <search_type> <query>`: Searches for items on Spotify. Acceptable search types are `album`, `artist`, `playlist`, `track`, `episode`, and `show`.
|
|
45
46
|
|
|
46
47
|
## Output Format
|
|
47
48
|
|
|
@@ -70,7 +71,7 @@ Developers can create interfaces for `spotify-cmd-daemon` using `/tmp/spotify-cm
|
|
|
70
71
|
* Displaying tracks from specific albums or playlists.
|
|
71
72
|
* MPRIS D-Bus interface support to reduce server queries.
|
|
72
73
|
* `spotify-cmd-ui`: A ncurses-based UI for track display and control, working with the same daemon.
|
|
73
|
-
* Search functionality.
|
|
74
|
+
* ~~Search functionality.~~ [Done in 0.1.4]
|
|
74
75
|
* Support for other resource types like artists.
|
|
75
76
|
|
|
76
77
|
## License
|
|
@@ -6,13 +6,13 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
6
6
|
|
|
7
7
|
setup(
|
|
8
8
|
name="spotify-cmd",
|
|
9
|
-
version="0.1.
|
|
9
|
+
version="0.1.4",
|
|
10
10
|
packages=find_packages(),
|
|
11
11
|
install_requires=[
|
|
12
12
|
'argparse==1.4.0',
|
|
13
13
|
'configparser==5.0.2',
|
|
14
14
|
'spotipy==2.23.0',
|
|
15
|
-
'daemon==1
|
|
15
|
+
'python-daemon==3.0.1'
|
|
16
16
|
],
|
|
17
17
|
entry_points={
|
|
18
18
|
'console_scripts': [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: spotify-cmd
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Command line Spotify client
|
|
5
5
|
Home-page: https://github.com/ciembor/spotify-cmd
|
|
6
6
|
Author: Maciej Ciemborowicz
|
|
@@ -25,11 +25,11 @@ License-File: LICENSE.md
|
|
|
25
25
|
Requires-Dist: argparse==1.4.0
|
|
26
26
|
Requires-Dist: configparser==5.0.2
|
|
27
27
|
Requires-Dist: spotipy==2.23.0
|
|
28
|
-
Requires-Dist: daemon==1
|
|
28
|
+
Requires-Dist: python-daemon==3.0.1
|
|
29
29
|
|
|
30
|
-
# 💚 spotify-cmd v0.1.
|
|
30
|
+
# 💚 spotify-cmd v0.1.3
|
|
31
31
|
|
|
32
|
-
`spotify-cmd` is a Spotify client that allows controlling the playback of albums and playlists from a
|
|
32
|
+
`spotify-cmd` is a Spotify client that allows controlling the playback of **albums and playlists from a user's library** (based on names or Spotify URIs) and individual tracks (based solely on Spotify URIs). The application is intended for use with [spotifyd](https://github.com/Spotifyd/spotifyd), but it works with any Spotify-enabled device.
|
|
33
33
|
|
|
34
34
|
## Installation
|
|
35
35
|
|
|
@@ -71,6 +71,7 @@ socket_buffer_size = 1024
|
|
|
71
71
|
* `play`, `pause`, `next`, `previous`: Controls playback.
|
|
72
72
|
* `set shuffle <on|off>`: Toggles shuffle mode.
|
|
73
73
|
* `set volume <0-100>`: Sets the volume level.
|
|
74
|
+
* `find <search_type> <query>`: Searches for items on Spotify. Acceptable search types are `album`, `artist`, `playlist`, `track`, `episode`, and `show`.
|
|
74
75
|
|
|
75
76
|
## Output Format
|
|
76
77
|
|
|
@@ -99,7 +100,7 @@ Developers can create interfaces for `spotify-cmd-daemon` using `/tmp/spotify-cm
|
|
|
99
100
|
* Displaying tracks from specific albums or playlists.
|
|
100
101
|
* MPRIS D-Bus interface support to reduce server queries.
|
|
101
102
|
* `spotify-cmd-ui`: A ncurses-based UI for track display and control, working with the same daemon.
|
|
102
|
-
* Search functionality.
|
|
103
|
+
* ~~Search functionality.~~ [Done in 0.1.4]
|
|
103
104
|
* Support for other resource types like artists.
|
|
104
105
|
|
|
105
106
|
## License
|
|
@@ -14,6 +14,7 @@ src/common/socket_data_handler.py
|
|
|
14
14
|
src/common/socket_message.py
|
|
15
15
|
src/spotify_cmd_client/__init__.py
|
|
16
16
|
src/spotify_cmd_client/client.py
|
|
17
|
+
src/spotify_cmd_client/data_presenter.py
|
|
17
18
|
src/spotify_cmd_client/main.py
|
|
18
19
|
src/spotify_cmd_daemon/__init__.py
|
|
19
20
|
src/spotify_cmd_daemon/main.py
|
|
@@ -26,6 +27,7 @@ src/spotify_cmd_daemon/operations/next_track.py
|
|
|
26
27
|
src/spotify_cmd_daemon/operations/pause_playback.py
|
|
27
28
|
src/spotify_cmd_daemon/operations/previous_track.py
|
|
28
29
|
src/spotify_cmd_daemon/operations/resume_playback.py
|
|
30
|
+
src/spotify_cmd_daemon/operations/search.py
|
|
29
31
|
src/spotify_cmd_daemon/operations/set_shuffle.py
|
|
30
32
|
src/spotify_cmd_daemon/operations/set_volume.py
|
|
31
33
|
src/spotify_cmd_daemon/operations/start_playback.py
|
|
@@ -35,6 +37,14 @@ src/spotify_cmd_daemon/operations/helpers/get_album.py
|
|
|
35
37
|
src/spotify_cmd_daemon/operations/helpers/get_playlist.py
|
|
36
38
|
src/spotify_cmd_daemon/operations/helpers/get_resource_from_library.py
|
|
37
39
|
src/spotify_cmd_daemon/operations/helpers/get_resource_uri.py
|
|
40
|
+
src/spotify_cmd_daemon/operations/presenters/__init__.py
|
|
41
|
+
src/spotify_cmd_daemon/operations/presenters/albums_presenter.py
|
|
42
|
+
src/spotify_cmd_daemon/operations/presenters/artists_presenter.py
|
|
43
|
+
src/spotify_cmd_daemon/operations/presenters/collection_presenter.py
|
|
44
|
+
src/spotify_cmd_daemon/operations/presenters/episodes_presenter.py
|
|
45
|
+
src/spotify_cmd_daemon/operations/presenters/playlists_presenter.py
|
|
46
|
+
src/spotify_cmd_daemon/operations/presenters/shows_presenter.py
|
|
47
|
+
src/spotify_cmd_daemon/operations/presenters/tracks_presenter.py
|
|
38
48
|
src/spotify_cmd_daemon/operations/validators/__init__.py
|
|
39
49
|
src/spotify_cmd_daemon/operations/validators/validate_resource_uri.py
|
|
40
50
|
src/spotify_cmd_daemon/operations/validators/validate_volume_percent.py
|
|
@@ -9,6 +9,7 @@ import json
|
|
|
9
9
|
from socket_message import SocketMessage
|
|
10
10
|
from socket_data_handler import SocketDataHandler
|
|
11
11
|
from config import Config
|
|
12
|
+
from .data_presenter import DataPresenter
|
|
12
13
|
|
|
13
14
|
class Client:
|
|
14
15
|
def __init__(self):
|
|
@@ -43,38 +44,9 @@ class Client:
|
|
|
43
44
|
formatted_response = json.dumps(response_dict['payload'], indent=2)
|
|
44
45
|
print(formatted_response)
|
|
45
46
|
else:
|
|
46
|
-
|
|
47
|
+
DataPresenter.print_output(response_dict['payload'])
|
|
47
48
|
except socket.error as msg:
|
|
48
49
|
print(f"Error receiving response from daemon: {msg}")
|
|
49
50
|
|
|
50
51
|
def close(self):
|
|
51
52
|
self.sock.close()
|
|
52
|
-
|
|
53
|
-
def __print_output(self, data):
|
|
54
|
-
if 'error' in data:
|
|
55
|
-
print(f"Error: {data['error']}")
|
|
56
|
-
elif 'notification' in data:
|
|
57
|
-
print(data['notification'])
|
|
58
|
-
elif 'albums' in data:
|
|
59
|
-
self.__print_collection('albums', data['albums'])
|
|
60
|
-
elif 'playlists' in data:
|
|
61
|
-
self.__print_collection('playlists', data['playlists'])
|
|
62
|
-
|
|
63
|
-
def __print_collection(self, type, items):
|
|
64
|
-
print("──────────────────────────────────────────")
|
|
65
|
-
for item in items:
|
|
66
|
-
if (type=='albums'):
|
|
67
|
-
self.__print_album(item)
|
|
68
|
-
elif (type=='playlists'):
|
|
69
|
-
self.__print_playlist(item)
|
|
70
|
-
print("──────────────────────────────────────────")
|
|
71
|
-
|
|
72
|
-
def __print_album(self, album_data):
|
|
73
|
-
print(f"Artist: {album_data['artists']}")
|
|
74
|
-
print(f"Album: {album_data['name']}")
|
|
75
|
-
print(f"URI: spotify:album:{album_data['spotify_id']}")
|
|
76
|
-
|
|
77
|
-
def __print_playlist(self, playlist_data):
|
|
78
|
-
print(f"Owner: {playlist_data['owner']}")
|
|
79
|
-
print(f"Name: {playlist_data['name']}")
|
|
80
|
-
print(f"URI: spotify:playlist:{playlist_data['spotify_id']}")
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
class DataPresenter:
|
|
2
|
+
PRINT_TEMPLATES = {
|
|
3
|
+
'albums': [
|
|
4
|
+
('Artist', 'artists'),
|
|
5
|
+
('Album', 'name'),
|
|
6
|
+
('URI', lambda d: f"spotify:album:{d['spotify_id']}")
|
|
7
|
+
],
|
|
8
|
+
'artists': [
|
|
9
|
+
('Artist', 'name'),
|
|
10
|
+
('Followers', 'followers'),
|
|
11
|
+
('URI', lambda d: f"spotify:artist:{d['spotify_id']}")
|
|
12
|
+
],
|
|
13
|
+
'playlists': [
|
|
14
|
+
('Owner', 'owner'),
|
|
15
|
+
('Name', 'name'),
|
|
16
|
+
('URI', lambda d: f"spotify:playlist:{d['spotify_id']}")
|
|
17
|
+
],
|
|
18
|
+
'tracks': [
|
|
19
|
+
('Artist', 'artists'),
|
|
20
|
+
('Name', 'name'),
|
|
21
|
+
('URI', lambda d: f"spotify:track:{d['spotify_id']}")
|
|
22
|
+
],
|
|
23
|
+
'episodes': [
|
|
24
|
+
('Name', 'name'),
|
|
25
|
+
('Description', 'description'),
|
|
26
|
+
('URI', lambda d: f"spotify:episode:{d['spotify_id']}")
|
|
27
|
+
],
|
|
28
|
+
'shows': [
|
|
29
|
+
('Name', 'name'),
|
|
30
|
+
('Description', 'description'),
|
|
31
|
+
('URI', lambda d: f"spotify:show:{d['spotify_id']}")
|
|
32
|
+
],
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def print_output(data):
|
|
37
|
+
if 'error' in data:
|
|
38
|
+
print(f"Error: {data['error']}")
|
|
39
|
+
elif 'notification' in data:
|
|
40
|
+
print(data['notification'])
|
|
41
|
+
else:
|
|
42
|
+
for key, value in data.items():
|
|
43
|
+
if key in DataPresenter.PRINT_TEMPLATES:
|
|
44
|
+
DataPresenter.__print_collection(key, value)
|
|
45
|
+
break
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def __print_collection(collection_type, items):
|
|
49
|
+
horizontal_line = "─" * 50
|
|
50
|
+
print(horizontal_line)
|
|
51
|
+
for item in items:
|
|
52
|
+
DataPresenter.__print_item(collection_type, item)
|
|
53
|
+
print(horizontal_line)
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def __print_item(collection_type, item_data):
|
|
57
|
+
for label, key in DataPresenter.PRINT_TEMPLATES[collection_type]:
|
|
58
|
+
value = key(item_data) if callable(key) else item_data[key]
|
|
59
|
+
print(f"{label}: {value}")
|
|
@@ -45,6 +45,10 @@ def main():
|
|
|
45
45
|
play_uri_parser = play_type_parser.add_parser('uri', help='play resource by spotify URI')
|
|
46
46
|
play_uri_parser.add_argument('uri', type=str, help='spotify uri')
|
|
47
47
|
|
|
48
|
+
find_parser = subparsers.add_parser('find', help='find items based on search query')
|
|
49
|
+
find_parser.add_argument('search_type', choices=['album', 'artist', 'playlist', 'track', 'episode', 'show'], help='type of item to find')
|
|
50
|
+
find_parser.add_argument('search_query', type=str, help='search query string')
|
|
51
|
+
|
|
48
52
|
parser.add_argument('--format', choices=['json', 'text', 'verbose'], default='text', help='output format')
|
|
49
53
|
|
|
50
54
|
args = parser.parse_args()
|
|
@@ -52,8 +56,14 @@ def main():
|
|
|
52
56
|
payload = {
|
|
53
57
|
'command': args.command,
|
|
54
58
|
'setting': getattr(args, 'setting', None),
|
|
55
|
-
'type': getattr(args, 'get_type', None) or
|
|
56
|
-
|
|
59
|
+
'type': (getattr(args, 'get_type', None) or
|
|
60
|
+
getattr(args, 'play_type', None) or
|
|
61
|
+
getattr(args, 'search_type', None)),
|
|
62
|
+
'value': (getattr(args, 'state', None) or
|
|
63
|
+
getattr(args, 'level', None) or
|
|
64
|
+
getattr(args, 'name', None) or
|
|
65
|
+
getattr(args, 'uri', None) or
|
|
66
|
+
getattr(args, 'search_query', None))
|
|
57
67
|
}
|
|
58
68
|
|
|
59
69
|
client = Client()
|
|
@@ -23,9 +23,9 @@ args = parser.parse_args()
|
|
|
23
23
|
spotify = SpotifyController()
|
|
24
24
|
server = SocketServer(spotify)
|
|
25
25
|
|
|
26
|
-
lock_file = "/tmp/
|
|
26
|
+
lock_file = "/tmp/spotify-cmd-daemon.lock"
|
|
27
27
|
if os.path.exists(lock_file):
|
|
28
|
-
print("
|
|
28
|
+
print(f"Daemon already running ({lock_file} exists).")
|
|
29
29
|
sys.exit(1)
|
|
30
30
|
else:
|
|
31
31
|
with open(lock_file, 'w'): pass
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .presenters.albums_presenter import AlbumsPresenter
|
|
2
|
+
|
|
3
|
+
def get_library_albums(spotipy_client):
|
|
4
|
+
albums = []
|
|
5
|
+
limit = 50
|
|
6
|
+
offset = 0
|
|
7
|
+
|
|
8
|
+
while True:
|
|
9
|
+
results = spotipy_client.current_user_saved_albums(limit=limit, offset=offset)
|
|
10
|
+
raw_albums = list(map(lambda item: item['album'], results['items']))
|
|
11
|
+
|
|
12
|
+
albums += AlbumsPresenter(raw_albums).format()
|
|
13
|
+
|
|
14
|
+
offset += limit
|
|
15
|
+
if len(results['items']) < limit:
|
|
16
|
+
break
|
|
17
|
+
|
|
18
|
+
return {'albums': albums}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .presenters.playlists_presenter import PlaylistsPresenter
|
|
2
|
+
|
|
3
|
+
def get_library_playlists(spotipy_client):
|
|
4
|
+
playlists = []
|
|
5
|
+
limit = 50
|
|
6
|
+
offset = 0
|
|
7
|
+
|
|
8
|
+
while True:
|
|
9
|
+
results = spotipy_client.current_user_playlists(limit=limit, offset=offset)
|
|
10
|
+
playlists += PlaylistsPresenter(results['items']).format()
|
|
11
|
+
|
|
12
|
+
offset += limit
|
|
13
|
+
if len(results['items']) < limit:
|
|
14
|
+
break
|
|
15
|
+
|
|
16
|
+
return {'playlists': playlists}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from .collection_presenter import CollectionPresenter
|
|
2
|
+
from .albums_presenter import AlbumsPresenter
|
|
3
|
+
from .artists_presenter import ArtistsPresenter
|
|
4
|
+
from .playlists_presenter import PlaylistsPresenter
|
|
5
|
+
from .tracks_presenter import TracksPresenter
|
|
6
|
+
from .shows_presenter import ShowsPresenter
|
|
7
|
+
from .episodes_presenter import EpisodesPresenter
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .collection_presenter import CollectionPresenter
|
|
2
|
+
|
|
3
|
+
class AlbumsPresenter(CollectionPresenter):
|
|
4
|
+
def format(self):
|
|
5
|
+
albums = []
|
|
6
|
+
|
|
7
|
+
for item in self.items:
|
|
8
|
+
album_info = super().format_item(item)
|
|
9
|
+
album_info.update({
|
|
10
|
+
'artists': ', '.join([artist['name'] for artist in item['artists']]),
|
|
11
|
+
'name': item['name']
|
|
12
|
+
})
|
|
13
|
+
albums.append(album_info)
|
|
14
|
+
return albums
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .collection_presenter import CollectionPresenter
|
|
2
|
+
|
|
3
|
+
class ArtistsPresenter(CollectionPresenter):
|
|
4
|
+
def format(self):
|
|
5
|
+
artists = []
|
|
6
|
+
|
|
7
|
+
for item in self.items:
|
|
8
|
+
artist_info = super().format_item(item)
|
|
9
|
+
artist_info.update({
|
|
10
|
+
'name': item['name'],
|
|
11
|
+
'followers': item['followers']['total']
|
|
12
|
+
})
|
|
13
|
+
artists.append(artist_info)
|
|
14
|
+
return artists
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class CollectionPresenter:
|
|
2
|
+
def __init__(self, items):
|
|
3
|
+
self.items = items
|
|
4
|
+
print(items)
|
|
5
|
+
def format_item(self, item):
|
|
6
|
+
return {
|
|
7
|
+
'spotify_id': item['id'],
|
|
8
|
+
'type': self.get_type()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
def get_type(self):
|
|
12
|
+
return self.__class__.__name__.replace('Presenter', '').lower()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .collection_presenter import CollectionPresenter
|
|
2
|
+
|
|
3
|
+
class EpisodesPresenter(CollectionPresenter):
|
|
4
|
+
def format(self):
|
|
5
|
+
episodes = []
|
|
6
|
+
|
|
7
|
+
for item in self.items:
|
|
8
|
+
episode_info = super().format_item(item)
|
|
9
|
+
episode_info.update({
|
|
10
|
+
'name': item['name'],
|
|
11
|
+
'description': item['description']
|
|
12
|
+
})
|
|
13
|
+
episodes.append(episode_info)
|
|
14
|
+
return episodes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .collection_presenter import CollectionPresenter
|
|
2
|
+
|
|
3
|
+
class PlaylistsPresenter(CollectionPresenter):
|
|
4
|
+
def format(self):
|
|
5
|
+
playlists = []
|
|
6
|
+
|
|
7
|
+
for item in self.items:
|
|
8
|
+
playlist_info = super().format_item(item)
|
|
9
|
+
playlist_info.update({
|
|
10
|
+
'owner': item['owner']['display_name'],
|
|
11
|
+
'name': item['name']
|
|
12
|
+
})
|
|
13
|
+
playlists.append(playlist_info)
|
|
14
|
+
return playlists
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .collection_presenter import CollectionPresenter
|
|
2
|
+
|
|
3
|
+
class ShowsPresenter(CollectionPresenter):
|
|
4
|
+
def format(self):
|
|
5
|
+
shows = []
|
|
6
|
+
|
|
7
|
+
for item in self.items:
|
|
8
|
+
show_info = super().format_item(item)
|
|
9
|
+
show_info.update({
|
|
10
|
+
'name': item['name'],
|
|
11
|
+
'description': item['description']
|
|
12
|
+
})
|
|
13
|
+
shows.append(show_info)
|
|
14
|
+
return shows
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .collection_presenter import CollectionPresenter
|
|
2
|
+
|
|
3
|
+
class TracksPresenter(CollectionPresenter):
|
|
4
|
+
def format(self):
|
|
5
|
+
tracks = []
|
|
6
|
+
|
|
7
|
+
for item in self.items:
|
|
8
|
+
track_info = super().format_item(item)
|
|
9
|
+
track_info.update({
|
|
10
|
+
'artists': ', '.join([artist['name'] for artist in item['artists']]),
|
|
11
|
+
'name': item['name']
|
|
12
|
+
})
|
|
13
|
+
tracks.append(track_info)
|
|
14
|
+
return tracks
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from .presenters import *
|
|
2
|
+
|
|
3
|
+
def search(spotipy_client, search_query, resource_type):
|
|
4
|
+
response = spotipy_client.search(q=search_query, type=resource_type)
|
|
5
|
+
collection_key = next(iter(response.keys()))
|
|
6
|
+
items = response[collection_key].get('items', [])
|
|
7
|
+
result = None
|
|
8
|
+
|
|
9
|
+
if resource_type == 'album':
|
|
10
|
+
result = AlbumsPresenter(items).format()
|
|
11
|
+
elif resource_type == 'artist':
|
|
12
|
+
result = ArtistsPresenter(items).format()
|
|
13
|
+
elif resource_type == 'playlist':
|
|
14
|
+
result = PlaylistsPresenter(items).format()
|
|
15
|
+
elif resource_type == 'track':
|
|
16
|
+
result = TracksPresenter(items).format()
|
|
17
|
+
elif resource_type == 'show':
|
|
18
|
+
result = ShowsPresenter(items).format()
|
|
19
|
+
elif resource_type == 'episode':
|
|
20
|
+
result = EpisodesPresenter(items).format()
|
|
21
|
+
|
|
22
|
+
return { f"{resource_type}s": result }
|
|
@@ -49,6 +49,8 @@ class SpotifyController:
|
|
|
49
49
|
self.handle_set(command_data)
|
|
50
50
|
elif command == 'get':
|
|
51
51
|
self.handle_get(command_data)
|
|
52
|
+
elif command == 'find':
|
|
53
|
+
self.handle_search(command_data)
|
|
52
54
|
except SpotifyException as e:
|
|
53
55
|
print(f"Spotify error: {e}")
|
|
54
56
|
self.response = {"error": str(e)}
|
|
@@ -56,6 +58,13 @@ class SpotifyController:
|
|
|
56
58
|
print(f"Error: {e}")
|
|
57
59
|
self.response = {"error": str(e)}
|
|
58
60
|
|
|
61
|
+
def handle_search(self, command_data):
|
|
62
|
+
type = command_data.get('type')
|
|
63
|
+
search_query = command_data.get('value')
|
|
64
|
+
|
|
65
|
+
self.response = operations.search(self.spotipy_client, search_query, type)
|
|
66
|
+
|
|
67
|
+
|
|
59
68
|
def handle_play(self, command_data):
|
|
60
69
|
type = command_data.get('type')
|
|
61
70
|
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
def get_library_albums(spotipy_client):
|
|
2
|
-
albums = []
|
|
3
|
-
limit = 50
|
|
4
|
-
offset = 0
|
|
5
|
-
|
|
6
|
-
while True:
|
|
7
|
-
results = spotipy_client.current_user_saved_albums(limit=limit, offset=offset)
|
|
8
|
-
for item in results['items']:
|
|
9
|
-
album = item['album']
|
|
10
|
-
album_info = {
|
|
11
|
-
'spotify_id': album['id'],
|
|
12
|
-
'type': 'album',
|
|
13
|
-
'artists': ', '.join([artist['name'] for artist in album['artists']]),
|
|
14
|
-
'name': album['name']
|
|
15
|
-
}
|
|
16
|
-
albums.append(album_info)
|
|
17
|
-
|
|
18
|
-
offset += limit
|
|
19
|
-
if len(results['items']) < limit:
|
|
20
|
-
break
|
|
21
|
-
|
|
22
|
-
return { 'albums': albums }
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
def get_library_playlists(spotipy_client):
|
|
2
|
-
playlists = []
|
|
3
|
-
limit = 50
|
|
4
|
-
offset = 0
|
|
5
|
-
|
|
6
|
-
while True:
|
|
7
|
-
results = spotipy_client.current_user_playlists(limit=limit, offset=offset)
|
|
8
|
-
for item in results['items']:
|
|
9
|
-
playlist_info = {
|
|
10
|
-
'spotify_id': item['id'],
|
|
11
|
-
'type': 'playlist',
|
|
12
|
-
'owner': item['owner']['display_name'],
|
|
13
|
-
'name': item['name']
|
|
14
|
-
}
|
|
15
|
-
playlists.append(playlist_info)
|
|
16
|
-
|
|
17
|
-
offset += limit
|
|
18
|
-
if len(results['items']) < limit:
|
|
19
|
-
break
|
|
20
|
-
|
|
21
|
-
return { 'playlists': playlists }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/helpers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/helpers/get_album.py
RENAMED
|
File without changes
|
{spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/helpers/get_playlist.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/resume_playback.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spotify-cmd-0.1.2 → spotify-cmd-0.1.4}/src/spotify_cmd_daemon/operations/validators/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|