Skip to content

Commit

Permalink
Merge pull request #374 from lovegaoshi/dev
Browse files Browse the repository at this point in the history
feat: qqQrc
  • Loading branch information
lovegaoshi authored Apr 17, 2024
2 parents 5000004 + 2e59d12 commit 854e587
Show file tree
Hide file tree
Showing 12 changed files with 922 additions and 243 deletions.
10 changes: 10 additions & 0 deletions __tests__/lyricfetch/qqqrc.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import qqLrcFetch from '../../src/utils/lrcfetch/qqqrc';
test('qq lrc', async () => {
const lrcOptions = await qqLrcFetch.getLrcOptions('wake');
expect(lrcOptions[0].lrc).not.toBeUndefined();

await new Promise(resolve => setTimeout(resolve, 1000));

const lrcContent = await qqLrcFetch.getLyric('5023727');
expect(lrcContent.length).not.toBe(0);
}, 29999);
8 changes: 8 additions & 0 deletions __tests__/lyricfetch/qrcDecode.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { decodeQrc } from '../../src/utils/lrcfetch/qrcdecoder';
test('qq lrc decode', async () => {
const result = decodeQrc(
'C7B616DAB7EDB954BD29849CDE385DFC55159BB06A2CD4BE6096BE42643B64045E75F2A0D7C092CB3C7D4F43D33F256CF6D2E9373250DEB2145F21D605EC95A46D8D5D14326497DE8F7496E1CDFCF443DFEC00661A574969CC4C9AFB28F69FE5EC80EA79D32C58449DC757B887BBFFD71715D58D9AAD322F0BAC8AE84791640FD823896A64DA8406905946D6BD3B40BB0838D3333E084CA0FDE95EEBF4FE12E29CB7952796483F04BFFC175909337E638FF7C12E06BE1AD19B7BFEA1C86196BB3B484BC6FD17F0BD49ED107679D6B47873247DFB267BE67B72F1879A3267128ABB520BD8B8D5F3E1054A925F9F337D018B51446B8C24DD2B17D1E49250D4A40A6C7A6B918028DCE85F645213CB679B51EB91CE444AABD0ADA1475916D1CB6861C922D3D329A865F25E5B2498B9DF1A7A582757767F3DBDA1CCD65F3FDE3EAD04B54D8938EAC907BE5E4E717F9BF51F3AB84B38AFB71DCFC8627F9EDAAEC11BC2926291721FC81EB21DA7103D3F10E456807F09452C91D9924A4C5EF62196AF37327586B7C578837528FC73F7FE4664A73E4E0F8421A93D06D67F5C8C6D75251FD284CC53E7B3ECFD6C153DE1A6E12CC1E78824454BCF894CC4B9253AB1E61768015D05EDDF680AEA80A5F2F80B17A721CC7AF951C1441881541B12A2DD229E02F21290606A8A0452D4F7CD0C128D1437E3F65F93EB1F92EF0057F579EF82B37C87915EE56A218E8907C11869121AF2ECF7A302C875BFEB5BC64FABB0D3E3C5794B3D6BBEF939AE7435527DFEDD15E5C02857B201394F70840FA78B8A7D6A79092DA8A40C79DC6B9ECA3A72A7ACA12F18103F77B146AA7D8A09A3A6DFF95FA14EFBD044D1E9A149D764FF4E9F93BD253565BCC6978E513A60C35894402F0EA046DF4A6417DBBCFFDB17F3734E467859433323913A840E6EFDA920A67707C7F6B056D33210C016A6AD34B6D23804B27DD2CECB544A54E960F71D1186D50C7ED28696C49A290FE89F3CF6A54D67F67A571974BF006E091AB8F563BD74C300AFFB65E23DAAAED0C925BD332CDCFA453B47A8E509A60C95976300A55A40B55357719D5120CF3DA0E49DC38E06F2934A6009F88C555EAD5F2C256E61444722EDC27DF8645D17413BD464588EDA0101A5FCBEC727BED4650EC012910AA2E7C42342F3A571D5FD31182E7E3A209774BE75CA42ED6E6D62F62853146C4EA3B7B1EADD65957202D9872C5A02BC0D3C1B3E6894E76635AA4C703F2035CE685908084F2BEFC1DC29F4FBFC9E9E06FEDE8D223F516ACE4D8BDA41C03EFFB23B725DDADE70E6DA573149BAC69494D23653D1722A1C041B28EB2AC64B31DD9878D4CDB9827BD1342ECC6165CA47A9FCBF07F7ACBE7249E8EABB143952E11EA96B1D24AC7F09BD2FD6E9E7CA16B7D10E2C86CE2F7430B336892E12EBC3563EC1E5936006BC59C03164B4A11AC5728C673377E0D251FCE558CE809A287F7A3661A42241CEF62F5230FC0C960F44BB557140B04F218D9A619CF7C7DCDDE3716338F2101085F17E684A6AD536C32CA199353C62FE742F8DA7BFEC280BA673D2A797FFED3AB5615FA617757FC49D5B9B3D0867CEB4D11096B0872422E225C17DC41661F39AF255DFA1447C64ECF23D6E116FB2C4055A75E92E6983F641DB041F2DCD62F696D544A76058751256BE826065DCF657A15BD6B2C6D5706F51C1F6293ED07400B0D80DE004B0331BEB526313F97F1442F3A3046D6C80813D69E88D461E06F2F756FD9592B60CB317CE457F77211DD00CE2E867DD5A06644B37920D98C8332026183D762DE0FB6250303B8F2A5C8B9046A46062AA71FB54452FCC96AEEC2E79DD40F44A01CADEE93D55C2B2CD7B115FCABAFE3B44F1AD8D6BC13921908ACC0358AE4FB69B6BD56788660D12FA008FFE435B4FB7941DBADCBD731AA7743F2B1A04F2300D4A12148F416716298A768D2A29001339F16871258E31C5F510F2B746B738B93C9CA166625B8E9B305A14EDC3CE7D8160E9197A0680D9C3E3361575C719DE7874FD0A411DC6D0344349288272CE51117B36B26683753354E151A5537DCFE1FE10A369286FF27647654F5FB1E3725A66173B516F02F353A1C376234FBEB834CF4457FFEFF1EA99DB4E60C008E5C14719DB23EE8D5EBD652A741B385B588158704905DEE3485B4BE273E3CC36F0C64DFCABE6C9BFED35C8E0477AF8D8F89D7425B228546CDDB63CCBFBE8A639E4747DA4970E8632785F9DFA388DB4B231588ED88C8805671F6855EC847EEBD7464426A8D0059728A17ECC838164ACEA8FA933DBBB87EC8C63B178BB060B71FCC208E8433602CFB1170776233A672D5AF97842355A37261EBBA04FE64E59653573F51BEB786AECC068585850A36B0F9C60333B4DABB995BA4004DA7F2A898409605A94B033B80E53DEE21D26DABCD05E7C3F6F59BF6DAFEEDDE5236DA5F12B63BC784B6A896542400D8702B2141573F233382D7013574227CD034C98C5FA2673196B6C59B89B27E2015A0B63B54BA79B721AEED56DF4376CA59B520A0206D1FD79F7267A78108CD93AC4F8BC8F4858B742069038E8BDACEFF2677259D08B1FF6BA0AD1082E96C5F8A99BF1B74E74F6E1D713BB5BAB42FA0A136E0189307534574687257D7E0EE164BD127FB7F23CDA4F9C60E5F477771C4E48551EEAF6E57B61CF30DEAAD3BAAFE97BCF791179514B69A6A25E1C120609CE60F03E7054F4653921CF373358981982457B651EB888AC61F27D3FDD6F6E38A98897FA0B8999364B9A1452FC0DB1D8C17D0783FAEC1CB43E620EB975907A11E8276B68FFE1081F388D8710D71C407EC57DEB034CE959156B660865EC867C2EB2F94F84BEB910501BB1DD056E54FB69A378549A9B3F56FF44D2FA08FEAB673DE314ACA894C92151131A440C1551A67EB05E66058A0EBBE63441FA412DD00854B1DA6BB5EDEF5F746F618D799003E34E8A00F107AFA36FA61836DEF38D2CDBD250FE1F6497D8AAA19379A51CE2EE2A94B798298175FCE9E9C8ABF29ECAEC6FB684515979B22AB177DD3F540E4546EF4B21640148485EC5381D88C001D045104D3BA6CEE9CEAD85395A444046E1944DBDDC5A4C757CC344386EB3413DEBCF92F0CCD2430C99CC1F83A792C486B69295297E37B81AE1A3E66D3E7BB24591EAF18F707E6D0EDDF3C0877D18513295FB2BA2266069CFE24D81FA5FC8B6B4E0842751F8A903CEE8CC59A2112F6906BB7189D50465321D5822D4CF83CE17A0BE571ED005F4032B49B84ABB6AAECD21EC0B6FFD0CAFD2398167E6B4A81FC663791F4653B742A71E5633E09D5C662D4DF046BED2CE2CBD8529A428DF72952A1571369D4E75A5ADFA0F63684D2E4E16C359B3DF187E80D43A4A35D7B5ED2B14D84649BC7EA82BE21C246DBDB61B019E2712C1738276F79EF1C257E5CEBCD0A85427FAC63F9587233758080FA4022F1DBFA3855247B36B38B557412F85A18204B00F98360B1160B72E26E25B5A6A488C8197958283923860F8D0FF08F262DD5FC4EDA95ADA5D6EB1D0BDF4CB9E37B2E147497E856EF37456C89EDCDF3D0616A89967B81412899618E3564AFD973895DE0156DDEBA3DC6450E3F2AE4CF3F0877DA25DE48F221DC87A105A28CB5BAEFE26FD1BA5F8CA619DCBCD99D25591ADDFA4CC2F2C4FA08C31F0EED3716E81C044A2E7B865BDBCB4FD8E03FF7C8DF456AAFD826FEF5C15C95F245B239D15BD97FD99C4A00F76B17BAE8E339F02CEEFEFC7626069517C0B03051415A4AD319E9D8E671DB69D0B920891E97F22CEBE1B42FD65653599FB1540D903F4E77BB9DA88C421A7947842157EE46BAD59FDA49B077FD1BB5E0DB39747C2021EEB35C5F19A5172DA262EC93065008F0E4D4FDE433FF8CCFB54225A42AFE8CDB1C60BC7F0E257D5C072976AAFC76FD34349F141803391F099B16CA5D06083F57C015A1EEB5D205AD560E37C8F314305C37201446DFB787502113B8C984AE417774A2331637AC22878766E2860BB5E4729188405175A26C0B0CA2B3F523C60E0582D8C433CD56EDAA9141235763B4912E62B233FD5A1484297FCBE6A20EA9106DD26E511171EBBBB382558AF9F6EC89690D9BBB128DE71422F53AA071D1DDE98087EF918EAB8224817F75F95D91821B6151A1E6F6ABFAAF5C4D9E67F9652119BC95C23BE61062F98DA0280DF0F0A6E6140BEB5B4A81683696D3AD7501DCA4122CE1F1A1A0E353DBE17D806D3CBD6BC31E6D79CB837AF794FAE71506BCA31AD39F77C25FFC88C9AE31C046A56DC57F5D2C57FE2B1384159B9C084252BE6F0D4B95CF77B2B02E26562872D5B0B99210A78D6E26D56DCE9176957F806AB20653AD32F615C5277D37254C4A81DB25BE872087A1FAF38DC18F9398B5FBF3CFE94BCF39CB54320C15E1E9CD4E394DD72060EF10EF45194098F30D5D370BC79ED6E666196BFE85997A7D5E046E1B1B8E03A8A637EA2271A5896B3BC40CD4FDF0445CF80ABCE7C6707CE98E1446AD725AB83535E764C125198693044AB62ABDFA9DD4C2BDABFCCF99586A46D1C700DA299A97E92AC5B6E063EBFBEB04CE1E7A45CEACBC64CAC6986E16662C19FFCCEE3B6FF96C926DA717010F9F1981F0370EDB2BC34380EB13694BC67363650CEE072904730334687573F570630DF73D0946A091F784BCD7163CDD23525063C24EBEE9227D6C1C4EFB75AC6D875013F9564BF580D3EF0BEC05C501B99DEEFB5618D8A0AE66E46ABFCC4E4E8A2871EA9F109FAC2859966485DB267003FC5A17116F7C8D77A9B364865F580ABBC4126A0827CD7E337F856873F8FD51ECC63595AD46B055442EF5A8B00D077DB6C180E618F7C402A9F309E1D7FD9E22963FBEEAE08EE2D551E2BEC5EB093D5DD318D8EE0BD70E7B27109ABCCB9104370FD3A8C00B04B9C1489B796187BFCFD27AB7837D2490ECC12DE938D7882B77978C0B994A42B6DFEBEE4D0030505152C9685206ECAE1F27318A5ECA5D52B1C253596AB55A94B06A7D085B4CB607A559B6A34C39B766A52CFBE5938D3CBF99C727B2E14F1EAA938BAF59F2B80A6C4400566BDBCE3574CA490A93D57F36137100E161209DE3B6EBCC9A6CA173A50DF8B17AA498CC3A0DB8872C27FB6B7F8FE766E3CD869D144662E2E2D6962777FEA8BE9567B1D8FEC5EA6EDCFAC86E030891209C582608EC7481A84A8C3EAA46B5AFECBD8390A767FAEAB9FDAB5125DE8288DDE503E955FA50085886D9193D4C375261FE5B3B59696A544A275AAAC37E5B4F6970AAD52C95CB3548FFD36FC0AA5997D4FD6F7E7C6941281F00BC5C938A1094415B5FAC16741A99019C936DFED89077F7D7DB1EDE59285DCD01128EF5CAD2DFB6B769FB72F807ACEBB83B2D5AE6E19AB7B6758A43880A176EC6711C9D761286F6134735A7D1E98094EFF5C480654B0E7F50C16630E370933AC584FF93199AA0FCDFB16103408B12C98EA7102FD8C4A7B8103D2949ACC186BD96D4B7FBB76B49BDE6D02CE9F5231F98173E26CFCFD922656F69CED32A692F813CAFA1F8782A4AE2360A8CAD2DA63FA47F0323DB0270BEF307F18C52C99A06BE66272D370287B9C6B4E46061CA2B434C2CE1FE9105B1E51D8A276320B792D794F3DEF5E6304743F14321503CA7DC73F59C0339A6DF7035757AA3ADE02E4C210A64C190266F9B4B6C0ED38203E01DBD6CB5A6B47A9A24C11B94CC6274E741A58D4691B064AAEFEF8543F976905358CFCD0F5C5560F49CB402245A55C4B5BABDAD41C5170C0FAFF033EF84D15DC691799E2E9578EDB3E68161833461CA5EC482A3CC4F7F3F80631ECE9B36D9857324AE9524E724A9D11B857EA72DB3A40A338ABC862DEA9A458B981854CA7AE4FB658A8A448A702426CF81A22E4D6C1E5C5FCFE1752B857F231BB63D47CE933A0B00C92FA7F3E59ACE272679461A70727915BE01C1407FF3EDE615B0BC7F88BC2B929366D516EE3B6EC258ED7541501C9046459EAFFB9F5B73C55B01C18968D1BE54B64AD6C773CAAA52B4FED5DCE6522CB3B94585E25946345F0CF9600ACE63311123A771250627272D05AB9D92404FF86D2DADE42246E164639C8638470EC6E999C4D7B62BDE19EFD6D9E12FE2E0CC10552D0B9BD4B0F9C04805DFD7ACDE751D38DBB282DCF13FC83497983EA9C599F468343FB6CD748A1E47BB3F5D1794F506805B1D3F4ADAAEF985DC119E3F47403F5DBCDC7D7D5EB71F2ED00040AE2411CEEE1314CA9DEA1FF77277249BBF54E9F897ABD655FE86911AD1854BCB6D8C799F0370FF8A379C872FE74DA9E77A5B1DBB1E480F8B282E77D0A2112D89C9305397BCE6FC3D2469642AEADC84FB6B98C4E8786894ABCE3AF37112100BB97B4F4EA490B0B71A40609BCEC6AD815FAE1F88D537A4108239E9DEA748583DDC60DD872E4D47BF299CC638F5A889FDAD3A6035FAFB5EED001FE8889B1DE311A6644B5C513ABC14E2D2885057E3C93D6BFC90F54D302B13BC9BD146A870792775A0659DBFEEEDDD7D9FB978650D7E3E62B80B404933825175D7AD2717619AE22A53D50E7136C9EAD0E988E193C048F434B32EEC8A8DB9FE428B38785B247F5A423B362349FD806477725711396850511EE4B4D8B515EF1EA5053AA0A5918CBDD17976F58A43833063920ACF3E11AD64FE5619FA8C8ECCE9CE60DF21C5C80240CF6CCE0167658D09F442E33B1E63E3B5D75DD87619D95BC113AE5B5B414CDA9D91F6A6C81ED88EEC67007990CB3B34E3292246964C8A44D42694134BC9E47FC4CE07BCFD56FCC6F5EC47E2C806A8B52C2F590767D0B933B6F5A44AA5D1FA9AAC304B85D624B957AD4ED8F9253788D817962F049A774BF5AEC2940D831C27BCB6488376DADB52118322756CD9DC53D75076EB1297A21E2EF0AF2D820958C51700BFF0CD19AD1D2D236A78AA2B75C3E0A443406FD9B803E68793284249E4717618EDE35229E65724242F0692F87CCBCB17F77D1987D473FB0CC869F284B27BEB80F0287'
);
// console.log(result)
expect(result.includes('<QrcInfos>')).toBeTruthy();
});
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@
"@react-navigation/material-top-tabs": "^6.6.13",
"@react-navigation/native": "^6.1.17",
"@react-navigation/native-stack": "^6.9.26",
"@sentry/react-native": "^5.20.0",
"@sentry/react-native": "^5.22.0",
"@sharcoux/slider": "^7.1.1",
"@shopify/flash-list": "^1.6.4",
"@shopify/react-native-skia": "1.2.0",
"@shopify/react-native-skia": "1.2.1",
"axios": "^1.6.8",
"babel-plugin-transform-remove-console": "^6.9.4",
"base-64": "^1.0.0",
Expand All @@ -57,7 +57,7 @@
"dayjs": "^1.11.9",
"deepmerge": "^4.3.1",
"dropbox": "git+https://[email protected]/lovegaoshi/dropbox-sdk-js.git",
"expo": "^50.0.15",
"expo": "^50.0.17",
"expo-clipboard": "~5.0.1",
"expo-document-picker": "~11.10.1",
"expo-image": "^1.10.6",
Expand Down Expand Up @@ -104,7 +104,7 @@
"react-native-url-polyfill": "^2.0.0",
"react-native-vector-icons": "^10.0.3",
"react-native-video": "git+https://github.com/lovegaoshi/react-native-video.git#dev-android-cache",
"react-native-webview": "^13.8.5",
"react-native-webview": "^13.8.6",
"react-native-windows": "^0.73.11",
"react-use": "^17.5.0",
"use-debounce": "^10.0.0",
Expand Down Expand Up @@ -140,7 +140,7 @@
"@welldone-software/why-did-you-render": "^8.0.1",
"argparse": "^2.0.1",
"babel-jest": "^29.6.4",
"babel-plugin-module-resolver": "^5.0.0",
"babel-plugin-module-resolver": "^5.0.1",
"cpx": "^1.5.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.0.0",
Expand Down
4 changes: 3 additions & 1 deletion src/components/player/Lyric.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export const LyricView = ({
else titleToFetch = reExtractSongName(track.title, artist);
const options = (
await Promise.all([
searchLyricOptions(titleToFetch, LrcSource.QQQrc),
searchLyricOptions(titleToFetch),
searchLyricOptions(titleToFetch, LrcSource.Kugou),
])
Expand All @@ -213,7 +214,8 @@ export const LyricView = ({
const resolvedLrc = resolvedLrcOptions[index!];
const lyric = resolvedLyric
? await searchLyric(resolvedLyric.lyricKey, resolvedLyric.source)
: await searchLyric(resolvedLrc.songMid, resolvedLrc.source);
: resolvedLrc.lrc ??
(await searchLyric(resolvedLrc.songMid, resolvedLrc.source));
setLrc(lyric);
setLrcOption(resolvedLrc);
updateLyricMapping({ newLrcDetail: { lyric }, resolvedLrc });
Expand Down
5 changes: 3 additions & 2 deletions src/components/playlist/usePlaylistRN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,12 @@ export default (playlist: NoxMedia.Playlist) => {
};

const scrollTo = (toIndex = -1, reset = false) => {
const currentIndex =
let currentIndex =
toIndex < 0
? playlist.songList.findIndex(song => song.id === currentPlayingId)
: toIndex;
if (currentIndex > -1 || reset) {
if (currentIndex === -1 && reset) currentIndex = 0;
if (currentIndex > -1) {
playlistRef.current?.scrollToIndex({
index: currentIndex,
viewPosition: 0.5,
Expand Down
1 change: 1 addition & 0 deletions src/components/setting/appearances/SkinSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ const SkinSettings = () => {
if (currentThemeIndex > -1) {
scrollViewRef.current?.scrollToIndex({
index: currentThemeIndex,
viewOffset: -214,
animated: false,
});
}
Expand Down
1 change: 1 addition & 0 deletions src/enums/LyricFetch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum LrcSource {
QQ = 'qq',
QQQrc = 'qqqrc',
Kugou = 'kugou',
}
1 change: 1 addition & 0 deletions src/types/request.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ declare global {
songMid: string;
label: string;
source?: LrcSource;
lrc?: string;
}

export interface NoxRegexFetch {
Expand Down
24 changes: 17 additions & 7 deletions src/utils/LyricFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,26 @@ import i18n from 'i18next';
import logger from './Logger';
import kugouLrcFetch from './lrcfetch/kugou';
import qqLrcFetch from './lrcfetch/qq';
import qqQrcFetch from './lrcfetch/qqqrc';
import { LrcSource } from '@enums/LyricFetch';

export const searchLyricOptions = async (
searchKey: string,
source = LrcSource.QQ
): Promise<NoxNetwork.NoxFetchedLyric[]> => {
switch (source) {
case LrcSource.Kugou:
return kugouLrcFetch.getLrcOptions(searchKey);
case LrcSource.QQ:
default:
return qqLrcFetch.getLrcOptions(searchKey);
try {
switch (source) {
case LrcSource.Kugou:
return await kugouLrcFetch.getLrcOptions(searchKey);
case LrcSource.QQQrc:
return await qqQrcFetch.getLrcOptions(searchKey);
case LrcSource.QQ:
default:
return await qqLrcFetch.getLrcOptions(searchKey);
}
} catch (e) {
logger.warn(`[lrcOptionFetch] ${searchKey} & ${source}: ${e}`);
return [];
}
};

Expand All @@ -23,12 +31,14 @@ export const searchLyric = async (searchMID: string, source = LrcSource.QQ) => {
switch (source) {
case LrcSource.Kugou:
return kugouLrcFetch.getLyric(searchMID);
case LrcSource.QQQrc:
return qqQrcFetch.getLyric(searchMID);
case LrcSource.QQ:
default:
return qqLrcFetch.getLyric(searchMID);
}
} catch (e) {
logger.error(e);
logger.warn(`[lrcFetch] ${searchMID} & ${source}: ${e}`);
return i18n.t('Lyric.failedToFetch');
}
};
109 changes: 109 additions & 0 deletions src/utils/lrcfetch/qqqrc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// https://github.com/bingaha/kugou-lrc
import { strFromU8, decompressSync } from 'fflate';
import { decode as atob, encode as btoa } from 'base-64';

import bfetch from '@utils/BiliFetch';
import { biliApiLimiter } from '@utils/mediafetch/throttle';
import { LrcSource } from '@enums/LyricFetch';
import { logger } from '../Logger';
import { decodeQrc } from './qrcdecoder';

const SearchSongAPI = 'https://u.y.qq.com/cgi-bin/musicu.fcg';

const searchPost = (kw: string): any => {
const body = {
comm: {
_channelid: '0',
_os_version: '6.2.9200-2',
authst: '',
ct: '19',
cv: '1873',
patch: '118',
psrf_access_token_expiresAt: 0,
psrf_qqaccess_token: '',
psrf_qqopenid: '',
psrf_qqunionid: '',
tmeAppID: 'qqmusic',
tmeLoginType: 2,
uin: '0',
wid: '0',
},
'music.musichallSong.PlayLyricInfo.GetPlayLyricInfo': {
method: 'GetPlayLyricInfo',
module: 'music.musichallSong.PlayLyricInfo',
param: {
songName: btoa(kw),
crypt: 1,
qrc: 1,
ct: 19,
cv: 1873,
lrc_t: 0,
qrc_t: 0,
roma: 1,
roma_t: 0,
type: -1,
trans: 1,
trans_t: 0,
},
},
};
return {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Host: 'u.y.qq.com',
},
referrer: 'https://u.qq.com/',
body: JSON.stringify(body),
};
};

const getQrcLyricOptions = async (
kw: string
): Promise<NoxNetwork.NoxFetchedLyric[]> => {
logger.debug(`[qrc] calling getQrcLyricOptions: ${kw}`);
const res = await bfetch(SearchSongAPI, searchPost(kw));
const json = await res.json();
const data = json['music.musichallSong.PlayLyricInfo.GetPlayLyricInfo']?.data;
if (data.lyric.length > 0) {
return [
{
key: data.songID,
songMid: data.songID,
source: LrcSource.QQQrc,
label: `[${LrcSource.QQQrc}] ${kw}`,
// HACK: this should be safe as the search param specifies
// encrypt:1 and qrc:1
lrc: decodeQrc(data.lyric),
},
];
}
return json[
'music.musichallSong.PlayLyricInfo.GetPlayLyricInfo'
].data.vecSongID.map((info: any) => ({
key: info,
songMid: info,
source: LrcSource.QQQrc,
label: `[${LrcSource.QQQrc}] ${kw}(${info})`,
}));
};

const getQrcLyric = async (songMid: string) => {
logger.debug(`[qrc] calling getQrcLyric: ${songMid}`);
const qrcPostParam = searchPost('');
const parsedBody = JSON.parse(qrcPostParam.body);
parsedBody['music.musichallSong.PlayLyricInfo.GetPlayLyricInfo'].param = {
songID: Number(songMid),
};
qrcPostParam.body = JSON.stringify(parsedBody);
const res = await bfetch(SearchSongAPI, qrcPostParam);
const json = await res.json();
const data = json['music.musichallSong.PlayLyricInfo.GetPlayLyricInfo'].data;
if (data.qrc == 0) return atob(data.lyric);
return decodeQrc(data.lyric);
};

export default {
getLrcOptions: getQrcLyricOptions,
getLyric: getQrcLyric,
};
Loading

0 comments on commit 854e587

Please sign in to comment.