- Migrates Video events to imeta tags
- Removes youtu.be links from the video feed. - Checks for video file types in uppercase as well as lowercase
This commit is contained in:
@@ -22,8 +22,10 @@ package com.vitorpamplona.quartz.events
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.encoders.Nip92MediaAttachments.Companion.IMETA
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import com.vitorpamplona.quartz.utils.filter
|
||||
|
||||
@Immutable
|
||||
abstract class VideoEvent(
|
||||
@@ -36,52 +38,73 @@ abstract class VideoEvent(
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig),
|
||||
RootScope {
|
||||
fun url() = tags.firstOrNull { it.size > 1 && it[0] == URL }?.get(1)
|
||||
private fun url() = tags.firstOrNull { it.size > 1 && it[0] == URL }?.get(1)
|
||||
|
||||
fun urls() = tags.filter { it.size > 1 && it[0] == URL }.map { it[1] }
|
||||
private fun urls() = tags.filter { it.size > 1 && it[0] == URL }.map { it[1] }
|
||||
|
||||
fun mimeType() = tags.firstOrNull { it.size > 1 && it[0] == MIME_TYPE }?.get(1)
|
||||
private fun mimeType() = tags.firstOrNull { it.size > 1 && it[0] == MIME_TYPE }?.get(1)
|
||||
|
||||
fun hash() = tags.firstOrNull { it.size > 1 && it[0] == HASH }?.get(1)
|
||||
private fun hash() = tags.firstOrNull { it.size > 1 && it[0] == HASH }?.get(1)
|
||||
|
||||
fun size() = tags.firstOrNull { it.size > 1 && it[0] == FILE_SIZE }?.get(1)
|
||||
private fun size() = tags.firstOrNull { it.size > 1 && it[0] == FILE_SIZE }?.get(1)
|
||||
|
||||
private fun dimensions() = tags.firstOrNull { it.size > 1 && it[0] == DIMENSION }?.get(1)?.let { Dimension.parse(it) }
|
||||
|
||||
private fun blurhash() = tags.firstOrNull { it.size > 1 && it[0] == BLUR_HASH }?.get(1)
|
||||
|
||||
private fun image() = tags.filter { it.size > 1 && it[0] == IMAGE }.map { it[1] }
|
||||
|
||||
private fun thumb() = tags.firstOrNull { it.size > 1 && it[0] == THUMB }?.get(1)
|
||||
|
||||
fun alt() = tags.firstOrNull { it.size > 1 && it[0] == ALT }?.get(1)
|
||||
|
||||
fun dimensions() = tags.firstOrNull { it.size > 1 && it[0] == DIMENSION }?.get(1)?.let { Dimension.parse(it) }
|
||||
|
||||
fun magnetURI() = tags.firstOrNull { it.size > 1 && it[0] == MAGNET_URI }?.get(1)
|
||||
|
||||
fun torrentInfoHash() = tags.firstOrNull { it.size > 1 && it[0] == TORRENT_INFOHASH }?.get(1)
|
||||
|
||||
fun blurhash() = tags.firstOrNull { it.size > 1 && it[0] == BLUR_HASH }?.get(1)
|
||||
|
||||
fun title() = tags.firstOrNull { it.size > 1 && it[0] == TITLE }?.get(1)
|
||||
|
||||
fun summary() = tags.firstOrNull { it.size > 1 && it[0] == SUMMARY }?.get(1)
|
||||
|
||||
fun image() = tags.firstOrNull { it.size > 1 && it[0] == IMAGE }?.get(1)
|
||||
|
||||
fun thumb() = tags.firstOrNull { it.size > 1 && it[0] == THUMB }?.get(1)
|
||||
fun duration() = tags.firstOrNull { it.size > 1 && it[0] == DURATION }?.get(1)
|
||||
|
||||
fun hasUrl() = tags.any { it.size > 1 && it[0] == URL }
|
||||
|
||||
fun isOneOf(mimeTypes: Set<String>) = tags.any { it.size > 1 && it[0] == FileHeaderEvent.MIME_TYPE && mimeTypes.contains(it[1]) }
|
||||
|
||||
// hack to fix pablo's bug
|
||||
fun rootVideo() =
|
||||
url()?.let {
|
||||
VideoMeta(
|
||||
url = it,
|
||||
mimeType = mimeType(),
|
||||
blurhash = blurhash(),
|
||||
alt = alt(),
|
||||
hash = hash(),
|
||||
dimension = dimensions(),
|
||||
size = size()?.toIntOrNull(),
|
||||
service = null,
|
||||
fallback = emptyList(),
|
||||
image = image(),
|
||||
)
|
||||
}
|
||||
|
||||
fun imetaTags() =
|
||||
tags
|
||||
.map { tagArray ->
|
||||
if (tagArray.size > 1 && tagArray[0] == IMETA) {
|
||||
VideoMeta.parse(tagArray)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}.plus(rootVideo())
|
||||
.filterNotNull()
|
||||
|
||||
companion object {
|
||||
private const val URL = "url"
|
||||
private const val ENCRYPTION_KEY = "aes-256-gcm"
|
||||
private const val MIME_TYPE = "m"
|
||||
private const val FILE_SIZE = "size"
|
||||
private const val DIMENSION = "dim"
|
||||
private const val HASH = "x"
|
||||
private const val MAGNET_URI = "magnet"
|
||||
private const val TORRENT_INFOHASH = "i"
|
||||
private const val BLUR_HASH = "blurhash"
|
||||
private const val ORIGINAL_HASH = "ox"
|
||||
private const val ALT = "alt"
|
||||
private const val TITLE = "title"
|
||||
private const val PUBLISHED_AT = "published_at"
|
||||
private const val SUMMARY = "summary"
|
||||
private const val DURATION = "duration"
|
||||
private const val IMAGE = "image"
|
||||
@@ -91,47 +114,129 @@ abstract class VideoEvent(
|
||||
kind: Int,
|
||||
dTag: String,
|
||||
url: String,
|
||||
magnetUri: String? = null,
|
||||
mimeType: String? = null,
|
||||
alt: String? = null,
|
||||
hash: String? = null,
|
||||
size: String? = null,
|
||||
size: Int? = null,
|
||||
duration: Int? = null,
|
||||
dimensions: Dimension? = null,
|
||||
blurhash: String? = null,
|
||||
originalHash: String? = null,
|
||||
magnetURI: String? = null,
|
||||
torrentInfoHash: String? = null,
|
||||
sensitiveContent: Boolean? = null,
|
||||
service: String? = null,
|
||||
altDescription: String,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (T) -> Unit,
|
||||
) {
|
||||
val tags =
|
||||
listOfNotNull(
|
||||
arrayOf("d", dTag),
|
||||
arrayOf(URL, url),
|
||||
magnetUri?.let { arrayOf(MAGNET_URI, it) },
|
||||
mimeType?.let { arrayOf(MIME_TYPE, it) },
|
||||
alt?.ifBlank { null }?.let { arrayOf(ALT, it) } ?: arrayOf("alt", altDescription),
|
||||
hash?.let { arrayOf(HASH, it) },
|
||||
size?.let { arrayOf(FILE_SIZE, it) },
|
||||
dimensions?.let { arrayOf(DIMENSION, it.toString()) },
|
||||
blurhash?.let { arrayOf(BLUR_HASH, it) },
|
||||
originalHash?.let { arrayOf(ORIGINAL_HASH, it) },
|
||||
magnetURI?.let { arrayOf(MAGNET_URI, it) },
|
||||
torrentInfoHash?.let { arrayOf(TORRENT_INFOHASH, it) },
|
||||
sensitiveContent?.let {
|
||||
if (it) {
|
||||
arrayOf("content-warning", "")
|
||||
} else {
|
||||
null
|
||||
}
|
||||
},
|
||||
val video =
|
||||
VideoMeta(
|
||||
url,
|
||||
mimeType,
|
||||
blurhash,
|
||||
dimensions,
|
||||
alt,
|
||||
hash,
|
||||
size,
|
||||
service,
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
)
|
||||
|
||||
val tags = mutableListOf<Array<String>>()
|
||||
|
||||
tags.add(arrayOf("d", dTag))
|
||||
tags.add(arrayOf(ALT, altDescription))
|
||||
if (sensitiveContent == true) {
|
||||
tags.add(arrayOf("content-warning", ""))
|
||||
}
|
||||
duration?.let { tags.add(arrayOf(DURATION, "duration")) }
|
||||
|
||||
tags.add(video.toIMetaArray())
|
||||
|
||||
val content = alt ?: ""
|
||||
signer.sign<T>(createdAt, kind, tags.toTypedArray(), content, onReady)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class VideoMeta(
|
||||
val url: String,
|
||||
val mimeType: String?,
|
||||
val blurhash: String?,
|
||||
val dimension: Dimension?,
|
||||
val alt: String?,
|
||||
val hash: String?,
|
||||
val size: Int?,
|
||||
val service: String?,
|
||||
val fallback: List<String>,
|
||||
val image: List<String>,
|
||||
) {
|
||||
fun toIMetaArray(): Array<String> =
|
||||
(
|
||||
listOfNotNull(
|
||||
"imeta",
|
||||
"$URL $url",
|
||||
mimeType?.let { "$MIME_TYPE $it" },
|
||||
alt?.let { "$ALT $it" },
|
||||
hash?.let { "$HASH $it" },
|
||||
size?.let { "$FILE_SIZE $it" },
|
||||
dimension?.let { "$DIMENSION $it" },
|
||||
blurhash?.let { "$BLUR_HASH $it" },
|
||||
service?.let { "$SERVICE $it" },
|
||||
) +
|
||||
fallback.map { "$FALLBACK $it" } +
|
||||
image.map { "$IMAGE $it" }
|
||||
|
||||
).toTypedArray()
|
||||
|
||||
companion object {
|
||||
const val URL = "url"
|
||||
const val MIME_TYPE = "m"
|
||||
const val FILE_SIZE = "size"
|
||||
const val DIMENSION = "dim"
|
||||
const val HASH = "x"
|
||||
const val BLUR_HASH = "blurhash"
|
||||
const val ALT = "alt"
|
||||
const val FALLBACK = "fallback"
|
||||
const val IMAGE = "image"
|
||||
const val SERVICE = "service"
|
||||
|
||||
fun parse(tagArray: Array<String>): VideoMeta? {
|
||||
var url: String? = null
|
||||
var mimeType: String? = null
|
||||
var blurhash: String? = null
|
||||
var dim: Dimension? = null
|
||||
var alt: String? = null
|
||||
var hash: String? = null
|
||||
var size: Int? = null
|
||||
var service: String? = null
|
||||
val fallback = mutableListOf<String>()
|
||||
val images = mutableListOf<String>()
|
||||
|
||||
tagArray.forEach {
|
||||
val parts = it.split(" ", limit = 2)
|
||||
val key = parts[0]
|
||||
val value = if (parts.size == 2) parts[1] else ""
|
||||
|
||||
if (value.isNotBlank()) {
|
||||
when (key) {
|
||||
URL -> url = value
|
||||
MIME_TYPE -> mimeType = value
|
||||
BLUR_HASH -> blurhash = value
|
||||
DIMENSION -> dim = Dimension.parse(value)
|
||||
ALT -> alt = value
|
||||
HASH -> hash = value
|
||||
FILE_SIZE -> size = value.toIntOrNull()
|
||||
SERVICE -> service = value
|
||||
FALLBACK -> fallback.add(value)
|
||||
IMAGE -> images.add(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return url?.let {
|
||||
VideoMeta(it, mimeType, blurhash, dim, alt, hash, size, service, fallback, images)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,48 +34,45 @@ class VideoHorizontalEvent(
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : VideoEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
) : VideoEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
RootScope {
|
||||
companion object {
|
||||
const val KIND = 34235
|
||||
const val ALT_DESCRIPTION = "Horizontal Video"
|
||||
|
||||
fun create(
|
||||
url: String,
|
||||
magnetUri: String? = null,
|
||||
mimeType: String? = null,
|
||||
alt: String? = null,
|
||||
hash: String? = null,
|
||||
size: String? = null,
|
||||
size: Int? = null,
|
||||
duration: Int? = null,
|
||||
dimensions: Dimension? = null,
|
||||
blurhash: String? = null,
|
||||
originalHash: String? = null,
|
||||
magnetURI: String? = null,
|
||||
torrentInfoHash: String? = null,
|
||||
sensitiveContent: Boolean? = null,
|
||||
service: String? = null,
|
||||
dTag: String = UUID.randomUUID().toString(),
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (VideoHorizontalEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
KIND,
|
||||
dTag,
|
||||
url,
|
||||
magnetUri,
|
||||
mimeType,
|
||||
alt,
|
||||
hash,
|
||||
size,
|
||||
dimensions,
|
||||
blurhash,
|
||||
originalHash,
|
||||
magnetURI,
|
||||
torrentInfoHash,
|
||||
sensitiveContent,
|
||||
ALT_DESCRIPTION,
|
||||
signer,
|
||||
createdAt,
|
||||
onReady,
|
||||
kind = KIND,
|
||||
dTag = dTag,
|
||||
url = url,
|
||||
mimeType = mimeType,
|
||||
alt = alt,
|
||||
hash = hash,
|
||||
size = size,
|
||||
duration = duration,
|
||||
dimensions = dimensions,
|
||||
blurhash = blurhash,
|
||||
sensitiveContent = sensitiveContent,
|
||||
service = service,
|
||||
altDescription = ALT_DESCRIPTION,
|
||||
signer = signer,
|
||||
createdAt = createdAt,
|
||||
onReady = onReady,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,41 +42,37 @@ class VideoVerticalEvent(
|
||||
|
||||
fun create(
|
||||
url: String,
|
||||
magnetUri: String? = null,
|
||||
mimeType: String? = null,
|
||||
alt: String? = null,
|
||||
hash: String? = null,
|
||||
size: String? = null,
|
||||
size: Int? = null,
|
||||
duration: Int? = null,
|
||||
dimensions: Dimension? = null,
|
||||
blurhash: String? = null,
|
||||
originalHash: String? = null,
|
||||
magnetURI: String? = null,
|
||||
torrentInfoHash: String? = null,
|
||||
sensitiveContent: Boolean? = null,
|
||||
service: String? = null,
|
||||
dTag: String = UUID.randomUUID().toString(),
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (VideoVerticalEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
KIND,
|
||||
dTag,
|
||||
url,
|
||||
magnetUri,
|
||||
mimeType,
|
||||
alt,
|
||||
hash,
|
||||
size,
|
||||
dimensions,
|
||||
blurhash,
|
||||
originalHash,
|
||||
magnetURI,
|
||||
torrentInfoHash,
|
||||
sensitiveContent,
|
||||
ALT_DESCRIPTION,
|
||||
signer,
|
||||
createdAt,
|
||||
onReady,
|
||||
kind = KIND,
|
||||
dTag = dTag,
|
||||
url = url,
|
||||
mimeType = mimeType,
|
||||
alt = alt,
|
||||
hash = hash,
|
||||
size = size,
|
||||
duration = duration,
|
||||
dimensions = dimensions,
|
||||
blurhash = blurhash,
|
||||
sensitiveContent = sensitiveContent,
|
||||
service = service,
|
||||
altDescription = ALT_DESCRIPTION,
|
||||
signer = signer,
|
||||
createdAt = createdAt,
|
||||
onReady = onReady,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user