forked from lucbeaulieu/KanbanView
-
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
version 2.6.3, added OPML support, updated database location, updated…
… requirements, added anonymization support
- Loading branch information
1 parent
6f74516
commit c395bc6
Showing
10 changed files
with
134 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
-include appstore/Makefile | ||
|
||
VERSION=2.6.2 | ||
VERSION=2.6.3 | ||
MAIN=things3_kanban | ||
APP=things3_app | ||
SERVER=things3_api | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,5 @@ flake8==3.7.9 | |
python-coveralls==2.9.3 | ||
flask==1.1.2 | ||
argcomplete==1.11.1 | ||
pywebview==3.3.5 | ||
setuptools==45.0.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ def package_files(directory): | |
AUTHOR_MAIL = "[email protected]" | ||
DESCRIPTON = "A simple read-only CLI, API and Web Service for Things 3" | ||
URL = "https://kanbanview.app" | ||
VERSION = "2.6.2" | ||
VERSION = "2.6.3" | ||
DATA_FILES = package_files('resources') | ||
OPTIONS = { | ||
'argv_emulation': False, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ | |
__copyright__ = "2020 Alexander Willner" | ||
__credits__ = ["Alexander Willner"] | ||
__license__ = "Apache License 2.0" | ||
__version__ = "2.6.2" | ||
__version__ = "2.6.3" | ||
__maintainer__ = "Alexander Willner" | ||
__email__ = "[email protected]" | ||
__status__ = "Development" | ||
|
@@ -30,7 +30,8 @@ class Things3(): | |
# Database info | ||
FILE_CONFIG = str(Path.home()) + '/.kanbanviewrc' | ||
FILE_DB = '/Library/Group Containers/'\ | ||
'JLMPQHK86H.com.culturedcode.ThingsMac/Things.sqlite3' | ||
'JLMPQHK86H.com.culturedcode.ThingsMac/'\ | ||
'Things Database.thingsdatabase/main.sqlite' | ||
TABLE_TASK = "TMTask" | ||
TABLE_AREA = "TMArea" | ||
TABLE_TAG = "TMTag" | ||
|
@@ -129,7 +130,7 @@ def __init__(self, | |
|
||
cfg = self.get_from_config(database, 'THINGSDB') | ||
self.database = cfg if cfg else self.database | ||
# Automated migration to new database location in Things 3.12.6 | ||
# Automated migration to new database location in Things 3.12.6/3.13.1 | ||
# -------------------------------- | ||
try: | ||
with open(self.database) as f_d: | ||
|
@@ -190,7 +191,8 @@ def anonymize_tasks(self, tasks): | |
if self.anonymize: | ||
for task in tasks: | ||
task['title'] = self.anonymize_string(task['title']) | ||
task['context'] = self.anonymize_string(task['context']) | ||
task['context'] = self.anonymize_string( | ||
task['context']) if 'context' in task else '' | ||
return tasks | ||
|
||
def get_inbox(self): | ||
|
@@ -230,6 +232,34 @@ def get_today(self): | |
""" | ||
return self.get_rows(query) | ||
|
||
def get_task(self, area=None, project=None): | ||
"""Get tasks.""" | ||
afilter = f'AND TASK.area = "{area}"' \ | ||
if area is not None else '' | ||
pfilter = f'AND TASK.project = "{project}"' \ | ||
if project is not None else '' | ||
query = f""" | ||
TASK.{self.IS_NOT_TRASHED} AND | ||
TASK.{self.IS_TASK} AND | ||
TASK.{self.IS_OPEN} AND | ||
TASK.{self.IS_ANYTIME} AND | ||
TASK.{self.IS_NOT_RECURRING} AND ( | ||
( | ||
PROJECT.title IS NULL OR ( | ||
PROJECT.{self.IS_NOT_TRASHED} | ||
) | ||
) AND ( | ||
HEADPROJ.title IS NULL OR ( | ||
HEADPROJ.{self.IS_NOT_TRASHED} | ||
) | ||
) | ||
) | ||
{afilter} | ||
{pfilter} | ||
ORDER BY TASK.duedate DESC, TASK.{self.DATE_CREATE} DESC | ||
""" | ||
return self.get_rows(query) | ||
|
||
def get_someday(self): | ||
"""Get someday tasks.""" | ||
query = f""" | ||
|
@@ -412,8 +442,9 @@ def get_trashed(self): | |
""" | ||
return self.get_rows(query) | ||
|
||
def get_projects(self): | ||
def get_projects(self, area=None): | ||
"""Get projects.""" | ||
afilter = f'AND TASK.area = "{area}"' if area is not None else '' | ||
query = f""" | ||
SELECT | ||
TASK.uuid, | ||
|
@@ -432,6 +463,7 @@ def get_projects(self): | |
TASK.{self.IS_NOT_TRASHED} AND | ||
TASK.{self.IS_PROJECT} AND | ||
TASK.{self.IS_OPEN} | ||
{afilter} | ||
ORDER BY TASK.title COLLATE NOCASE | ||
""" | ||
return self.execute_query(query) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ | |
__copyright__ = "Copyright 2020 Alexander Willner" | ||
__credits__ = ["Alexander Willner"] | ||
__license__ = "Apache License 2.0" | ||
__version__ = "2.6.2" | ||
__version__ = "2.6.3" | ||
__maintainer__ = "Alexander Willner" | ||
__email__ = "[email protected]" | ||
__status__ = "Development" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ | |
__copyright__ = "Copyright 2020 Alexander Willner" | ||
__credits__ = ["Luc Beaulieu", "Alexander Willner"] | ||
__license__ = "Apache License 2.0" | ||
__version__ = "2.6.2" | ||
__version__ = "2.6.3" | ||
__maintainer__ = "Alexander Willner" | ||
__email__ = "[email protected]" | ||
__status__ = "Development" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ | |
__copyright__ = "2020 Alexander Willner" | ||
__credits__ = ["Alexander Willner"] | ||
__license__ = "Apache License 2.0" | ||
__version__ = "2.6.2" | ||
__version__ = "2.6.3" | ||
__maintainer__ = "Alexander Willner" | ||
__email__ = "[email protected]" | ||
__status__ = "Development" | ||
|
@@ -21,13 +21,16 @@ | |
import webbrowser | ||
import argcomplete # type: ignore | ||
from things3.things3 import Things3 | ||
from things3.things3_opml import Things3OPML | ||
|
||
|
||
class Things3CLI(): | ||
"""Simple read-only Thing 3 CLI.""" | ||
|
||
print_json = False | ||
print_csv = False | ||
print_opml = False | ||
anonymize = False | ||
things3 = None | ||
|
||
def __init__(self, database=None): | ||
|
@@ -37,6 +40,8 @@ def print_tasks(self, tasks): | |
"""Print a task.""" | ||
if self.print_json: | ||
print(json.dumps(tasks)) | ||
elif self.print_opml: | ||
Things3OPML().print_tasks(tasks) | ||
elif self.print_csv: | ||
fieldnames = ['uuid', 'title', 'context', 'context_uuid', 'size', | ||
'type', 'due', 'created', 'modified', 'started', | ||
|
@@ -48,7 +53,7 @@ def print_tasks(self, tasks): | |
else: | ||
for task in tasks: | ||
title = task['title'] | ||
context = task['context'] | ||
context = task['context'] if 'context' in task else '' | ||
print(' - ', title, ' (', context, ')') | ||
|
||
@classmethod | ||
|
@@ -88,6 +93,10 @@ def get_parser(cls): | |
help='Shows all tasks') | ||
subparsers.add_parser('csv', | ||
help='Exports tasks as CSV') | ||
subparsers.add_parser('areas', | ||
help='Shows all areas') | ||
subparsers.add_parser('opml', | ||
help='Exports tasks as OPML') | ||
subparsers.add_parser('due', | ||
help='Shows tasks with due dates') | ||
subparsers.add_parser('empty', | ||
|
@@ -147,6 +156,14 @@ def get_parser(cls): | |
action="store_true", default=False, | ||
help="output as CSV", dest="csv") | ||
|
||
parser.add_argument("-o", "--opml", | ||
action="store_true", default=False, | ||
help="output as OPML", dest="opml") | ||
|
||
parser.add_argument("-a", "--anonymize", | ||
action="store_true", default=False, | ||
help="anonymize output", dest="anonymize") | ||
|
||
parser.add_argument( | ||
"--version", | ||
action="version", | ||
|
@@ -165,10 +182,15 @@ def main(self, args=None): | |
command = args.command | ||
self.print_json = args.json | ||
self.print_csv = args.csv | ||
self.print_opml = args.opml | ||
self.anonymize = args.anonymize | ||
self.things3.anonymize = self.anonymize | ||
|
||
if command in self.things3.functions: | ||
func = self.things3.functions[command] | ||
self.print_tasks(func(self.things3)) | ||
elif command == "opml": | ||
Things3OPML().print_all(self.things3) | ||
elif command == "csv": | ||
print("Deprecated: use --csv instead") | ||
elif command == "feedback": | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ | |
__copyright__ = "Copyright 2020 Alexander Willner" | ||
__credits__ = ["Luc Beaulieu", "Alexander Willner"] | ||
__license__ = "Apache License 2.0" | ||
__version__ = "2.6.2" | ||
__version__ = "2.6.3" | ||
__maintainer__ = "Alexander Willner" | ||
__email__ = "[email protected]" | ||
__status__ = "Development" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
|
||
"""OPML Plugin for the Thing 3 CLI.""" | ||
|
||
from __future__ import print_function | ||
|
||
__author__ = "Alexander Willner" | ||
__copyright__ = "2020 Alexander Willner" | ||
__credits__ = ["Alexander Willner"] | ||
__license__ = "Apache License 2.0" | ||
__version__ = "2.6.3" | ||
__maintainer__ = "Alexander Willner" | ||
__email__ = "[email protected]" | ||
__status__ = "Development" | ||
|
||
import xml.etree.ElementTree as ET | ||
from xml.etree.ElementTree import Element, SubElement | ||
from xml.dom import minidom | ||
|
||
|
||
class Things3OPML(): | ||
"""OPML Plugin for Thing 3 CLI.""" | ||
|
||
@staticmethod | ||
def get_top(): | ||
"""Get first element.""" | ||
top = Element('opml') | ||
head = SubElement(top, 'head') | ||
title = SubElement(head, 'title') | ||
title.text = 'Things 3 Database' | ||
return top | ||
|
||
@staticmethod | ||
def print(top): | ||
"""Print pretty XML.""" | ||
xmlstr = minidom.parseString( | ||
ET.tostring(top)).toprettyxml(indent=" ") | ||
print(xmlstr) | ||
|
||
def print_tasks(self, tasks): | ||
"""Print pretty XML of selected tasks.""" | ||
top = self.get_top() | ||
body = SubElement(top, 'body') | ||
for task in tasks: | ||
SubElement(body, 'outline').set('text', task['title']) | ||
self.print(top) | ||
|
||
def print_all(self, things3): | ||
"""Print.""" | ||
top = self.get_top() | ||
body = SubElement(top, 'body') | ||
|
||
for area in things3.get_areas(): | ||
area_element = SubElement(body, 'outline') | ||
area_element.set('text', area['title']) | ||
for task in things3.get_task(area['uuid']): | ||
SubElement(area_element, 'outline').set('text', task['title']) | ||
for project in things3.get_projects(area['uuid']): | ||
project_element = SubElement(area_element, 'outline') | ||
project_element.set('text', project['title']) | ||
for task in things3.get_task(None, project['uuid']): | ||
SubElement(project_element, 'outline').set( | ||
'text', task['title']) | ||
self.print(top) |