Browse Source

cleaned up link extraction naming

Benton Edmondson 2 years ago
parent
commit
445d62f703
5 changed files with 100 additions and 23 deletions
  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
 // TODO throughout this file: attach the problematic object to the error
-
+// make these all methods on Dictionary
 type Dict = map[string]any
 type Dict = map[string]any
 
 
 func Get[T any](o Dict, key string) (T, error) {
 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`
 	`GetList`
 	For a given key, return the value if it is a
 	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) {
 func GetList(d Dict, key string) ([]any, error) {
 	value, err := Get[any](d, key)
 	value, err := Get[any](d, key)
@@ -127,20 +127,20 @@ func GetList(d Dict, key string) ([]any, error) {
 }
 }
 
 
 /*
 /*
-	`GetLinks`
+	`GetLinksStrict`
 	Returns a list
 	Returns a list
 	of Links. Strings are interpreted as Links and
 	of Links. Strings are interpreted as Links and
 	are not fetched. If d.content is absent, d.mediaType
 	are not fetched. If d.content is absent, d.mediaType
 	is interpreted as applying to these strings.
 	is interpreted as applying to these strings.
 	Non-string, non-Link elements are ignored.
 	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,
 // TODO: for simplicity, make this a method of Post,
 // it is easier to conceptualize when it works only on
 // it is easier to conceptualize when it works only on
 // Posts, plus I can use my other post methods
 // Posts, plus I can use my other post methods
-func GetLinks(d Dict, key string) ([]Link, error) {
+func GetLinksStrict(d Dict, key string) ([]Link, error) {
-	values, err := GetList(d, "url")
+	values, err := GetList(d, key)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -193,14 +193,14 @@ func GetLinks(d Dict, key string) ([]Link, error) {
 }
 }
 
 
 /*
 /*
-	`GetAsLinks`
+	`GetLinksLenient`
-	Similar to `GetLinks`, but converts Posts
+	Similar to `GetLinksStrict`, but converts Posts
 	to Links instead of ignoring them, and treats
 	to Links instead of ignoring them, and treats
 	strings as URLs (not Links) and fetches them.
 	strings as URLs (not Links) and fetches them.
 
 
 	Used for `Post.attachment`, `Actor.icon`, etc.
 	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)
 	values, err := GetContent[Content](d, key)
 	if err != nil {
 	if err != nil {
 		return []Link{}, err
 		return []Link{}, err

+ 70 - 4
kinds/link.go

@@ -3,6 +3,7 @@ package kinds
 import (
 import (
 	"net/url"
 	"net/url"
 	"strings"
 	"strings"
+	"errors"
 )
 )
 
 
 type Link Dict
 type Link Dict
@@ -16,8 +17,19 @@ func (l Link) Category() string {
 	return "link"
 	return "link"
 }
 }
 
 
-func (l Link) MediaType() (string, error) {
+func (l Link) Supertype() (string, error) {
-	return Get[string](l, "mediaType")
+	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) {
 func (l Link) URL() (*url.URL, error) {
@@ -33,6 +45,16 @@ func (l Link) Identifier() (*url.URL, error) {
 	return nil, nil
 	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
 // TODO: update of course to be nice markup of some sort
 func (l Link) String() (string, error) {
 func (l Link) String() (string, error) {
 	output := ""
 	output := ""
@@ -43,9 +65,53 @@ func (l Link) String() (string, error) {
 		output += url.String()
 		output += url.String()
 	}
 	}
 
 
-	if mediaType, err := l.MediaType(); err == nil {
+	if Subtype, err := l.Subtype(); err == nil {
-		output += " (" + mediaType + ")"
+		output += " (" + Subtype + ")"
 	}
 	}
 
 
 	return output, nil
 	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) {
 func (p Post) Attachments() ([]Link, error) {
-	return GetAsLinks(p, "attachment")
+	return GetLinksLenient(p, "attachment")
 }
 }
 
 
 // func (p Post) bestLink() (Link, error) {
 // func (p Post) bestLink() (Link, error) {
@@ -71,17 +71,17 @@ func (p Post) Link() (Link, error) {
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
+
+	links, err := GetLinksStrict(p, "url")
+	if err != nil {
+		return nil, err
+	}
+
 	switch kind {
 	switch kind {
-	// case "audio", "image", "video":
+	case "audio", "image", "video":
-	// 	return GetBestLink(p)
+		return SelectBestLink(links, kind)
 	case "article", "document", "note", "page":
 	case "article", "document", "note", "page":
-		if links, err := GetLinks(p, "url"); err != nil {
+		return SelectFirstLink(links)
-			return nil, err
-		} else if len(links) == 0 {
-			return nil, err
-		} else {
-			return links[0], nil
-		}
 	default:
 	default:
 		return nil, errors.New("Link extraction is not supported for type " + kind)
 		return nil, errors.New("Link extraction is not supported for type " + kind)
 	}
 	}

+ 4 - 0
main.go

@@ -8,6 +8,10 @@ import (
 	"os"
 	"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() {
 func main() {
 	link := os.Args[len(os.Args)-1]
 	link := os.Args[len(os.Args)-1]
 	command := os.Args[1]
 	command := os.Args[1]

+ 7 - 0
style/style.go

@@ -4,6 +4,13 @@ import (
 	"fmt"
 	"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 (
 // const (
 // 	Bold = 
 // 	Bold = 
 // )
 // )