|
""" |
|
Trello to Newsletter builder |
|
|
|
This is heavily inspired by: https://changelog.com/trello-as-a-cms/ |
|
|
|
To install: |
|
pip install click cached_property markdown py-trello |
|
|
|
To run: |
|
export TRELLO_APP_KEY='' |
|
export TRELLO_APP_SECRET='' |
|
export TRELLO_AUTH_TOKEN='' |
|
|
|
python trello-to-newsletter.py --board='My Newsletter board' |
|
|
|
""" |
|
|
|
import click |
|
import markdown |
|
import os |
|
|
|
from trello import TrelloClient |
|
from cached_property import cached_property |
|
|
|
|
|
TRELLO_APP_KEY = os.environ.get('TRELLO_APP_KEY') |
|
TRELLO_APP_SECRET = os.environ.get('TRELLO_APP_SECRET') |
|
TRELLO_AUTH_TOKEN = os.environ.get('TRELLO_AUTH_TOKEN') |
|
# TRELLO_BOARD_ID = os.environ.get('TRELLO_BOARD_ID') |
|
# TRELLO_DEFAULT_LIST = os.environ.get('TRELLO_DEFAULT_LIST', 'Uncategorized') |
|
|
|
|
|
class Post(object): |
|
|
|
def __init__(self, card): |
|
self.card = card |
|
|
|
@property |
|
def attached_link(self): |
|
# No supported in py-trello |
|
return False |
|
|
|
@cached_property |
|
def body(self): |
|
if self.attached_link: |
|
return self.card.description |
|
else: |
|
if '\n\n' in self.card.description: |
|
return self.card.description.split('\n\n', 1)[1] |
|
else: |
|
return self.card.description |
|
|
|
@cached_property |
|
def draft(self): |
|
return 'Draft' in self.labels |
|
|
|
@cached_property |
|
def labels(self): |
|
return [label.name for label in self.card.labels] |
|
|
|
@cached_property |
|
def link(self): |
|
return self.card.description.split('\n\n', 1)[0] |
|
|
|
@cached_property |
|
def sponsored(self): |
|
return 'Sponsored' in self.labels |
|
|
|
@cached_property |
|
def title(self): |
|
return self.card.name |
|
|
|
|
|
class Meta(object): |
|
|
|
def __init__(self, list_object): |
|
self.list_object = list_object |
|
|
|
def get_card(self, name): |
|
cards = self.list_object.list_cards() |
|
for card in cards: |
|
if card.name == name: |
|
return card |
|
return None |
|
|
|
@cached_property |
|
def editors_note(self): |
|
card = self.get_card('editors_note') |
|
if card: |
|
return card.description |
|
return None |
|
|
|
@cached_property |
|
def preview_text(self): |
|
card = self.get_card('preview_text') |
|
if card: |
|
return card.description |
|
return None |
|
|
|
@cached_property |
|
def published_at(self): |
|
card = self.get_card('published_at') |
|
if card: |
|
return card.description |
|
return None |
|
|
|
|
|
@click.command() |
|
@click.option('--board') |
|
@click.option('--board-id') |
|
@click.option('--html/--no-html', default=False) |
|
def main(board, board_id, html): |
|
output = [] |
|
trello = TrelloClient( |
|
api_key=TRELLO_APP_KEY, |
|
api_secret=TRELLO_APP_SECRET, |
|
token=TRELLO_AUTH_TOKEN |
|
# token_secret=str(trello_config.auth_token), |
|
) |
|
|
|
if board: |
|
for obj in trello.list_boards(): |
|
if board == obj.name: |
|
board = obj |
|
else: |
|
board = trello.get_board(board_id) |
|
|
|
open_lists = board.open_lists() |
|
meta = None |
|
if len(open_lists): |
|
for item in open_lists: |
|
if item.name == 'Meta': |
|
meta = Meta(item) |
|
# click.echo(u'published_at: {0}\n'.format(meta.published_at)) |
|
# click.echo(u'preview_text: {0}\n'.format(meta.preview_text)) |
|
# click.echo(u'editors_note: {0}\n'.format(meta.editors_note)) |
|
output.append(u'published_at: {0}\n'.format(meta.published_at)) |
|
output.append(u'preview_text: {0}\n'.format(meta.preview_text)) |
|
output.append(u'editors_note: {0}\n'.format(meta.editors_note)) |
|
continue |
|
|
|
cards = item.list_cards() |
|
if len(cards): |
|
# click.echo(u'## {0}\n'.format(item.name)) |
|
output.append(u'## {0}\n'.format(item.name)) |
|
for card in cards: |
|
post = Post(card) |
|
|
|
if post.draft: |
|
continue |
|
|
|
if post.sponsored: |
|
# click.echo(u'#### Sponsored\n') |
|
output.append(u'#### Sponsored\n') |
|
|
|
if not post.link: |
|
# click.echo(u'WARNING: {0} does not have a valid link!\n'.format(post.title,)) |
|
# click.echo(u'#### Whoops\n') |
|
output.append(u'WARNING: {0} does not have a valid link!\n'.format(post.title,)) |
|
output.append(u'#### Whoops\n') |
|
|
|
# click.echo(u'### [{0}]({1})\n'.format(post.title, post.link)) |
|
# click.echo(u'{0}\n'.format(post.body)) |
|
output.append(u'### [{0}]({1})\n'.format(post.title, post.link)) |
|
output.append(u'{0}\n'.format(post.body)) |
|
|
|
text = '\n'.join(output) |
|
if html: |
|
text = markdown.markdown(text) |
|
|
|
click.echo(text) |
|
|
|
|
|
if __name__ == '__main__': |
|
main() |
This is super cool. I unfortunately don't use trello for anything but would be super cool way to organize a newsletter visually! I wish I had this.