User Tools

Site Tools


python:deezer-album-tracker

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
python:deezer-album-tracker [2024/03/28 17:03] Wulf Rajekpython:deezer-album-tracker [2024/04/21 20:05] (current) Wulf Rajek
Line 2: Line 2:
  
 This script uses the deezer public api to provide a list of albums released the past half year of artists in the configuration file. Configuration file will be created if it doesn't exist. Adding/removing artists can be done using command line options. The output can be emailed for easy use from cron with customisable subject line. This script uses the deezer public api to provide a list of albums released the past half year of artists in the configuration file. Configuration file will be created if it doesn't exist. Adding/removing artists can be done using command line options. The output can be emailed for easy use from cron with customisable subject line.
 +
 +Depending on network speed and amount of albums per artist and due to deezer API rate limit of max 50 requests per 5 seconds, querying 180 days for 235 artists takes about 1:45 minutes.
  
 Prerequisites for fuzzy search: Prerequisites for fuzzy search:
Line 8: Line 10:
 Usage: Usage:
 <code> <code>
-usage: dat.py [-h] [--list] [--add ARTIST_NAME] [--delete SEARCH_TERM] [--email]+usage: dat.py [-h] [--list] [--days DAYS] [--add ARTIST_NAME] [--delete SEARCH_TERM] [--email]
  
 Deezer Album Tracker Deezer Album Tracker
Line 15: Line 17:
   -h, --help            show this help message and exit   -h, --help            show this help message and exit
   --list                List all monitored artists   --list                List all monitored artists
 +  --days DAYS           Amount of days to list
   --add ARTIST_NAME     Add a new artist   --add ARTIST_NAME     Add a new artist
   --delete SEARCH_TERM  Delete an artist by fuzzy search   --delete SEARCH_TERM  Delete an artist by fuzzy search
Line 22: Line 25:
 Example output: Example output:
 <code> <code>
-./dat.py  +$ /dat.py --days 7 
-Albums released in the past 6 months+Albums released in the past 7 days: 
-Release Date: 2024-01-12 + 
-Artist: Papa Roach +Release Date: 2024-04-19 
-Album Name: Scars (feat. Chris Daughtry) (Live)+Artist: Staind 
 +Album Name: Better Days (feat. Dorothy) (1 track) 
 +Link: https://www.deezer.com/album/571491071 
 + 
 +Release Date: 2024-04-19 
 +Artist: Distilled Harmony 
 +Album Name: Nova (3 tracks) 
 +Link: https://www.deezer.com/album/572632871
  
-Release Date: 2023-11-03 +Release Date: 2024-04-19 
-Artist: Limp Bizkit +Artist: Taylor Swift 
-Album Name: Counterfeit Countdown+Album Name: THE TORTURED POETS DEPARTMENT [EXPLICIT] (16 tracks) 
 +Link: https://www.deezer.com/album/574109801
  
-Release Date: 2023-10-31 
-Artist: Papa Roach 
-Album Name: Leave a Light On (Talk Away The Dark) 
 </code> </code>
  
Line 40: Line 48:
 <code json config.json> <code json config.json>
 { {
 +    "global": {
 +        "days": 180
 +    },
     "email": {     "email": {
         "smtp_server": "emailserver",         "smtp_server": "emailserver",
Line 60: Line 71:
 } }
 </code> </code>
 +
 +
 +To add artists in bulk, the simplest way is to create a text file with an artist on each line, then use the following bash command to let dat.py search deezer for the id and add it to the config file:
 +<code>while read p; do ./dat.py --add "$p"; done <artists.txt</code>
  
  
 <code python dat.py> <code python dat.py>
 #!/usr/bin/python #!/usr/bin/python
 +import ssl
 import smtplib import smtplib
 from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
Line 70: Line 86:
 import json import json
 from datetime import datetime, timedelta from datetime import datetime, timedelta
 +import time
 import argparse import argparse
-from fuzzywuzzy import fuzz +from fuzzywuzzy import fuzzprocess
-from fuzzywuzzy import process+
 import os import os
  
 # Constants for file paths # Constants for file paths
-CONFIG_FILE = "config.json"+CONFIG_FILENAME = "config.json" 
 +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 
 +CONFIG_FILE = os.path.join(SCRIPT_DIR, CONFIG_FILENAME) 
  
 def load_config(): def load_config():
Line 82: Line 101:
         # Create default config file if it doesn't exist         # Create default config file if it doesn't exist
         default_config = {         default_config = {
 +            "global": {
 +                "days": "180"
 +            },
             "email": {             "email": {
                 "smtp_server": "smtp.example.com",                 "smtp_server": "smtp.example.com",
Line 97: Line 119:
     with open(CONFIG_FILE, "r") as config_file:     with open(CONFIG_FILE, "r") as config_file:
         return json.load(config_file)         return json.load(config_file)
 +
  
 def save_config(config): def save_config(config):
Line 102: Line 125:
         json.dump(config, config_file, indent=4)         json.dump(config, config_file, indent=4)
  
-def send_email(subject, body, recipients):+ 
 +def send_email(body):
     config = load_config()     config = load_config()
     email_config = config.get('email', {})     email_config = config.get('email', {})
Line 113: Line 137:
     sender_email = email_config.get('sender_email')     sender_email = email_config.get('sender_email')
     sender_password = email_config.get('sender_password')     sender_password = email_config.get('sender_password')
 +    email_subject = config.get('email_subject', 'Deezer Album Tracker')
  
     msg = MIMEMultipart()     msg = MIMEMultipart()
     msg['From'] = sender_email     msg['From'] = sender_email
     msg['To'] = ', '.join(email_config.get('email_recipients'))     msg['To'] = ', '.join(email_config.get('email_recipients'))
-    msg['Subject'] = f"{subject} - {datetime.now().strftime('%Y-%m-%d')}"+    msg['Subject'] = f"{email_subject} - {datetime.now().strftime('%Y-%m-%d')}"
  
     body = MIMEText(body)     body = MIMEText(body)
Line 131: Line 156:
         server.login(sender_email, sender_password)         server.login(sender_email, sender_password)
         server.send_message(msg)         server.send_message(msg)
 +
  
 def get_artist_name(artist_id): def get_artist_name(artist_id):
Line 139: Line 165:
         return data.get('name', '')         return data.get('name', '')
     return ''     return ''
 +
  
 def get_artist_id(artist_name): def get_artist_id(artist_name):
Line 150: Line 177:
     return None     return None
  
-def get_albums(artist_ids):+ 
 +def get_albums(artist_ids, lookupdays):
     base_url = "https://api.deezer.com/artist/{}/albums"     base_url = "https://api.deezer.com/artist/{}/albums"
-    six_months_ago = (datetime.now() - timedelta(days=180)).strftime('%Y-%m-%d')+    earliest_release = (datetime.now() - timedelta(days=lookupdays)).strftime('%Y-%m-%d')
     albums = []     albums = []
 +    request_count = 0
 +    start_time = time.time()
 +
 +    today = datetime.today().strftime('%Y-%m-%d')
  
     for artist_id in artist_ids:     for artist_id in artist_ids:
         url = base_url.format(artist_id)         url = base_url.format(artist_id)
         response = requests.get(url)         response = requests.get(url)
 +        request_count += 1
         if response.status_code == 200:         if response.status_code == 200:
             data = response.json()             data = response.json()
Line 163: Line 196:
             for album in data['data']:             for album in data['data']:
                 release_date = datetime.strptime(album['release_date'], '%Y-%m-%d')                 release_date = datetime.strptime(album['release_date'], '%Y-%m-%d')
-                if release_date >= datetime.strptime(six_months_ago, '%Y-%m-%d'):+                if (datetime.strptime(earliest_release, '%Y-%m-%d') <= release_date <= 
 +                        datetime.strptime(today, '%Y-%m-%d')): 
 +                    trackresponse = requests.get(album['tracklist']) 
 +                    request_count += 1 
 +                    if trackresponse.status_code == 200: 
 +                        tracklist = trackresponse.json() 
 +                        trackamount = tracklist['total'
 +                    else: 
 +                        trackamount = 0 
                     albums.append({                     albums.append({
                         'artist': artist_name,                         'artist': artist_name,
                         'album_name': album['title'],                         'album_name': album['title'],
-                        'release_date': album['release_date']+                        'release_date': album['release_date'], 
 +                        'trackamount': trackamount, 
 +                        'explicit_lyrics': album['explicit_lyrics'], 
 +                        'link': album['link']
                     })                     })
 +
 +        # Deezer rate limit is 50 requests / 5 seconds. Limiting to 40/5 here:
 +        # Check if 40 requests have been made in less than 5 seconds
 +        if request_count == 40:
 +            elapsed_time = time.time() - start_time
 +            if elapsed_time < 5:
 +                time.sleep(5 - elapsed_time)
 +            # Reset request count and start time
 +            request_count = 0
 +            start_time = time.time()
 +
     return sorted(albums, key=lambda x: x['release_date'], reverse=True)     return sorted(albums, key=lambda x: x['release_date'], reverse=True)
 +
  
 def list_artists(): def list_artists():
     config = load_config()     config = load_config()
     subscribed_artists = config.get('artist_ids', {})     subscribed_artists = config.get('artist_ids', {})
-    for artist_id, artist_name in subscribed_artists.items(): +    sorted_artists = dict(sorted(subscribed_artists.items(), key=lambda item: item[1].casefold())) 
-        print(f"{artist_id}{artist_name}")+    for artist_id, artist_name in sorted_artists.items(): 
 +        print(f"{artist_name ({artist_id})") 
  
 def add_artist(artist_name): def add_artist(artist_name):
Line 187: Line 246:
     else:     else:
         print("Artist not found.")         print("Artist not found.")
 +
  
 def delete_artist(search_term): def delete_artist(search_term):
Line 196: Line 256:
     for index, (artist_name, score) in enumerate(choices):     for index, (artist_name, score) in enumerate(choices):
         print(f"{index + 1}. {artist_name} ({score})")         print(f"{index + 1}. {artist_name} ({score})")
-    choice_index int(input("Enter the number of the artist to delete: ")) - 1 +    choice_input = input("Enter the number of the artist to delete: ") 
-    if 0 <= choice_index < len(choices): +    if choice_input.isnumeric(): 
-        artist_name = choices[choice_index][0] +        choice_index = int(choice_input) - 1 
-        artist_id = [key for key, value in subscribed_artists.items() if value == artist_name][0] +        if 0 <= choice_index < len(choices): 
-        del config[artist_id] +            artist_name = choices[choice_index][0] 
-        save_config(config) +            artist_id = [key for key, value in subscribed_artists.items() if value == artist_name][0] 
-        print(f"Artist '{artist_name}' deleted successfully.")+            del config['artist_ids'][artist_id] 
 +            save_config(config) 
 +            print(f"Artist '{artist_name}' deleted successfully.") 
 +        else: 
 +            print("Invalid choice.")
     else:     else:
-        print("Invalid choice.")+        print("No number entered.") 
  
 def main(): def main():
     parser = argparse.ArgumentParser(description="Deezer Album Tracker")     parser = argparse.ArgumentParser(description="Deezer Album Tracker")
     parser.add_argument("--list", action="store_true", help="List all monitored artists")     parser.add_argument("--list", action="store_true", help="List all monitored artists")
 +    parser.add_argument("--days", metavar="DAYS", help="Amount of days to list")
     parser.add_argument("--add", metavar="ARTIST_NAME", help="Add a new artist")     parser.add_argument("--add", metavar="ARTIST_NAME", help="Add a new artist")
     parser.add_argument("--delete", metavar="SEARCH_TERM", help="Delete an artist by fuzzy search")     parser.add_argument("--delete", metavar="SEARCH_TERM", help="Delete an artist by fuzzy search")
Line 224: Line 290:
         config = load_config()         config = load_config()
         artist_ids = config.get('artist_ids', [])         artist_ids = config.get('artist_ids', [])
-        albums = get_albums(artist_ids)+        if args.days: 
 +            lookupdays = int(args.days) 
 +        else: 
 +            lookupdays = config.get('global', {})['days'
 +        albums = get_albums(artist_ids, lookupdays)
  
-        print("Albums released in the past 6 months:")+        output = f"Albums released in the past {lookupdays} days:\n\n"
         for album in albums:         for album in albums:
-            print("Release Date:", album['release_date']) +            output += f"Release Date: {album['release_date']}\n" 
-            print("Artist:", album['artist']) +            output += f"Artist: {album['artist']}\n" 
-            print("Album Name:", album['album_name']) +            output += f"Album Name: {album['album_name']}" 
-            print()+            if album['explicit_lyrics'] is True: 
 +                output += " [EXPLICIT]" 
 +            if album['trackamount'] > 0: 
 +                output += f" ({album['trackamount']} track" 
 +                if album['trackamount'] > 1: 
 +                    output += "s" 
 +                output += ")" 
 +            output += "\n" 
 +            output += f"Link: {album['link']}\n" 
 +            output += "\n" 
 +        print(output)
  
         if args.email:         if args.email:
-            email_subject = config.get('email_subject', 'Deezer Album Tracker'+            send_email(output
-            email_recipients = config.get('email_recipients', []) +
-            email_body = "\n".join([f"Release Date: {album['release_date']}\nArtist: {album['artist']}\nAlbum Name: {album['album_name']}\n" for album in albums]) +
-            send_email(email_subject, email_body, email_recipients)+
  
 if __name__ == "__main__": if __name__ == "__main__":
     main()     main()
 +
 </code> </code>
  
python/deezer-album-tracker.1711645438.txt.gz · Last modified: 2024/03/28 17:03 by Wulf Rajek