├── .gitignore ├── LICENSE ├── README ├── README.md ├── gen_rst_readme.py ├── requirements.txt ├── setup.py └── todoist_cli ├── __init__.py └── todoist_cli.py /.gitignore: -------------------------------------------------------------------------------- 1 | AccountCredentials.py 2 | 3 | # Secret 4 | secret.py 5 | tasks.txt 6 | *_tasks.txt 7 | 8 | # Byte-compiled / optimized / DLL files 9 | __pycache__/ 10 | *.py[cod] 11 | 12 | # C extensions 13 | *.so 14 | 15 | # Distribution / packaging 16 | .Python 17 | env/ 18 | bin/ 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .cache 41 | nosetests.xml 42 | coverage.xml 43 | 44 | # Translations 45 | *.mo 46 | 47 | # Mr Developer 48 | .mr.developer.cfg 49 | .project 50 | .pydevproject 51 | 52 | # Rope 53 | .ropeproject 54 | 55 | # Django stuff: 56 | *.log 57 | *.pot 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Christopher Su 2 | 3 | 4 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 5 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 7 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 8 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 9 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 10 | SOFTWARE. -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | todoist-cli 2 | =========== 3 | 4 | A command line interface for adding tasks to Todoist. 5 | 6 | Installation 7 | ------------ 8 | 9 | :: 10 | 11 | git clone https://github.com/csu/todoist-cli.git 12 | cd todoist-cli 13 | pip install -r requirements.txt 14 | 15 | Usage 16 | ----- 17 | 18 | :: 19 | 20 | Usage: todoist.py [OPTIONS] FILE 21 | 22 | Add tasks from a file 23 | 24 | Options: 25 | -po, --project TEXT a project id 26 | -pi, --priority TEXT priority (1 to 4, 4 highest) 27 | -i, --indent TEXT indent level (1 to 4, 1 top-level) 28 | -d, --date TEXT due date (Todoist-formatted date string) 29 | --help Show this message and exit. 30 | 31 | Add four tabs to the start of a line to increment the indent level by 1. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | todoist-cli 2 | =========== 3 | 4 | A command line interface for adding tasks to Todoist. 5 | 6 | ## Installation 7 | ```bash 8 | pip install todoist-cli 9 | ``` 10 | 11 | ## Usage 12 | ``` 13 | Usage: todoist.py [OPTIONS] FILE 14 | 15 | Add tasks from a file 16 | 17 | Options: 18 | -po, --project TEXT a project id 19 | -pi, --priority TEXT priority (1 to 4, 4 highest) 20 | -i, --indent TEXT indent level (1 to 4, 1 top-level) 21 | -d, --date TEXT due date (Todoist-formatted date string) 22 | --help Show this message and exit. 23 | ``` 24 | 25 | Add four tabs to the start of a line to increment the indent level by 1. -------------------------------------------------------------------------------- /gen_rst_readme.py: -------------------------------------------------------------------------------- 1 | import pandoc 2 | import os 3 | import re 4 | 5 | pandoc.core.PANDOC_PATH = '/usr/local/bin/pandoc' 6 | 7 | def convert_md_to_rst(): 8 | doc = pandoc.Document() 9 | doc.markdown = open('README.md').read() 10 | 11 | filtered = str(doc.rst) 12 | filtered = re.sub('Table of Contents\n~~~~~~~~~~~~~~~~~.*Installation\n------------', 'Installation\n------------', filtered, flags=re.DOTALL) 13 | filtered = re.sub('\n`\|Build Status\| `_ `\|Latest\nVersion\| `_\n', '', filtered, flags=re.DOTALL) 14 | filtered = re.sub('`\|Gitter\|.*>`_', '', filtered, flags=re.DOTALL) 15 | filtered = re.sub('`\|HuBoard\|.*`_', '', filtered, flags=re.DOTALL) 16 | filtered = re.sub('Contribute\n----------.*', '', filtered, flags=re.DOTALL) 17 | 18 | f = open('README', 'w+') 19 | f.write(filtered) 20 | f.close() 21 | 22 | convert_md_to_rst() -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2017.11.5 2 | chardet==3.0.4 3 | click==6.7 4 | idna==2.6 5 | requests==2.20.0 6 | urllib3==1.26.5 7 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup, find_packages 4 | 5 | setup( 6 | name='todoist-cli', 7 | version='0.0.2', 8 | description='A CLI for batch creating Todoist tasks.', 9 | long_description=open('README').read(), 10 | author='Christopher Su', 11 | author_email='gh@christopher.su', 12 | url='https://github.com/csu/todoist-cli', 13 | packages=find_packages(), 14 | install_requires=[ 15 | 'certifi==2017.11.5', 16 | 'chardet==3.0.4', 17 | 'click==6.7', 18 | 'idna==2.6', 19 | 'requests==2.20.0', 20 | 'urllib3==1.26.5', 21 | ], 22 | entry_points={ 23 | 'console_scripts': [ 24 | 'todoist=todoist_cli.todoist_cli:main' 25 | ], 26 | } 27 | ) 28 | -------------------------------------------------------------------------------- /todoist_cli/__init__.py: -------------------------------------------------------------------------------- 1 | import todoist_cli -------------------------------------------------------------------------------- /todoist_cli/todoist_cli.py: -------------------------------------------------------------------------------- 1 | import os 2 | import urllib 3 | 4 | import click 5 | import requests 6 | 7 | def main(): 8 | # put your Todoist API token in ~/.todoist 9 | config_file = os.path.join(os.path.expanduser('~'), '.todoist') 10 | token = None 11 | if os.path.isfile(config_file): 12 | with open(config_file) as f: 13 | token = f.read().strip() 14 | if not token: 15 | print 'Put your Todoist API token in ~/.todoist' 16 | quit() 17 | 18 | def add_task(task, project=None, priority=None, indent=None, date=None): 19 | if priority: 20 | priority = int(priority) 21 | if indent: 22 | indent = int(indent) 23 | 24 | # four spaces = further indent 25 | while task.startswith(' '): 26 | if not indent: 27 | indent = 1 28 | task = task[4:] 29 | if indent < 4: 30 | indent += 1 31 | 32 | task = urllib.quote(task) 33 | 34 | if date: 35 | date = urllib.quote(date) 36 | 37 | request = 'https://api.todoist.com/API/addItem?content=' + task + '&token=' + token 38 | if project: 39 | request += '&project_id=' + project 40 | if priority: 41 | request += '&priority=' + str(priority) 42 | if indent: 43 | request += '&indent=' + str(indent) 44 | if date: 45 | request += '&date_string=' + date 46 | r = requests.get(request) 47 | 48 | @click.command() 49 | @click.option('--project', '-po', help='a project id') 50 | @click.option('--priority', '-pi', help='priority (1 to 4, 4 highest)') 51 | @click.option('--indent', '-i', help='indent level (1 to 4, 1 top-level)') 52 | @click.option('--date', '-d', help='due date (Todoist-formatted date string)') 53 | @click.argument('file') 54 | def add_tasks_from_file(file, project, priority, indent, date): 55 | """Add tasks from a file""" 56 | with open(file) as f: 57 | content = f.readlines() 58 | for item in content: 59 | add_task(item, project, priority, indent, date) 60 | 61 | add_tasks_from_file() 62 | 63 | if __name__ == '__main__': 64 | main() --------------------------------------------------------------------------------