-
-
Save tors42/be34feb13e15486a1f10660dda3f9133 to your computer and use it in GitHub Desktop.
Export Chess960 games from cc and import them into an existing Lichess Study
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
String ccUser = "entarozerathul"; | |
String variant = "chess960"; | |
int maxNumGames = 64; | |
String nameOfExistingLichessStudy = "ccimport"; | |
if (! Files.exists(Path.of("chariot.jar"))) { | |
Files.write(Path.of("chariot.jar"), URI.create( | |
"https://repo1.maven.org/maven2/io/github/tors42/chariot/0.0.87/chariot-0.0.87.jar" | |
).toURL().openStream().readAllBytes()); | |
} | |
/env --class-path chariot.jar | |
import chariot.*; | |
import chariot.Client.*; | |
import chariot.model.*; | |
void runWithClient(ClientAuth client) { | |
if (client.account().profile() instanceof Entry(var user) | |
&& client.studies().listStudiesByUser(user.id()).stream(). | |
filter(meta -> meta.name().equals(nameOfExistingLichessStudy)). | |
map(meta -> meta.id()).findFirst().orElse(null) instanceof String studyId) { | |
List<String> pgns = ccExport(); | |
if (! pgns.isEmpty()) { | |
try { | |
var tmp = Files.createTempFile("pgn-export-", "-" + ccUser); | |
Files.write(tmp, pgns); | |
System.out.println("Wrote " + pgns.size() + " PGNs to " + tmp); | |
} catch (IOException ioe) {} | |
var chapters = client.studies().importPgn(studyId, p -> p.name("imported").pgn(pgns)).stream().toList(); | |
System.out.println("Imported " + chapters.size() + " chapters"); | |
} else { | |
System.out.println("Found no games"); | |
} | |
} else { | |
System.out.println("You must create a study named " + nameOfExistingLichessStudy + "in order to be able to import games."); | |
} | |
} | |
record YearMonth(String year, String month) { | |
static YearMonth of(Path path) { | |
try { return new YearMonth( path.getParent().getFileName().toString(), path.getFileName().toString()); | |
} catch(Exception e) { return null; } | |
} | |
} | |
public record Archives(List<URI> archives) { | |
Stream<YearMonth> toYearMonth() { | |
return archives.stream().map(URI::getPath).map(Path::of) | |
.mapMulti((path, stream) -> { if (YearMonth.of(path) instanceof YearMonth ym) stream.accept(ym); }); | |
} | |
} | |
public record Game(String pgn, String rules) {} | |
public record Games(List<Game> games) {} | |
List<String> ccExport() { | |
var ccClient = Client.basic(cc -> cc.api("https://api.chess.com").userAgent(ccUser, true)); | |
var listOfArchives = ccClient.custom().of(Archives.class).path("/pub/player/%s/games/archives").toOne(); | |
var gamesInArchive = ccClient.custom().of(Games.class).path("/pub/player/%s/games/%s/%s").toOne(); | |
return switch(listOfArchives.request(r -> r.path(ccUser))) { | |
case NoEntry<?> fail -> { System.err.println("Failed to list archives: " + fail); yield List.of(); } | |
case Entry(Archives archives) -> archives.toYearMonth().toList().reversed().stream(). | |
flatMap(archive -> switch(gamesInArchive.request(r -> r.path(ccUser, archive.year(), archive.month()))) { | |
case NoEntry<?> fail -> { System.err.println("Failed to fetch archive: " + archive); yield Stream.of(); } | |
case Entry(Games(List<Game> games)) -> games.stream(); | |
}). | |
filter(game -> variant.equals(game.rules())). | |
map(Game::pgn). | |
limit(maxNumGames). | |
toList(); | |
}; | |
} | |
switch (Client.basic().withPkce( | |
url -> System.out.println("Visit the following URL to grant permission:\n\n" + url), | |
pkce -> pkce.scope(Client.Scope.study_read, Client.Scope.study_write))) { | |
case AuthOk(var client) -> runWithClient(client); | |
case AuthFail(var fail) -> System.out.println("Authorization failed: " + fail); | |
} | |
/exit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Runs with https://jdk.java.net/22
First create a study named "ccimport",
and then run the script
Example of run,