gdumitrescu
6/16/2015 - 1:00 PM

Trello to Newsletter builder

Trello to Newsletter builder

Recent Updates

Financial Aid: We need your help!

So far we’ve been able to fund 23 people, including 9 speakers, which is awesome!

Announcing Program for DjangoCon US 2015

Congratulations to all our accepted speakers!

Call for Conference Venues

While we’re in the midst of preparations for Austin, it’s also time to think about 2016! Where will we be next year? We need your help in making that decision!

How We Select Financial Aid for Recipients

Deciding how to allocate our financial aid budget is something we take very seriously.

"""
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()