Building a LoL Rank fetcher for Livestreams!
League of Legendsfor the uninitiated) every now and then, and in some very old live streams, I used to have a little box telling people my Rank.
Back then, I used a PHP-script that I wrote in order to get the ranks.
This, however, meant that I had to update my summoner name (I used a GET parameter, so it wasn't a big deal) when I was going to play on a smurf.
Initial ResearchToday, I found something very interesting, but before we dive in any deeper, I want you to know that writing this post so detailed cost me a lot of effort since I can't go as fast as I normally go.
So please if you really enjoyed this, make a donation for my efforts.
Now let's get into it!
I went with my usual stuff, checking which ports were listening on my PC (to search for malware) and I noticed there was a listener being opened by the LoL client (just the launcher, not the game).
So, I fired up my browser (jepp, that was my first guess) and entered the URL with the port
http://localhost:50864, and what did ya know?
So I thought? maybe the site is running on HTTPS?
So I changed the URL to
But what credentials would I possibly need?
So thinking it might be some pre-configured thing, I decided to look into my LoL installation folder.
Not too soon, I immediately saw a file called
What was interesting about it was that it wasn't the normal
0kbsize (which means the file is empty) but was
This meant that there was something in it.
So, I opened the file and saw this (I blurted out something that resembles a password):
After a bit of searching, I came by this code that showed me how to build the credential string.
So it was quite obvious to me what the stuff on the lockfile meant:
So now that I have that, I can try to create something with it!
Process Name : Process ID : Port : Password : https
First, I created a repo on GitLab in order to easily show you what I exactly have been doing in my code.
Feel free to fork my code if you'd like to.
I then created my main script
I could now work on the first step in building my program:
Reading the LockfileReading the
lockfilenow will save me a lot of issues later, as this file will contain all the
dynamically generateddata that I need.
This saves me from having to keep track of this myself in case of me restarting the client or my PC or whatever.
So first, I defined a function that will read the
To do so, I used Python's built-in file reader like so.
I only need to read the file, so I added the
rflag to it.
I then added a print statement to see whether it read the file properly, which it didn't.
This time, it worked just fine.
added a variable to easily change that if needed.
Now that I have all of that, I could work on getting all the individual values.
To do so, I had to
Python (and most other languages) has a nice function for that, so obviously, I went with that.
Obviously, I used the
:as a delimiter.
This is the code that I ended up with, which worked just fine.
return the data to the the call and remove the function call.
Now that we have all the data we can get out of the lockfile, we can start building the function to connect to the client api.
Connect to the client APIIn order to connect to the client api, I defined a function called
We will use this function to build the basic connection parameters.
I have decided to do this using
urllib3, as that seems to be the most used on StackOverflow (lmao).
So I added an import for that into my script.
Next, I added an urllib3 poolmanager, after which I added a call to the
I now passed the results of the
readLockfilefunction into the
getConnectionfunction so I could access its data.
Now that I have that data, I can start building the URL.
It was really simple and this is what I ended up with, nothing major.
I could now work on getting the right headers.
The way I did this is not how I would normally do this, but for the sake of ease for you guys, I decided to do it this way anyways.
I added the first 2 basic headers:
Now how I know that it uses the
Well, I don't, they are just pure guesses at this moment.
I now realized that I do not need the url here, but somewhere else, so, I removed the creation of the url out of that function for now and moved some bits and pieces around.
At this point, I was ready to try to connect to the api.
So I added a return statement to
getConnection(I forgot that) and build the rest of the code to connect to the api.
fix that, so I did and tried again...
This actually means that what I build so far is sorta working.
So now I just dumped the data we got from the request.
403, which is just what I expected since we didn't pass any authentication yet.
So let's do that next!
Authentication to the Client APILooking back at the IcuRequest.js, we can see we need to pass a basic authentication token into the header.
This token is made by taking the username
riotand password (the one in our
lockfile) and encoding it using base64.
This should be super simple, so let's get that done!
First, I need to import the bas64 library.
I then defined a function that will create the token for us.
It takes the
passwordvariable so we don't have to pass the entire data object to it.
I ended up with this small code, which does the job just fine I guess :)
That means I can now pass it to the
I added a
tokenparameter to the function to which I can pass this token.
I then proceeded to add the
However, I got an error when I tried to run it...
decoded the bytes and tried again...
After about an hour of searching with my friend
Spike2147, I finally got that golden eureka moment:
And when thinking about it, it does kinda make sense.
Using `https://localhost` was forbidden, but using `https://127.0.0.1` wasn't.
All I got not is a juicy
404error (which I can easily fix) <3
Getting the SummonerSo now that I got the authentication to work, I needed to get my Summoner information.
Luckily, this was not very difficult.
After a bit of Wiresharking (of which I did not have a screenshot T_T), I found that the endpoint that I need was
So, I added that in and found some useful data:
I now created a function to easily decode the JSON so that we could get our
summonerIdfrom the object.
After I finished that, I went and created a function that would get our
And while this is no major thing, having it in a function can make it easier in the long run.
After adding and removing some code, I could now work to the next step.
Getting the RankNow that we have our
summonerId, we can hook that into the
Riot Games APIto get the current stats directly from their servers.
So, I added a variable for the
API Key(well, I did this a big before actually ending up here, sorry) and then proceeded to read the
Riot Games Documentation.
I quickly came by this page, at which I could easily test the endpoints.
That was just what I needed!
So after seeing what request headers I needed, I could continue on my script.
so, I created a function called
getRank, which took the
summonerIdas a parameter, adds some headers (of which the API key is one, the most important one even!), sends off a new request and decodes the JSON.
Now that I had all of that, I was only interested in the
"leagueName": "Karthus's Urfriders",
"leagueName": "Malzahar's Outriders",
RANKED_SOLO_5x5Queue (as that's what I mostly play on stream anyway).
I now added a little
forloop that will check if the
RANKED_SOLO_5x5and if so, returns that entire object.
At this point, the research part of this project is over.
All that's left to do is to build a wrapper around it.
Since I'll be using this for streams, I probably will decide on using a HTTP server for that, but I'll see about that.
I hope you guys enjoyed this little research project of mine, if you did, please leave a donation, this project was quite a bit of effort for me so it'll be nice to see something in return :)
But for now,
Leave a comment
Please login to leave comment!