diff --git a/.gitignore b/.gitignore
index c585554..cf23dc0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,10 @@
-!bcao/
+*
+!*/
+__pycache__/**
+!bcao/*.py
!requirements.txt
!.gitignore
!mypy.ini
!.run/
!.idea/
!README.md
-/*
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index e04aa25..0fb7faa 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -20,14 +20,28 @@
+
+
+
+
-
+
+
+
+
+
+
+
@@ -43,6 +57,14 @@
+
+
+
+
+
+
+
+
@@ -51,19 +73,33 @@
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -87,8 +123,8 @@
-
+
@@ -104,7 +140,9 @@
-
+
+
+
1602927759343
@@ -183,7 +221,14 @@
1603814270092
-
+
+ 1603888340561
+
+
+
+ 1603888340561
+
+
@@ -213,116 +258,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
\ No newline at end of file
diff --git a/.run/bcao (ceres).run.xml b/.run/bcao (ceres).run.xml
index d9df8aa..1f2ae9b 100644
--- a/.run/bcao (ceres).run.xml
+++ b/.run/bcao (ceres).run.xml
@@ -12,11 +12,11 @@
-
+
-
+
diff --git a/.run/bcao.run.xml b/.run/bcao.run.xml
index be7d6a2..3d300c5 100644
--- a/.run/bcao.run.xml
+++ b/.run/bcao.run.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/.run/mypy.run.xml b/.run/mypy.run.xml
index 44157fa..939ab35 100644
--- a/.run/mypy.run.xml
+++ b/.run/mypy.run.xml
@@ -6,14 +6,14 @@
-
+
-
+
-
-
+
+
diff --git a/bcao/__init__.py b/bcao/__init__.py
new file mode 100644
index 0000000..795ba80
--- /dev/null
+++ b/bcao/__init__.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+import re
+
+import mutagen
+from mutagen.flac import FLAC
+from mutagen.mp3 import MP3
+# noinspection PyProtectedMember
+from mutagen.id3 import ID3Tags
+# noinspection PyProtectedMember
+from mutagen.mp4 import Tags
+from mutagen.oggvorbis import OggVorbis
+
+from typing import Dict, List, Union
+
+format_lookup: Dict[str, str] = {
+ "mp3": "id3",
+ "m4a": "m4a",
+ "ogg": "vorbis",
+ "flac": "vorbis",
+ "wav": "id3",
+ "aiff": "id3"
+}
+fully_supported: List[str] = ["ogg", "flac", "mp3", "m4a", "wav", "aiff"]
+MutagenFile = Union[MP3, FLAC, OggVorbis, mutagen.FileType]
+MutagenTags = Union[ID3Tags, Tags, mutagen.oggvorbis.OggVCommentDict]
+sanitisation_regex = re.compile(r"[?\\/:|*\"<>]")
diff --git a/bcao.py b/bcao/__main__.py
similarity index 65%
rename from bcao.py
rename to bcao/__main__.py
index e93c725..794dcf8 100755
--- a/bcao.py
+++ b/bcao/__main__.py
@@ -5,6 +5,14 @@
# input: a .zip from bandcamp
# output: it organises it, adds cover art, puts it in the right place...
+# pycharm tells me some of these classes shouldn't be imported because they're not declared in __all__.
+# however, the mutagen docs show example code where someone creates a mutagen.flac.Picture by referring to it as
+# Picture(), implying that they had imported mutagen.flac.Picture, and therefore i'm right and the computer is WRONG
+# https://mutagen.readthedocs.io/en/latest/api/flac.html#mutagen.Picture.data
+
+from . import *
+from bcao.song_info import SongInfo
+
import argparse
import io
import os
@@ -13,182 +21,21 @@ import sys
import tempfile
import shutil
from os import path
-from base64 import b64encode
from zipfile import ZipFile
+from typing import Optional, List, Dict
from pathlib import Path
-from typing import Optional, Union, List, Dict
-# pycharm tells me some of these classes shouldn't be imported because they're not declared in __all__.
-# however, the mutagen docs show example code where someone creates a mutagen.flac.Picture by referring to it as
-# Picture(), implying that they had imported mutagen.flac.Picture, and therefore i'm right and the computer is WRONG
-# https://mutagen.readthedocs.io/en/latest/api/flac.html#mutagen.Picture.data
-import mutagen
# noinspection PyProtectedMember
-from mutagen.flac import Picture, FLAC
-from mutagen.oggvorbis import OggVorbis
-from mutagen.mp3 import MP3
-from mutagen.mp4 import MP4, MP4Cover
+from mutagen.flac import Picture
+from mutagen.mp4 import MP4Cover
# noinspection PyProtectedMember
-from mutagen.id3 import APIC, PictureType, Frame, TRCK, TPE1, TIT2, TALB, TPE2
+from mutagen.id3 import APIC, PictureType
from PIL import Image
-fully_supported: List[str] = ["ogg", "flac", "mp3", "m4a", "wav", "aiff"]
-MutagenFile = Union[MP3, FLAC, OggVorbis, mutagen.FileType]
-MutagenTags = Union[mutagen.id3.ID3Tags, mutagen.mp4.Tags, mutagen.oggvorbis.OggVCommentDict]
args: argparse.Namespace
tmp_dir: tempfile.TemporaryDirectory # type: ignore
-format_lookup: Dict[str, str] = {
- "mp3": "id3",
- "m4a": "m4a",
- "ogg": "vorbis",
- "flac": "vorbis",
- "wav": "id3",
- "aiff": "id3"
-}
-
-class SongInfo:
- tag_lookup: Dict[str, Dict[str, str]] = {
- "track": {"id3": "TRCK", "m4a": "trkn", "vorbis": "tracknumber"},
- "artist": {"id3": "TPE1", "m4a": "©ART", "vorbis": "artist"},
- "title": {"id3": "TIT2", "m4a": "©nam", "vorbis": "title"},
- "album": {"id3": "TALB", "m4a": "©alb", "vorbis": "album"},
- "album_artist": {"id3": "TPE2", "m4a": "aART", "vorbis": "albumartist"}
- }
-
- def __init__(self, file_name: Path):
- self.m_file: MutagenFile = mutagen.File(file_name)
- self.m_tags: MutagenTags = self.m_file.tags
-
- self.file_name = str(file_name.name)
- self.format = path.splitext(file_name)[1][1:]
- self.fallback = False
-
- if self.format not in format_lookup:
- raise ValueError(f"Unsupported file type: {self.format}")
-
- fallbacks = re.match(
- r"^(?P.+) - (?P.+) - (?P