Advertisement
nonogamer9

OC-WEB 1.0: An Web Browser For OpenComputers!

Aug 9th, 2024 (edited)
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.13 KB | Software | 0 0
  1. local component = require("component")
  2. local event = require("event")
  3. local internet = require("internet")
  4. local term = require("term")
  5. local unicode = require("unicode")
  6.  
  7. local gpu = component.gpu
  8. local hasColor = gpu.getDepth() > 1
  9.  
  10. local function bootUpScreen()
  11.     term.clear()
  12.     local logo = [[
  13.  ::::::::   ::::::::               :::       ::: :::::::::: :::::::::
  14. :+:    :+: :+:    :+:              :+:       :+: :+:        :+:    :+:
  15. +:+    +:+ +:+                     +:+       +:+ +:+        +:+    +:+
  16. +#+    +:+ +#+       +#++:++#++:++ +#+  +:+  +#+ +#++:++#   +#++:++#+
  17. +#+    +#+ +#+                     +#+ +#+#+ +#+ +#+        +#+    +#+
  18. #+#    #+# #+#    #+#               #+#+# #+#+#  #+#        #+#    #+#
  19.  ########   ########                 ###   ###   ########## #########
  20.     ]]
  21.     term.setCursor(1, 1)
  22.     term.write(logo)
  23.     term.setCursor(1, select(2, term.getCursor()) + 1)
  24.     term.write("Loading...")
  25.     term.setCursor(1, select(2, term.getCursor()) + 2)
  26.     term.write("OC-WEB: A Web Browser For OpenComputers Coded by nonogamer9")
  27.     os.sleep(3)
  28. end
  29.  
  30. local function resolveURL(base, relative)
  31.     if not base or not relative then return nil end
  32.     if relative:match("^https?://") then return relative end
  33.     if relative:sub(1, 1) == "/" then
  34.         return base:match("^(https?://[^/]+)") .. relative
  35.     else
  36.         local baseMatch = base:match("^(https?://.*/)") or base:match("^(https?://[^/]+)")
  37.         if baseMatch then
  38.             if baseMatch:sub(-1) ~= "/" then
  39.                 baseMatch = baseMatch .. "/"
  40.             end
  41.             return baseMatch .. relative
  42.         else
  43.             return nil
  44.         end
  45.     end
  46. end
  47.  
  48. local function handleJavaScript(html, currentBaseURL)
  49.     local redirectUrl = html:match("window%.location%s*=%s*['\"](.-)['\"]")
  50.     if redirectUrl then
  51.         return resolveURL(currentBaseURL, redirectUrl)
  52.     end
  53.     return nil
  54. end
  55.  
  56. local function fetch(url, visited)
  57.     visited = visited or {}
  58.     if visited[url] then
  59.         return false, "Redirect loop detected"
  60.     end
  61.     visited[url] = true
  62.  
  63.     local handle, err = internet.request(url)
  64.     if not handle then
  65.         return false, "Failed to connect to " .. url .. ": " .. (err or "unknown error")
  66.     end
  67.  
  68.     local data = ""
  69.     for chunk in handle do
  70.         if chunk then
  71.             data = data .. chunk
  72.         end
  73.     end
  74.  
  75.     local redirectUrl = data:match('<meta%s+http%-equiv="refresh"%s+content=".-;url=(.-)"')
  76.     if redirectUrl then
  77.         local resolvedRedirectUrl = resolveURL(url, redirectUrl)
  78.         if resolvedRedirectUrl then
  79.             print("Redirecting to: " .. resolvedRedirectUrl)
  80.             return fetch(resolvedRedirectUrl, visited)
  81.         else
  82.             return false, "Invalid redirect URL: " .. redirectUrl
  83.         end
  84.     end
  85.  
  86.     local jsRedirectUrl = handleJavaScript(data, url)
  87.     if jsRedirectUrl then
  88.         print("JavaScript redirecting to: " .. jsRedirectUrl)
  89.         return fetch(jsRedirectUrl, visited)
  90.     end
  91.  
  92.     return true, data
  93. end
  94.  
  95. local function parseHTML(html)
  96.     local links = {}
  97.     html = html:gsub("<script.->.-</script>", "")
  98.     html = html:gsub("<style.->.-</style>", "")
  99.     html = html:gsub("<b>(.-)</b>", function(content) return "[B]" .. content .. "[/B]" end)
  100.     html = html:gsub("<strong>(.-)</strong>", function(content) return "[B]" .. content .. "[/B]" end)
  101.     html = html:gsub("<i>(.-)</i>", function(content) return "[I]" .. content .. "[/I]" end)
  102.     html = html:gsub("<em>(.-)</em>", function(content) return "[I]" .. content .. "[/I]" end)
  103.     html = html:gsub("<u>(.-)</u>", function(content) return "[U]" .. content .. "[/U]" end)
  104.     html = html:gsub("<a href=\"(.-)\">(.-)</a>", function(href, content)
  105.         table.insert(links, {href = href, content = content})
  106.         return content .. " [" .. #links .. "]"
  107.     end)
  108.     html = html:gsub("<h[1-6]>(.-)</h[1-6]>", function(content) return "[H]" .. content .. "[/H]" end)
  109.     html = html:gsub("<li>(.-)</li>", function(content) return " * " .. content end)
  110.     html = html:gsub("<br>", "\n")
  111.     html = html:gsub("<p>", "\n\n")
  112.     html = html:gsub("</p>", "\n\n")
  113.     html = html:gsub("<div>(.-)</div>", function(content) return content .. "\n" end)
  114.     html = html:gsub("<.->", "")
  115.     html = html:gsub("&lt;", "<")
  116.     html = html:gsub("&gt;", ">")
  117.     html = html:gsub("&amp;", "&")
  118.     html = html:gsub("&quot;", "\"")
  119.     html = html:gsub("&apos;", "'")
  120.     return html, links
  121. end
  122.  
  123. local function display(baseURL, data, links)
  124.     local lines = {}
  125.     for line in data:gmatch("[^\r\n]+") do
  126.         table.insert(lines, line)
  127.     end
  128.  
  129.     local offset = 0
  130.     local screenWidth, screenHeight = gpu.getResolution()
  131.     local contentHeight = screenHeight - 1
  132.  
  133.     local function redraw()
  134.         term.setCursor(1, 1)
  135.         for i = 1, contentHeight do
  136.             local line = lines[i + offset] or ""
  137.             term.setCursor(1, i)
  138.             term.clearLine()
  139.             term.write(unicode.sub(line, 1, screenWidth))
  140.         end
  141.  
  142.         term.setCursor(1, screenHeight)
  143.         gpu.setBackground(0x333333)
  144.         term.clearLine()
  145.         term.write("URL: " .. (baseURL or "N/A") .. " | Use Arrow Keys to Scroll, Q to Quit, U to Change URL")
  146.         gpu.setBackground(0x000000)
  147.     end
  148.  
  149.     redraw()
  150.  
  151.     while true do
  152.         local eventType, _, _, y, _, scrollDirection = event.pull()
  153.         local needsRedraw = false
  154.         if eventType == "key_down" then
  155.             if y == 200 then
  156.                 offset = math.max(0, offset - 1)
  157.                 needsRedraw = true
  158.             elseif y == 208 then
  159.                 offset = math.min(#lines - contentHeight, offset + 1)
  160.                 needsRedraw = true
  161.             elseif y == 16 then
  162.                 break
  163.             elseif y == 22 then
  164.                 return false
  165.             end
  166.         elseif eventType == "scroll" then
  167.             if scrollDirection == 1 then
  168.                 offset = math.max(0, offset - 1)
  169.                 needsRedraw = true
  170.             elseif scrollDirection == -1 then
  171.                 offset = math.min(#lines - contentHeight, offset + 1)
  172.                 needsRedraw = true
  173.             end
  174.         elseif eventType == "touch" then
  175.             local lineIndex = y + offset
  176.             if lineIndex <= #lines then
  177.                 local line = lines[lineIndex]
  178.                 local linkIndex = line:match("%[(%d+)%]$")
  179.                 if linkIndex then
  180.                     local link = links[tonumber(linkIndex)]
  181.                     if link and link.href then
  182.                         local resolvedURL = resolveURL(baseURL, link.href)
  183.                         if resolvedURL then
  184.                             print("Opening link: " .. resolvedURL)
  185.                             local success, newData = fetch(resolvedURL)
  186.                             if success then
  187.                                 local newParsedData, newLinks = parseHTML(newData)
  188.                                 display(resolvedURL, newParsedData, newLinks)
  189.                             else
  190.                                 print("Error fetching URL: " .. newData)
  191.                             end
  192.                         else
  193.                             print("Invalid URL: " .. tostring(link.href))
  194.                         end
  195.                     else
  196.                         print("Invalid link at index: " .. linkIndex)
  197.                     end
  198.                 end
  199.             end
  200.         end
  201.         if needsRedraw then
  202.             redraw()
  203.         end
  204.     end
  205. end
  206.  
  207. function main(showBootScreen)
  208.     if showBootScreen then
  209.         bootUpScreen()
  210.     end
  211.     term.clear()
  212.     print("Enter a URL:")
  213.     local url = io.read()
  214.     if not url:match("^https?://") then
  215.         print("Invalid URL. Please include http:// or https://")
  216.     else
  217.         local success, data = fetch(url)
  218.         if success then
  219.             local parsedData, links = parseHTML(data)
  220.             if display(url, parsedData, links) == false then
  221.                 main(false)
  222.             end
  223.         else
  224.             print("Error fetching URL: " .. data)
  225.         end
  226.     end
  227. end
  228.  
  229. main(true)
  230.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement