diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index fb7134a69..082914852 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -190,6 +190,7 @@ import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent import com.vitorpamplona.quartz.nip88Polls.response.PollResponseEvent import com.vitorpamplona.quartz.nip89AppHandlers.definition.AppDefinitionEvent +import com.vitorpamplona.quartz.nipC0CodeSnippets.CodeSnippetEvent import com.vitorpamplona.quartz.nip89AppHandlers.recommendation.AppRecommendationEvent import com.vitorpamplona.quartz.nip90Dvms.NIP90ContentDiscoveryRequestEvent import com.vitorpamplona.quartz.nip90Dvms.NIP90ContentDiscoveryResponseEvent @@ -2065,6 +2066,12 @@ object LocalCache : ILocalCache, ICacheProvider { wasVerified: Boolean, ) = consumeRegularEvent(event, relay, wasVerified) + fun consume( + event: CodeSnippetEvent, + relay: NormalizedRelayUrl?, + wasVerified: Boolean, + ) = consumeRegularEvent(event, relay, wasVerified) + fun consume( event: PollEvent, relay: NormalizedRelayUrl?, @@ -3104,6 +3111,7 @@ object LocalCache : ILocalCache, ICacheProvider { is PinListEvent -> consume(event, relay, wasVerified) is PublicMessageEvent -> consume(event, relay, wasVerified) is PeopleListEvent -> consume(event, relay, wasVerified) + is CodeSnippetEvent -> consume(event, relay, wasVerified) is PollNoteEvent -> consume(event, relay, wasVerified) is PollEvent -> consume(event, relay, wasVerified) is PollResponseEvent -> consume(event, relay, wasVerified) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/CodeSnippetEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/CodeSnippetEvent.kt new file mode 100644 index 000000000..35a74618b --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/CodeSnippetEvent.kt @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets + +import androidx.compose.runtime.Immutable +import com.vitorpamplona.quartz.nip01Core.core.Event +import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder +import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate +import com.vitorpamplona.quartz.nip22Comments.RootScope +import com.vitorpamplona.quartz.nip31Alts.alt +import com.vitorpamplona.quartz.utils.TimeUtils + +/** + * NIP-C0: Code Snippet event (kind:1337). + * + * The `.content` field holds the raw code text. All metadata is stored as optional tags. + */ +@Immutable +class CodeSnippetEvent( + id: HexKey, + pubKey: HexKey, + createdAt: Long, + tags: Array>, + content: String, + sig: HexKey, +) : Event(id, pubKey, createdAt, KIND, tags, content, sig), + RootScope { + + /** Programming language, lowercase (e.g. "python"). */ + fun language() = tags.language() + + /** File extension without the leading dot (e.g. "py"). */ + fun extension() = tags.snippetExtension() + + /** Snippet filename (e.g. "hello-world.py"). */ + fun snippetName() = tags.snippetName() + + /** Brief description of the snippet's purpose. */ + fun snippetDescription() = tags.snippetDescription() + + /** Execution runtime (e.g. "node v18.15.0"). */ + fun runtime() = tags.runtime() + + /** SPDX license identifier (e.g. "MIT"). */ + fun license() = tags.license() + + /** List of required dependencies. */ + fun deps() = tags.deps() + + /** Repository URL or NIP-34 Git announcement reference. */ + fun repo() = tags.repo() + + companion object { + const val KIND = 1337 + const val ALT_DESCRIPTION = "Code snippet" + + fun build( + code: String, + language: String? = null, + extension: String? = null, + name: String? = null, + description: String? = null, + runtime: String? = null, + license: String? = null, + deps: List = emptyList(), + repo: String? = null, + createdAt: Long = TimeUtils.now(), + initializer: TagArrayBuilder.() -> Unit = {}, + ) = eventTemplate(KIND, code, createdAt) { + alt(ALT_DESCRIPTION) + language?.let { language(it) } + extension?.let { extension(it) } + name?.let { snippetName(it) } + description?.let { snippetDescription(it) } + runtime?.let { runtime(it) } + license?.let { license(it) } + if (deps.isNotEmpty()) deps(deps) + repo?.let { repo(it) } + initializer() + } + } +} diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/TagArrayBuilderExt.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/TagArrayBuilderExt.kt new file mode 100644 index 000000000..d9570bc6c --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/TagArrayBuilderExt.kt @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets + +import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.DepTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.ExtensionTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.LanguageTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.LicenseTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.RepoTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.RuntimeTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.SnippetDescriptionTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.SnippetNameTag + +fun TagArrayBuilder.language(language: String) = addUnique(LanguageTag.assemble(language)) + +fun TagArrayBuilder.extension(extension: String) = addUnique(ExtensionTag.assemble(extension)) + +fun TagArrayBuilder.snippetName(name: String) = addUnique(SnippetNameTag.assemble(name)) + +fun TagArrayBuilder.snippetDescription(description: String) = addUnique(SnippetDescriptionTag.assemble(description)) + +fun TagArrayBuilder.runtime(runtime: String) = addUnique(RuntimeTag.assemble(runtime)) + +fun TagArrayBuilder.license(license: String) = addUnique(LicenseTag.assemble(license)) + +fun TagArrayBuilder.deps(deps: List) = addAll(DepTag.assemble(deps)) + +fun TagArrayBuilder.repo(repo: String) = addUnique(RepoTag.assemble(repo)) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/TagArrayExt.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/TagArrayExt.kt new file mode 100644 index 000000000..b2222bd9e --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/TagArrayExt.kt @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets + +import com.vitorpamplona.quartz.nip01Core.core.TagArray +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.DepTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.ExtensionTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.LanguageTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.LicenseTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.RepoTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.RuntimeTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.SnippetDescriptionTag +import com.vitorpamplona.quartz.nipC0CodeSnippets.tags.SnippetNameTag + +fun TagArray.language() = firstNotNullOfOrNull(LanguageTag::parse) + +fun TagArray.snippetExtension() = firstNotNullOfOrNull(ExtensionTag::parse) + +fun TagArray.snippetName() = firstNotNullOfOrNull(SnippetNameTag::parse) + +fun TagArray.snippetDescription() = firstNotNullOfOrNull(SnippetDescriptionTag::parse) + +fun TagArray.runtime() = firstNotNullOfOrNull(RuntimeTag::parse) + +fun TagArray.license() = firstNotNullOfOrNull(LicenseTag::parse) + +fun TagArray.deps() = mapNotNull(DepTag::parse) + +fun TagArray.repo() = firstNotNullOfOrNull(RepoTag::parse) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/DepTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/DepTag.kt new file mode 100644 index 000000000..7577ee3b2 --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/DepTag.kt @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets.tags + +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + +/** NIP-C0: `dep` tag — a dependency required to run the snippet (repeatable) */ +class DepTag { + companion object { + const val TAG_NAME = "dep" + + fun parse(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } + + fun assemble(dep: String) = arrayOf(TAG_NAME, dep) + + fun assemble(deps: List) = deps.map { assemble(it) } + } +} diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/ExtensionTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/ExtensionTag.kt new file mode 100644 index 000000000..51cb77ba4 --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/ExtensionTag.kt @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets.tags + +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + +/** NIP-C0: `extension` tag — file extension without the leading dot (e.g. "py", "js") */ +class ExtensionTag { + companion object { + const val TAG_NAME = "extension" + + fun parse(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } + + fun assemble(extension: String) = arrayOf(TAG_NAME, extension) + } +} diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/LanguageTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/LanguageTag.kt new file mode 100644 index 000000000..6390fd909 --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/LanguageTag.kt @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets.tags + +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + +/** NIP-C0: `l` tag — programming language name (lowercase, e.g. "python", "javascript") */ +class LanguageTag { + companion object { + const val TAG_NAME = "l" + + fun parse(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } + + fun assemble(language: String) = arrayOf(TAG_NAME, language) + } +} diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/LicenseTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/LicenseTag.kt new file mode 100644 index 000000000..db8e657ac --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/LicenseTag.kt @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets.tags + +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + +/** NIP-C0: `license` tag — SPDX license identifier (e.g. "MIT", "Apache-2.0") */ +class LicenseTag { + companion object { + const val TAG_NAME = "license" + + fun parse(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } + + fun assemble(license: String) = arrayOf(TAG_NAME, license) + } +} diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/RepoTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/RepoTag.kt new file mode 100644 index 000000000..296019ba6 --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/RepoTag.kt @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets.tags + +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + +/** + * NIP-C0: `repo` tag — repository reference as a URL or NIP-34 Git announcement + * (e.g. "https://github.com/user/repo" or a NIP-34 naddr) + */ +class RepoTag { + companion object { + const val TAG_NAME = "repo" + + fun parse(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } + + fun assemble(repo: String) = arrayOf(TAG_NAME, repo) + } +} diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/RuntimeTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/RuntimeTag.kt new file mode 100644 index 000000000..37b18041d --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/RuntimeTag.kt @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets.tags + +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + +/** NIP-C0: `runtime` tag — execution environment specification (e.g. "node v18.15.0") */ +class RuntimeTag { + companion object { + const val TAG_NAME = "runtime" + + fun parse(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } + + fun assemble(runtime: String) = arrayOf(TAG_NAME, runtime) + } +} diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/SnippetDescriptionTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/SnippetDescriptionTag.kt new file mode 100644 index 000000000..bf052fb8e --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/SnippetDescriptionTag.kt @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets.tags + +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + +/** NIP-C0: `description` tag — brief explanation of the snippet's purpose */ +class SnippetDescriptionTag { + companion object { + const val TAG_NAME = "description" + + fun parse(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } + + fun assemble(description: String) = arrayOf(TAG_NAME, description) + } +} diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/SnippetNameTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/SnippetNameTag.kt new file mode 100644 index 000000000..8daf224fd --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipC0CodeSnippets/tags/SnippetNameTag.kt @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nipC0CodeSnippets.tags + +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + +/** NIP-C0: `name` tag — snippet filename (e.g. "hello-world.js") */ +class SnippetNameTag { + companion object { + const val TAG_NAME = "name" + + fun parse(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } + + fun assemble(name: String) = arrayOf(TAG_NAME, name) + } +} diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt index 2870e06fa..c0d3504da 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt @@ -151,6 +151,7 @@ import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceEvent import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceReplyEvent import com.vitorpamplona.quartz.nipB7Blossom.BlossomAuthorizationEvent import com.vitorpamplona.quartz.nipB7Blossom.BlossomServersEvent +import com.vitorpamplona.quartz.nipC0CodeSnippets.CodeSnippetEvent interface EventBuilder { fun build( @@ -196,6 +197,7 @@ class EventFactory { CalendarTimeSlotEvent.KIND -> CalendarTimeSlotEvent(id, pubKey, createdAt, tags, content, sig) CalendarRSVPEvent.KIND -> CalendarRSVPEvent(id, pubKey, createdAt, tags, content, sig) ChessGameEvent.KIND -> ChessGameEvent(id, pubKey, createdAt, tags, content, sig) + CodeSnippetEvent.KIND -> CodeSnippetEvent(id, pubKey, createdAt, tags, content, sig) FavoriteRelayListEvent.KIND -> FavoriteRelayListEvent(id, pubKey, createdAt, tags, content, sig) JesterEvent.KIND -> JesterEvent(id, pubKey, createdAt, tags, content, sig) LiveChessGameChallengeEvent.KIND -> LiveChessGameChallengeEvent(id, pubKey, createdAt, tags, content, sig)