post.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package kinds
  2. import (
  3. "net/url"
  4. "strings"
  5. "time"
  6. "mimicry/style"
  7. "fmt"
  8. "errors"
  9. )
  10. type Post Dict
  11. // TODO: make the Post references *Post because why not
  12. func (p Post) Kind() (string, error) {
  13. kind, err := Get[string](p, "type")
  14. return strings.ToLower(kind), err
  15. }
  16. func (p Post) Title() (string, error) {
  17. title, err := GetNatural(p, "name", "en")
  18. return strings.TrimSpace(title), err
  19. }
  20. func (p Post) Body() (string, error) {
  21. body, err := GetNatural(p, "content", "en")
  22. return strings.TrimSpace(body), err
  23. }
  24. func (p Post) BodyPreview() (string, error) {
  25. body, err := p.Body()
  26. // probably should convert to runes and just work with that
  27. if len(body) > 280*2 { // this is a bug because len counts bytes whereas later I work based on runes
  28. return fmt.Sprintf("%s…", string([]rune(body)[:280])), err
  29. } else {
  30. return body, err
  31. }
  32. }
  33. func (p Post) Identifier() (*url.URL, error) {
  34. return GetURL(p, "id")
  35. }
  36. func (p Post) Created() (time.Time, error) {
  37. return GetTime(p, "published")
  38. }
  39. func (p Post) Updated() (time.Time, error) {
  40. return GetTime(p, "updated")
  41. }
  42. func (p Post) Category() string {
  43. return "post"
  44. }
  45. func (p Post) Creators() ([]Actor, error) {
  46. return GetContent[Actor](p, "attributedTo")
  47. }
  48. func (p Post) Attachments() ([]Link, error) {
  49. return GetLinksLenient(p, "attachment")
  50. }
  51. // func (p Post) bestLink() (Link, error) {
  52. // }
  53. func (p Post) Link() (Link, error) {
  54. kind, err := p.Kind()
  55. if err != nil {
  56. return nil, err
  57. }
  58. links, err := GetLinksStrict(p, "url")
  59. if err != nil {
  60. return nil, err
  61. }
  62. switch kind {
  63. case "audio", "image", "video":
  64. return SelectBestLink(links, kind)
  65. case "article", "document", "note", "page":
  66. return SelectFirstLink(links)
  67. default:
  68. return nil, errors.New("Link extraction is not supported for type " + kind)
  69. }
  70. }
  71. func (p Post) String() (string, error) {
  72. output := ""
  73. if title, err := p.Title(); err == nil {
  74. output += style.Bold(title)
  75. output += "\n"
  76. }
  77. if body, err := p.BodyPreview(); err == nil {
  78. output += body
  79. output += "\n"
  80. }
  81. if created, err := p.Created(); err == nil {
  82. output += time.Now().Sub(created).String()
  83. }
  84. if creators, err := p.Creators(); err == nil {
  85. output += " "
  86. for _, creator := range creators {
  87. if name, err := creator.InlineName(); err == nil {
  88. output += style.Bold(name) + ", "
  89. }
  90. }
  91. }
  92. if link, err := p.Link(); err == nil {
  93. if linkStr, err := link.String(); err == nil {
  94. output += "\n"
  95. output += linkStr
  96. }
  97. }
  98. if attachments, err := p.Attachments(); err == nil {
  99. output += "\nAttachments:\n"
  100. for _, attachment := range attachments {
  101. if attachmentStr, err := attachment.String(); err == nil {
  102. output += attachmentStr + "\n"
  103. } else {
  104. continue
  105. }
  106. }
  107. }
  108. return strings.TrimSpace(output), nil
  109. }