Add statuscafe.lua

This commit is contained in:
Soph :3 2025-07-11 13:27:06 +00:00
parent 4eb352c002
commit 4cdd4f1c93

171
statuscafe.lua Normal file
View file

@ -0,0 +1,171 @@
-- requires xmlparser to be wgeted
-- https://raw.githubusercontent.com/jonathanpoelen/lua-xmlparser/refs/heads/master/xmlparser.lua
-- requires morefonts to be installed
-- put statuscafe.lua in startup/
-- change my username in http.get
-- get a sanjuuni.sad.ovh password from me or selfhost it
-- https://git.sad.ovh/sophie/sanjuuni-to-emoji-api
-- for your knowledge: AI was used to create the querySelector and getTextContent functions
local parse = require('../xmlparser').parse
local mf = require("../morefonts")
local strings = require "cc.strings"
function querySelector(rootNode, selector)
local parts = {}
for part in string.gmatch(selector, "[^%s>]+") do
table.insert(parts, part)
end
local currentNodes = {}
if rootNode and rootNode.children then
for _, child in ipairs(rootNode.children) do
table.insert(currentNodes, child)
end
end
local resultNode = nil
for i, tagName in ipairs(parts) do
local nextNodes = {}
local foundInThisLevel = false
for _, node in ipairs(currentNodes) do
if node.tag == tagName then
foundInThisLevel = true
if i == #parts then
resultNode = node
break
end
if node.children then
for _, child in ipairs(node.children) do
table.insert(nextNodes, child)
end
end
end
end
if resultNode then break end
if not foundInThisLevel and i < #parts then
return nil
end
currentNodes = nextNodes
end
return resultNode
end
function getTextContent(node)
if not node or not node.children then return nil end
local text = ""
for _, child in ipairs(node.children) do
if child.text then
text = text .. child.text
end
end
return text
end
function trim(s)
if s == nil then return nil end
return s:match("^%s*(.-)%s*$")
end
--- Draws an image to the terminal.
---@param image bimg The image to draw.
---@param x number The x position to draw the image at.
---@param y number The y position to draw the image at.
---@param palette table? The palette to use for the image.
local function drawImage(monitor, image, x, y, palette)
for _, frame in ipairs(image) do
for y, row in ipairs(frame) do
monitor.setCursorPos(1, y)
monitor.blit(table.unpack(row))
end
if frame.palette then for i = 0, #frame.palette do
local c = frame.palette[i]
if type(c) == "table" then monitor.setPaletteColor(2^i, table.unpack(c))
else monitor.setPaletteColor(2^i, c) end
end end
if image.animation then sleep(frame.duration or image.secondsPerFrame or 0.05) end
end
monitor.setBackgroundColor(colors.black)
monitor.setTextColor(colors.white)
--monitor.clear()
monitor.setCursorPos(1, 1)
--for i = 0, 15 do monitor.setPaletteColor(2^i, monitor.nativePaletteColor(2^i)) end
end
local monitor = peripheral.find("monitor")
monitor.clear()
monitor.setCursorPos(2,2)
monitor.write("Loading..")
local req = http.get("https://status.cafe/users/sophie.atom")
local rawXML = req.readAll();
local doc, err = parse(rawXML)
if err then
print("Error parsing XML: " .. err)
return
end
local latestEntryRaw = querySelector(doc, "feed > entry")
if not latestEntryRaw then
print("Error: Missing latest entry in the feed!")
else
local latestEntry = {}
local usernameNode = querySelector(doc, "feed > author > name")
latestEntry.username = getTextContent(usernameNode) or ""
local statusNode = querySelector(latestEntryRaw, "content")
latestEntry.status = getTextContent(statusNode) or ""
local titleNode = querySelector(latestEntryRaw, "title")
latestEntry.title = getTextContent(titleNode) or ""
local updatedNode = querySelector(latestEntryRaw, "updated")
latestEntry.updated = getTextContent(updatedNode) or ""
local usernameLength = string.len(latestEntry.username)
local statusLength = string.len(latestEntry.status)
local titlePart = string.sub(latestEntry.title, usernameLength + 1)
local endIndex = math.min(statusLength, 53)
local emojiRaw = string.sub(titlePart, 1, string.len(titlePart) - endIndex)
latestEntry.emoji = trim(emojiRaw)
local req = http.post({
url = "https://sanjuuni.sad.ovh/render",
body = "{\"emoji\": \"" .. latestEntry.emoji .. "\"}",
headers = {
["Content-Type"] = "application/json",
["Authorization"] = "<..>"
}
})
local data = req.readAll() -- actually read the data.
print(data)
monitor.setTextScale(0.5)
data = textutils.unserialize(data) -- convert the string file data into a usable lua object
drawImage(monitor, data, 0, 0)
monitor.setCursorPos(1, 1)
mf.writeOn(monitor, latestEntry.username, 18, 2, {font="fonts/Times9k"})
mf.writeOn(monitor, "At " .. latestEntry.updated, 18, 5, {font="fonts/3x3-Mono"})
width, height = monitor.getSize();
local lines = strings.wrap(latestEntry.status, width-(18+5))
for i = 0, #lines-1 do
monitor.setCursorPos(18, 7+i)
monitor.write(lines[i+1])
end
end