写作绅士,读作丧尸 X岛揭示板
顺猴者昌 逆猴者亡 首页版规 |用户系统 |移动客户端下载 | 丧尸路标 | | 常用图串及路标 | 请关注 官方公众号:【X岛揭示板】 官方微博: 【@X岛极速版】| 人,是会思考的芦苇
常用串:·豆知识·跑团板聊天室·公告汇总串·X岛路标

No.62048096 - 无标题 - 技术宅


回应模式
No.62048096
名 称
E-mail
标题
颜文字
正文
附加图片
•程序语言、压制投稿、视频制作以及各计算机领域的技术问题
•我觉得还是CSDN靠谱一点
•本版发文间隔为15秒。

无标题 无名氏 2024-04-16(二)05:45:25 ID:83YvGLK [举报] [订阅] [只看PO] No.62048096 [回应] 管理
有人知道Tachiyomi的记录导出为json的方法吗?备份文件是 .tachibk,尝试直接更改扩展名为 .json,乱码;直接更改为 .zip,居然能看到部分中文,但是打开会卡住只能强行退出浏览app
Tips 无名氏 2099-01-01 00:00:01 ID:Tips超级公民 [举报] No.9999999 管理
  _ _
  ( ゚_゚)
/ (⁰  )╲/
无标题 无名氏 2024-04-16(二)07:03:25 ID:83YvGLK (PO主) [举报] No.62048212 管理
>>No.62048096
话说 .zip 居然能作为文件打开而且漫画名是正常的也只有漫画名是正常的其它全部乱码……

这样特殊的扩展名文件是怎么得来的?以前用过一段时间 全是漫画 app,备份文件扩展名也是专属的,是可以自己定义扩展名吗?然后打卡乱码是因为加密了吗?
无标题 无名氏 2024-04-16(二)08:18:22 ID:CzzTJVo [举报] No.62048536 管理
没加密,用的kotlinx serialization,格式是protobuf然后套了一层gzip,你知道上面的名词具体是什么的话转成json应该不成问题

代码在这里
https://github.com/mihonapp/mihon/blob/main/app%2Fsrc%2Fmain%2Fjava%2Feu%2Fkanade%2Ftachiyomi%2Fdata%2Fbackup%2Fcreate%2FBackupCreator.kt#L87-L99
无标题 无名氏 2024-04-16(二)08:30:58 ID:83YvGLK (PO主) [举报] No.62048626 管理
>>No.62048536
虽然有听说 Tachiyomi 作者转去做 mihon 了,以为是从头开始,没想到直接用 Tachiyomi 的现成的包啊,,
你提到的名词一个都不懂,对数据处理相关的经验只有 json, csv, mangodb, mysql 不过好歹有头绪了,谢谢!
无标题 无名氏 2024-04-16(二)08:32:59 ID:83YvGLK (PO主) [举报] No.62048643 管理
>>No.62048626
不是处理,是存储*
无标题 无名氏 2024-04-16(二)08:54:47 ID:CzzTJVo [举报] No.62048803 管理
>>No.62048626
并不是作者转去做mihon了,而是tachiyomi的原作者(仓库拥有者)不再维护,mihon是tachiyomi的其中一个活跃开发者重新搞的一个分支版本,当前代码基本上是一样的
无标题 无名氏 2024-04-17(三)01:11:17 ID:83YvGLK (PO主) [举报] No.62060178 管理
>>No.62048536
去了解了一下,但是还是完全没有头绪,不懂kotlin,问chatgpt是否可以直接把.tachibk解压缩gzip从protobuf转为json,但是遇到了很多错误,不知怎么解决……
无标题 无名氏 2024-04-17(三)01:13:44 ID:83YvGLK (PO主) [举报] No.62060192 管理
>>No.62048803
去搜了缘由没想到是因为版权,唉!
无标题 无名氏 2024-04-17(三)01:22:28 ID:83YvGLK (PO主) [举报] No.62060237 管理
>>No.62060178
目前进展:mac m1试过用 gradle for java创建项目,安装了kotlin 和 gradle后用gradle创建了一个 kotlin项目,看官方文档学会了进行serializable和 json之间的转换
目前疑问:文件读取只会用java,是用java的io.file读入.tachibk然后操作?但是怎么解码?是要用Tachiyomi里定义的decode类吗?是不是要在我用gradle创建的kotlin项目里导入完整的Tachiyomi项目然后引用?可是看到里面用了很多安卓相关的库,我不需要安卓,就只想做到那种,终端一行命令加上文件名然后就输出json文件,研究了半天源码,看不懂,卡在这了……
无标题 无名氏 2024-04-18(四)14:10:17 ID:4oFnDNS [举报] No.62076764 管理
>>No.62048536
这个肥哥不是说了嘛,你先解压缩这个gzip文件(Java有库可以直接读)得到里面的protobuf 二进制文件,然后去找Protobuf 的Java库,用它的reflection 来读里面的各个field就可以了。Protobuf 一般要原来的schema去transpile成对应的Java 代码才能读的,但是你这种情况要不就去app源码里面找Protobuf schema ,要不就直接用reflection。无论哪种方法,Protobuf 库有直接序列化成json的方法的,直接用就行
无标题 无名氏 2024-04-18(四)14:11:38 ID:4oFnDNS [举报] No.62076777 管理
gzip解压缩部分也可以直接用gzip -d 或者zcat或者gunzip 来解压,省去你写解压部分的代码
无标题 无名氏 2024-04-18(四)18:05:26 ID:CzzTJVo [举报] No.62079375 管理
>>No.62060237
你想简单粗暴就是直接git拉tachiyomi代码然后导入gradle项目,然后直接整个main方法调用现成的decode就完了,可能需要处理下Android包的问题
https://github.com/mihonapp/mihon/blob/main/app%2Fsrc%2Fmain%2Fjava%2Feu%2Fkanade%2Ftachiyomi%2Fdata%2Fbackup%2FBackupDecoder.kt
无标题 无名氏 2024-04-18(四)19:40:12 ID:MK1koCU [举报] No.62080352 管理
>>No.62076777
尝试了但没有成功。
备份文件的扩展名是 .tachibk,如果直接用 gzip -d *.tachibk 会提示 unknown suffix -- ignored,所以手动改扩展名为 .gz,得到了一个没有扩展名的二进制文件,然后从源码创建了以下 .protobuf 文件:
syntax = "proto3";

message Manga {
string url = 1;
string title = 2;
string artist = 3;
string author = 4;
string description = 5;
string genre = 6;
int32 status = 7;
string thumbnailUrl = 8;
bool favorite = 9;
string source = 10;
int64 dateAdded = 11;
int64 viewerFlags = 12;
int64 chapterFlags = 13;
string updateStrategy = 14;
int64 lastModifiedAt = 15;
int64 favoriteModifiedAt = 16;
int32 version = 17;
}

然后用 protoc --decode Manga manga.proto < myprotobin
但是得到:
[libprotobuf ERROR /tmp/protobuf-20230319-70010-1pqiw5q/protobuf-21.12/src/google/protobuf/wire_format_lite.cc:618] String field 'Manga.url' contains invalid UTF-8 data when parsing a protocol buffer. Use the 'bytes' type if you intend to send raw bytes.
Failed to parse input.
所以我修改 .protobuf 文件的 url 类型为 byte,但是得到的内容很短(明明有几千条记录),如下:
101 {
1: "\351\246\231\351\246\231\350\205\220\345\256\205"
2: 1471112097704477289
}
101 {
1: "Cartoon18"
2: 28664779574072063
}
绝对是没有解码成功,直接用 vscode 打开二进制文件还能看到中文的漫画标题呢,可是问题出在哪儿?

实在是没有思路了……
无标题 无名氏 2024-04-18(四)19:42:43 ID:83YvGLK (PO主) [举报] No.62080386 管理
>>No.62079375
我看到哪个解码函数了,但是不懂安卓所以不知道怎么处理相关的包,对java了解实际上也不多,感觉还不如上面那个老哥的方法更容易些……
无标题 无名氏 2024-04-18(四)19:44:00 ID:83YvGLK (PO主) [举报] No.62080402 管理
>>No.62080352
不是 .protobuf 文件,是 .proto 文件,以及 url 的类型 string会给错,byte和 bytes结果也都不大对……
无标题 无名氏 2024-04-18(四)19:44:43 ID:83YvGLK (PO主) [举报] No.62080411 管理
>>No.62080352
艾玛饼切错了!
无标题 无名氏 2024-04-18(四)20:02:28 ID:83YvGLK (PO主) [举报] No.62080645 管理
目前最大的疑问是解压缩 gzip,明明扩展名不是 gzip文件,是不是手动修改扩展名这一步出了问题?
无标题 无名氏 2024-04-19(五)00:33:42 ID:CzzTJVo [举报] No.62083994 管理
我电脑没在身边,帮你问了下ai

Here's a Python implementation of a backup file decoder based on the provided Kotlin files. This implementation assumes that the backup file is in Protocol Buffers format and uses the `protobuf` library to decode it.

```python
import gzip
import protobuf

# Define the protobuf message classes
BackupManga = protobuf.Descriptors.BackupManga
BackupChapter = protobuf.Descriptors.BackupChapter
BackupCategory = protobuf.Descriptors.BackupCategory
BackupTracking = protobuf.Descriptors.BackupTracking
BackupHistory = protobuf.Descriptors.BackupHistory
BackupSource = protobuf.Descriptors.BackupSource
BackupPreference = protobuf.Descriptors.BackupPreference
BackupSourcePreferences = protobuf.Descriptors.BackupSourcePreferences
Backup = protobuf.Descriptors.Backup

def decode_backup(backup_file_path):
with open(backup_file_path, 'rb') as f:
content = f.read()

# Check if the file is gzipped
if content[:2] == b'\x1f\x8b':
content = gzip.decompress(content)

# Parse the protobuf message
backup = Backup.FromString(content)

# Process the backup data
print(f"Number of manga: {len(backup.backupManga)}")
for manga in backup.backupManga:
print(f"Manga: {manga.title}")
for chapter in manga.chapters:
print(f" Chapter: {chapter.name}")

print(f"Number of categories: {len(backup.backupCategories)}")
for category in backup.backupCategories:
print(f"Category: {category.name}")

print(f"Number of tracking entries: {sum(len(manga.tracking) for manga in backup.backupManga)}")
for manga in backup.backupManga:
for tracking in manga.tracking:
print(f"Tracking: {tracking.title}")

print(f"Number of history entries: {sum(len(manga.history) for manga in backup.backupManga)}")
for manga in backup.backupManga:
for history in manga.history:
print(f"History: {history.url}")

print(f"Number of sources: {len(backup.backupSources)}")
for source in backup.backupSources:
print(f"Source: {source.name}")

print(f"Number of preferences: {len(backup.backupPreferences)}")
for pref in backup.backupPreferences:
print(f"Preference: {pref.key} = {pref.value}")

print(f"Number of source preferences: {len(backup.backupSourcePreferences)}")
for source_prefs in backup.backupSourcePreferences:
print(f"Source preferences for {source_prefs.sourceKey}:")
for pref in source_prefs.prefs:
print(f" {pref.key} = {pref.value}")

if __name__ == "__main__":
backup_file_path = input("Enter the path to the backup file: ")
decode_backup(backup_file_path)
```

This program defines the Protobuf message classes based on the Kotlin classes provided. The `decode_backup` function takes the path to the backup file as input, opens the file, decompresses it if it's gzipped, and parses the Protobuf message using the `protobuf` library.

After parsing the backup data, the function processes and prints the various components of the backup, such as manga, chapters, categories, tracking entries, history entries, sources, preferences, and source preferences.

Note that you'll need to have the `protobuf` library installed to run this program. You can install it using `pip install protobuf`.
无标题 无名氏 2024-04-19(五)00:34:39 ID:CzzTJVo [举报] No.62084003 管理
> Give me an example of the descriptor file.

Unfortunately, I don't have access to the actual Protobuf descriptor file for the data structures defined in the provided Kotlin files. However, I can provide an example of what the descriptor file might look like based on the structure of the data classes.

```protobuf
syntax = "proto3";

package eu.kanade.tachiyomi.data.backup.models;

message BackupManga {
int64 source = 1;
string url = 2;
string title = 3;
string artist = 4;
string author = 5;
string description = 6;
repeated string genre = 7;
int32 status = 8;
string thumbnailUrl = 9;
int64 dateAdded = 13;
int32 viewer = 14;
repeated BackupChapter chapters = 16;
repeated int64 categories = 17;
repeated BackupTracking tracking = 18;
bool favorite = 100;
int32 chapterFlags = 101;
repeated BrokenBackupHistory brokenHistory = 102;
int32 viewerFlags = 103;
repeated BackupHistory history = 104;
int32 updateStrategy = 105;
int64 lastModifiedAt = 106;
int64 favoriteModifiedAt = 107;
repeated string excludedScanlators = 108;
int64 version = 109;
}

message BackupChapter {
string url = 1;
string name = 2;
string scanlator = 3;
bool read = 4;
bool bookmark = 5;
int64 lastPageRead = 6;
int64 dateFetch = 7;
int64 dateUpload = 8;
float chapterNumber = 9;
int64 sourceOrder = 10;
int64 lastModifiedAt = 11;
int64 version = 12;
}

// ... other message definitions for BackupCategory, BackupTracking, etc.

message Backup {
repeated BackupManga backupManga = 1;
repeated BackupCategory backupCategories = 2;
repeated BrokenBackupSource backupBrokenSources = 100;
repeated BackupSource backupSources = 101;
repeated BackupPreference backupPreferences = 104;
repeated BackupSourcePreferences backupSourcePreferences = 105;
}
```

This is a simplified example of what the Protobuf descriptor file might look like based on the data structures in the provided Kotlin files. Note that the field numbers and message names are derived from the Kotlin code, but the actual structure and naming conventions may differ in the real descriptor file.

In this example, each data class is represented as a Protobuf message, and the fields within each class are defined with their corresponding data types and field numbers. Nested classes are represented as nested messages within their parent message.
无标题 无名氏 2024-04-19(五)00:35:34 ID:CzzTJVo [举报] No.62084009 管理
照着把剩下的定义文件补充完应该就行

UP主: