~mapperr/trl

ref: 65a3ac89edf3692c7663fabc4330d4a8bdc23ef3 trl/trullo.py -rw-r--r-- 7.9 KiB
65a3ac89 — mapperr Update help 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
"""Trullo

usage:
    trl b [<board_shortcut>]
    trl l [<list_shortcuts>...]
    trl ll
    trl c <card_shortcut> [o | m <list_shortcut> | e | n <list_shortcut>]
    trl c n <list_shortcut>
    trl g <api_path>
    trl -h

    -h --help  this help message


commands:
    b [<board_shortcut>]
        shows the boards you can access
        with board_shortcut you can select the board you want to work with

    l [<list_shortcuts>...]
        shows lists and cards in the board you have currently selected
        with list_shortcuts you can show only selected lists and their cards

    ll
        shows only the board's lists

    c <card_shortcut> [o | m <list_shortcut> | e]
        shows the card infos
        with o it opens the card shortLink with your default browser
        with m and a target list you can move the card to that list
        with e you can edit the card title and description in your $EDITOR

    c n <list_shortcut>
        create a new card in the list specified by list_shortcut

    g <api_path>
        make a direct api call adding auth params automatically (for debugging/hacking purpose)

env:
    you have to export this 2 variables to authenticate with trello:

    TRELLO_API_TOKEN - your trello api key
    TRELLO_TOKEN - a generated token

    you can obtain those values here: https://trello.com/app-key

"""
import logging
import os
import pprint
import subprocess
import tempfile
import urllib

from docopt import docopt

from trullo.printer import Printer
from trullo.tclient import TClient
from trullo.trl_card import TrlCard

# logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(level=logging.INFO)
logging.getLogger('urllib3.connectionpool').setLevel(logging.INFO)

logger = logging.getLogger(__name__)


def edit_card(card_to_edit: TrlCard = None) -> (str, str):
    """
    :param card_to_edit:
    :return: a Tuple with the new name and description of the card
    """
    tempfile_suffix = 'newcard.md'
    clean_card_name = 'New Card Title'
    card_description = 'New Card Description'
    if card_to_edit is not None:
        tempfile_suffix = f'{card.id}.md'
        clean_card_name = str(card_to_edit.raw_data['name']).replace('\n', '')
        card_description = card_to_edit.raw_data['desc']

    tmpfile_path = f'{tempfile.gettempdir()}/.trl-{tempfile_suffix}'
    with open(tmpfile_path, 'w') as fd:
        fd.writelines(
            f"# The line below is the card title, lines after that are the card description\n"
            f"{clean_card_name}\n{card_description}")
    subprocess.Popen([os.environ.get('EDITOR'), tmpfile_path]).wait()
    with open(tmpfile_path, 'r') as fd:
        lines = fd.readlines()
    return urllib.parse.quote(lines[1].replace('\n', ''), safe=''), \
           urllib.parse.quote(str.join('', lines[2:]), safe='')


if __name__ == '__main__':
    args = docopt(__doc__, version='Trullo beta')

    tclient = TClient()

    tmpdir = tempfile.gettempdir()
    selected_board_filepath = f'{tmpdir}/.trl-selected-board'
    if os.path.exists(selected_board_filepath):
        with open(selected_board_filepath, 'r') as fh:
            selected_board_id, selected_board_name = fh.readline().split(
                ' ', 1)

    if args['g']:
        api_path = args['<api_path>']
        pp = pprint.PrettyPrinter(indent=4)
        pp.pprint(tclient.get(api_path))

    if args['b']:
        boards = tclient.get_boards()
        if args['<board_shortcut>']:
            board_shortcut = args['<board_shortcut>']
            matching_boards = [board for board in boards
                               if board.get_normalized_name()
                                   .startswith(board_shortcut)]
            if len(matching_boards) > 1:
                matching_names = \
                    [board.get_normalized_name() for board in matching_boards]
                print(
                    f'shortcut [{board_shortcut}] matches more than one board: '
                    f'{matching_names}')
                exit(1)
            board = matching_boards[0]
            print(f'selected board {board.raw_data["name"]}')
            with open(selected_board_filepath, 'w') as fh:
                fh.write(f'{board.id} {board.raw_data["name"]}')
        else:
            Printer.print_boards(boards)
            if os.path.exists(selected_board_filepath):
                print(f'\ncurrently selected board: {selected_board_name}')
            else:
                print(f'\nselect a board with `trl b <board_shortcut>`')

    # stuff that works only if a board is selected
    if not args['b'] and not os.path.exists(selected_board_filepath):
        print(f'first select a board with `trl b`')
        exit(1)

    if args['ll']:
        board = tclient.get_board(selected_board_id)
        Printer.print_board_lists(board)

    if args['l']:
        board = tclient.get_board(selected_board_id)
        list_shortcuts = args['<list_shortcuts>']
        if list_shortcuts is not None and len(list_shortcuts) > 0:
            Printer.print_board(board, list_shortcuts)
        else:
            Printer.print_board(board)

    if args['c']:
        board = tclient.get_board(selected_board_id)
        new_command = args['n']
        if new_command:
            target_list_shortcut = args['<list_shortcut>']
            matching_lists = [list_ for list_ in board.lists if
                              list_.get_normalized_name().startswith(
                                  target_list_shortcut)]
            if len(matching_lists) > 1:
                matching_names = \
                    [list_.get_normalized_name() for list_ in matching_lists]
                print(
                    f'shortcut [{target_list_shortcut}] '
                    f'matches more than one list: '
                    f'{matching_names}')
                exit(1)
            list_id = matching_lists[0].id

            new_card_name, new_card_desc = edit_card()
            tclient.new_card(list_id, new_card_name, new_card_desc)
        else:
            card_shortcut = args['<card_shortcut>']
            matching_cards = [
                card
                for card in board.cards
                if card.get_normalized_name().startswith(card_shortcut)
            ]

            if len(matching_cards) > 1:
                matching_names = \
                    [matching_card.get_normalized_name()
                     for matching_card in matching_cards]
                print(
                    f'shortcut [{card_shortcut}] '
                    f'matches more than one card: '
                    f'{matching_names}')
                exit(1)

            selected_card = matching_cards[0]
            card = tclient.get_card(selected_card.id)

            open_command = args['o']
            move_command = args['m']
            edit_command = args['e']
            if open_command:
                subprocess.Popen(['xdg-open', card.raw_data['shortUrl']])
            elif move_command:
                target_list_shortcut = args['<list_shortcut>']

                matching_lists = [list_ for list_ in board.lists if
                                  list_.get_normalized_name().startswith(
                                      target_list_shortcut)]
                if len(matching_lists) > 1:
                    matching_names = \
                        [list_.get_normalized_name() for list_ in
                         matching_lists]
                    print(
                        f'shortcut [{target_list_shortcut}] '
                        f'matches more than one list: '
                        f'{matching_names}')
                    exit(1)
                list_id = matching_lists[0].id

                tclient.move_card(card.id, list_id)
            elif edit_command:
                card_new_name, card_new_desc = edit_card(card)
                logger.debug(card_new_desc)
                tclient.edit_card(card.id, card_new_name, card_new_desc)
            else:
                Printer.print_card(card)