note_serializer.rb 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. # frozen_string_literal: true
  2. class ActivityPub::NoteSerializer < ActivityPub::Serializer
  3. include FormattingHelper
  4. context_extensions :atom_uri, :conversation, :sensitive, :voters_count
  5. attributes :id, :type, :summary,
  6. :in_reply_to, :published, :url,
  7. :attributed_to, :to, :cc, :sensitive,
  8. :atom_uri, :in_reply_to_atom_uri,
  9. :conversation
  10. attribute :content
  11. attribute :content_map, if: :language?
  12. attribute :updated, if: :edited?
  13. has_many :virtual_attachments, key: :attachment
  14. has_many :virtual_tags, key: :tag
  15. has_one :replies, serializer: ActivityPub::CollectionSerializer, if: :local?
  16. has_many :poll_options, key: :one_of, if: :poll_and_not_multiple?
  17. has_many :poll_options, key: :any_of, if: :poll_and_multiple?
  18. attribute :end_time, if: :poll_and_expires?
  19. attribute :closed, if: :poll_and_expired?
  20. attribute :voters_count, if: :poll_and_voters_count?
  21. def id
  22. ActivityPub::TagManager.instance.uri_for(object)
  23. end
  24. def type
  25. object.preloadable_poll ? 'Question' : 'Note'
  26. end
  27. def summary
  28. object.spoiler_text.presence
  29. end
  30. def content
  31. status_content_format(object)
  32. end
  33. def content_map
  34. { object.language => content }
  35. end
  36. def replies
  37. replies = object.self_replies(5).pluck(:id, :uri)
  38. last_id = replies.last&.first
  39. ActivityPub::CollectionPresenter.new(
  40. type: :unordered,
  41. id: ActivityPub::TagManager.instance.replies_uri_for(object),
  42. first: ActivityPub::CollectionPresenter.new(
  43. type: :unordered,
  44. part_of: ActivityPub::TagManager.instance.replies_uri_for(object),
  45. items: replies.map(&:second),
  46. next: last_id ? ActivityPub::TagManager.instance.replies_uri_for(object, page: true, min_id: last_id) : ActivityPub::TagManager.instance.replies_uri_for(object, page: true, only_other_accounts: true)
  47. )
  48. )
  49. end
  50. def language?
  51. object.language.present?
  52. end
  53. delegate :edited?, to: :object
  54. def in_reply_to
  55. return unless object.reply? && !object.thread.nil?
  56. if object.thread.uri.nil? || object.thread.uri.start_with?('http')
  57. ActivityPub::TagManager.instance.uri_for(object.thread)
  58. else
  59. object.thread.url
  60. end
  61. end
  62. def published
  63. object.created_at.iso8601
  64. end
  65. def updated
  66. object.edited_at.iso8601
  67. end
  68. def url
  69. ActivityPub::TagManager.instance.url_for(object)
  70. end
  71. def attributed_to
  72. ActivityPub::TagManager.instance.uri_for(object.account)
  73. end
  74. def to
  75. ActivityPub::TagManager.instance.to(object)
  76. end
  77. def cc
  78. ActivityPub::TagManager.instance.cc(object)
  79. end
  80. def sensitive
  81. object.account.sensitized? || object.sensitive
  82. end
  83. def virtual_attachments
  84. object.ordered_media_attachments
  85. end
  86. def virtual_tags
  87. object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis
  88. end
  89. def atom_uri
  90. return unless object.local?
  91. OStatus::TagManager.instance.uri_for(object)
  92. end
  93. def in_reply_to_atom_uri
  94. return unless object.reply? && !object.thread.nil?
  95. OStatus::TagManager.instance.uri_for(object.thread)
  96. end
  97. def conversation
  98. return if object.conversation.nil?
  99. if object.conversation.uri?
  100. object.conversation.uri
  101. else
  102. OStatus::TagManager.instance.unique_tag(object.conversation.created_at, object.conversation.id, 'Conversation')
  103. end
  104. end
  105. def local?
  106. object.account.local?
  107. end
  108. def poll_options
  109. object.preloadable_poll.loaded_options
  110. end
  111. def poll_and_multiple?
  112. object.preloadable_poll&.multiple?
  113. end
  114. def poll_and_not_multiple?
  115. object.preloadable_poll && !object.preloadable_poll.multiple?
  116. end
  117. def closed
  118. object.preloadable_poll.expires_at.iso8601
  119. end
  120. alias end_time closed
  121. def voters_count
  122. object.preloadable_poll.voters_count
  123. end
  124. def poll_and_expires?
  125. object.preloadable_poll&.expires_at&.present?
  126. end
  127. def poll_and_expired?
  128. object.preloadable_poll&.expired?
  129. end
  130. def poll_and_voters_count?
  131. object.preloadable_poll&.voters_count
  132. end
  133. class MediaAttachmentSerializer < ActivityPub::Serializer
  134. context_extensions :blurhash, :focal_point
  135. include RoutingHelper
  136. attributes :type, :media_type, :url, :name, :blurhash
  137. attribute :focal_point, if: :focal_point?
  138. attribute :width, if: :width?
  139. attribute :height, if: :height?
  140. has_one :icon, serializer: ActivityPub::ImageSerializer, if: :thumbnail?
  141. def type
  142. 'Document'
  143. end
  144. def name
  145. object.description
  146. end
  147. def media_type
  148. object.file_content_type
  149. end
  150. def url
  151. object.local? ? full_asset_url(object.file.url(:original, false)) : object.remote_url
  152. end
  153. def focal_point?
  154. object.file.meta.is_a?(Hash) && object.file.meta['focus'].is_a?(Hash)
  155. end
  156. def focal_point
  157. [object.file.meta['focus']['x'], object.file.meta['focus']['y']]
  158. end
  159. def icon
  160. object.thumbnail
  161. end
  162. def thumbnail?
  163. object.thumbnail.present?
  164. end
  165. def width?
  166. object.file.meta&.dig('original', 'width').present?
  167. end
  168. def height?
  169. object.file.meta&.dig('original', 'height').present?
  170. end
  171. def width
  172. object.file.meta.dig('original', 'width')
  173. end
  174. def height
  175. object.file.meta.dig('original', 'height')
  176. end
  177. end
  178. class MentionSerializer < ActivityPub::Serializer
  179. attributes :type, :href, :name
  180. def type
  181. 'Mention'
  182. end
  183. def href
  184. ActivityPub::TagManager.instance.uri_for(object.account)
  185. end
  186. def name
  187. "@#{object.account.acct}"
  188. end
  189. end
  190. class TagSerializer < ActivityPub::Serializer
  191. context_extensions :hashtag
  192. include RoutingHelper
  193. attributes :type, :href, :name
  194. def type
  195. 'Hashtag'
  196. end
  197. def href
  198. tag_url(object)
  199. end
  200. def name
  201. "##{object.name}"
  202. end
  203. end
  204. class CustomEmojiSerializer < ActivityPub::EmojiSerializer
  205. end
  206. class OptionSerializer < ActivityPub::Serializer
  207. class RepliesSerializer < ActivityPub::Serializer
  208. attributes :type, :total_items
  209. def type
  210. 'Collection'
  211. end
  212. def total_items
  213. object.votes_count
  214. end
  215. end
  216. attributes :type, :name
  217. has_one :replies, serializer: ActivityPub::NoteSerializer::OptionSerializer::RepliesSerializer
  218. def type
  219. 'Note'
  220. end
  221. def name
  222. object.title
  223. end
  224. def replies
  225. object
  226. end
  227. end
  228. end