Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions native/app/src/main/java/com/localstream/app/domain/Formatters.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ import kotlin.math.pow
object TitleCleaner {
private val YEAR_IN_PAREN_REGEX = Regex("[\\(\\[]((?:19|20)\\d{2})[\\)\\]]")
private val YEAR_REGEX = Regex("(?:^|[\\s\\._\\-\\(\\[])((?:19|20)\\d{2})(?=[\\s\\._\\-\\)\\]]|$)")
private val EXTENSION_REGEX = Regex("\\.[^/.]+$")
private val SEASON_EPISODE_CLEAN_REGEX = Regex("[sS]\\d+(\\s*)?([eE]\\d+)?|(\\d+)(\\s*)?x(\\d+).*", RegexOption.IGNORE_CASE)
private val YEAR_SUFFIX_REGEX = Regex("(?<=\\w|\\s|\\.|\\-|_|\\()\\s*[\\(\\.\\[\\-_]?(19|20)\\d{2}.*")
private val SEPARATORS_REGEX = Regex("[\\.\\-_]")
private val TAGS_REGEX = Regex("1080p|720p|2160p|4k|bluray|webrip|hdtv|x264|x265|hevc|vostfr|french|truefrench", RegexOption.IGNORE_CASE)
private val OPEN_BRACKET_END_REGEX = Regex("[\\(\\[\\{]\\s*$")
private val TRAILING_SYMBOLS_REGEX = Regex("[\\s\\-\\.\\(\\)\\[\\]\\{\\}]+$")

@Suppress("ReturnCount")
fun extractYear(filename: String): Int? {
val nameWithoutExt = filename.replace(Regex("\\.[^/.]+$"), "")
val nameWithoutExt = filename.replace(EXTENSION_REGEX, "")
val parenMatch = YEAR_IN_PAREN_REGEX.find(nameWithoutExt)
if (parenMatch != null) {
return parenMatch.groupValues[1].toIntOrNull()
Expand All @@ -21,22 +28,21 @@ object TitleCleaner {
}

fun getCleanTitle(filename: String): String {
var title = filename.replace(Regex("\\.[^/.]+$"), "")
title = title.replace(Regex("[sS]\\d+(\\s*)?([eE]\\d+)?|(\\d+)(\\s*)?x(\\d+).*", RegexOption.IGNORE_CASE), "")
title = title.replace(Regex("(?<=\\w|\\s|\\.|\\-|_|\\()\\s*[\\(\\.\\[\\-_]?(19|20)\\d{2}.*"), "")
title = title.replace(Regex("[\\.\\-_]"), " ")
title = title.replace(
Regex("1080p|720p|2160p|4k|bluray|webrip|hdtv|x264|x265|hevc|vostfr|french|truefrench", RegexOption.IGNORE_CASE),
""
)
var title = filename.replace(EXTENSION_REGEX, "")
title = title.replace(SEASON_EPISODE_CLEAN_REGEX, "")
title = title.replace(YEAR_SUFFIX_REGEX, "")
title = title.replace(SEPARATORS_REGEX, " ")
title = title.replace(TAGS_REGEX, "")
return title.trim()
.replace(Regex("[\\(\\[\\{]\\s*$"), "")
.replace(Regex("[\\s\\-\\.\\(\\)\\[\\]\\{\\}]+$"), "")
.replace(OPEN_BRACKET_END_REGEX, "")
.replace(TRAILING_SYMBOLS_REGEX, "")
.trim()
}
}

object Formatters {
private val TRAILING_ZEROS_REGEX = Regex("\\.?0+$")

private val suspectPaths = listOf(
"/dcim/", "/camera/", "/whatsapp/", "/snapchat/", "/instagram/",
"/telegram/", "/signal/", "/viber/", "/messenger/", "/tiktok/",
Expand Down Expand Up @@ -65,7 +71,7 @@ object Formatters {
val sizes = arrayOf("B", "KB", "MB", "GB", "TB")
val i = floor(ln(bytes.toDouble()) / ln(k)).toInt()
val value = bytes / k.pow(i.toDouble())
val formatted = String.format(Locale.US, "%.2f", value).replace(Regex("\\.?0+$"), "")
val formatted = String.format(Locale.US, "%.2f", value).replace(TRAILING_ZEROS_REGEX, "")
return "$formatted ${sizes[i]}"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ object VideoFilterSorter {
}
}

private val HD_OR_4K_REGEX = Regex("1080p|720p|2160p|4k", RegexOption.IGNORE_CASE)

private fun filterByResolution(videos: List<VideoItem>, opts: FilterSortOptions): List<VideoItem> {
if (opts.filterResolution == ResolutionFilter.ALL) return videos
return videos.filter { v ->
Expand All @@ -33,7 +35,7 @@ object VideoFilterSorter {
ResolutionFilter.TWO_K -> n.contains("1440p")
ResolutionFilter.ONE_THOUSAND_EIGHTY_P -> n.contains("1080p")
ResolutionFilter.SEVEN_HUNDRED_TWENTY_P -> n.contains("720p")
ResolutionFilter.SD -> !Regex("1080p|720p|2160p|4k", RegexOption.IGNORE_CASE).containsMatchIn(n)
ResolutionFilter.SD -> !HD_OR_4K_REGEX.containsMatchIn(n)
ResolutionFilter.ALL -> true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,15 @@ object VideoGrouper {
return video.copy(season = sStr.toIntOrNull(), episode = eStr.toIntOrNull())
}

private val SERIES_SEPARATORS_REGEX = Regex("[\\.\\-_/\\\\\\[\\]\\(\\)]")
private val SERIES_TRAILING_DASH_SPACE_REGEX = Regex("[\\s\\-]+$")

private fun resolveSeriesName(video: VideoItem, match: MatchResult?): String {
val sName = video.seriesName ?: if (match != null) {
video.name.substring(0, match.range.first)
.replace(Regex("[\\.\\-_/\\\\\\[\\]\\(\\)]"), " ")
.replace(SERIES_SEPARATORS_REGEX, " ")
.trim()
.replace(Regex("[\\s\\-]+$"), "")
.replace(SERIES_TRAILING_DASH_SPACE_REGEX, "")
} else {
TitleCleaner.getCleanTitle(video.name)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ object VideoNameParser {

val SEASON_EPISODE_REGEX = Regex("[sS](\\d+)(\\s*)[eE](\\d+)|(\\d+)(\\s*)x(\\d+)")
private val SEASON_FOLDER_REGEX = Regex("Saison\\s*(\\d+)|Season\\s*(\\d+)|S(\\d+)", RegexOption.IGNORE_CASE)
private val EXTENSION_DOT_WORD_REGEX = Regex("\\.\\w+$")
private val SERIES_SEPARATORS_REGEX = Regex("[\\.\\-_/\\\\\\[\\]\\(\\)]")
private val SERIES_TRAILING_DASH_SPACE_REGEX = Regex("[\\s\\-]+$")
private val LEADING_DIGITS_REGEX = Regex("^(\\d+)")

fun videoBaseName(fileName: String): String =
fileName.replace(Regex("\\.\\w+$"), "").lowercase()
fileName.replace(EXTENSION_DOT_WORD_REGEX, "").lowercase()

fun subtitleBaseName(fileName: String): String =
fileName.replace(Regex("\\.\\w+$"), "").replace(LANG_SUFFIX_REGEX, "").lowercase()
fileName.replace(EXTENSION_DOT_WORD_REGEX, "").replace(LANG_SUFFIX_REGEX, "").lowercase()

fun parentFolder(relativePath: String): String {
val normalized = relativePath.replace('\\', '/').trimEnd('/')
Expand All @@ -34,9 +38,9 @@ object VideoNameParser {
val sStr = if (groupValues[1].isNotEmpty()) groupValues[1] else groupValues[4]
val eStr = if (groupValues[3].isNotEmpty()) groupValues[3] else groupValues[6]
var seriesName = fileName.substring(0, match.range.first)
.replace(Regex("[\\.\\-_/\\\\\\[\\]\\(\\)]"), " ")
.replace(SERIES_SEPARATORS_REGEX, " ")
.trim()
.replace(Regex("[\\s\\-]+$"), "")
.replace(SERIES_TRAILING_DASH_SPACE_REGEX, "")
if (seriesName.isEmpty()) seriesName = "Série Inconnue"
return SeriesInfo(seriesName = seriesName, season = sStr.toIntOrNull(), episode = eStr.toIntOrNull())
}
Expand All @@ -53,7 +57,7 @@ object VideoNameParser {
sMatch.groupValues[2].ifEmpty { sMatch.groupValues[3] }
}
val seriesName = if (pathParts.size >= 3) pathParts[pathParts.size - 3] else "Série Inconnue"
val epMatch = Regex("^(\\d+)").find(fileName)
val epMatch = LEADING_DIGITS_REGEX.find(fileName)
return SeriesInfo(
seriesName = seriesName,
season = sVal.toIntOrNull(),
Expand Down
Loading