Skip to content

Commit 4ccad9a

Browse files
committed
Added swap between devices with spotify connect functionality
1 parent e98335a commit 4ccad9a

File tree

6 files changed

+126
-7
lines changed

6 files changed

+126
-7
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Makefile for the template_python_project
22

33
SHELL=/bin/bash
4-
PYTHON_VERSION=3.6
4+
PYTHON_VERSION=3
55
PYTHON_BIN=venv/bin/
66
TESTS_FOLDER=tests
77

configuration/configuration.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ def __init__(self, config_src: Union[TextIOWrapper, StringIO, str], config_schem
5151
if not all(spoti_var != '' for spoti_var in self.get_spotifies()[0]):
5252
logger.error('Spotify config has some empty values!\n%s' % self.get_spotifies()[0])
5353
raise Exception('Spotify config has some empty values!')
54-
if not all(switch_var != '' for switch_var in self.get_switchbots()[0]):
55-
logger.error('switchbot config has some empty values\n%s' % self.get_switchbots()[0])
56-
raise Exception('switchbot config has some empty values!')
54+
# if not all(switch_var != '' for switch_var in self.get_switchbots()[0]):
55+
# logger.error('switchbot config has some empty values\n%s' % self.get_switchbots()[0])
56+
# raise Exception('switchbot config has some empty values!')
5757

5858
@staticmethod
5959
def load_configuration_schema(config_schema_path: str) -> Dict:

configuration/yml_schema.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
}
1414
},
1515
"required": [
16-
"spotify",
17-
"switchbot"
16+
"spotify"
1817
],
1918
"definitions": {
2019
"spotify": {

confs/switch_between_mac_pixel5.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
spotify:
2+
- config: # Spotify API credentials
3+
username: !ENV ${SPOTIFY_USERNAME}
4+
client_id: !ENV ${SPOTIFY_CLIENT_ID}
5+
client_secret: !ENV ${SPOTIFY_SECRET}
6+
scope: user-read-playback-state # leave it as is
7+
redirect_uri: 'http://localhost:8081' # leave it as is
8+
target_device: Pixel 5 # target device
9+
target_device_id: d639d8f68cf6953504cb83ab0043386e7dcbc737 # id of target device
10+
- config: # Spotify API credentials
11+
username: !ENV ${SPOTIFY_USERNAME}
12+
client_id: !ENV ${SPOTIFY_CLIENT_ID}
13+
client_secret: !ENV ${SPOTIFY_SECRET}
14+
scope: user-modify-playback-state # leave it as is
15+
redirect_uri: 'http://localhost:8081' # leave it as is
16+
target_device: Kostas’s MacbookPro # target device
17+
swap_mode: true # swap between devices
18+
target_device_id: 922f1165ffae326c70970e222b92f48f1510bbfd # id of target device
19+
type: spotipy_lib # leave it as is

spotipy_lib/spotipy.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def get_playback_info(self):
8181
song = current_playback["item"]["uri"]
8282
if "progress_ms" in current_playback:
8383
progress_ms = current_playback["progress_ms"]
84-
return (context, song, progress_ms)
84+
return context, song, progress_ms
8585

8686
def play_on_device(self, target_device_id, session_info):
8787
found_track = True

swap_devices.py

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import os
2+
from time import sleep
3+
import argparse
4+
import logging
5+
import traceback
6+
import requests.exceptions
7+
8+
from spotipy_lib.spotipy import Spotipy
9+
from spotipy_lib.spotipy import SpotifyException
10+
from configuration.configuration import Configuration
11+
12+
logger = logging.getLogger('Spotify Connect')
13+
14+
15+
def _setup_log(log_path: str = 'logs/output.log', debug: bool = False) -> None:
16+
""" Sets up logger. """
17+
18+
log_path = log_path.split(os.sep)
19+
if len(log_path) > 1:
20+
try:
21+
os.makedirs((os.sep.join(log_path[:-1])))
22+
except FileExistsError:
23+
pass
24+
log_filename = os.sep.join(log_path)
25+
# noinspection PyArgumentList
26+
logging.basicConfig(level=logging.INFO if debug is not True else logging.DEBUG,
27+
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
28+
datefmt='%Y-%m-%d %H:%M:%S',
29+
handlers=[
30+
logging.FileHandler(log_filename),
31+
# logging.handlers.TimedRotatingFileHandler(log_filename, when='midnight', interval=1),
32+
logging.StreamHandler()
33+
]
34+
)
35+
36+
37+
def _argparser() -> argparse.Namespace:
38+
""" Parses and returns the command line arguments. """
39+
40+
parser = argparse.ArgumentParser(
41+
description='Script to trigger Spotify Connect to play on specific device.',
42+
add_help=False)
43+
# Required Args
44+
required_arguments = parser.add_argument_group('Required Arguments')
45+
config_file_params = {
46+
'type': argparse.FileType('r'),
47+
'required': True,
48+
'help': "The configuration yml file"
49+
}
50+
51+
required_arguments.add_argument('-c', '--config-file', **config_file_params)
52+
required_arguments.add_argument('-l', '--log', help="Name of the output log file")
53+
# Optional args
54+
optional = parser.add_argument_group('Optional Arguments')
55+
optional.add_argument('-d', '--debug', action='store_true', help='Enables the debug log messages')
56+
optional.add_argument("-h", "--help", action="help", help="Show this help message and exit")
57+
58+
return parser.parse_args()
59+
60+
61+
def main():
62+
"""
63+
Handles the core flow of SpotiClick.
64+
65+
:Example:
66+
python main.py -c confs/raspotify_conf.yml
67+
-l logs/spoticlick.log
68+
"""
69+
70+
# Initializing
71+
args = _argparser()
72+
_setup_log(args.log, args.debug)
73+
# Load the configuration
74+
configuration = Configuration(config_src=args.config_file)
75+
# Init Spotipy
76+
spoti_read_config = configuration.get_spotifies()[0]
77+
print(spoti_read_config)
78+
spoti_modify_config = configuration.get_spotifies()[1]
79+
target_device_id_1 = spoti_read_config["target_device_id"]
80+
target_device_id_2 = spoti_modify_config["target_device_id"]
81+
spot_read = Spotipy(config=spoti_read_config, token_id='read')
82+
# Check active
83+
device_1_active = spot_read.is_target_device_active()
84+
if not device_1_active:
85+
target_device_id = target_device_id_1
86+
else:
87+
target_device_id = target_device_id_2
88+
89+
spot_modify = Spotipy(config=spoti_modify_config, token_id='modify')
90+
# Change device
91+
logger.info("Transferring music to device id: %s" % target_device_id)
92+
spot_modify.play_on_device(target_device_id=target_device_id, session_info=spot_read.get_playback_info())
93+
logger.info("Music Transferred!")
94+
95+
96+
if __name__ == '__main__':
97+
try:
98+
main()
99+
except Exception as e:
100+
logging.error(str(e) + '\n' + str(traceback.format_exc()))
101+
raise e

0 commit comments

Comments
 (0)