updating scripts

This commit is contained in:
2026-04-02 11:26:40 +01:00
parent b5c2d4593d
commit f9e935dcec
6 changed files with 70 additions and 96 deletions

18
bash-scripts/master-perms.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
# This script will update the permissions of the /home/zaine/master-folder directory and all its contents to ensure that the nextcloud user has the necessary permissions to access and modify files within that directory.
# The two commands to run are:
# sudo chown -R zaine:www-data /home/zaine/master-folder
# sudo chmod -R 2775 /home/zaine/master-folder
# Update ownership to zaine:www-data
sudo chown -R zaine:www-data /home/zaine/master-folder
# Update permissions to 2775
sudo chmod -R 2775 /home/zaine/master-folder
echo "Permissions updated for /home/zaine/master-folder and its contents."
# cron job to run this script every hour
# 0 * * * * /path/to/this/script.sh

0
bash-scripts/system-clean.sh~ Normal file → Executable file
View File

View File

@@ -1,132 +1,88 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import csv import csv
from decimal import Decimal, InvalidOperation import re
from pathlib import Path from decimal import Decimal
from datetime import datetime from datetime import datetime
import sys from pathlib import Path
RAW_DIR = Path("/home/zaine/master-folder/attachments/bank-statements/nationwide/raw") RAW_DIR = Path("/home/zaine/master-folder/attachments/bank-statements/nationwide/raw")
CLEANED_DIR = Path("/home/zaine/master-folder/attachments/bank-statements/nationwide/cleaned") CLEANED_DIR = Path("/home/zaine/master-folder/attachments/bank-statements/nationwide/cleaned")
# Only keep digits, dot, minus for money
MONEY_REGEX = re.compile(r"[^\d\.-]")
def clean_money(value: str) -> Decimal | None: def clean_money(value: str):
if not value: if not value:
return None return None
# Remove all non-numeric characters
value = ( value = MONEY_REGEX.sub("", value)
value.replace("£", "")
.replace(",", "")
.strip()
)
if not value: if not value:
return None return None
return Decimal(value)
try: def parse_date(value: str):
return Decimal(value) # Input format: 27 Feb 2026
except InvalidOperation: return datetime.strptime(value.strip(), "%d %b %Y").strftime("%m/%d/%Y")
return None
def parse_date(value: str) -> str | None:
"""
Convert '01 Dec 2025''12/01/2025'
"""
value = value.strip()
if not value:
return None
try:
dt = datetime.strptime(value, "%d %b %Y")
return dt.strftime("%m/%d/%Y")
except ValueError:
return None
def convert(in_path: Path, out_path: Path): def convert(in_path: Path, out_path: Path):
with open(in_path, newline="", encoding="latin-1") as f_in, \ rows_written = 0
open(out_path, "w", newline="", encoding="utf-8") as f_out:
reader = csv.reader(f_in) # Read raw bytes and decode aggressively
with open(in_path, "rb") as f:
lines = f.read().decode("utf-8", errors="ignore").splitlines()
# Skip metadata lines until header with open(out_path, "w", newline="", encoding="utf-8") as f_out:
for row in reader: writer = csv.writer(f_out, lineterminator="\r\n")
if row and row[0] == "Date": writer.writerow(["Date", "Payee", "Description", "Amount"])
header = row
break
else:
raise RuntimeError("Could not find Nationwide CSV header row")
dict_reader = csv.DictReader(f_in, fieldnames=header) for row in csv.reader(lines):
if not row:
fieldnames = ["Date", "Payee", "Description", "Amount"] continue
writer = csv.DictWriter(f_out, fieldnames=fieldnames) first = row[0].strip()
writer.writeheader() if first.startswith("Account") or first == "Date":
continue
for row in dict_reader: if len(row) < 5:
raw_date = row.get("Date") or ""
date = parse_date(raw_date)
if not date:
continue continue
desc = (row.get("Description") or "").strip() try:
payee = desc date = parse_date(row[0])
except:
continue
paid_out = clean_money(row.get("Paid out", "")) desc = row[2].strip()
paid_in = clean_money(row.get("Paid in", "")) paid_out = clean_money(row[3])
paid_in = clean_money(row[4])
if paid_out is not None: if paid_out is not None:
amount = -paid_out amount = f"{-paid_out:.2f}"
elif paid_in is not None: elif paid_in is not None:
amount = paid_in amount = f"{paid_in:.2f}"
else: else:
continue continue
writer.writerow({ writer.writerow([date, desc, desc, amount])
"Date": date, rows_written += 1
"Payee": payee,
"Description": desc,
"Amount": f"{amount:.2f}",
})
def select_file(files: list[Path]) -> Path:
print("\nSelect a Nationwide CSV to clean:\n")
for i, f in enumerate(files, start=1):
print(f"[{i}] {f.name}")
try:
choice = int(input("\nEnter number: ").strip())
return files[choice - 1]
except (ValueError, IndexError):
print("Invalid selection.")
sys.exit(1)
return rows_written
def main(): def main():
if not RAW_DIR.exists():
print(f"Raw directory does not exist: {RAW_DIR}")
sys.exit(1)
CLEANED_DIR.mkdir(parents=True, exist_ok=True) CLEANED_DIR.mkdir(parents=True, exist_ok=True)
csv_files = sorted(RAW_DIR.glob("*.csv")) files = sorted(RAW_DIR.glob("*.csv"))
if not files:
print("No CSV files found.")
return
if not csv_files: print("\nSelect a Nationwide CSV to clean:\n")
print("No CSV files found in raw directory.") for i, f in enumerate(files, 1):
sys.exit(0) print(f" [{i}] {f.name}")
in_path = select_file(csv_files) choice = int(input("\nEnter number: "))
in_path = files[choice - 1]
out_name = f"{in_path.stem}-cleaned.csv" out_path = CLEANED_DIR / f"{in_path.stem}-cleaned.csv"
out_path = CLEANED_DIR / out_name
convert(in_path, out_path)
print(f"\n✔ Written cleaned file to:\n{out_path}\n")
n = convert(in_path, out_path)
print(f"\n{n} rows written to:\n {out_path}\n")
if __name__ == "__main__": if __name__ == "__main__":
main() main()

2
cookbook_org_sync.py Normal file → Executable file
View File

@@ -38,7 +38,7 @@ NEXTCLOUD_PASSWORD = os.environ.get("NEXTCLOUD_PASS", "Shakkal123!") # or hard
RECIPES_ENDPOINT = "/apps/cookbook/api/v1/recipes" RECIPES_ENDPOINT = "/apps/cookbook/api/v1/recipes"
OUTPUT_ORG = Path( OUTPUT_ORG = Path(
"/home/zaine/master-folder/org_files/org_roam/" "/home/zaine/master-folder/org_files/org_roam/Misc/"
"20260307233451-recipes_cookbook.org" "20260307233451-recipes_cookbook.org"
) )

0
cookbook_org_sync.py~ Normal file → Executable file
View File

View File

@@ -28,7 +28,7 @@ APP_DB = Path("/home/zaine/master-folder/projects/calibre/data/app.db")
CALIBRE_LIBRARY_ROOT = Path("/home/zaine/master-folder/projects/calibre/library") CALIBRE_LIBRARY_ROOT = Path("/home/zaine/master-folder/projects/calibre/library")
OUTPUT_ORG = Path("/home/zaine/master-folder/org_files/org_roam/20250724230557-books_org_agenda.org") OUTPUT_ORG = Path("/home/zaine/master-folder/org_files/org_roam/Books/20250724230557-books_org_agenda.org")
UNSORTED_SHELF = "Unsorted" UNSORTED_SHELF = "Unsorted"