pleroma-comments.lua 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. -- can't resolve seggfault on luasec, luasocket'
  2. -- local https = "wget"
  3. local json = require("cjson")
  4. -- for testing
  5. function printTable(t)
  6. for key, value in pairs(t) do
  7. print(key, value)
  8. end
  9. end
  10. function tokenizeString(inputString, delimiter)
  11. local tokens = {}
  12. for token in inputString:gmatch("[^" .. delimiter .. "]+") do
  13. table.insert(tokens, token)
  14. end
  15. return tokens
  16. end
  17. function get(link)
  18. local args = {
  19. "-qO-",
  20. link
  21. }
  22. local data = pandoc.pipe("wget", args, "")
  23. local parsed = json.decode(data)
  24. -- print(link)
  25. return parsed
  26. end
  27. function get_epoch_time(timestamp)
  28. local pattern = "(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+).000Z"
  29. local year, month, day, hour, min, sec = timestamp:match(pattern)
  30. local epoch = os.time({
  31. year = year,
  32. month = month,
  33. day = day,
  34. hour = hour,
  35. min = min,
  36. sec = sec
  37. })
  38. return epoch
  39. end
  40. function get_short_date(timestamp)
  41. return os.date(
  42. "%a, %B %d, %Y", get_epoch_time(timestamp)
  43. )
  44. end
  45. function write_comments(pleroma_posts, instance, show_avatars)
  46. show_avatars = show_avatars or false
  47. function get_user(acct_data, instance, include_img)
  48. -- user data
  49. local user_info = ""
  50. local result = ""
  51. local vars = {
  52. alias = acct_data["display_name"],
  53. uid = acct_data["id"],
  54. handle = acct_data["acct"],
  55. host=instance
  56. }
  57. if include_img then
  58. user_info = [[
  59. <figure>
  60. <img src="$avatar$" loading="lazy" alt="avatar"/>
  61. <figcaption>$alias$ <a href="$host$/users/$uid$">@$handle$</a> </figcaption>
  62. </figure>
  63. ]]
  64. vars.avatar = acct_data["avatar_static"]
  65. result = user_info:gsub("%$(%w+)%$", vars)
  66. else
  67. user_info = "<p>$alias$ <a href=\"$host$/users/$uid$\">@$handle$</a></p>"
  68. result = user_info:gsub("%$(%w+)%$", vars)
  69. end
  70. return result
  71. end
  72. function get_card(card, instance)
  73. if card == nil or type(card) ~= "table" then
  74. return ""
  75. end
  76. if card["provider_url"] == instance then
  77. -- skip rendering a card
  78. return ""
  79. end
  80. -- print(type(card))
  81. local card_template = [[
  82. <article class="card">
  83. <header>
  84. <h1 class="card-title">$title$</h1>
  85. <p class="card-description">$description$</p>
  86. </header>
  87. <!-- <img src="$image$" alt="$image_description$" class="card-image" loading="lazy"/> -->
  88. <footer>
  89. <a href="$link$" class="card-link">Read More</a>
  90. </footer>
  91. </article>
  92. ]]
  93. local vars = {
  94. title = card["title"],
  95. description = card["description"],
  96. image = card["image"],
  97. image_description=card["image_description"],
  98. link = card["url"]
  99. }
  100. return card_template:gsub("%$(%w+)%$", vars)
  101. end
  102. function get_media(attachments)
  103. if type(attachments) ~= "table" then
  104. return ""
  105. end
  106. if #attachments < 1 then
  107. return ""
  108. end
  109. local media_list = {"<p>media attached: </p><ol>"}
  110. local item = "<li><a href=\"$link$\">$mime$</a></li>"
  111. for _, v in pairs(attachments) do
  112. local vars = {
  113. link = v["preview_url"],
  114. mime = v["pleroma"]["mime_type"]
  115. }
  116. local foo = item:gsub("%$(%w+)%$", vars)
  117. print(foo)
  118. table.insert(media_list, foo)
  119. end
  120. table.insert(media_list, "</ol>")
  121. return table.concat(media_list, "\n")
  122. end
  123. function get_poll(poll)
  124. if type(poll) ~= "table" then
  125. return ""
  126. end
  127. local bar_chart = {"<div class=\"chart\">"}
  128. local bar_template = [[
  129. <div class="bar-container">
  130. <div class="bar" style="width: $pct$%;">
  131. <span>$pct$%</span>
  132. </div>
  133. <div class="bar-text">
  134. $label$
  135. </div>
  136. </div>
  137. ]]
  138. local total_votes = math.floor(poll["votes_count"])
  139. local total_voters = math.floor(poll["voters_count"])
  140. for _, v in pairs(poll["options"]) do
  141. local percentage = (v["votes_count"]/total_votes) * 100
  142. local rounded = math.floor(0.5 + percentage)
  143. local vars = {
  144. label = v["title"],
  145. pct = rounded
  146. }
  147. local bar = bar_template:gsub("%$(%w+)%$", vars)
  148. table.insert(bar_chart, bar)
  149. end
  150. -- close chart div
  151. table.insert(bar_chart, "</div>")
  152. local summary = "<p>$x$ people have cast $y$ votes</p>"
  153. local foo = summary:gsub(
  154. "%$(%w+)%$",
  155. {x=total_voters, y=total_votes}
  156. )
  157. table.insert(bar_chart, foo)
  158. return table.concat(bar_chart,"\n")
  159. end
  160. if #pleroma_posts == 0 then
  161. return ""
  162. end
  163. local template = [[
  164. <article class="pleroma-comment" id="pleroma-comment$i$">
  165. <h3>
  166. #$i$ <a href="$host$/notice/$pid$">$datetime$</a>
  167. </h3>
  168. $user$
  169. <blockquote>
  170. $text$
  171. </blockquote>
  172. $card$
  173. $attributes$
  174. </article>
  175. ]]
  176. local comments = {}
  177. local replies = pleroma_posts-- ["descendants"]
  178. for i, post in ipairs(replies) do
  179. local pid = post["id"]
  180. local datetime = get_short_date(post["created_at"])
  181. local text = post["content"]
  182. local attrs = {}
  183. table.insert(
  184. attrs, get_media(post["media_attachments"])
  185. )
  186. table.insert(attrs, get_poll(post["poll"]))
  187. local interpolated = template:gsub("%$(%w+)%$", {
  188. i= #replies - i + 1,
  189. host=instance,
  190. pid=pid,
  191. datetime=datetime,
  192. user=get_user(post["account"], instance, true),
  193. text = text,
  194. card = get_card(post["card"], instance),
  195. attributes = table.concat(attrs)
  196. })
  197. -- print(interpolated)
  198. table.insert(
  199. comments, pandoc.RawBlock("html", interpolated)
  200. )
  201. end
  202. -- print(comments)
  203. return comments
  204. end
  205. function combine_tables(a,b)
  206. -- iterate through b, add to a
  207. for i=1,#b do
  208. table.insert(a, b[i])
  209. end
  210. return a
  211. end
  212. function get_url_from_pandoc_str(pandoc_str)
  213. local str = pandoc.utils.stringify(pandoc_str)
  214. -- 1 = protocol, 2 = host ...
  215. -- https://host.tld/notice/12345
  216. local tokens = tokenizeString(str, '/')
  217. local id = tokens[#tokens]
  218. local host = tokens[2]
  219. local id = tokens[#tokens]
  220. local link = str
  221. return link, host, id
  222. end
  223. function get_status(host, post_id)
  224. local url = "https://" .. host .. "/api/v1/statuses/" .. post_id
  225. print(url)
  226. return get(url)
  227. end
  228. function get_replies(host, id)
  229. local url = "https://" .. host .. "/api/v1/statuses/" .. id .. "/context"
  230. print(url)
  231. local got = get(url)
  232. return got["descendants"]
  233. end
  234. function Meta(meta)
  235. local pleroma_urls = meta["pleroma-urls"]
  236. -- print(elem)
  237. if pleroma_urls == nil then
  238. return -- abort
  239. end
  240. local all_replies = {}
  241. local hrefs = {}
  242. local host = ""
  243. -- for each listed url in "pleroma-urls"
  244. for _, v in pairs(pleroma_urls) do
  245. local link, domain, id = get_url_from_pandoc_str(v)
  246. host = domain
  247. table.insert(hrefs,
  248. {link = link, id = id}
  249. )
  250. local op = get_status(host, id)
  251. table.insert(all_replies, op)
  252. local replies = get_replies(host, id)
  253. combine_tables(all_replies, replies)
  254. end
  255. table.sort(all_replies,
  256. function(a, b)
  257. local ta = get_epoch_time(a["created_at"])
  258. local tb = get_epoch_time(b["created_at"])
  259. return ta > tb
  260. end
  261. )
  262. local c = write_comments(all_replies, "https://" .. host)
  263. meta["pleroma-comments"] = c
  264. meta["pleroma-comments-count"] = #c
  265. meta["pleroma-has-comments"] = (#c > 0)
  266. meta["pleroma"] = hrefs
  267. return meta
  268. end