-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add option for tags #74
Comments
AFAICT tags aren't in the public API https://developer.apple.com/documentation/eventkit/ekevent |
Semi-related:
In
That seems to be enough basic info to figure out resolving both this issue, and maybe also #72 Would just need to figure out how to match up the ID/data that the API is currently able to provide, with an ID that can be looked up in the sqlite database; and then extract the associated hashtags/etc. I was thinking that maybe Edit: Collated/cross-posted the above on the following gist for future reference: https://gist.github.com/0xdevalias/ccc2b083ff58b52aa701462f2cfb3cc8#accessing--exporting-apples-reminders-data-on-macos Edit 2: Found this cool blog post laying out a lot of the specifics of how the internals of Apple CoreData based SQLite databases are laid out: https://fatbobman.com/en/posts/tables_and_fields_of_coredata/ Edit 3: Based on that blog post, we can see that we can look up what the Edit 4: I wrote a basic python script to extract the CoreData models + hierarchy from the Reminders SQLite CoreData Models + Associated tables⇒ ./extract-coredata-model-hierarchy.py /Users/devalias/Library/Reminders/Container_v1/Stores/Data-5070B790-D66D-40F7-8F4A-EC8E0FA88F3A.sqlite
- 1: REMCDAccountListData (Table: ZREMCDACCOUNTLISTDATA)
- 2: REMCDChangeTrackingState (Table: ZREMCDCHANGETRACKINGSTATE)
- 3: REMCDHashtagLabel (Table: ZREMCDHASHTAGLABEL)
- 4: REMCDMigrationState (Table: ZREMCDMIGRATIONSTATE)
- 5: REMCDObject (Table: ZREMCDOBJECT)
- 6: REMCDAccount
- 7: REMCDAlarm
- 8: REMCDAlarmTrigger
- 9: REMCDAlarmDateTrigger
- 10: REMCDAlarmLocationTrigger
- 11: REMCDAlarmTimeIntervalTrigger
- 12: REMCDAlarmVehicleTrigger
- 13: REMCDAssignment
- 14: REMCDAttachment
- 15: REMCDFileAttachment
- 16: REMCDAudioAttachment
- 17: REMCDImageAttachment
- 18: REMCDURLAttachment
- 19: REMCDAuxiliaryChangeInfo
- 20: REMCDAuxiliaryReminderChangeInfo
- 21: REMCDAuxiliaryReminderChangeDeleteInfo
- 22: REMCDAuxiliaryReminderChangeMoveInfo
- 23: REMCDCalDAVNotification
- 24: REMCDHashtag
- 25: REMCDList
- 26: REMCDManualSortHint_v1
- 27: REMCDRecurrenceRule
- 28: REMCDSharedToMeReminderPlaceholder
- 29: REMCDSharee
- 30: REMCDSmartList
- 31: REMCDPublicTemplate (Table: ZREMCDPUBLICTEMPLATE)
- 32: REMCDReminder (Table: ZREMCDREMINDER)
- 33: REMCDReplicaManager (Table: ZREMCDREPLICAMANAGER)
- 34: REMCDSavedAttachment (Table: ZREMCDSAVEDATTACHMENT)
- 35: REMCDSavedReminder (Table: ZREMCDSAVEDREMINDER)
- 36: REMCDTemplate (Table: ZREMCDTEMPLATE)
- 37: REMCDTemplateOperationQueueItem (Table: ZREMCDTEMPLATEOPERATIONQUEUEITEM)
- 38: REMCKCloudState (Table: ZREMCKCLOUDSTATE)
- 39: REMCKServerChangeToken (Table: ZREMCKSERVERCHANGETOKEN)
- 40: REMCKSharedEntitySyncActivity (Table: ZREMCKSHAREDENTITYSYNCACTIVITY)
- 41: REMCKSharedObjectOwnerName (Table: ZREMCKSHAREDOBJECTOWNERNAME)
- 16001: CHANGE
- 16002: TRANSACTION
- 16003: TRANSACTIONSTRING |
Working with the above rough notes (and remembering how SQL joins work), I eventually came up with this, that would seem to extract all of the relevant entries from ⇒ reminders show Reminders --sort creation-date --sort-order ascending --format json | jq '[limit(1;.[])]'
[
{
"dueDate": "2023-08-13T14:00:00Z",
"externalId": "EAA1A308-368E-4F90-B9D5-6E6A12AE7E6D",
"isCompleted": false,
"list": "Reminders",
"priority": 0,
"title": "Foo Bar Baz"
}
] SELECT ZO.*
FROM ZREMCDOBJECT ZO
JOIN (
SELECT Z_PK
FROM ZREMCDREMINDER
WHERE ZCKIDENTIFIER = 'EAA1A308-368E-4F90-B9D5-6E6A12AE7E6D'
OR ZDACALENDARITEMUNIQUEIDENTIFIER = 'EAA1A308-368E-4F90-B9D5-6E6A12AE7E6D'
) AS ZR ON ZO.ZREMINDER = ZR.Z_PK
OR ZO.ZREMINDER1 = ZR.Z_PK
OR ZO.ZREMINDER2 = ZR.Z_PK
OR ZO.ZREMINDER3 = ZR.Z_PK
OR ZO.ZREMINDER4 = ZR.Z_PK
OR ZO.ZREMINDER5 = ZR.Z_PK
ORDER BY ZO.Z_ENT; This gives me 3 rows:
⇒ EXTERNAL_ID='EAA1A308-368E-4F90-B9D5-6E6A12AE7E6D' &&
sqlite3 -readonly -json /Users/devalias/Library/Reminders/Container_v1/Stores/Data-5070B790-D66D-40F7-8F4A-EC8E0FA88F3A.sqlite "
SELECT ZO.*
FROM ZREMCDOBJECT ZO
JOIN (
SELECT Z_PK
FROM ZREMCDREMINDER
WHERE ZCKIDENTIFIER = '$EXTERNAL_ID'
OR ZDACALENDARITEMUNIQUEIDENTIFIER = '$EXTERNAL_ID'
) AS ZR ON ZO.ZREMINDER = ZR.Z_PK
OR ZO.ZREMINDER1 = ZR.Z_PK
OR ZO.ZREMINDER2 = ZR.Z_PK
OR ZO.ZREMINDER3 = ZR.Z_PK
OR ZO.ZREMINDER4 = ZR.Z_PK
OR ZO.ZREMINDER5 = ZR.Z_PK
ORDER BY ZO.Z_ENT;
" | jq 'length'
3 If there were other associated rows, they would obviously have been included as well. This would allow for a much more robust/complete amount of reminders data to be shown/exported; without needing to wait for the official API's to be updated to support it (and then if/when the API's are updated, these methods could then use the official API) Edit: Collated/cross-posted the above on the following gist for future reference: https://gist.github.com/0xdevalias/ccc2b083ff58b52aa701462f2cfb3cc8#accessing--exporting-apples-reminders-data-on-macos |
For what it's worth, interacting directly with OS X application sqlite dbs is fraught with peril/pain: the schemas change fairly often, encodings, formats, etc of rows change. From my experience trying to export notes, it's been challenging to say the least: I've had to remove functionality because of changes to the underlying sqlite dataset. |
fwiw it's possible to use the private APIs that reminders.app uses instead for this kinda thing, which i imagine might be a bit safer long term. i have a private codebase unrelated to this repo that does that successfully to handle multiple URLs which isn't exposed in the public API |
@keith Oh? Interesting.. that's not a path I've looked into before. Curious, do you have any particularly useful blog / gist / etc references that go into the process and/or the findings more that you'd be happy to share? Would be interested to read more about it. |
the gist is you copy the runtime headers from the framework that contains REMStore, and then you can poke around at those private methods at least to fetch data. I didn't try to do any edits through that, but unsurprisingly the reminders you get from fetching there have matching IDs with the ones you get from the public APIs. |
@keith Interesting, thanks! Have had ChatGPT expand on that a bit (Ref), and got myself a whole new pile of sideproject reading/learning to do! (Refs: 1, 2, 3, 4, 5, 6, 7, 8, etc) Edit: Captured these references in my gist here, and will likely expand on them in future: https://gist.github.com/0xdevalias/ccc2b083ff58b52aa701462f2cfb3cc8#macos-private-frameworks |
Tags were introduced in the Reminders app in macOS Monterey and can be extremely useful when managing various types of tasks. I think adding this to the reminders CLI would make it all the more powerful than it already is, especially when used with scripts and automation.
Usage examples:
NOTE: Adding support for multiple tags would be ideal but not required
These are just some basic examples but you can probably see how useful this could be.
Also, yes, I did see that there was one comment about this already on #59, but, I felt it was worth explicitly calling it out in a separate issue, so as not to get lost. If you'd rather work on this in the already open issue for enhancements, then please feel free to delete this one.
The text was updated successfully, but these errors were encountered: