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