Add statuscafe.lua
This commit is contained in:
parent
4eb352c002
commit
4cdd4f1c93
1 changed files with 171 additions and 0 deletions
171
statuscafe.lua
Normal file
171
statuscafe.lua
Normal 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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue