|
1 // Copyright © 2017 Mikael Berthe <mikael@lilotux.net> |
|
2 // |
|
3 // Licensed under the MIT license. |
|
4 // Please see the LICENSE file is this directory. |
|
5 |
|
6 package printer |
|
7 |
|
8 import ( |
|
9 "fmt" |
|
10 "io" |
|
11 "os" |
|
12 "reflect" |
|
13 "time" |
|
14 |
|
15 "github.com/jaytaylor/html2text" |
|
16 |
|
17 "github.com/McKael/madon" |
|
18 ) |
|
19 |
|
20 // PlainPrinter is the default "plain text" printer |
|
21 type PlainPrinter struct { |
|
22 Indent string |
|
23 NoSubtitles bool |
|
24 } |
|
25 |
|
26 // NewPrinterPlain returns a plaintext ResourcePrinter |
|
27 // For PlainPrinter, the option parameter contains the indent prefix. |
|
28 func NewPrinterPlain(option string) (*PlainPrinter, error) { |
|
29 indentInc := " " |
|
30 if option != "" { |
|
31 indentInc = option |
|
32 } |
|
33 return &PlainPrinter{Indent: indentInc}, nil |
|
34 } |
|
35 |
|
36 // PrintObj sends the object as text to the writer |
|
37 // If the writer w is nil, standard output will be used. |
|
38 // For PlainPrinter, the option parameter contains the initial indent. |
|
39 func (p *PlainPrinter) PrintObj(obj interface{}, w io.Writer, initialIndent string) error { |
|
40 if w == nil { |
|
41 w = os.Stdout |
|
42 } |
|
43 switch o := obj.(type) { |
|
44 case []madon.Account, []madon.Attachment, []madon.Card, []madon.Context, |
|
45 []madon.Instance, []madon.Mention, []madon.Notification, |
|
46 []madon.Relationship, []madon.Report, []madon.Results, |
|
47 []madon.Status, []madon.StreamEvent, []madon.Tag: |
|
48 return p.plainForeach(o, w, initialIndent) |
|
49 case *madon.Account: |
|
50 return p.plainPrintAccount(o, w, initialIndent) |
|
51 case madon.Account: |
|
52 return p.plainPrintAccount(&o, w, initialIndent) |
|
53 case *madon.Attachment: |
|
54 return p.plainPrintAttachment(o, w, initialIndent) |
|
55 case madon.Attachment: |
|
56 return p.plainPrintAttachment(&o, w, initialIndent) |
|
57 case *madon.Card: |
|
58 return p.plainPrintCard(o, w, initialIndent) |
|
59 case madon.Card: |
|
60 return p.plainPrintCard(&o, w, initialIndent) |
|
61 case *madon.Context: |
|
62 return p.plainPrintContext(o, w, initialIndent) |
|
63 case madon.Context: |
|
64 return p.plainPrintContext(&o, w, initialIndent) |
|
65 case *madon.Instance: |
|
66 return p.plainPrintInstance(o, w, initialIndent) |
|
67 case madon.Instance: |
|
68 return p.plainPrintInstance(&o, w, initialIndent) |
|
69 case *madon.Notification: |
|
70 return p.plainPrintNotification(o, w, initialIndent) |
|
71 case madon.Notification: |
|
72 return p.plainPrintNotification(&o, w, initialIndent) |
|
73 case *madon.Relationship: |
|
74 return p.plainPrintRelationship(o, w, initialIndent) |
|
75 case madon.Relationship: |
|
76 return p.plainPrintRelationship(&o, w, initialIndent) |
|
77 case *madon.Report: |
|
78 return p.plainPrintReport(o, w, initialIndent) |
|
79 case madon.Report: |
|
80 return p.plainPrintReport(&o, w, initialIndent) |
|
81 case *madon.Results: |
|
82 return p.plainPrintResults(o, w, initialIndent) |
|
83 case madon.Results: |
|
84 return p.plainPrintResults(&o, w, initialIndent) |
|
85 case *madon.Status: |
|
86 return p.plainPrintStatus(o, w, initialIndent) |
|
87 case madon.Status: |
|
88 return p.plainPrintStatus(&o, w, initialIndent) |
|
89 case *madon.UserToken: |
|
90 return p.plainPrintUserToken(o, w, initialIndent) |
|
91 case madon.UserToken: |
|
92 return p.plainPrintUserToken(&o, w, initialIndent) |
|
93 } |
|
94 // TODO: Mention |
|
95 // TODO: StreamEvent |
|
96 // TODO: Tag |
|
97 |
|
98 return fmt.Errorf("PlainPrinter not yet implemented for %T (try json or yaml...)", obj) |
|
99 } |
|
100 |
|
101 func (p *PlainPrinter) plainForeach(ol interface{}, w io.Writer, ii string) error { |
|
102 switch reflect.TypeOf(ol).Kind() { |
|
103 case reflect.Slice: |
|
104 s := reflect.ValueOf(ol) |
|
105 |
|
106 for i := 0; i < s.Len(); i++ { |
|
107 o := s.Index(i).Interface() |
|
108 if err := p.PrintObj(o, w, ii); err != nil { |
|
109 return err |
|
110 } |
|
111 } |
|
112 } |
|
113 return nil |
|
114 } |
|
115 |
|
116 func html2string(h string) string { |
|
117 t, err := html2text.FromString(h) |
|
118 if err == nil { |
|
119 return t |
|
120 } |
|
121 return h // Failed: return initial string |
|
122 } |
|
123 |
|
124 func indentedPrint(w io.Writer, indent string, title, skipIfEmpty bool, label string, format string, args ...interface{}) { |
|
125 prefix := indent |
|
126 if title { |
|
127 prefix += "- " |
|
128 } else { |
|
129 prefix += " " |
|
130 } |
|
131 value := fmt.Sprintf(format, args...) |
|
132 if !title && skipIfEmpty && len(value) == 0 { |
|
133 return |
|
134 } |
|
135 fmt.Fprintf(w, "%s%s: %s\n", prefix, label, value) |
|
136 } |
|
137 |
|
138 func (p *PlainPrinter) plainPrintAccount(a *madon.Account, w io.Writer, indent string) error { |
|
139 indentedPrint(w, indent, true, false, "Account ID", "%d (%s)", a.ID, a.Username) |
|
140 indentedPrint(w, indent, false, false, "User ID", "%s", a.Acct) |
|
141 indentedPrint(w, indent, false, false, "Display name", "%s", a.DisplayName) |
|
142 indentedPrint(w, indent, false, false, "Creation date", "%v", a.CreatedAt.Local()) |
|
143 indentedPrint(w, indent, false, false, "URL", "%s", a.URL) |
|
144 indentedPrint(w, indent, false, false, "Statuses count", "%d", a.StatusesCount) |
|
145 indentedPrint(w, indent, false, false, "Followers count", "%d", a.FollowersCount) |
|
146 indentedPrint(w, indent, false, false, "Following count", "%d", a.FollowingCount) |
|
147 if a.Locked { |
|
148 indentedPrint(w, indent, false, false, "Locked", "%v", a.Locked) |
|
149 } |
|
150 indentedPrint(w, indent, false, true, "User note", "%s", html2string(a.Note)) // XXX too long? |
|
151 return nil |
|
152 } |
|
153 |
|
154 func (p *PlainPrinter) plainPrintAttachment(a *madon.Attachment, w io.Writer, indent string) error { |
|
155 indentedPrint(w, indent, true, false, "Attachment ID", "%d", a.ID) |
|
156 indentedPrint(w, indent, false, false, "Type", "%s", a.Type) |
|
157 indentedPrint(w, indent, false, false, "Local URL", "%s", a.URL) |
|
158 indentedPrint(w, indent, false, true, "Remote URL", "%s", a.RemoteURL) |
|
159 indentedPrint(w, indent, false, true, "Preview URL", "%s", a.PreviewURL) |
|
160 indentedPrint(w, indent, false, true, "Text URL", "%s", a.PreviewURL) |
|
161 return nil |
|
162 } |
|
163 |
|
164 func (p *PlainPrinter) plainPrintCard(c *madon.Card, w io.Writer, indent string) error { |
|
165 indentedPrint(w, indent, true, false, "Card title", "%s", c.Title) |
|
166 indentedPrint(w, indent, false, true, "Description", "%s", c.Description) |
|
167 indentedPrint(w, indent, false, true, "URL", "%s", c.URL) |
|
168 indentedPrint(w, indent, false, true, "Image", "%s", c.Image) |
|
169 return nil |
|
170 } |
|
171 |
|
172 func (p *PlainPrinter) plainPrintContext(c *madon.Context, w io.Writer, indent string) error { |
|
173 indentedPrint(w, indent, true, false, "Context", "%d relative(s)", len(c.Ancestors)+len(c.Descendents)) |
|
174 if len(c.Ancestors) > 0 { |
|
175 indentedPrint(w, indent, false, false, "Ancestors", "") |
|
176 p.PrintObj(c.Ancestors, w, indent+p.Indent) |
|
177 } |
|
178 if len(c.Descendents) > 0 { |
|
179 indentedPrint(w, indent, false, false, "Descendents", "") |
|
180 p.PrintObj(c.Descendents, w, indent+p.Indent) |
|
181 } |
|
182 return nil |
|
183 } |
|
184 |
|
185 func (p *PlainPrinter) plainPrintInstance(i *madon.Instance, w io.Writer, indent string) error { |
|
186 indentedPrint(w, indent, true, false, "Instance title", "%s", i.Title) |
|
187 indentedPrint(w, indent, false, true, "Description", "%s", html2string(i.Description)) |
|
188 indentedPrint(w, indent, false, true, "URL", "%s", i.URI) |
|
189 indentedPrint(w, indent, false, true, "Email", "%s", i.Email) |
|
190 return nil |
|
191 } |
|
192 |
|
193 func (p *PlainPrinter) plainPrintNotification(n *madon.Notification, w io.Writer, indent string) error { |
|
194 indentedPrint(w, indent, true, false, "Notification ID", "%d", n.ID) |
|
195 indentedPrint(w, indent, false, false, "Type", "%s", n.Type) |
|
196 indentedPrint(w, indent, false, false, "Timestamp", "%v", n.CreatedAt.Local()) |
|
197 if n.Account != nil { |
|
198 indentedPrint(w, indent+p.Indent, true, false, "Account", "(%d) @%s - %s", |
|
199 n.Account.ID, n.Account.Acct, n.Account.DisplayName) |
|
200 } |
|
201 if n.Status != nil { |
|
202 p.plainPrintStatus(n.Status, w, indent+p.Indent) |
|
203 } |
|
204 return nil |
|
205 } |
|
206 |
|
207 func (p *PlainPrinter) plainPrintRelationship(r *madon.Relationship, w io.Writer, indent string) error { |
|
208 indentedPrint(w, indent, true, false, "ID", "%d", r.ID) |
|
209 indentedPrint(w, indent, false, false, "Following", "%v", r.Following) |
|
210 indentedPrint(w, indent, false, false, "Followed-by", "%v", r.FollowedBy) |
|
211 indentedPrint(w, indent, false, false, "Blocking", "%v", r.Blocking) |
|
212 indentedPrint(w, indent, false, false, "Muting", "%v", r.Muting) |
|
213 indentedPrint(w, indent, false, false, "Requested", "%v", r.Requested) |
|
214 return nil |
|
215 } |
|
216 |
|
217 func (p *PlainPrinter) plainPrintReport(r *madon.Report, w io.Writer, indent string) error { |
|
218 indentedPrint(w, indent, true, false, "Report ID", "%d", r.ID) |
|
219 indentedPrint(w, indent, false, false, "Action taken", "%s", r.ActionTaken) |
|
220 return nil |
|
221 } |
|
222 |
|
223 func (p *PlainPrinter) plainPrintResults(r *madon.Results, w io.Writer, indent string) error { |
|
224 indentedPrint(w, indent, true, false, "Results", "%d account(s), %d status(es), %d hashtag(s)", |
|
225 len(r.Accounts), len(r.Statuses), len(r.Hashtags)) |
|
226 if len(r.Accounts) > 0 { |
|
227 indentedPrint(w, indent, false, false, "Accounts", "") |
|
228 p.PrintObj(r.Accounts, w, indent+p.Indent) |
|
229 } |
|
230 if len(r.Statuses) > 0 { |
|
231 indentedPrint(w, indent, false, false, "Statuses", "") |
|
232 p.PrintObj(r.Statuses, w, indent+p.Indent) |
|
233 } |
|
234 if len(r.Hashtags) > 0 { |
|
235 indentedPrint(w, indent, false, false, "Hashtags", "") |
|
236 for _, tag := range r.Hashtags { |
|
237 indentedPrint(w, indent+p.Indent, true, false, "Tag", "%s", tag) |
|
238 } |
|
239 } |
|
240 return nil |
|
241 } |
|
242 |
|
243 func (p *PlainPrinter) plainPrintStatus(s *madon.Status, w io.Writer, indent string) error { |
|
244 indentedPrint(w, indent, true, false, "Status ID", "%d", s.ID) |
|
245 indentedPrint(w, indent, false, false, "From", "%s", s.Account.Acct) |
|
246 indentedPrint(w, indent, false, false, "Timestamp", "%v", s.CreatedAt.Local()) |
|
247 |
|
248 if s.Reblog != nil { |
|
249 indentedPrint(w, indent, false, false, "Reblogged from", "%s", s.Reblog.Account.Username) |
|
250 return p.plainPrintStatus(s.Reblog, w, indent+p.Indent) |
|
251 } |
|
252 |
|
253 indentedPrint(w, indent, false, false, "Contents", "%s", html2string(s.Content)) |
|
254 if s.InReplyToID > 0 { |
|
255 indentedPrint(w, indent, false, false, "In-Reply-To", "%d", s.InReplyToID) |
|
256 } |
|
257 if s.Reblogged { |
|
258 indentedPrint(w, indent, false, false, "Reblogged", "%v", s.Reblogged) |
|
259 } |
|
260 indentedPrint(w, indent, false, false, "URL", "%s", s.URL) |
|
261 return nil |
|
262 } |
|
263 |
|
264 func (p *PlainPrinter) plainPrintUserToken(s *madon.UserToken, w io.Writer, indent string) error { |
|
265 indentedPrint(w, indent, true, false, "User token", "%s", s.AccessToken) |
|
266 indentedPrint(w, indent, false, true, "Type", "%s", s.TokenType) |
|
267 if s.CreatedAt != 0 { |
|
268 indentedPrint(w, indent, false, true, "Timestamp", "%v", time.Unix(int64(s.CreatedAt), 0)) |
|
269 } |
|
270 indentedPrint(w, indent, false, true, "Scope", "%s", s.Scope) |
|
271 return nil |
|
272 } |