wmt

weekly music toot
git clone git://git.pyratebeard.net/wmt.git
Log | Files | Refs | README

wmt.py (4320B)


      1 #!/usr/bin/env python
      2 """
      3                             ██
      4                            ░██
      5    ███     ██ ██████████  ██████
      6   ░░██  █ ░██░░██░░██░░██░░░██░
      7    ░██ ███░██ ░██ ░██ ░██  ░██
      8    ░████░████ ░██ ░██ ░██  ░██
      9    ███░ ░░░██ ███ ░██ ░██  ░░██
     10   ░░░    ░░░ ░░░  ░░  ░░    ░░
     11 w e e k l y   m u s i c   t o o t
     12 
     13  author ▓▒ pyratebeard <root@pyratebeard.net>
     14    code ▓▒ https://git.pyratebeard.net/wmt
     15 
     16 `wmt` is used for sending an automated toot
     17 to my mastodon profile listing the music that
     18 has been listened to on my navidrome server
     19 since the previous monday.
     20 
     21 it is an advancement of my wmt script used
     22 with cmus. since i am on the move a bit more
     23 i don't use cmus all the time. i also wanted
     24 to include music that i listen to outside of
     25 work.
     26 
     27 the main difference is the cmus script put
     28 the list into most to least played. this one
     29 does not, yet. i would like to combine the
     30 two lists if possible but for now this will
     31 be the list posted to mastodon.
     32 """
     33 
     34 import requests
     35 import os
     36 import datetime
     37 from dotenv import load_dotenv, dotenv_values
     38 from subprocess import check_output
     39 from mastodon import Mastodon
     40 
     41 # pull vars and secrets from .env file
     42 # if the file does not exist write the
     43 # required vars to a new file and exit
     44 var_file = '.env'
     45 local_vars = ['NAVIDROME_URL', # instance url
     46               'USERNAME',      # navidrome username
     47               'PASSWORD',      # navidrome password
     48               'ALBUM_LIMIT',   # request result album limit, default 20
     49               'NTFY_URL',      # instance and tag url
     50               'MASTODON_URL',  # instance url
     51               'ACCESS_TOKEN']  # app access token
     52 
     53 if not os.path.exists(var_file):
     54     # add `=""` to each var to make it as
     55     # easy as possible to populate
     56     content = '=""\n'.join(local_vars) + '=""\n'
     57     with open(var_file, "x", encoding="utf-8") as f:
     58         f.writelines(content)
     59     print(f"local var file {var_file} created\npopulate and run again")
     60     exit()
     61 else:
     62     load_dotenv()
     63 
     64 # log in to navidrome instance
     65 NAVIDROME_URL = os.getenv('NAVIDROME_URL')
     66 login_url = f'{NAVIDROME_URL}/auth/login'
     67 login_data = {
     68     'username': os.getenv("USERNAME"),
     69     'password': os.getenv("PASSWORD")
     70 }
     71 
     72 try:
     73     login_res = requests.post(login_url, json=login_data)
     74     login_res.raise_for_status()
     75     token = login_res.json().get('token')
     76     if not token:
     77         print("login succeeded but no token received.")
     78         exit()
     79 except Exception as e:
     80     print(f"login failed: {e}")
     81     exit()
     82 
     83 headers = {
     84     'X-ND-Authorization': f'Bearer {token}'
     85 }
     86 
     87 # set data and pull album list
     88 params = {
     89     '_start': 0,
     90     '_end': os.getenv("ALBUM_LIMIT", 20),
     91     '_sort': 'play_date',
     92     '_order': 'DESC',
     93     'recently_played': 'true'
     94 }
     95 
     96 try:
     97     res = requests.get(f'{NAVIDROME_URL}/api/album', headers=headers, params=params)
     98     res.raise_for_status()
     99     albums = res.json()
    100 except Exception as e:
    101     print(f"failed to fetch albums: {e}")
    102     exit()
    103 
    104 # get last monday date to start new week
    105 today = datetime.date.today()
    106 monday = today - datetime.timedelta(days=today.weekday())
    107 
    108 # find all albums played since monday
    109 week_music = []
    110 for a in albums:
    111     play_date = datetime.datetime.fromisoformat(a.get('playDate'))
    112     if play_date.date() >= monday:
    113         week_music.append(f"{a['name']} by {a['artist']}")
    114 
    115 # compose toot
    116 toot = (f"""(automated) #weeklymusictoot
    117 
    118 this week i listened to:
    119 
    120 """)
    121 
    122 # 500 char max
    123 # toot is 54 chars inc newlines
    124 # albums no more than 446 so slice
    125 # last album until list fits
    126 while True:
    127     char_count = sum(len(s) for s in week_music)
    128     if char_count > 446:
    129         week_music = week_music[:-1]
    130     else:
    131         break
    132 
    133 # add albums to toot
    134 for album in week_music:
    135     toot += f"* {album}\n"
    136 
    137 # post toot
    138 try:
    139     MASTODON_URL = os.getenv("MASTODON_URL")
    140     mastodon = Mastodon(api_base_url = MASTODON_URL, access_token = ACCESS_TOKEN)
    141     mastodon.toot(toot)
    142 except Exception as e:
    143     NTFY_URL = os.getenv("NTFY_URL")
    144     requests.post(NTFY_URL,
    145         data="wmt toot failed".encode(encoding='utf-8'))
    146     exit()