Add Apple Music integration for now playing

This commit is contained in:
2023-11-02 08:58:44 +11:00
parent c1d756ec6f
commit 4b6107188e
15 changed files with 183 additions and 0 deletions

1
.gitignore vendored
View File

@@ -21,3 +21,4 @@ config/systemd/que.service.erb
script/deploy
tmp/*
public/media
*.p8

View File

@@ -42,6 +42,7 @@ gem "ruby-filemagic", git: "https://github.com/dnitza/ruby-filemagic", branch: "
gem "webmention"
gem "sanitize"
gem "time_math2", require: "time_math"
gem "jwt"
gem "lastfm", "~> 1.27"
gem "mail"
gem "que"

View File

@@ -286,6 +286,7 @@ GEM
link-header-parser (~> 5.0)
nokogiri (>= 1.13)
json (2.6.3)
jwt (2.7.1)
language_server-protocol (3.17.0.3)
lastfm (1.27.4)
httparty
@@ -532,6 +533,7 @@ DEPENDENCIES
hanami-view!
httparty
image_processing (~> 1.0)
jwt
lastfm (~> 1.27)
mail
matrix

View File

@@ -0,0 +1,12 @@
module Adamantium
module Actions
module RecentlyPlayed
class Index < Action
include Deps["views.recently_played.index"]
def handle(req, res)
res.render index
end
end
end
end
end

View File

@@ -27,6 +27,10 @@ I currently live in Canberra with my partner and [our dogs](https://instagram.co
In my spare time I like to tinker on various Ruby projects (including the software that powers this blog), make things with [Processing](https://processing.org), explore the various [hiking trails](/hikes) around Canberra and potter around [in the garden](/tagged/garden).
### Currently listening to
<div hx-get="/recently_played" hx-trigger="load"></div>
### 2023 Goals
- 25 Hikes

View File

@@ -0,0 +1,43 @@
require "httparty"
require "jwt"
module Adamantium
module Queries
module Posts
class RecentlyPlayed
include Deps["settings"]
def call
resp = HTTParty.get("https://api.music.apple.com/v1/me/recent/played", {
headers: {
"Authorization" => "Bearer #{jwt}",
"Music-User-Token" => settings.apple_music_user_token
}
})
resp.body
end
private
def jwt
authentication_payload = {
iss: settings.apple_music_team,
iat: Time.now.to_i, # Issue date
exp: Time.now.to_i + 3600 # Expiry of this token.
}
# The file we got from Apple
apple_music_secret = File.read(File.join(Hanami.app.root, "config", "AuthKey_#{settings.apple_music_key}.p8"))
private_key = OpenSSL::PKey::EC.new(apple_music_secret)
JWT.encode(
authentication_payload,
private_key,
'ES256',
kid: settings.apple_music_key
)
end
end
end
end
end

View File

@@ -0,0 +1,9 @@
div class="grid grid-cols-4 gap-4"
- recently_played_music.each do |album|
a href="#{album[:href]}"
div
img class="rounded transition-transform ease-out hover:scale-105" src="#{album[:image]}"
span class="inline-block text-sm"
= album[:name]
span class="inline-block text-sm font-bold"
= album[:artist]

View File

@@ -0,0 +1,27 @@
module Adamantium
module Views
module RecentlyPlayed
class Index < Adamantium::View
config.layout = false
include Deps["queries.posts.recently_played"]
expose :recently_played_music do |recently_played_result|
# raise recently_played_result["data"].inspect
JSON.parse(recently_played_result)["data"].reject{ |a| a["type"] != "albums" }.map do |album|
{
artist: album["attributes"]["artistName"],
name: album["attributes"]["name"],
image: album["attributes"]["artwork"]["url"].gsub("{w}", "256").gsub("{h}", "256"),
href: album["attributes"]["url"]
}
end
end
private_expose :recently_played_result do
recently_played.call
end
end
end
end
end

View File

@@ -49,6 +49,8 @@ module Adamantium
get "/movies", to: "movies.index"
get "/recently_played", to: "recently_played.index"
get "/:slug", to: "pages.show"
get "/trips", to: "trips.index"

View File

@@ -28,6 +28,10 @@ module Adamantium
setting :lastfm_api_key, default: nil
setting :lastfm_secret, default: nil
setting :apple_music_team, default: nil
setting :apple_music_key, default: nil
setting :apple_music_user_token, default: nil
setting :omdb_api_key, default: nil
setting :shortcut_key, default: nil

View File

@@ -0,0 +1,13 @@
module Admin
module Actions
module AppleMusic
class Index < Action
include Deps["views.apple_music.index"]
def handle(req, res)
res.render index
end
end
end
end
end

View File

@@ -49,5 +49,7 @@ module Admin
post "/trips/remove_post", to: Auth.call(action: "trips.remove_post")
get "/trips/new", to: Auth.call(action: "trips.new")
post "/trips/:id", to: Auth.call(action: "trips.update")
get "/apple_music", to: Auth.call(action: "apple_music.index")
end
end

View File

@@ -0,0 +1,32 @@
script src="https://js-cdn.music.apple.com/musickit/v3/musickit.js" data-web-components async
javascript:
document.addEventListener('musickitloaded', async function () {
// Call configure() to configure an instance of MusicKit on the Web.
try {
await MusicKit.configure({
developerToken: '#{developer_token}',
app: {
name: 'Blog',
build: '2023.1',
},
});
} catch (err) {
// Handle configuration error
}
// MusicKit instance is available
const music = MusicKit.getInstance();
await music.authorize();
document.querySelectorAll(".mut")[0].innerHTML = music.musicUserToken;
});
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
h1 Admin // Apple Music auth
div
p Your music user token is:
code
pre class="mut"
p keep it secret, keep it safe

View File

@@ -17,6 +17,8 @@ div class="max-w-prose mx-auto prose dark:prose-invert"
a href="/admin/bookmarks" Bookmarks
li
a href="/admin/trips" Trips
li
a href="/admin/apple_music" Apple Music
div class="max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600"

View File

@@ -0,0 +1,29 @@
require "jwt"
module Admin
module Views
module AppleMusic
class Index < Admin::View
include Deps["settings"]
expose :developer_token do
authentication_payload = {
iss: settings.apple_music_team,
iat: Time.now.to_i, # Issue date
exp: Time.now.to_i + 3600 # Expiry of this token.
}
# The file we got from Apple
apple_music_secret = File.read(File.join(Hanami.app.root, "config", "AuthKey_#{settings.apple_music_key}.p8"))
private_key = OpenSSL::PKey::EC.new(apple_music_secret)
JWT.encode(
authentication_payload,
private_key,
'ES256',
kid: settings.apple_music_key
)
end
end
end
end
end