mirror of
https://github.com/tachiyomiorg/tachiyomi-extensions-inspector.git
synced 2025-01-12 00:39:07 +01:00
uninstalling extensions implemented
This commit is contained in:
parent
99316f4bd5
commit
832c224ed4
@ -17,6 +17,7 @@ import ir.armor.tachidesk.util.getSource
|
|||||||
import ir.armor.tachidesk.util.getSourceList
|
import ir.armor.tachidesk.util.getSourceList
|
||||||
import ir.armor.tachidesk.util.getThumbnail
|
import ir.armor.tachidesk.util.getThumbnail
|
||||||
import ir.armor.tachidesk.util.installAPK
|
import ir.armor.tachidesk.util.installAPK
|
||||||
|
import ir.armor.tachidesk.util.removeExtension
|
||||||
import ir.armor.tachidesk.util.sourceFilters
|
import ir.armor.tachidesk.util.sourceFilters
|
||||||
import ir.armor.tachidesk.util.sourceGlobalSearch
|
import ir.armor.tachidesk.util.sourceGlobalSearch
|
||||||
import ir.armor.tachidesk.util.sourceSearch
|
import ir.armor.tachidesk.util.sourceSearch
|
||||||
@ -79,11 +80,20 @@ class Main {
|
|||||||
|
|
||||||
app.get("/api/v1/extension/install/:apkName") { ctx ->
|
app.get("/api/v1/extension/install/:apkName") { ctx ->
|
||||||
val apkName = ctx.pathParam("apkName")
|
val apkName = ctx.pathParam("apkName")
|
||||||
println(apkName)
|
println("installing $apkName")
|
||||||
|
|
||||||
ctx.status(
|
ctx.status(
|
||||||
installAPK(apkName)
|
installAPK(apkName)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.get("/api/v1/extension/uninstall/:apkName") { ctx ->
|
||||||
|
val apkName = ctx.pathParam("apkName")
|
||||||
|
println("uninstalling $apkName")
|
||||||
|
removeExtension(apkName)
|
||||||
|
ctx.status(200)
|
||||||
|
}
|
||||||
|
|
||||||
app.get("/api/v1/source/list") { ctx ->
|
app.get("/api/v1/source/list") { ctx ->
|
||||||
ctx.json(getSourceList())
|
ctx.json(getSourceList())
|
||||||
}
|
}
|
||||||
|
@ -66,28 +66,28 @@ fun getManga(mangaId: Int, proxyThumbnail: Boolean = true): MangaDataClass {
|
|||||||
println("${mangaEntry[MangaTable.title]} is initialized")
|
println("${mangaEntry[MangaTable.title]} is initialized")
|
||||||
println("${mangaEntry[MangaTable.thumbnail_url]}")
|
println("${mangaEntry[MangaTable.thumbnail_url]}")
|
||||||
MangaDataClass(
|
MangaDataClass(
|
||||||
mangaId,
|
mangaId,
|
||||||
mangaEntry[MangaTable.sourceReference].value,
|
mangaEntry[MangaTable.sourceReference].value,
|
||||||
|
|
||||||
mangaEntry[MangaTable.url],
|
mangaEntry[MangaTable.url],
|
||||||
mangaEntry[MangaTable.title],
|
mangaEntry[MangaTable.title],
|
||||||
if (proxyThumbnail) proxyThumbnailUrl(mangaId) else mangaEntry[MangaTable.thumbnail_url],
|
if (proxyThumbnail) proxyThumbnailUrl(mangaId) else mangaEntry[MangaTable.thumbnail_url],
|
||||||
|
|
||||||
true,
|
true,
|
||||||
|
|
||||||
mangaEntry[MangaTable.artist],
|
mangaEntry[MangaTable.artist],
|
||||||
mangaEntry[MangaTable.author],
|
mangaEntry[MangaTable.author],
|
||||||
mangaEntry[MangaTable.description],
|
mangaEntry[MangaTable.description],
|
||||||
mangaEntry[MangaTable.genre],
|
mangaEntry[MangaTable.genre],
|
||||||
MangaStatus.valueOf(mangaEntry[MangaTable.status]).name,
|
MangaStatus.valueOf(mangaEntry[MangaTable.status]).name,
|
||||||
)
|
)
|
||||||
} else { // initialize manga
|
} else { // initialize manga
|
||||||
val source = getHttpSource(mangaEntry[MangaTable.sourceReference].value)
|
val source = getHttpSource(mangaEntry[MangaTable.sourceReference].value)
|
||||||
val fetchedManga = source.fetchMangaDetails(
|
val fetchedManga = source.fetchMangaDetails(
|
||||||
SManga.create().apply {
|
SManga.create().apply {
|
||||||
url = mangaEntry[MangaTable.url]
|
url = mangaEntry[MangaTable.url]
|
||||||
title = mangaEntry[MangaTable.title]
|
title = mangaEntry[MangaTable.title]
|
||||||
}
|
}
|
||||||
).toBlocking().first()
|
).toBlocking().first()
|
||||||
|
|
||||||
// update database
|
// update database
|
||||||
@ -97,25 +97,25 @@ fun getManga(mangaId: Int, proxyThumbnail: Boolean = true): MangaDataClass {
|
|||||||
|
|
||||||
// mangaEntry = MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!!
|
// mangaEntry = MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!!
|
||||||
val newThumbnail =
|
val newThumbnail =
|
||||||
if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url!!.isNotEmpty()) {
|
if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url!!.isNotEmpty()) {
|
||||||
fetchedManga.thumbnail_url
|
fetchedManga.thumbnail_url
|
||||||
} else mangaEntry[MangaTable.thumbnail_url]
|
} else mangaEntry[MangaTable.thumbnail_url]
|
||||||
|
|
||||||
MangaDataClass(
|
MangaDataClass(
|
||||||
mangaId,
|
mangaId,
|
||||||
mangaEntry[MangaTable.sourceReference].value,
|
mangaEntry[MangaTable.sourceReference].value,
|
||||||
|
|
||||||
mangaEntry[MangaTable.url],
|
mangaEntry[MangaTable.url],
|
||||||
mangaEntry[MangaTable.title],
|
mangaEntry[MangaTable.title],
|
||||||
if (proxyThumbnail) proxyThumbnailUrl(mangaId) else newThumbnail,
|
if (proxyThumbnail) proxyThumbnailUrl(mangaId) else newThumbnail,
|
||||||
|
|
||||||
true,
|
true,
|
||||||
|
|
||||||
fetchedManga.artist,
|
fetchedManga.artist,
|
||||||
fetchedManga.author,
|
fetchedManga.author,
|
||||||
fetchedManga.description,
|
fetchedManga.description,
|
||||||
fetchedManga.genre,
|
fetchedManga.genre,
|
||||||
MangaStatus.valueOf(fetchedManga.status).name,
|
MangaStatus.valueOf(fetchedManga.status).name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,8 +135,8 @@ fun getThumbnail(mangaId: Int): Pair<InputStream, String> {
|
|||||||
if (potentialCache != null) {
|
if (potentialCache != null) {
|
||||||
println("using cached thumbnail file")
|
println("using cached thumbnail file")
|
||||||
return@transaction Pair(
|
return@transaction Pair(
|
||||||
pathToInputStream(potentialCache),
|
pathToInputStream(potentialCache),
|
||||||
"image/${potentialCache.substringAfter("$mangaId.")}"
|
"image/${potentialCache.substringAfter("$mangaId.")}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ fun getThumbnail(mangaId: Int): Pair<InputStream, String> {
|
|||||||
}
|
}
|
||||||
println(thumbnailUrl)
|
println(thumbnailUrl)
|
||||||
val response = source.client.newCall(
|
val response = source.client.newCall(
|
||||||
GET(thumbnailUrl, source.headers)
|
GET(thumbnailUrl, source.headers)
|
||||||
).execute()
|
).execute()
|
||||||
|
|
||||||
println(response.code)
|
println(response.code)
|
||||||
@ -161,8 +161,8 @@ fun getThumbnail(mangaId: Int): Pair<InputStream, String> {
|
|||||||
writeStream(response.body!!.byteStream(), filePath)
|
writeStream(response.body!!.byteStream(), filePath)
|
||||||
|
|
||||||
return@transaction Pair(
|
return@transaction Pair(
|
||||||
pathToInputStream(filePath),
|
pathToInputStream(filePath),
|
||||||
contentType
|
contentType
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
throw Exception("request error! ${response.code}")
|
throw Exception("request error! ${response.code}")
|
||||||
|
@ -17,6 +17,7 @@ import kotlinx.coroutines.runBlocking
|
|||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okio.buffer
|
import okio.buffer
|
||||||
import okio.sink
|
import okio.sink
|
||||||
|
import org.jetbrains.exposed.sql.deleteWhere
|
||||||
import org.jetbrains.exposed.sql.insert
|
import org.jetbrains.exposed.sql.insert
|
||||||
import org.jetbrains.exposed.sql.select
|
import org.jetbrains.exposed.sql.select
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
@ -32,8 +33,8 @@ fun installAPK(apkName: String): Int {
|
|||||||
val dirPathWithoutType = "${Config.extensionsRoot}/$fileNameWithoutType"
|
val dirPathWithoutType = "${Config.extensionsRoot}/$fileNameWithoutType"
|
||||||
|
|
||||||
// check if we don't have the dex file already downloaded
|
// check if we don't have the dex file already downloaded
|
||||||
val dexPath = "${Config.extensionsRoot}/$fileNameWithoutType.jar"
|
val jarPath = "${Config.extensionsRoot}/$fileNameWithoutType.jar"
|
||||||
if (!File(dexPath).exists()) {
|
if (!File(jarPath).exists()) {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
val api = ExtensionGithubApi()
|
val api = ExtensionGithubApi()
|
||||||
val apkToDownload = api.getApkUrl(extensionRecord)
|
val apkToDownload = api.getApkUrl(extensionRecord)
|
||||||
@ -130,3 +131,21 @@ private fun downloadAPKFile(url: String, apkPath: String) {
|
|||||||
sink.writeAll(response.body!!.source())
|
sink.writeAll(response.body!!.source())
|
||||||
sink.close()
|
sink.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeExtension(pkgName: String) {
|
||||||
|
val extensionRecord = getExtensionList(true).first { it.apkName == pkgName }
|
||||||
|
val fileNameWithoutType = pkgName.substringBefore(".apk")
|
||||||
|
val jarPath = "${Config.extensionsRoot}/$fileNameWithoutType.jar"
|
||||||
|
transaction {
|
||||||
|
val extensionId = ExtensionsTable.select { ExtensionsTable.name eq extensionRecord.name }.first()[ExtensionsTable.id]
|
||||||
|
|
||||||
|
SourceTable.deleteWhere { SourceTable.extension eq extensionId }
|
||||||
|
ExtensionsTable.update({ ExtensionsTable.name eq extensionRecord.name }) {
|
||||||
|
it[ExtensionsTable.installed] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File(jarPath).exists()) {
|
||||||
|
File(jarPath).delete()
|
||||||
|
}
|
||||||
|
}
|
@ -46,7 +46,7 @@ export default function ExtensionCard(props: IProps) {
|
|||||||
name, lang, versionName, iconUrl, installed, apkName,
|
name, lang, versionName, iconUrl, installed, apkName,
|
||||||
},
|
},
|
||||||
} = props;
|
} = props;
|
||||||
const [installedState, setInstalledState] = useState<string>((installed ? 'installed' : 'install'));
|
const [installedState, setInstalledState] = useState<string>((installed ? 'uninstall' : 'install'));
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const langPress = lang === 'all' ? 'All' : lang.toUpperCase();
|
const langPress = lang === 'all' ? 'All' : lang.toUpperCase();
|
||||||
@ -54,10 +54,25 @@ export default function ExtensionCard(props: IProps) {
|
|||||||
function install() {
|
function install() {
|
||||||
setInstalledState('installing');
|
setInstalledState('installing');
|
||||||
fetch(`http://127.0.0.1:4567/api/v1/extension/install/${apkName}`).then(() => {
|
fetch(`http://127.0.0.1:4567/api/v1/extension/install/${apkName}`).then(() => {
|
||||||
setInstalledState('installed');
|
setInstalledState('uninstall');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function uninstall() {
|
||||||
|
setInstalledState('uninstalling');
|
||||||
|
fetch(`http://127.0.0.1:4567/api/v1/extension/uninstall/${apkName}`).then(() => {
|
||||||
|
setInstalledState('install');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleButtonClick() {
|
||||||
|
if (installedState === 'install') {
|
||||||
|
install();
|
||||||
|
} else {
|
||||||
|
uninstall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardContent className={classes.root}>
|
<CardContent className={classes.root}>
|
||||||
@ -80,7 +95,7 @@ export default function ExtensionCard(props: IProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button variant="outlined" onClick={() => install()}>{installedState}</Button>
|
<Button variant="outlined" onClick={() => handleButtonClick()}>{installedState}</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user