You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
7.5 KiB

7 years ago
7 years ago
8 years ago
8 years ago
  1. # frozen_string_literal: true
  2. module AtomBuilderHelper
  3. def stream_updated_at
  4. if @account.stream_entries.last
  5. (@account.updated_at > @account.stream_entries.last.created_at ? @account.updated_at : @account.stream_entries.last.created_at)
  6. else
  7. @account.updated_at
  8. end
  9. end
  10. def entry(xml, is_root = false, &block)
  11. if is_root
  12. root_tag(xml, :entry, &block)
  13. else
  14. xml.entry(&block)
  15. end
  16. end
  17. def feed(xml, &block)
  18. root_tag(xml, :feed, &block)
  19. end
  20. def unique_id(xml, date, id, type)
  21. xml.id_ TagManager.instance.unique_tag(date, id, type)
  22. end
  23. def simple_id(xml, id)
  24. xml.id_ id
  25. end
  26. def published_at(xml, date)
  27. xml.published date.iso8601
  28. end
  29. def updated_at(xml, date)
  30. xml.updated date.iso8601
  31. end
  32. def verb(xml, verb)
  33. xml['activity'].send('verb', TagManager::VERBS[verb])
  34. end
  35. def content(xml, content, warning = nil)
  36. xml.summary(warning) unless warning.blank?
  37. xml.content({ type: 'html' }, content) unless content.blank?
  38. end
  39. def title(xml, title)
  40. xml.title strip_tags(title || '').truncate(80)
  41. end
  42. def author(xml, &block)
  43. xml.author(&block)
  44. end
  45. def category(xml, term)
  46. xml.category(term: term)
  47. end
  48. def target(xml, &block)
  49. xml['activity'].object(&block)
  50. end
  51. def object_type(xml, type)
  52. xml['activity'].send('object-type', TagManager::TYPES[type])
  53. end
  54. def uri(xml, uri)
  55. xml.uri uri
  56. end
  57. def name(xml, name)
  58. xml.name name
  59. end
  60. def summary(xml, summary)
  61. xml.summary(summary) unless summary.blank?
  62. end
  63. def subtitle(xml, subtitle)
  64. xml.subtitle(subtitle) unless subtitle.blank?
  65. end
  66. def link_alternate(xml, url)
  67. xml.link(rel: 'alternate', type: 'text/html', href: url)
  68. end
  69. def link_self(xml, url)
  70. xml.link(rel: 'self', type: 'application/atom+xml', href: url)
  71. end
  72. def link_next(xml, url)
  73. xml.link(rel: 'next', type: 'application/atom+xml', href: url)
  74. end
  75. def link_hub(xml, url)
  76. xml.link(rel: 'hub', href: url)
  77. end
  78. def link_salmon(xml, url)
  79. xml.link(rel: 'salmon', href: url)
  80. end
  81. def portable_contact(xml, account)
  82. xml['poco'].preferredUsername account.username
  83. xml['poco'].displayName(account.display_name) unless account.display_name.blank?
  84. xml['poco'].note(Formatter.instance.simplified_format(account)) unless account.note.blank?
  85. end
  86. def in_reply_to(xml, uri, url)
  87. xml['thr'].send('in-reply-to', ref: uri, href: url, type: 'text/html')
  88. end
  89. def link_mention(xml, account)
  90. xml.link(:rel => 'mentioned', :href => TagManager.instance.uri_for(account), 'ostatus:object-type' => TagManager::TYPES[:person])
  91. end
  92. def link_enclosure(xml, media)
  93. xml.link(rel: 'enclosure', href: full_asset_url(media.file.url(:original, false)), type: media.file_content_type, length: media.file_file_size)
  94. end
  95. def link_avatar(xml, account)
  96. single_link_avatar(xml, account, :original, 120)
  97. end
  98. def logo(xml, url)
  99. xml.logo url
  100. end
  101. def email(xml, email)
  102. xml.email email
  103. end
  104. def conditionally_formatted(activity)
  105. if activity.is_a?(Status)
  106. Formatter.instance.format(activity.reblog? ? activity.reblog : activity)
  107. elsif activity.nil?
  108. nil
  109. else
  110. activity.content
  111. end
  112. end
  113. def link_visibility(xml, item)
  114. return unless item.respond_to?(:visibility) && item.public_visibility?
  115. xml.link(:rel => 'mentioned', :href => TagManager::COLLECTIONS[:public], 'ostatus:object-type' => TagManager::TYPES[:collection])
  116. end
  117. def privacy_scope(xml, level)
  118. xml['mastodon'].scope(level)
  119. end
  120. def include_author(xml, account)
  121. simple_id xml, TagManager.instance.uri_for(account)
  122. object_type xml, :person
  123. uri xml, TagManager.instance.uri_for(account)
  124. name xml, account.username
  125. email xml, account.local? ? "#{account.acct}@#{Rails.configuration.x.local_domain}" : account.acct
  126. summary xml, account.note
  127. link_alternate xml, TagManager.instance.url_for(account)
  128. link_avatar xml, account
  129. portable_contact xml, account
  130. privacy_scope xml, account.locked? ? :private : :public
  131. end
  132. def rich_content(xml, activity)
  133. if activity.is_a?(Status)
  134. content xml, conditionally_formatted(activity), activity.spoiler_text
  135. else
  136. content xml, conditionally_formatted(activity)
  137. end
  138. end
  139. def include_target(xml, target)
  140. simple_id xml, TagManager.instance.uri_for(target)
  141. if target.object_type == :person
  142. include_author xml, target
  143. else
  144. object_type xml, target.object_type
  145. verb xml, target.verb
  146. title xml, target.title
  147. link_alternate xml, TagManager.instance.url_for(target)
  148. end
  149. # Statuses have content and author
  150. return unless target.is_a?(Status)
  151. rich_content xml, target
  152. verb xml, target.verb
  153. published_at xml, target.created_at
  154. updated_at xml, target.updated_at
  155. author(xml) do
  156. include_author xml, target.account
  157. end
  158. if target.reply?
  159. in_reply_to xml, TagManager.instance.uri_for(target.thread), TagManager.instance.url_for(target.thread)
  160. end
  161. link_visibility xml, target
  162. target.mentions.each do |mention|
  163. link_mention xml, mention.account
  164. end
  165. target.media_attachments.each do |media|
  166. link_enclosure xml, media
  167. end
  168. target.tags.each do |tag|
  169. category xml, tag.name
  170. end
  171. category(xml, 'nsfw') if target.sensitive?
  172. privacy_scope(xml, target.visibility)
  173. end
  174. def include_entry(xml, stream_entry)
  175. unique_id xml, stream_entry.created_at, stream_entry.activity_id, stream_entry.activity_type
  176. published_at xml, stream_entry.created_at
  177. updated_at xml, stream_entry.updated_at
  178. title xml, stream_entry.title
  179. rich_content xml, stream_entry.activity
  180. verb xml, stream_entry.verb
  181. link_self xml, account_stream_entry_url(stream_entry.account, stream_entry, format: 'atom')
  182. link_alternate xml, account_stream_entry_url(stream_entry.account, stream_entry)
  183. object_type xml, stream_entry.object_type
  184. # Comments need thread element
  185. if stream_entry.threaded?
  186. in_reply_to xml, TagManager.instance.uri_for(stream_entry.thread), TagManager.instance.url_for(stream_entry.thread)
  187. end
  188. if stream_entry.targeted?
  189. target(xml) do
  190. include_target(xml, stream_entry.target)
  191. end
  192. end
  193. link_visibility xml, stream_entry.activity
  194. stream_entry.mentions.each do |mentioned|
  195. link_mention xml, mentioned
  196. end
  197. return unless stream_entry.activity.is_a?(Status)
  198. stream_entry.activity.media_attachments.each do |media|
  199. link_enclosure xml, media
  200. end
  201. stream_entry.activity.tags.each do |tag|
  202. category xml, tag.name
  203. end
  204. category(xml, 'nsfw') if stream_entry.activity.sensitive?
  205. privacy_scope(xml, stream_entry.activity.visibility)
  206. end
  207. private
  208. def root_tag(xml, tag, &block)
  209. xml.send(tag, {
  210. 'xmlns' => TagManager::XMLNS,
  211. 'xmlns:thr' => TagManager::THR_XMLNS,
  212. 'xmlns:activity' => TagManager::AS_XMLNS,
  213. 'xmlns:poco' => TagManager::POCO_XMLNS,
  214. 'xmlns:media' => TagManager::MEDIA_XMLNS,
  215. 'xmlns:ostatus' => TagManager::OS_XMLNS,
  216. 'xmlns:mastodon' => TagManager::MTDN_XMLNS,
  217. }, &block)
  218. end
  219. def single_link_avatar(xml, account, size, px)
  220. xml.link('rel' => 'avatar', 'type' => account.avatar_content_type, 'media:width' => px, 'media:height' => px, 'href' => full_asset_url(account.avatar.url(size)))
  221. end
  222. end