diff --git a/archive/src/main/kotlin/org/openrs2/archive/ArchiveModule.kt b/archive/src/main/kotlin/org/openrs2/archive/ArchiveModule.kt index fb92e236..2e210684 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/ArchiveModule.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/ArchiveModule.kt @@ -6,6 +6,8 @@ import com.google.inject.multibindings.Multibinder import org.openrs2.archive.key.KeyDownloader import org.openrs2.archive.key.OpenOsrsKeyDownloader import org.openrs2.archive.key.RuneLiteKeyDownloader +import org.openrs2.archive.name.NameDownloader +import org.openrs2.archive.name.RuneStarNameDownloader import org.openrs2.buffer.BufferModule import org.openrs2.cache.CacheModule import org.openrs2.db.Database @@ -25,8 +27,11 @@ public object ArchiveModule : AbstractModule() { .toProvider(DatabaseProvider::class.java) .`in`(Scopes.SINGLETON) - val binder = Multibinder.newSetBinder(binder(), KeyDownloader::class.java) - binder.addBinding().to(OpenOsrsKeyDownloader::class.java) - binder.addBinding().to(RuneLiteKeyDownloader::class.java) + val keyBinder = Multibinder.newSetBinder(binder(), KeyDownloader::class.java) + keyBinder.addBinding().to(OpenOsrsKeyDownloader::class.java) + keyBinder.addBinding().to(RuneLiteKeyDownloader::class.java) + + val nameBinder = Multibinder.newSetBinder(binder(), NameDownloader::class.java) + nameBinder.addBinding().to(RuneStarNameDownloader::class.java) } } diff --git a/archive/src/main/kotlin/org/openrs2/archive/name/DownloadCommand.kt b/archive/src/main/kotlin/org/openrs2/archive/name/DownloadCommand.kt new file mode 100644 index 00000000..b76ce64d --- /dev/null +++ b/archive/src/main/kotlin/org/openrs2/archive/name/DownloadCommand.kt @@ -0,0 +1,14 @@ +package org.openrs2.archive.name + +import com.github.ajalt.clikt.core.CliktCommand +import com.google.inject.Guice +import kotlinx.coroutines.runBlocking +import org.openrs2.archive.ArchiveModule + +public class DownloadCommand : CliktCommand(name = "download") { + override fun run(): Unit = runBlocking { + val injector = Guice.createInjector(ArchiveModule) + val importer = injector.getInstance(NameImporter::class.java) + importer.download() + } +} diff --git a/archive/src/main/kotlin/org/openrs2/archive/name/NameCommand.kt b/archive/src/main/kotlin/org/openrs2/archive/name/NameCommand.kt index 9a77d77b..35ad92f0 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/name/NameCommand.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/name/NameCommand.kt @@ -6,6 +6,7 @@ import com.github.ajalt.clikt.core.subcommands public class NameCommand : NoOpCliktCommand(name = "name") { init { subcommands( + DownloadCommand(), GenerateCommand(), ImportCommand() ) diff --git a/archive/src/main/kotlin/org/openrs2/archive/name/NameDownloader.kt b/archive/src/main/kotlin/org/openrs2/archive/name/NameDownloader.kt new file mode 100644 index 00000000..270e1e3f --- /dev/null +++ b/archive/src/main/kotlin/org/openrs2/archive/name/NameDownloader.kt @@ -0,0 +1,5 @@ +package org.openrs2.archive.name + +public interface NameDownloader { + public suspend fun download(): Sequence +} diff --git a/archive/src/main/kotlin/org/openrs2/archive/name/NameImporter.kt b/archive/src/main/kotlin/org/openrs2/archive/name/NameImporter.kt index b97bf818..1e65cba3 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/name/NameImporter.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/name/NameImporter.kt @@ -7,8 +7,17 @@ import javax.inject.Singleton @Singleton public class NameImporter @Inject constructor( - private val database: Database + private val database: Database, + private val downloaders: Set ) { + public suspend fun download() { + val names = mutableSetOf() + for (downloader in downloaders) { + names += downloader.download() + } + import(names) + } + public suspend fun import(names: Iterable) { database.execute { connection -> connection.prepareStatement( diff --git a/archive/src/main/kotlin/org/openrs2/archive/name/RuneStarNameDownloader.kt b/archive/src/main/kotlin/org/openrs2/archive/name/RuneStarNameDownloader.kt new file mode 100644 index 00000000..e28fb53d --- /dev/null +++ b/archive/src/main/kotlin/org/openrs2/archive/name/RuneStarNameDownloader.kt @@ -0,0 +1,46 @@ +package org.openrs2.archive.name + +import kotlinx.coroutines.future.await +import org.openrs2.http.checkStatusCode +import java.io.IOException +import java.net.URI +import java.net.http.HttpClient +import java.net.http.HttpRequest +import java.net.http.HttpResponse +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.streams.asSequence + +@Singleton +public class RuneStarNameDownloader @Inject constructor( + private val client: HttpClient +) : NameDownloader { + override suspend fun download(): Sequence { + val names = readTsv(NAMES_ENDPOINT, 4) + val individualNames = readTsv(INDIVIDUAL_NAMES_ENDPOINT, 0) + return names + individualNames + } + + private suspend fun readTsv(uri: URI, column: Int): Sequence { + val request = HttpRequest.newBuilder(uri) + .GET() + .build() + + val response = client.sendAsync(request, HttpResponse.BodyHandlers.ofLines()).await() + response.checkStatusCode() + + return response.body().map { line -> + val columns = line.split('\t') + if (column >= columns.size) { + throw IOException("Column out of range") + } + columns[column] + }.asSequence() + } + + private companion object { + private val NAMES_ENDPOINT = URI("https://raw.githubusercontent.com/RuneStar/cache-names/master/names.tsv") + private val INDIVIDUAL_NAMES_ENDPOINT = + URI("https://raw.githubusercontent.com/RuneStar/cache-names/master/individual-names.tsv") + } +}