generated from extratone/latte
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Apple Music Wrapped.jelly
2000 lines (1923 loc) · 138 KB
/
Apple Music Wrapped.jelly
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import Shortcuts
#Color: pink, #Icon: musicNote
/*
Create a detailed report for the music you've listened to in the past year. The shortcut can optionally create a Top 25 playlist for your most played songs and generate a PDF report. The shortcut is primarily designed for Apple Music subscribers.
To calculate number of plays, the shortcut looks at songs that have been played in full without skipping and added to your library in any given year.
*/
/*
Special thanks to the people who helped and/or tested this shortcut beforehand:
- Silvia Gatta
- John Voorhees
- Ryan Christoffel
- Kyle Seth Gray
- Jason Tate (AbsolutePunk/Chorus.fm forever)
- Jason Snell
- Myke Hurley
- Stephen Hackett
- James Thomson
- Simon Støvring
*/
/*
VCF Choose from List method based on Listify and Image Menu Builder:
* https://reddit.com/r/shortcuts/comments/a1dk4v/listify_easily_create_pretty_choose_from_list/
* https://reddit.com/r/shortcuts/comments/a2tel6/image_menu_builder_build_menus_with_images_using/
*/
// Year to generate a report for
text(text: "2020") >> Year
var SelectedYear = Year
// Number of songs to look for
number(value: 50) >> number
var NumberofSongs = Number
continueInShortcuts()
number(value: Selected Year) >> number 1
if(Number > 2014) {
nothing()
} else {
alert(alert: "Apple Music launched in 2015, but you entered ${Selected Year}. This will result in an error if you continue running the shortcut.", title: "⛔️ Easy There, Time Traveler ⛔️", cancel: $2)
alert(alert: "Look, it's not my fault. You will see an error if you continue. Any year before 2015 will cause this shortcut to error out when parsing numbers. Please retry with a different year.", title: "You Can't Avoid the Inevitable")
alert(alert: "Fine.", title: "...")
alert(alert: "I guess you like to live dangerously, rejecting authority even in the form of an alert inside a shortcut.", title: "")
alert(alert: "I can respect that.", title: "")
alert(alert: "But it's not like I didn't warn you. Go ahead and see if you can get that error.", title: "🤷♂️", cancel: $2)
} >> IFResult
// Name of the playlist
text(text: "${Year} Wrapped") >> Playlist Name
// Generate start and end dates
date(date: "1/1/${Year} 12AM") >> date
var StartDate = Date
date(date: "12/31/${Year} 11:59PM") >> date 1
var EndDate = Date
// Set initial duration value
number(value: false) >> number 2
var Duration = Number
number(value: false) >> number 3
var TotalDuration = Number
sendNotification(body: "Collecting ${Year} songs you added to your library in ${ActionOutput}...", title: "${Playlist Name}", sound: false)
filterMusic() >> Main Music Results
count(type: Items, input: Main Music Results) >> count
if(Count > 5) {
nothing()
} else {
alert(alert: "Less than 5 songs were found for ${Selected Year}. This means that you didn't add enough songs to your library, or that iCloud Music Library is turned off.", title: "❌ Not Enough Songs ❌")
} >> IFResult 1
repeatEach(Main Music Results) {
musicDetail(detail: Duration, music: Repeat Item) >> musicDetail
number(value: Details of Music) >> Track Duration
// Add duration of each track to a variable
math(input: Track Duration, operation: +, operand: Duration) >> math
var Duration = Calculation Result
musicDetail(detail: Play Count, music: Repeat Item) >> musicDetail 1
math(input: Play Count, operation: *, operand: Track Duration) >> math 1
// Multiply a track play count by its duration, then add to a different variable
math(input: Calculation Result, operand: Total Duration) >> math 2
var TotalDuration = Calculation Result
text(text: "<li><strong>${Repeat Item.get(Artist)}</strong> – ${Variable.get(Artist)}</li>") >> text
//Unable to get shortcuts action is.workflow.actions.appendvariable
musicDetail(detail: Album Artwork, music: Repeat Item) >> musicDetail 2
//Unable to get shortcuts action is.workflow.actions.appendvariable
} >> RepeatResult
// Calculate average duration of songs
musicDetail(detail: Duration, music: Main Music Results) >> musicDetail 3
statistic(input: Duration) >> statistic
//Unable to get shortcuts action is.workflow.actions.measurement.create
//Unable to get shortcuts action is.workflow.actions.measurement.convert
round(number: Converted Measurement, roundTo: Tenths) >> round
var AverageDuration = Rounded Number
// Create main grid image
combineImage(images: Covers, mode: In a Grid) >> combineImage
resizeImage(image: Combined Image, width: 1000) >> resizeImage
encode(input: Resized Image) >> encode
// Convert track duration to hours
//Unable to get shortcuts action is.workflow.actions.measurement.create
//Unable to get shortcuts action is.workflow.actions.measurement.convert
round(number: Converted Measurement, roundTo: Tenths) >> round 1
// Create main list of tracks as HTML
combineText(text: Tracks, combine: New Lines) >> combineText
var 886695D4-F65A-4AAE-9D02-5C26B1D32E75 = """<ol type="1">

</ol>"""
text("${886695D4-F65A-4AAE-9D02-5C26B1D32E75}")
var TrackList = Text
// Isolate most played song
getItemFromList(list: Main Music Results) >> getItemFromList
text(text: "${Item from List.get(Name)} by ${ActionOutput.get(Name)}") >> text 1
var MostPlayedSong = Text
// Get URL and assemble widget for most played song
getItemFromList(list: Main Music Results) >> Top Song
searchItunes(query: "${Top Song.get(Title)} ${ActionOutput.get(Title)}", by: All, count: true) >> searchItunes
count(type: Items, input: iTunes Products) >> count 1
if(Count == "1") {
productDetail(detail: Store URL, product: iTunes Products) >> productDetail
replaceText(input: "${Store URL}", find: "music.apple.com", replace: "embed.music.apple.com", caseSensitive: true) >> replaceText
text(text: "<p align="center"><iframe allow="autoplay *; encrypted-media *;" frameborder="0" height="150" style="width:100%;max-width:660px;overflow:hidden;background:transparent;" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-storage-access-by-user-activation allow-top-navigation-by-user-activation" src="${Replace Text}&app=music"></iframe></p>") >> text 2
var EmbedMostPlayedTrackURL = Text
} else {
nothing()
//Unable to get shortcuts action is.workflow.actions.setvariable
} >> IFResult 2
musicDetail(detail: Play Count, music: Top Song) >> musicDetail 4
// Build listening time for most played song
musicDetail(detail: Duration, music: Top Song) >> musicDetail 5
number(value: Details of Music) >> number 4
math(input: Number, operation: *, operand: Details of Music) >> math 3
//Unable to get shortcuts action is.workflow.actions.measurement.create
//Unable to get shortcuts action is.workflow.actions.measurement.convert
round(number: Converted Measurement, roundTo: Tenths) >> round 2
//Unable to get shortcuts action is.workflow.actions.measurement.create
//Unable to get shortcuts action is.workflow.actions.measurement.convert
round(number: Converted Measurement, roundTo: Tenths) >> Hours
//Unable to get shortcuts action is.workflow.actions.measurement.create
//Unable to get shortcuts action is.workflow.actions.measurement.convert
number(value: Converted Measurement) >> number 5
// Assemble list of Top 10 songs
getItemFromList(list: Main Music Results, type: Items in Range, startIndex: "true", endIndex: "10") >> getItemFromList 1
repeatEach(Item from List) {
searchItunes(query: "${Repeat Item.get(Artist)} ${Variable.get(Artist)}", count: true) >> searchItunes 1
// Check if the item is available on iTunes or not
count(type: Items, input: iTunes Products) >> count 2
if(Count == "1") {
text(text: "${Repeat Index}. [${Variable}](${iTunes Products.get(Name)})") >> text 3
//Unable to get shortcuts action is.workflow.actions.appendvariable
} else {
text(text: "${Repeat Index}. ${Variable}") >> text 4
//Unable to get shortcuts action is.workflow.actions.appendvariable
}
}
// Assemble top nine image
getItemFromList(list: Main Music Results, type: Items in Range, startIndex: "1", endIndex: "9") >> getItemFromList 2
repeatEach(Item from List) {
musicDetail(detail: Album Artwork, music: Repeat Item) >> musicDetail 6
//Unable to get shortcuts action is.workflow.actions.appendvariable
} >> RepeatResult 1
combineImage(images: Top 9, mode: In a Grid) >> combineImage 1
resizeImage(image: Combined Image, width: 1000) >> Top 9 Image
encode(input: Top 9 Image) >> encode 1
var Top9 = Base64 Encoded
/*
Generate playlist of Top 25.
Limited to 25 because larger numbers are not reliable
*/
menu(, [Yes, Create a Playlist, Nope]) {
case("Yes, Create a Playlist"):
createPlaylist(name: "${Playlist Name}", author: "Apple Music Wrapped – Shortcuts ", description: "Your top 25 songs of ${Year}.") >> createPlaylist
filterMusic() >> Top 25
addToPlaylist(music: Top 25, playlist: Playlist Name)
case("Nope"):
nothing()
}
// Get top genres
repeatEach(Main Music Results) {
musicDetail(detail: Genre, music: Repeat Item) >> musicDetail 7
var EE2756B0-259A-41E9-9511-95A014555C9E = """
"""
text("${EE2756B0-259A-41E9-9511-95A014555C9E}")
var Genres = Text
}
// For each genre, pair it with the number of times it appears in the list, plus a custom separator
splitText(text: Genres) >> splitText
repeatEach(Split Text) {
// Match the genre and how many times it appears
matchText(text: "${Genres}", regex: "(?m)^${Repeat Item}$") >> matchText
count(type: Items, input: Matches) >> count 3
text(text: "${Count} ${ActionOutput} ~~GENRE~~") >> text 5
//Unable to get shortcuts action is.workflow.actions.appendvariable
}
// Remove duplicate lines of genres + counts via JS
splitText(text: Genre Count) >> splitText 1
combineText(text: Split Text, combine: Custom, separator: "\n") >> combineText 1
var Items = Combined Text
var 3886D006-9580-4A3B-8AE2-C31AFD3509D6 = """<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-16">
<script>
var str = ""
var lines = str.split("\n")
var workingSet = lines
workingSet = lines.map(s => {
return s.toLowerCase()
})
var unique = []
workingSet.forEach((s, i) => {
if (workingSet.indexOf(s) == i) {
unique.push(lines[i])
}
})
document.write(unique.join("\n"));
</script>
</head>
<body>
</body>
</html>"""
text("${3886D006-9580-4A3B-8AE2-C31AFD3509D6}")
encode(input: Text) >> encode 2
url(url: "data:text/html;base64,${Base64 Encoded}") >> url
urlContents(url: "${URL}") >> urlContents
getTextFrom(input: Contents of Web Page) >> getTextFrom
splitText(text: Text, separator: Custom, customSeparator: " ~~GENRE~~") >> splitText 2
// Remove separator and empty lines
repeatEach(Split Text) {
count(type: Characters, input: Repeat Item) >> count 4
if(Count > false) {
//Unable to get shortcuts action is.workflow.actions.appendvariable
} else {
} >> IFResult 3
}
// Isolate counts of genres
combineText(text: Number and Genre, combine: New Lines) >> All Numbers and Genres
matchText(text: "${All Numbers and Genres}", regex: "(?m).*(\d+)\s") >> matchText 1
combineText(text: Matches, combine: Custom, separator: ",") >> Numbers
// Sort genre counts from biggest to smallest via JS
var DBE652A1-D443-4FB8-98CA-B026B5AF7862 = """<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-16">
<script>
numbers = [];
sorted = numbers.sort(function(a,b){return a - b});
document.write(sorted.reverse());
</script>
</head>
<body>
</body>
</html>"""
text("${DBE652A1-D443-4FB8-98CA-B026B5AF7862}")
encode(input: Text) >> encode 3
url(url: "data:text/html;base64,${Base64 Encoded}") >> url 1
urlContents(url: "${URL}") >> urlContents 1
getTextFrom(input: Contents of Web Page) >> getTextFrom 1
splitText(text: Text, separator: Custom, customSeparator: ",") >> Sorted Genre Counts
// Get the highest count
getItemFromList(list: Sorted Genre Counts) >> Top Genre
replaceText(input: "${Top Genre}", find: " ", replace: "") >> replaceText 1
var FirstTopGenre = Updated Text
// Compare to second item in the list for equal results
getItemFromList(list: Sorted Genre Counts, type: Item At Index, index: "2") >> Second Top Genre
replaceText(input: "${Second Top Genre}", find: " ", replace: "") >> replaceText 2
var SecondTopGenre = Updated Text
// Compare the top genre value to the second genre in the list. If they're equal, present two top genres in the final report.
number(value: First Top Genre) >> number 6
if(Number == 5) {
matchText(text: "${All Numbers and Genres}", regex: "(?m).*(${First Top Genre})\s(.*)") >> Matches
getItemFromList(list: Matches) >> getItemFromList 3
getMatchGroup(matches: Item from List, index: "2") >> Equal Genre 1
var MostListenedGenre = Equal Genre 1
getItemFromList(list: Matches, type: Item At Index, index: "2") >> getItemFromList 4
getMatchGroup(matches: Item from List, index: "2") >> Equal Genre 2
var SecondMostListenedGenre = Equal Genre 2
var D3DD8A30-A3B6-4B2A-8B12-AE6E758C149A = """<h2>Your favorite genres are:</h2>
<h2 class="centerText"> and </h2>"""
text("${D3DD8A30-A3B6-4B2A-8B12-AE6E758C149A}")
var GenreBlock = Text
} else {
// Find the single genre that is paired with the highest count
matchText(text: "${All Numbers and Genres}", regex: "(?m).*(${Top Genre})\s(.*)") >> matchText 2
getMatchGroup(matches: Matches, index: "2") >> getMatchGroup
var MostListenedGenre = Text
var B0D9EAAB-A082-42BC-8B29-710B85BFE2E5 = """<h2>Your favorite genre is:</h2>
<h2 class="centerText"></h2>"""
text("${B0D9EAAB-A082-42BC-8B29-710B85BFE2E5}")
var GenreBlock = Text
}
// Get top artists
repeatEach(Main Music Results) {
musicDetail(music: Repeat Item) >> musicDetail 8
var 0AE73BAF-8807-49C1-B33E-5A00BB722066 = """
"""
text("${0AE73BAF-8807-49C1-B33E-5A00BB722066}")
var Artists = Text
}
// For each artist, pair it with the number of times it appears in the list, plus a custom separator
splitText(text: Artists) >> splitText 3
repeatEach(Split Text) {
// Match the artist and how many times it appears
matchText(text: "${Artists}", regex: "(?m)^${Repeat Item}$") >> matchText 3
count(type: Items, input: Matches) >> count 5
text(text: "${Count} ${ActionOutput} ~~ARTIST~~") >> text 6
//Unable to get shortcuts action is.workflow.actions.appendvariable
}
// Remove duplicate lines of artists + counts via JS
splitText(text: Artist Count) >> splitText 4
combineText(text: Split Text, combine: Custom, separator: "\n") >> combineText 2
replaceText(input: "${Combined Text}", find: """, replace: "\"") >> replaceText 3
var ArtistItems = Updated Text
var 3872B132-35A7-4ABF-B44F-48EEFF578F08 = """<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-16">
<script>
var str = ""
var result = document.getElementById('result');
var lines = str.split("\n")
var workingSet = lines
workingSet = lines.map(s => {
return s.toLowerCase()
})
var unique = []
workingSet.forEach((s, i) => {
if (workingSet.indexOf(s) == i) {
unique.push(lines[i])
}
})
document.write(unique.join("\n"));
</script>
</head>
<body>
</body>
</html>"""
text("${3872B132-35A7-4ABF-B44F-48EEFF578F08}")
encode(input: Text) >> encode 4
url(url: "data:text/html;base64,${Base64 Encoded}") >> url 2
urlContents(url: "${URL}") >> urlContents 2
getTextFrom(input: Contents of Web Page) >> getTextFrom 2
splitText(text: Text, separator: Custom, customSeparator: " ~~ARTIST~~") >> splitText 5
// Remove separator and empty lines
repeatEach(Split Text) {
count(type: Characters, input: Repeat Item) >> count 6
if(Count > false) {
//Unable to get shortcuts action is.workflow.actions.appendvariable
} else {
} >> IFResult 4
} >> RepeatResult 2
sendNotification(body: "Now assembling your top artists of ${Year}...", title: "${Playlist Name}", sound: false)
// Isolate counts of artists
combineText(text: Number and Artist, combine: New Lines) >> All Numbers and Artists
/*
Regex to match numbers and artist names
Added fix for white space. This may fix most issues but break artist names if they begin with an empty space
*/
matchText(text: "${All Numbers and Artists}", regex: "(?m)^\s?(\d*)\s(.+)$") >> matchText 4
getMatchGroup(matches: Matches) >> getMatchGroup 1
combineText(text: Text, combine: Custom, separator: ",") >> combineText 3
// Sort artist counts from biggest to smallest via JS
var FA6C2EBC-3FAF-4E48-9A10-F1583A55B494 = """<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-16">
<script>
numbers = [];
sorted = numbers.sort(function(a,b){return a - b});
document.write(sorted.reverse());
</script>
</head>
<body>
</body>
</html>"""
text("${FA6C2EBC-3FAF-4E48-9A10-F1583A55B494}")
encode(input: Text) >> encode 5
url(url: "data:text/html;base64,${Base64 Encoded}") >> url 3
urlContents(url: "${URL}") >> urlContents 3
getTextFrom(input: Contents of Web Page) >> getTextFrom 3
splitText(text: Text, separator: Custom, customSeparator: ",") >> Sorted Top Artists
// Get the highest artist count
getItemFromList(list: Sorted Top Artists) >> getItemFromList 5
replaceText(input: "${Item from List}", find: " ", replace: "") >> replaceText 4
var FirstTopArtist = Updated Text
// Compare to second artist in the list for equal results
// If the list of artist counts is greater than 1
count(type: Items, input: Sorted Top Artists) >> count 7
if(Count > true) {
getItemFromList(list: Sorted Top Artists, type: Item At Index, index: "2") >> getItemFromList 6
replaceText(input: "${Item from List}", find: " ", replace: "") >> replaceText 5
var SecondTopArtist = Updated Text
number(value: First Top Artist) >> number 7
// Compare the top artist value to the second artist in the list. If they're equal, present two top artists in the final report.
if(Number == ""${Second Top Artist}"") {
matchText(text: "${All Numbers and Artists}", regex: "(?m).*(${First Top Artist})\s(.*)") >> matchText 5
getItemFromList(list: Matches) >> getItemFromList 7
getMatchGroup(matches: Item from List, index: "2") >> getMatchGroup 2
var MostListenedArtist = Text
getItemFromList(list: Text Matches, type: Item At Index, index: "2") >> getItemFromList 8
getMatchGroup(matches: Item from List, index: "2") >> getMatchGroup 3
var SecondMostListenedArtist = Text
list(items: (
{
WFItemType = 0;
WFValue = {
Value = {
attachmentsByRange = {
"{0, 1}" = {
Type = Variable;
VariableName = "Most Listened Artist";
};
};
string = "\Ufffc";
};
WFSerializationType = WFTextTokenString;
};
},
{
WFItemType = 0;
WFValue = {
Value = {
attachmentsByRange = {
"{0, 1}" = {
Type = Variable;
VariableName = "Second Most Listened Artist";
};
};
string = "\Ufffc";
};
WFSerializationType = WFTextTokenString;
};
}
)) >> list
repeatEach(List) {
searchItunes(query: "${Repeat Item}", by: Artist, results: Artists, count: true) >> searchItunes 2
count(type: Items, input: iTunes Products) >> count 8
if(Count > false) {
// Get the iTunes listing for the artists and download the HTML version of the webpage
artistDetail(property: Store URL, note: iTunes Products) >> artistDetail
downloadURL(url: "${Store URL}") >> downloadURL
htmlFromRichText(text: Contents of URL) >> htmlFromRichText
// Scrape the og:image meta tag
matchText(text: "${HTML from Rich Text}", regex: "\<meta\sproperty\=\"og\:image\"\scontent\=\"(.*?)\"") >> matchText 6
// If there is an image, save it to a variable
count(type: Items, input: Matches) >> count 9
if(Count == "1") {
getMatchGroup(matches: Text Matches) >> getMatchGroup 4
getURLSFromInput(text: "${Text}") >> getURLSFromInput
// Replace the URL to remove the white background version
replaceText(input: "${URLs}", find: "cw.png", replace: ".png") >> replaceText 6
url(url: "${Replace Text}") >> url 4
downloadURL(url: "${URL}") >> downloadURL 1
//Unable to get shortcuts action is.workflow.actions.appendvariable
} else {
nothing()
//Unable to get shortcuts action is.workflow.actions.appendvariable
}
} else {
// Two artists, no iTunes profile pictures
nothing()
//Unable to get shortcuts action is.workflow.actions.appendvariable
}
} >> RepeatResult 3
count(type: Items, input: Two Artist Images) >> count 10
if(Count > false) {
combineImage(images: Two Artist Images) >> combineImage 2
encode(input: Combined Image) >> encode 6
var A6E12BDD-DA56-47A8-B6C5-F0073E0C4342 = """<h2>Your favorite artists of  are:</h2>
<h2 class="centerText"> and </h2>
<img id="twoArtists" width="500" src="data:image/jpeg;charset=utf-8;base64," class="centerRound" vspace="30"></img>"""
text("${A6E12BDD-DA56-47A8-B6C5-F0073E0C4342}")
var ArtistBlock = Text
} else {
// Two equal top artists, no image
var 612C3D54-2C3C-4826-8CF3-E8DBB5FC4689 = """<h2>Your favorite artists of  are:</h2>
<h2 class="centerText"> and </h2>"""
text("${612C3D54-2C3C-4826-8CF3-E8DBB5FC4689}")
var ArtistBlock = Text
}
} else {
/*
Multiple artist counts, but the first one is DIFFERENT from the second one
Find the single artist that is paired with the highest count
*/
matchText(text: "${All Numbers and Artists}", regex: "(?m).*(${First Top Artist})\s(.*)") >> matchText 7
getItemFromList(list: Matches) >> getItemFromList 9
getMatchGroup(matches: Item from List, index: "2") >> getMatchGroup 5
var MostListenedArtist = Text
searchItunes(query: "${Most Listened Artist}", by: Artist, results: Artists, count: true) >> searchItunes 3
count(type: Items, input: iTunes Products) >> count 11
if(Count > false) {
artistDetail(property: Store URL, note: iTunes Products) >> artistDetail 1
downloadURL(url: "${Store URL}") >> downloadURL 2
htmlFromRichText(text: Contents of URL) >> htmlFromRichText 1
matchText(text: "${HTML from Rich Text}", regex: "\<meta\sproperty\=\"og\:image\"\scontent\=\"(.*?)\"") >> matchText 8
// Check if there is an artist image
count(type: Items, input: Matches) >> count 12
if(Count == "1") {
getMatchGroup(matches: Text Matches) >> getMatchGroup 6
getURLSFromInput(text: "${Text}") >> getURLSFromInput 1
replaceText(input: "${URLs}", find: "cw.png", replace: ".png") >> replaceText 7
url(url: "${Replace Text}") >> url 5
downloadURL(url: "${URL}") >> downloadURL 3
encode(input: Contents of URL) >> encode 7
// One top artist with iTunes profile picture
var F0291DB5-E41C-4FDB-ADA6-9B9DE9171EB5 = """<h2>Your favorite artist of  is:</h2>
<h2 class="centerText"></h2>
<img id="singleTopArtist" width="300" src="data:image/jpeg;charset=utf-8;base64," class="centerRound" vspace="20"></img>"""
text("${F0291DB5-E41C-4FDB-ADA6-9B9DE9171EB5}")
var ArtistBlock = Text
} else {
// One top artist, no iTunes profile picture
var E31435AE-AF4D-4196-8C4E-4442532386E4 = """<h2>Your favorite artist of  is:</h2>
<h2 class="centerText"></h2>"""
text("${E31435AE-AF4D-4196-8C4E-4442532386E4}")
var ArtistBlock = Text
}
} else {
// One top artist, no iTunes match
var FA40A781-A14F-4214-B677-9B5BD7140CBE = """<h2>Your favorite artist of  is:</h2>
<h2 class="centerText"></h2>"""
text("${FA40A781-A14F-4214-B677-9B5BD7140CBE}")
var ArtistBlock = Text
}
}
} else {
// If the user has only listened to one artist...
/*
My subtle message here is that if you have only listened to one artist in any given year, I will not give you a pretty profile picture for the artist. Music is beautiful! Go listen to some new artists, expand your horizons! Don't keep listening to the same stuff over and over and over.
My life changed when my friend Riccardo in high school convinced me to give Oasis a listen. If it weren't for him, years later I probably wouldn't have been inspired to pick up a guitar and learn Oasis songs. Which means I probably wouldn't have appeared more interesting than I actually was to the beautiful girl who would later become my girlfriend. Which means that I probably wouldn't have started MacStories in the first place!
What I'm trying to say is that music can breathe change into our lives and you never know where a new song can take you. This shortcut probably wouldn't have been created hadn't I listened to Oasis on a crappy CD player in 2004.
Go listen to some more music, starting today.
(If you have a really good reason for this, please don't get upset at me for sharing this story.)
❤
*/
matchText(text: "${All Numbers and Artists}", regex: "(?m).*(${First Top Artist})\s(.*)") >> matchText 9
getItemFromList(list: Matches) >> getItemFromList 10
getMatchGroup(matches: Item from List, index: "2") >> getMatchGroup 7
var MostListenedArtist = Text
var 86CC49E7-511A-4546-9775-82362748042E = """<h2>Your favorite artist of  is:</h2>
<h2 class="centerText"></h2>"""
text("${86CC49E7-511A-4546-9775-82362748042E}")
var ArtistBlock = Text
}
// Assemble artist top 5 (or less)
getItemFromList(list: Sorted Top Artists, type: Items in Range, startIndex: "1", endIndex: "5") >> getItemFromList 11
repeatEach(Item from List) {
// For each numeric value, get the matching artist names
matchText(text: "${All Numbers and Artists}", regex: "(?m)^\s?(${Repeat Item})\s(.+)$") >> matchText 10
getMatchGroup(matches: Matches, index: "2") >> Matching Artists
// Count how many matching artist names there are for a value
count(type: Items, input: Matching Artists) >> count 13
var MatchingArtistCount = Count
// By default, get the first match and save it as a variable
getItemFromList(list: Matching Artists) >> First Item from List
var TopArtistMatch = First Item from List
// Check if top artist #1 is already in the final variable
//Unable to get shortcuts action is.workflow.actions.getvariable
if(Artist Top 5 .contains ""${Top Artist Match}"") {
// If it contains the first match, continue with the next ones
repeat(Matching Artist Count) {
// Repeat for all the artist name matches, but only until a match is found and the Boolean is false
//Unable to get shortcuts action is.workflow.actions.getvariable
if(Bool == "False") {
} else {
/*
Start looking for other artist names NOT contained in the final variable using a 1-index list method
To start from Position #2, start at 1 and add Repeat Index
*/
math(input: Repeat Index 2, operand: "true") >> math 4
getItemFromList(list: Matching Artists, type: Item At Index, index: Calculation Result) >> Second Item from List
var TopArtistMatch = Second Item from List
// Try again with a reset variable and see if it is contained in the final variable this time
if(Artist Top 5 .contains ""${Top Artist Match}"") {
// Also contained, so continue with the next match
text(text: "True") >> text 7
var Bool = Text
} else {
// Not contained, so break the loop and add actually this artist name
text(text: "False") >> text 8
var Bool = Text
}
} >> IFResult 5
}
} else {
} >> IFResult 6
//Unable to get shortcuts action is.workflow.actions.appendvariable
} >> RepeatResult 4
splitText(text: Artist Top 5) >> splitText 6
repeatEach(Split Text) {
// Add a manual text delimiter we can use for splitting text later
text(text: "${Repeat Item} ~~TOP~~") >> text 9
//Unable to get shortcuts action is.workflow.actions.appendvariable
}
// Remove entries for duplicate artist names
combineText(text: Process Top Artists, combine: Custom, separator: "\n") >> combineText 4
var BEF03C82-CB58-4815-A382-0F840C352921 = """<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-16">
<script>
var str = ""
var result = document.getElementById('result');
var lines = str.split("\n")
var workingSet = lines
workingSet = lines.map(s => {
return s.toLowerCase()
})
var unique = []
workingSet.forEach((s, i) => {
if (workingSet.indexOf(s) == i) {
unique.push(lines[i])
}
})
document.write(unique.join("\n"));
</script>
</head>
<body>
</body>
</html>"""
text("${BEF03C82-CB58-4815-A382-0F840C352921}")
encode(input: Text) >> encode 8
url(url: "data:text/html;base64,${Base64 Encoded}") >> url 6
urlContents(url: "${URL}") >> urlContents 4
getTextFrom(input: Contents of Web Page) >> getTextFrom 4
splitText(text: Text, separator: Custom, customSeparator: " ~~TOP~~") >> splitText 7
// Remove empty lines
repeatEach(Split Text) {
count(type: Words, input: Repeat Item) >> count 14
if(Count > false) {
text(text: "${Repeat Index}. ${Variable}") >> text 10
//Unable to get shortcuts action is.workflow.actions.appendvariable
} else {
} >> IFResult 7
}
// Count how many artist names are in the Top section now
count(type: Items, input: Final Top Artists) >> count 15
combineText(text: Final Top Artists, combine: New Lines) >> combineText 5
richTextFromMarkdown(markdown: Combined Text) >> richTextFromMarkdown
htmlFromRichText(text: Rich Text from Markdown) >> htmlFromRichText 2
var 0EAFAB5D-E940-424F-9DAD-88F647FB94D0 = """<h2 class="centerText">Your Top  Artists</h2>
<p>Here are your top  artists of :</p>
"""
text("${0EAFAB5D-E940-424F-9DAD-88F647FB94D0}")
var Top5ArtistsBlock = Text
// Start assembling HTML
combineText(text: Top 10, combine: New Lines) >> combineText 6
richTextFromMarkdown(markdown: Combined Text) >> richTextFromMarkdown 1
htmlFromRichText(text: Rich Text from Markdown) >> htmlFromRichText 3
// Ask to generate PDF report for music summary
var 403B5EF5-072B-4711-A09E-BBFF98CCE5C8 = """BEGIN:VCARD
VERSION:3.0
N;CHARSET=utf-8:Yes, Create PDF;;;
ORG:Save a PDF version of the report to Files;
item4.URL:
PHOTO;ENCODING=b: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
END:VCARD"""
text("${403B5EF5-072B-4711-A09E-BBFF98CCE5C8}")
//Unable to get shortcuts action is.workflow.actions.appendvariable
var D87DB7DB-7272-4DEA-A5D3-999647FF225F = """BEGIN:VCARD
VERSION:3.0
N;CHARSET=utf-8:Yes, Create PDF + Upload to Dropbox;;;
ORG:Save a PDF version of the report to Dropbox;
item4.URL:
PHOTO;ENCODING=b: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
END:VCARD"""
text("${D87DB7DB-7272-4DEA-A5D3-999647FF225F}")
//Unable to get shortcuts action is.workflow.actions.appendvariable
var 84A17EC4-510D-4B22-9CEB-9DAD67CBB5B2 = """BEGIN:VCARD
VERSION:3.0
N;CHARSET=utf-8:Nope;;;
ORG:Just Continue to Preview;
item4.URL:
PHOTO;ENCODING=b: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
END:VCARD"""
text("${84A17EC4-510D-4B22-9CEB-9DAD67CBB5B2}")
//Unable to get shortcuts action is.workflow.actions.appendvariable
combineText(text: List Contacts, combine: New Lines) >> combineText 7
setName(input: Combined Text, name: "Options.vcf") >> setName
list(items: (
{
WFItemType = 0;
WFValue = {
Value = {
attachmentsByRange = {
"{0, 1}" = {
Aggrandizements = (
{
CoercionItemClass = WFContactContentItem;
Type = WFCoercionVariableAggrandizement;
}
);
OutputName = "Set Name";
OutputUUID = "00F46A44-34C2-41F7-9D59-EDD8049A5201";
Type = ActionOutput;
};
};
string = "\Ufffc";
};
WFSerializationType = WFTextTokenString;
};
}
)) >> list 1
choose(list: List, prompt: "Save Report for ${Selected Year}? ") >> choose
if(Chosen Item == "Yes, Create PDF") {
var 7235C607-E9D7-47DE-B3F8-BFF73E852617 = """<h1 class="centerText">Your  in Music</h1>
<img id="albumCovers" width="500" src="data:image/jpeg;charset=utf-8;base64," class="centerRound" vspace="30"></img>
<h2>Your most played song of the year is:</h2>
<h2 class="centerText"></h2>
<h3 class="centerText">(You've listened to this song for a total of  hours, or  times.)</h3>
<h2 class="centerText">Your Top 10 Songs</h2>
<p>Here are your top 10 songs of :</p>




<h3 class="centerText">(Genres calculated based on your top  songs of the year.)</h3>
<h2 class="centerText">Share Your #Top9</h2>
<img id="top9" width="500" src="data:image/jpeg;charset=utf-8;base64," class="centerRound" vspace="30"></img>
<h3>Your  most listened songs have an average track duration of  minutes. All together, they have a total duration of  hours.</h3>
<h3>In total, you've listened to your Top  songs  hours this year (that's  minutes).</h3>
<h3>(That's the number of times you've listened to each song in full, without skipping.)</h3>
"""
text("${7235C607-E9D7-47DE-B3F8-BFF73E852617}")
var 7D59D941-6DB5-44B2-9978-B5A44CBDA50B = """<head>
<meta name="viewport" content="initial-scale=1.0" viewport-fit=cover>
<meta charset="utf-8">
<style>
body {
background-image: linear-gradient(to right, #FC7046, #C451C3);
}
h1{
font-family: -apple-system;
color: white;
font-weight: 800;
font-size: 3em;
}
h2 {
font-family: -apple-system;
font-weight: 800;
color: white;
font-size: 2em;
}
h3,h4 {
font-family: -apple-system;
font-weight: 800;
color: white;
font-size: 1.5em;
}
p, ul{
font-family: -apple-system;
font-weight: 400;
color: white;
font-size: 1.5em;
}
ol{
font-family: -apple-system;
font-weight: 400;
color: white;
font-size: 1.5em;
margin: 15px;
}
a {
color: white;
}
.center {
display: block;
margin-left: auto;
margin-right: auto;
}
.centerText {
text-align: center;
}
.centerRound {
display: block;
margin-left: auto;
margin-right: auto;
border-radius: 8px;
max-width: 100%;
height: auto;
}
</style>
<title>Your  in Music</title>

</head>"""
text("${7D59D941-6DB5-44B2-9978-B5A44CBDA50B}")
richTextFromHTML() >> richTextFromHTML
createPDF(input: Rich Text from HTML) >> createPDF
setName(input: PDF, name: "${Playlist Name}") >> setName 1
saveFile(input: Renamed Item)
} else {
if(Chosen Item .contains "Dropbox") {
var 8C28E3C6-0254-4018-8F49-A3A0AA6BAC31 = """<h1 class="centerText">Your  in Music</h1>
<img id="albumCovers" width="500" src="data:image/jpeg;charset=utf-8;base64," class="centerRound" vspace="30"></img>
<h2>Your most played song of the year is:</h2>
<h2 class="centerText"></h2>
<h3 class="centerText">(You've listened to this song for a total of  hours, or  times.)</h3>
<h2 class="centerText">Your Top 10 Songs</h2>
<p>Here are your top 10 songs of :</p>




<h3 class="centerText">(Genres calculated based on your top  songs of the year.)</h3>
<h2 class="centerText">Share Your #Top9</h2>
<img id="top9" width="500" src="data:image/jpeg;charset=utf-8;base64," class="centerRound" vspace="30"></img>
<h3>Your  most listened songs have an average track duration of  minutes. All together, they have a total duration of  hours.</h3>
<h3>In total, you've listened to your Top  songs  hours this year (that's  minutes).</h3>
<h3>(That's the number of times you've listened to each song in full, without skipping.)</h3>
"""
text("${8C28E3C6-0254-4018-8F49-A3A0AA6BAC31}")
var CD668CBC-1CCE-444D-B5B6-659BFDE55FFE = """<head>
<meta name="viewport" content="initial-scale=1.0" viewport-fit=cover>
<meta charset="utf-8">
<style>
body {
background-image: linear-gradient(to right, #FC7046, #C451C3);
}
h1{
font-family: -apple-system;
color: white;
font-weight: 800;
font-size: 3em;
}
h2 {
font-family: -apple-system;
font-weight: 800;
color: white;
font-size: 2em;
}
h3,h4 {
font-family: -apple-system;
font-weight: 800;
color: white;
font-size: 1.5em;
}
p, ul{
font-family: -apple-system;
font-weight: 400;
color: white;
font-size: 1.5em;
}
ol{
font-family: -apple-system;
font-weight: 400;
color: white;
font-size: 1.5em;
margin: 15px;
}
a {
color: white;
}
.center {
display: block;
margin-left: auto;
margin-right: auto;
}
.centerText {
text-align: center;
}
.centerRound {
display: block;
margin-left: auto;
margin-right: auto;
border-radius: 8px;
max-width: 100%;
height: auto;
}
</style>
<title>Your  in Music</title>

</head>"""
text("${CD668CBC-1CCE-444D-B5B6-659BFDE55FFE}")
richTextFromHTML() >> richTextFromHTML 1
createPDF(input: Rich Text from HTML) >> createPDF 1
setName(input: PDF, name: "${Playlist Name}") >> setName 2
saveFile(input: Renamed Item, ask: false, path: "/") >> saveFile
getFileLink(file: Saved File) >> getFileLink
setClipboard(variable: Link to File)
alert(alert: "Link copied to the clipboard:
${Link to File}
Continue to open the full report in Safari.", title: "Link to ${Playlist Name}.pdf Copied")
} else {
if(Chosen Item == "Nope") {
nothing()
} else {
}
}
}
// Prepare final webpage and open in Safari
sendNotification(body: "Assembling final report. Safari will open shortly.", title: "${Playlist Name}", sound: false, attachment: Top 9 Image)
// Encoded apple-touch-icon image file
var E388903D-50E1-420F-ABB6-C0DFF89269B9 = """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