All of the informative coronavirus megathread posts and information, collated in one place!
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.

203 lines
6.7 KiB

  1. #!/usr/bin/ruby
  2. # BB_POSTINDEX.RB makes a neat post collection index for Xenforo2 forum
  3. # posts. Write the post summary text followed by the post URL in
  4. # any (raw) text editor, with a single newline separating the summary
  5. # from the URL, but as many blank lines as you want separating each
  6. # post summary. Optionally, prefix the summary with specific commands
  7. # to force different output formatting:
  8. # - !extra categorizes the comment as an extra to be placed at
  9. # the end of the post collection for the day,
  10. # - !daystart specifies that the following posts should be placed
  11. # inside spoiler tags given by the specified day (see example).
  12. # - !dayend similarly signals the end of the spoiler tags.
  13. #
  14. # Example: So the text files I write to sort posts look like:
  15. #
  16. # !daystart Saturday, 15 February 2020
  17. #
  18. # Oh, snap! Things just got real ((@UserName) post)
  19. # https://blahblahblah/page-12#post-3456789
  20. #
  21. # !extra (@WinnerPoster) made an interesting comment
  22. # https://blahblahblah/page-13#post-4214133
  23. #
  24. # !dayend
  25. #
  26. # Then running this script with formats the posts with hyperlinks
  27. # to the posts, @'s for the credited users, and puts everything
  28. # behind spoiler tags separating the days. Within each day, the
  29. # normal posts are formatted with bullet points and a sans serif
  30. # font for whimsy, and the extra posts appear in a separate section
  31. # "Informative takes and extras:" at the end of the spoiler.
  32. # For whimsy, use Arial san serif font for the main post list.
  33. LIST_FORMAT_FONT = "arial"
  34. # Use text macros to dictate the format of the post collection index.
  35. # !daystart begins a spoiler tag for a given day
  36. DAY_START = "!daystart"
  37. # !dayend ends the spoiler tag for a given day
  38. DAY_END = "!dayend"
  39. # !extra specifies that the post is an informative extra, to appear
  40. # separately in a list at the end
  41. EXTRA = "!extra"
  42. # A class to represent an INDEXEDPOST with a given summary, user,
  43. # and post hyperlink. Optionally, the post may be specified as
  44. # an 'extra', in which case no list-style bullet point and sans
  45. # serif formatting is applied.
  46. #
  47. # Example:
  48. # # Create a new indexed post and print it in default list format
  49. # post1 = IndexedPost.new("List post (@User post)", "@User", "www.blah#p-1")
  50. # puts post1 #=> [FONT=arial][URL='www.blah#p-1']○ List post ([/URL]
  51. # # @User[URL='www.blah#p-1'] post)[/URL][/FONT]
  52. #
  53. # # Create a new indexed post and print it in extra format
  54. # post2 = IndexedPost.new("@User's extra post", "@User", "www.blah", true)
  55. # puts post2 #=> @User[URL='www.blah']'s extra post[/URL]
  56. # # And in list form:
  57. # puts post2.list_format #=> [FONT=arial][URL='www.blah']○ [/URL]
  58. # #@User[URL='www.blah']'s extra post[/URL][/FONT]
  59. #
  60. class IndexedPost
  61. # Create a new indexed post with the given SUMMARY, USER and
  62. # POST_HYPERLINK. If EXTRA is true, formats the post as an
  63. # informative extra without any explicit list formatting.
  64. def initialize(summary, user, post_hyperlink, extra=false)
  65. @summary = summary
  66. @user = user
  67. @post_hyperlink = post_hyperlink
  68. @extra = extra
  69. end
  70. # Return a string representation for this post in extra format,
  71. # i.e. in the regular font with just the hyperlink and no
  72. # additional formatting.
  73. def extra_format()
  74. text = @summary.split(@user).map do |part|
  75. if (part.length > 0)
  76. "[URL='" + @post_hyperlink + "']" + part + "[/URL]"
  77. end
  78. end
  79. text.join(" " + @user + " ")
  80. end
  81. # Return a string representation for this post in list format,
  82. # i.e. in sans serif font with an ASCII bullet point prepended.
  83. # TODO: These methods are very similar. Refactor to get rid of the
  84. # code duplication at some point later?
  85. def list_format()
  86. text = ("○ " + @summary).split(@user).map do |part|
  87. if (part.length > 0)
  88. "[URL='" + @post_hyperlink + "']" + part + "[/URL]"
  89. end
  90. end
  91. "[FONT=" + LIST_FORMAT_FONT + "]" + text.join(" " + @user + " ") + "[/FONT]"
  92. end
  93. # Return the printable string representation for this indexed post.
  94. def to_s()
  95. if (@extra)
  96. self.extra_format
  97. else
  98. self.list_format
  99. end
  100. end
  101. end
  102. # Assume that the file full of posts is the first command line arg
  103. if (ARGV.length < 1)
  104. raise(ArgumentError, "No post file specified in command line args")
  105. else
  106. posts_file = File.open(ARGV.join(""))
  107. end
  108. # Read lines from the post collection file (ignoring blank lines), and
  109. # generate the index structure.
  110. list_posts = []
  111. extra_posts = []
  112. day_active = false
  113. line = posts_file.gets.strip
  114. while (line)
  115. # Skip any preceding white space or blank lines
  116. line.strip!
  117. if (not line.empty?)
  118. case
  119. when line.start_with?(DAY_START)
  120. # Start the spoiler tag and refresh the post lists
  121. puts "[SPOILER=\"" + line.split(DAY_START)[1].strip! + "\"]"
  122. list_posts = []
  123. extra_posts = []
  124. day_active = true
  125. when line.start_with?(DAY_END)
  126. # Print all of the collected list posts
  127. list_posts.map { |post| puts post.list_format }
  128. # Print all of the collected extra posts in a separate section
  129. puts "\nInformative takes and extras:"
  130. extra_posts.map { |post| puts post.extra_format }
  131. # Finally, end the spoiler tag
  132. puts "[/SPOILER]"
  133. day_active = false
  134. else
  135. # If the line begins with !extra, it's an extra/informative post
  136. extra = line.start_with?(EXTRA)
  137. if (extra)
  138. line = line.split(EXTRA)[1].strip
  139. end
  140. # Parse the user name (assumed to be between a pair of parentheses
  141. # for simplicity)
  142. user_with_parens = line.scan(/\(@.+\)(?=['\s])/)[0].strip
  143. user = user_with_parens[1..-2]
  144. # And remove the extra parentheses in the formatted summary
  145. summary = line.gsub(user_with_parens, user)
  146. # Grab the next line too for the hyperlink
  147. post_hyperlink = posts_file.gets.strip
  148. # Instantiate a new post index and add it to the list.
  149. indexed_post = IndexedPost.new(summary, user, post_hyperlink, extra)
  150. if (extra)
  151. extra_posts << indexed_post
  152. else
  153. list_posts << indexed_post
  154. end
  155. end
  156. end
  157. # Read in the next line
  158. line = posts_file.gets
  159. end
  160. # Done reading! Close the collected posts file.
  161. posts_file.close()
  162. # Check: at the end here, if we still have collected posts for the day,
  163. # print them all now and close the spoiler tag.
  164. if (day_active)
  165. # TODO: Duplicate code from the case. Refactor?
  166. # Print all of the collected list posts
  167. list_posts.map { |post| puts post.list_format }
  168. # Print all of the collected extra posts in a separate section
  169. puts "\nInformative takes and extras:"
  170. extra_posts.map { |post| puts post.extra_format }
  171. # Finally, end the spoiler tag
  172. puts "[/SPOILER]"
  173. end