The code powering m.abunchtell.com https://m.abunchtell.com
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.
 
 
 
 

286 lines
7.8 KiB

  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 link_header(xml, account)
  99. xml.link('rel' => 'header', 'type' => account.header_content_type, 'media:width' => 700, 'media:height' => 335, 'href' => full_asset_url(account.header.url(:original)))
  100. end
  101. def logo(xml, url)
  102. xml.logo url
  103. end
  104. def email(xml, email)
  105. xml.email email
  106. end
  107. def conditionally_formatted(activity)
  108. if activity.is_a?(Status)
  109. Formatter.instance.format(activity.reblog? ? activity.reblog : activity)
  110. elsif activity.nil?
  111. nil
  112. else
  113. activity.content
  114. end
  115. end
  116. def link_visibility(xml, item)
  117. return unless item.respond_to?(:visibility) && item.public_visibility?
  118. xml.link(:rel => 'mentioned', :href => TagManager::COLLECTIONS[:public], 'ostatus:object-type' => TagManager::TYPES[:collection])
  119. end
  120. def privacy_scope(xml, level)
  121. xml['mastodon'].scope(level)
  122. end
  123. def include_author(xml, account)
  124. simple_id xml, TagManager.instance.uri_for(account)
  125. object_type xml, :person
  126. uri xml, TagManager.instance.uri_for(account)
  127. name xml, account.username
  128. email xml, account.local? ? "#{account.acct}@#{Rails.configuration.x.local_domain}" : account.acct
  129. summary xml, account.note
  130. link_alternate xml, TagManager.instance.url_for(account)
  131. link_avatar xml, account
  132. link_header xml, account
  133. portable_contact xml, account
  134. privacy_scope xml, account.locked? ? :private : :public
  135. end
  136. def rich_content(xml, activity)
  137. if activity.is_a?(Status)
  138. content xml, conditionally_formatted(activity), activity.spoiler_text
  139. else
  140. content xml, conditionally_formatted(activity)
  141. end
  142. end
  143. def include_target(xml, target)
  144. simple_id xml, TagManager.instance.uri_for(target)
  145. if target.object_type == :person
  146. include_author xml, target
  147. else
  148. object_type xml, target.object_type
  149. verb xml, target.verb
  150. title xml, target.title
  151. link_alternate xml, TagManager.instance.url_for(target)
  152. end
  153. # Statuses have content and author
  154. return unless target.is_a?(Status)
  155. rich_content xml, target
  156. verb xml, target.verb
  157. published_at xml, target.created_at
  158. updated_at xml, target.updated_at
  159. author(xml) do
  160. include_author xml, target.account
  161. end
  162. if target.reply?
  163. in_reply_to xml, TagManager.instance.uri_for(target.thread), TagManager.instance.url_for(target.thread)
  164. end
  165. link_visibility xml, target
  166. target.mentions.each do |mention|
  167. link_mention xml, mention.account
  168. end
  169. target.media_attachments.each do |media|
  170. link_enclosure xml, media
  171. end
  172. target.tags.each do |tag|
  173. category xml, tag.name
  174. end
  175. category(xml, 'nsfw') if target.sensitive?
  176. privacy_scope(xml, target.visibility)
  177. end
  178. def include_entry(xml, stream_entry)
  179. unique_id xml, stream_entry.created_at, stream_entry.activity_id, stream_entry.activity_type
  180. published_at xml, stream_entry.created_at
  181. updated_at xml, stream_entry.updated_at
  182. title xml, stream_entry.title
  183. rich_content xml, stream_entry.activity
  184. verb xml, stream_entry.verb
  185. link_self xml, account_stream_entry_url(stream_entry.account, stream_entry, format: 'atom')
  186. link_alternate xml, account_stream_entry_url(stream_entry.account, stream_entry)
  187. object_type xml, stream_entry.object_type
  188. # Comments need thread element
  189. if stream_entry.threaded?
  190. in_reply_to xml, TagManager.instance.uri_for(stream_entry.thread), TagManager.instance.url_for(stream_entry.thread)
  191. end
  192. if stream_entry.targeted?
  193. target(xml) do
  194. include_target(xml, stream_entry.target)
  195. end
  196. end
  197. link_visibility xml, stream_entry.activity
  198. stream_entry.mentions.each do |mentioned|
  199. link_mention xml, mentioned
  200. end
  201. return unless stream_entry.activity.is_a?(Status)
  202. stream_entry.activity.media_attachments.each do |media|
  203. link_enclosure xml, media
  204. end
  205. stream_entry.activity.tags.each do |tag|
  206. category xml, tag.name
  207. end
  208. category(xml, 'nsfw') if stream_entry.activity.sensitive?
  209. privacy_scope(xml, stream_entry.activity.visibility)
  210. end
  211. private
  212. def root_tag(xml, tag, &block)
  213. xml.send(tag, {
  214. 'xmlns' => TagManager::XMLNS,
  215. 'xmlns:thr' => TagManager::THR_XMLNS,
  216. 'xmlns:activity' => TagManager::AS_XMLNS,
  217. 'xmlns:poco' => TagManager::POCO_XMLNS,
  218. 'xmlns:media' => TagManager::MEDIA_XMLNS,
  219. 'xmlns:ostatus' => TagManager::OS_XMLNS,
  220. 'xmlns:mastodon' => TagManager::MTDN_XMLNS,
  221. }, &block)
  222. end
  223. def single_link_avatar(xml, account, size, px)
  224. xml.link('rel' => 'avatar', 'type' => account.avatar_content_type, 'media:width' => px, 'media:height' => px, 'href' => full_asset_url(account.avatar.url(size)))
  225. end
  226. end