|
|
- #!/usr/bin/ruby
-
- # BB_POSTINDEX.RB makes a neat post collection index for Xenforo2 forum
- # posts. Write the post summary text followed by the post URL in
- # any (raw) text editor, with a single newline separating the summary
- # from the URL, but as many blank lines as you want separating each
- # post summary. Optionally, prefix the summary with specific commands
- # to force different output formatting:
- # - !extra categorizes the comment as an extra to be placed at
- # the end of the post collection for the day,
- # - !daystart specifies that the following posts should be placed
- # inside spoiler tags given by the specified day (see example).
- # - !dayend similarly signals the end of the spoiler tags.
- #
- # Example: So the text files I write to sort posts look like:
- #
- # !daystart Saturday, 15 February 2020
- #
- # Oh, snap! Things just got real ((@UserName) post)
- # https://blahblahblah/page-12#post-3456789
- #
- # !extra (@WinnerPoster) made an interesting comment
- # https://blahblahblah/page-13#post-4214133
- #
- # !dayend
- #
- # Then running this script with formats the posts with hyperlinks
- # to the posts, @'s for the credited users, and puts everything
- # behind spoiler tags separating the days. Within each day, the
- # normal posts are formatted with bullet points and a sans serif
- # font for whimsy, and the extra posts appear in a separate section
- # "Informative takes and extras:" at the end of the spoiler.
-
- # For whimsy, use Arial san serif font for the main post list.
- LIST_FORMAT_FONT = "arial"
-
- # Use text macros to dictate the format of the post collection index.
- # !daystart begins a spoiler tag for a given day
- DAY_START = "!daystart"
-
- # !dayend ends the spoiler tag for a given day
- DAY_END = "!dayend"
-
- # !extra specifies that the post is an informative extra, to appear
- # separately in a list at the end
- EXTRA = "!extra"
-
-
- # A class to represent an INDEXEDPOST with a given summary, user,
- # and post hyperlink. Optionally, the post may be specified as
- # an 'extra', in which case no list-style bullet point and sans
- # serif formatting is applied.
- #
- # Example:
- # # Create a new indexed post and print it in default list format
- # post1 = IndexedPost.new("List post (@User post)", "@User", "www.blah#p-1")
- # puts post1 #=> [FONT=arial][URL='www.blah#p-1']○ List post ([/URL]
- # # @User[URL='www.blah#p-1'] post)[/URL][/FONT]
- #
- # # Create a new indexed post and print it in extra format
- # post2 = IndexedPost.new("@User's extra post", "@User", "www.blah", true)
- # puts post2 #=> @User[URL='www.blah']'s extra post[/URL]
- # # And in list form:
- # puts post2.list_format #=> [FONT=arial][URL='www.blah']○ [/URL]
- # #@User[URL='www.blah']'s extra post[/URL][/FONT]
- #
- class IndexedPost
-
- # Create a new indexed post with the given SUMMARY, USER and
- # POST_HYPERLINK. If EXTRA is true, formats the post as an
- # informative extra without any explicit list formatting.
- def initialize(summary, user, post_hyperlink, extra=false)
- @summary = summary
- @user = user
- @post_hyperlink = post_hyperlink
- @extra = extra
- end
-
- # Return a string representation for this post in extra format,
- # i.e. in the regular font with just the hyperlink and no
- # additional formatting.
- def extra_format()
- text = @summary.split(@user).map do |part|
- if (part.length > 0)
- "[URL='" + @post_hyperlink + "']" + part + "[/URL]"
- end
- end
- text.join(" " + @user + " ")
- end
-
- # Return a string representation for this post in list format,
- # i.e. in sans serif font with an ASCII bullet point prepended.
- # TODO: These methods are very similar. Refactor to get rid of the
- # code duplication at some point later?
- def list_format()
- text = ("○ " + @summary).split(@user).map do |part|
- if (part.length > 0)
- "[URL='" + @post_hyperlink + "']" + part + "[/URL]"
- end
- end
- "[FONT=" + LIST_FORMAT_FONT + "]" + text.join(" " + @user + " ") + "[/FONT]"
- end
-
- # Return the printable string representation for this indexed post.
- def to_s()
- if (@extra)
- self.extra_format
- else
- self.list_format
- end
- end
-
- end
-
-
- # Assume that the file full of posts is the first command line arg
- if (ARGV.length < 1)
- raise(ArgumentError, "No post file specified in command line args")
- else
- posts_file = File.open(ARGV.join(""))
- end
-
- # Read lines from the post collection file (ignoring blank lines), and
- # generate the index structure.
- list_posts = []
- extra_posts = []
- day_active = false
-
- line = posts_file.gets.strip
-
- while (line)
- # Skip any preceding white space or blank lines
- line.strip!
- if (not line.empty?)
- case
- when line.start_with?(DAY_START)
- # Start the spoiler tag and refresh the post lists
- puts "[SPOILER=\"" + line.split(DAY_START)[1].strip! + "\"]"
- list_posts = []
- extra_posts = []
- day_active = true
-
- when line.start_with?(DAY_END)
- # Print all of the collected list posts
- list_posts.map { |post| puts post.list_format }
-
- # Print all of the collected extra posts in a separate section
- puts "\nInformative takes and extras:"
- extra_posts.map { |post| puts post.extra_format }
-
- # Finally, end the spoiler tag
- puts "[/SPOILER]"
- day_active = false
-
- else
- # If the line begins with !extra, it's an extra/informative post
- extra = line.start_with?(EXTRA)
- if (extra)
- line = line.split(EXTRA)[1].strip
- end
-
- # Parse the user name (assumed to be between a pair of parentheses
- # for simplicity)
- user_with_parens = line.scan(/\(@.+\)(?=['\s])/)[0].strip
- user = user_with_parens[1..-2]
-
- # And remove the extra parentheses in the formatted summary
- summary = line.gsub(user_with_parens, user)
-
- # Grab the next line too for the hyperlink
- post_hyperlink = posts_file.gets.strip
-
- # Instantiate a new post index and add it to the list.
- indexed_post = IndexedPost.new(summary, user, post_hyperlink, extra)
- if (extra)
- extra_posts << indexed_post
- else
- list_posts << indexed_post
- end
- end
- end
-
- # Read in the next line
- line = posts_file.gets
- end
-
- # Done reading! Close the collected posts file.
- posts_file.close()
-
- # Check: at the end here, if we still have collected posts for the day,
- # print them all now and close the spoiler tag.
- if (day_active)
- # TODO: Duplicate code from the case. Refactor?
- # Print all of the collected list posts
- list_posts.map { |post| puts post.list_format }
-
- # Print all of the collected extra posts in a separate section
- puts "\nInformative takes and extras:"
- extra_posts.map { |post| puts post.extra_format }
-
- # Finally, end the spoiler tag
- puts "[/SPOILER]"
- end
|