-- 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