YnM Ora Sopel py

from sopel import plugin
import time
from threading import Timer
from datetime import datetime, timedelta
import json
import os

# Emlékeztetők tárolásának fájl elérési útja
REMINDER_FILE = '/home/ai/.sopel/plugins/notify/reminders.json'

# Szótár a timer objektumok tárolására
timer_objects = {}

# Biztosítjuk, hogy a könyvtár létezzen
os.makedirs(os.path.dirname(REMINDER_FILE), exist_ok=True)

def load_reminders():
    """Emlékeztetők betöltése fájlból és időbélyegek átalakítása datetime objektumokká."""
    try:
        with open(REMINDER_FILE, 'r', encoding='utf-8') as f:
            content = f.read()
            if not content:
                return {}
            loaded_data = json.loads(content)
            
            # Átalakítjuk a string típusú időpontokat datetime objektumokká
            for username, reminders_list in loaded_data.items():
                for reminder in reminders_list:
                    if isinstance(reminder['time'], str):
                        reminder['time'] = datetime.strptime(reminder['time'], '%Y-%m-%d %H:%M:%S')
            return loaded_data
    except (FileNotFoundError, json.JSONDecodeError):
        return {}

def save_reminders(reminders):
    """Emlékeztetők mentése fájlba, datetime objektumok stringgé alakítása."""
    serializable_reminders = {}
    for username, reminders_list in reminders.items():
        serializable_reminders[username] = []
        for reminder in reminders_list:
            reminder_copy = reminder.copy()
            if isinstance(reminder_copy['time'], datetime):
                reminder_copy['time'] = reminder_copy['time'].strftime('%Y-%m-%d %H:%M:%S')
            serializable_reminders[username].append(reminder_copy)
    
    with open(REMINDER_FILE, 'w', encoding='utf-8') as f:
        json.dump(serializable_reminders, f, ensure_ascii=False)

def send_reminder(bot, username, reminder_id, reminder_message):
    """Emlékeztető küldése a felhasználónak és az emlékeztető adatainak törlése."""
    try:
        bot.say(f"@{username} - {reminder_message}")
        
        # Emlékeztetők betöltése fájlból
        reminders = load_reminders()

        if username in reminders:
            # Az elküldött emlékeztető kiszűrése az id alapján
            reminders[username] = [r for r in reminders[username] if r['id'] != reminder_id]
            
            # Ha nincs több emlékeztető a felhasználónak, töröljük a felhasználó kulcsát
            if not reminders[username]:
                del reminders[username]
            
            # Frissített emlékeztetők mentése fájlba
            save_reminders(reminders)
        
        # Timer objektum törlése, ha létezik
        timer_key = f"{username}_{reminder_id}"
        if timer_key in timer_objects:
            del timer_objects[timer_key]
    except Exception as e:
        bot.say(f"Hiba történt {username} emlékeztetőjének küldésekor: {e}")

def check_existing_reminders(bot):
    """Ellenőrzi az elmaradt emlékeztetőket és újraütemezi a jövőbeli emlékeztetőket."""
    now = datetime.now()
    reminders = load_reminders()
    
    for username, reminders_to_process in reminders.items():
        for reminder_data in reminders_to_process:
            reminder_time = reminder_data['time']
            
            # Biztosítjuk, hogy reminder_time egy datetime objektum
            if isinstance(reminder_time, str):
                reminder_time = datetime.strptime(reminder_time, '%Y-%m-%d %H:%M:%S')
            
            if reminder_time <= now:
                # Az elmaradt emlékeztető azonnali küldése
                send_reminder(bot, username, reminder_data['id'], 
                            f"{reminder_data['message']} (Elmaradt emlékeztető {reminder_time.strftime('%Y-%m-%d %H:%M:%S')}-ról)")

                # Emlékeztetők újra betöltése és elmaradtak eltávolítása
                reminders = load_reminders()
                reminders[username] = [r for r in reminders[username] if r['id'] != reminder_data['id']]
                if not reminders[username]:
                    del reminders[username]
                save_reminders(reminders)
                
                # Timer objektum törlése
                timer_key = f"{username}_{reminder_data['id']}"
                if timer_key in timer_objects:
                    del timer_objects[timer_key]
            else:
                # Jövőbeli emlékeztetők ütemezése
                delay = (reminder_time - now).total_seconds()
                if delay > 0:
                    timer = Timer(delay, send_reminder, 
                                [bot, username, reminder_data['id'], reminder_data['message']])
                    timer.start()
                    timer_objects[f"{username}_{reminder_data['id']}"] = timer


@plugin.event('READY')
def on_ready(bot, trigger):
    """Emlékeztetők inicializálása, amikor a bot elindul."""
    try:
        reminders = load_reminders()
        check_existing_reminders(bot)

        # Rendszeres időzítő beállítása, hogy 5 percenként ellenőrizze az elmaradt emlékeztetőket
        check_timer = Timer(300, check_existing_reminders, [bot])  # 300 másodperc = 5 perc
        check_timer.start()
        timer_objects['check_existing_reminders'] = check_timer
        
    except Exception as e:
        bot.say(f"Hiba történt az emlékeztetők ellenőrzésekor: {e}")

@plugin.event('SHUTDOWN')
def on_shutdown(bot, trigger):
    """Időzítők törlése, amikor a bot leáll."""
    for timer in timer_objects.values():
        if timer.is_alive():
            timer.cancel()
    timer_objects.clear()

@plugin.rule(r'\[(\S+)\]!ora ?(\d+)(m|h|d) ?(.*)')
def set_reminder(bot, trigger):
    """Új emlékeztető beállítása, amikor a szabály illeszkedik."""
    try:
        username = trigger.group(1)
        time_value = int(trigger.group(2))
        time_unit = trigger.group(3)
        reminder_message = trigger.group(4).strip()

        if not reminder_message:
            bot.say("Kérlek, adj meg egy emlékeztető üzenetet!")
            return

        # Idő átváltása másodpercekké
        time_units = {'m': 60, 'h': 3600, 'd': 86400}
        if time_unit not in time_units:
            bot.say("Sajnálom, csak perceket (m), órákat (h) és napokat (d) támogatok.")
            return
        
        delay = time_value * time_units[time_unit]

        # Emlékeztető időpontjának kiszámítása
        reminder_time = datetime.now() + timedelta(seconds=delay)
        
        # Egyedi ID létrehozása
        reminder_id = str(int(time.time() * 1000))

        # Emlékeztető ütemezése
        timer = Timer(delay, send_reminder, [bot, username, reminder_id, reminder_message])
        timer.start()
        timer_objects[f"{username}_{reminder_id}"] = timer

        # Aktuális emlékeztetők betöltése fájlból
        reminders = load_reminders()
        
        # Emlékeztető mentése
        if username not in reminders:
            reminders[username] = []
        
        reminders[username].append({
            'id': reminder_id,
            'message': reminder_message,
            'time': reminder_time
        })

        save_reminders(reminders)

        # Emlékeztető megerősítése
        bot.say(f"Emlékeztető beállítva {time_value}{time_unit}-ra/ért. Emlékeztetlek: {reminder_message} - időpont: {reminder_time.strftime('%Y-%m-%d %H:%M:%S')}")

    except Exception as e:
        bot.say(f"Hiba történt az emlékeztető feldolgozásakor: {e}")

@plugin.rule(r'\[(\S+)\]!orak')
def list_reminders(bot, trigger):
    """Összes aktív emlékeztető felsorolása egy felhasználó számára."""
    username = trigger.group(1)

    # Emlékeztetők betöltése fájlból, hogy biztosan az aktuális adatokat tartalmazza
    reminders = load_reminders()

    if username not in reminders or not reminders[username]:
        bot.say(f"@{username} nincsenek aktív emlékeztetőid.")
        return
    
    bot.say(f"@{username} aktív emlékeztetők:")
    for idx, reminder in enumerate(reminders[username], 1):
        reminder_time = reminder['time']
        if isinstance(reminder_time, str):
            reminder_time = datetime.strptime(reminder_time, '%Y-%m-%d %H:%M:%S')
            
        time_left = reminder_time - datetime.now()
        days, seconds = time_left.days, time_left.seconds
        hours = seconds // 3600
        minutes = (seconds % 3600) // 60
        
        time_str = []
        if days > 0:
            time_str.append(f"{days} nap")
        if hours > 0:
            time_str.append(f"{hours} óra")
        if minutes > 0:
            time_str.append(f"{minutes} perc")
        
        time_display = ", ".join(time_str) if time_str else "kevesebb mint 1 perc"
        
        bot.say(f"{idx}. '{reminder['message']}' - {time_display} múlva")

@plugin.rule(r'\[(\S+)\]!delora (\d+)')
def delete_reminder(bot, trigger):
    """Egy adott emlékeztető törlése."""
    username = trigger.group(1)
    try:
        reminder_index = int(trigger.group(2)) - 1
        
        reminders = load_reminders()
        
        if username not in reminders or not reminders[username]:
            bot.say(f"@{username} nincsenek aktív emlékeztetőid.")
            return
        
        if reminder_index < 0 or reminder_index >= len(reminders[username]):
            bot.say(f"@{username} érvénytelen emlékeztető szám. Használhatod a !orak parancsot a listázáshoz.")
            return
        
        # Az emlékeztető törlése
        reminder_to_delete = reminders[username][reminder_index]
        
        # Timer törlése, ha létezik
        timer_key = f"{username}_{reminder_to_delete['id']}"
        if timer_key in timer_objects:
            if timer_objects[timer_key].is_alive():
                timer_objects[timer_key].cancel()
            del timer_objects[timer_key]
        
        # Emlékeztető eltávolítása a listából
        del reminders[username][reminder_index]
        if not reminders[username]:
            del reminders[username]
        
        save_reminders(reminders)
        
        bot.say(f"@{username} emlékeztető törölve: '{reminder_to_delete['message']}'")
        
    except (ValueError, IndexError) as e:
        bot.say(f"@{username} hiba történt az emlékeztető törlésekor: {e}")