melipass / lastfm-to-markdown

GitHub Actions workflow that automatically updates the covers from your last.fm's weekly chart everyday, inside your profile repository's README.md file. Useful for customizing your profile in repos named after your GitHub username.
MIT License
37 stars 5 forks source link

lastfm-to-markdown suggestions! #2

Open JAVAB3ANS opened 2 years ago

JAVAB3ANS commented 2 years ago

Hey! This project is pretty sick so on behalf of us music fans, I decided to make it so it would output 8 images (medium-sized) with white captions like how Last.FM collages generally do it so the cover wouldn't render in such a poor resolution for captions at the smallest size.

Here's how lastfmweekly.yml would look:

name: lastfmweekly

on:
  schedule:
    - cron: "2 0 * * *"
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  # This workflow contains a single job called "build"
  build:
    runs-on: ubuntu-latest
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - name: repo checkout
        uses: actions/checkout@v2

      - name: python setup
        uses: actions/setup-python@v2
        with:
          python-version: '3.x'

      - name: python packages installation
        run: |
          python -m pip install --upgrade pip
          pip install -r dependencies.txt
      - name: use lastfm api
        env:
          LASTFM_API_KEY: ${{ secrets.LASTFM_API_KEY }}
          LASTFM_USER: ${{ secrets.LASTFM_USER }}
          IMAGE_COUNT: 8
        run: python lastfm.py

      - name: commit changes
        continue-on-error: true
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git add -A
          git commit -m "Updated last.fm's weekly chart" -a

      - name: push changes
        continue-on-error: true
        uses: ad-m/github-push-action@v0.6.0
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}\
          branch: main

Here's how lastfm.py would look

import requests 
import sys
from PIL import Image, ImageFont, ImageDraw 
import urllib.request
import os

def lastfm_request(payload):
    headers = {"user-agent": os.getenv("LASTFM_USER")}
    payload["api_key"] = os.getenv("LASTFM_API_KEY")
    payload["format"] = "json"
    payload["user"] = os.getenv("LASTFM_USER")
    response = requests.get("https://ws.audioscrobbler.com/2.0/",
                            headers=headers, params=payload)
    return response

def get_weekly_album_chart():
    payload = {"method": "user.getweeklyalbumchart"}
    data = lastfm_request(payload).json()["weeklyalbumchart"]["album"]
    artist_and_album = []
    for i in range(len(data)):
        artist_and_album.append([data[i]["artist"]["#text"],
                                data[i]["name"]])
    return artist_and_album

def get_album_covers(artist_and_album):
    images = []
    for album in artist_and_album:
        payload = {"method": "album.getinfo",
                   "artist": album[0],
                   "album": album[1]}
        request_response = lastfm_request(payload).json()
        url = request_response["album"]["image"][2]["#text"] """ this would be "[2] medium" instead of "[1] small" since readers wouldn't be able to make this out """
        link_to_album = request_response["album"]["url"]
        if (url != ""):
            images.append([album[0], album[1], url, link_to_album]) 
    return images

def update_readme(images):
    with open("README.md", "r", encoding="utf-8") as file:
        readme = file.readlines()
    lastfm_line_index = readme.index("<!-- lastfm -->\n") + 1
    lastfm_line = '<p align="center">'
    i = 0
    for img in images:
        if (i < int(os.getenv("IMAGE_COUNT"))):
            if (requests.get(img[2]).status_code == 200):   

                list = ["album-covers", "album-covers-finished"]
                for items in list:
                    os.makedirs(items, exist_ok=True)

                urllib.request.urlretrieve(img[2], f"./album-covers/album-cover_{i}.png")
                my_image = Image.open(f"./album-covers/album-cover_{i}.png")  
                image_editable = ImageDraw.Draw(my_image) 
                image_editable.text((1,1), f"{img[0]}\n{img[1]}", (252, 255, 250), font=ImageFont.truetype("./fonts/basic_sans_serif_7.ttf", 10)) """ Locally download basic_sans_serif_7.ttf into /fonts/ directory for usage """
                my_image.save(f"./album-covers-finished/album-cover_final_{i}.png")

                lastfm_line += f'<a href="{img[3]}"><img src="./album-covers-finished/album-cover_final_{i}.png" title="{img[0]} - {img[1]}"></a> '
                i = i + 1
            else:
                pass
        else:
            break
    if (readme[lastfm_line_index] == lastfm_line):
        sys.exit(0)
    else:
        lastfm_line = lastfm_line + "</p>\n"
        readme[lastfm_line_index] = lastfm_line
    with open("README.md", "w", encoding="utf-8") as file:
        file.writelines(readme)

update_readme(get_album_covers(get_weekly_album_chart()))

For dependencies.txt, we'd only need to download one more module:

requests==2.25.1
Pillow==9.1.1

Here's how it would look on my end. Assuming that each album I've listened to has a Lastfm page, I've removed the if os.getenv("INCLUDE_LINK") == "false": portions and action.yml

image

Thanks a lot for looking at this, and I hope that I contributed in a constructive manner!

melipass commented 2 years ago

Hey @JAVAB3ANS, I love your changes! I know of several last.fm collage generators that add that text, but I didn't think about doing it for this project before, it's a great idea 😁

I don't have much free time right now, so I'll be able to take a deeper look at the code in a week or two. I actually like to have small covers in my profile, but it's just a personal preference and it would be great to add a variable to the .yml file to activate your changes. Feel free to open a pull request for this if you want.

Thank you so much for sharing this!

JAVAB3ANS commented 2 years ago

@melipass Yeah thanks so much! I'm nearly done with the current updates, but do let me know what you think before we can pull request!

Cheers,

@JAVAB3ANS