From: Alexander Goussas Date: Sun, 5 Jul 2026 19:57:35 +0000 (-0500) Subject: feat: add option to export wordlist to Anki X-Git-Url: http://git.frustrated-labs.net/?a=commitdiff_plain;h=HEAD;p=larousseapi feat: add option to export wordlist to Anki --- diff --git a/src/main/java/net/frustratedfunctor/ui/UiResource.java b/src/main/java/net/frustratedfunctor/ui/UiResource.java index 589b11d..3f9b039 100644 --- a/src/main/java/net/frustratedfunctor/ui/UiResource.java +++ b/src/main/java/net/frustratedfunctor/ui/UiResource.java @@ -8,13 +8,21 @@ import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; import net.frustratedfunctor.definitions.WordDefinitionService; import net.frustratedfunctor.translations.WordTranslationService; +import org.jboss.resteasy.reactive.PartType; +import org.jboss.resteasy.reactive.RestForm; +import org.jboss.resteasy.reactive.multipart.FileUpload; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStreamReader; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.stream.Collectors; @Path("/ui") public class UiResource { @@ -47,4 +55,55 @@ public class UiResource { return index.data("translationsDefinitions", data); } + // TODO: Use SSE to run this in the background and notify client when process is done. + + @Path("ankiExport") + @POST + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response exportToAnki( + @RestForm("lang") String lang, + @PartType(MediaType.MULTIPART_FORM_DATA) + @RestForm("anki-export") FileUpload fileUpload + ) throws Exception { + final var file = fileUpload.uploadedFile().toFile(); + final var sb = new StringBuilder( + """ + #separator:Tab + #html:true + #notetype:Basic + #deck:%s + """.formatted("CHANGEME") // TODO: Allow customizing deck name. + ); + + try ( + final var reader = new InputStreamReader(new FileInputStream(file)); + final var br = new BufferedReader(reader) + ) { + final var words = br.lines().toList(); + for (final var word : words) { + final var def = definitions.define(word, lang); + sb.append(def.word()) + .append("\t") + .append("") + .append("\n"); + Thread.sleep(500); + } + } + + final var contents = sb.toString(); + return Response.ok() + .header("Content-Disposition", "attachment; filename=\"anki.txt\"") + .header("Content-Length", contents.length()) + .entity(contents) + .build(); + } + } diff --git a/src/main/resources/templates/pub/index.html b/src/main/resources/templates/pub/index.html index 05d60c8..377a783 100644 --- a/src/main/resources/templates/pub/index.html +++ b/src/main/resources/templates/pub/index.html @@ -45,6 +45,24 @@

Frustrated Langs

+
+
+ Upload file to export to Anki. + + + +
+
+