commit ac86d5a31ed63c5be7e51b33e11175e6c4fbc8b4
parent dc54e0964ba42fe8d56b8afd8be7d103c123b461
Author: pyratebeard <root@pyratebeard.net>
Date: Mon, 12 Jan 2026 10:51:40 +0000
feat: wmt script
is used for sending an automated toot to my mastodon profile listing the music that has been listened to on my navidrome server since the previous monday
Diffstat:
| A | wmt.py | | | 146 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 146 insertions(+), 0 deletions(-)
diff --git a/wmt.py b/wmt.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+"""
+ ██
+ ░██
+ ███ ██ ██████████ ██████
+ ░░██ █ ░██░░██░░██░░██░░░██░
+ ░██ ███░██ ░██ ░██ ░██ ░██
+ ░████░████ ░██ ░██ ░██ ░██
+ ███░ ░░░██ ███ ░██ ░██ ░░██
+ ░░░ ░░░ ░░░ ░░ ░░ ░░
+w e e k l y m u s i c t o o t
+
+ author ▓▒ pyratebeard <root@pyratebeard.net>
+ code ▓▒ https://git.pyratebeard.net/wmt
+
+`wmt` is used for sending an automated toot
+to my mastodon profile listing the music that
+has been listened to on my navidrome server
+since the previous monday.
+
+it is an advancement of my wmt script used
+with cmus. since i am on the move a bit more
+i don't use cmus all the time. i also wanted
+to include music that i listen to outside of
+work.
+
+the main difference is the cmus script put
+the list into most to least played. this one
+does not, yet. i would like to combine the
+two lists if possible but for now this will
+be the list posted to mastodon.
+"""
+
+import requests
+import os
+import datetime
+from dotenv import load_dotenv, dotenv_values
+from subprocess import check_output
+from mastodon import Mastodon
+
+# pull vars and secrets from .env file
+# if the file does not exist write the
+# required vars to a new file and exit
+var_file = '.env'
+local_vars = ['NAVIDROME_URL', # instance url
+ 'USERNAME', # navidrome username
+ 'PASSWORD', # navidrome password
+ 'ALBUM_LIMIT', # request result album limit, default 20
+ 'NTFY_URL', # instance and tag url
+ 'MASTODON_URL', # instance url
+ 'ACCESS_TOKEN'] # app access token
+
+if not os.path.exists(var_file):
+ # add `=""` to each var to make it as
+ # easy as possible to populate
+ content = '=""\n'.join(local_vars) + '=""\n'
+ with open(var_file, "x", encoding="utf-8") as f:
+ f.writelines(content)
+ print(f"local var file {var_file} created\npopulate and run again")
+ exit()
+else:
+ load_dotenv()
+
+# log in to navidrome instance
+NAVIDROME_URL = os.getenv('NAVIDROME_URL')
+login_url = f'{NAVIDROME_URL}/auth/login'
+login_data = {
+ 'username': os.getenv("USERNAME"),
+ 'password': os.getenv("PASSWORD")
+}
+
+try:
+ login_res = requests.post(login_url, json=login_data)
+ login_res.raise_for_status()
+ token = login_res.json().get('token')
+ if not token:
+ print("login succeeded but no token received.")
+ exit()
+except Exception as e:
+ print(f"login failed: {e}")
+ exit()
+
+headers = {
+ 'X-ND-Authorization': f'Bearer {token}'
+}
+
+# set data and pull album list
+params = {
+ '_start': 0,
+ '_end': os.getenv("ALBUM_LIMIT", 20),
+ '_sort': 'play_date',
+ '_order': 'DESC',
+ 'recently_played': 'true'
+}
+
+try:
+ res = requests.get(f'{NAVIDROME_URL}/api/album', headers=headers, params=params)
+ res.raise_for_status()
+ albums = res.json()
+except Exception as e:
+ print(f"failed to fetch albums: {e}")
+ exit()
+
+# get last monday date to start new week
+today = datetime.date.today()
+monday = today - datetime.timedelta(days=today.weekday())
+
+# find all albums played since monday
+week_music = []
+for a in albums:
+ play_date = datetime.datetime.fromisoformat(a.get('playDate'))
+ if play_date.date() >= monday:
+ week_music.append(f"{a['name']} by {a['artist']}")
+
+# compose toot
+toot = (f"""(automated) #weeklymusictoot
+
+this week i listened to:
+
+""")
+
+# 500 char max
+# toot is 54 chars inc newlines
+# albums no more than 446 so slice
+# last album until list fits
+while True:
+ char_count = sum(len(s) for s in week_music)
+ if char_count > 446:
+ week_music = week_music[:-1]
+ else:
+ break
+
+# add albums to toot
+for album in week_music:
+ toot += f"* {album}\n"
+
+# post toot
+try:
+ MASTODON_URL = os.getenv("MASTODON_URL")
+ mastodon = Mastodon(api_base_url = MASTODON_URL, access_token = ACCESS_TOKEN)
+ mastodon.toot(toot)
+except Exception as e:
+ NTFY_URL = os.getenv("NTFY_URL")
+ requests.post(NTFY_URL,
+ data="wmt toot failed".encode(encoding='utf-8'))
+ exit()