193 lines
6.6 KiB
Python
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()
|
|
|