Skip to content
This repository has been archived by the owner on Dec 4, 2022. It is now read-only.

Commit

Permalink
KTS Scripting implemented (#17)
Browse files Browse the repository at this point in the history
* ByteArray return implemented.

To lower overhead and provide greater abstraction on what can be returned from an extension

- IExtension.kt; getPassage return changed to ByteArray
- LuaExtension.kt; use checkstring to get the byte array of that string (which can be easily decoded to a string). Lua strings are just bytearrays. So this works fine.
- Test.kt; Implemented bytearray decoding

* KTS Scripting implemented

This implements KTS extension support. Included are additional libraries, some minor changes to the way libs are handled

- build.gradle.kts; Updated kotlin, Updated dokka, Implemented scripting support
- ExtensionType.kt; Defines the type of extension
- javax.script.ScriptEngineFactory; Definition to use the kts script engine
- KtsExtension.kt; Delegated class that redirects to the parsed kts script
- names.kt; Added json type parameter for extension type
- RepoData.kt; RepoExtension now has a type parameter
- ShosetsuKtsLib.kt; translation of ShosetsuLuaLib.kt for KTS
- ShosetsuSharedLib.kt; httpClient is now located here to be shared
- ShosetsuLuaLib.kt; now uses ShosetsuSharedLib.kt, old httpClient is deprecated
- Test.kt; Modified to use path values instead and patched for KTS support using ExtensionType.kt
  • Loading branch information
Doomsdayrs authored May 21, 2021
1 parent f2f66eb commit 87dc4a7
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 45 deletions.
29 changes: 18 additions & 11 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@ version = "1.0.0"
description = "Kotlin library for shosetsu"

plugins {
kotlin("jvm") version "1.4.20"
id("org.jetbrains.dokka") version "0.10.0"
kotlin("plugin.serialization") version "1.4.20"
kotlin("jvm") version "1.5.0"
id("org.jetbrains.dokka") version "1.4.32"
kotlin("plugin.serialization") version "1.5.0"
maven
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { kotlinOptions.jvmTarget = "1.8" }
tasks.withType<KotlinCompile> { kotlinOptions.jvmTarget = "1.8" }


tasks.dokka {
outputFormat = "html"
outputDirectory = "$buildDir/javadoc"
}

val dokkaJar by tasks.creating(Jar::class) {
group = JavaBasePlugin.DOCUMENTATION_GROUP
Expand All @@ -32,19 +29,29 @@ repositories {
dependencies {
implementation(kotlin("stdlib"))
implementation("org.jsoup:jsoup:1.12.1")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.20")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.0")
dokkaHtmlPlugin("org.jetbrains.dokka:kotlin-as-java-plugin:1.4.32")

// java only
implementation("org.luaj:luaj-jse:3.0.1")
implementation("com.squareup.okhttp3:okhttp:4.2.1")
implementation("com.google.guava:guava:30.0-jre")
implementation("net.java.dev.jna:jna:4.2.2")

// Cross platform confirmed
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
testImplementation("org.jetbrains.kotlin:kotlin-test:1.4.20")
testImplementation("org.jetbrains.kotlin:kotlin-test:1.5.0")

implementation(kotlin("reflect"))
implementation(kotlin("script-runtime"))
implementation(kotlin("script-util"))
implementation(kotlin("compiler-embeddable"))
implementation(kotlin("scripting-compiler-embeddable"))
implementation(kotlin("script-util"))

}

val compileTestKotlin: KotlinCompile by tasks
compileTestKotlin.kotlinOptions {
languageVersion = "1.4"
languageVersion = "1.5"
}
12 changes: 12 additions & 0 deletions src/main/kotlin/app/shosetsu/lib/ExtensionType.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package app.shosetsu.lib

/**
* Type of extension
*/
enum class ExtensionType {
/** .lua */
LuaScript,

/** .kts */
KotlinScript
}
12 changes: 12 additions & 0 deletions src/main/kotlin/app/shosetsu/lib/ShosetsuSharedLib.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package app.shosetsu.lib

import okhttp3.OkHttpClient

/**
* shosetsu-kotlin-lib
* 06 / 10 / 2020
*/
object ShosetsuSharedLib {
/** okhttp HTTP Client used by lib functions. */
lateinit var httpClient: OkHttpClient
}
5 changes: 4 additions & 1 deletion src/main/kotlin/app/shosetsu/lib/json/RepoData.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package app.shosetsu.lib.json

import app.shosetsu.lib.ExtensionType
import app.shosetsu.lib.Version
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand Down Expand Up @@ -36,7 +37,9 @@ data class RepoExtension internal constructor(
@SerialName(J_LIB_VERSION)
val libVersion: Version,
@SerialName(J_MD5)
val md5: String
val md5: String,
@SerialName(J_EXTENSION_TYPE)
val type: ExtensionType
)


Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/app/shosetsu/lib/json/names.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const val J_VERSION = "ver"
const val J_LIB_VERSION = "libVer"
const val J_FILE_NAME = "fileName"
const val J_IMAGE_URL = "imageURL"
const val J_EXTENSION_TYPE = "type"


// LuaExtension
Expand Down
17 changes: 17 additions & 0 deletions src/main/kotlin/app/shosetsu/lib/kts/KtsExtension.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package app.shosetsu.lib.kts

import app.shosetsu.lib.IExtension
import java.io.File
import kotlin.time.ExperimentalTime

/**
* shosetsu-services
* 06 / 10 / 2020
*/
@ExperimentalTime
class KtsExtension(
private val content: String,
private val _kts: IExtension = KtsObjectLoader().load(content)
) : IExtension by _kts {
constructor(file: File) : this(file.readText())
}
22 changes: 22 additions & 0 deletions src/main/kotlin/app/shosetsu/lib/kts/KtsObjectLoader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package app.shosetsu.lib.kts

import javax.script.ScriptEngine
import javax.script.ScriptEngineManager

/**
* This class is not thread-safe, don't use it for parallel executions and create new instances instead.
*/
class KtsObjectLoader(classLoader: ClassLoader? = Thread.currentThread().contextClassLoader) {

val engine: ScriptEngine = ScriptEngineManager(classLoader).getEngineByExtension("kts")

@Throws(IllegalArgumentException::class)
inline fun <reified T> Any?.castOrError(): T = takeIf { it is T }?.let { it as T }
?: throw IllegalArgumentException("Cannot cast $this to expected type ${T::class}")

@Throws(RuntimeException::class)
inline fun <reified T> load(script: String): T =
kotlin.runCatching { engine.eval(script) }
.getOrElse @Throws(RuntimeException::class) { throw RuntimeException("Cannot load script", it) }
.castOrError()
}
49 changes: 49 additions & 0 deletions src/main/kotlin/app/shosetsu/lib/kts/ShosetsuKtsLib.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package app.shosetsu.lib.kts

import app.shosetsu.lib.ShosetsuSharedLib.httpClient
import app.shosetsu.lib.exceptions.HTTPException
import app.shosetsu.lib.lua.ShosetsuLuaLib.LibFunctions.RequestDocument
import okhttp3.*
import okhttp3.internal.closeQuietly
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.util.concurrent.TimeUnit

/**
* shosetsu-kotlin-lib
* 06 / 10 / 2020
*/
object ShosetsuKtsLib {
val defaultCacheControl: CacheControl
get() = CacheControl.Builder().maxAge(10, TimeUnit.MINUTES).build()

val defaultHeaders: Headers
get() = Headers.Builder().build()

val defaultBody: RequestBody
get() = FormBody.Builder().build()


// For normal extensions, these simple functions are sufficient.
fun get(url: String, headers: Headers, cacheControl: CacheControl): Request =
Request.Builder().url(url).headers(headers).cacheControl(cacheControl).build()

fun post(url: String, headers: Headers, body: RequestBody, cacheControl: CacheControl): Request =
Request.Builder().url(url).post(body).headers(headers).cacheControl(cacheControl).build()


fun parseDocument(content: String): Document = Jsoup.parse(content)!!

fun requestResponse(request: Request): Response = httpClient.newCall(request).execute()

fun requestDocument(request: Request): Document = Document(
requestResponse(request).let { r ->
r.takeIf { it.code == 200 }?.body?.string() ?: run {
r.closeQuietly()
throw HTTPException(r.code)
}
}
)

fun getDocument(url: String): Document = RequestDocument(get(url, defaultHeaders, defaultCacheControl))
}
15 changes: 11 additions & 4 deletions src/main/kotlin/app/shosetsu/lib/lua/ShosetsuLuaLib.kt
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class ShosetsuLuaLib : TwoArgFunction() {
}

fun Document(str: String): Document = Jsoup.parse(str)!!
fun Request(req: Request): Response = httpClient.newCall(req).execute()
fun Request(req: Request): Response = ShosetsuSharedLib.httpClient.newCall(req).execute()

@Throws(HTTPException::class)
fun RequestDocument(req: Request): Document = Document(
Expand All @@ -222,7 +222,7 @@ class ShosetsuLuaLib : TwoArgFunction() {
)

// For advanced users who want to (or need to) do everything themselves.
fun HttpClient(): OkHttpClient = httpClient
fun HttpClient(): OkHttpClient = ShosetsuSharedLib.httpClient

fun RequestBuilder(): Request.Builder = Request.Builder()
fun HeadersBuilder(): Headers.Builder = Headers.Builder()
Expand Down Expand Up @@ -268,8 +268,15 @@ class ShosetsuLuaLib : TwoArgFunction() {
lateinit var libLoader: (name: String) -> LuaValue?

/** okhttp client used by [LibFunctions] */
lateinit var httpClient: OkHttpClient

@Deprecated(
"Use ShosetsuSharedLib",
ReplaceWith("ShosetsuSharedLib.httpClient", "app.shosetsu.lib.ShosetsuSharedLib")
)
var httpClient: OkHttpClient
get() = ShosetsuSharedLib.httpClient
set(value) {
ShosetsuSharedLib.httpClient = value
}
private val permaLuaFuncs by lazy {
mapOf(
"GET" to loadResource("GET.lua"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory
50 changes: 21 additions & 29 deletions src/test/kotlin/app/shosetsu/lib/Test.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package app.shosetsu.lib

import app.shosetsu.lib.ExtensionType.KotlinScript
import app.shosetsu.lib.ExtensionType.LuaScript
import app.shosetsu.lib.ShosetsuSharedLib.httpClient
import app.shosetsu.lib.json.RepoIndex
import app.shosetsu.lib.kts.KtsExtension
import app.shosetsu.lib.lua.LuaExtension
import app.shosetsu.lib.lua.ShosetsuLuaLib
import app.shosetsu.lib.lua.shosetsuGlobals
Expand All @@ -12,6 +16,7 @@ import java.io.File
import java.util.concurrent.TimeUnit.MILLISECONDS
import kotlin.system.exitProcess
import kotlin.time.Duration
import kotlin.time.DurationUnit
import kotlin.time.ExperimentalTime
import kotlin.time.measureTimedValue

Expand All @@ -33,10 +38,7 @@ import kotlin.time.measureTimedValue
* shosetsu-services
* 03 / June / 2019
*
* @author github.com/doomsdayrs;github.com/TechnoJo4
*
* In IDEA, The Classpath should be shosetsu-services but
* the Working directory should be shosetsu-extensions.
* @author github.com/doomsdayrs; github.com/TechnoJo4
*/
@ExperimentalTime
object Test {
Expand All @@ -59,27 +61,13 @@ object Test {
private const val SPECIFIC_NOVEL_URL = "/"
private const val SPECIFIC_CHAPTER = 0

private val SOURCES: List<String> = arrayOf<String>(
"en/BestLightNovel",
//"en/BoxNovel",
//"en/CreativeNovels",
//"en/FastNovel",
//"en/Foxaholic", // TODO: Investigate
//"en/KissLightNovels",
//"en/MNovelFree", //Doesn't seem to be a novelfull
//"en/MTLNovel",
//"en/NovelFull",
//"en/NovelTrench",
//"en/ReadLightNovel",
//"en/ReadNovelFull",
//"en/VipNovel",
//"en/VolareNovels",
//"en/WuxiaWorld",
//"jp/Syosetsu",
//"pt/SaikaiScan",
//"zn/15doc",
//"zn/Tangsanshu"
).map { "src/main/resources/src/$it.lua" }
/** Replace with the directory of the extensions you want to use*/
private const val DIRECTORY = ""

private val SOURCES: Array<Pair<String, ExtensionType>> =
// Should be an array of the path of the script to the type of that script
arrayOf<Pair<String, ExtensionType>>()

// END CONFIG

private val globals = shosetsuGlobals()
Expand All @@ -95,12 +83,12 @@ object Test {
ShosetsuLuaLib.libLoader = {
outputTimedValue("loadScript") {
loadScript(
File("src/main/resources/lib/$it.lua"),
File("$DIRECTORY/src/main/resources/lib/$it.lua"),
"lib"
)
}
}
ShosetsuLuaLib.httpClient = OkHttpClient.Builder().addInterceptor {
httpClient = OkHttpClient.Builder().addInterceptor {
outputTimedValue("Time till response") {
it.proceed(it.request().also { request ->
println(request.url.toUrl().toString())
Expand Down Expand Up @@ -246,7 +234,7 @@ object Test {

@ExperimentalTime
private fun printExecutionTime(job: String, time: Duration) {
printExecutionTime(job, time.inMilliseconds)
printExecutionTime(job, time.toDouble(DurationUnit.MILLISECONDS))
}

private fun printExecutionTime(job: String, timeMs: Double) {
Expand Down Expand Up @@ -275,7 +263,11 @@ object Test {


val extension = outputTimedValue("LuaExtension") {
LuaExtension(File(extensionPath))
val file = File(extensionPath.first)
when (extensionPath.second) {
LuaScript -> LuaExtension(file)
KotlinScript -> KtsExtension(file)
}
}

if (SPECIFIC_NOVEL) {
Expand Down

0 comments on commit 87dc4a7

Please sign in to comment.