Skip to content

Commit

Permalink
Merge branch 'master' of github.com:matthew-parlette/scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
matthew-parlette committed Jun 8, 2016
2 parents d919b9b + 1ed106e commit 191b9f9
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 0 deletions.
2 changes: 2 additions & 0 deletions recurring-tasks/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.yaml
*.log
52 changes: 52 additions & 0 deletions recurring-tasks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# OVerview

Create Trello cards on a weekly or monthly basis.

The cards will be in a specific list on a specific board.

# Config

Example Configuration `config.yaml`:

```
monthly:
'1':
- plan finances for the month
trello:
api-key: API-KEY-HERE
api-secret: API-SECRET-HERE
board: qs9sZTxs
list: 5624e269b8a14c9076961c7d
token: TOKEN-HERE
token-secret: TOKEN-SECRET_HERE
weekly:
monday:
- task
thursday:
- take out trash
```

## trello

The `trello` section defines API keys and which board and list to use.

If you don't know the board or list IDs, you can run the script in debug
(`./recurring-tasks -d`) and it will print a list of IDs for the boards or
lists.

## monthly

Using weekday names, specify a list of tasks to perform on each day

## monthly

Using the day of the month (integer), specify a list of tasks to perform
on that day.

# Usage

To run this as a daily cron job:

```
0 6 * * * cd /home/matt/scripts/recurring-tasks;./recurring-tasks -c personal.yaml
```
178 changes: 178 additions & 0 deletions recurring-tasks/recurring-tasks
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#!/usr/bin/python

import argparse
import logging
import os
import yaml
import trello
import trello.util
import datetime

global config


def merge(x, y):
"""
store a copy of x, but overwrite with y's values where applicable
"""
merged = dict(x, **y)

xkeys = x.keys()

# if the value of merged[key] was overwritten with y[key]'s value
# then we need to put back any missing x[key] values
for key in xkeys:
# if this key is a dictionary, recurse
if isinstance(x[key], dict) and key in y:
merged[key] = merge(x[key], y[key])

return merged


def create_card(name, description=""):
log.debug("Creating card '{}'...".format(name))

if config['trello']['board']:
board = trelloAPI.get_board(config['trello']['board'])
if board:
log.debug("Loaded board {}".format(str(board)))
if config['trello']['list']:
trellolist = board.get_list(config['trello']['list'])
if trellolist:
trellolist.add_card(
name=name,
desc=description)
log.info("Card created for {}".format(name))
else:
log.error("Couldn't load list {}".format(
config['trello']['list']))
else:
log.error("No list id defined in config. "
"Possible values are:\n{}".format(
'\n'.join(["{} - {}".format(
l.id, l.name) for l in board.open_lists()])))
else:
log.error("Couldn't load board {}".format(
config['trello']['board']))
else:
log.error("No board id defined in config. "
"Possible values are:\n{}".format(
'\n'.join(["{} - {}".format(
b.id, b.name) for b in trelloAPI.list_boards()])))

if __name__ == "__main__":
# Parse command line arguments
parser = argparse.ArgumentParser(
description='Process command line options.')
parser.add_argument(
'-d', '--debug', action='store_true', help='Enable debug logging')
parser.add_argument(
'-c', '--config', help='Specify a config file to use',
type=str, default='config.yaml')
parser.add_argument('--version', action='version', version='0')
args = parser.parse_args()

# Setup logging options
log_level = logging.DEBUG if args.debug else logging.INFO
log = logging.getLogger(os.path.basename(__file__))
log.setLevel(log_level)
formatter = logging.Formatter('%(asctime)s:%(name)s:%(levelname)s'
':%(funcName)s(%(lineno)i):%(message)s')

# Console Logging
ch = logging.StreamHandler()
ch.setLevel(log_level)
ch.setFormatter(formatter)
log.addHandler(ch)

# File Logging
fh = logging.FileHandler(os.path.basename(__file__) + '.log')
fh.setLevel(log_level)
fh.setFormatter(formatter)
log.addHandler(fh)

log.info("Initializing...")

log.info("Loading configuration...")
# Load Config
global config
defaults = {
"weekly": {
# "monday": [
# "task",
# ],
},
"monthly": {
# "1": [
# "task",
# ],
},
"trello": {
"api-key": "",
"api-secret": "",
"token": "",
"token-secret": "",
"board": "",
"list": "",
},
}
if os.path.isfile(args.config):
log.debug("Loading config file %s" % args.config)
config = yaml.load(file(args.config))
if config:
# config contains items
config = merge(defaults, yaml.load(file(args.config)))
log.debug("Config merged with defaults")
else:
# config is empty, just use defaults
config = defaults
log.debug("Config file was empty, loaded config from defaults")
else:
log.debug("Config file does not exist, creating a default config...")
config = defaults

log.debug("Config loaded as:\n%s, saving this to disk" % str(config))
with open(args.config, 'w') as outfile:
outfile.write(yaml.dump(config, default_flow_style=False))
log.debug("Config loaded as:\n%s" % str(config))

log.info("Initializing Trello...")
global trello
try:
trelloAPI = trello.TrelloClient(
api_key=config['trello']['api-key'],
api_secret=config['trello']['api-secret'],
token=config['trello']['token'],
token_secret=config['trello']['token-secret'])
if args.debug:
log.debug("Testing Trello (Listing Boards)...")
log.debug(str(trelloAPI.list_boards()))
except trello.exceptions.ResourceUnavailable:
log.error("Authentication error, starting oauth generation...")
trello.util.create_oauth_token(
expiration='never',
key=config['trello']['api-key'],
secret=config['trello']['api-secret'])

log.info("Initialization complete")

dow = datetime.datetime.today().strftime("%A").lower() # string
log.debug("Day of week is {}".format(dow))
dom = datetime.datetime.today().strftime("%-d") # decimal
log.debug("Day of month is {}".format(str(dom)))

tasks = []
# Check for day of week tasks
if str(dow) in config['weekly']:
tasks.extend(config['weekly'][str(dow)])

# Check for day of month tasks
if str(dom) in config['monthly']:
tasks.extend(config['monthly'][str(dom)])

log.info("Tasks for today are {}".format(tasks))

# Create task cards
for task in tasks:
log.info("Creating task card '{}'...".format(task))
create_card(name=task, description="")

0 comments on commit 191b9f9

Please sign in to comment.