Files
2026-03-18 19:55:21 +01:00

193 lines
6.6 KiB
Python

import locale
import re
import urllib.request
from datetime import datetime
from pathlib import Path
import tkinter as tk
from tkinter import messagebox, ttk
from tkinter import Tk
from tkinter.scrolledtext import ScrolledText
import shutil, re, os
from whoosh.index import create_in,open_dir
from whoosh.fields import Schema, TEXT, DATETIME, KEYWORD, ID, NUMERIC
from whoosh.qparser import QueryParser
from whoosh import index, qparser, query
DATA_DIR = Path(__file__).parent / "data"
CONTACTS_DIR = DATA_DIR / "contacts"
EMAILS_DIR = DATA_DIR / "emails"
INDEX_DIR = Path(__file__).parent / "index"
CONTACTS = {}
def create_index():
if not os.path.exists(INDEX_DIR):
os.mkdir(INDEX_DIR)
if not index.exists_in(INDEX_DIR, indexname="EmailIndex"):
schema = Schema(sender=TEXT(stored=True),
receiver=KEYWORD(stored=True),
date=DATETIME(stored=True),
subject=TEXT(stored=True),
body=TEXT(stored=True,phrase=False),
file_name=ID(stored=True))
idx = create_in(INDEX_DIR, schema=schema, indexname="EmailIndex")
print(f"Created index: {idx.indexname}")
else:
print(f"An index already exists")
def add_to_index(writer, path, file_name):
try:
f = open(path, "r")
sender = f.readline().strip()
receiver = f.readline().strip()
date_raw = f.readline().strip()
date = datetime.strptime(date_raw, '%Y%m%d')
subject = f.readline().strip()
body = f.read()
f.close()
writer.add_document(
sender=sender,
receiver=receiver,
date=date,
subject=subject,
body=body,
file_name=file_name
)
except:
messagebox.showerror(f"[ERR] adding {path}/{file_name}")
def index_emails(delete = False):
if delete:
shutil.rmtree(INDEX_DIR)
os.mkdir(INDEX_DIR)
create_index()
idx = index.open_dir(INDEX_DIR, "EmailIndex")
writer = idx.writer()
count = 0
for f in os.listdir(EMAILS_DIR):
if not os.path.isdir(EMAILS_DIR / f):
add_to_index(writer, EMAILS_DIR / f, f)
count += 1
writer.commit()
return count
def create_contacts():
try:
f = open(CONTACTS_DIR / "agenda.txt", "r")
email = f.readline()
while email:
name = f.readline()
CONTACTS[email.strip()] = name.strip()
email = f.readline()
except:
messagebox.showerror(f"[ERR] creating contacts list")
def load(delete = False):
create_contacts()
return index_emails(delete)
class EmailsUI():
def __init__(self, root, title = "AII"):
self.root = root
self.root.title(title)
self.root.geometry("900x600")
# Menu Principal
self.menu = tk.Menu(self.root)
self.root.config(menu=self.menu)
# Menu Datos
datos_menu = tk.Menu(self.menu, tearoff=0)
datos_menu.add_command(label="Cargar", command=lambda: self.callback("load"))
datos_menu.add_command(label="Listar", command=lambda: self.callback("list"))
datos_menu.add_separator()
datos_menu.add_command(label="Salir", command=self.root.quit)
self.menu.add_cascade(label="Datos", menu=datos_menu)
# Menu Buscar
buscar_menu = tk.Menu(self.menu, tearoff=0)
buscar_menu.add_command(label="Cuerpo o Asunto", command=lambda: self.callback("search_body_or_subject"))
buscar_menu.add_command(label="Fecha", command=lambda: self.callback("search_date"))
buscar_menu.add_command(label="Spam", command=lambda: self.callback("search_spam"))
self.menu.add_cascade(label="Buscar", menu=buscar_menu)
# Callback externo desde el punto de entrada
self.callback = None
def show_list(self, items, fields, title="Listado"):
mw = tk.Toplevel(self.root)
mw.title(title)
listbox = tk.Listbox(mw, width=80, height=20)
listbox.pack(side="left", fill="both", expand=True)
scrollbar = tk.Scrollbar(mw)
scrollbar.pack(side="right", fill="y")
listbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.yview)
for item in items:
row = " | ".join(str(item.get(field, "Unknown")) for field in fields)
listbox.insert("end", row)
def ask_text(self, label, callback):
mw = tk.Toplevel(self.root)
mw.title(label)
tk.Label(mw, text=label).pack(pady=5)
entry = ttk.Entry(mw)
entry.pack(pady=5)
ttk.Button(mw, text="Aceptar", command=
lambda: [callback(entry.get()), mw.destroy()]).pack(pady=10)
def ask_spinbox(self, label, options, callback):
mw = tk.Toplevel(self.root)
mw.title(label)
tk.Label(mw, text=label).pack(pady=5)
spinbox = ttk.Spinbox(mw, values=options, state="readonly", width=40)
spinbox.pack(pady=5)
ttk.Button(mw, text="Aceptar", command=
lambda: [callback(spinbox.get()), mw.destroy()]).pack(pady=10)
def ask_radiobutton(self, label, options, callback):
mw = tk.Toplevel(self.root)
mw.title(label)
tk.Label(mw, text=label).pack(pady=5)
sv = tk.StringVar(value=options[0])
for option in options:
tk.Radiobutton(mw, text=option, variable=sv, value=option).pack(anchor="w")
ttk.Button(mw, text="Aceptar", command=
lambda: [callback(sv.get()), mw.destroy()]).pack(pady=10)
def info(slef, message):
messagebox.showinfo("Información", message)
def main():
locale.setlocale(locale.LC_TIME, "es_ES.UTF-8")
create_index()
root = Tk()
ui = EmailsUI(root)
def handle_action(action):
match(action):
case "load":
resp = messagebox.askyesno(title="Cargar", message="Quieres cargar todos los datos de nuevo?")
if resp:
recipes_count = load(True)
ui.info(f"Se han indexado {recipes_count} emails")
case "list":
ix = open_dir(INDEX_DIR, "EmailIndex")
with ix.searcher() as searcher:
emails = searcher.search(query.Every(), limit=None)
print(emails)
ui.show_list(emails, ["sender", "receiver", "name", "subject", "body"])
# buscar con queries y tal...
ui.callback = handle_action
root.mainloop()
if __name__ == "__main__":
main()