@@ -118,15 +118,18 @@ def sync_player(player, import_matches: true)
118118 return { success : false , error : 'Player missing PUUID' } if player . riot_puuid . blank?
119119
120120 begin
121- # 1. Fetch current rank and profile
121+ # 1. Fetch account info to get current gameName#tagLine
122+ account_data = fetch_account_by_puuid ( player . riot_puuid )
123+
124+ # 2. Fetch current rank and profile
122125 summoner_data = fetch_summoner_by_puuid ( player . riot_puuid )
123126 # Use PUUID to fetch rank data (summoner_id is no longer returned by Riot API)
124127 rank_data = fetch_rank_data_by_puuid ( player . riot_puuid )
125128
126- # 2 . Update player with fresh data
127- update_player_from_riot ( player , summoner_data , rank_data )
129+ # 3 . Update player with fresh data (including summoner_name if changed)
130+ update_player_from_riot ( player , account_data , summoner_data , rank_data )
128131
129- # 3 . Optionally fetch recent matches
132+ # 4 . Optionally fetch recent matches
130133 matches_imported = 0
131134 matches_imported = import_player_matches ( player , count : 20 ) if import_matches
132135
@@ -146,6 +149,19 @@ def sync_player(player, import_matches: true)
146149 end
147150 end
148151
152+ # Fetch account info (gameName, tagLine) by PUUID
153+ def fetch_account_by_puuid ( puuid )
154+ regional_endpoint = get_regional_endpoint ( region )
155+
156+ # Use whitelisted host to prevent SSRF
157+ uri = URI ::HTTPS . build (
158+ host : regional_api_host ( regional_endpoint ) ,
159+ path : "/riot/account/v1/accounts/by-puuid/#{ ERB ::Util . url_encode ( puuid ) } "
160+ )
161+ response = make_request ( uri . to_s )
162+ JSON . parse ( response . body )
163+ end
164+
149165 # Fetch summoner by PUUID
150166 def fetch_summoner_by_puuid ( puuid )
151167 # Use whitelisted host to prevent SSRF
@@ -216,26 +232,26 @@ def import_player_matches(player, count: 20)
216232
217233 # Search for a player by Riot ID (GameName#TagLine)
218234 def search_riot_id ( game_name , tag_line )
219- Rails . logger . info ( "🎮 Searching for Riot ID: #{ game_name } ##{ tag_line } " )
220- Rails . logger . info ( "🌍 Region: #{ region } " )
235+ Rails . logger . info ( "Searching for Riot ID: #{ game_name } ##{ tag_line } " )
236+ Rails . logger . info ( "Region: #{ region } " )
221237
222238 regional_endpoint = get_regional_endpoint ( region )
223- Rails . logger . info ( "🗺️ Regional endpoint: #{ regional_endpoint } " )
239+ Rails . logger . info ( "Regional endpoint: #{ regional_endpoint } " )
224240
225241 # Use whitelisted host to prevent SSRF
226242 # Use ERB::Util.url_encode instead of CGI.escape to properly encode spaces as %20 (not +)
227243 encoded_game_name = ERB ::Util . url_encode ( game_name )
228244 encoded_tag_line = ERB ::Util . url_encode ( tag_line )
229245
230- Rails . logger . info ( "📝 Encoded game_name: '#{ game_name } ' -> '#{ encoded_game_name } '" )
231- Rails . logger . info ( "📝 Encoded tag_line: '#{ tag_line } ' -> '#{ encoded_tag_line } '" )
246+ Rails . logger . info ( "Encoded game_name: '#{ game_name } ' -> '#{ encoded_game_name } '" )
247+ Rails . logger . info ( "Encoded tag_line: '#{ tag_line } ' -> '#{ encoded_tag_line } '" )
232248
233249 uri = URI ::HTTPS . build (
234250 host : regional_api_host ( regional_endpoint ) ,
235251 path : "/riot/account/v1/accounts/by-riot-id/#{ encoded_game_name } /#{ encoded_tag_line } "
236252 )
237253
238- Rails . logger . info ( "🔗 Full URL: #{ uri } " )
254+ Rails . logger . info ( "Full URL: #{ uri } " )
239255
240256 response = make_request ( uri . to_s )
241257 account_data = JSON . parse ( response . body )
@@ -254,9 +270,9 @@ def search_riot_id(game_name, tag_line)
254270 rank_data : rank_data
255271 }
256272 rescue StandardError => e
257- Rails . logger . error ( "❌ Failed to search Riot ID #{ game_name } ##{ tag_line } : #{ e . message } " )
258- Rails . logger . error ( "❌ Exception class: #{ e . class . name } " )
259- Rails . logger . error ( "❌ Backtrace: #{ e . backtrace . first ( 5 ) . join ( "\n " ) } " )
273+ Rails . logger . error ( "Failed to search Riot ID #{ game_name } ##{ tag_line } : #{ e . message } " )
274+ Rails . logger . error ( "Exception class: #{ e . class . name } " )
275+ Rails . logger . error ( "Backtrace: #{ e . backtrace . first ( 5 ) . join ( "\n " ) } " )
260276 nil
261277 end
262278
@@ -302,7 +318,7 @@ def check_existing_player(puuid, summoner_name, riot_data)
302318 # Log security warning when attempting to import player from another org
303319 def log_security_warning ( summoner_name , riot_data , existing_player )
304320 Rails . logger . warn (
305- "⚠️ SECURITY: Attempt to import player #{ summoner_name } " \
321+ " SECURITY: Attempt to import player #{ summoner_name } " \
306322 "(PUUID: #{ riot_data [ :puuid ] } ) that belongs to organization " \
307323 "#{ existing_player . organization . name } by organization #{ organization . name } "
308324 )
@@ -372,16 +388,16 @@ def make_request(url)
372388 request [ 'X-Riot-Token' ] = api_key
373389
374390 # Debug logging
375- Rails . logger . info ( "🔍 Making Riot API request to: #{ uri } " )
376- Rails . logger . info ( "🔑 API Key present: #{ api_key . present? } (length: #{ api_key &.length || 0 } )" )
391+ Rails . logger . info ( " Making Riot API request to: #{ uri } " )
392+ Rails . logger . info ( " API Key present: #{ api_key . present? } (length: #{ api_key &.length || 0 } )" )
377393
378394 response = Net ::HTTP . start ( uri . hostname , uri . port , use_ssl : true ) do |http |
379395 http . request ( request )
380396 end
381397
382398 unless response . is_a? ( Net ::HTTPSuccess )
383399 error_message = "Riot API Error: #{ response . code } - #{ response . body } "
384- Rails . logger . error ( "❌ Riot API Error - URL: #{ uri } - Status: #{ response . code } - Body: #{ response . body } " )
400+ Rails . logger . error ( "Riot API Error - URL: #{ uri } - Status: #{ response . code } - Body: #{ response . body } " )
385401
386402 # Create custom exception with status code for better error handling
387403 error = RiotApiError . new ( error_message )
@@ -390,13 +406,13 @@ def make_request(url)
390406 raise error
391407 end
392408
393- Rails . logger . info ( "✅ Riot API request successful: #{ response . code } " )
409+ Rails . logger . info ( " Riot API request successful: #{ response . code } " )
394410 response
395411 end
396412
397413 # Update player with Riot data
398- def update_player_from_riot ( player , summoner_data , rank_data )
399- player . update! (
414+ def update_player_from_riot ( player , account_data , summoner_data , rank_data )
415+ update_attrs = {
400416 summoner_level : summoner_data [ 'summonerLevel' ] ,
401417 profile_icon_id : summoner_data [ 'profileIconId' ] ,
402418 solo_queue_tier : rank_data [ 'tier' ] ,
@@ -406,7 +422,18 @@ def update_player_from_riot(player, summoner_data, rank_data)
406422 solo_queue_losses : rank_data [ 'losses' ] ,
407423 last_sync_at : Time . current ,
408424 sync_status : 'success'
409- )
425+ }
426+
427+ # Update summoner_name if it has changed
428+ if account_data [ 'gameName' ] . present? && account_data [ 'tagLine' ] . present?
429+ new_summoner_name = "#{ account_data [ 'gameName' ] } ##{ account_data [ 'tagLine' ] } "
430+ if player . summoner_name != new_summoner_name
431+ Rails . logger . info ( " Player #{ player . id } name changed: #{ player . summoner_name } → #{ new_summoner_name } " )
432+ update_attrs [ :summoner_name ] = new_summoner_name
433+ end
434+ end
435+
436+ player . update! ( update_attrs )
410437 end
411438
412439 # Import a match from Riot data
0 commit comments