mirror of
https://git.um-react.app/um/um-react.git
synced 2025-11-28 11:33:02 +00:00
feat: add support for kuwo ios ekey db
This commit is contained in:
@@ -3,7 +3,7 @@ import { objectify } from 'radash';
|
||||
|
||||
export function productionKeyToStaging<S, P extends Record<string, unknown>>(
|
||||
src: P,
|
||||
make: (k: keyof P, v: P[keyof P]) => null | S
|
||||
make: (k: keyof P, v: P[keyof P]) => null | S,
|
||||
): S[] {
|
||||
const result: S[] = [];
|
||||
for (const [key, value] of Object.entries(src)) {
|
||||
@@ -31,7 +31,7 @@ export const qmc2StagingToProductionKey = (key: StagingQMCv2Key) => key.name.nor
|
||||
export const qmc2StagingToProductionValue = (key: StagingQMCv2Key) => key.ekey.trim();
|
||||
export const qmc2ProductionToStaging = (
|
||||
key: keyof ProductionQMCv2Keys,
|
||||
value: ProductionQMCv2Keys[keyof ProductionQMCv2Keys]
|
||||
value: ProductionQMCv2Keys[keyof ProductionQMCv2Keys],
|
||||
): StagingQMCv2Key => {
|
||||
return {
|
||||
id: nanoid(),
|
||||
@@ -44,7 +44,13 @@ export const qmc2ProductionToStaging = (
|
||||
|
||||
export interface StagingKWMv2Key {
|
||||
id: string;
|
||||
/**
|
||||
* Resource ID
|
||||
*/
|
||||
rid: string;
|
||||
/**
|
||||
* Quality String
|
||||
*/
|
||||
quality: string;
|
||||
ekey: string;
|
||||
}
|
||||
@@ -58,16 +64,17 @@ export const parseKwm2ProductionKey = (key: string): null | { rid: string; quali
|
||||
|
||||
return { rid, quality };
|
||||
};
|
||||
export const kwm2StagingToProductionKey = (key: StagingKWMv2Key) => `${key.rid}-${key.quality}`;
|
||||
export const kwm2StagingToProductionKey = (key: StagingKWMv2Key) => `${key.rid}-${key.quality.replace(/[\D]/g, '')}`;
|
||||
export const kwm2StagingToProductionValue = (key: StagingKWMv2Key) => key.ekey;
|
||||
export const kwm2ProductionToStaging = (
|
||||
key: keyof ProductionKWMv2Keys,
|
||||
value: ProductionKWMv2Keys[keyof ProductionKWMv2Keys]
|
||||
value: ProductionKWMv2Keys[keyof ProductionKWMv2Keys],
|
||||
): null | StagingKWMv2Key => {
|
||||
if (typeof value !== 'string') return null;
|
||||
|
||||
const parsed = parseKwm2ProductionKey(key);
|
||||
if (!parsed) return null;
|
||||
const { quality, rid } = parsed;
|
||||
|
||||
return { id: nanoid(), rid: parsed.rid, quality: parsed.quality, ekey: value };
|
||||
return { id: nanoid(), rid, quality, ekey: value };
|
||||
};
|
||||
|
||||
33
src/features/settings/panels/KWMv2/InstructionsIOS.tsx
Normal file
33
src/features/settings/panels/KWMv2/InstructionsIOS.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Code, ListItem, OrderedList, Text, chakra } from '@chakra-ui/react';
|
||||
|
||||
const KUWO_IOS_DIR = '/var/mobile/Containers/Data/Application/<酷我数据目录>/mmkv';
|
||||
|
||||
export function InstructionsIOS() {
|
||||
return (
|
||||
<>
|
||||
<Text>你需要越狱来访问 iOS 应用的私有数据。</Text>
|
||||
<Text>
|
||||
⚠️ 请注意,越狱通常意味着你的设备
|
||||
<chakra.span color="red.400">将失去保修资格</chakra.span>。
|
||||
</Text>
|
||||
<OrderedList>
|
||||
<ListItem>
|
||||
<Text>
|
||||
访问设备的这个目录:
|
||||
<Code wordBreak="break-word">{KUWO_IOS_DIR}</Code>
|
||||
</Text>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Text>
|
||||
提取密钥数据库文件 <Code>kw_ekey</Code> 至浏览器可访问的目录,如下载目录。
|
||||
</Text>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Text>
|
||||
提交刚刚提取的 <Code>kw_ekey</Code> 密钥数据库。
|
||||
</Text>
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
import { Tab, TabList, TabPanel, TabPanels } from '@chakra-ui/react';
|
||||
import { AndroidADBPullInstruction } from '~/components/AndroidADBPullInstruction/AndroidADBPullInstruction';
|
||||
import { InstructionsPC } from './InstructionsPC';
|
||||
import { InstructionsIOS } from './InstructionsIOS';
|
||||
|
||||
export function KWMv2AllInstructions() {
|
||||
return (
|
||||
<>
|
||||
<TabList>
|
||||
<Tab>安卓</Tab>
|
||||
<Tab>iOS</Tab>
|
||||
<Tab>Windows</Tab>
|
||||
</TabList>
|
||||
<TabPanels flex={1} overflow="auto">
|
||||
@@ -16,6 +18,9 @@ export function KWMv2AllInstructions() {
|
||||
file="cn.kuwo.player.mmkv.defaultconfig"
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<InstructionsIOS />
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<InstructionsPC />
|
||||
</TabPanel>
|
||||
|
||||
@@ -22,7 +22,7 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import { MdAdd, MdDeleteForever, MdExpandMore, MdFileUpload } from 'react-icons/md';
|
||||
|
||||
import { ImportSecretModal } from '~/components/ImportSecretModal';
|
||||
import { MMKVParser } from '~/util/MMKVParser';
|
||||
import { parseAndroidKuwoEKey, parseIosKuwoEKey } from '~/util/mmkv/kuwo';
|
||||
|
||||
import { kwm2AddKey, kwm2ClearKeys, kwm2ImportKeys } from '../settingsSlice';
|
||||
import { selectStagingKWMv2Keys } from '../settingsSelector';
|
||||
@@ -41,9 +41,11 @@ export function PanelKWMv2Key() {
|
||||
const handleSecretImport = async (file: File) => {
|
||||
let keys: Omit<StagingKWMv2Key, 'id'>[] | null = null;
|
||||
if (/cn\.kuwo\.player\.mmkv/i.test(file.name)) {
|
||||
const fileBuffer = await file.arrayBuffer();
|
||||
keys = MMKVParser.parseKuwoEKey(new DataView(fileBuffer));
|
||||
keys = parseAndroidKuwoEKey(new DataView(await file.arrayBuffer()));
|
||||
} else if (/kw_ekey/.test(file.name)) {
|
||||
keys = parseIosKuwoEKey(new DataView(await file.arrayBuffer()));
|
||||
}
|
||||
|
||||
if (keys?.length === 0) {
|
||||
toast({
|
||||
title: '未导入密钥',
|
||||
|
||||
Reference in New Issue
Block a user