summaryrefslogtreecommitdiff
path: root/lib/sampling/riot_api.rb
blob: 3de4185df93f938752cb04be2e90e13f07bd0911 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
module Sampling
	module RiotApi
		##
		# Return whether or not this sampling method works with the specified game.
		# Spoiler: It only works with League of Legends (or subclasses of it).
		public
		def works_with?(game)
			if api_key.nil? or region.nil?
				return false
			end
			if game.name == "League of Legends"
				return true
			end
			unless game.parent.nil?
				return works_with?(game.parent)
			end
		end

		##
		# This sampling method uses remote IDs
		public
		def uses_remote?
			return true
		end

		##
		# When given a summoner name for a user, figure out the summoner ID.
		public
		def set_remote_name(user, game, summoner_name)
			Delayed::Job.enqueue(UsernameJob.new(user, game, summoner_name), :queue => api_name)
		end
		private
		class UsernameJob < Job
			def initialize(user, game, summoner_name)
				@user_id = user.id
				@game_id = game.id
				# Escape any funny stuff
				summoner_names = [summoner_name].map{|name|Sampling::RiotApi::standardize(name.gsub(',',''))}
				# Generate the request
				super("v1.3/summoner/by-name/%{summonerNames}", { :summonerNames => summoner_names.join(",") })
			end
			def handle(data)
				user = User.find(@user_id)
				game = Game.find(@game_id)
				
				normalized_summoner_name = data.keys.first
				remote_data = {
					:id   => data[normalized_summoner_name]["id"],
					:name => data[normalized_summoner_name]["name"],
				}

				user.set_remote_username(game, remote_data)
			end
		end	

		##
		# When given data from RemoteUsername#value, give back a readable name to display.
		# Here, this is the summoner name.
		public
		def get_remote_name(data)
			data["name"]
		end

		##
		# Fetch all the statistics for a match.
		public
		def sampling_start(match)
			@match.teams.each do |team|
				team.users.each do |user|
					Delayed::Job.enqueue(MatchJob.new(user, match), :queue => api_name)
				end
			end
		end
		private
		class FetchStatisticsJob < Job
			def initialize(user, match)
				@user_id = user.id
				@match_id = match.id
				# Get the summoner id
				summoner = user.get_remote_username(match.tournament_stage.tournament.game)
				if summoner.nil?
					raise "Someone didn't enter their summoner name"
				end
				# Generate the request
				super("v1.3/game/by-summoner/%{summonerId}/recent", { :summonerId => summoner["id"] })
			end
			def handle(data)
				user = User.find(@user_id)
				match = Match.find(@match_id)
				Statistic.create(user: user, match: match, value: TODO)
			end
		end

		public
		def sampling_done?(match)
			# TODO
		end

		public
		def render_user_interaction(match, user)
			return ""
		end

		public
		def handle_user_interaction(match, user)
		end

		########################################################################

		private
		def api_name
			"prod.api.pvp.net/api/lol"
		end

		private
		def api_key
			ENV["RIOT_API_KEY"]
		end

		private
		def region
			ENV["RIOT_API_REGION"]
		end

		private
		def url(request, args={})
			"https://prod.api.pvp.net/api/lol/#{region}/#{request % args.merge(args){|k,v|url_escape(v)}}?#{api_key}"
		end

		private
		def url_escape(string)
			URI::escape(string.to_s, /[^a-zA-Z0-9._~!$&'()*+,;=:@-]/)
		end

		private
		def standardize(summoner_name)
			summoner_name.to_s.downcase.gsub(' ', '')
		end

		private
		class Job < ThrottledApiRequest.new(api_name, 10.seconds, 10)
			def initialize(request, args={})
					@url = Sampling::RiotApi::url(request, args)
			end

			def perform
				response = open(@url)
				status = response.status
				data = JSON::parse(response.read)

				# Error codes that RIOT uses:
				#   "400"=>"Bad request"
				#   "401"=>"Unauthorized"
				#   "429"=>"Rate limit exceeded"
				#   "500"=>"Internal server error"
				#   "503"=>"Service unavailable"
				#   "404"=>"Not found"
				# Should probably handle these better
				if status[0] != "200"
					raise "GET #{@url} => #{status.join(" ")}"
				end
				self.handle(data)
			end

			def handle(data)
			end
		end
	end
end