fix(core/media_downloader): public stories

Signed-off-by: rhunk <101876869+rhunk@users.noreply.github.com>
This commit is contained in:
rhunk
2025-02-05 21:26:56 +01:00
parent 296d996b6c
commit d5a926f336
6 changed files with 84 additions and 37 deletions

View File

@ -10,6 +10,7 @@ import me.rhunk.snapenhance.common.database.impl.ConversationMessage
import me.rhunk.snapenhance.common.database.impl.FriendFeedEntry
import me.rhunk.snapenhance.common.database.impl.FriendInfo
import me.rhunk.snapenhance.common.database.impl.StoryEntry
import me.rhunk.snapenhance.common.database.impl.StorySnapEntry
import me.rhunk.snapenhance.common.database.impl.UserConversationLink
import me.rhunk.snapenhance.common.util.ktx.getBlobOrNull
import me.rhunk.snapenhance.common.util.ktx.getIntOrNull
@ -24,7 +25,8 @@ enum class DatabaseType(
val fileName: String
) {
MAIN("main.db"),
ARROYO("arroyo.db")
ARROYO("arroyo.db"),
SIMPLE_DB_HELPER("simple_db_helper.db")
}
class DatabaseAccess(
@ -495,4 +497,15 @@ class DatabaseAccess(
}
}?.close()
}
fun getStorySnapEntry(rawSnapId: String): StorySnapEntry? {
return useDatabase(DatabaseType.SIMPLE_DB_HELPER)?.performOperation {
readDatabaseObject(
StorySnapEntry(),
"DiscoverStorySnap",
"rawSnapId = ?",
arrayOf(rawSnapId)
)
}
}
}

View File

@ -207,9 +207,22 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
}
}
private fun downloadOperaMedia(downloadManagerClient: DownloadManagerClient, mediaInfoMap: Map<SplitMediaAssetType, MediaInfo>) {
private fun downloadOperaMedia(downloadManagerClient: DownloadManagerClient, mediaInfoMap: Map<SplitMediaAssetType, MediaInfo>, paramMap: ParamMap) {
if (mediaInfoMap.isEmpty()) return
paramMap["SNAP_ID"]?.toString()?.let { snapId ->
context.database.getStorySnapEntry(snapId)?.let { storySnapEntry ->
downloadManagerClient.downloadSingleMedia(
storySnapEntry.mediaUrl ?: throw Exception("Media URL not found"),
DownloadMediaType.fromUri(Uri.parse(storySnapEntry.mediaUrl)),
(storySnapEntry.mediaKey to storySnapEntry.mediaIv).takeIf { it.first != null && it.second != null }?.let { (key, iv) ->
MediaEncryptionKeyPair(key!!, iv!!, urlSafe = false)
}
)
return
}
}
val originalMediaInfo = mediaInfoMap[SplitMediaAssetType.ORIGINAL]!!
val originalMediaInfoReference = handleLocalReferences(originalMediaInfo.uri)
@ -286,7 +299,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
downloadSource = MediaDownloadSource.CHAT_MEDIA,
friendInfo = author,
forceAllowDuplicate = forceAllowDuplicate
), mediaInfoMap)
), mediaInfoMap, paramMap)
return
}
@ -333,40 +346,12 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
downloadSource = MediaDownloadSource.STORY,
friendInfo = author,
forceAllowDuplicate = forceAllowDuplicate,
), mediaInfoMap)
), mediaInfoMap, paramMap)
return
}
val snapSource = paramMap["SNAP_SOURCE"].toString()
//public stories
if ((snapSource == "PUBLIC_USER" || snapSource == "SAVED_STORY") &&
(forceDownload || shouldAutoDownload("public_stories"))) {
val author = (
paramMap["USER_ID"]?.let { context.database.getFriendInfo(it.toString())?.mutableUsername } // only for following users
?: paramMap["USERNAME"]?.toString()?.takeIf {
it.contains("value=")
}?.substringAfter("value=")?.substringBefore(")")?.substringBefore(",")
?: paramMap["CONTEXT_USER_IDENTITY"]?.toString()?.takeIf {
it.contains("username=")
}?.substringAfter("username=")?.substringBefore(",")
// fallback display name
?: paramMap["USER_DISPLAY_NAME"]?.toString()?.takeIf { it.isNotEmpty() }
?: paramMap["TIME_STAMP"]?.toString()
?: "unknown"
).sanitizeForPath()
downloadOperaMedia(provideDownloadManagerClient(
mediaIdentifier = paramMap["SNAP_ID"].toString(),
mediaAuthor = author,
downloadSource = MediaDownloadSource.PUBLIC_STORY,
creationTimestamp = paramMap["SNAP_TIMESTAMP"]?.toString()?.toLongOrNull(),
forceAllowDuplicate = forceAllowDuplicate,
), mediaInfoMap)
return
}
//spotlight
if (snapSource == "SINGLE_SNAP_STORY" && (forceDownload || shouldAutoDownload("spotlight"))) {
downloadOperaMedia(provideDownloadManagerClient(
@ -375,7 +360,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
mediaAuthor = paramMap["CREATOR_DISPLAY_NAME"].toString(),
creationTimestamp = paramMap["SNAP_TIMESTAMP"]?.toString()?.toLongOrNull(),
forceAllowDuplicate = forceAllowDuplicate,
), mediaInfoMap)
), mediaInfoMap, paramMap)
return
}
@ -481,6 +466,29 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
}.show()
}
}
//public stories
val author = (
paramMap["USER_ID"]?.let { context.database.getFriendInfo(it.toString())?.mutableUsername } // only for following users
?: paramMap["USERNAME"]?.toString()?.takeIf {
it.contains("value=")
}?.substringAfter("value=")?.substringBefore(")")?.substringBefore(",")
?: paramMap["CONTEXT_USER_IDENTITY"]?.toString()?.takeIf {
it.contains("username=")
}?.substringAfter("username=")?.substringBefore(",")
// fallback display name
?: paramMap["USER_DISPLAY_NAME"]?.toString()?.takeIf { it.isNotEmpty() }
?: paramMap["TIME_STAMP"]?.toString()
?: "unknown"
).sanitizeForPath()
downloadOperaMedia(provideDownloadManagerClient(
mediaIdentifier = paramMap["SNAP_ID"].toString(),
mediaAuthor = author,
downloadSource = MediaDownloadSource.PUBLIC_STORY,
creationTimestamp = paramMap["SNAP_TIMESTAMP"]?.toString()?.toLongOrNull(),
forceAllowDuplicate = forceAllowDuplicate,
), mediaInfoMap, paramMap)
}
private fun shouldAutoDownload(keyFilter: String? = null): Boolean {

View File

@ -16,7 +16,7 @@ class MediaInfo(obj: Any?) : AbstractWrapper(obj) {
init {
instance?.let {
if (it is List<*>) {
if (it.size == 0) {
if (it.isEmpty()) {
throw RuntimeException("MediaInfo is empty")
}
instance = it[0]!!