#!/usr/bin/python3 import notify2 from time import sleep from playsound import playsound import os from pystray import MenuItem as item import pystray from PIL import Image import argparse import threading NAME = 'Eye Strain Reminder' MESSAGE = 'Friendly reminder to observe the 20-20-20 rule' MESSAGE_MISSED = 'Missed notification(s), resuming countdown' TIMEOUT = 20 MILLISECOND = 1000 MINUTE = 60 DIR = os.path.dirname(os.path.abspath(__file__)) icon = mute = disable_notifs = invert_icons = notify_thread = sound = None #mute = False #disable_notifs = False #invert_icons = False #notify_thread = None def init(): print("Initializing EyeStrainReminder...") notify2.init(NAME) def create_tray_icon(): global icon image = get_image() icon = pystray.Icon(NAME, image, NAME, generate_menu_items()) icon.run() def update_icon(): global icon image = get_image() icon.icon = image def get_image(): theme = [[f"{DIR}/files/eye_light.png", f"{DIR}/files/eye_dark.png"], [f"{DIR}/files/eye_dark.png", f"{DIR}/files/eye_light.png"]] return Image.open(theme[invert_icons][disable_notifs]) def generate_menu_items(): menu_items = [] menu_items.append(item('Mute' if not mute else 'Unmute', toggle_mute)) menu_items.append(item('Do Not Disturb' if not disable_notifs else 'Enable Notifications', toggle_notifications)) return menu_items def toggle_mute(): global mute mute = not mute update_menu() def toggle_notifications(): global disable_notifs disable_notifs = not disable_notifs update_menu() update_icon() def update_menu(): global icon icon.menu = generate_menu_items() icon.update_menu() def uninit(): notify2.uninit() def wait(): #sleep(TIMEOUT*MINUTE) pass def send_notification(): if not disable_notifs: notify(MESSAGE) else: print("Notifications are disabled, waiting for an enable...") while disable_notifs: sleep(10) notify(MESSAGE_MISSED) def notify(message): print(message) notification = notify2.Notification(NAME, message, "notification-device-eject") notification.set_timeout(TIMEOUT * MILLISECOND) notification.set_urgency(notify2.URGENCY_LOW) notification.show() play_sound() sleep(TIMEOUT) notification.close() play_sound() def play_sound(): if not mute: playsound(sound) def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("-i", "--invert_icons", action="store_true", default=False, help="Default to the dark icon for light themes") parser.add_argument("-m", "--mute", action="store_true", default=False, help="Mute notification sounds by default") parser.add_argument("-n", "--disable_notifs", action="store_true", default=False, help="Disable notifications by default") parser.add_argument("-s", "--sound", action="store", default=f"{DIR}/files/default.wav", help="Custom notification sound") args = parser.parse_args() globals().update(args.__dict__) def main(): init() while 1: wait() send_notification() uninit() if __name__ == '__main__': parse_args() notify_thread = threading.Thread(target=main, name="Notify Thread") notify_thread.start() create_tray_icon() notify_thread.join()