From 9814b3ccab0364724ed996c3ac9deac79e3d46cf Mon Sep 17 00:00:00 2001 From: Eyre_S Date: Tue, 13 Feb 2024 14:04:49 +0800 Subject: [PATCH] fix Bilibili av/bv conversion failed when avid > 2^30 --- gradle.properties | 2 +- .../cc/sukazyo/cono/morny/util/BiliTool.scala | 31 ++++++++++--------- .../cc/sukazyo/cono/morny/util/UseMath.scala | 6 ++++ .../cono/morny/test/utils/BiliToolTest.scala | 4 +++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3882b9d..6c986a3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ MORNY_ARCHIVE_NAME = morny-coeur MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s -VERSION = 1.3.0 +VERSION = 1.3.1 USE_DELTA = false VERSION_DELTA = diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/BiliTool.scala b/src/main/scala/cc/sukazyo/cono/morny/util/BiliTool.scala index 37a2473..5097d16 100644 --- a/src/main/scala/cc/sukazyo/cono/morny/util/BiliTool.scala +++ b/src/main/scala/cc/sukazyo/cono/morny/util/BiliTool.scala @@ -30,12 +30,12 @@ object BiliTool { private val V_CONV_XOR = 177451812L private val V_CONV_ADD = 8728348608L - private val BV_TABLE = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF" - private val TABLE_INT = BV_TABLE.length - private val BV_TABLE_REVERSED = - val mapping = mutable.HashMap.empty[Char, Int] - for (i <- BV_TABLE.indices) mapping += (BV_TABLE(i) -> i) - mapping.toMap + private val X_AV_MAX = Math.pow(2, 30).toLong + private val X_AV_ALT = Int.MaxValue.toLong + 1 + + private val BB58_TABLE_REV: Map[Char, Int] = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF".toCharArray.zipWithIndex.toMap + private val BB58_TABLE: Map[Int, Char] = BB58_TABLE_REV.map((k,v) => (v, k)) + private val BB58_TABLE_SIZE: Long = BB58_TABLE.size private val BV_TEMPLATE = "1 4 1 7 " private val BV_TEMPLATE_FILTER = Array(9, 8, 1, 6, 2, 4) @@ -56,7 +56,7 @@ object BiliTool { def this (bv: String, length: Int) = this(bv, s"given length is $length") - /** Error of illegal BV id, where the reason is the BV id contains non [[BV_TABLE base58 character]]. + /** Error of illegal BV id, where the reason is the BV id contains non [[BB58_TABLE base58 character]]. * * @param bv the source of illegal BV id. * @param c the illegal character @@ -79,7 +79,7 @@ object BiliTool { * @see $AvBvSeeAlso * * @param bv a BV id, which should be exactly 10 digits and all chars should be - * a legal base58 char (which means can be found in [[BV_TABLE]]). + * a legal base58 char (which means can be found in [[BB58_TABLE]]). * otherwise, an [[IllegalFormatException]] will be thrown. * @return an AV id which will shows the save video of input __bv__ in $Bilibili * @throws IllegalFormatException when the input __bv__ is not a legal 10 digits base58 @@ -91,11 +91,14 @@ object BiliTool { if (bv.length != 10) throw IllegalFormatException(bv, bv.length) for (i <- BV_TEMPLATE_FILTER.indices) { val _get = BV_TEMPLATE_FILTER(i) - val tableToken = BV_TABLE_REVERSED get bv(_get) + val tableToken = BB58_TABLE_REV get bv(_get) if tableToken isEmpty then throw IllegalFormatException(bv, bv(_get), _get) - av = av + (tableToken.get * (TABLE_INT**i).toLong) + av = av + (tableToken.get.toLong * (BB58_TABLE_SIZE**i).toLong) } - (av - V_CONV_ADD) ^ V_CONV_XOR + av = (av - V_CONV_ADD) ^ V_CONV_XOR + if (av < 0) + av+ X_AV_ALT + else av } /** Convert an AV video format to a BV video format for $Bilibili. @@ -107,11 +110,11 @@ object BiliTool { * @return a BV id which will shows the save video of input __av__ in $Bilibili */ def toBv (av: Long): String = { - val _av = (av^V_CONV_XOR)+V_CONV_ADD + val __av =if (av > X_AV_MAX) av - X_AV_ALT else av + val _av = (__av^V_CONV_XOR)+V_CONV_ADD val bv = Array(BV_TEMPLATE:_*) for (i <- BV_TEMPLATE_FILTER.indices) { - import Math.{floor, pow} - bv(BV_TEMPLATE_FILTER(i)) = BV_TABLE( (floor(_av/(TABLE_INT**i)) % TABLE_INT) toInt ) + bv(BV_TEMPLATE_FILTER(i)) = BB58_TABLE( (_av/(BB58_TABLE_SIZE**i) % BB58_TABLE_SIZE) toInt ) } String copyValueOf bv } diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/UseMath.scala b/src/main/scala/cc/sukazyo/cono/morny/util/UseMath.scala index fdbfd1b..30c7879 100644 --- a/src/main/scala/cc/sukazyo/cono/morny/util/UseMath.scala +++ b/src/main/scala/cc/sukazyo/cono/morny/util/UseMath.scala @@ -16,6 +16,12 @@ object UseMath { def ** (other: Int): Double = Math.pow(self, other) } + extension (self: Long) { + @targetName("pow") + def ** (other: Long): Long = + Math.pow(self, other).toLong + } + extension (base: Int) { def percentageOf (another: Int): Int = Math.round((another.toDouble/base)*100).toInt diff --git a/src/test/scala/cc/sukazyo/cono/morny/test/utils/BiliToolTest.scala b/src/test/scala/cc/sukazyo/cono/morny/test/utils/BiliToolTest.scala index 1ae8264..c8e2de2 100644 --- a/src/test/scala/cc/sukazyo/cono/morny/test/utils/BiliToolTest.scala +++ b/src/test/scala/cc/sukazyo/cono/morny/test/utils/BiliToolTest.scala @@ -13,6 +13,10 @@ class BiliToolTest extends MornyTests with TableDrivenPropertyChecks { ("1Q541167Qg", 455017605L), ("1mK4y1C7Bz", 882584971L), ("1T24y197V2", 688730800L), + ("1b2421A7FH", 1600345142L), + ("1DB421k7zX", 1350018000L), + ("19m411D7wx", 1900737470L), + ("1LQ4y1A7im", 709042411L), ) forAll (examples) { (bv, av) => s"while using av$av/BV$bv :" - {