Files
Projekcija/tools/add_song.py

437 lines
15 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sqlite3
import json
import os
import urllib.request
import sys
# Dodajanje poti do korenskega imenika, da lahko uvozimo db_schema
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from db_schema import create_tables
DB_PATH = 'songs.db'
SETTINGS_PATH = 'settings.json'
EXPORT_PATH = 'pesmi_export.txt'
# ---------------------------------------------------------------------------
# PREDHODNE NASTAVITVE IN POVEZAVA NA BAZO
# ---------------------------------------------------------------------------
if not os.path.exists(SETTINGS_PATH):
print("Nastavitve manjkajo! Zaženi program za prjekcijo, da jih pripravi.")
exit()
with open(SETTINGS_PATH, "r", encoding="utf-8") as f:
settings = json.load(f)
conn = sqlite3.connect(DB_PATH)
create_tables(conn)
cursor = conn.cursor()
# ---------------------------------------------------------------------------
# POMOŽNE FUNKCIJE
# ---------------------------------------------------------------------------
def send_ntfy_notification(song_id, title, lyrics):
"""
Pošlje obvestilo o spremembi besedila preko ntfy.sh.
"""
topic = settings.get("ntfy_topic", "").strip()
if not topic:
return
label = settings.get("installation_label", "Projekcija")
message = f"{song_id}\n{title}\n{lyrics}"
try:
url = f"https://ntfy.sh/{topic}"
req = urllib.request.Request(
url,
data=message.encode('utf-8'),
method='POST'
)
with urllib.request.urlopen(req, timeout=5) as response:
pass
except Exception as e:
print(f"Napaka pri pošiljanju ntfy obvestila: {e}")
def get_next_free_id(start: int = 792) -> int:
"""Vrne prvo prosto številko pesmi, ki je ≥ start (privzeto 792)."""
next_id = start
while True:
cursor.execute("SELECT 1 FROM songs WHERE id = ?", (next_id,))
if cursor.fetchone() is None:
return next_id
next_id += 1
def slovenski_kljuc(naslov: str) -> str:
nadom = {'č': 'cz', 'Č': 'Cz', 'š': 'sz', 'Š': 'Sz', 'ž': 'zz', 'Ž': 'Zz'}
return ''.join(nadom.get(z, z) for z in naslov).lower()
def prikazi_meni():
print("\nIzberi možnost:")
print("1. Dodaj pesem")
print("2. Uredi pesem")
print("3. Prestavi pesem")
print("4. Izbriši pesem")
print("5. Izvozi bazo v TXT")
print("6. Uvozi bazo iz TXT")
print("7. Izpiši kazalo")
print("9. Zapri program")
def uredi_vnos(lines):
processed, prazne = [], 0
for line in lines:
if line.strip() == "":
prazne += 1
continue
if prazne:
processed.extend([""] * prazne)
prazne = 0
if line.strip().startswith("- "):
line = line.replace("- ", "", 1)
processed.append(line)
if prazne:
processed.extend([""] * prazne)
return "\n".join(processed)
# ---------------------------------------------------------------------------
# FUNKCIJE POSAMEZNIH MENIJSKIH OPCIJ
# ---------------------------------------------------------------------------
def dodaj_pesem():
# -- izbira št. pesmi ----------------------------------------------------
while True:
try:
song_id = int(input("Vnesi številko pesmi: "))
break
except ValueError:
print("Vnesi veljavno celo število!")
cursor.execute("SELECT title FROM songs WHERE id = ?", (song_id,))
row = cursor.fetchone()
if row:
print(f"Želiš prepisati obstoječo pesem {song_id} {row[0]}?")
predlagana = get_next_free_id()
print(f"Prva prosta številka nad 791 je {predlagana}.")
izbira = input("D = prepiši, N ali Enter = uporabi predlagano, "
"ali vnesi drugo številko: ").strip()
if izbira.lower() == "d":
pass
elif izbira.lower() == "n" or izbira == "":
song_id = predlagana
else:
try:
song_id = int(izbira)
except ValueError:
print("Neveljaven vnos uporabljam predlagano številko.")
song_id = predlagana
# -- vnos besedila -------------------------------------------------------
title = input("Vnesi naslov pesmi: ")
print("Vnesi besedilo (prazna vrstica = presledek, dve prazni = nova kitica).\n"
"Ko končaš, vpiši 'konec'.")
lines = []
while True:
line = input()
if line.strip().lower() == "konec":
break
if line.strip().startswith("- "):
line = line.replace("- ", "", 1)
lines.append(line)
full_lyrics = uredi_vnos(lines)
cursor.execute("INSERT OR REPLACE INTO songs (id, title, lyrics) VALUES (?,?,?)",
(song_id, title, full_lyrics))
conn.commit()
send_ntfy_notification(song_id, title, full_lyrics)
print("Pesem uspešno shranjena!")
def uredi_pesem():
try:
song_id = int(input("Vnesi številko pesmi za urejanje: "))
except ValueError:
print("Uporabi celo število!")
return
cursor.execute("SELECT title, lyrics FROM songs WHERE id = ?", (song_id,))
result = cursor.fetchone()
if not result:
print("Pesem s to številko ne obstaja.")
return
print(f"Trenutni naslov: {result[0]}")
print(f"Trenutno besedilo:\n{result[1]}")
new_title = input("Nov naslov (pusti prazno za obdržanje): ")
print("Novo besedilo (vpiši 'konec' za zaključek, pusti prazno za obdržanje):")
lines = []
while True:
line = input()
if line.strip().lower() == "konec":
break
if line.strip().startswith("- "):
line = line.replace("- ", "", 1)
lines.append(line)
if new_title.strip() == "":
new_title = result[0]
new_lyrics = result[1] if len(lines) == 0 else uredi_vnos(lines)
cursor.execute("UPDATE songs SET title = ?, lyrics = ? WHERE id = ?",
(new_title, new_lyrics, song_id))
conn.commit()
send_ntfy_notification(song_id, new_title, new_lyrics)
print("Pesem uspešno posodobljena!")
def prestavi_pesem():
try:
old_id = int(input("Vnesi številko pesmi, ki jo želiš prestaviti: "))
new_id = int(input("Vnesi novo številko pesmi: "))
except ValueError:
print("Uporabi cela števila!")
return
cursor.execute("SELECT title, lyrics FROM songs WHERE id = ?", (old_id,))
vir = cursor.fetchone()
if vir is None:
print("Pesem s to številko ne obstaja.")
return
cursor.execute("SELECT title FROM songs WHERE id = ?", (new_id,))
cilj = cursor.fetchone()
if cilj:
print(f"Želiš prepisati obstoječo pesem {new_id} {cilj[0]}?")
predlagana = get_next_free_id()
print(f"Prva prosta številka nad 791 je {predlagana}.")
izbira = input("D = prepiši, N ali Enter = predlagana, ali vnesi drugo številko: ").strip()
if izbira.lower() == "d":
pass
elif izbira.lower() == "n" or izbira == "":
new_id = predlagana
else:
try:
new_id = int(izbira)
except ValueError:
print("Neveljaven vnos uporabljam predlagano številko.")
new_id = predlagana
cursor.execute("INSERT OR REPLACE INTO songs (id, title, lyrics) VALUES (?,?,?)",
(new_id, vir[0], vir[1]))
cursor.execute("DELETE FROM songs WHERE id = ?", (old_id,))
conn.commit()
send_ntfy_notification(new_id, vir[0], vir[1])
print("Pesem uspešno prestavljena!")
def izbrisi_pesem():
try:
song_id = int(input("Vnesi številko pesmi za izbris: "))
except ValueError:
print("Uporabi celo število!")
return
cursor.execute("SELECT title FROM songs WHERE id = ?", (song_id,))
row = cursor.fetchone()
if row is None:
print("Pesem s to številko ne obstaja.")
return
potrdi = input(f"Želiš res izbrisati pesem {song_id} {row[0]}? (D/N): ").strip().lower()
if potrdi == "d":
cursor.execute("DELETE FROM songs WHERE id = ?", (song_id,))
conn.commit()
print("Pesem uspešno izbrisana!")
else:
print("Brisanje preklicano.")
def izvozi_bazo():
cursor.execute("SELECT id, title, lyrics FROM songs ORDER BY id")
pesmi = cursor.fetchall()
with open(EXPORT_PATH, "w", encoding="utf-8") as f:
for pesem in pesmi:
f.write("===\n")
f.write(f"{pesem[0]}\n{pesem[1]}\n{pesem[2]}\n")
print(f"Baza je bila izvožena v '{EXPORT_PATH}'.")
# ---------------------------------------------------------------------------
# 6. UVOZ BAZE Z NAPREDNO KONTROLO PODVOJENIH PESMI
# ---------------------------------------------------------------------------
def uvozi_bazo():
if not os.path.exists(EXPORT_PATH):
print(f"Datoteka '{EXPORT_PATH}' ne obstaja.")
return
with open(EXPORT_PATH, "r", encoding="utf-8") as f:
vsebina = f.read().replace('\r\n', '\n').replace('\r', '\n')
pesmi_raw = [p for p in vsebina.strip().split("===\n") if p.strip()]
duplicate_mode = None # 'd', 'n', 'p' ==> vedno prepiši / preskoči / nova ID
for pesem_raw in pesmi_raw:
vrstice = pesem_raw.strip().split("\n")
if len(vrstice) < 3:
print("Preskočena nepopolna pesem.")
continue
try:
song_id = int(vrstice[0])
except ValueError:
print("Neveljaven ID preskočeno.")
continue
title = vrstice[1]
raw_lyrics_lines = vrstice[2:]
# -- predobdelava besedila ------------------------------------------
processed_lines, prazne = [], 0
for line in raw_lyrics_lines:
if line.strip().startswith("- "):
line = line.replace("- ", "", 1)
if line.strip() == "":
prazne += 1
continue
if prazne:
processed_lines.extend([""] * prazne)
prazne = 0
processed_lines.append(line)
if prazne:
processed_lines.extend([""] * prazne)
lyrics = "\n".join(processed_lines)
# -- obravnava podvojene številke -----------------------------------
cursor.execute("SELECT title FROM songs WHERE id = ?", (song_id,))
exists = cursor.fetchone()
if exists:
# Če imamo globalni način, ga upoštevamo
if duplicate_mode is not None:
choice = duplicate_mode
else:
print(f"\nPozor: pesem št. {song_id} \"{exists[0]}\" že obstaja.")
print("Izberi dejanje:")
print(" d … prepiši")
print(" n … preskoči")
print(" p … shrani pod prvo prosto številko ≥ 792")
print(" da … prepiši to in vse naslednje podvojene pesmi")
print(" na … preskoči to in vse naslednje podvojene pesmi")
print(" pa … shrani to in vse naslednje podvojene pesmi pod novo ID")
izbira = input("Tvoja izbira: ").strip().lower()
if izbira in {"da", "na", "pa"}:
duplicate_mode = izbira[0] # 'd', 'n', 'p'
choice = duplicate_mode
elif izbira in {"d", "n", "p"}:
choice = izbira
else:
print("Neznana izbira pesem preskočena.")
continue
# izvajanje po izbrani logiki
if choice == "n":
print("Pesem preskočena.")
continue
elif choice == "p":
song_id = get_next_free_id()
print(f"Shranjujem pod novo številko {song_id}.")
# choice == 'd' -> prepis
# -- shranjevanje pesmi ---------------------------------------------
cursor.execute("INSERT OR REPLACE INTO songs (id, title, lyrics) VALUES (?,?,?)",
(song_id, title, lyrics))
send_ntfy_notification(song_id, title, lyrics)
conn.commit()
print("\nUvoz pesmi uspešen!")
# ---------------------------------------------------------------------------
# DODATNE FUNKCIJE (kazalo, projekcija) nespremenjene
# ---------------------------------------------------------------------------
def izpisi_kazalo():
poglavja = [
(13, " -- SLAVIMO GOSPODA -- "),
(13, "ADVENTNE"),
(27, "BOŽIČNA DEVETDNEVNICA"),
(39, "BOŽIČNE"),
(65, "POSTNE"),
(119, "VELIKONOČNE"),
(142, "ČAS MED LETOM"),
(160, "MARIJINE"),
(240, "SVETNIŠKE"),
(263, "ZAKRAMENTI"),
(383, "MAŠNE"),
(406, "DAROVANJSKE"),
(419, "OBHAJILNE"),
(470, "BLAGOSLOVNE"),
(497, "ZAKRAMENT SPRAVE"),
(505, "MAŠNIŠKO POSVEČENJE"),
(539, "POGREB"),
(696, "LITANIJE"),
(773, "KRIŽEV POT"),
(777, "ROŽNI VENEC"),
(786, "MISIJONSKE"),
(788, "ZAHVALNE"),
(790, "JUBILATE DEO in ON ŽIVI"),
(1273,"DRUGE PESMI"),
]
cursor.execute("SELECT id, title FROM songs ORDER BY id")
zaporedno = cursor.fetchall()
cursor.execute("SELECT id, title FROM songs")
abecedno = cursor.fetchall()
abecedno.sort(key=lambda x: slovenski_kljuc(x[1]))
with open("kazalo.txt", "w", encoding="utf-8") as f:
f.write("ZAPOREDNO KAZALO\n")
trenutno_poglavje, indeks = None, 0
for pesem in zaporedno:
while indeks < len(poglavja) and pesem[0] >= poglavja[indeks][0]:
trenutno_poglavje = poglavja[indeks][1]
f.write(f"\n--- {trenutno_poglavje} ---\n")
indeks += 1
f.write(f"{pesem[0]}\t{pesem[1]}\n")
f.write("\n\nABECEDNO KAZALO\n")
for pesem in abecedno:
f.write(f"{pesem[0]}\t{pesem[1]}\n")
print("Kazalo izpisano v 'kazalo.txt'.")
# ---------------------------------------------------------------------------
# G L A V N I Z A G O N
# ---------------------------------------------------------------------------
def main():
while True:
prikazi_meni()
izbira = input("Vnesi številko možnosti: ").strip()
os.system('cls' if os.name == 'nt' else 'clear')
if izbira == "1": dodaj_pesem()
elif izbira == "2": uredi_pesem()
elif izbira == "3": prestavi_pesem()
elif izbira == "4": izbrisi_pesem()
elif izbira == "5": izvozi_bazo()
elif izbira == "6": uvozi_bazo()
elif izbira == "7": izpisi_kazalo()
elif izbira == "9":
print("Program se zapira …")
break
else:
print("Napačna izbira, poskusi znova.")
conn.close()
if __name__ == "__main__":
main()