132 lines
3.0 KiB
Go
132 lines
3.0 KiB
Go
// take in web source, parse primary actions and action text
|
|
|
|
// GOAL: lower cognitive load
|
|
// phases:
|
|
// a. generate a list of <a> tags, and <button> tags
|
|
// b. generate a summary of what activity I'm doing (e.g. browsing, reading blog, etc) - max 5 words
|
|
// c. generate new html with the dumbed down version of the website, without any garbage
|
|
|
|
/// e.g. could even be google.com or facebook or anything
|
|
|
|
// either
|
|
// 1. generate a special keypad for the current website
|
|
// 2. create a new webpage for minimalists
|
|
|
|
// We can hit our llama server (hosted in asus) and run a pipeline of requests to
|
|
// 1. return structured list of items that are important
|
|
// 2. Generate a new webpage with key actions (using tailwind and ion-icons)
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"golang.org/x/net/html"
|
|
"golang.org/x/net/html/atom"
|
|
"io"
|
|
"io/fs"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type Action struct {
|
|
Node *html.Node
|
|
Href string
|
|
}
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 {
|
|
panic("cmon man")
|
|
}
|
|
website := os.Args[1]
|
|
fmt.Printf("parsing website: %s\n", website)
|
|
|
|
resp, err := http.Get(website)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
bodyContents := string(body)
|
|
|
|
// parse the specific <a> tags with html stdlib and button
|
|
doc, err := html.Parse(strings.NewReader(bodyContents))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// find the descendants that are <a>, find hrefs
|
|
actions := []Action{}
|
|
for node := range doc.Descendants() {
|
|
if node.Type == html.ElementNode {
|
|
if node.DataAtom == atom.A {
|
|
for _, attr := range node.Attr {
|
|
if attr.Key == "href" {
|
|
href := fmt.Sprintf("%s%s", website, attr.Val)
|
|
action := Action{
|
|
Href: href,
|
|
Node: node,
|
|
}
|
|
actions = append(actions, action)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Printf("found %d actions\n", len(actions))
|
|
|
|
output := `<!DOCTYPE html>
|
|
<div style="display:flex; flex-direction: column;">`
|
|
for i, action := range actions {
|
|
fmt.Printf("action %d: %s\n", i, action.Href)
|
|
|
|
output += fmt.Sprintf(`<a href="%s" style="padding: 10px;">`, action.Href)
|
|
|
|
// get the childnodes, and use
|
|
children := action.Node.ChildNodes()
|
|
for child := range children {
|
|
var buf bytes.Buffer
|
|
err := html.Render(&buf, child)
|
|
if err != nil {
|
|
fmt.Printf("err in rendering first child: %s\n", err)
|
|
continue
|
|
}
|
|
output += fmt.Sprintf(`%s`, buf.String())
|
|
}
|
|
output += `</a>`
|
|
}
|
|
output += `</div></html>`
|
|
fmt.Printf("output: %s", output)
|
|
|
|
err = os.WriteFile("result.html", []byte(output), fs.ModeAppend)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// Traverse all children of node until Data is of type text
|
|
func extractNodeText(node *html.Node) string {
|
|
if node.Type == html.TextNode {
|
|
return node.Data
|
|
}
|
|
|
|
if node.FirstChild == nil {
|
|
return ""
|
|
}
|
|
|
|
return extractNodeText(node.FirstChild)
|
|
}
|
|
|
|
func isValidTextNode(data string) bool {
|
|
exNewLines := strings.Trim(data, "\n")
|
|
return strings.Trim(exNewLines, " ") != ""
|
|
}
|