Skip to content

Instantly share code, notes, and snippets.

@tors42
Created May 1, 2024 15:21
Show Gist options
  • Save tors42/be34feb13e15486a1f10660dda3f9133 to your computer and use it in GitHub Desktop.
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
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
@tors42
Copy link
Author

tors42 commented May 1, 2024

Runs with https://jdk.java.net/22

First create a study named "ccimport",
and then run the script

Example of run,

$ jshell chess960-cc.jsh 
Visit the following URL to grant permission:

https://lichess.org/oauth?scope=study%3Aread+study%3Awrite&code_challenge=25I0rUMQxA3s7DXFfc2YNNbCRR7aj8GtGa6VSFOaoO0&response_type=code&code_challenge_method=S256&client_id=chariot&redirect_uri=http%3A%2F%2F127.0.0.1%3A32993%2F&state=LtTp99SC
Wrote 13 PGNs to /tmp/pgn-export-10614070444967535563-entarozerathul
Imported 13 chapters

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment