forked from smarty-archives/trello-backup
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrello-backup.py
executable file
·146 lines (123 loc) · 4.45 KB
/
trello-backup.py
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
#!/usr/bin/env python3 -u
import configparser
import os, sys
import json
import requests
import time
import io
configFile = 'trello-backup.config'
configFile = os.path.join(os.path.abspath(os.path.dirname(__file__)), configFile)
API_KEY = TOKEN = API_URL = ''
def main():
if os.path.isfile(configFile):
config = configparser.RawConfigParser()
config.read(configFile)
else:
sys.exit('Config file "{0}" does not exist.'.format(configFile))
global API_KEY, TOKEN, API_URL
API_KEY = config.get('Credentials', 'API_KEY')
TOKEN = config.get('Credentials', 'TOKEN')
API_URL = config.get('Paths', 'API_URL')
OUTPUT_DIRECTORY = config.get('Paths', 'OUTPUT_DIRECTORY')
TOKEN_EXPIRATION = config.get('Options', 'TOKEN_EXPIRATION')
APP_NAME = config.get('Options', 'APP_NAME')
ORGANIZATION_IDS = config.get('Options', 'ORGANIZATION_IDS')
ORGANIZATION_NAMES = config.get('Options', 'ORGANIZATION_NAMES')
PRETTY_PRINT = config.get('Options', 'PRETTY_PRINT') == 'yes'
if not API_KEY:
print('You need an API key to run this app.')
print('Visit this url: https://trello.com/1/appKey/generate')
API_KEY = raw_input('Then enter the API key here: ')
print('\n[IMPORTANT] Make sure to add the key to the config file.\n')
raw_input('Press enter to continue...\n')
if not TOKEN:
print('You need a token to run this app.')
print("Visit this url: {0}connect?key={1}&name={2}&response_type=token&expiration={3}".format(API_URL, API_KEY, APP_NAME, TOKEN_EXPIRATION))
TOKEN = raw_input('Then enter the token here: ')
print('\n[IMPORTANT] Make sure to add the token to the config file.\n')
raw_input('Press enter to continue...\n')
if ORGANIZATION_NAMES and not ORGANIZATION_IDS:
ORGANIZATION_IDS = get_organization_ids(ORGANIZATION_NAMES)
# Parameters to get list of boards
boardsPayload = {
'key':API_KEY,
'token':TOKEN,
'filter':'open',
'lists':'open',
}
# Parameters to get board contents
boardPayload = {
'key':API_KEY,
'token':TOKEN,
'lists':'open',
'fields':'all',
'actions':'all',
'action_fields':'all',
'actions_limit':'1000',
'cards':'all',
'card_fields':'all',
'card_attachments':'true',
'card_customFieldItems':'true',
'lists':'all',
'list_fields':'all',
'labels':'all',
'customFields':'true',
'members':'all',
'member_fields':'all',
'checklists':'all',
'checklist_fields':'all',
'organization':'false',
'pluginData':'true'
}
boards = requests.get(API_URL + "members/me/boards", params=boardsPayload)
try:
if len(boards.json()) <= 0:
print('No boards found.')
return
except ValueError:
print('Unable to access your boards. Check your key and token.')
return
if not os.path.exists(OUTPUT_DIRECTORY):
os.makedirs(OUTPUT_DIRECTORY)
print('Backing up boards:')
epoch_time = str(int(time.time()))
for board in boards.json():
if ORGANIZATION_IDS and (not board["idOrganization"] or not board["idOrganization"] in ORGANIZATION_IDS):
continue
print(u" - {0} - {1} ({2})".format(board["idOrganization"], board["name"], board["id"]))
boardContents = requests.get(API_URL + "boards/" + board["id"], params=boardPayload)
filename = boardFilename(OUTPUT_DIRECTORY, board, epoch_time)
with io.open(filename, 'w', encoding='utf8') as file:
args = dict( sort_keys=True, indent=4) if PRETTY_PRINT else dict()
data = json.dumps(boardContents.json(), ensure_ascii=False, **args)
file.write(data)
def boardFilename(output_dir, board, epoch_time):
organization_id = sanitize(board["idOrganization"])
boardName = sanitize(board["name"])
formatted = u'{0}-{1}_'.format(organization_id, boardName)
filename = formatted + '.json'
return os.path.join(output_dir, filename)
def sanitize(name):
if name is None:
return "None"
return name.replace("/","-").replace(":","-")
def get_organization_ids(ORGANIZATION_NAMES):
selected_organizations = []
for organization in ORGANIZATION_NAMES.split(','):
selected_organizations.append(organization.strip())
organization_ids = []
# Parameters to get a list of organizations
organizationsPayload = {
'key':API_KEY,
'token':TOKEN,
}
organizations = requests.get(API_URL + "members/my/organizations", params=organizationsPayload)
if len(organizations.json()) <= 0:
print('No organizations found.')
else:
for organization in organizations.json():
if organization["name"] in selected_organizations:
organization_ids.append(organization["id"])
return organization_ids
if __name__ == '__main__':
main()