main
1package content
2
3import (
4 "encoding/json"
5 "net/url"
6 "time"
7)
8
9// Observation is a specific discussion/permalink that points at an Item's URL
10type Observation struct {
11 Id URLID // Observation URLID
12 URL *url.URL // Observation URL
13
14 TargetURL *url.URL
15 DiscussionURL *url.URL
16
17 Title string
18 SourceName string
19 Seen time.Time
20}
21
22func NewObservation(
23 observationURL *url.URL,
24 targetURL *url.URL,
25 discussionURL *url.URL,
26 sourceName string,
27 title string,
28) (*Observation, error) {
29
30 id, err := NewURLID(observationURL)
31 if err != nil {
32 return nil, err
33 }
34 return &Observation{
35 Id: id,
36 URL: observationURL,
37
38 TargetURL: targetURL,
39 DiscussionURL: discussionURL,
40
41 Title: title,
42 SourceName: sourceName,
43 Seen: time.Now(),
44 }, nil
45}
46
47// MarshalJSON allows for stringified urls in marshaled Observation type
48// satisfies the json.Marshaler interface
49func (obs *Observation) MarshalJSON() ([]byte, error) {
50 o := struct {
51 Id URLID `json:"id"`
52 URL string `json:"url"`
53
54 TargetURL string `json:"target_url"`
55 DiscussionURL string `json:"discussion_url,omitempty"`
56
57 SourceName string `json:"source_name"`
58 Seen time.Time `json:"seen"`
59 Title string `json:"title,omitempty"`
60 }{
61 Id: obs.Id,
62 URL: obs.URL.String(),
63
64 TargetURL: obs.TargetURL.String(),
65 DiscussionURL: obs.DiscussionURL.String(),
66
67 SourceName: obs.SourceName,
68 Seen: obs.Seen,
69 Title: obs.Title,
70 }
71 return json.Marshal(&o)
72}
73
74// UnmarshalJSON parses string urls from the json bytes to url.URL where needed
75// satisfies the json.Unmarshaler interface
76func (obs *Observation) UnmarshalJSON(data []byte) error {
77 o := struct {
78 Id URLID `json:"id"`
79 URL string `json:"url"`
80
81 TargetURL string `json:"target_url"`
82 DiscussionURL string `json:"discussion_url,omitempty"`
83
84 SourceName string `json:"source_name"`
85 Seen time.Time `json:"seen"`
86 Title string `json:"title,omitempty"`
87 }{}
88 err := json.Unmarshal(data, &o)
89 if err != nil {
90 return err
91 }
92
93 obsURL, err := url.Parse(o.URL)
94 if err != nil {
95 return err
96 }
97 obs.Id = o.Id
98 obs.URL = obsURL
99
100 targetURL, err := url.Parse(o.TargetURL)
101 if err != nil {
102 return err
103 }
104 obs.TargetURL = targetURL
105
106 if o.DiscussionURL != "" {
107 discussionURL, err := url.Parse(o.DiscussionURL)
108 if err != nil {
109 return err
110 }
111 obs.DiscussionURL = discussionURL
112 }
113
114 obs.SourceName = o.SourceName
115 obs.Seen = o.Seen
116 obs.Title = o.Title
117
118 return nil
119}