2026-10-08 10:38:54 +00:00
|
|
|
#!/usr/bin/python3
|
2026-10-08 12:26:35 +02:00
|
|
|
import json
|
|
|
|
|
import re
|
|
|
|
|
import sqlite3
|
|
|
|
|
import argparse
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
def load_genre(conn, unique=False):
|
|
|
|
|
"""
|
|
|
|
|
Return all genres from the books table.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
conn: sqlite3 connection
|
|
|
|
|
unique: if True, return unique genres only
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
list[str]
|
|
|
|
|
"""
|
|
|
|
|
genres = []
|
|
|
|
|
|
|
|
|
|
for (genres_json,) in conn.execute("SELECT genres FROM books"):
|
|
|
|
|
if not genres_json:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
genres.extend(json.loads(genres_json))
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if unique:
|
|
|
|
|
return sorted(set(genres))
|
|
|
|
|
|
|
|
|
|
return genres
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
parser = argparse.ArgumentParser()
|
2026-10-08 10:38:54 +00:00
|
|
|
parser.add_argument(
|
|
|
|
|
"-p", "--print-only",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Print data only",
|
|
|
|
|
)
|
2026-10-08 12:26:35 +02:00
|
|
|
parser.add_argument(
|
|
|
|
|
"database",
|
|
|
|
|
type=Path,
|
|
|
|
|
help="SQL Database Path",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
database = args.database.resolve()
|
|
|
|
|
|
|
|
|
|
if not database.is_file():
|
|
|
|
|
parser.error(f"Database is not a file: {database}")
|
|
|
|
|
|
|
|
|
|
db = sqlite3.connect(database)
|
|
|
|
|
cur = db.cursor()
|
|
|
|
|
|
|
|
|
|
list_genres = load_genre(cur,True)
|
|
|
|
|
|
2026-10-08 10:38:54 +00:00
|
|
|
#for genre in list_genres:
|
|
|
|
|
# print(genre)
|
|
|
|
|
rows = cur.execute(
|
|
|
|
|
"SELECT id, genres FROM books"
|
|
|
|
|
).fetchall()
|
|
|
|
|
|
|
|
|
|
for book_id, genres_json in rows:
|
2026-10-08 12:26:35 +02:00
|
|
|
if not genres_json:
|
|
|
|
|
continue
|
|
|
|
|
genres = json.loads(genres_json)
|
|
|
|
|
new_genres = []
|
2026-10-08 10:38:54 +00:00
|
|
|
print("=================================")
|
|
|
|
|
print(f"Before sed: {genres}")
|
2026-10-08 12:26:35 +02:00
|
|
|
for genre in genres:
|
|
|
|
|
genre = re.sub(r'(?i)^audio\s*books?$', '', genre)
|
|
|
|
|
genre = re.sub(r'(?i)^audiobooks?$', '', genre)
|
2026-10-08 10:38:54 +00:00
|
|
|
genre = re.sub(r'(?i)\bhörb(uch|ücher)\b', '', genre)
|
|
|
|
|
genre = re.sub(r'(?i)^(hörspiele?|hoerspiele?)$', '', genre)
|
2026-10-08 12:26:35 +02:00
|
|
|
genre = re.sub(r'(?i)^spoken\s*word$', '', genre)
|
|
|
|
|
genre = re.sub(r'(?i)^speech$', '', genre)
|
|
|
|
|
|
|
|
|
|
genre = re.sub(r'(?i)^(sci[- ]?fi|sf)$', 'Science Fiction', genre)
|
|
|
|
|
genre = re.sub(r'(?i)^nonfiction$', 'NonFiction', genre)
|
|
|
|
|
|
2026-10-08 10:38:54 +00:00
|
|
|
genre = re.sub(r'^-\s*|\s*-$', '', genre)
|
2026-10-08 12:26:35 +02:00
|
|
|
genre = genre.strip()
|
|
|
|
|
|
2026-10-08 10:38:54 +00:00
|
|
|
new_genres.append(genre)
|
2026-10-08 12:26:35 +02:00
|
|
|
|
|
|
|
|
new_genres = sorted(set(new_genres))
|
2026-10-08 10:38:54 +00:00
|
|
|
|
|
|
|
|
print("Write to Database")
|
2026-10-08 12:26:35 +02:00
|
|
|
|
2026-10-08 10:38:54 +00:00
|
|
|
print(f"After sed: {new_genres}")
|
|
|
|
|
print("=================================")
|
|
|
|
|
|
|
|
|
|
list_difference = False
|
|
|
|
|
|
|
|
|
|
for old,new in zip(genres,new_genres):
|
|
|
|
|
if old != new:
|
|
|
|
|
list_difference = True
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if not list_difference:
|
|
|
|
|
print("No difference: Dont Commit to Database")
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if args.print_only:
|
|
|
|
|
print("Print only: Dont Commit to database")
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
print("Write to Database")
|
2026-10-08 12:26:35 +02:00
|
|
|
cur.execute(
|
|
|
|
|
"UPDATE books SET genres=? WHERE id=?",
|
|
|
|
|
(json.dumps(new_genres), book_id),
|
|
|
|
|
)
|
2026-10-08 10:38:54 +00:00
|
|
|
print("Database Updated")
|
2026-10-08 12:26:35 +02:00
|
|
|
|
|
|
|
|
db.commit()
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2026-10-08 10:38:54 +00:00
|
|
|
main()
|