diff --git a/courses.py b/courses.py
index 3125398..2cd53f7 100644
--- a/courses.py
+++ b/courses.py
@@ -28,6 +28,15 @@ COURSES = {
"env_pass": "PRACTITIONER_PASSWORD",
"root": Path("nlp-practitioner"),
},
+ "quantic": {
+ "name": "NLP Quantic (cursnlp.ro)",
+ "base_url": "https://shop.cursnlp.ro",
+ "course_path": "/curs/34",
+ "login_path": "/login",
+ "env_user": "PRACTITIONER_USERNAME",
+ "env_pass": "PRACTITIONER_PASSWORD",
+ "root": Path("nlp-quantic"),
+ },
}
diff --git a/download.py b/download.py
index ed00916..3b267bd 100644
--- a/download.py
+++ b/download.py
@@ -278,6 +278,8 @@ def download_vimeo_audio(vimeo_url: str, referer: str, dest: Path) -> bool:
"http_headers": {"Referer": referer},
"quiet": True,
"no_warnings": True,
+ "noprogress": True,
+ "concurrent_fragment_downloads": 8,
"postprocessors": [{
"key": "FFmpegExtractAudio",
"preferredcodec": "mp3",
diff --git a/nlp-quantic/audio_phone/_covers/M1.png b/nlp-quantic/audio_phone/_covers/M1.png
new file mode 100644
index 0000000..6ef9b10
Binary files /dev/null and b/nlp-quantic/audio_phone/_covers/M1.png differ
diff --git a/nlp-quantic/audio_phone/_covers/M2.png b/nlp-quantic/audio_phone/_covers/M2.png
new file mode 100644
index 0000000..c1752c5
Binary files /dev/null and b/nlp-quantic/audio_phone/_covers/M2.png differ
diff --git a/nlp-quantic/audio_phone/_covers/M3.png b/nlp-quantic/audio_phone/_covers/M3.png
new file mode 100644
index 0000000..b7ab37d
Binary files /dev/null and b/nlp-quantic/audio_phone/_covers/M3.png differ
diff --git a/nlp-quantic/audio_phone/_covers/M4.png b/nlp-quantic/audio_phone/_covers/M4.png
new file mode 100644
index 0000000..54d13f2
Binary files /dev/null and b/nlp-quantic/audio_phone/_covers/M4.png differ
diff --git a/nlp-quantic/audio_phone/_covers/M5.png b/nlp-quantic/audio_phone/_covers/M5.png
new file mode 100644
index 0000000..032d001
Binary files /dev/null and b/nlp-quantic/audio_phone/_covers/M5.png differ
diff --git a/nlp-quantic/audio_phone/index.html b/nlp-quantic/audio_phone/index.html
new file mode 100644
index 0000000..37536c4
--- /dev/null
+++ b/nlp-quantic/audio_phone/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+NLP Quantic audio
+
+
+
+NLP Quantic – audio
+
+Dacă browserul întreabă „permiți descărcări multiple?”, apasă Permite.
+
+
+
+
diff --git a/nlp-quantic/summaries/pdf/NLP Quantic M3 _ 16sept2023.pdf b/nlp-quantic/summaries/pdf/NLP Quantic M3 _ 16sept2023.pdf
new file mode 100644
index 0000000..4c905f6
Binary files /dev/null and b/nlp-quantic/summaries/pdf/NLP Quantic M3 _ 16sept2023.pdf differ
diff --git a/nlp-quantic/summaries/pdf/NLP Quantic Modulul 2.pdf b/nlp-quantic/summaries/pdf/NLP Quantic Modulul 2.pdf
new file mode 100644
index 0000000..27a72ba
Binary files /dev/null and b/nlp-quantic/summaries/pdf/NLP Quantic Modulul 2.pdf differ
diff --git a/nlp-quantic/summaries/pdf/NLP Quantic Workshop bonus _ 17.08.23.pdf b/nlp-quantic/summaries/pdf/NLP Quantic Workshop bonus _ 17.08.23.pdf
new file mode 100644
index 0000000..8a3c593
Binary files /dev/null and b/nlp-quantic/summaries/pdf/NLP Quantic Workshop bonus _ 17.08.23.pdf differ
diff --git a/rename_phone_practitioner.py b/rename_phone_practitioner.py
index 35e270d..e1c69f7 100644
--- a/rename_phone_practitioner.py
+++ b/rename_phone_practitioner.py
@@ -49,6 +49,7 @@ def find_font(size: int) -> ImageFont.FreeTypeFont:
"C:/Windows/Fonts/arialbd.ttf",
"C:/Windows/Fonts/arial.ttf",
"C:/Windows/Fonts/segoeui.ttf",
+ "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
]
for c in candidates:
if Path(c).exists():
@@ -109,7 +110,7 @@ def make_cover(module_num: int, theme_full: str, out_path: Path) -> Path:
# Course label (small, top)
f_small = find_font(36)
- label = COURSE_PREFIX + " - 2024"
+ label = f"{COURSE_PREFIX} - {YEAR}"
bbox = draw.textbbox((0, 0), label, font=f_small)
draw.text(((size - (bbox[2] - bbox[0])) / 2, 60), label, font=f_small, fill="#ffffff")
diff --git a/rename_phone_quantic.py b/rename_phone_quantic.py
new file mode 100644
index 0000000..0d28a28
--- /dev/null
+++ b/rename_phone_quantic.py
@@ -0,0 +1,63 @@
+"""Copies NLP Quantic MP3s to nlp-quantic/audio_phone/ with phone-friendly names + ID3 tags + cover.
+
+Reuses cover/tag helpers from rename_phone_practitioner.py.
+Run after: python download.py --course quantic
+"""
+from __future__ import annotations
+
+import json
+import re
+import shutil
+import sys
+from pathlib import Path
+
+import rename_phone_practitioner as rp
+
+ROOT = Path(__file__).parent
+QUANTIC = ROOT / "nlp-quantic"
+AUDIO_DST = QUANTIC / "audio_phone"
+COVERS_DIR = AUDIO_DST / "_covers"
+MANIFEST = QUANTIC / "manifest.json"
+
+rp.COURSE_PREFIX = "NLP Quantic"
+rp.ARTIST = "cursnlp.ro"
+rp.ALBUM_ARTIST = "cursnlp.ro"
+rp.YEAR = "2023"
+
+
+def clean_title(t: str) -> str:
+ return re.sub(r"\s+", " ", t.replace(",", " ")).strip()
+
+
+def main() -> int:
+ manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
+ errors = 0
+ for mod in manifest["modules"]:
+ n = int(mod["name"].split()[-1])
+ lecs = [L for L in mod["lectures"] if L["type"] in ("audio", "vimeo")]
+ if not lecs:
+ continue
+ cover = COVERS_DIR / f"M{n}.png"
+ if not cover.exists():
+ rp.make_cover(n, "", cover)
+ album = f"NLP Quantic - Modul {n}"
+ out_dir = AUDIO_DST / f"Quantic M{n}"
+ out_dir.mkdir(parents=True, exist_ok=True)
+ for idx, lec in enumerate(lecs, 1):
+ src = ROOT / lec["audio_path"]
+ if lec.get("download_status") != "complete" or not src.exists():
+ print(f" MISSING: {lec['title']}")
+ errors += 1
+ continue
+ title = clean_title(lec["title"])
+ dst = out_dir / f"Q{n}-{idx:02d} {rp.safe_filename_part(title)}.mp3"
+ if not (dst.exists() and dst.stat().st_size >= src.stat().st_size):
+ shutil.copy2(src, dst)
+ rp.tag_mp3(dst, title=title, album=album, track_num=idx, track_total=len(lecs), cover_png=cover)
+ print(f" ok: {dst.relative_to(QUANTIC)}")
+ print(f"\nDONE. errors={errors} Output: {AUDIO_DST}")
+ return 0 if errors == 0 else 2
+
+
+if __name__ == "__main__":
+ sys.exit(main())