From 8e346118a79ff9eda54b3e3e73e12c5a389b3014 Mon Sep 17 00:00:00 2001 From: km222uq Date: Tue, 21 Oct 2025 23:17:23 +0200 Subject: [PATCH 1/9] git ignore update --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index b080932..840820e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ venv/ # Python cache __pycache__/ + +# egg +*.egg-info/ From d832bd1df98063c2376afc8513e883a408d8e753 Mon Sep 17 00:00:00 2001 From: km222uq Date: Tue, 21 Oct 2025 23:26:38 +0200 Subject: [PATCH 2/9] split player utils into two files for linux and mac to not double the file length and keep logic seperated --- src/songfetch/__init__.py | 10 + ...{player_utils.py => player_utils_linux.py} | 0 src/songfetch/player_utils_mac.py | 259 ++++++++++++++++++ 3 files changed, 269 insertions(+) rename src/songfetch/{player_utils.py => player_utils_linux.py} (100%) create mode 100644 src/songfetch/player_utils_mac.py diff --git a/src/songfetch/__init__.py b/src/songfetch/__init__.py index e69de29..e00677a 100644 --- a/src/songfetch/__init__.py +++ b/src/songfetch/__init__.py @@ -0,0 +1,10 @@ +import platform + +if platform.system() == 'Darwin': + from .player_utils_mac import * +elif platform.system() == 'Linux': + from .player_utils_linux import * +else: + # Fallback to Linux for other systems + from .player_utils_linux import * + diff --git a/src/songfetch/player_utils.py b/src/songfetch/player_utils_linux.py similarity index 100% rename from src/songfetch/player_utils.py rename to src/songfetch/player_utils_linux.py diff --git a/src/songfetch/player_utils_mac.py b/src/songfetch/player_utils_mac.py new file mode 100644 index 0000000..e8d779e --- /dev/null +++ b/src/songfetch/player_utils_mac.py @@ -0,0 +1,259 @@ +import subprocess +import getpass + +# Default values for fallback +DEFAULTS = { + "player_name": "No player", + "art": "", + "title": "No title found", + "artist": "No artist found", + "album": "No album found", + "duration_formatted": "00:00", + "volume": "Unknown", + "position": 0, + "duration": 0, + "url": "No URL found", + "status": "No status", + "loop": "Unknown", + "shuffle": "Unknown", + "user": "No User" +} + + +def run_applescript(script): + """Helper to run AppleScript and return output""" + try: + result = subprocess.run([ + "osascript", "-e", script + ], capture_output=True, text=True) + return result.stdout.strip() + except Exception: + return "" + + +def get_backend(): + return "CoreAudio" + + +def get_player_name(): + try: + # Check if Music app is running + script = ''' + tell application "System Events" + if exists (processes where name is "Music") then + return "Music" + else + return "" + end if + end tell + ''' + if run_applescript(script): + return "Music" + return DEFAULTS["player_name"] + except Exception: + return DEFAULTS["player_name"] + + +def get_art(): + # Mac album art is harder to get via AppleScript, return default + return DEFAULTS["art"] + + +def get_title(): + try: + script = ''' + tell application "Music" + if player state is playing or player state is paused then + return name of current track + else + return "" + end if + end tell + ''' + title = run_applescript(script) + return title if title else DEFAULTS["title"] + except Exception: + return DEFAULTS["title"] + + +def get_artist(): + try: + script = ''' + tell application "Music" + if player state is playing or player state is paused then + return artist of current track + else + return "" + end if + end tell + ''' + artist = run_applescript(script) + return artist if artist else DEFAULTS["artist"] + except Exception: + return DEFAULTS["artist"] + + +def get_album(): + try: + script = ''' + tell application "Music" + if player state is playing or player state is paused then + return album of current track + else + return "" + end if + end tell + ''' + album = run_applescript(script) + return album if album else DEFAULTS["album"] + except Exception: + return DEFAULTS["album"] + + +def get_duration_formatted(): + try: + script = ''' + tell application "Music" + if player state is playing or player state is paused then + set dur to duration of current track + set mins to dur div 60 + set secs to dur mod 60 + return (mins as string) & ":" & (secs as string) + else + return "00:00" + end if + end tell + ''' + duration = run_applescript(script) + return duration if duration else DEFAULTS["duration_formatted"] + except Exception: + return DEFAULTS["duration_formatted"] + + +def get_volume(): + try: + script = ''' + set vol to output volume of (get volume settings) + return vol as string + ''' + vol = run_applescript(script) + if vol.isdigit(): + return f"{vol}%" + return DEFAULTS["volume"] + except Exception: + return DEFAULTS["volume"] + + +def get_position(): + try: + script = ''' + tell application "Music" + if player state is playing or player state is paused then + return player position + else + return 0 + end if + end tell + ''' + pos = run_applescript(script) + try: + return int(float(pos)) + except ValueError: + return DEFAULTS["position"] + except Exception: + return DEFAULTS["position"] + + +def get_duration(): + try: + script = ''' + tell application "Music" + if player state is playing or player state is paused then + return duration of current track + else + return 0 + end if + end tell + ''' + dur = run_applescript(script) + try: + return int(float(dur)) + except ValueError: + return DEFAULTS["duration"] + except Exception: + return DEFAULTS["duration"] + + +def get_url(): + # Mac doesn't typically have URLs for local tracks + return DEFAULTS["url"] + + +def get_status(): + try: + script = ''' + tell application "Music" + set state to player state + if state is playing then + return "Playing" + else if state is paused then + return "Paused" + else + return "Stopped" + end if + end tell + ''' + status = run_applescript(script) + return status if status else DEFAULTS["status"] + except Exception: + return DEFAULTS["status"] + + +def get_loop(): + try: + script = ''' + tell application "Music" + if player state is playing or player state is paused then + if repeat is on then + return "On" + else + return "Off" + end if + else + return "Unknown" + end if + end tell + ''' + loop = run_applescript(script) + return loop if loop else DEFAULTS["loop"] + except Exception: + return DEFAULTS["loop"] + + +def get_shuffle(): + try: + script = ''' + tell application "Music" + if player state is playing or player state is paused then + if shuffle is on then + return "On" + else + return "Off" + end if + else + return "Unknown" + end if + end tell + ''' + shuffle = run_applescript(script) + return shuffle if shuffle else DEFAULTS["shuffle"] + except Exception: + return DEFAULTS["shuffle"] + + +def get_user(): + try: + username = getpass.getuser() + return username if username else DEFAULTS["user"] + except Exception: + return DEFAULTS["user"] From b6949dee33d0aa4e2eb32dcddb9814080f673069 Mon Sep 17 00:00:00 2001 From: km222uq Date: Tue, 21 Oct 2025 23:28:10 +0200 Subject: [PATCH 3/9] change ascii conv due to errors --- src/songfetch/ascii_convert.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/songfetch/ascii_convert.py b/src/songfetch/ascii_convert.py index a8788a8..59dcb31 100644 --- a/src/songfetch/ascii_convert.py +++ b/src/songfetch/ascii_convert.py @@ -1,17 +1,25 @@ -import ascii_magic as magic, urllib.parse, urllib.request, tempfile +import ascii_magic as magic +import urllib.parse +import urllib.request +import tempfile from importlib import resources + def default_art(file="../assets/default_art.txt"): # Get the default music note art from file - with resources.files("songfetch.assets").joinpath("default_art.txt").open("r", encoding="utf-8") as f: + with resources.files("songfetch.assets").joinpath( + "default_art.txt" + ).open("r", encoding="utf-8") as f: return f.read().split('\n') # Art to ASCII + + def convert(art_uri): # Init variables ascii_art_lines = None # Check file type - if art_uri is None or art_uri.strip() == "": # If return empty string + if art_uri is None or art_uri.strip() == "": # If return empty string return default_art() # We need to check each URI type @@ -22,7 +30,7 @@ def convert(art_uri): # Decode to get rid of possible "%20%20..." ascii_art = magic.from_image(urllib.parse.unquote(new_uri)) # Convert to ascii - ascii_string = ascii_art.to_ascii(columns = 60, width_ratio = 2.2) + ascii_string = ascii_art.to_ascii(columns=60, width_ratio=2.2) ascii_art_lines = ascii_string.split('\n') # Catch the error @@ -39,11 +47,11 @@ def convert(art_uri): urllib.request.urlretrieve(art_uri, temp.name) ascii_art = magic.from_image(temp.name) # Convert to ascii - ascii_string = ascii_art.to_ascii(columns = 60, width_ratio = 2.2) + ascii_string = ascii_art.to_ascii(columns=60, width_ratio=2.2) ascii_art_lines = ascii_string.split('\n') # Catch the error - except Exception as e : + except Exception as e: return default_art() # Edge cases @@ -55,4 +63,3 @@ def convert(art_uri): return ascii_art_lines else: return default_art() - From ebf5ec2f38a3df63d64c8e29ac7a40a434f09170 Mon Sep 17 00:00:00 2001 From: km222uq Date: Tue, 21 Oct 2025 23:37:35 +0200 Subject: [PATCH 4/9] player utils port for mac --- src/songfetch/player_utils_mac.py | 335 ++++++++++++++++++++---------- 1 file changed, 226 insertions(+), 109 deletions(-) diff --git a/src/songfetch/player_utils_mac.py b/src/songfetch/player_utils_mac.py index e8d779e..14e6afd 100644 --- a/src/songfetch/player_utils_mac.py +++ b/src/songfetch/player_utils_mac.py @@ -19,6 +19,15 @@ "user": "No User" } +# Supported players and their AppleScript apps +SUPPORTED_PLAYERS = { + "Spotify": "Spotify", + "Music": "Music", + "iTunes": "iTunes", # For older macOS +} + +_current_player = None + def run_applescript(script): """Helper to run AppleScript and return output""" @@ -31,103 +40,167 @@ def run_applescript(script): return "" -def get_backend(): - return "CoreAudio" - +def detect_current_player(): + """Detect which media player is currently active/playing""" + global _current_player -def get_player_name(): - try: - # Check if Music app is running - script = ''' + for player_name, app_name in SUPPORTED_PLAYERS.items(): + script = f''' tell application "System Events" - if exists (processes where name is "Music") then - return "Music" - else - return "" + if exists (processes where name is "{app_name}") then + tell application "{app_name}" + if player state is playing or player state is paused then + return "{player_name}" + end if + end tell end if end tell + return "" ''' - if run_applescript(script): - return "Music" - return DEFAULTS["player_name"] - except Exception: - return DEFAULTS["player_name"] + result = run_applescript(script) + if result: + _current_player = result + return result + + _current_player = None + return None + + +def get_current_player(): + """Get the current player, detecting if not set""" + if _current_player is None: + detect_current_player() + return _current_player + + +def get_player_name(): + player = get_current_player() + if player: + return player + return DEFAULTS["player_name"] def get_art(): - # Mac album art is harder to get via AppleScript, return default + # Album art is not easily accessible via AppleScript for most players return DEFAULTS["art"] def get_title(): - try: + player = get_current_player() + if not player: + return DEFAULTS["title"] + + app_name = SUPPORTED_PLAYERS.get(player, "Music") + + if player == "Spotify": script = ''' - tell application "Music" + tell application "Spotify" + if player state is playing or player state is paused then + return name of current track + end if + end tell + ''' + else: # Music or iTunes + script = f''' + tell application "{app_name}" if player state is playing or player state is paused then return name of current track - else - return "" end if end tell ''' - title = run_applescript(script) - return title if title else DEFAULTS["title"] - except Exception: - return DEFAULTS["title"] + + title = run_applescript(script) + return title if title else DEFAULTS["title"] def get_artist(): - try: + player = get_current_player() + if not player: + return DEFAULTS["artist"] + + app_name = SUPPORTED_PLAYERS.get(player, "Music") + + if player == "Spotify": script = ''' - tell application "Music" + tell application "Spotify" + if player state is playing or player state is paused then + return artist of current track + end if + end tell + ''' + else: + script = f''' + tell application "{app_name}" if player state is playing or player state is paused then return artist of current track - else - return "" end if end tell ''' - artist = run_applescript(script) - return artist if artist else DEFAULTS["artist"] - except Exception: - return DEFAULTS["artist"] + + artist = run_applescript(script) + return artist if artist else DEFAULTS["artist"] def get_album(): - try: + player = get_current_player() + if not player: + return DEFAULTS["album"] + + app_name = SUPPORTED_PLAYERS.get(player, "Music") + + if player == "Spotify": script = ''' - tell application "Music" + tell application "Spotify" + if player state is playing or player state is paused then + return album of current track + end if + end tell + ''' + else: + script = f''' + tell application "{app_name}" if player state is playing or player state is paused then return album of current track - else - return "" end if end tell ''' - album = run_applescript(script) - return album if album else DEFAULTS["album"] - except Exception: - return DEFAULTS["album"] + + album = run_applescript(script) + return album if album else DEFAULTS["album"] def get_duration_formatted(): - try: + player = get_current_player() + if not player: + return DEFAULTS["duration_formatted"] + + app_name = SUPPORTED_PLAYERS.get(player, "Music") + + if player == "Spotify": script = ''' - tell application "Music" + tell application "Spotify" if player state is playing or player state is paused then set dur to duration of current track set mins to dur div 60 set secs to dur mod 60 - return (mins as string) & ":" & (secs as string) - else - return "00:00" + return (mins as string) & ":" & text -2 thru -1 of ("0" & secs) end if end tell ''' - duration = run_applescript(script) - return duration if duration else DEFAULTS["duration_formatted"] - except Exception: - return DEFAULTS["duration_formatted"] + else: + script = f''' + tell application "{app_name}" + if player state is playing or player state is paused then + set dur to duration of current track + set mins to dur div 60 + set secs to dur mod 60 + return (mins as string) & ":" & text -2 thru -1 of ("0" & secs) + end if + end tell + ''' + + duration = run_applescript(script) + return duration if duration else DEFAULTS["duration_formatted"] def get_volume(): @@ -145,110 +218,149 @@ def get_volume(): def get_position(): + player = get_current_player() + if not player: + return DEFAULTS["position"] + + app_name = SUPPORTED_PLAYERS.get(player, "Music") + + script = f''' + tell application "{app_name}" + if player state is playing or player state is paused then + return player position + end if + end tell + ''' + + pos = run_applescript(script) try: - script = ''' - tell application "Music" - if player state is playing or player state is paused then - return player position - else - return 0 - end if - end tell - ''' - pos = run_applescript(script) - try: - return int(float(pos)) - except ValueError: - return DEFAULTS["position"] - except Exception: + return int(float(pos)) + except ValueError: return DEFAULTS["position"] def get_duration(): - try: + player = get_current_player() + if not player: + return DEFAULTS["duration"] + + app_name = SUPPORTED_PLAYERS.get(player, "Music") + + if player == "Spotify": script = ''' - tell application "Music" + tell application "Spotify" if player state is playing or player state is paused then return duration of current track - else - return 0 end if end tell ''' - dur = run_applescript(script) - try: - return int(float(dur)) - except ValueError: - return DEFAULTS["duration"] - except Exception: + else: + script = f''' + tell application "{app_name}" + if player state is playing or player state is paused then + return duration of current track + end if + end tell + ''' + + dur = run_applescript(script) + try: + return int(float(dur)) + except ValueError: return DEFAULTS["duration"] def get_url(): - # Mac doesn't typically have URLs for local tracks + # URLs are not typically available for local tracks return DEFAULTS["url"] def get_status(): - try: - script = ''' - tell application "Music" - set state to player state - if state is playing then - return "Playing" - else if state is paused then - return "Paused" - else - return "Stopped" - end if - end tell - ''' - status = run_applescript(script) - return status if status else DEFAULTS["status"] - except Exception: + player = get_current_player() + if not player: return DEFAULTS["status"] + app_name = SUPPORTED_PLAYERS.get(player, "Music") + + script = f''' + tell application "{app_name}" + set state to player state + if state is playing then + return "Playing" + else if state is paused then + return "Paused" + else + return "Stopped" + end if + end tell + ''' + + status = run_applescript(script) + return status if status else DEFAULTS["status"] + def get_loop(): - try: - script = ''' - tell application "Music" + player = get_current_player() + if not player: + return DEFAULTS["loop"] + + app_name = SUPPORTED_PLAYERS.get(player, "Music") + + if player == "Spotify": + # Spotify doesn't have loop in AppleScript, return Unknown + return DEFAULTS["loop"] + else: + script = f''' + tell application "{app_name}" if player state is playing or player state is paused then if repeat is on then return "On" else return "Off" end if - else - return "Unknown" end if end tell ''' - loop = run_applescript(script) - return loop if loop else DEFAULTS["loop"] - except Exception: - return DEFAULTS["loop"] + + loop = run_applescript(script) + return loop if loop else DEFAULTS["loop"] def get_shuffle(): - try: + player = get_current_player() + if not player: + return DEFAULTS["shuffle"] + + app_name = SUPPORTED_PLAYERS.get(player, "Music") + + if player == "Spotify": + # Spotify shuffle status via AppleScript script = ''' - tell application "Music" + tell application "Spotify" + if player state is playing or player state is paused then + if shuffling is true then + return "On" + else + return "Off" + end if + end if + end tell + ''' + else: + script = f''' + tell application "{app_name}" if player state is playing or player state is paused then if shuffle is on then return "On" else return "Off" end if - else - return "Unknown" end if end tell ''' - shuffle = run_applescript(script) - return shuffle if shuffle else DEFAULTS["shuffle"] - except Exception: - return DEFAULTS["shuffle"] + + shuffle = run_applescript(script) + return shuffle if shuffle else DEFAULTS["shuffle"] def get_user(): @@ -257,3 +369,8 @@ def get_user(): return username if username else DEFAULTS["user"] except Exception: return DEFAULTS["user"] + + +# Backend is CoreAudio +def get_backend(): + return "CoreAudio" From 0ef16dbf44db4cb5e76ee1608c53edbbf751c896 Mon Sep 17 00:00:00 2001 From: km222uq Date: Tue, 21 Oct 2025 23:40:36 +0200 Subject: [PATCH 5/9] crashed fix: changes to help mac compatibility and remove crashes --- src/songfetch/main.py | 77 ++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/src/songfetch/main.py b/src/songfetch/main.py index 0c8c5b0..2a59234 100755 --- a/src/songfetch/main.py +++ b/src/songfetch/main.py @@ -1,6 +1,6 @@ import os from songfetch.ascii_convert import convert -from songfetch.player_utils import ( +from songfetch import ( get_art, get_loop, get_shuffle, @@ -18,6 +18,7 @@ get_position ) + def progress_bar(): # Calculate percentage pos = get_position() @@ -46,6 +47,7 @@ def progress_bar(): return fprint + eprint + display_str + def get_info_line(): # Get some strings to use later line = f"\033[34m─────────────────────────────────────────\033[0m" @@ -65,34 +67,36 @@ def get_info_line(): # Here we concatenate all the info into one list # Use ANSI escape sequences to style the colors info_lines = [ - # Print username and track data - f"\033[1;34m{get_user()}\033[0m@\033[1;34m{get_player_name()}\033[0m", - line, f"\033[97m{now_playing}\033[0m", line, - f"\033[34mTitle\033[0m: {get_title()}", - f"\033[34mArtist\033[0m: {get_artist()}", - f"\033[34mAlbum\033[0m: {get_album()}", - f"\033[34mDuration\033[0m: {get_duration_formatted()}", - f"\033[34m{progress_bar()}\033[0m", - - # Print player data - line, f"\033[97m{playback_info}\033[0m", line, - f"\033[34mStatus\033[0m: {get_status()}", - f"\033[34mVolume\033[0m: {get_volume()}", - f"\033[34mLoop\033[0m: {get_loop()}", - f"\033[34mShuffle\033[0m: {get_shuffle()}", - f"\033[34mPlayer\033[0m: {get_player_name()}", - f"\033[34mURL\033[0m: {get_url()}", - - # Print system data - line, f"\033[97m{audio_system}\033[0m", line, - f"\033[34mBackend\033[0m: {get_backend()}", - "", - # Print palette - normal, bright -] + # Print username and track data + f"\033[1;34m{get_user()}\033[0m@\033[1;34m{get_player_name()}\033[0m", + line, f"\033[97m{now_playing}\033[0m", line, + f"\033[34mTitle\033[0m: {get_title()}", + f"\033[34mArtist\033[0m: {get_artist()}", + f"\033[34mAlbum\033[0m: {get_album()}", + f"\033[34mDuration\033[0m: {get_duration_formatted()}", + f"\033[34m{progress_bar()}\033[0m", + + # Print player data + line, f"\033[97m{playback_info}\033[0m", line, + f"\033[34mStatus\033[0m: {get_status()}", + f"\033[34mVolume\033[0m: {get_volume()}", + f"\033[34mLoop\033[0m: {get_loop()}", + f"\033[34mShuffle\033[0m: {get_shuffle()}", + f"\033[34mPlayer\033[0m: {get_player_name()}", + f"\033[34mURL\033[0m: {get_url()}", + + # Print system data + line, f"\033[97m{audio_system}\033[0m", line, + f"\033[34mBackend\033[0m: {get_backend()}", + "", + # Print palette + normal, bright + ] return info_lines # Main function + + def main(): # Get terminal size columns = os.get_terminal_size().columns @@ -107,25 +111,36 @@ def main(): else: art_col = convert(get_art()) # Find the longest line in both column lists - max_art = max(len(x) for x in art_col) + if art_col: + max_art = max(len(x) for x in art_col) + else: + max_art = 0 # Always get info lines though info_col = get_info_line() - max_info = max(len(y) for y in info_col[:-2]) + if len(info_col) > 2: + max_info = max(len(y) for y in info_col[:-2]) + else: + max_info = 0 + + # Ensure minimum widths, caused crashes by empty art/info + art_width = max(1, max_art - 2) + info_width = max(1, max_info) - # Print lists next to each other when one list may be longer than the other: + # Print lists next to each other when one may be longer if len(art_col) > len(info_col): # Compare lenghts # Replace but with added padding (spaces) new_info_col = info_col + [''] * (len(art_col) - len(info_col)) # Loop through all lines in art for i in range(len(art_col)): - print(f"{art_col[i]:{max_art-2}}{new_info_col[i]:{max_info}}") + print(f"{art_col[i]:{art_width}}{new_info_col[i]:{info_width}}") else: # Pad but the othre way around new_art_col = art_col + [''] * (len(info_col) - len(art_col)) # Loop all lines in info for j in range(len(info_col)): - print(f"{new_art_col[j]:{max_art-2}}{info_col[j]:{max_info}}") + print(f"{new_art_col[j]:{art_width}}{info_col[j]:{info_width}}") + # Run the program if __name__ == "__main__": From 82d739a6135184862c0a9a804e624f492249275e Mon Sep 17 00:00:00 2001 From: km222uq Date: Tue, 21 Oct 2025 23:41:01 +0200 Subject: [PATCH 6/9] brew formula --- .github/workflows/update-formula.yml | 36 ++++++++++++++++++++++++++++ Formula/songfetch.rb | 17 +++++++++++++ pyproject.toml | 1 + 3 files changed, 54 insertions(+) create mode 100644 .github/workflows/update-formula.yml create mode 100644 Formula/songfetch.rb diff --git a/.github/workflows/update-formula.yml b/.github/workflows/update-formula.yml new file mode 100644 index 0000000..1fbd60f --- /dev/null +++ b/.github/workflows/update-formula.yml @@ -0,0 +1,36 @@ +name: Update Homebrew Formula + +on: + release: + types: [published] + +jobs: + update-formula: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Get release version + id: release + run: | + VERSION=${GITHUB_REF#refs/tags/v} + echo "version=$VERSION" >> $GITHUB_OUTPUT + - name: Download tarball and compute SHA256 + run: | + curl -sL https://github.com/${{ github.repository }}/archive/refs/tags/v${{ steps.release.outputs.version }}.tar.gz -o tarball.tar.gz + SHA256=$(shasum -a 256 tarball.tar.gz | cut -d' ' -f1) + echo "sha256=$SHA256" >> $GITHUB_ENV + sed -i "s|v1\.0\.2|v${{ steps.release.outputs.version }}|g" Formula/songfetch.rb + sed -i "s|PLACEHOLDER_SHA256|$SHA256|" Formula/songfetch.rb + - name: Commit and push changes + run: | + git add Formula/songfetch.rb + if git diff --cached --quiet; then + echo "No changes to commit" + else + git config --global user.name 'GitHub Actions' + git config --global user.email 'actions@github.com' + git commit -m "Update formula to v${{ steps.release.outputs.version }}" + git push + fi diff --git a/Formula/songfetch.rb b/Formula/songfetch.rb new file mode 100644 index 0000000..4a87190 --- /dev/null +++ b/Formula/songfetch.rb @@ -0,0 +1,17 @@ +class Songfetch < Formula + desc "A CLI tool that displays current song information in the terminal" + homepage "https://github.com/fwtwoo/songfetch" + url "https://github.com/fwtwoo/songfetch/archive/refs/tags/v1.0.2.tar.gz" + sha256 "71ba5a2649c59caa9bfb12ceb8077857241aed25a40631d78acbe634aa28f144" + license "GPL-2.0" + + depends_on "python@3.14" + + def install + system "python3", "-m", "pip", "install", "--prefix=#{prefix}", "." + end + + test do + system "#{bin}/songfetch", "--help" + end +end \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index b0ae020..4064ef4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", "Operating System :: POSIX :: Linux", + "Operating System :: MacOS", ] [project.scripts] From 1a514921b90b8c60a04d8f897d4469fe31753757 Mon Sep 17 00:00:00 2001 From: km222uq Date: Tue, 21 Oct 2025 23:41:15 +0200 Subject: [PATCH 7/9] innit for assets for import --- src/songfetch/assets/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/songfetch/assets/__init__.py diff --git a/src/songfetch/assets/__init__.py b/src/songfetch/assets/__init__.py new file mode 100644 index 0000000..e69de29 From 149a9fc7e5c193b2572151ba789884cfabe9f92f Mon Sep 17 00:00:00 2001 From: km222uq Date: Tue, 21 Oct 2025 23:45:12 +0200 Subject: [PATCH 8/9] sha256 hotfix --- Formula/songfetch.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Formula/songfetch.rb b/Formula/songfetch.rb index 4a87190..733b756 100644 --- a/Formula/songfetch.rb +++ b/Formula/songfetch.rb @@ -2,7 +2,7 @@ class Songfetch < Formula desc "A CLI tool that displays current song information in the terminal" homepage "https://github.com/fwtwoo/songfetch" url "https://github.com/fwtwoo/songfetch/archive/refs/tags/v1.0.2.tar.gz" - sha256 "71ba5a2649c59caa9bfb12ceb8077857241aed25a40631d78acbe634aa28f144" + sha256 "1b4c73283d7b5981b314ae3f77b6150947077aa505ab8869bb12bce0df6f7bf4" license "GPL-2.0" depends_on "python@3.14" From 3cbb1e6a79c126799afee3204706a8a3fb7235f8 Mon Sep 17 00:00:00 2001 From: km222uq Date: Tue, 21 Oct 2025 23:48:09 +0200 Subject: [PATCH 9/9] read me --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index acbc7da..a51fce0 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,13 @@ Then install the full program: yay -S songfetch ``` +## Installation (Homebrew/MacOS): + +```bash +brew tap fwtwoo/songfetch https://github.com/fwtwoo/songfetch +brew install songfetch +``` + ## Dependencies: ```bash python