Skip to content

Commit 90fcc18

Browse files
authored
fix(apply): add support for Spotify 1.2.78+ (#3629)
1 parent 04155e7 commit 90fcc18

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

src/apply/apply.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -260,18 +260,32 @@ func getColorCSS(scheme map[string]string) string {
260260

261261
func insertCustomApp(jsPath string, flags Flag) {
262262
utils.ModifyFile(jsPath, func(content string) string {
263-
const REACT_REGEX = `([\w_\$][\w_\$\d]*(?:\(\))?)\.lazy\(\((?:\(\)=>|function\(\)\{return )(\w+)\.(\w+)\(\d+\)\.then\(\w+\.bind\(\w+,\d+\)\)\}?\)\)`
264-
const REACT_ELEMENT_REGEX = `(\[\w_\$][\w_\$\d]*(?:\(\))?\.createElement|\([\w$\.,]+\))\(([\w\.]+),\{path:"\/collection"(?:,(element|children)?[:.\w,{}()$/*"]+)?\}`
265-
reactSymbs := utils.FindSymbol(
263+
// React lazy loading patterns for dynamic imports
264+
reactPatterns := []string{
265+
// Sync pattern: X.lazy((() => Y.Z(123).then(W.bind(W, 456))))
266+
`([\w_\$][\w_\$\d]*(?:\(\))?)\.lazy\(\((?:\(\)=>|function\(\)\{return )(\w+)\.(\w+)\(\d+\)\.then\(\w+\.bind\(\w+,\d+\)\)\}?\)\)`,
267+
// Async pattern (1.2.78+): m.lazy(async()=>{...await o.e(123).then(...)})
268+
`([\w_\$][\w_\$\d]*)\.lazy\(async\(\)=>\{(?:[^{}]|\{[^{}]*\})*await\s+(\w+)\.(\w+)\(\d+\)\.then\(\w+\.bind\(\w+,\d+\)\)`,
269+
// Async Promise.all pattern (1.2.78+): m.lazy(async()=>await Promise.all([...]).then(...))
270+
`([\w_\$][\w_\$\d]*(?:\(\))?)\.lazy\(async\(\)=>await\s+Promise\.all\(\[[^\]]+\]\)\.then\((\w+)\.bind\((\w+),\d+\)\)`,
271+
}
272+
273+
// React element/route patterns for path matching
274+
elementPatterns := []string{
275+
// JSX pattern (1.2.78+): (0,S.jsx)(se.qh,{path:"/collection/*",element:...})
276+
`(\([\w$\.,]+\))\(([\w\.]+),\{path:"/collection(?:/[\w\*]+)?",?(element|children)?`,
277+
// createElement pattern: X.createElement(Y,{path:"/collection"...})
278+
`([\w_\$][\w_\$\d]*(?:\(\))?\.createElement|\([\w$\.,]+\))\(([\w\.]+),\{path:"\/collection"(?:,(element|children)?[:.\w,{}()$/*"]+)?\}`,
279+
}
280+
281+
reactSymbs, matchedReactPattern := utils.FindSymbolWithPattern(
266282
"Custom app React symbols",
267283
content,
268-
[]string{
269-
REACT_REGEX})
270-
eleSymbs := utils.FindSymbol(
284+
reactPatterns)
285+
eleSymbs, matchedElementPattern := utils.FindSymbolWithPattern(
271286
"Custom app React Element",
272287
content,
273-
[]string{
274-
REACT_ELEMENT_REGEX})
288+
elementPatterns)
275289

276290
if (len(reactSymbs) < 2) || (len(eleSymbs) == 0) {
277291
utils.PrintError("Spotify version mismatch with Spicetify. Please report it on our github repository.")
@@ -320,14 +334,14 @@ func insertCustomApp(jsPath string, flags Flag) {
320334

321335
utils.ReplaceOnce(
322336
&content,
323-
REACT_REGEX,
337+
matchedReactPattern,
324338
func(submatches ...string) string {
325339
return fmt.Sprintf("%s%s", submatches[0], appReactMap)
326340
})
327341

328342
utils.ReplaceOnce(
329343
&content,
330-
REACT_ELEMENT_REGEX,
344+
matchedElementPattern,
331345
func(submatches ...string) string {
332346
return fmt.Sprintf("%s%s", appEleMap, submatches[0])
333347
})

src/utils/utils.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,24 @@ func FindSymbol(debugInfo, content string, clues []string) []string {
313313
return nil
314314
}
315315

316+
// FindSymbolWithPattern uses regexp from one or multiple clues to find variable or
317+
// function symbol in obfuscated code. Returns the matched symbols and the pattern that matched.
318+
func FindSymbolWithPattern(debugInfo, content string, clues []string) ([]string, string) {
319+
for _, v := range clues {
320+
re := regexp.MustCompile(v)
321+
found := re.FindStringSubmatch(content)
322+
if found != nil {
323+
return found[1:], v
324+
}
325+
}
326+
327+
if len(debugInfo) > 0 {
328+
PrintError("Cannot find symbol for " + debugInfo)
329+
}
330+
331+
return nil, ""
332+
}
333+
316334
// CreateJunction creates a junction in Windows or a symlink in Linux/Mac.
317335
func CreateJunction(location, destination string) error {
318336
CheckExistAndDelete(destination)

0 commit comments

Comments
 (0)