keith / reminders-cli

A simple CLI for interacting with macOS reminders
MIT License
663 stars 52 forks source link

Unable to Execute reminders-cli Commands in VS Code Terminal on macOS #58

Closed epodak closed 1 year ago

epodak commented 1 year ago

I am having difficulty executing reminders-cli commands through the integrated terminal in Visual Studio Code (VS Code) on my macOS system. While the commands work perfectly in my system's terminal (zsh), I encounter an issue when running the same commands in the VS Code terminal. The error message states "You need to grant reminders access".

I have checked the PATH in both terminals and they are identical. I have also ensured that the default shell for VS Code is set to zsh. However, the problem persists.

When I attempt to run my Python script which uses subprocess to call reminders-cli, I get the following error message:

Exception has occurred: CalledProcessError
Command '['reminders', 'show-lists']' returned non-zero exit status 1.
File "/Users/myusername/workspace/reminders/myscript.py", line 6, in myfunction
lists_output = subprocess.check_output(['reminders', 'show-lists'], text=True)
File "/Users/myusername/workspace/reminders/myscript.py", line 34, in <module>
myfunction()
subprocess.CalledProcessError: Command '['reminders', 'show-lists']' returned non-zero exit status 1.

I understand from the error message that I need to grant access to reminders, which I did through the "Security & Privacy" settings in macOS for my terminal. However, VS Code does not appear on the list of apps that can be granted access to reminders, and no prompt appears when I run reminders-cli commands in the VS Code terminal to allow access.

Any guidance on how to resolve this issue would be greatly appreciated. Thank you in advance for your time and assistance.

keith commented 1 year ago

Can you manually add VS Code to that list? 🤔

epodak commented 1 year ago

I constructed an apple script to read reminders requests to solve this problem.

import json
import subprocess

class Reminder:
    def __init__(self):
        self._reminders_file = 'reminders.json'

    def _get_existing_reminders(self):
        try:
            with open(self._reminders_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        except FileNotFoundError:
            return {}

    def export_to_json(self):
        lists_output = subprocess.check_output(['reminders', 'show-lists'], text=True)
        lists = lists_output.splitlines()

        all_reminders = {}
        for list_name in lists:
            reminders_output = subprocess.check_output(['reminders', 'show', list_name], text=True)
            reminders = reminders_output.splitlines()
            all_reminders[list_name] = reminders

        with open(self._reminders_file, 'w', encoding='utf-8') as f:
            json.dump(all_reminders, f, ensure_ascii=False)

    def import_from_json(self):
        all_reminders = self._get_existing_reminders()

        for list_name in all_reminders:
            for reminder in all_reminders[list_name]:
                existing_reminders = subprocess.check_output(['reminders', 'show', list_name], text=True).splitlines()
                # 避免添加重复的提醒
                if reminder not in existing_reminders:
                    subprocess.run(['reminders', 'add', list_name, reminder])

if __name__ == "__main__":
    reminder = Reminder()
    reminder.export_to_json()
    reminder.import_from_json()
epodak commented 1 year ago

apple script


import json
import subprocess

def get_reminders():
    script = """
    set allReminders to {}
    tell application "Reminders"
        set reminderLists to every list
        repeat with aList in reminderLists
            set listName to name of aList
            set listReminders to {}
            set remindersInList to every reminder of aList
            repeat with aReminder in remindersInList
                set end of listReminders to name of aReminder
            end repeat
            set end of allReminders to {listName:listReminders}
        end repeat
    end tell
    return allReminders
    """

    process = subprocess.Popen(['osascript', '-'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = process.communicate(script.encode())

    # 注意:AppleScript 返回的数据格式可能需要额外处理才能正确解析为 JSON
    reminders = json.loads(stdout.decode())

    return reminders

def write_reminders_to_file():
    reminders = get_reminders()

    with open('reminders.json', 'w') as f:
        json.dump(reminders, f)

write_reminders_to_file()