import { useAppDispatch, useAppSelector } from '~/hooks'; import { ExtLink } from '~/components/ExtLink'; import { ChangeEvent, ClipboardEvent, useId } from 'react'; import { VQuote } from '~/components/HelpText/VQuote'; import { selectStagingQtfmAndroidKey } from '../settingsSelector'; import { qtfmAndroidUpdateKey } from '../settingsSlice'; import { workerClientBus } from '~/decrypt-worker/client.ts'; import { GetQingTingFMDeviceKeyPayload } from '~/decrypt-worker/types.ts'; import { DECRYPTION_WORKER_ACTION_NAME } from '~/decrypt-worker/constants.ts'; import { Ruby } from '~/components/Ruby'; import { HiWord } from '~/components/HelpText/HiWord'; const QTFM_DEVICE_ID_URL = 'https://github.com/parakeet-rs/qtfm-device-id/releases/latest'; export function PanelQingTing() { const dispatch = useAppDispatch(); const secretKey = useAppSelector(selectStagingQtfmAndroidKey); const setSecretKey = (secretKey: string) => { dispatch(qtfmAndroidUpdateKey({ deviceKey: secretKey })); }; const handleDataPaste = (e: ClipboardEvent) => { const plainText = e.clipboardData.getData('text/plain'); const matchDeviceSecret = plainText.match(/^DEVICE_SECRET: ([0-9a-fA-F]+)/m); if (matchDeviceSecret) { e.preventDefault(); setSecretKey(matchDeviceSecret[1]); return; } const dataMap = Object.create(null); for (const [, key, value] of plainText.matchAll(/^(PRODUCT|DEVICE|MANUFACTURER|BRAND|BOARD|MODEL): (.+)/gim)) { dataMap[key.toLowerCase()] = value; } const { product, device, manufacturer, brand, board, model } = dataMap; if (product && device && manufacturer && brand && board && model) { e.preventDefault(); workerClientBus .request( DECRYPTION_WORKER_ACTION_NAME.QINGTING_FM_GET_DEVICE_KEY, dataMap, ) .then(setSecretKey) .catch((err) => { alert(`生成设备密钥时发生错误: ${err}`); }); } }; const handleDataInput = (e: ChangeEvent) => { setSecretKey(e.target.value); }; const idSecretKey = useId(); return (

蜻蜓 FM

蜻蜓 FM的安卓版本需要获取设备密钥,并以此来生成解密密钥。

粘贴含有设备密钥的信息的内容时将自动提取密钥(如通过 qtfm-device-id 获取的设备信息),不需要 root。

注意事项

  • 下载的文件位于 [内部储存]/ Android/ data/ fm.qingting.qtradio/ files/Music/

    • 你可能需要使用有 特权 的文件浏览器访问。

  • 音频文件文件名为「.p~!」前缀。

  • 因为解密密钥与文件名相关,因此解密前请不要更改文件名。

); }