Skip to content

Commit 2a0a491

Browse files
RTnhNErikBjare
andauthored
fix: update watcher with api fixes (#30)
* Fix: Update watcher with api fixes There are two primary things that this does: 1. This fixes the redirect url problem. It changed from having localhost be acceptable to needing it to be a loopback url. See https://developer.spotify.com/documentation/web-api/concepts/redirect_uri 2. The `audio_features` api is discontinued by spotify for new webapps. Having the method call be unwrapped with a try except block killed the watcher. This change just wraps the audio_features in a try except block so that people who have old apps that currently have access to the API route can still use it. See below for info about changes to the Spotify Web API: https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api * Fix: use pure oath for auth * Fix: change to AW based logging Errors were not logged with the original type of logging. This makes the errors or other logs go to the default AW logging places. * Fix: Correct redirect uri * Fix: Move args into main --------- Co-authored-by: Erik Bjäreholt <erik@bjareho.lt>
1 parent 2449ebc commit 2a0a491

File tree

1 file changed

+37
-35
lines changed

1 file changed

+37
-35
lines changed

aw_watcher_spotify/main.py

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77
from time import sleep
88
from datetime import datetime, timezone, timedelta
99
import json
10+
import argparse
1011

1112
from requests import ConnectionError
12-
import spotipy
13-
import spotipy.util as util
14-
from spotipy.oauth2 import SpotifyClientCredentials
13+
from spotipy.exceptions import SpotifyException
14+
from spotipy import Spotify
15+
from spotipy.oauth2 import SpotifyOAuth, SpotifyOauthError
1516

1617
from aw_core import dirs
1718
from aw_core.models import Event
1819
from aw_client.client import ActivityWatchClient
20+
from aw_core.log import setup_logging
21+
1922

20-
logger = logging.getLogger("aw-watcher-spotify")
2123
DEFAULT_CONFIG = """
2224
[aw-watcher-spotify]
2325
username = ""
@@ -35,10 +37,10 @@ def get_current_track(sp) -> Optional[dict]:
3537

3638
def data_from_track(track: dict, sp) -> dict:
3739
song_name = track["item"]["name"]
38-
# local files do not have IDs
39-
data = (
40-
(sp.audio_features(track["item"]["id"])[0] or {}) if track["item"]["id"] else {}
41-
)
40+
try:
41+
data = sp.audio_features(track["item"]["id"])[0] or {}
42+
except SpotifyException:
43+
data = {}
4244
data["title"] = song_name
4345
data["uri"] = track["item"]["uri"]
4446

@@ -58,27 +60,18 @@ def data_from_track(track: dict, sp) -> dict:
5860
return data
5961

6062

61-
def auth(username, client_id=None, client_secret=None):
63+
def auth(username: str, client_id: str, client_secret: str) -> Spotify:
6264
scope = "user-read-currently-playing"
63-
# spotipy.oauth2.SpotifyOAuth(client_id, client_secret, )
64-
# specify port
65-
token = util.prompt_for_user_token(
66-
username,
67-
scope=scope,
68-
client_id=client_id,
69-
client_secret=client_secret,
70-
redirect_uri="http://127.0.0.1:8088",
71-
)
72-
73-
if token:
74-
credential_manager = SpotifyClientCredentials(
75-
client_id=client_id, client_secret=client_secret
65+
try:
66+
auth_manager = SpotifyOAuth(
67+
client_id=client_id,
68+
client_secret=client_secret,
69+
redirect_uri="http://127.0.0.1:8088",
70+
scope=scope,
71+
cache_path=f".cache-{username}"
7672
)
77-
return spotipy.Spotify(
78-
auth=token, client_credentials_manager=credential_manager
79-
)
80-
else:
81-
logger.error("Was unable to get token")
73+
return Spotify(auth_manager=auth_manager)
74+
except SpotifyOauthError as e:
8275
sys.exit(1)
8376

8477

@@ -98,8 +91,17 @@ def print_statusline(msg):
9891

9992

10093
def main():
101-
logging.basicConfig(level=logging.INFO)
102-
94+
argparser = argparse.ArgumentParser()
95+
argparser.add_argument("--testing", action="store_true")
96+
argparser.add_argument("--verbose", action="store_true")
97+
args = argparser.parse_args()
98+
setup_logging(
99+
name="aw-watcher-spotify",
100+
testing=args.testing,
101+
verbose=args.verbose,
102+
log_stderr=True,
103+
log_file=True,
104+
)
103105
config_dir = dirs.get_config_dir("aw-watcher-spotify")
104106

105107
config = load_config()
@@ -108,7 +110,7 @@ def main():
108110
client_id = config["aw-watcher-spotify"].get("client_id", None)
109111
client_secret = config["aw-watcher-spotify"].get("client_secret", None)
110112
if not username or not client_id or not client_secret:
111-
logger.warning(
113+
logging.warning(
112114
"username, client_id or client_secret not specified in config file (in folder {}). Get your client_id and client_secret here: https://developer.spotify.com/my-applications/".format(
113115
config_dir
114116
)
@@ -129,23 +131,23 @@ def main():
129131
track = get_current_track(sp)
130132
# from pprint import pprint
131133
# pprint(track)
132-
except spotipy.client.SpotifyException as e:
134+
except SpotifyException as e:
133135
print_statusline("\nToken expired, trying to refresh\n")
134136
sp = auth(username, client_id=client_id, client_secret=client_secret)
135137
continue
136138
except ConnectionError as e:
137-
logger.error(
139+
logging.error(
138140
"Connection error while trying to get track, check your internet connection."
139141
)
140142
sleep(poll_time)
141143
continue
142144
except json.JSONDecodeError as e:
143-
logger.error("Error trying to decode")
145+
logging.error("Error trying to decode")
144146
sleep(0.1)
145147
continue
146148
except Exception as e:
147-
logger.error("Unknown Error")
148-
logger.error(traceback.format_exc())
149+
logging.error("Unknown Error")
150+
logging.error(traceback.format_exc())
149151
sleep(0.1)
150152
continue
151153

0 commit comments

Comments
 (0)