mirror of
https://github.com/fumiama/copymanga.git
synced 2026-06-28 14:50:29 +08:00
v2.3.1
新增 1. 增强型数据访问选项 2. 漫画下载数量并发限制 修复 1. 同时下载过多漫画时失败 (fix #67) 2. 主页滑动横幅后刷新闪退 (fix #65) 3. v2.3.0 增强型数据访问下登录失败 优化 1. 网络不佳时自动打开增强型数据访问 2. 不再反复读取代理状态
This commit is contained in:
@@ -9,8 +9,8 @@ android {
|
|||||||
applicationId 'top.fumiama.copymanga'
|
applicationId 'top.fumiama.copymanga'
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 34
|
targetSdkVersion 34
|
||||||
versionCode 58
|
versionCode 59
|
||||||
versionName '2.3.0'
|
versionName '2.3.1'
|
||||||
resourceConfigurations += ['zh', 'zh-rCN']
|
resourceConfigurations += ['zh', 'zh-rCN']
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ class Shelf(private val token: String, getString: (Int) -> String) {
|
|||||||
private val apiUrl: String = getString(R.string.shelfOperateApiUrl).format(hostUrl)
|
private val apiUrl: String = getString(R.string.shelfOperateApiUrl).format(hostUrl)
|
||||||
private val queryApiUrlTemplate = getString(R.string.bookUserQueryApiUrl)
|
private val queryApiUrlTemplate = getString(R.string.bookUserQueryApiUrl)
|
||||||
private val referer: String = getString(R.string.referer).format(DownloadTools.app_ver)
|
private val referer: String = getString(R.string.referer).format(DownloadTools.app_ver)
|
||||||
private val ua: String = getString(R.string.pc_ua).format(DownloadTools.app_ver)
|
|
||||||
private val addApiUrl get() = "$apiUrl?platform=3".let { CMApi.apiProxy?.wrap(it)?:it }
|
private val addApiUrl get() = "$apiUrl?platform=3".let { CMApi.apiProxy?.wrap(it)?:it }
|
||||||
private val delApiUrl get() = "${apiUrl}s?platform=3".let { CMApi.apiProxy?.wrap(it)?:it }
|
private val delApiUrl get() = "${apiUrl}s?platform=3".let { CMApi.apiProxy?.wrap(it)?:it }
|
||||||
suspend fun add(comicId: String): String = withContext(Dispatchers.IO) {
|
suspend fun add(comicId: String): String = withContext(Dispatchers.IO) {
|
||||||
@@ -29,9 +28,13 @@ class Shelf(private val token: String, getString: (Int) -> String) {
|
|||||||
append(token)
|
append(token)
|
||||||
}
|
}
|
||||||
val re = DownloadTools.requestWithBody(
|
val re = DownloadTools.requestWithBody(
|
||||||
addApiUrl, "POST", body.encodeToByteArray(), referer, ua
|
addApiUrl, "POST", body.encodeToByteArray()
|
||||||
)?.decodeToString() ?: return@withContext "空回应"
|
)?.decodeToString() ?: return@withContext "空回应"
|
||||||
return@withContext Gson().fromJson(re, ReturnBase::class.java).message
|
return@withContext try {
|
||||||
|
Gson().fromJson(re, ReturnBase::class.java).message
|
||||||
|
} catch (e: Exception) {
|
||||||
|
"$re ${e.message}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun del(vararg bookIds: Int): String = withContext(Dispatchers.IO) {
|
suspend fun del(vararg bookIds: Int): String = withContext(Dispatchers.IO) {
|
||||||
@@ -48,9 +51,13 @@ class Shelf(private val token: String, getString: (Int) -> String) {
|
|||||||
append(token)
|
append(token)
|
||||||
}
|
}
|
||||||
val re = DownloadTools.requestWithBody(
|
val re = DownloadTools.requestWithBody(
|
||||||
delApiUrl, "DELETE", body.encodeToByteArray(), referer, ua
|
delApiUrl, "DELETE", body.encodeToByteArray()
|
||||||
)?.decodeToString() ?: return@withContext "空回应"
|
)?.decodeToString() ?: return@withContext "空回应"
|
||||||
return@withContext Gson().fromJson(re, ReturnBase::class.java).message
|
return@withContext try {
|
||||||
|
Gson().fromJson(re, ReturnBase::class.java).message
|
||||||
|
} catch (e: Exception) {
|
||||||
|
"$re ${e.message}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun query(pathWord: String): BookQueryStructure? = withContext(Dispatchers.IO) {
|
suspend fun query(pathWord: String): BookQueryStructure? = withContext(Dispatchers.IO) {
|
||||||
@@ -58,7 +65,7 @@ class Shelf(private val token: String, getString: (Int) -> String) {
|
|||||||
Gson().fromJson(DownloadTools.getHttpContent(
|
Gson().fromJson(DownloadTools.getHttpContent(
|
||||||
queryApiUrlTemplate.format(hostUrl, pathWord).let {
|
queryApiUrlTemplate.format(hostUrl, pathWord).let {
|
||||||
CMApi.apiProxy?.wrap(it)?:it
|
CMApi.apiProxy?.wrap(it)?:it
|
||||||
}, referer, ua
|
}, referer
|
||||||
).decodeToString(), BookQueryStructure::class.java)
|
).decodeToString(), BookQueryStructure::class.java)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|||||||
@@ -78,10 +78,7 @@ open class AutoDownloadHandler(
|
|||||||
var cnt = 0
|
var cnt = 0
|
||||||
while (cnt++ <= 3) {
|
while (cnt++ <= 3) {
|
||||||
try {
|
try {
|
||||||
val data = DownloadTools.getHttpContent(
|
val data = DownloadTools.getHttpContent(CMApi.apiProxy?.wrap(url)?:url)
|
||||||
CMApi.apiProxy?.wrap(url)?:url, null,
|
|
||||||
DownloadTools.pc_ua
|
|
||||||
)
|
|
||||||
if(exit) return@withContext
|
if(exit) return@withContext
|
||||||
val fi = data.inputStream()
|
val fi = data.inputStream()
|
||||||
val pass = setGsonItem(Gson().fromJson(fi.reader(), jsonClass))
|
val pass = setGsonItem(Gson().fromJson(fi.reader(), jsonClass))
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ class PausableDownloader(private val url: String, private val waitMilliseconds:
|
|||||||
try {
|
try {
|
||||||
val data = (DownloadTools.getHttpContent(
|
val data = (DownloadTools.getHttpContent(
|
||||||
(if(isApi) CMApi.apiProxy?.wrap(url) else null)?:url,
|
(if(isApi) CMApi.apiProxy?.wrap(url) else null)?:url,
|
||||||
DownloadTools.referer,
|
DownloadTools.referer
|
||||||
DownloadTools.pc_ua
|
|
||||||
))
|
))
|
||||||
whenFinish?.let { it(data) }
|
whenFinish?.let { it(data) }
|
||||||
return@withContext true
|
return@withContext true
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ object DownloadTools {
|
|||||||
capsule
|
capsule
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getHttpContent(u: String, refer: String? = null, ua: String? = null): ByteArray =
|
suspend fun getHttpContent(u: String, refer: String? = null, ua: String? = pc_ua): ByteArray =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
if (Comandy.useComandy) {
|
if (Comandy.useComandy) {
|
||||||
getComandyApiConnection(u, "GET", refer, ua).let { capsule ->
|
getComandyApiConnection(u, "GET", refer, ua).let { capsule ->
|
||||||
@@ -150,7 +150,7 @@ object DownloadTools {
|
|||||||
FutureTask(if (Comandy.useComandy) Callable{
|
FutureTask(if (Comandy.useComandy) Callable{
|
||||||
try {
|
try {
|
||||||
Comandy.instance?.request(Gson().toJson(
|
Comandy.instance?.request(Gson().toJson(
|
||||||
getComandyNormalConnection(u, "GET"))
|
getComandyNormalConnection(u, "GET", pc_ua))
|
||||||
)?.let { result ->
|
)?.let { result ->
|
||||||
Gson().fromJson(result, ComandyCapsule::class.java)?.let {
|
Gson().fromJson(result, ComandyCapsule::class.java)?.let {
|
||||||
if (it.code != 200) null
|
if (it.code != 200) null
|
||||||
@@ -164,7 +164,7 @@ object DownloadTools {
|
|||||||
} else Callable {
|
} else Callable {
|
||||||
var ret: ByteArray? = null
|
var ret: ByteArray? = null
|
||||||
try {
|
try {
|
||||||
val connection = getNormalConnection(u, "GET")
|
val connection = getNormalConnection(u, "GET", pc_ua)
|
||||||
val ci = connection.inputStream
|
val ci = connection.inputStream
|
||||||
if(readSize > 0) {
|
if(readSize > 0) {
|
||||||
ret = ByteArray(readSize)
|
ret = ByteArray(readSize)
|
||||||
@@ -186,22 +186,22 @@ object DownloadTools {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
fun requestWithBody(url: String, method: String, body: ByteArray, refer: String? = null, ua: String? = null): ByteArray? {
|
fun requestWithBody(url: String, method: String, body: ByteArray, refer: String? = referer, ua: String? = pc_ua, contentType: String? = "application/x-www-form-urlencoded;charset=utf-8"): ByteArray? {
|
||||||
Log.d("MyDT", "$method Http: $url")
|
Log.d("MyDT", "$method Http: $url")
|
||||||
var ret: ByteArray? = null
|
var ret: ByteArray? = null
|
||||||
val task = FutureTask(if(Comandy.useComandy) Callable{
|
val task = FutureTask(if(Comandy.useComandy) Callable{
|
||||||
try {
|
try {
|
||||||
val capsule = getComandyApiConnection(url, method, refer, ua)
|
val capsule = getComandyApiConnection(url, method, refer, ua)
|
||||||
|
contentType?.let { capsule.headers["content-type"] = it }
|
||||||
capsule.data = body.decodeToString()
|
capsule.data = body.decodeToString()
|
||||||
Comandy.instance?.request(Gson().toJson(capsule))?.let { result ->
|
Comandy.instance?.request(Gson().toJson(capsule))?.let { result ->
|
||||||
Gson().fromJson(result, ComandyCapsule::class.java)?.let {
|
Gson().fromJson(result, ComandyCapsule::class.java)?.let {
|
||||||
if (it.code != 200) null
|
it.data?.let { d -> Base64.decode(d, Base64.DEFAULT) }?:"empty comandy data".encodeToByteArray()
|
||||||
else it.data?.let { d -> Base64.decode(d, Base64.DEFAULT) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
ex.printStackTrace()
|
ex.printStackTrace()
|
||||||
null
|
ex.message?.encodeToByteArray()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else Callable {
|
else Callable {
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
|
|||||||
cv.tic.apply { post { text = name } }
|
cv.tic.apply { post { text = name } }
|
||||||
homeF?.let {
|
homeF?.let {
|
||||||
if(img.startsWith("http")) {
|
if(img.startsWith("http")) {
|
||||||
Log.d("MyHH", "load card image: $img")
|
//Log.d("MyHH", "load card image: $img")
|
||||||
val waitMillis = cardLoadingWaits.getAndIncrement().toLong()*200
|
val waitMillis = cardLoadingWaits.getAndIncrement().toLong()*200
|
||||||
val g = Glide.with(it).load(GlideUrl(CMApi.imageProxy?.wrap(img)?:img, CMApi.myGlideHeaders))
|
val g = Glide.with(it).load(GlideUrl(CMApi.imageProxy?.wrap(img)?:img, CMApi.myGlideHeaders))
|
||||||
.addListener(GlideHideLottieViewListener(WeakReference(cv.laic)) {
|
.addListener(GlideHideLottieViewListener(WeakReference(cv.laic)) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package top.fumiama.copymanga.user
|
|||||||
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
|
import android.util.Log
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@@ -10,6 +11,8 @@ import top.fumiama.copymanga.json.LoginInfoStructure
|
|||||||
import top.fumiama.copymanga.tools.api.CMApi
|
import top.fumiama.copymanga.tools.api.CMApi
|
||||||
import top.fumiama.copymanga.tools.http.Comandy
|
import top.fumiama.copymanga.tools.http.Comandy
|
||||||
import top.fumiama.copymanga.tools.http.DownloadTools
|
import top.fumiama.copymanga.tools.http.DownloadTools
|
||||||
|
import top.fumiama.copymanga.tools.http.DownloadTools.app_ver
|
||||||
|
import top.fumiama.copymanga.tools.http.DownloadTools.pc_ua
|
||||||
import top.fumiama.dmzj.copymanga.R
|
import top.fumiama.dmzj.copymanga.R
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
@@ -20,12 +23,13 @@ class Member(private val pref: SharedPreferences, private val getString: (Int) -
|
|||||||
var err = ""
|
var err = ""
|
||||||
if (Comandy.useComandy) getComandyLoginConnection(username, pwd, salt).let { capsule ->
|
if (Comandy.useComandy) getComandyLoginConnection(username, pwd, salt).let { capsule ->
|
||||||
try {
|
try {
|
||||||
Comandy.instance?.request(Gson().toJson(capsule))?.let { result ->
|
val para = Gson().toJson(capsule)
|
||||||
|
Comandy.instance?.request(para)?.let { result ->
|
||||||
Gson().fromJson(result, ComandyCapsule::class.java)!!.let {
|
Gson().fromJson(result, ComandyCapsule::class.java)!!.let {
|
||||||
if (it.code != 200) {
|
if (it.code != 200) {
|
||||||
val l = LoginInfoStructure()
|
val l = LoginInfoStructure()
|
||||||
l.code = it.code
|
l.code = it.code
|
||||||
l.message = it.data?.let { d -> Base64.decode(d, Base64.DEFAULT).decodeToString() }
|
l.message = it.data?.let { d -> Base64.decode(d, Base64.DEFAULT).decodeToString() }?:"HTTP ${it.code}"
|
||||||
return@withContext l
|
return@withContext l
|
||||||
}
|
}
|
||||||
Base64.decode(it.data, Base64.DEFAULT)
|
Base64.decode(it.data, Base64.DEFAULT)
|
||||||
@@ -37,7 +41,7 @@ class Member(private val pref: SharedPreferences, private val getString: (Int) -
|
|||||||
}
|
}
|
||||||
}?.let {
|
}?.let {
|
||||||
try {
|
try {
|
||||||
saveInfo(it)
|
return@withContext saveInfo(it)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
err = e.message.toString()
|
err = e.message.toString()
|
||||||
}
|
}
|
||||||
@@ -46,7 +50,7 @@ class Member(private val pref: SharedPreferences, private val getString: (Int) -
|
|||||||
inputStream.use {
|
inputStream.use {
|
||||||
it?.readBytes()?.let { data ->
|
it?.readBytes()?.let { data ->
|
||||||
try {
|
try {
|
||||||
saveInfo(data)
|
return@withContext saveInfo(data)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
err = e.message.toString()
|
err = e.message.toString()
|
||||||
}
|
}
|
||||||
@@ -143,7 +147,7 @@ class Member(private val pref: SharedPreferences, private val getString: (Int) -
|
|||||||
setRequestProperty("accept", "application/json")
|
setRequestProperty("accept", "application/json")
|
||||||
val r = if(!getBoolean("settings_cat_net_sw_use_foreign", false)) "1" else "0"
|
val r = if(!getBoolean("settings_cat_net_sw_use_foreign", false)) "1" else "0"
|
||||||
val pwdEncoded = Base64.encode("$pwd-$salt".toByteArray(), Base64.DEFAULT).decodeToString()
|
val pwdEncoded = Base64.encode("$pwd-$salt".toByteArray(), Base64.DEFAULT).decodeToString()
|
||||||
outputStream.write("username=${URLEncoder.encode(username, Charset.defaultCharset().name())}&password=$pwdEncoded&salt=$salt&platform=3&authorization=Token+&version=1.4.4&source=copyApp®ion=$r&webp=1".toByteArray())
|
outputStream.write("username=${URLEncoder.encode(username, Charset.defaultCharset().name())}&password=$pwdEncoded&salt=$salt&platform=3&authorization=Token+&version=$app_ver&source=copyApp®ion=$r&webp=1".toByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,14 +156,14 @@ class Member(private val pref: SharedPreferences, private val getString: (Int) -
|
|||||||
getString(R.string.loginApiUrl).format(CMApi.myHostApiUrl).let {
|
getString(R.string.loginApiUrl).format(CMApi.myHostApiUrl).let {
|
||||||
CMApi.apiProxy?.wrap(it)?:it
|
CMApi.apiProxy?.wrap(it)?:it
|
||||||
}.let {
|
}.let {
|
||||||
DownloadTools.getComandyApiConnection(it, "POST").apply {
|
DownloadTools.getComandyApiConnection(it, "POST", null, pc_ua).apply {
|
||||||
pref.apply {
|
pref.apply {
|
||||||
headers["content-type"] = "application/x-www-form-urlencoded;charset=utf-8"
|
headers["content-type"] = "application/x-www-form-urlencoded;charset=utf-8"
|
||||||
headers["platform"] = "3"
|
headers["platform"] = "3"
|
||||||
headers["accept"] = "application/json"
|
headers["accept"] = "application/json"
|
||||||
val r = if(!getBoolean("settings_cat_net_sw_use_foreign", false)) "1" else "0"
|
val r = if(!getBoolean("settings_cat_net_sw_use_foreign", false)) "1" else "0"
|
||||||
val pwdEncoded = Base64.encode("$pwd-$salt".toByteArray(), Base64.DEFAULT).decodeToString()
|
val pwdEncoded = Base64.encode("$pwd-$salt".toByteArray(), Base64.DEFAULT).decodeToString()
|
||||||
data = "username=${URLEncoder.encode(username, Charset.defaultCharset().name())}&password=$pwdEncoded&salt=$salt&platform=3&authorization=Token+&version=1.4.4&source=copyApp®ion=$r&webp=1"
|
data = "username=${URLEncoder.encode(username, Charset.defaultCharset().name())}&password=$pwdEncoded&salt=$salt&platform=3&authorization=Token+&version=$app_ver&source=copyApp®ion=$r&webp=1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user