wmt

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

wmt.py (4422B)


      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 cwd = os.path.dirname(os.path.realpath(__file__))
     45 var_file = cwd + '/.env'
     46 local_vars = ['NAVIDROME_URL', # instance url
     47               'USERNAME',      # navidrome username
     48               'PASSWORD',      # navidrome password
     49               'ALBUM_LIMIT',   # request result album limit, default 20
     50               'NTFY_URL',      # instance and tag url
     51               'MASTODON_URL',  # instance url
     52               'ACCESS_TOKEN']  # app access token
     53 
     54 if not os.path.exists(var_file):
     55     # add `=""` to each var to make it as
     56     # easy as possible to populate
     57     content = '=""\n'.join(local_vars) + '=""\n'
     58     with open(var_file, "x", encoding="utf-8") as f:
     59         f.writelines(content)
     60     print(f"local var file {var_file} created\npopulate and run again")
     61     exit()
     62 else:
     63     load_dotenv()
     64 
     65 # log in to navidrome instance
     66 NAVIDROME_URL = os.getenv('NAVIDROME_URL')
     67 login_url = f'{NAVIDROME_URL}/auth/login'
     68 login_data = {
     69     'username': os.getenv("USERNAME"),
     70     'password': os.getenv("PASSWORD")
     71 }
     72 
     73 try:
     74     login_res = requests.post(login_url, json=login_data)
     75     login_res.raise_for_status()
     76     token = login_res.json().get('token')
     77     if not token:
     78         print("login succeeded but no token received.")
     79         exit()
     80 except Exception as e:
     81     print(f"login failed: {e}")
     82     exit()
     83 
     84 headers = {
     85     'X-ND-Authorization': f'Bearer {token}'
     86 }
     87 
     88 # set data and pull album list
     89 params = {
     90     '_start': 0,
     91     '_end': os.getenv("ALBUM_LIMIT", 20),
     92     '_sort': 'play_date',
     93     '_order': 'DESC',
     94     'recently_played': 'true'
     95 }
     96 
     97 try:
     98     res = requests.get(f'{NAVIDROME_URL}/api/album', headers=headers, params=params)
     99     res.raise_for_status()
    100     albums = res.json()
    101 except Exception as e:
    102     print(f"failed to fetch albums: {e}")
    103     exit()
    104 
    105 # get last monday date to start new week
    106 today = datetime.date.today()
    107 monday = today - datetime.timedelta(days=today.weekday())
    108 
    109 # find all albums played since monday
    110 week_music = []
    111 for a in albums:
    112     play_date = datetime.datetime.fromisoformat(a.get('playDate'))
    113     if play_date.date() >= monday:
    114         week_music.append(f"{a['name']} by {a['artist']}")
    115 
    116 # compose toot
    117 toot = (f"""(automated) #weeklymusictoot
    118 
    119 this week i listened to:
    120 
    121 """)
    122 
    123 # 500 char max
    124 # toot is 54 chars inc newlines
    125 # albums no more than 446 so slice
    126 # last album until list fits
    127 while True:
    128     char_count = sum(len(s) for s in week_music)
    129     if char_count > 446:
    130         week_music = week_music[:-1]
    131     else:
    132         break
    133 
    134 # add albums to toot
    135 for album in week_music:
    136     toot += f"* {album}\n"
    137 
    138 # post toot
    139 try:
    140     MASTODON_URL = os.getenv("MASTODON_URL")
    141     ACCESS_TOKEN = os.getenv("ACCESS_TOKEN")
    142     mastodon = Mastodon(api_base_url = MASTODON_URL, access_token = ACCESS_TOKEN)
    143     mastodon.toot(toot)
    144 except Exception as e:
    145     NTFY_URL = os.getenv("NTFY_URL")
    146     requests.post(NTFY_URL,
    147         data="wmt toot failed".encode(encoding='utf-8'))
    148     exit()