post.go 2.9 KB

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