diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index dac78eef..5c44737d 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -76,5 +76,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 7ccaa502..634fb7c2 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -18,6 +18,7 @@ allprojects {
maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://maven.topi.wtf/snapshots")
+ maven("https://maven.topi.wtf/releases")
}
}
diff --git a/core/src/commonMain/kotlin/dev/schlaubi/lavakord/audio/internal/AbstractLavakord.kt b/core/src/commonMain/kotlin/dev/schlaubi/lavakord/audio/internal/AbstractLavakord.kt
index e04823e1..d4437258 100644
--- a/core/src/commonMain/kotlin/dev/schlaubi/lavakord/audio/internal/AbstractLavakord.kt
+++ b/core/src/commonMain/kotlin/dev/schlaubi/lavakord/audio/internal/AbstractLavakord.kt
@@ -1,13 +1,15 @@
package dev.schlaubi.lavakord.audio.internal
-import dev.arbjerg.lavalink.protocol.v4.*
+import dev.arbjerg.lavalink.protocol.v4.Error
+import dev.arbjerg.lavalink.protocol.v4.LavalinkSerializersModule
+import dev.arbjerg.lavalink.protocol.v4.Message
+import dev.arbjerg.lavalink.protocol.v4.VoiceState
import dev.schlaubi.lavakord.LavaKord
import dev.schlaubi.lavakord.LavaKordOptions
import dev.schlaubi.lavakord.RestException
import dev.schlaubi.lavakord.audio.*
import dev.schlaubi.lavakord.internal.HttpEngine
import dev.schlaubi.lavakord.internal.RestNodeImpl
-import dev.schlaubi.lavakord.rest.updatePlayer
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.*
diff --git a/plugins/lavasearch/build.gradle.kts b/plugins/lavasearch/build.gradle.kts
new file mode 100644
index 00000000..26909ef3
--- /dev/null
+++ b/plugins/lavasearch/build.gradle.kts
@@ -0,0 +1,53 @@
+import com.vanniktech.maven.publish.JavadocJar
+import com.vanniktech.maven.publish.KotlinMultiplatform
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
+plugins {
+ `lavalink-module`
+ `lavalink-publishing`
+ kotlin("plugin.serialization")
+ alias(libs.plugins.ksp)
+}
+
+kotlin {
+ jvm {
+ compilations.all {
+ compilerOptions.configure {
+ jvmTarget = JvmTarget.JVM_11
+ }
+ }
+ }
+ sourceSets {
+ all {
+ languageSettings.optIn("kotlin.contracts.ExperimentalContracts")
+ languageSettings.optIn("dev.schlaubi.lavakord.PluginApi")
+ languageSettings.optIn("dev.schlaubi.lavakord.UnsafeRestApi")
+ }
+ commonMain {
+ kotlin.srcDir(layout.buildDirectory.dir("generated/ksp/metadata/commonMain/kotlin"))
+ dependencies {
+ api(projects.core)
+ api(libs.lavasearch.protocol)
+
+ implementation(libs.ktor.client.resources)
+ implementation(libs.kord.ksp.annotations)
+ }
+ }
+ }
+}
+
+dependencies {
+ kspCommonMainMetadata(libs.kord.ksp.processors)
+}
+
+tasks {
+ listOf("sourcesJar", "jsSourcesJar", "jvmSourcesJar", "compileKotlinJs", "compileKotlinJvm", "dokkaHtml").forEach {
+ named(it) {
+ dependsOn("kspCommonMainKotlinMetadata")
+ }
+ }
+}
+
+mavenPublishing {
+ configure(KotlinMultiplatform(JavadocJar.Dokka("dokkaHtml")))
+}
diff --git a/plugins/lavasearch/build/generated/ksp/metadata/commonMain/kotlin/dev/schlaubi/lavakord/plugins/lavasearch/model/SearchType.kt b/plugins/lavasearch/build/generated/ksp/metadata/commonMain/kotlin/dev/schlaubi/lavakord/plugins/lavasearch/model/SearchType.kt
new file mode 100644
index 00000000..388c067d
--- /dev/null
+++ b/plugins/lavasearch/build/generated/ksp/metadata/commonMain/kotlin/dev/schlaubi/lavakord/plugins/lavasearch/model/SearchType.kt
@@ -0,0 +1,97 @@
+// THIS FILE IS AUTO-GENERATED BY KordEnumProcessor.kt, DO NOT EDIT!
+@file:Suppress(names = arrayOf("RedundantVisibilityModifier", "IncorrectFormatting",
+ "ReplaceArrayOfWithLiteral", "SpellCheckingInspection", "GrazieInspection"))
+
+package dev.schlaubi.lavakord.plugins.lavasearch.model
+
+import kotlin.Any
+import kotlin.Boolean
+import kotlin.Int
+import kotlin.LazyThreadSafetyMode.PUBLICATION
+import kotlin.String
+import kotlin.Suppress
+import kotlin.collections.List
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+
+/**
+ * See [SearchType]s in the
+ * [Discord Developer Documentation](https://github.com/topi314/LavaSearch?tab=readme-ov-file#api).
+ */
+@Serializable(with = SearchType.Serializer::class)
+public sealed class SearchType(
+ /**
+ * The raw value used by Discord.
+ */
+ public val `value`: String,
+) {
+ public final override fun equals(other: Any?): Boolean = this === other ||
+ (other is SearchType && this.value == other.value)
+
+ public final override fun hashCode(): Int = value.hashCode()
+
+ public final override fun toString(): String =
+ "SearchType.${this::class.simpleName}(value=$value)"
+
+ /**
+ * An unknown [SearchType].
+ *
+ * This is used as a fallback for [SearchType]s that haven't been added to Kord yet.
+ */
+ public class Unknown(
+ `value`: String,
+ ) : SearchType(value)
+
+ public object Track : SearchType("track")
+
+ public object Album : SearchType("album")
+
+ public object Artist : SearchType("artist")
+
+ public object Playlist : SearchType("playlist")
+
+ /**
+ * Search suggestions
+ */
+ public object Text : SearchType("text")
+
+ internal object Serializer : KSerializer {
+ public override val descriptor: SerialDescriptor =
+ PrimitiveSerialDescriptor("dev.schlaubi.lavakord.plugins.lavasearch.model.SearchType",
+ PrimitiveKind.STRING)
+
+ public override fun serialize(encoder: Encoder, `value`: SearchType) =
+ encoder.encodeString(value.value)
+
+ public override fun deserialize(decoder: Decoder) =
+ when (val value = decoder.decodeString()) {
+ "track" -> Track
+ "album" -> Album
+ "artist" -> Artist
+ "playlist" -> Playlist
+ "text" -> Text
+ else -> Unknown(value)
+ }
+ }
+
+ public companion object {
+ /**
+ * A [List] of all known [SearchType]s.
+ */
+ public val entries: List by lazy(mode = PUBLICATION) {
+ listOf(
+ Track,
+ Album,
+ Artist,
+ Playlist,
+ Text,
+ )
+ }
+
+ }
+}
diff --git a/plugins/lavasearch/src/commonMain/kotlin/Plugin.kt b/plugins/lavasearch/src/commonMain/kotlin/Plugin.kt
new file mode 100644
index 00000000..e3cda732
--- /dev/null
+++ b/plugins/lavasearch/src/commonMain/kotlin/Plugin.kt
@@ -0,0 +1,17 @@
+package dev.schlaubi.lavakord.plugins.lavasearch
+
+import dev.schlaubi.lavakord.Plugin
+
+/**
+ * Bindings for the [LavaSrc plugin](https://github.com/topi314/LavaSearch).
+ *
+ * ```kotlin
+ * plugins {
+ * install(LavaSearch)
+ * }
+ * ```
+ */
+public object LavaSearch : Plugin {
+ override val name: String = "lavasearch-plugin"
+ override val version: String = "4.0.0-beta.3"
+}
diff --git a/plugins/lavasearch/src/commonMain/kotlin/model/SearchType.kt b/plugins/lavasearch/src/commonMain/kotlin/model/SearchType.kt
new file mode 100644
index 00000000..b034210d
--- /dev/null
+++ b/plugins/lavasearch/src/commonMain/kotlin/model/SearchType.kt
@@ -0,0 +1,36 @@
+@file:GenerateKordEnum(
+ "SearchType",
+ GenerateKordEnum.ValueType.STRING,
+ docUrl = "https://github.com/topi314/LavaSearch?tab=readme-ov-file#api",
+ entries = [
+ GenerateKordEnum.Entry(
+ "Track",
+ stringValue = "track",
+ kDoc = "Tracks."
+ ),
+ GenerateKordEnum.Entry(
+ "Album",
+ stringValue = "album",
+ kDoc = "Album."
+ ),
+ GenerateKordEnum.Entry(
+ "Artist",
+ stringValue = "artist",
+ kDoc = "Artists."
+ ),
+ GenerateKordEnum.Entry(
+ "Playlist",
+ stringValue = "playlist",
+ kDoc = "Playlists."
+ ),
+ GenerateKordEnum.Entry(
+ "Text",
+ stringValue = "text",
+ kDoc = "Search suggestions."
+ )
+ ]
+)
+
+package dev.schlaubi.lavakord.plugins.lavasearch.model
+
+import dev.kord.ksp.GenerateKordEnum
diff --git a/plugins/lavasearch/src/commonMain/kotlin/rest/Rest.kt b/plugins/lavasearch/src/commonMain/kotlin/rest/Rest.kt
new file mode 100644
index 00000000..2aad1b55
--- /dev/null
+++ b/plugins/lavasearch/src/commonMain/kotlin/rest/Rest.kt
@@ -0,0 +1,41 @@
+package dev.schlaubi.lavakord.plugins.lavasearch.rest
+
+import com.github.topi314.lavasearch.protocol.SearchResult
+import dev.schlaubi.lavakord.audio.Link
+import dev.schlaubi.lavakord.audio.Node
+import dev.schlaubi.lavakord.plugins.lavasearch.model.SearchType
+import dev.schlaubi.lavakord.rest.get
+
+/**
+ * Searches for [query].
+ *
+ * @param types the allowed [SearchTypes][SearchType]
+ * @see SearchResult
+ */
+public suspend fun Node.search(query: String, vararg types: SearchType): SearchResult =
+ search(query, types.asIterable())
+
+/**
+ * Searches for [query].
+ *
+ * @param types the allowed [SearchTypes][SearchType]
+ * @see SearchResult
+ */
+public suspend fun Node.search(query: String, types: Iterable): SearchResult =
+ get(LavaSearchRoute(query, types.toList()))
+
+/**
+ * Searches for [query].
+ *
+ * @param types the allowed [SearchTypes][SearchType]
+ * @see SearchResult
+ */
+public suspend fun Link.search(query: String, vararg types: SearchType): SearchResult = node.search(query, *types)
+
+/**
+ * Searches for [query].
+ *
+ * @param types the allowed [SearchTypes][SearchType]
+ * @see SearchResult
+ */
+public suspend fun Link.search(query: String, types: Iterable): SearchResult = node.search(query, types)
diff --git a/plugins/lavasearch/src/commonMain/kotlin/rest/Route.kt b/plugins/lavasearch/src/commonMain/kotlin/rest/Route.kt
new file mode 100644
index 00000000..ba9541ba
--- /dev/null
+++ b/plugins/lavasearch/src/commonMain/kotlin/rest/Route.kt
@@ -0,0 +1,8 @@
+package dev.schlaubi.lavakord.plugins.lavasearch.rest
+
+import dev.schlaubi.lavakord.plugins.lavasearch.model.SearchType
+import dev.schlaubi.lavakord.rest.routes.V4Api
+import io.ktor.resources.*
+
+@Resource("loadsearch")
+internal data class LavaSearchRoute(val query: String, val types: List, val player: V4Api = V4Api())
diff --git a/settings.gradle.kts b/settings.gradle.kts
index b9ad81ab..7470eb6e 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -9,6 +9,7 @@ include(
":plugins:kspProcessor",
":plugins:sponsorblock",
":plugins:lavasrc",
+ ":plugins:lavasearch",
"java",
"jda",
"jda-java"
@@ -54,6 +55,7 @@ dependencyResolutionManagement {
library("kotlinx-nodejs", "org.jetbrains.kotlin-wrappers", "kotlin-node").version("18.16.12-pre.594")
library("lavalink-protocol", "dev.arbjerg.lavalink", "protocol").version("4.0.0-beta.5")
+ library("lavasearch-protocol", "com.github.topi314.lavasearch", "lavasearch-protocol").version("1.0.0-beta.3")
library("kotlinpoet", "com.squareup", "kotlinpoet-ksp")
.version("1.14.2")