Bläddra i källkod

cleaned up link extraction naming

Benton Edmondson 2 år sedan
förälder
incheckning
445d62f703
5 ändrade filer med 100 tillägg och 23 borttagningar
  1. 9 9
      kinds/extractor.go
  2. 70 4
      kinds/link.go
  3. 10 10
      kinds/post.go
  4. 4 0
      main.go
  5. 7 0
      style/style.go

+ 9 - 9
kinds/extractor.go

@@ -7,7 +7,7 @@ import (
 )
 
 // TODO throughout this file: attach the problematic object to the error
-
+// make these all methods on Dictionary
 type Dict = map[string]any
 
 func Get[T any](o Dict, key string) (T, error) {
@@ -114,7 +114,7 @@ func GetContent[T Content](d Dict, key string) ([]T, error) {
 /*
 	`GetList`
 	For a given key, return the value if it is a
-	slice, if not, make it a slice of size 1
+	slice, if not, put it in a slice and return that.
 */
 func GetList(d Dict, key string) ([]any, error) {
 	value, err := Get[any](d, key)
@@ -127,20 +127,20 @@ func GetList(d Dict, key string) ([]any, error) {
 }
 
 /*
-	`GetLinks`
+	`GetLinksStrict`
 	Returns a list
 	of Links. Strings are interpreted as Links and
 	are not fetched. If d.content is absent, d.mediaType
 	is interpreted as applying to these strings.
 	Non-string, non-Link elements are ignored.
 
-	Used exclusively for `Post.url`.
+	Used for `Post.url`.
 */
 // TODO: for simplicity, make this a method of Post,
 // it is easier to conceptualize when it works only on
 // Posts, plus I can use my other post methods
-func GetLinks(d Dict, key string) ([]Link, error) {
-	values, err := GetList(d, "url")
+func GetLinksStrict(d Dict, key string) ([]Link, error) {
+	values, err := GetList(d, key)
 	if err != nil {
 		return nil, err
 	}
@@ -193,14 +193,14 @@ func GetLinks(d Dict, key string) ([]Link, error) {
 }
 
 /*
-	`GetAsLinks`
-	Similar to `GetLinks`, but converts Posts
+	`GetLinksLenient`
+	Similar to `GetLinksStrict`, but converts Posts
 	to Links instead of ignoring them, and treats
 	strings as URLs (not Links) and fetches them.
 
 	Used for `Post.attachment`, `Actor.icon`, etc.
 */
-func GetAsLinks(d Dict, key string) ([]Link, error) {
+func GetLinksLenient(d Dict, key string) ([]Link, error) {
 	values, err := GetContent[Content](d, key)
 	if err != nil {
 		return []Link{}, err

+ 70 - 4
kinds/link.go

@@ -3,6 +3,7 @@ package kinds
 import (
 	"net/url"
 	"strings"
+	"errors"
 )
 
 type Link Dict
@@ -16,8 +17,19 @@ func (l Link) Category() string {
 	return "link"
 }
 
-func (l Link) MediaType() (string, error) {
-	return Get[string](l, "mediaType")
+func (l Link) Supertype() (string, error) {
+	mediaType, err := Get[string](l, "mediaType")
+	return strings.Split(mediaType, "/")[0], err
+}
+
+func (l Link) Subtype() (string, error) {
+	if mediaType, err := Get[string](l, "mediaType"); err != nil {
+		return "", err
+	} else if split := strings.Split(mediaType, "/"); len(split) < 2 {
+		return "", errors.New("Media type " + mediaType + " lacks a subtype")
+	} else {
+		return split[1], nil
+	}
 }
 
 func (l Link) URL() (*url.URL, error) {
@@ -33,6 +45,16 @@ func (l Link) Identifier() (*url.URL, error) {
 	return nil, nil
 }
 
+// used for link prioritization, roughly
+// related to resolution
+func (l Link) rating() int {
+	height, err := Get[int](l, "height")
+	if err != nil { height = 1 }
+	width, err := Get[int](l, "width")
+	if err != nil { width = 1 }
+	return height * width
+}
+
 // TODO: update of course to be nice markup of some sort
 func (l Link) String() (string, error) {
 	output := ""
@@ -43,9 +65,53 @@ func (l Link) String() (string, error) {
 		output += url.String()
 	}
 
-	if mediaType, err := l.MediaType(); err == nil {
-		output += " (" + mediaType + ")"
+	if Subtype, err := l.Subtype(); err == nil {
+		output += " (" + Subtype + ")"
 	}
 
 	return output, nil
 }
+
+func SelectBestLink(links []Link, supertype string) (Link, error) {
+	if len(links) == 0 {
+		return nil, errors.New("Can't select best link of type " + supertype + "/* from an empty list")
+	}
+
+	bestLink := links[0]
+
+	for _, thisLink := range links[1:] {
+		var bestLinkSupertypeMatches bool
+		if bestLinkSupertype, err := bestLink.Supertype(); err != nil {
+			bestLinkSupertypeMatches = false
+		} else {
+			bestLinkSupertypeMatches = bestLinkSupertype == supertype
+		}
+
+		var thisLinkSuperTypeMatches bool
+		if thisLinkSupertype, err := thisLink.Supertype(); err != nil {
+			thisLinkSuperTypeMatches = false
+		} else {
+			thisLinkSuperTypeMatches = thisLinkSupertype == supertype
+		}
+
+		if thisLinkSuperTypeMatches && !bestLinkSupertypeMatches {
+			bestLink = thisLink
+			continue
+		} else if !thisLinkSuperTypeMatches && bestLinkSupertypeMatches {
+			continue
+		} else if thisLink.rating() > bestLink.rating() {
+			bestLink = thisLink
+			continue
+		}
+	}
+
+	return bestLink, nil
+}
+
+func SelectFirstLink(links []Link) (Link, error) {
+	if len(links) == 0 {
+		return nil, errors.New("can't select first Link from an empty list of links")
+	} else {
+		return links[0], nil
+	}
+}

+ 10 - 10
kinds/post.go

@@ -59,7 +59,7 @@ func (p Post) Creators() ([]Actor, error) {
 }
 
 func (p Post) Attachments() ([]Link, error) {
-	return GetAsLinks(p, "attachment")
+	return GetLinksLenient(p, "attachment")
 }
 
 // func (p Post) bestLink() (Link, error) {
@@ -71,17 +71,17 @@ func (p Post) Link() (Link, error) {
 	if err != nil {
 		return nil, err
 	}
+
+	links, err := GetLinksStrict(p, "url")
+	if err != nil {
+		return nil, err
+	}
+
 	switch kind {
-	// case "audio", "image", "video":
-	// 	return GetBestLink(p)
+	case "audio", "image", "video":
+		return SelectBestLink(links, kind)
 	case "article", "document", "note", "page":
-		if links, err := GetLinks(p, "url"); err != nil {
-			return nil, err
-		} else if len(links) == 0 {
-			return nil, err
-		} else {
-			return links[0], nil
-		}
+		return SelectFirstLink(links)
 	default:
 		return nil, errors.New("Link extraction is not supported for type " + kind)
 	}

+ 4 - 0
main.go

@@ -8,6 +8,10 @@ import (
 	"os"
 )
 
+// TODO: when returning errors, use zero value for return
+// also change all error messages to using sprintf-style
+// formatting, all lowercase, and no punctuation
+
 func main() {
 	link := os.Args[len(os.Args)-1]
 	command := os.Args[1]

+ 7 - 0
style/style.go

@@ -4,6 +4,13 @@ import (
 	"fmt"
 )
 
+/*
+	To, e.g., bold, prepend the bold character,
+	then substitute all resets with `${reset}${bold}`
+	to force rebold after all resets, to make sure. Might
+	be complex with layering
+*/
+
 // const (
 // 	Bold = 
 // )