-- Telem Installer by cyberbit -- MIT License -- Version 2026-07-19 local pretty = require 'cc.pretty' local pprint = pretty.pretty_print local prender = function (data) return pretty.render(pretty.pretty(data)) end local dryRun = false local termW, termH = term.getSize() local boxSizing = { mainPadding = 2 } boxSizing.contentBox = termW - boxSizing.mainPadding * 2 + 1 boxSizing.borderBox = boxSizing.contentBox - 1 local curt = term.current local ObjectModel = (function () ---@diagnostic disable: deprecated -- -- Lua object model implementation -- -- By Shira-3749 -- Source: https://github.com/Shira-3749/lua-object-model -- local a='Lua 5.1'==_VERSION;local unpack=unpack or table.unpack;local function b(c,...)local d={}setmetatable(d,c)if c.constructor then c.constructor(d,...)end;return d end;local function e(d,f,...)if nil==d.___superScope then d.___superScope={}end;local g=d.___superScope[f]local h;if nil~=g then h=g.__parent else h=d.__parent end;d.___superScope[f]=h;local i={pcall(h[f],d,...)}local j=table.remove(i,1)d.___superScope[f]=g;if not j then error(i[1])end;return unpack(i)end;local function k(d,l)local c=getmetatable(d)while c do if c==l then return true end;c=c.__parent end;return false end;local function m(d)if d.destructor then d:destructor()end end;local function c(n)local c={}if n then for o,p in pairs(n)do c[o]=p end;c.__parent=n end;c.__index=c;if not n and not a then c.__gc=m end;if n then c.super=e end;local q={__call=b}setmetatable(c,q)return c end;return{class=c,instanceof=k,new=b,super=e} end)() local function httpGetRedirect(url, headers, binary) local maxRedirects = 5 local redirects = 0 while redirects < maxRedirects do local res, err, errRes = http.get(url, headers, binary) if not res then return nil, err, errRes end local statusCode = res.getResponseCode() if statusCode >= 300 and statusCode < 400 then local location = res.getResponseHeaders()['Location'] if not location then return nil, 'Redirect location not provided' end url = location redirects = redirects + 1 else return res end end return nil, 'Too many redirects' end local REST = (function () local REST = ObjectModel.class() function REST:constructor() self.headers = {} self.baseURL = nil end function REST:setBaseURL(url) self.baseURL = url return self end function REST:setHeaders(headers) for k,v in pairs(headers) do self.headers[k] = v end return self end function REST:get(url, headers) if headers then self:setHeaders(headers) end local res, err, errRes = httpGetRedirect(self.baseURL .. url, self.headers, true) if not res then return res, err, errRes end local body = res.readAll() res.close() return textutils.unserializeJSON(body) end return REST end)() local ui = (function () -- PrimeUI by JackMacWindows -- Public domain/CC0 -- Packaged from https://github.com/MCJack123/PrimeUI local a=require"cc.expect".expect;local b={} do local c={}local d; function b.addTask(e)a(1,e,"function")local f={coro=coroutine.create(e)}c[#c+1]=f;_,f.filter=coroutine.resume(f.coro)end; function b.resolve(...)coroutine.yield(c,...)end; function b.clear()term.setCursorPos(1,1)term.setCursorBlink(false)term.setBackgroundColor(colors.black)term.setTextColor(colors.white)term.clear()c={}d=nil end; function b.setCursorWindow(g)a(1,g,"table","nil")d=g and g.restoreCursor end; function b.getWindowPos(g,h,i)if g==term then return h,i end;while g~=term.native()and g~=term.current()do if not g.getPosition then return h,i end;local j,k=g.getPosition()h,i=h+j-1,i+k-1;_,g=debug.getupvalue(select(2,debug.getupvalue(g.isColor,1)),1)end;return h,i end; function b.run()while true do if d then d()end;local l=table.pack(os.pullEvent())for _,m in ipairs(c)do if m.filter==nil or m.filter==l[1]then local n=table.pack(coroutine.resume(m.coro,table.unpack(l,1,l.n)))if not n[1]then error(n[2],2)end;if n[2]==c then return table.unpack(n,3,n.n)end;m.filter=n[2]end end end end end; function b.borderBox(g,h,i,o,p,q,r)a(1,g,"table")a(2,h,"number")a(3,i,"number")a(4,o,"number")a(5,p,"number")q=a(6,q,"number","nil")or colors.white;r=a(7,r,"number","nil")or colors.black;g.setBackgroundColor(r)g.setTextColor(q)g.setCursorPos(h-1,i-1)g.write("\x9C"..("\x8C"):rep(o))g.setBackgroundColor(q)g.setTextColor(r)g.write("\x93")for s=1,p do g.setCursorPos(g.getCursorPos()-1,i+s-1)g.write("\x95")end;g.setBackgroundColor(r)g.setTextColor(q)for s=1,p do g.setCursorPos(h-1,i+s-1)g.write("\x95")end;g.setCursorPos(h-1,i+p)g.write("\x8D"..("\x8C"):rep(o).."\x8E")end; function b.button(g,h,i,t,u,q,r,v)a(1,g,"table")a(2,h,"number")a(3,i,"number")a(4,t,"string")a(5,u,"function","string")q=a(6,q,"number","nil")or colors.white;r=a(7,r,"number","nil")or colors.gray;v=a(8,v,"number","nil")or colors.lightGray;g.setCursorPos(h,i)g.setBackgroundColor(r)g.setTextColor(q)g.write(" "..t.." ")b.addTask(function()local w=false;while true do local x,y,z,A=os.pullEvent()local B,C=b.getWindowPos(g,h,i)if x=="mouse_click"and y==1 and z>=B and z=B and zp then F.setCursorPos(o,p)F.setBackgroundColor(r)F.setTextColor(q)F.write("\31")end;G.setCursorPos(2,J)G.setCursorBlink(true)b.setCursorWindow(G)local B,C=b.getWindowPos(g,h,i)b.addTask(function()local L=1;while true do local l=table.pack(os.pullEvent())local M;if l[1]=="key"then if l[2]==keys.up then M=-1 elseif l[2]==keys.down then M=1 elseif l[2]==keys.space and D[H[J][1]]~="R"then H[J][2]=not H[J][2]G.setCursorPos(2,J)G.write(H[J][2]and"\xD7"or" ")if type(u)=="string"then b.resolve("checkSelectionBox",u,H[J][1],H[J][2])elseif u then u(H[J][1],H[J][2])else D[H[J][1]]=H[J][2]end;for s,m in ipairs(H)do local N=D[m[1]]=="R"and"R"or m[2]G.setCursorPos(2,s)G.write(N and(N=="R"and"-"or"\xD7")or" ")end;G.setCursorPos(2,J)end elseif l[1]=="mouse_scroll"and l[3]>=B and l[3]=C and l[4]=1 and J+M<=E)then J=J+M;if J-L<0 or J-L>=p then L=L+M;G.reposition(1,2-L)end;G.setCursorPos(2,J)end;F.setCursorPos(o,1)F.write(L>1 and"\30"or" ")F.setCursorPos(o,p)F.write(L1 then error("bad argument #1 (value out of range)",2)end;g.setCursorPos(h,i)g.setBackgroundColor(r)g.setBackgroundColor(q)g.write((" "):rep(math.floor(aj*o)))g.setBackgroundColor(r)g.setTextColor(q)g.write((ah and"\x7F"or" "):rep(o-math.floor(aj*o)))end;ai(0)return ai end; -- function b.scrollBox(g,h,i,o,p,ak,al,am,q,r)a(1,g,"table")a(2,h,"number")a(3,i,"number")a(4,o,"number")a(5,p,"number")a(6,ak,"number")a(7,al,"boolean","nil")a(8,am,"boolean","nil")q=a(9,q,"number","nil")or colors.white;r=a(10,r,"number","nil")or colors.black;if al==nil then al=true end;local F=window.create(g==term and term.current()or g,h,i,o,p)F.setBackgroundColor(r)F.clear()local G=window.create(F,1,1,o-(am and 1 or 0),ak)G.setBackgroundColor(r)G.clear()if am then F.setBackgroundColor(r)F.setTextColor(q)F.setCursorPos(o,p)F.write(ak>p and"\31"or" ")end;h,i=b.getWindowPos(g,h,i)b.addTask(function()local L=1;while true do local l=table.pack(os.pullEvent())ak=select(2,G.getSize())local M;if l[1]=="key"and al then if l[2]==keys.up then M=-1 elseif l[2]==keys.down then M=1 end elseif l[1]=="mouse_scroll"and l[3]>=h and l[3]=i and l[4]=1 and L+M<=ak-p)then L=L+M;G.reposition(1,2-L)end;if am then F.setBackgroundColor(r)F.setTextColor(q)F.setCursorPos(o,1)F.write(L>1 and"\30"or" ")F.setCursorPos(o,p)F.write(Lo-1 and at:sub(1,o-4).."..."or at)end;ap.setCursorPos(o,1)ap.write(ar>1 and"\30"or" ")ap.setCursorPos(o,p)ap.write(ar<#an-p+1 and"\31"or" ")ap.setVisible(true)end;as()b.addTask(function()while true do local _,a8=os.pullEvent("key")if a8==keys.down and aq<#an then aq=aq+1;if aq>ar+p-1 then ar=ar+1 end;if type(ao)=="string"then b.resolve("selectionBox",ao,aq)elseif ao then ao(aq)end;as()elseif a8==keys.up and aq>1 then aq=aq-1;if aq