Examples
Every plugin in the plugin store has its code a click away, under its View source button. These two cover most of what a music provider can do:
| Plugin | Shows |
|---|---|
| YouTube Music | A complete music provider: works signed out, signs in through a web view, rotates cookies, loads the library and playlists in a thread, and resolves streams in another one. |
| Spotify | A Spotify Premium provider built on Spotify’s own protocol: OAuth with PKCE in a web view, a TCP session with Diffie-Hellman and a cipher in Lua, and songs streamed through a byte source decrypted with nari.cipher. |
Scrobble to a webhook
Section titled “Scrobble to a webhook”A thread sends every song you listen to past its half to a webhook, even with the screen off. A switch in its
settings turns it off; it works from main.lua because both sides share the plugin’s data.
local worker = nari.thread("scrobbler.lua")worker:on_error(function(problem) nari.log("scrobbler stopped: " .. problem) end)
nari.settings(function() return { { title = "Scrobbling", description = "Sends every song you listen to past its half to the webhook", value = function() return nari.get("paused") and "Off" or "On" end, action = function() nari.set("paused", not nari.get("paused")) end, }, }end)local WEBHOOK = "https://example.com/scrobble"local current
local function scrobble(song) if nari.get("paused") then return end local response, problem = nari.http({ method = "POST", url = WEBHOOK, headers = { ["Content-Type"] = "application/json" }, body = nari.json_encode({ title = song.title, artist = song.artist, album = song.album }), }) nari.log(response and ("scrobbled, status " .. response.status) or problem)end
nari.on("track", function(song) current = song if not song then return end nari.after(math.min(song.duration / 2000, 240), function() if current and current.id == song.id then scrobble(song) end end)end)A button on Now Playing
Section titled “A button on Now Playing”A button that counts how many times it was pressed, and remembers it between restarts.
local count = nari.get("presses") or 0
nari.on("page", function(name, page) if name ~= "NowPlaying" then return end local button = NariButton.new() button.text = "Liked " .. count button.bg_color = ThemeEngine.Colors.AccentBg button.fg_color = ThemeEngine.Colors.AccentFg button.custom_minimum_size = Vector2(260, 100) button.pressed:connect(function() count = count + 1 nari.set("presses", count) button.text = "Liked " .. count end) page.top:add_child(button)end)