scoredl 0.1.0__tar.gz

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.
scoredl-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.4
2
+ Name: scoredl
3
+ Version: 0.1.0
4
+ Summary: CLI tool to download and assemble MuseScore sheets into high-quality PDFs
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: playwright>=1.40.0
8
+ Requires-Dist: svglib>=1.5.0
9
+ Requires-Dist: reportlab>=4.0.0
10
+ Requires-Dist: pypdf>=4.0.0
11
+
12
+ # ๐ŸŽผ scoredl
13
+
14
+ CLI tool sederhana berbasis Python untuk mengunduh partitur musik dari **MuseScore** dan mengonversinya langsung menjadi satu file PDF utuh berkualitas tinggi (lossless SVG).
15
+
16
+ ![Python](https://img.shields.io/badge/python-3.10+-blue)
17
+ ![Playwright](https://img.shields.io/badge/automation-Playwright-2EAD33)
18
+
19
+ ## Fitur
20
+
21
+ - ๐Ÿ”„ Auto-scroll & lazy load handling via Playwright
22
+ - ๐Ÿ–ผ๏ธ Konversi vektor SVG murni langsung ke lembaran PDF (lossless)
23
+ - ๐Ÿท๏ธ Penamaan file otomatis berdasarkan metadata judul lagu
24
+ - ๐Ÿ“‚ Opsi simpan file SVG mentah ke subfolder terpisah (`--keep-svg`)
25
+ - ๐Ÿงน Pembersihan file temporary otomatis setelah proses selesai
26
+
27
+ ## Instalasi
28
+
29
+ **Metode 1 โ€” via PyPI (disarankan)**
30
+ ```bash
31
+ pip install scoredl
32
+ playwright install chromium
33
+ ```
34
+
35
+ **Metode 2 โ€” manual (mode developer)**
36
+ ```bash
37
+ git clone https://github.com/RyhmnyRin/scoredl.git
38
+ cd scoredl
39
+ python -m venv .venv
40
+
41
+ # Windows PowerShell
42
+ .venv\Scripts\Activate.ps1
43
+
44
+ # Linux/macOS
45
+ source .venv/bin/activate
46
+
47
+ pip install -e .
48
+ playwright install chromium
49
+ ```
50
+
51
+ ## Penggunaan
52
+
53
+ ```bash
54
+ scoredl "https://musescore.com/user/xxxx/scores/yyyy"
55
+ ```
56
+
57
+ Tentukan nama file output:
58
+ ```bash
59
+ scoredl "https://musescore.com/user/xxxx/scores/yyyy" -o "NamaLagu.pdf"
60
+ ```
61
+
62
+ Simpan juga file SVG mentahnya (tersimpan di `saved_svgs/<Judul Lagu>/`):
63
+ ```bash
64
+ scoredl "https://musescore.com/user/xxxx/scores/yyyy" --keep-svg
65
+ ```
66
+
67
+ ## Argumen CLI
68
+
69
+ | Argumen | Opsi Panjang | Deskripsi | Wajib |
70
+ |---|---|---|---|
71
+ | `url` | โ€“ | URL partitur MuseScore | โœ… |
72
+ | `-o` | `--output` | Nama file PDF output | โŒ |
73
+ | โ€“ | `--keep-svg` | Simpan file SVG mentah per halaman | โŒ |
74
+
75
+ ## Kontributor
76
+
77
+ - [RyhmnyRin](https://github.com/RyhmnyRin)
@@ -0,0 +1,66 @@
1
+ # ๐ŸŽผ scoredl
2
+
3
+ CLI tool sederhana berbasis Python untuk mengunduh partitur musik dari **MuseScore** dan mengonversinya langsung menjadi satu file PDF utuh berkualitas tinggi (lossless SVG).
4
+
5
+ ![Python](https://img.shields.io/badge/python-3.10+-blue)
6
+ ![Playwright](https://img.shields.io/badge/automation-Playwright-2EAD33)
7
+
8
+ ## Fitur
9
+
10
+ - ๐Ÿ”„ Auto-scroll & lazy load handling via Playwright
11
+ - ๐Ÿ–ผ๏ธ Konversi vektor SVG murni langsung ke lembaran PDF (lossless)
12
+ - ๐Ÿท๏ธ Penamaan file otomatis berdasarkan metadata judul lagu
13
+ - ๐Ÿ“‚ Opsi simpan file SVG mentah ke subfolder terpisah (`--keep-svg`)
14
+ - ๐Ÿงน Pembersihan file temporary otomatis setelah proses selesai
15
+
16
+ ## Instalasi
17
+
18
+ **Metode 1 โ€” via PyPI (disarankan)**
19
+ ```bash
20
+ pip install scoredl
21
+ playwright install chromium
22
+ ```
23
+
24
+ **Metode 2 โ€” manual (mode developer)**
25
+ ```bash
26
+ git clone https://github.com/RyhmnyRin/scoredl.git
27
+ cd scoredl
28
+ python -m venv .venv
29
+
30
+ # Windows PowerShell
31
+ .venv\Scripts\Activate.ps1
32
+
33
+ # Linux/macOS
34
+ source .venv/bin/activate
35
+
36
+ pip install -e .
37
+ playwright install chromium
38
+ ```
39
+
40
+ ## Penggunaan
41
+
42
+ ```bash
43
+ scoredl "https://musescore.com/user/xxxx/scores/yyyy"
44
+ ```
45
+
46
+ Tentukan nama file output:
47
+ ```bash
48
+ scoredl "https://musescore.com/user/xxxx/scores/yyyy" -o "NamaLagu.pdf"
49
+ ```
50
+
51
+ Simpan juga file SVG mentahnya (tersimpan di `saved_svgs/<Judul Lagu>/`):
52
+ ```bash
53
+ scoredl "https://musescore.com/user/xxxx/scores/yyyy" --keep-svg
54
+ ```
55
+
56
+ ## Argumen CLI
57
+
58
+ | Argumen | Opsi Panjang | Deskripsi | Wajib |
59
+ |---|---|---|---|
60
+ | `url` | โ€“ | URL partitur MuseScore | โœ… |
61
+ | `-o` | `--output` | Nama file PDF output | โŒ |
62
+ | โ€“ | `--keep-svg` | Simpan file SVG mentah per halaman | โŒ |
63
+
64
+ ## Kontributor
65
+
66
+ - [RyhmnyRin](https://github.com/RyhmnyRin)
@@ -0,0 +1,50 @@
1
+ import os
2
+ from svglib.svglib import svg2rlg
3
+ from reportlab.graphics import renderPDF
4
+ from pypdf import PdfWriter, PdfReader
5
+
6
+ def compile_svgs_to_pdf(svg_files: list, output_pdf_path: str, title: str = "Sheet Music"):
7
+ print(f"[*] Mengonversi {len(svg_files)} halaman SVG ke PDF...")
8
+ temp_pdf_pages = []
9
+
10
+ # 1. Konversi tiap file SVG menjadi PDF lembaran sementara
11
+ for idx, svg_path in enumerate(svg_files):
12
+ print(f"[*] Memproses lembar {idx + 1}/{len(svg_files)}: {svg_path}")
13
+ drawing = svg2rlg(svg_path)
14
+ page_pdf_path = svg_path.replace(".svg", ".pdf")
15
+ renderPDF.drawToFile(drawing, page_pdf_path)
16
+ temp_pdf_pages.append(page_pdf_path)
17
+
18
+ # 2. Gabungkan lembaran PDF individual ke dalam satu file utuh
19
+ print("[*] Menggabungkan seluruh lembar ke file akhir...")
20
+ writer = PdfWriter()
21
+
22
+ for pdf_page in temp_pdf_pages:
23
+ reader = PdfReader(pdf_page)
24
+ for page in reader.pages:
25
+ writer.add_page(page)
26
+
27
+ # 3. Sematkan Metadata Dokumen (Sesuai ide awal lo buat preserve copyright)
28
+ writer.add_metadata({
29
+ "/Title": title,
30
+ "/Producer": "Score-dl CLI Engine"
31
+ })
32
+
33
+ # Simpan file hasil akhir
34
+ with open(output_pdf_path, "wb") as f_out:
35
+ writer.write(f_out)
36
+
37
+ # 4. Cleanup: Hapus file PDF per-halaman sementara
38
+ for temp_pdf in temp_pdf_pages:
39
+ try:
40
+ os.remove(temp_pdf)
41
+ except Exception:
42
+ pass
43
+
44
+ print(f"[โœ“] Selesai! Partitur utuh berhasil disimpan ke: {output_pdf_path}")
45
+
46
+ if __name__ == "__main__":
47
+ # Test manual builder menggunakan file SVG yang sudah lo extract
48
+ folder = "temp_svgs"
49
+ files = [os.path.join(folder, f"page_{i}.svg") for i in range(6)]
50
+ compile_svgs_to_pdf(files, "Non-Breath-Oblige.pdf", title="Non-Breath Oblige - PinocchioP")
@@ -0,0 +1,146 @@
1
+ import os
2
+ import random
3
+ import time
4
+ from playwright.sync_api import sync_playwright
5
+
6
+ def extract_score_data(score_url: str, output_dir: str = "temp_svgs"):
7
+ os.makedirs(output_dir, exist_ok=True)
8
+ svg_files = []
9
+ metadata = {
10
+ "title": "Unknown Title",
11
+ "pages": 0
12
+ }
13
+
14
+ user_data_dir = os.path.join(os.getcwd(), ".browser_session")
15
+
16
+ with sync_playwright() as p:
17
+ context = p.chromium.launch_persistent_context(
18
+ user_data_dir=user_data_dir,
19
+ headless=False,
20
+ channel="chrome",
21
+ args=[
22
+ "--disable-blink-features=AutomationControlled",
23
+ "--no-sandbox"
24
+ ],
25
+ viewport={"width": 1280, "height": 850}
26
+ )
27
+
28
+ page = context.pages[0] if context.pages else context.new_page()
29
+
30
+ # Intercept dan simpan konten SVG langsung dari memory browser
31
+ seen_svg_urls = set()
32
+ downloaded_files = []
33
+
34
+ def handle_response(response):
35
+ url = response.url
36
+ if "scoredata" in url and ".svg" in url:
37
+ if url in seen_svg_urls:
38
+ return
39
+ seen_svg_urls.add(url)
40
+
41
+ try:
42
+ svg_content = response.body()
43
+ # Beri nama unik sementara berdasarkan index URL yang ditemukan
44
+ idx = len(seen_svg_urls) - 1
45
+ file_path = os.path.join(output_dir, f"page_{idx}.svg")
46
+
47
+ with open(file_path, "wb") as f:
48
+ f.write(svg_content)
49
+
50
+ print(f"[+] Berhasil menyimpan lembar -> {file_path}")
51
+ except Exception as e:
52
+ print(f"[!] Gagal ekstrak SVG: {e}")
53
+
54
+ page.on("response", handle_response)
55
+
56
+ print(f"[*] Mengakses target: {score_url}")
57
+ page.goto(score_url, wait_until="domcontentloaded", timeout=60000)
58
+
59
+ # Pemeriksaan Cloudflare
60
+ print("[*] Memeriksa proteksi Cloudflare...")
61
+ for _ in range(15):
62
+ title = page.title()
63
+ if "Just a moment" not in title and title.strip() != "":
64
+ break
65
+ time.sleep(1)
66
+
67
+ try:
68
+ metadata["title"] = page.title().split("|")[0].strip()
69
+ except Exception:
70
+ pass
71
+
72
+ print(f"[*] Judul: {metadata['title']}")
73
+ print("[*] Menunggu elemen lembar partitur...")
74
+
75
+ try:
76
+ page.wait_for_selector("#jmuse-scroller-component", timeout=15000)
77
+ time.sleep(2)
78
+ except Exception:
79
+ pass
80
+
81
+ print("[*] Menjalankan human scrolling...")
82
+
83
+ total_height = page.evaluate("""() => {
84
+ const scroller = document.querySelector('#jmuse-scroller-component');
85
+ return scroller ? scroller.scrollHeight : document.body.scrollHeight;
86
+ }""")
87
+
88
+ current_scroll = 0
89
+ step_size = 850
90
+
91
+ while current_scroll < total_height:
92
+ current_scroll += step_size
93
+
94
+ page.evaluate(f"""(scrollVal) => {{
95
+ const scroller = document.querySelector('#jmuse-scroller-component');
96
+ if (scroller) {{
97
+ scroller.scrollTo({{
98
+ top: scrollVal,
99
+ behavior: 'smooth'
100
+ }});
101
+ }} else {{
102
+ window.scrollTo({{
103
+ top: scrollVal,
104
+ behavior: 'smooth'
105
+ }});
106
+ }}
107
+ }}""", current_scroll)
108
+
109
+ time.sleep(1)
110
+
111
+ total_height = page.evaluate("""() => {
112
+ const scroller = document.querySelector('#jmuse-scroller-component');
113
+ return scroller ? scroller.scrollHeight : document.body.scrollHeight;
114
+ }""")
115
+
116
+ print("[*] Menunggu finalisasi asset...")
117
+ time.sleep(0.4)
118
+
119
+ metadata["pages"] = len(svg_files)
120
+ context.close()
121
+
122
+ # Ambil file fisik langsung dari disk agar tidak ada duplikat memori
123
+ all_svgs = [
124
+ os.path.join(output_dir, f)
125
+ for f in os.listdir(output_dir)
126
+ if f.endswith(".svg")
127
+ ]
128
+
129
+ # Urutkan berdasarkan angka halaman asli (page_0, page_1, dst)
130
+ import re
131
+ all_svgs.sort(key=lambda x: int(re.search(r'page_(\d+)', x).group(1)))
132
+
133
+ # Update total halaman valid yang sebenarnya tersimpan
134
+ metadata["pages"] = len(all_svgs)
135
+ svg_files = all_svgs
136
+
137
+ return metadata, svg_files
138
+
139
+ if __name__ == "__main__":
140
+ target = "https://musescore.com/user/40260509/scores/7121958"
141
+ meta, files = extract_score_data(target)
142
+ print("\n" + "=" * 40)
143
+ print(f"Hasil Ekstraksi:")
144
+ print(f"Judul : {meta['title']}")
145
+ print(f"Total : {meta['pages']} file SVG tersimpan di folder lokal")
146
+ print("=" * 40)
scoredl-0.1.0/main.py ADDED
@@ -0,0 +1,63 @@
1
+ import argparse
2
+ import os
3
+ import re
4
+ import shutil
5
+ from extractor import extract_score_data
6
+ from builder import compile_svgs_to_pdf
7
+
8
+ def sanitize_filename(name: str) -> str:
9
+ return re.sub(r'[\\/*?:"<>|]', "", name).strip()
10
+
11
+ def main():
12
+ parser = argparse.ArgumentParser(
13
+ prog="scoredl",
14
+ description="CLI Tool untuk mengekstrak partitur MuseScore menjadi PDF berkualitas tinggi."
15
+ )
16
+ parser.add_argument("url", type=str, help="URL lembar musik MuseScore target")
17
+ parser.add_argument("-o", "--output", type=str, default=None, help="Nama file PDF output")
18
+ parser.add_argument("--keep-svg", action="store_true", help="Simpan file SVG ke folder tersendiri sesuai judul")
19
+
20
+ args = parser.parse_args()
21
+
22
+ print("=" * 50)
23
+ print(" Score-dl - MuseScore Sheet Extractor ")
24
+ print("=" * 50)
25
+
26
+ # Gunakan folder sementara unik
27
+ temp_dir = ".temp_extract"
28
+ meta, svg_files = extract_score_data(args.url, output_dir=temp_dir)
29
+
30
+ if not svg_files:
31
+ print("[!] Gagal mengekstrak halaman partitur. Proses dibatalkan.")
32
+ return
33
+
34
+ clean_title = sanitize_filename(meta["title"])
35
+ final_pdf_name = args.output if args.output else f"{clean_title}.pdf"
36
+ if not final_pdf_name.endswith(".pdf"):
37
+ final_pdf_name += ".pdf"
38
+
39
+ # Compile ke PDF
40
+ compile_svgs_to_pdf(svg_files, final_pdf_name, title=meta["title"])
41
+
42
+ # Penanganan folder SVG jika user memilih --keep-svg
43
+ if args.keep_svg:
44
+ # Buat folder khusus sesuai judul lagu agar tidak tertukar
45
+ svg_dest_dir = os.path.join("saved_svgs", clean_title)
46
+ os.makedirs(svg_dest_dir, exist_ok=True)
47
+
48
+ for idx, old_path in enumerate(svg_files):
49
+ new_file_name = f"{clean_title}_page_{idx + 1}.svg"
50
+ new_path = os.path.join(svg_dest_dir, new_file_name)
51
+ shutil.copy2(old_path, new_path)
52
+
53
+ print(f"[โœ“] Salinan SVG resolusi tinggi tersimpan di: {svg_dest_dir}")
54
+
55
+ # Bersihkan folder sementara
56
+ shutil.rmtree(temp_dir, ignore_errors=True)
57
+
58
+ print("\n" + "=" * 50)
59
+ print(f"[โœ“] SUKSES! Partitur siap cetak: {final_pdf_name}")
60
+ print("=" * 50)
61
+
62
+ if __name__ == "__main__":
63
+ main()
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "scoredl"
7
+ version = "0.1.0"
8
+ description = "CLI tool to download and assemble MuseScore sheets into high-quality PDFs"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ "playwright>=1.40.0",
13
+ "svglib>=1.5.0",
14
+ "reportlab>=4.0.0",
15
+ "pypdf>=4.0.0"
16
+ ]
17
+
18
+ [project.scripts]
19
+ scoredl = "main:main"
20
+
21
+ [tool.setuptools]
22
+ py-modules = ["main", "extractor", "builder"]
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.4
2
+ Name: scoredl
3
+ Version: 0.1.0
4
+ Summary: CLI tool to download and assemble MuseScore sheets into high-quality PDFs
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: playwright>=1.40.0
8
+ Requires-Dist: svglib>=1.5.0
9
+ Requires-Dist: reportlab>=4.0.0
10
+ Requires-Dist: pypdf>=4.0.0
11
+
12
+ # ๐ŸŽผ scoredl
13
+
14
+ CLI tool sederhana berbasis Python untuk mengunduh partitur musik dari **MuseScore** dan mengonversinya langsung menjadi satu file PDF utuh berkualitas tinggi (lossless SVG).
15
+
16
+ ![Python](https://img.shields.io/badge/python-3.10+-blue)
17
+ ![Playwright](https://img.shields.io/badge/automation-Playwright-2EAD33)
18
+
19
+ ## Fitur
20
+
21
+ - ๐Ÿ”„ Auto-scroll & lazy load handling via Playwright
22
+ - ๐Ÿ–ผ๏ธ Konversi vektor SVG murni langsung ke lembaran PDF (lossless)
23
+ - ๐Ÿท๏ธ Penamaan file otomatis berdasarkan metadata judul lagu
24
+ - ๐Ÿ“‚ Opsi simpan file SVG mentah ke subfolder terpisah (`--keep-svg`)
25
+ - ๐Ÿงน Pembersihan file temporary otomatis setelah proses selesai
26
+
27
+ ## Instalasi
28
+
29
+ **Metode 1 โ€” via PyPI (disarankan)**
30
+ ```bash
31
+ pip install scoredl
32
+ playwright install chromium
33
+ ```
34
+
35
+ **Metode 2 โ€” manual (mode developer)**
36
+ ```bash
37
+ git clone https://github.com/RyhmnyRin/scoredl.git
38
+ cd scoredl
39
+ python -m venv .venv
40
+
41
+ # Windows PowerShell
42
+ .venv\Scripts\Activate.ps1
43
+
44
+ # Linux/macOS
45
+ source .venv/bin/activate
46
+
47
+ pip install -e .
48
+ playwright install chromium
49
+ ```
50
+
51
+ ## Penggunaan
52
+
53
+ ```bash
54
+ scoredl "https://musescore.com/user/xxxx/scores/yyyy"
55
+ ```
56
+
57
+ Tentukan nama file output:
58
+ ```bash
59
+ scoredl "https://musescore.com/user/xxxx/scores/yyyy" -o "NamaLagu.pdf"
60
+ ```
61
+
62
+ Simpan juga file SVG mentahnya (tersimpan di `saved_svgs/<Judul Lagu>/`):
63
+ ```bash
64
+ scoredl "https://musescore.com/user/xxxx/scores/yyyy" --keep-svg
65
+ ```
66
+
67
+ ## Argumen CLI
68
+
69
+ | Argumen | Opsi Panjang | Deskripsi | Wajib |
70
+ |---|---|---|---|
71
+ | `url` | โ€“ | URL partitur MuseScore | โœ… |
72
+ | `-o` | `--output` | Nama file PDF output | โŒ |
73
+ | โ€“ | `--keep-svg` | Simpan file SVG mentah per halaman | โŒ |
74
+
75
+ ## Kontributor
76
+
77
+ - [RyhmnyRin](https://github.com/RyhmnyRin)
@@ -0,0 +1,11 @@
1
+ README.md
2
+ builder.py
3
+ extractor.py
4
+ main.py
5
+ pyproject.toml
6
+ scoredl.egg-info/PKG-INFO
7
+ scoredl.egg-info/SOURCES.txt
8
+ scoredl.egg-info/dependency_links.txt
9
+ scoredl.egg-info/entry_points.txt
10
+ scoredl.egg-info/requires.txt
11
+ scoredl.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ scoredl = main:main
@@ -0,0 +1,4 @@
1
+ playwright>=1.40.0
2
+ svglib>=1.5.0
3
+ reportlab>=4.0.0
4
+ pypdf>=4.0.0
@@ -0,0 +1,3 @@
1
+ builder
2
+ extractor
3
+ main
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+