main program

                Never    
import argparse
from psutil import process_iter, NoSuchProcess, AccessDenied, ZombieProcess
from yaml import dump, dump_all, load_all
from colorama import init, Style, Fore
from time import localtime
from os import startfile

ALARM_FILE = 'alarms.txt'
WEEKDAYS = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']


def readable_time(hrs, min):
    hrs = str(hrs)
    min = str(min)

    if len(hrs) < 2:
        hrs = '0' + hrs
    if len(min) < 2:
        min = '0' + min

    return f'{hrs}:{min}'


def read_alarms():
    with open(ALARM_FILE, 'r') as f:
        return list(load_all(f))


def days_str_to_int(days):
    translated_days = []
    for chosen_day in days:
        if chosen_day in range(7):
            print('trigg')
            translated_days.append(chosen_day)
        else:
            if len(chosen_day) < 2:
                raise NameError(Fore.RED + 'Ambiguous weekday entered; less than two characters long.')
            else:
                found = None
                for idx, DAY in enumerate(WEEKDAYS):
                    if chosen_day in DAY:
                        translated_days.append(idx)
                        break
    return translated_days


def set_alarm(args):
    alarm = vars(args)
    del alarm['func']
    alarm['days'] = days_str_to_int(alarm['days'])

    with open(ALARM_FILE, 'a') as f:
        dump(alarm, f, explicit_start=True)

    print(f"Alarm has been set for days {alarm['days']} at {readable_time(alarm['hours'], alarm['minutes'])} and will play {alarm['url']}")


def list_alarms(args):
    alarms = read_alarms()
    if alarms:
        for idx, alarm in enumerate(alarms):
            print(f'{Fore.GREEN} + Alarm #{idx}')
            print(f'''          {alarm['days']}        {readable_time(alarm['hours'], alarm['minutes'])}                   
            ''')
    else:
        print(Fore.RED + 'There are no alarms currently set.')


def remove_alarm(args):
    alarms = read_alarms()
    try:
        alarm = alarms[args.index]
        while True:
            ans = input(f"You have chosen the alarm at {readable_time(alarm['hours'], alarm['minutes'])} playing {alarm['url']}. Are you sure you want to remove it? (y/n)").lower()
            if ans in ['y', 'yes']:
                del alarms[args.index]
                with open(ALARM_FILE, 'w') as f:
                    for alarm in alarms:
                        dump(alarm, f, explicit_start=True)
                print(Fore.GREEN + f'\nAlarm #{args.index} has been removed successfully')
                return
            elif ans in ['n', 'no']:
                print(Fore.RED + 'Removal canceled.')
                return

            else:
                print('Please type (y)es to delete the alarm or (n)o to cancel')

    except IndexError:
        raise IndexError(Fore.RED + f'Alarm with an index of {args.index} could not be found')


def start_alarm_checker():
    for proc in process_iter():
        try:
            if proc.name() == 'alarm_checker.exe':
                return
        except (NoSuchProcess, AccessDenied, ZombieProcess):
            pass
    else:
        startfile('alarm_checker.exe')


def parse():
    init(autoreset=True)
    main_parser = argparse.ArgumentParser(description='The main parser for the alarm program')
    subparsers = main_parser.add_subparsers()

    # Setting the alarm
    parser_set = subparsers.add_parser('set', help='Set an alarm for the specified time')
    parser_set.add_argument('hours', type=int, choices=list(range(24)), help='The time in hours (between 0 and 23).')
    parser_set.add_argument('minutes', type=int, choices=list(range(59)),
                            help='The time in minutes (between 0 and 60).')
    parser_set.add_argument('--days', nargs='*', default=[localtime().tm_wday],
                            help='What days the alarm should be active, either in text or numbers. Default: Today')
    parser_set.add_argument('--url', type=str, default='https://www.youtube.com/watch?v=dQw4w9WgXcQ',
                            help='What URL the alarm should open. Default: www.youtube.com/watch?v=dQw4w9WgXcQ')
    parser_set.add_argument('--once', action='store_true', help='If the alarm is a one-time use. Default: False')
    parser_set.set_defaults(func=set_alarm)

    # Listing all the current active alarms
    parser_list = subparsers.add_parser('list', help='List all alarms')
    parser_list.set_defaults(func=list_alarms)

    # Delete an alarm by index
    parser_delete = subparsers.add_parser('remove', help='Remove an alarm by index (starting at 1)')
    parser_delete.add_argument('index', type=int, help='Index of alarm')
    parser_delete.set_defaults(func=remove_alarm)

    args = main_parser.parse_args()
    args.func(args)


if __name__ == '__main__':
    start_alarm_checker()
    parse()

Raw Text