Skip to content

Commit

Permalink
Extract arg lists from Bot API
Browse files Browse the repository at this point in the history
  • Loading branch information
alllex committed Jul 14, 2024
1 parent 775d336 commit 1213044
Show file tree
Hide file tree
Showing 13 changed files with 17,798 additions and 403 deletions.
3,312 changes: 3,312 additions & 0 deletions api-spec/telegram-bot-api.args.json

Large diffs are not rendered by default.

14,008 changes: 14,008 additions & 0 deletions api-spec/telegram-bot-api.json

Large diffs are not rendered by default.

32 changes: 30 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,44 @@ tasks.test {
useJUnitPlatform()
}

val generateTelegramBotApi by tasks.registering(GenerateTelegramBotApiTask::class) {
val updateApiSpec by tasks.registering {
group = "telegram"
val specFile = layout.projectDirectory.file("api-spec/telegram-bot-api.html")
outputs.file(specFile)
outputs.upToDateWhen { false }
doLast {
val url = "https://core.telegram.org/bots/api"
val rawText = uri(url).toURL().readText()
val genTimeRe = "^<!-- page generated in .* -->$".toRegex()
val text = rawText.lineSequence()
.filterNot { genTimeRe.matches(it) }
.joinToString("\n")
specFile.asFile.writeText(text)
}
}

val extractBotApi by tasks.registering(BotApiExtract::class) {
group = "telegram"
apiSpecFile = layout.projectDirectory.file("api-spec/telegram-bot-api.html")
outputFile = layout.projectDirectory.file("api-spec/telegram-bot-api.json")
}

val extractBotApiArgLists by tasks.registering(BotApiArgListExtract::class) {
group = "telegram"
apiJsonFile = extractBotApi.flatMap { it.outputFile }
outputFile = layout.projectDirectory.file("api-spec/telegram-bot-api.args.json")
}

val generateBotApi by tasks.registering(BotApiGenerate::class) {
group = "telegram"
apiJsonFile = extractBotApi.flatMap { it.outputFile }
packageName = "me.alllex.tbot.api.model"
telegramClientPackage = "me.alllex.tbot.api.client"
outputDirectory = layout.projectDirectory.dir("src/main/generated-kotlin")
}

kotlin.sourceSets.main {
kotlin.srcDir(generateTelegramBotApi)
kotlin.srcDir(generateBotApi)
}

kotlin.compilerOptions {
Expand Down
17 changes: 2 additions & 15 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
plugins {
`kotlin-dsl`
alias(libs.plugins.kotlin.serialization)
}

repositories {
Expand All @@ -9,20 +10,6 @@ repositories {
dependencies {
implementation("org.jsoup:jsoup:1.17.1")
implementation("me.alllex.parsus:parsus-jvm:0.6.1")
implementation(libs.kotlinx.serialization.json)
}

val updateApiSpec by tasks.registering {
group = "telegram"
val specFile = layout.projectDirectory.file("../api-spec/telegram-bot-api.html")
outputs.file(specFile)
outputs.upToDateWhen { false }
doLast {
val url = "https://core.telegram.org/bots/api"
val rawText = uri(url).toURL().readText()
val genTimeRe = "^<!-- page generated in .* -->$".toRegex()
val text = rawText.lineSequence()
.filterNot { genTimeRe.matches(it) }
.joinToString("\n")
specFile.asFile.writeText(text)
}
}
8 changes: 8 additions & 0 deletions buildSrc/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
rootProject.name = "buildSrc"

dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
35 changes: 35 additions & 0 deletions buildSrc/src/main/kotlin/BotApiArgListExtract.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import kotlinx.serialization.encodeToString
import me.alllex.tbot.apigen.BotApi
import me.alllex.tbot.apigen.BotApiArgLists
import me.alllex.tbot.apigen.BotApiElementArgs
import me.alllex.tbot.apigen.jsonSerialization
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.*

@CacheableTask
abstract class BotApiArgListExtract : DefaultTask() {

@get:[InputFile PathSensitive(PathSensitivity.RELATIVE)]
abstract val apiJsonFile: RegularFileProperty

@get:OutputFile
abstract val outputFile: RegularFileProperty

@TaskAction
fun execute() {
val apiJsonText = apiJsonFile.get().asFile.readText(Charsets.UTF_8)
val botApi = jsonSerialization.decodeFromString<BotApi>(apiJsonText)

val argLists = BotApiArgLists(
types = botApi.types.map {
BotApiElementArgs(name = it.name.value, args = it.fields?.map { it.name }.orEmpty())
},
methods = botApi.methods.map {
BotApiElementArgs(name = it.name.value, args = it.parameters.map { it.name })
}
)

outputFile.get().asFile.writeText(jsonSerialization.encodeToString(argLists))
}
}
26 changes: 26 additions & 0 deletions buildSrc/src/main/kotlin/BotApiExtract.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import kotlinx.serialization.encodeToString
import me.alllex.tbot.apigen.BotApiDefinitionParser
import me.alllex.tbot.apigen.jsonSerialization
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.*

@CacheableTask
abstract class BotApiExtract : DefaultTask() {

@get:[InputFile PathSensitive(PathSensitivity.RELATIVE)]
abstract val apiSpecFile: RegularFileProperty

@get:OutputFile
abstract val outputFile: RegularFileProperty

@TaskAction
fun execute() {
val html = apiSpecFile.get().asFile.readText()
val parser = BotApiDefinitionParser()
val botApi = parser.run(html)

val outputJson = jsonSerialization.encodeToString(botApi)
outputFile.get().asFile.writeText(outputJson)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,13 @@ import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.*

@CacheableTask
abstract class GenerateTelegramBotApiTask : DefaultTask() {
abstract class BotApiGenerate : DefaultTask() {

@get:[InputFile PathSensitive(PathSensitivity.RELATIVE)]
abstract val apiSpecFile: RegularFileProperty
abstract val apiJsonFile: RegularFileProperty

@get:Input
abstract val packageName: Property<String>
Expand All @@ -28,11 +22,11 @@ abstract class GenerateTelegramBotApiTask : DefaultTask() {

@TaskAction
fun generate() {
BotApiGenerator.generateFromSpec(
apiSpecFile.get().asFile.readText(),
BotApiGenerator().run(
apiJsonFile.get().asFile,
outputDirectory.get().asFile,
packageName.get(),
telegramClientPackage.get()
telegramClientPackage.get(),
)
}

Expand Down
16 changes: 16 additions & 0 deletions buildSrc/src/main/kotlin/me/alllex/tbot/apigen/BotApiArgLists.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package me.alllex.tbot.apigen

import kotlinx.serialization.Serializable


@Serializable
data class BotApiElementArgs(
val name: String,
val args: List<String>,
)

@Serializable
data class BotApiArgLists(
val types: List<BotApiElementArgs>,
val methods: List<BotApiElementArgs>,
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package me.alllex.tbot.apigen

import kotlinx.serialization.Serializable
import me.alllex.parsus.parser.Grammar
import me.alllex.parsus.parser.ParseException
import me.alllex.parsus.parser.getOrElse
Expand Down Expand Up @@ -53,6 +54,7 @@ data class ApiMethodDefinition(
val parametersTableElement: Element? = null,
)

@Serializable
@JvmInline
value class BotApiElementName(val value: String) {
init {
Expand All @@ -66,18 +68,21 @@ value class BotApiElementName(val value: String) {
}
}

@Serializable
@JvmInline
value class KotlinType(val value: String) {
override fun toString(): String = value
}

@Serializable
data class BotApiElement(
val name: BotApiElementName,
val description: String,
val fields: List<Field>? = null,
val unionTypes: List<BotApiElementName>? = null,
val originalName: BotApiElementName = name,
) {
@Serializable
data class Field(
val serialName: String,
val description: String,
Expand All @@ -89,13 +94,15 @@ data class BotApiElement(
}
}

@Serializable
data class BotApiMethod(
val name: BotApiElementName,
val description: String,
val parameters: List<BotApiElement.Field>,
val returnType: KotlinType
)

@Serializable
data class BotApi(
val types: List<BotApiElement>,
val methods: List<BotApiMethod>,
Expand Down
Loading

0 comments on commit 1213044

Please sign in to comment.