Skip to content

Instantly share code, notes, and snippets.

@pyrmont
Last active November 14, 2018 05:05
Show Gist options
  • Save pyrmont/ed8277c5d07e76458c13e883261b4bd6 to your computer and use it in GitHub Desktop.
Save pyrmont/ed8277c5d07e76458c13e883261b4bd6 to your computer and use it in GitHub Desktop.
A script to generate an RSS feed for a Letterboxd watchlist.
@username = # Enter username as a String
# Editing below this line should not be required
require 'net/http'
require 'rss'
require 'uri'
class Watchlist
PATTERNS = {
title: /<meta property="og:title" content="([^"]+)" \/>/,
desc: /<meta property="og:description" content="([^"]+)" \/>/,
imdb: /<a href="([^"]+)maindetails" [^>]+ data-track-action="IMDb">/, poster: /(<div\s(?:[^>]+\s+)*class=["|'](?:[^"|']+\s+)*poster(?:\s+[^"|']+)*["|'](?:\s+[^>]+)*>)/im,
link: /data\-target\-link="([^"]+)"/
}
def initialize(username:)
@username = username
end
def rss()
RSS::Maker.make("rss2.0") do |maker|
maker.channel.title = "Letterboxd Watchlist for @#{@username}"
maker.channel.link = "https://letterboxd.com/#{@username}/watchlist/"
maker.channel.description = "An RSS feed of the movies in the Letterboxd Watchlist for @#{@username}."
maker.channel.generator = "Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
maker.channel.lastBuildDate = Time.now.to_s
movies.each do |movie|
maker.items.new_item do |item|
item.title = movie[:title]
item.link = movie[:imdb_url]
item.description = movie[:description]
item.guid.yield_self do |guid|
guid.permanent_link = false
guid.content = movie[:imdb_url]
end
end
end
end
end
def movies()
movie_pages.map do |page|
{ title: attr_title(page),
description: attr_desc(page),
imdb_url: attr_imdb(page) }
end
end
private def attr_title(html)
first_match html, PATTERNS[:title]
end
private def attr_desc(html)
first_match html, PATTERNS[:desc]
end
private def attr_imdb(html)
first_match html, PATTERNS[:imdb]
end
private def first_match(string, pattern)
result = string.match(pattern)
raise unless result
result[1]
rescue
msg = "The pattern #{pattern} did not match in the following:\n\n#{string}"
raise msg
end
private def movie_pages()
movie_urls.map { |url| read url }
end
private def movie_urls()
html = read "#{@username}/watchlist/"
results = html.scan PATTERNS[:poster]
results.map { |result| first_match(result[0], PATTERNS[:link]) }
end
private def read(fragment)
base_url = 'https://letterboxd.com/'
Net::HTTP.get(URI.parse(base_url + fragment))
end
end
rss = Watchlist.new(username: @username).rss
File.write 'feed.xml', rss
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment