-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c7f10f4
Showing
19 changed files
with
780 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# IntelliJ | ||
*.iml | ||
*.ipr | ||
*.iws | ||
.idea/ | ||
.settings/ | ||
|
||
# Build | ||
build/ | ||
bin/ | ||
dist/ | ||
manifest.mf | ||
|
||
# Maven | ||
target/ | ||
build.xml | ||
|
||
# Other Stuff | ||
logs/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
## Unfinished API for the League of Legends client endpoints of the locally running server | ||
|
||
### How to obtain an API instance? | ||
Make sure to start the League of Legends client before you call the #hookAPI method, | ||
the system will fetch all tokens and ports from the running process so you don't have to | ||
do or provide anything manually. | ||
```java | ||
final LeagueClientAPI api = LeagueClient.getInstance().hookAPI(); | ||
``` | ||
|
||
### What's currently possible? | ||
The API provided by this library currently only supports a few things: | ||
- You can fetch all people that you're in a lobby with (even in ranked lobbies where names are hidden): `LeagueClient#getParticipants` | ||
- You can fetch locale data (language, region, etc.): `LeagueClient#getRegionLocale` | ||
- You can fetch your wallet data (RP, blue essence): `LeagueClient#getWallet` | ||
- You can fetch your login session info: `LeagueClient#getSession` | ||
- You can fetch your current summoner data (profile icon id, level, required xp, etc.): `LeagueClient#getCurrentSummoner` | ||
- You can check if your account is eligible for a free riot alias change: `LeagueClient#isEligibleForFreeRiotAlias` | ||
- You can invite people to your current lobby: `LeagueClient#inviteToLobby` | ||
- You can create a new lobby for any active game mode: `LeagueClient#createLobby` | ||
- You can set your Solo & Duo Rank to Challenger (only visible in chat module, not profile): `LeagueClient#fakeRank` | ||
|
||
### How do I contribute/find more endpoints? | ||
Easiest way is to use an IFEO debugger to get rid of some of the flags that get applied to the client when it gets started. | ||
Once this is done you can use a tool like Fiddler after enabling HTTPS decryption. If you want to make your own IFEO debugger | ||
I'd recommend to use C# for simplicity, might upload a project for one at a later point. Any implementation you find on GitHub | ||
should work just fine. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>dev.dexuby</groupId> | ||
<artifactId>leagueclient4j</artifactId> | ||
<version>1.0.0</version> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<artifactId>maven-shade-plugin</artifactId> | ||
<version>3.5.1</version> | ||
<executions> | ||
<execution> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>shade</goal> | ||
</goals> | ||
<configuration> | ||
<relocations> | ||
<relocation> | ||
<pattern>org.slf4j</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.slf4j</shadedPattern> | ||
</relocation> | ||
<relocation> | ||
<pattern>dev.dexuby.easycommon</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.easycommon</shadedPattern> | ||
</relocation> | ||
<relocation> | ||
<pattern>org.intellij</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.intellij</shadedPattern> | ||
</relocation> | ||
<relocation> | ||
<pattern>org.jetbrains</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.jetbrains</shadedPattern> | ||
</relocation> | ||
<relocation> | ||
<pattern>com.google.gson</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.gson</shadedPattern> | ||
</relocation> | ||
</relocations> | ||
<filters> | ||
<filter> | ||
<artifact>*:*</artifact> | ||
<excludes> | ||
<exclude>module-info.class</exclude> | ||
<exclude>META-INF/**</exclude> | ||
</excludes> | ||
</filter> | ||
</filters> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
<repositories> | ||
<repository> | ||
<id>jitpack.io</id> | ||
<url>https://jitpack.io</url> | ||
</repository> | ||
</repositories> | ||
<properties> | ||
<maven.compiler.target>17</maven.compiler.target> | ||
<maven.compiler.source>17</maven.compiler.source> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>dev.dexuby</groupId> | ||
<artifactId>leagueclient4j</artifactId> | ||
<version>1.0.0</version> | ||
|
||
<properties> | ||
<maven.compiler.source>17</maven.compiler.source> | ||
<maven.compiler.target>17</maven.compiler.target> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-shade-plugin</artifactId> | ||
<version>3.5.1</version> | ||
<executions> | ||
<execution> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>shade</goal> | ||
</goals> | ||
<configuration> | ||
<relocations> | ||
<relocation> | ||
<pattern>org.slf4j</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.slf4j</shadedPattern> | ||
</relocation> | ||
<relocation> | ||
<pattern>dev.dexuby.easycommon</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.easycommon</shadedPattern> | ||
</relocation> | ||
<relocation> | ||
<pattern>org.intellij</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.intellij</shadedPattern> | ||
</relocation> | ||
<relocation> | ||
<pattern>org.jetbrains</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.jetbrains</shadedPattern> | ||
</relocation> | ||
<relocation> | ||
<pattern>com.google.gson</pattern> | ||
<shadedPattern>dev.dexuby.leagueclient4j.external.gson</shadedPattern> | ||
</relocation> | ||
</relocations> | ||
<filters> | ||
<filter> | ||
<artifact>*:*</artifact> | ||
<excludes> | ||
<exclude>module-info.class</exclude> | ||
<exclude>META-INF/**</exclude> | ||
</excludes> | ||
</filter> | ||
</filters> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<repositories> | ||
<repository> | ||
<id>jitpack.io</id> | ||
<url>https://jitpack.io</url> | ||
</repository> | ||
</repositories> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-simple</artifactId> | ||
<version>1.7.5</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.github.dexuby</groupId> | ||
<artifactId>easy-common</artifactId> | ||
<version>1.0.4</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.code.gson</groupId> | ||
<artifactId>gson</artifactId> | ||
<version>2.10.1</version> | ||
</dependency> | ||
</dependencies> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package dev.dexuby.leagueclient4j; | ||
|
||
import com.google.gson.Gson; | ||
import com.google.gson.GsonBuilder; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public final class Constants { | ||
|
||
public static final Logger LOGGER = LoggerFactory.getLogger("leaguebreach"); | ||
public static final String LEAGUE_CLIENT_EXECUTABLE = "LeagueClientUx.exe"; | ||
public static final Gson GSON = new GsonBuilder() | ||
.create(); | ||
|
||
} |
167 changes: 167 additions & 0 deletions
167
src/main/java/dev/dexuby/leagueclient4j/LeagueClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package dev.dexuby.leagueclient4j; | ||
|
||
import dev.dexuby.easycommon.external.jetbrains.annotations.NotNull; | ||
import dev.dexuby.easycommon.external.jetbrains.annotations.Nullable; | ||
import dev.dexuby.leagueclient4j.api.RequestData; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Base64; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
|
||
public final class LeagueClient { | ||
|
||
private static class LeagueClientSingleton { | ||
|
||
private static final LeagueClient INSTANCE = new LeagueClient(); | ||
|
||
} | ||
|
||
private LeagueClient() { | ||
|
||
} | ||
|
||
/** | ||
* Create a new league client API instance by fetching all the necessary data from the running process. | ||
* | ||
* @return The created league client API instance. | ||
*/ | ||
|
||
public LeagueClientAPI hookAPI() { | ||
|
||
final ProcessHandle processHandle = this.findLeagueProcessHandle(); | ||
if (processHandle == null) { | ||
Constants.LOGGER.error("Failed to find LeagueClientUx.exe"); | ||
return null; | ||
} | ||
|
||
final String commandLine = this.getCommandLine(processHandle).orElse(null); | ||
if (commandLine == null) { | ||
Constants.LOGGER.error("Failed to fetch command line."); | ||
return null; | ||
} | ||
|
||
final Map<String, String> arguments = this.extractArguments(commandLine); | ||
final String riotPort = arguments.get("--riotclient-app-port"); | ||
final String riotToken = Base64.getEncoder().encodeToString(("riot:" + arguments.get("--riotclient-auth-token")).getBytes(StandardCharsets.ISO_8859_1)); | ||
final String clientPort = arguments.get("--app-port"); | ||
final String clientToken = Base64.getEncoder().encodeToString(("riot:" + arguments.get("--remoting-auth-token")).getBytes(StandardCharsets.ISO_8859_1)); | ||
|
||
return new LeagueClientAPI(new RequestData(riotPort, riotToken, clientPort, clientToken)); | ||
|
||
} | ||
|
||
/** | ||
* Find the league client process handle. | ||
* | ||
* @return The process handle or <code>null</code>. | ||
*/ | ||
|
||
@Nullable | ||
private ProcessHandle findLeagueProcessHandle() { | ||
|
||
return ProcessHandle.allProcesses() | ||
.filter(handle -> handle.info().command().orElse("").endsWith(Constants.LEAGUE_CLIENT_EXECUTABLE)) | ||
.findFirst() | ||
.orElse(null); | ||
|
||
} | ||
|
||
/** | ||
* Get command line on windows. | ||
* | ||
* @param processHandle The process handle. | ||
* @return Optional containing the command line or nothing if not found. | ||
*/ | ||
|
||
private Optional<String> getCommandLine(@NotNull final ProcessHandle processHandle) { | ||
|
||
if (!this.isWindows()) | ||
return processHandle.info().commandLine(); | ||
|
||
try { | ||
final Process process = new ProcessBuilder("wmic", "process", "where", "ProcessID=" + processHandle.pid(), "get", | ||
"commandline", "/format:list"). | ||
redirectErrorStream(true). | ||
start(); | ||
try (final InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream()); | ||
final BufferedReader reader = new BufferedReader(inputStreamReader)) { | ||
while (true) { | ||
final String line = reader.readLine(); | ||
if (line == null) | ||
return Optional.empty(); | ||
if (!line.startsWith("CommandLine=")) | ||
continue; | ||
return Optional.of(line.substring("CommandLine=".length())); | ||
} | ||
} | ||
} catch (final IOException ex) { | ||
Constants.LOGGER.error("Failed to fetch command line:", ex); | ||
return Optional.empty(); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Extracts all arguments from the provided command line. | ||
* | ||
* @param commandLine The command line. | ||
* @return The extracted arguments as a map. | ||
*/ | ||
|
||
private Map<String, String> extractArguments(@NotNull final String commandLine) { | ||
|
||
final Map<String, String> arguments = new HashMap<>(); | ||
final StringBuilder stringBuilder = new StringBuilder(); | ||
boolean read = false; | ||
for (final char c : commandLine.toCharArray()) { | ||
if (c == '"') { | ||
if (read) { | ||
read = false; | ||
final String argument = stringBuilder.toString(); | ||
final int firstIndex = argument.indexOf('='); | ||
if (firstIndex != -1) | ||
arguments.put(argument.substring(0, firstIndex), argument.substring(firstIndex + 1)); | ||
stringBuilder.setLength(0); | ||
} else { | ||
read = true; | ||
} | ||
} else { | ||
if (read) | ||
stringBuilder.append(c); | ||
} | ||
} | ||
|
||
return arguments; | ||
|
||
} | ||
|
||
/** | ||
* Determines if the program is running on Windows. | ||
* | ||
* @return <code>true</code> if it's running on Windows, <code>false</code> otherwise. | ||
*/ | ||
|
||
private boolean isWindows() { | ||
|
||
return System.getProperty("os.name").startsWith("Windows"); | ||
|
||
} | ||
|
||
/** | ||
* Returns the singleton instance. | ||
* | ||
* @return The singleton instance. | ||
*/ | ||
|
||
public static LeagueClient getInstance() { | ||
|
||
return LeagueClientSingleton.INSTANCE; | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.