Skip to content

Commit

Permalink
Implement caching for Speedrun.com.
Browse files Browse the repository at this point in the history
  • Loading branch information
stefansundin committed Jan 15, 2021
1 parent d530088 commit 5d965a8
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 61 deletions.
79 changes: 64 additions & 15 deletions app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1181,39 +1181,88 @@

if /speedrun\.com\/run\/(?<run_id>[^\/?#]+)/ =~ params[:q]
# https://www.speedrun.com/run/1zx0qkez
response = App::Speedrun.get("/runs/#{run_id}")
raise(App::SpeedrunError, response) if !response.success?
game = response.json["data"]["game"]
game, _ = App::Cache.cache("speedrun.run.#{run_id}", 60*60, 60) do
response = App::Speedrun.get("/runs/#{run_id}")
raise(App::SpeedrunError, response) if !response.success?
response.json["data"]["game"]
end
return [422, "Something went wrong. Try again later."] if game.nil?
elsif /speedrun\.com\/(?<game>[^\/?#]+)/ =~ params[:q]
# https://www.speedrun.com/alttp#No_Major_Glitches
else
game = params[:q]
end

response = App::Speedrun.get("/games/#{game}")
if response.redirect?
game = response.headers["location"][0].split("/")[-1]
path, _ = App::Cache.cache("speedrun.game.#{game.downcase}", 60*60, 60) do
response = App::Speedrun.get("/games/#{game}")
if response.redirect?
game = response.headers["location"][0].split("/")[-1]
response = App::Speedrun.get("/games/#{game}")
end
next "Error: Can't find a game with that name." if response.code == 404
raise(App::SpeedrunError, response) if !response.success?
data = response.json["data"]
"#{data["id"]}/#{data["abbreviation"]}"
end
return [response.code, "Can't find a game with that name."] if response.code == 404
raise(App::SpeedrunError, response) if !response.success?
data = response.json["data"]
return [422, "Something went wrong. Try again later."] if path.nil?
return [422, path] if path.start_with?("Error:")

redirect Addressable::URI.new(path: "/speedrun/#{data["id"]}/#{data["abbreviation"]}").normalize.to_s
redirect Addressable::URI.new(path: "/speedrun/#{path}").normalize.to_s
end

get "/speedrun/:id/:abbr" do |id, abbr|
@id = id
@abbr = abbr

response = App::Speedrun.get("/runs", query: { status: "verified", orderby: "verify-date", direction: "desc", game: id, embed: "category,players,level,platform,region" })
raise(App::SpeedrunError, response) if !response.success?
@data = response.json["data"].reject { |run| run["videos"].nil? }
data, @updated_at = App::Cache.cache("speedrun.runs.#{id}", 60*60, 60) do
response = App::Speedrun.get("/runs", query: { status: "verified", orderby: "verify-date", direction: "desc", game: id, embed: "category,players,level,platform,region" })
raise(App::SpeedrunError, response) if !response.success?
response.json["data"].reject do |run|
run["videos"].nil?
end.map do |run|
players = run["players"]["data"].map { |player| player["name"] || player["names"]["international"] }
videos = if run["videos"].has_key?("links")
run["videos"]["links"].map { |link| link["uri"] }
elsif run["videos"].has_key?("text")
[ run["videos"]["text"] ]
end

if !run["level"]["data"].empty?
category_link = "https://www.speedrun.com/#{@abbr}/#{run["level"]["data"]["weblink"].split("/")[-1]}"
category = "#{run["category"]["data"]["name"]}: #{run["level"]["data"]["name"]}"
else
category_link = "https://www.speedrun.com/#{@abbr}##{run["category"]["data"]["weblink"].partition("#")[2]}"
category = run["category"]["data"]["name"]
end

if run["platform"]["data"].is_a?(Hash)
platform = run["platform"]["data"]["name"]
platform += " (#{run["region"]["data"]["name"]})" if run["system"]["region"]
platform += " [emu]" if run["system"]["emulated"]
end

{
"id" => run["id"],
"date" => run["date"],
"submitted" => run["submitted"],
"comment" => run["comment"],
"times" => run["times"]["primary_t"].round,
"category_link" => category_link,
"category" => category,
"platform" => platform,
"players" => players,
"videos" => videos,
}
end.to_json
end
return [422, "Something went wrong. Try again later."] if data.nil?
return [422, data] if data.start_with?("Error:")

@data = JSON.parse(data)

@data.map do |run|
[
run["videos"]["links"]&.map { |link| link["uri"] },
run["videos"]["text"],
run["videos"],
run["comment"],
].flatten.compact.map(&:grep_urls)
end.flatten.tap { |urls| App::URL.resolve(urls) }
Expand Down
29 changes: 9 additions & 20 deletions app/speedrun.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,17 @@ class Speedrun < HTTP
}
ERROR_CLASS = SpeedrunError

@@cache = {}

def self.resolve_id(type, id)
@@cache[type] ||= {}
return @@cache[type][id] if @@cache[type][id]
value = $redis.get("speedrun:#{type}:#{id}")
if value
@@cache[type][id] = value
return value
end

if type == "game"
response = get("/games/#{id}")
raise(SpeedrunError, response) if !response.success?
value = response.json["data"]["names"]["international"]
else
raise("unsupported type")
value, _ = App::Cache.cache("speedrun.#{type}.#{id}", 24*60*60, 60) do
if type == "game"
response = Speedrun.get("/games/#{id}")
raise(SpeedrunError, response) if !response.success?
response.json["data"]["names"]["international"]
else
raise("unsupported type")
end
end

$redis.set("speedrun:#{type}:#{id}", value)
@@cache[type][id] = value
return value
value
end
end
end
Expand Down
35 changes: 9 additions & 26 deletions views/speedrun.atom.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,34 @@
<icon>https://www.speedrun.com/favicon.ico</icon>
<link href="<%= request.original_url.esc %>" rel="self" />
<link href="https://www.speedrun.com/<%= @abbr %>" rel="alternate" />
<updated><%= @data[0]["submitted"] || Time.parse(@data[0]["date"]) if @data[0] %></updated>
<updated><%= @updated_at %></updated>
<%-
@data.each do |run|
players = run["players"]["data"].map { |player| player["name"] || player["names"]["international"] }
videos = if run["videos"].has_key?("links")
"Videos: " + run["videos"]["links"].map { |link| link["uri"] }.join(" | ")
elsif run["videos"].has_key?("text")
"Videos: " + run["videos"]["text"]
videos = if run["videos"]
"Videos: " + run["videos"].join(" | ")
else
"No video"
end

if !run["level"]["data"].empty?
category_link = "https://www.speedrun.com/#{@abbr}/#{run["level"]["data"]["weblink"].split("/")[-1]}"
category = "#{run["category"]["data"]["name"]}: #{run["level"]["data"]["name"]}"
else
category_link = "https://www.speedrun.com/#{@abbr}##{run["category"]["data"]["weblink"].partition("#")[2]}"
category = run["category"]["data"]["name"]
end

if run["platform"]["data"].is_a?(Hash)
platform = run["platform"]["data"]["name"]
platform += " (#{run["region"]["data"]["name"]})" if run["system"]["region"]
platform += " [emu]" if run["system"]["emulated"]
end
-%>

<entry>
<id>speedrun:run:<%= run["id"] %><%= ":#{params[:cachebuster]}" if params[:cachebuster] %></id>
<title>[<%= run["times"]["primary_t"].round.to_duration %>] <%= players.join(", ").esc %> - <%= category %></title>
<title>[<%= run["times"].to_duration %>] <%= run["players"].join(", ").esc %> - <%= run["category"] %></title>
<link href="<%= "https://www.speedrun.com/run/#{run["id"]}" %>" />
<updated><%= run["submitted"] || Time.parse(run["date"]) %></updated>
<author><name><%= players.join(", ").esc %></name></author>
<author><name><%= run["players"].join(", ").esc %></name></author>
<content type="html">
<%= <<~EOF.esc
#{videos.linkify_and_embed(request).to_paragraphs}
#{run["comment"].linkify.to_paragraphs}
<p>Category: <a href="#{category_link}" rel="noreferrer">#{category}</a></p>
<p>Runners: #{players.map { |name| "<a href='https://www.speedrun.com/user/#{name}' rel='noreferrer'>#{name}</a>" }.join(", ")}</p>
<p>Category: <a href="#{run["category_link"]}" rel="noreferrer">#{run["category"]}</a></p>
<p>Runners: #{run["players"].map { |name| "<a href='https://www.speedrun.com/user/#{name}' rel='noreferrer'>#{name}</a>" }.join(", ")}</p>
EOF
-%>
<%= <<~EOF.esc if platform
<p>Platform: #{platform}</p>
<%= <<~EOF.esc if run["platform"]
<p>Platform: #{run["platform"]}</p>
EOF
-%>
</content>
Expand Down

0 comments on commit 5d965a8

Please sign in to comment.