aboutsummaryrefslogtreecommitdiff
path: root/human.go
diff options
context:
space:
mode:
Diffstat (limited to 'human.go')
-rw-r--r--human.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/human.go b/human.go
new file mode 100644
index 0000000..d78d31f
--- /dev/null
+++ b/human.go
@@ -0,0 +1,96 @@
+package human
+
+import (
+ "encoding/json"
+ "errors"
+ "net/url"
+ "strings"
+ "time"
+)
+
+const Version = "0.1.1"
+
+var (
+ stdPorts = map[string]string{
+ "http": "80", "https": "443", "gemini": "1965",
+ }
+)
+
+var (
+ ErrInvalidURL = errors.New("invalid url")
+)
+
+// URL represents a standard [url.URL] following normalization rules of human.json.
+type URL url.URL
+
+func (u *URL) normalize() {
+ if strings.Contains(u.Host, ":") {
+ sp := strings.Split(u.Host, ":")
+ if v, ok := stdPorts[u.Scheme]; ok && v == sp[1] {
+ u.Host = sp[0]
+ }
+ }
+ u.Path = strings.TrimSuffix(u.Path, "/")
+}
+
+func (u *URL) UnmarshalJSON(b []byte) error {
+ var s string
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ raw, err := url.Parse(s)
+ if err != nil {
+ return err
+ }
+ *u = URL(*raw)
+ u.normalize()
+ return nil
+}
+
+func (u *URL) MarshalJSON() ([]byte, error) {
+ u.normalize()
+ return json.Marshal(u.String())
+}
+
+func (u *URL) String() string {
+ ur := url.URL(*u)
+ return ur.String()
+}
+
+// Vouch a website to trust it.
+type Vouch struct {
+ URL *URL `json:"url"`
+ VouchedAt time.Time `json:"-"`
+}
+
+func (v *Vouch) UnmarshalJSON(b []byte) error {
+ type t Vouch
+ var r struct {
+ t
+ VouchedAt string `json:"vouched_at"`
+ }
+ err := json.Unmarshal(b, &r)
+ if err != nil {
+ return err
+ }
+ *v = Vouch(r.t)
+ v.VouchedAt, err = time.Parse(time.DateOnly, r.VouchedAt)
+ return err
+}
+
+func (v *Vouch) MarshalJSON() ([]byte, error) {
+ type t Vouch
+ r := struct {
+ t
+ VouchedAt string `json:"vouched_at"`
+ }{t(*v), v.VouchedAt.Format(time.DateOnly)}
+ return json.Marshal(r)
+}
+
+// Human represents the human.json file.
+type Human struct {
+ Version string `json:"string"`
+ URL *URL `json:"url"`
+ Vouches []*Vouch `json:"vouches"`
+}