cifraclub-wrapper 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,606 @@
1
+ ````md
2
+ # cifraclub-wrapper
3
+
4
+ Wrapper em TypeScript para buscar, listar, baixar e transpor cifras do Cifra Club.
5
+
6
+ A biblioteca permite:
7
+
8
+ - pesquisar músicas
9
+ - listar músicas de um songbook
10
+ - baixar cifras completas
11
+ - transpor tons
12
+ - ajustar capo
13
+ - filtrar apenas letras, acordes ou remover tablaturas
14
+
15
+ Ela expõe uma API simples para trabalhar com metadados e conteúdo processado das cifras.
16
+
17
+ ## Instalação
18
+
19
+ ```bash
20
+ npm install cifraclub-wrapper
21
+ ````
22
+
23
+ ou
24
+
25
+ ```bash
26
+ yarn add cifraclub-wrapper
27
+ ```
28
+
29
+ ## Importação
30
+
31
+ ```ts
32
+ import CifraClub from 'cifraclub-wrapper'
33
+ ```
34
+
35
+ Também é possível importar os tipos e classes auxiliares:
36
+
37
+ ```ts
38
+ import CifraClub, { Cifra, CifraList, CifraMeta } from 'cifraclub-wrapper'
39
+ ```
40
+
41
+ ## Visão geral
42
+
43
+ A biblioteca possui três estruturas principais:
44
+
45
+ ### `CifraClub`
46
+
47
+ Classe principal da API.
48
+
49
+ Responsável por:
50
+
51
+ * pesquisar músicas
52
+ * listar músicas de um songbook
53
+ * baixar várias cifras
54
+ * carregar uma cifra individual
55
+
56
+ ### `Cifra`
57
+
58
+ Representa uma cifra individual já carregada.
59
+
60
+ Permite:
61
+
62
+ * acessar metadados
63
+ * acessar conteúdo estruturado
64
+ * transpor a cifra
65
+ * alterar capo
66
+ * extrair apenas letras
67
+ * extrair apenas acordes
68
+ * remover tablaturas
69
+
70
+ ### `CifraList`
71
+
72
+ Representa uma coleção de cifras.
73
+
74
+ Permite aplicar filtros em lote, como:
75
+
76
+ * `lyrics()`
77
+ * `chords()`
78
+ * `noTabs()`
79
+
80
+ ---
81
+
82
+ ## Exemplo rápido
83
+
84
+ ```ts
85
+ import CifraClub from 'cifraclub-wrapper'
86
+
87
+ async function main() {
88
+ const results = await CifraClub.search('quanta coisa tenho feito')
89
+
90
+ if (!results.length) return
91
+
92
+ const cifra = await CifraClub.get(results[0])
93
+
94
+ if (!cifra) return
95
+
96
+ console.log(cifra.metadata)
97
+ console.log(cifra.data)
98
+ }
99
+
100
+ main()
101
+ ```
102
+
103
+ ---
104
+
105
+ ## API
106
+
107
+ ## `CifraClub.search(search: string): Promise<CifraMeta[]>`
108
+
109
+ Pesquisa músicas no Cifra Club a partir de um texto.
110
+
111
+ ### Exemplo
112
+
113
+ ```ts
114
+ const results = await CifraClub.search('Aclame ao Senhor')
115
+
116
+ console.log(results)
117
+ ```
118
+
119
+ ### Retorno
120
+
121
+ Um array de objetos `CifraMeta` com dados básicos da música encontrada.
122
+
123
+ ### Observação
124
+
125
+ O retorno da busca é inicial e pode não conter todos os campos completos até que a cifra seja carregada com `get()`.
126
+
127
+ ---
128
+
129
+ ## `CifraClub.list(id: string): Promise<CifraMeta[]>`
130
+
131
+ Lista as músicas de um songbook pelo ID.
132
+
133
+ ### Exemplo
134
+
135
+ ```ts
136
+ const musics = await CifraClub.list('123456')
137
+
138
+ console.log(musics)
139
+ ```
140
+
141
+ ### Retorno
142
+
143
+ Um array de `CifraMeta` com informações mais completas, incluindo:
144
+
145
+ * tom original
146
+ * capo
147
+ * afinação
148
+ * versão
149
+ * id da música
150
+ * autor
151
+
152
+ ---
153
+
154
+ ## `CifraClub.get(data: CifraMeta): Promise<Cifra | boolean>`
155
+
156
+ Carrega uma cifra a partir de um objeto `CifraMeta`.
157
+
158
+ ### Exemplo
159
+
160
+ ```ts
161
+ const results = await CifraClub.search('Porque Ele Vive')
162
+ const cifra = await CifraClub.get(results[0])
163
+
164
+ if (cifra) {
165
+ console.log(cifra.metadata)
166
+ console.log(cifra.data)
167
+ }
168
+ ```
169
+
170
+ ### Retorno
171
+
172
+ Retorna uma instância de `Cifra` em caso de sucesso, ou `false` em caso de erro.
173
+
174
+ ---
175
+
176
+ ## `CifraClub.downloadList(data?: CifraMeta[]): Promise<CifraList>`
177
+
178
+ Baixa várias cifras e devolve uma coleção `CifraList`.
179
+
180
+ ### Exemplo
181
+
182
+ ```ts
183
+ const musics = await CifraClub.list('123456')
184
+ const cifras = await CifraClub.downloadList(musics)
185
+
186
+ console.log(cifras.data)
187
+ ```
188
+
189
+ ---
190
+
191
+ # Classe `Cifra`
192
+
193
+ Representa uma cifra já carregada e processada.
194
+
195
+ ## Propriedades
196
+
197
+ ### `html_url: string`
198
+
199
+ URL pública da cifra no site.
200
+
201
+ ### `metadata`
202
+
203
+ Retorna os metadados da cifra.
204
+
205
+ ```ts
206
+ console.log(cifra.metadata)
207
+ ```
208
+
209
+ ### `data`
210
+
211
+ Retorna o conteúdo estruturado da cifra.
212
+
213
+ ```ts
214
+ console.log(cifra.data)
215
+ ```
216
+
217
+ Formato do conteúdo:
218
+
219
+ ```ts
220
+ Array<{
221
+ type: string
222
+ text: string
223
+ }>
224
+ ```
225
+
226
+ Exemplo:
227
+
228
+ ```ts
229
+ [
230
+ { type: 'indicator_chords', text: '[Intro] C G Am F' },
231
+ { type: 'lyrics', text: 'Quanta coisa tenho feito...' },
232
+ { type: 'chords', text: 'C G Am F' }
233
+ ]
234
+ ```
235
+
236
+ ---
237
+
238
+ ## Métodos
239
+
240
+ ## `await cifra.get()`
241
+
242
+ Carrega ou recarrega a cifra.
243
+
244
+ ### Exemplo
245
+
246
+ ```ts
247
+ await cifra.get()
248
+ ```
249
+
250
+ ---
251
+
252
+ ## `cifra.lyrics(): Cifra`
253
+
254
+ Retorna uma nova instância contendo apenas linhas de letra.
255
+
256
+ ### Exemplo
257
+
258
+ ```ts
259
+ const lyricsOnly = cifra.lyrics()
260
+
261
+ console.log(lyricsOnly.data)
262
+ ```
263
+
264
+ ---
265
+
266
+ ## `cifra.chords(): Cifra`
267
+
268
+ Retorna uma nova instância contendo apenas linhas de acordes e indicadores.
269
+
270
+ ### Exemplo
271
+
272
+ ```ts
273
+ const chordsOnly = cifra.chords()
274
+
275
+ console.log(chordsOnly.data)
276
+ ```
277
+
278
+ ---
279
+
280
+ ## `cifra.noTabs(): Cifra`
281
+
282
+ Retorna uma nova instância sem linhas de tablatura.
283
+
284
+ ### Exemplo
285
+
286
+ ```ts
287
+ const semTabs = cifra.noTabs()
288
+
289
+ console.log(semTabs.data)
290
+ ```
291
+
292
+ ---
293
+
294
+ ## `await cifra.transpose(halfsteps = 0)`
295
+
296
+ Transpõe a cifra em semitons.
297
+
298
+ ### Exemplo
299
+
300
+ ```ts
301
+ await cifra.transpose(2) // sobe 2 semitons
302
+ await cifra.transpose(-1) // desce 1 semitom
303
+ ```
304
+
305
+ ### Observação
306
+
307
+ A transposição altera o conteúdo carregado da cifra.
308
+
309
+ ---
310
+
311
+ ## `await cifra.capo(capo = 0)`
312
+
313
+ Altera o capo da música e recalcula o tom exibido nos metadados.
314
+
315
+ ### Exemplo
316
+
317
+ ```ts
318
+ await cifra.capo(2)
319
+
320
+ console.log(cifra.metadata.tone)
321
+ ```
322
+
323
+ ---
324
+
325
+ # Classe `CifraList`
326
+
327
+ Coleção de cifras.
328
+
329
+ ## Propriedade
330
+
331
+ ### `data: Cifra[]`
332
+
333
+ Array com todas as cifras carregadas.
334
+
335
+ ---
336
+
337
+ ## Métodos
338
+
339
+ ## `push(...items)`
340
+
341
+ Adiciona cifras à lista.
342
+
343
+ ```ts
344
+ list.push(cifra1, cifra2)
345
+ ```
346
+
347
+ ## `lyrics(): CifraList`
348
+
349
+ Aplica `lyrics()` em todas as cifras da lista.
350
+
351
+ ```ts
352
+ const onlyLyrics = list.lyrics()
353
+ ```
354
+
355
+ ## `chords(): CifraList`
356
+
357
+ Aplica `chords()` em todas as cifras da lista.
358
+
359
+ ```ts
360
+ const onlyChords = list.chords()
361
+ ```
362
+
363
+ ## `noTabs(): CifraList`
364
+
365
+ Remove tablaturas de todas as cifras da lista.
366
+
367
+ ```ts
368
+ const noTabs = list.noTabs()
369
+ ```
370
+
371
+ ---
372
+
373
+ # Tipo `CifraMeta`
374
+
375
+ Estrutura de metadados usada pela biblioteca.
376
+
377
+ ```ts
378
+ type CifraMeta = {
379
+ path: string
380
+ position: number
381
+ hash: URLSearchParams
382
+ name: string
383
+ author: string
384
+ tone_songbook: string
385
+ capo_songbook: number
386
+ tone: string
387
+ id: string
388
+ tuning: string
389
+ version: string
390
+ minor: boolean
391
+ }
392
+ ```
393
+
394
+ ## Campos principais
395
+
396
+ ### `name`
397
+
398
+ Nome da música.
399
+
400
+ ### `author`
401
+
402
+ Nome do artista ou autor.
403
+
404
+ ### `tone_songbook`
405
+
406
+ Tom original informado no songbook.
407
+
408
+ ### `capo_songbook`
409
+
410
+ Capotraste original informado.
411
+
412
+ ### `tone`
413
+
414
+ Tom calculado considerando capo.
415
+
416
+ ### `tuning`
417
+
418
+ Afinação da música.
419
+
420
+ ### `version`
421
+
422
+ Versão da cifra.
423
+
424
+ ### `minor`
425
+
426
+ Indica se a música está em tonalidade menor.
427
+
428
+ ---
429
+
430
+ # Tipos de linha no conteúdo
431
+
432
+ O conteúdo processado da cifra é dividido em linhas com tipos.
433
+
434
+ Os tipos mais comuns são:
435
+
436
+ ### `lyrics`
437
+
438
+ Linha de letra.
439
+
440
+ ### `chords`
441
+
442
+ Linha de acordes.
443
+
444
+ ### `tab`
445
+
446
+ Linha de tablatura.
447
+
448
+ ### `indicator_lyrics`
449
+
450
+ Linha de seção com letra, como `[Refrão]`.
451
+
452
+ ### `indicator_chords`
453
+
454
+ Linha de seção com acordes, como `[Intro]`.
455
+
456
+ ### `empty`
457
+
458
+ Linha vazia.
459
+
460
+ ---
461
+
462
+ # Exemplos completos
463
+
464
+ ## Buscar e carregar a primeira música encontrada
465
+
466
+ ```ts
467
+ import CifraClub from 'cifraclub-wrapper'
468
+
469
+ async function main() {
470
+ const results = await CifraClub.search('Aclame ao Senhor')
471
+
472
+ if (!results.length) {
473
+ console.log('Nenhuma música encontrada')
474
+ return
475
+ }
476
+
477
+ const cifra = await CifraClub.get(results[0])
478
+
479
+ if (!cifra) {
480
+ console.log('Erro ao carregar cifra')
481
+ return
482
+ }
483
+
484
+ console.log('Metadados:', cifra.metadata)
485
+ console.log('Conteúdo:', cifra.data)
486
+ }
487
+
488
+ main()
489
+ ```
490
+
491
+ ## Baixar várias cifras de um songbook
492
+
493
+ ```ts
494
+ import CifraClub from 'cifraclub-wrapper'
495
+
496
+ async function main() {
497
+ const musics = await CifraClub.list('123456')
498
+ const list = await CifraClub.downloadList(musics)
499
+
500
+ console.log(list.data.length)
501
+ }
502
+
503
+ main()
504
+ ```
505
+
506
+ ## Trabalhar apenas com letras
507
+
508
+ ```ts
509
+ const cifra = await CifraClub.get(meta)
510
+
511
+ if (cifra) {
512
+ const onlyLyrics = cifra.lyrics()
513
+ console.log(onlyLyrics.data)
514
+ }
515
+ ```
516
+
517
+ ## Trabalhar apenas com acordes
518
+
519
+ ```ts
520
+ const cifra = await CifraClub.get(meta)
521
+
522
+ if (cifra) {
523
+ const onlyChords = cifra.chords()
524
+ console.log(onlyChords.data)
525
+ }
526
+ ```
527
+
528
+ ## Remover tablaturas
529
+
530
+ ```ts
531
+ const cifra = await CifraClub.get(meta)
532
+
533
+ if (cifra) {
534
+ const clean = cifra.noTabs()
535
+ console.log(clean.data)
536
+ }
537
+ ```
538
+
539
+ ## Transpor música
540
+
541
+ ```ts
542
+ const cifra = await CifraClub.get(meta)
543
+
544
+ if (cifra) {
545
+ await cifra.transpose(1)
546
+ console.log(cifra.data)
547
+ }
548
+ ```
549
+
550
+ ## Ajustar capo
551
+
552
+ ```ts
553
+ const cifra = await CifraClub.get(meta)
554
+
555
+ if (cifra) {
556
+ await cifra.capo(3)
557
+ console.log(cifra.metadata.tone)
558
+ }
559
+ ```
560
+
561
+ ---
562
+
563
+ # Observações
564
+
565
+ Esta biblioteca depende da estrutura atual das respostas e páginas do Cifra Club. Mudanças no HTML ou nos endpoints utilizados podem impactar o funcionamento.
566
+
567
+ As operações de download em lote incluem pequeno intervalo entre requisições para reduzir a agressividade das chamadas.
568
+
569
+ ---
570
+
571
+ # Compatibilidade
572
+
573
+ Compatível com ambientes Node.js que suportem:
574
+
575
+ * `URLSearchParams`
576
+ * `async/await`
577
+
578
+ ---
579
+
580
+ # Licença
581
+
582
+ MIT
583
+
584
+ ```
585
+ MIT License
586
+
587
+ Copyright (c) 2026 Sebastião Jonas
588
+
589
+ Permission is hereby granted, free of charge, to any person obtaining a copy
590
+ of this software and associated documentation files (the "Software"), to deal
591
+ in the Software without restriction, including without limitation the rights
592
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
593
+ copies of the Software, and to permit persons to whom the Software is
594
+ furnished to do so, subject to the following conditions:
595
+
596
+ The above copyright notice and this permission notice shall be included in all
597
+ copies or substantial portions of the Software.
598
+
599
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
600
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
601
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
602
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
603
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
604
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
605
+ SOFTWARE.
606
+ ```
package/dist/index.d.ts CHANGED
@@ -1,15 +1,14 @@
1
1
  declare class Cifra {
2
- id: string;
3
- name: string;
4
- author: string;
5
- transpose: number;
6
- meta: CifraMeta;
7
- content: Array<{
8
- type: string;
9
- text: string;
10
- }>;
2
+ private halfsteps;
3
+ private meta;
4
+ private content;
11
5
  readonly html_url: string;
12
6
  private readonly content_url;
7
+ get metadata(): CifraMeta;
8
+ get data(): {
9
+ type: string;
10
+ text: string;
11
+ }[];
13
12
  constructor(data: CifraMeta);
14
13
  lyrics(): Cifra;
15
14
  noTabs(): Cifra;
@@ -17,6 +16,9 @@ declare class Cifra {
17
16
  private formatContent;
18
17
  get(): Promise<void>;
19
18
  private fetch;
19
+ private calculateCapo;
20
+ transpose(halfsteps?: number): Promise<void>;
21
+ capo(capo?: number): Promise<void>;
20
22
  private getContent;
21
23
  }
22
24
  declare class CifraList {
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var u=require('axios');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var u__default=/*#__PURE__*/_interopDefault(u);var C=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});var $=C("cheerio"),c=class{$;constructor(t){this.$=$.load(t,{decodeEntities:false});}find(t){return this.$(t)}setText(t,r){return this.$(t).text(r),this}setHtml(t,r){return this.$(t).html(r),this}addClass(t,r){return this.$(t).addClass(r),this}setAttr(t,r,s){return this.$(t).attr(r,s),this}remove(t){return this.$(t).remove(),this}each(t,r){return this.$(t).each((s,e)=>r(this.$(e),s)),this}extractText(t){return this.$(t).text().trim()}extractList(t){return this.$(t).map((r,s)=>this.$(s).text().trim()).get()}html(){return this.$.html()}};var w=a=>`https://solr.sscdn.co/cc/h2/?q=${encodeURIComponent(a)}&callback`,f={accept:"*/*","accept-language":"pt-BR,pt;q=0.9",origin:"https://www.cifraclub.com.br",priority:"u=1, i",referer:"https://www.cifraclub.com.br/","sec-ch-ua":'"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',"sec-ch-ua-mobile":"?0","sec-ch-ua-platform":'"Windows"',"sec-fetch-dest":"empty","sec-fetch-mode":"cors","sec-fetch-site":"same-site","user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36"},d="https://api.cifraclub.com.br/v3",_="https://www.cifraclub.com.br",b={start:/#t\d+#/g,end:/#\/t\d+#/g};function A(a,t,r=false,s=12){if(!r)return (t-a+s)%s;let e=(t-a)%s;return e>s/2&&(e-=s),e<-s/2&&(e+=s),e}var x=(a=0,t=false,r=false)=>`${["A",t?"A#":"Bb","B","C",t?"C#":"Db","D",t?"D#":"Eb","E","F",t?"F#":"Gb","G",t?"G#":"Ab"][a]}${r?"m":""}`,g=(a,t=false)=>{let r=["A",["Bb","A#"],["B","Cb"],["C","B#"],["Db","C#"],"D",["D#","Eb"],["E","Fb"],["F","E#"],["F#","Gb"],"G",["Ab","G#"]],s=false;return r.forEach((e,n)=>{s!==false&&typeof e=="string"||(typeof e=="string"&&a.startsWith(e)&&(s=t?new RegExp(e,"g"):n),Array.isArray(e)&&e.forEach(i=>{a.startsWith(i)&&(s=t?new RegExp(e.join("|"),"g"):n);}));}),s};function E(a){return new Promise(t=>setTimeout(t,a))}var v=/\b[A-G](?:#|b)?(?:maj|min|m|dim|aug|sus|add)?\d*(?:\([^)]+\))?(?:\/[A-G](?:#|b)?)?\b/g,p=class{id="";name="";author="";transpose=0;meta;content=[];html_url;content_url="";constructor(t){this.html_url=`${_}${t.path}`,this.content_url=`${d}/song/${t.id}/${t.hash.get("instrument")}/${t.version}/transpose`,this.meta=t;}lyrics(){return {...this,content:this.content.filter(t=>t.type.includes("lyrics"))}}noTabs(){return {...this,content:this.content.filter(t=>t.type!=="tab")}}chords(){return {...this,content:this.content.filter(t=>t.type.includes("chords")||t.type.includes("indicator_"))}}formatContent(t){this.content=t.split(`
2
- `).map(r=>{let s=r.match(/<\/?b>/gi),n=r.includes("|")&&r.includes("--")&&/A|B|C|D|E|F|G/i.test(r)?"tab":s?"chords":"lyrics";return r=r.replace(b.start,"").replace(b.end,""),r.includes("[")&&r.includes("]")&&(n=`indicator_${n}`),r.trim().length==0&&(n="empty"),{type:n,text:r.trimEnd().replace(/<\/?b>/gi,"")}}).filter((r,s,e)=>{if(s===0)return true;let n=e[s-1].type=="empty";return !(r.type=="empty"&&n)});}async get(){await this.fetch();}async fetch(){let t=await u__default.default.get(this.html_url,{headers:f}),r=new c(t.data),[s,e]=r.find("#cifra_tom").text().match(v),n=g(e||s),i=r.find("#cifra_capo").text();if(!this.meta.capo_songbook&&i){let[y]=i.match(/\d+/g);this.meta.capo_songbook=parseInt(y);}let o=g(this.meta.tone_songbook);this.transpose=A(o,n,true);let m=o+this.meta.capo_songbook;m>=12&&(m-=12),this.meta.tone=x(m,true,this.meta.minor),await this.getContent();}async getContent(){let t=await u__default.default.get(`${this.content_url}?halfSteps=${this.transpose}&newFormat=false`,{headers:f});this.formatContent(t.data?.content||"");}},l=class a{data;constructor(t=[]){this.data=t;}push(...t){this.data.push(...t);}lyrics(){return new a(this.data.map(t=>t.lyrics()))}noTabs(){return new a(this.data.map(t=>t.noTabs()))}chords(){return new a(this.data.map(t=>t.chords()))}},h=class a{static async search(t){let r=w(t);try{let n=(await u__default.default.get(r)).data.trim().slice(1,-1);return JSON.parse(n).response.docs.map(o=>({path:`${o.d}/${o.u}`,hash:new URLSearchParams(""),name:o.m,author:o.a,position:0}))}catch{return []}}static async list(t){try{return (await u__default.default.get(`${d}/songbook/${t}`,{headers:f})).data?.songs?.map((s,e)=>{let[,n]=s.siteUrl.split("#"),i=s.apiUrl.split("version/")[1];return {position:e,path:`${s.apiUrl}${i?`/${i}.html`:""}`,hash:new URLSearchParams(n||""),name:s.name,author:s.artist.name,id:s.songId,tone_songbook:s.stdTone,tuning:s.tuning,version:i||"principal",capo_songbook:s.capo||0,minor:s.minor}})}catch(r){console.error(r);}return []}static async downloadList(t=[]){let r=new l;try{for(let s of t){console.log(`${s.name} - ${s.author} (${s.tone_songbook})`);let e=await a.get(s);e instanceof p&&r.push(e),await E(100);}}catch(s){console.error(s);}return r}static async get(t){try{let r=new p(t);return await r.get(),r}catch(r){console.log(r);}return false}};var T=h;exports.Cifra=p;exports.CifraList=l;exports.default=T;
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var l=require('axios');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var l__default=/*#__PURE__*/_interopDefault(l);var y=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});var C=y("cheerio"),c=class{$;constructor(t){this.$=C.load(t,{decodeEntities:false});}find(t){return this.$(t)}setText(t,r){return this.$(t).text(r),this}setHtml(t,r){return this.$(t).html(r),this}addClass(t,r){return this.$(t).addClass(r),this}setAttr(t,r,e){return this.$(t).attr(r,e),this}remove(t){return this.$(t).remove(),this}each(t,r){return this.$(t).each((e,s)=>r(this.$(s),e)),this}extractText(t){return this.$(t).text().trim()}extractList(t){return this.$(t).map((r,e)=>this.$(e).text().trim()).get()}html(){return this.$.html()}};var _=a=>`https://solr.sscdn.co/cc/h2/?q=${encodeURIComponent(a)}&callback`,f={accept:"*/*","accept-language":"pt-BR,pt;q=0.9",origin:"https://www.cifraclub.com.br",priority:"u=1, i",referer:"https://www.cifraclub.com.br/","sec-ch-ua":'"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',"sec-ch-ua-mobile":"?0","sec-ch-ua-platform":'"Windows"',"sec-fetch-dest":"empty","sec-fetch-mode":"cors","sec-fetch-site":"same-site","user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36"},b="https://api.cifraclub.com.br/v3",$="https://www.cifraclub.com.br",g={start:/#t\d+#/g,end:/#\/t\d+#/g};function w(a,t,r=false,e=12){if(!r)return (t-a+e)%e;let s=(t-a)%e;return s>e/2&&(s-=e),s<-e/2&&(s+=e),s}var A=(a=0,t=false,r=false)=>`${["A",t?"A#":"Bb","B","C",t?"C#":"Db","D",t?"D#":"Eb","E","F",t?"F#":"Gb","G",t?"G#":"Ab"][a]}${r?"m":""}`,m=(a,t=false)=>{let r=["A",["Bb","A#"],["B","Cb"],["C","B#"],["Db","C#"],"D",["D#","Eb"],["E","Fb"],["F","E#"],["F#","Gb"],"G",["Ab","G#"]],e=false;return r.forEach((s,n)=>{e!==false&&typeof s=="string"||(typeof s=="string"&&a.startsWith(s)&&(e=t?new RegExp(s,"g"):n),Array.isArray(s)&&s.forEach(i=>{a.startsWith(i)&&(e=t?new RegExp(s.join("|"),"g"):n);}));}),e};function x(a){return new Promise(t=>setTimeout(t,a))}var E=/\b[A-G](?:#|b)?(?:maj|min|m|dim|aug|sus|add)?\d*(?:\([^)]+\))?(?:\/[A-G](?:#|b)?)?\b/g,h=class{halfsteps=0;meta;content=[];html_url;content_url="";get metadata(){return this.meta}get data(){return this.content}constructor(t){this.html_url=`${$}${t.path}`,this.content_url=`${b}/song/${t.id}/${t.hash.get("instrument")}/${t.version}/transpose`,this.meta=t;}lyrics(){return {...this,content:this.content.filter(t=>t.type.includes("lyrics"))}}noTabs(){return {...this,content:this.content.filter(t=>t.type!=="tab")}}chords(){return {...this,content:this.content.filter(t=>t.type.includes("chords")||t.type.includes("indicator_"))}}formatContent(t){this.content=t.split(`
2
+ `).map(r=>{let e=r.match(/<\/?b>/gi),n=r.includes("|")&&r.includes("--")&&/A|B|C|D|E|F|G/i.test(r)?"tab":e?"chords":"lyrics";return r=r.replace(g.start,"").replace(g.end,""),r.includes("[")&&r.includes("]")&&(n=`indicator_${n}`),r.trim().length==0&&(n="empty"),{type:n,text:r.trimEnd().replace(/<\/?b>/gi,"")}}).filter((r,e,s)=>{if(e===0)return true;let n=s[e-1].type=="empty";return !(r.type=="empty"&&n)});}async get(){await this.fetch();}async fetch(){let t=await l__default.default.get(this.html_url,{headers:f}),r=new c(t.data),[e,s]=r.find("#cifra_tom").text().match(E),n=m(s||e),i=r.find("#cifra_capo").text();if(!this.meta.capo_songbook&&i){let[d]=i.match(/\d+/g);this.meta.capo_songbook=parseInt(d);}let o=m(this.meta.tone_songbook);this.halfsteps=w(o,n,true),this.calculateCapo(),await this.getContent();}calculateCapo(){let r=m(this.meta.tone_songbook)+this.meta.capo_songbook;r>=12&&(r-=12),this.meta.tone=A(r,true,this.meta.minor);}async transpose(t=0){this.halfsteps+=t,await this.getContent();}async capo(t=0){this.meta.capo_songbook=t,this.calculateCapo();}async getContent(){let t=await l__default.default.get(`${this.content_url}?halfSteps=${this.halfsteps}&newFormat=false`,{headers:f});this.formatContent(t.data?.content||"");}},u=class a{data;constructor(t=[]){this.data=t;}push(...t){this.data.push(...t);}lyrics(){return new a(this.data.map(t=>t.lyrics()))}noTabs(){return new a(this.data.map(t=>t.noTabs()))}chords(){return new a(this.data.map(t=>t.chords()))}},p=class a{static async search(t){let r=_(t);try{let n=(await l__default.default.get(r)).data.trim().slice(1,-1);return JSON.parse(n).response.docs.map(o=>({path:`${o.d}/${o.u}`,hash:new URLSearchParams(""),name:o.m,author:o.a,position:0}))}catch{return []}}static async list(t){try{return (await l__default.default.get(`${b}/songbook/${t}`,{headers:f})).data?.songs?.map((e,s)=>{let[,n]=e.siteUrl.split("#"),i=e.apiUrl.split("version/")[1];return {position:s,path:`${e.apiUrl}${i?`/${i}.html`:""}`,hash:new URLSearchParams(n||""),name:e.name,author:e.artist.name,id:e.songId,tone_songbook:e.stdTone,tuning:e.tuning,version:i||"principal",capo_songbook:e.capo||0,minor:e.minor}})}catch(r){console.error(r);}return []}static async downloadList(t=[]){let r=new u;try{for(let e of t){console.log(`${e.name} - ${e.author} (${e.tone_songbook})`);let s=await a.get(e);s instanceof h&&r.push(s),await x(100);}}catch(e){console.error(e);}return r}static async get(t){try{let r=new h(t);return await r.get(),r}catch(r){console.log(r);}return false}};var M=p;exports.Cifra=h;exports.CifraList=u;exports.default=M;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "cifraclub-wrapper",
3
3
  "main": "./dist/index.js",
4
4
  "types": "./dist/index.d.ts",
5
- "version": "1.0.1",
5
+ "version": "1.0.2",
6
6
  "type": "commonjs",
7
7
  "files": [
8
8
  "dist"