- recoded lib
- add sync.py (synchronisize boards)
This commit is contained in:
parent
7bd62d9ec9
commit
271f9b3469
71
README.md
71
README.md
|
@ -1,47 +1,74 @@
|
|||
# Nextcloud Deck importieren/exportieren
|
||||
|
||||
## Installation
|
||||
## Voraussetzung
|
||||
|
||||
1. Download https://github.com/johappel/nextcloud-import-export/archive/refs/heads/main.zip
|
||||
oder auf der Komandozeile git clone https://github.com/johappel/nextcloud-import-export.git
|
||||
[Python](https://www.python.org/downloads/) muss installiert sein. Du kannst diese [Anleitung](https://kinsta.com/de/wissensdatenbank/python-installieren/) nutzen.
|
||||
|
||||
## Optional: Git installieren
|
||||
|
||||
Installiere [Git](https://git-scm.com/book/de/v2/Erste-Schritte-Git-installieren): Das ermöglicht dir, die Skripte aktuell zu halten und dich an der Entwicklung zu beteiligen.
|
||||
|
||||
## Installation der Skripte
|
||||
|
||||
1. [Download](https://github.com/johappel/nextcloud-import-export/archive/refs/heads/main.zip) der Skripte oder mit Git
|
||||
`git clone https://github.com/johappel/nextcloud-import-export.git`
|
||||
2. Gehe in das Verzeichnis nextcloud-import-export (cd nextcloud-import-export)
|
||||
3. Führe auf der Komandozeile aus:`pip install requests`
|
||||
4. Kopiere die Datei "sample.config.py" nach "config.py" und trage dort die Daten zu deinen Nextcloudinstanzen ein
|
||||
3. Führe auf der Kommandozeile aus: `pip install requests`
|
||||
4. Kopiere die Datei "sample.config.py" nach "config.py" und trage dort die Daten zu deinen Nextcloud-Instanzen ein.
|
||||
5. Mit diesem Befehl auf der Kommandozeile holst du die neueste Version:
|
||||
`git pull`
|
||||
|
||||
## Anwendungsfälle
|
||||
|
||||
## Verwendung
|
||||
Um ein bestimmtes Deck auf eine andfere Nextcloud Instanz zu kopieren gibst du auf der Komandozeile an:
|
||||
Um ein bestimmtes Deck auf eine andere Nextcloud-Instanz zu kopieren, gibst du auf der Kommandozeile einen der folgenden Befehle ein:
|
||||
|
||||
```python
|
||||
python clone.py --"Name des Decks"
|
||||
```
|
||||
oder
|
||||
```python
|
||||
python3 clone.py --"Name des Decks"
|
||||
1. Um ein Deck zu kopieren:
|
||||
|
||||
```sh
|
||||
python clone.py --board "Name des Decks"
|
||||
```
|
||||
|
||||
Um alle Decks zu kopieren, gibst du ein:
|
||||
2. Um ein bestehendes Deck auf der Zielinstanz zu löschen und zu ersetzen:
|
||||
|
||||
```python
|
||||
```sh
|
||||
python sync.py --board "Name des Decks" --replace
|
||||
```
|
||||
|
||||
3. Um ein bestehendes Deck auf der Zielinstanz mit den Daten, Karten und Stacks der Originalinstanz synchron zu halten:
|
||||
|
||||
```sh
|
||||
python sync.py --board "Name des Decks"
|
||||
```
|
||||
|
||||
4. Um ein Backup aller Decks mit Datum des Backups im Titel auf der Zielinstanz zu sichern:
|
||||
|
||||
```sh
|
||||
python backup.py
|
||||
```
|
||||
|
||||
|
||||
Dank der großartigen Arbeit von @svbergerem:
|
||||
https://gist.github.com/svbergerem/5914d7f87764901aefddba125af99938
|
||||
|
||||
### Funktionen des Skripts
|
||||
|
||||
1. **Daten von der Quellinstanz abrufen:**
|
||||
- `getBoards()`: Ruft die Liste aller Boards ab.
|
||||
- `getBoardDetails(boardId)`: Ruft Details eines spezifischen Boards ab.
|
||||
- `getStacks(boardId)`: Ruft die Stacks eines Boards ab.
|
||||
- `getStacksArchived(boardId)`: Ruft die archivierten Stacks eines Boards ab.
|
||||
Gib bei den folgenden Funktionen als Parameter 'from' oder 'to' ein, je nachdem, ob du die Daten von der Quellinstanz oder der Zielinstanz abfragst:
|
||||
- `getBoards(from_or_to)`: Ruft die Liste aller Boards ab.
|
||||
- `getBoardDetails(boardId, from_or_to)`: Ruft Details eines spezifischen Boards ab.
|
||||
- `getStacks(boardId, from_or_to)`: Ruft die Stacks eines Boards ab.
|
||||
- `getStacksArchived(boardId, from_or_to)`: Ruft die archivierten Stacks eines Boards ab.
|
||||
2. **Daten zur Zielinstanz übertragen:**
|
||||
- `createBoard(title, color)`: Erstellt ein Board.
|
||||
- `createLabel(title, color, boardId)`: Erstellt ein Label in einem Board.
|
||||
- `createStack(title, order, boardId)`: Erstellt einen Stack in einem Board.
|
||||
- `createCard(title, ctype, order, description, duedate, boardId, stackId)`: Erstellt eine Karte in einem Stack.
|
||||
- `assignLabel(labelId, cardId, boardId, stackId)`: Weist ein Label einer Karte zu.
|
||||
- `assignLabel(labelId, cardId, boardId, stackId)`: Weist einer Karte ein Label zu.
|
||||
- `archiveCard(card, boardId, stackId)`: Archiviert eine Karte.
|
||||
- `copyCard(card, boardIdTo, stackIdTo, labelsMap)`: Kopiert eine Karte, einschließlich ihrer Labels und archiviertem Status.
|
||||
- `copyCard(card, boardIdTo, stackIdTo, labelsMap)`: Kopiert eine Karte, einschließlich ihrer Labels und des archivierten Status.
|
||||
- `deleteBoard(boardIdTo)`: Löscht ein Board.
|
||||
- `deleteStacks(boardIdTo)`: Löscht alle Listen eines Boards.
|
||||
- `deleteLabels(boardIdTo)`: Löscht alle Karten eines Boards.
|
||||
|
||||
# @todo:
|
||||
- Synchronisation verbessern (nur dezidierte Karten ersetzen)
|
||||
- Grafisches User Interface
|
||||
|
|
Binary file not shown.
12
backup.py
12
backup.py
|
@ -1,4 +1,10 @@
|
|||
from .lib import *
|
||||
from datetime import datetime
|
||||
from lib import *
|
||||
|
||||
# datetime object containing current date and time
|
||||
now = datetime.now()
|
||||
# dd/mm/YY H:M:S
|
||||
dt_string = now.strftime("_%Y-%m-%d-%H-%M-%S")
|
||||
|
||||
boards = getBoards()
|
||||
|
||||
|
@ -6,9 +12,9 @@ boards = getBoards()
|
|||
for board in boards:
|
||||
boardIdFrom = board['id']
|
||||
# create board
|
||||
createdBoard = createBoard(board['title'], board['color'])
|
||||
createdBoard = createBoard(board['title']+dt_string, board['color'])
|
||||
boardIdTo = createdBoard['id']
|
||||
print('Created board', board['title'])
|
||||
print('Created board', board['title'], dt_string)
|
||||
|
||||
# create labels
|
||||
boardDetails = getBoardDetails(board['id'])
|
||||
|
|
26
clone.py
26
clone.py
|
@ -4,22 +4,36 @@ import lib
|
|||
# Argumente von der Kommandozeile einlesen
|
||||
parser = argparse.ArgumentParser(description='Klonen eines bestimmten Boards von einer Nextcloud-Instanz zu einer anderen.')
|
||||
parser.add_argument('--board', type=str, required=True, help='Der Titel des zu klonenden Boards.')
|
||||
parser.add_argument('--replace', action='store_true', help='Ersetze das Board im Ziel, falls es bereits existiert.')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Board-Titel, den wir klonen möchten
|
||||
board_to_clone = args.board
|
||||
|
||||
# Hole alle Boards von der Quellinstanz
|
||||
boards = lib.getBoards()
|
||||
boards_from = lib.getBoards()
|
||||
|
||||
# Finde das gewünschte Board
|
||||
board_to_clone_data = next((board for board in boards if board['title'] == board_to_clone), None)
|
||||
board_to_clone_data = next((board for board in boards_from if board['title'] == board_to_clone), None)
|
||||
|
||||
if not board_to_clone_data:
|
||||
print(f'Board "{board_to_clone}" nicht gefunden.')
|
||||
else:
|
||||
boardIdFrom = board_to_clone_data['id']
|
||||
# Erstelle das Board in der Zielinstanz
|
||||
|
||||
# Überprüfe, ob das Board im Ziel bereits existiert
|
||||
boards_to = lib.getBoards('to')
|
||||
existing_board_to = next((board for board in boards_to if board['title'] == board_to_clone and 0 == board['deletedAt']), None)
|
||||
|
||||
# Löschen wenn der parameter --replace gesetzt wurde und das Board existiert
|
||||
if args.replace and existing_board_to:
|
||||
# Lösche das bestehende Board im Ziel
|
||||
print(f'Lösche Board: {existing_board_to["id"]}')
|
||||
lib.deleteBoard(existing_board_to['id'])
|
||||
print(f'Board "{board_to_clone}" im Ziel gelöscht')
|
||||
|
||||
# Erstelle das Board in der Zielinstanz, wenn es nicht existiert oder ersetzt werden soll
|
||||
if not existing_board_to or args.replace:
|
||||
createdBoard = lib.createBoard(board_to_clone_data['title'], board_to_clone_data['color'])
|
||||
boardIdTo = createdBoard['id']
|
||||
print(f'Board "{board_to_clone}" erstellt')
|
||||
|
@ -38,7 +52,7 @@ else:
|
|||
createdStack = lib.createStack(stack['title'], stack['order'], boardIdTo)
|
||||
stackIdTo = createdStack['id']
|
||||
stacksMap[stack['id']] = stackIdTo
|
||||
print(f' Stapel "{stack['title']}" erstellt')
|
||||
print(f' Stapel "{stack["title"]}" erstellt')
|
||||
|
||||
if 'cards' in stack:
|
||||
for card in stack['cards']:
|
||||
|
@ -49,7 +63,9 @@ else:
|
|||
stacks = lib.getStacksArchived(boardIdFrom)
|
||||
for stack in stacks:
|
||||
if 'cards' in stack:
|
||||
print(f' Stack "{stack['title']}"')
|
||||
print(f' Stack "{stack["title"]}"')
|
||||
for card in stack['cards']:
|
||||
lib.copyCard(card, boardIdTo, stacksMap[stack['id']], labelsMap)
|
||||
print(f' {len(stack["cards"])} archivierte Karten erstellt')
|
||||
else:
|
||||
print(f'Board "{board_to_clone}" existiert bereits und wird nicht ersetzt (verwenden Sie --replace, um zu ersetzen).')
|
||||
|
|
140
lib.py
140
lib.py
|
@ -1,9 +1,6 @@
|
|||
# thanks to the awesome work of @svbergerem
|
||||
# -> svbergerem/nextcloud-deck-export-import.py
|
||||
# https://gist.github.com/svbergerem/5914d7f87764901aefddba125af99938
|
||||
|
||||
import requests
|
||||
import config
|
||||
import base64
|
||||
|
||||
urlFrom = config.urlFrom
|
||||
authFrom = config.authFrom
|
||||
|
@ -11,123 +8,66 @@ authFrom = config.authFrom
|
|||
urlTo = config.urlTo
|
||||
authTo = config.authTo
|
||||
|
||||
|
||||
headers = {'OCS-APIRequest': 'true', 'Content-Type': 'application/json'}
|
||||
|
||||
def getBoards():
|
||||
response = requests.get(
|
||||
f'{urlFrom}/index.php/apps/deck/api/v1.0/boards',
|
||||
auth=authFrom,
|
||||
headers=headers)
|
||||
def make_request(method, endpoint, from_to='from', json=None):
|
||||
if from_to == 'from':
|
||||
url = urlFrom
|
||||
auth = authFrom
|
||||
else: # from_to == 'to'
|
||||
url = urlTo
|
||||
auth = authTo
|
||||
|
||||
response = requests.request(method, f'{url}{endpoint}', auth=auth, headers=headers, json=json)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
def getBoardDetails(boardId):
|
||||
response = requests.get(
|
||||
f'{urlFrom}/index.php/apps/deck/api/v1.0/boards/{boardId}',
|
||||
auth=authFrom,
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
def getBoards(from_to='from'):
|
||||
boards = make_request('GET', '/index.php/apps/deck/api/v1.0/boards', from_to)
|
||||
return [board for board in boards if 0 == board['deletedAt']]
|
||||
|
||||
def getStacks(boardId):
|
||||
response = requests.get(
|
||||
f'{urlFrom}/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks',
|
||||
auth=authFrom,
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
def getBoardDetails(boardId, from_to='from'):
|
||||
return make_request('GET', f'/index.php/apps/deck/api/v1.0/boards/{boardId}', from_to)
|
||||
|
||||
def getStacksArchived(boardId):
|
||||
response = requests.get(
|
||||
f'{urlFrom}/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/archived',
|
||||
auth=authFrom,
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
def getStacks(boardId, from_to='from'):
|
||||
return make_request('GET', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks', from_to)
|
||||
|
||||
def getStacksArchived(boardId, from_to='from'):
|
||||
return make_request('GET', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/archived', from_to)
|
||||
|
||||
def createBoard(title, color):
|
||||
response = requests.post(
|
||||
f'{urlTo}/index.php/apps/deck/api/v1.0/boards',
|
||||
auth=authTo,
|
||||
json={
|
||||
'title': title,
|
||||
'color': color
|
||||
},
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
board = response.json()
|
||||
board = make_request('POST', '/index.php/apps/deck/api/v1.0/boards', 'to', json={'title': title, 'color': color})
|
||||
boardId = board['id']
|
||||
# remove all default labels
|
||||
for label in board['labels']:
|
||||
labelId = label['id']
|
||||
response = requests.delete(
|
||||
f'{urlTo}/index.php/apps/deck/api/v1.0/boards/{boardId}/labels/{labelId}',
|
||||
auth=authTo,
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
make_request('DELETE', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/labels/{labelId}', 'to')
|
||||
return board
|
||||
|
||||
def createLabel(title, color, boardId):
|
||||
response = requests.post(
|
||||
f'{urlTo}/index.php/apps/deck/api/v1.0/boards/{boardId}/labels',
|
||||
auth=authTo,
|
||||
json={
|
||||
'title': title,
|
||||
'color': color
|
||||
},
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
return make_request('POST', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/labels', 'to', json={'title': title, 'color': color})
|
||||
|
||||
def createStack(title, order, boardId):
|
||||
response = requests.post(
|
||||
f'{urlTo}/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks',
|
||||
auth=authTo,
|
||||
json={
|
||||
'title': title,
|
||||
'order': order
|
||||
},
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
return make_request('POST', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks', 'to', json={'title': title, 'order': order})
|
||||
|
||||
def createCard(title, ctype, order, description, duedate, boardId, stackId):
|
||||
response = requests.post(
|
||||
f'{urlTo}/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/{stackId}/cards',
|
||||
auth=authTo,
|
||||
json={
|
||||
'title': title,
|
||||
'type': ctype,
|
||||
'order': order,
|
||||
'description': description,
|
||||
'duedate': duedate
|
||||
},
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
try:
|
||||
return make_request('POST', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/{stackId}/cards', 'to',
|
||||
json={'title': title, 'type': ctype, 'order': order, 'description': description, 'duedate': duedate})
|
||||
except requests.exceptions.HTTPError as e:
|
||||
print(f"Error creating card: {e}")
|
||||
print(f"Response: {e.response.text}")
|
||||
raise
|
||||
|
||||
def assignLabel(labelId, cardId, boardId, stackId):
|
||||
response = requests.put(
|
||||
f'{urlTo}/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/assignLabel',
|
||||
auth=authTo,
|
||||
json={
|
||||
'labelId': labelId
|
||||
},
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
make_request('PUT', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/assignLabel', 'to', json={'labelId': labelId})
|
||||
|
||||
def archiveCard(card, boardId, stackId):
|
||||
cardId = card['id']
|
||||
card['archived'] = True
|
||||
response = requests.put(
|
||||
f'{urlTo}/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}',
|
||||
auth=authTo,
|
||||
json=card,
|
||||
headers=headers)
|
||||
response.raise_for_status()
|
||||
make_request('PUT', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{card["id"]}', 'to', json=card)
|
||||
|
||||
def copyCard(card, boardIdTo, stackIdTo, labelsMap):
|
||||
print(f"Copying card '{card['title']}' to board {boardIdTo}, stack {stackIdTo}")
|
||||
createdCard = createCard(
|
||||
card['title'],
|
||||
card['type'],
|
||||
|
@ -146,4 +86,16 @@ def copyCard(card, boardIdTo, stackIdTo, labelsMap):
|
|||
if card['archived']:
|
||||
archiveCard(createdCard, boardIdTo, stackIdTo)
|
||||
|
||||
# Löschfunktionen auf der Zielinstanz
|
||||
def deleteBoard(boardId):
|
||||
make_request('DELETE', f'/index.php/apps/deck/api/v1.0/boards/{boardId}', 'to')
|
||||
|
||||
def deleteStacks(boardId):
|
||||
stacks = getStacks(boardId, 'to')
|
||||
for stack in stacks:
|
||||
make_request('DELETE', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/{stack["id"]}', 'to')
|
||||
|
||||
def deleteLabels(boardId):
|
||||
boardDetails = getBoardDetails(boardId, 'to')
|
||||
for label in boardDetails['labels']:
|
||||
make_request('DELETE', f'/index.php/apps/deck/api/v1.0/boards/{boardId}/labels/{label["id"]}', 'to')
|
||||
|
|
107
sync.py
Normal file
107
sync.py
Normal file
|
@ -0,0 +1,107 @@
|
|||
import argparse
|
||||
import requests
|
||||
import lib
|
||||
|
||||
# Argumente von der Kommandozeile einlesen
|
||||
parser = argparse.ArgumentParser(description='Clone or sync a specific board from one Nextcloud instance to another.')
|
||||
parser.add_argument('--board', type=str, required=True, help='The title of the board to clone or sync.')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Board-Titel, den wir klonen oder synchronisieren möchten
|
||||
board_to_clone = args.board
|
||||
|
||||
# Hole alle Boards von der Quellinstanz
|
||||
source_boards = lib.getBoards()
|
||||
|
||||
# Finde das gewünschte Board in der Quellinstanz
|
||||
board_to_clone_data = next((board for board in source_boards if board['title'] == board_to_clone), None)
|
||||
|
||||
if not board_to_clone_data:
|
||||
print(f'Board "{board_to_clone}" nicht gefunden.')
|
||||
exit()
|
||||
|
||||
boardIdFrom = board_to_clone_data['id']
|
||||
|
||||
# Hole alle Boards von der Zielinstanz
|
||||
target_boards = lib.getBoards('to')
|
||||
|
||||
# Überprüfen, ob das Board in der Zielinstanz existiert
|
||||
target_board_data = next((board for board in target_boards if board['title'] == board_to_clone), None)
|
||||
|
||||
if target_board_data:
|
||||
boardIdTo = target_board_data['id']
|
||||
print(f'Board "{board_to_clone}" already exists. Syncing...')
|
||||
else:
|
||||
# Erstelle das Board in der Zielinstanz
|
||||
createdBoard = lib.createBoard(board_to_clone_data['title'], board_to_clone_data['color'])
|
||||
boardIdTo = createdBoard['id']
|
||||
print(f'Created board "{board_to_clone}"')
|
||||
|
||||
# Kopiere oder synchronisiere die Labels des Boards
|
||||
boardDetails = lib.getBoardDetails(boardIdFrom)
|
||||
labelsMap = {}
|
||||
target_board_details = lib.getBoardDetails(boardIdTo,'to')
|
||||
|
||||
# Existierende Labels in der Zielinstanz sammeln
|
||||
existing_labels = {label['title']: label['id'] for label in target_board_details['labels']}
|
||||
|
||||
for label in boardDetails['labels']:
|
||||
if label['title'] in existing_labels:
|
||||
labelsMap[label['id']] = existing_labels[label['title']]
|
||||
else:
|
||||
createdLabel = lib.createLabel(label['title'], label['color'], boardIdTo)
|
||||
labelsMap[label['id']] = createdLabel['id']
|
||||
|
||||
# Kopiere oder synchronisiere die Stacks und Karten des Boards
|
||||
stacks = lib.getStacks(boardIdFrom)
|
||||
target_stacks = lib.getStacks(boardIdTo,'to')
|
||||
stacksMap = {}
|
||||
|
||||
# Existierende Stacks in der Zielinstanz sammeln
|
||||
existing_stacks = {stack['title']: stack['id'] for stack in target_stacks}
|
||||
|
||||
for stack in stacks:
|
||||
if stack['title'] in existing_stacks:
|
||||
stackIdTo = existing_stacks[stack['title']]
|
||||
stacksMap[stack['id']] = stackIdTo
|
||||
print(f' Stack "{stack["title"]}" already exists. Syncing...')
|
||||
else:
|
||||
createdStack = lib.createStack(stack['title'], stack['order'], boardIdTo)
|
||||
stackIdTo = createdStack['id']
|
||||
stacksMap[stack['id']] = stackIdTo
|
||||
print(f' Created stack "{stack["title"]}"')
|
||||
|
||||
if 'cards' in stack:
|
||||
for card in stack['cards']:
|
||||
try:
|
||||
lib.copyCard(card, boardIdTo, stackIdTo, labelsMap)
|
||||
except requests.exceptions.HTTPError as e:
|
||||
print(f' Failed to create card "{card["title"]}". Error: {e}')
|
||||
print(f' Response: {e.response.text}')
|
||||
print(f' Created {len(stack["cards"])} cards')
|
||||
|
||||
# Kopiere oder synchronisiere die archivierten Stacks und Karten des Boards
|
||||
archived_stacks = lib.getStacksArchived(boardIdFrom)
|
||||
target_archived_stacks = lib.getStacksArchived(boardIdTo,'to')
|
||||
|
||||
# Existierende archivierte Stacks in der Zielinstanz sammeln
|
||||
existing_archived_stacks = {stack['title']: stack['id'] for stack in target_archived_stacks}
|
||||
|
||||
for stack in archived_stacks:
|
||||
if stack['title'] in existing_archived_stacks:
|
||||
stackIdTo = existing_archived_stacks[stack['title']]
|
||||
print(f' Archived stack "{stack['title']}" already exists. Syncing...')
|
||||
else:
|
||||
createdStack = lib.createStack(stack['title'], stack['order'], boardIdTo)
|
||||
stackIdTo = createdStack['id']
|
||||
stacksMap[stack['id']] = stackIdTo
|
||||
print(f' Created archived stack "{stack['title']}"')
|
||||
|
||||
if 'cards' in stack:
|
||||
for card in stack['cards']:
|
||||
try:
|
||||
lib.copyCard(card, boardIdTo, stackIdTo, labelsMap)
|
||||
except requests.exceptions.HTTPError as e:
|
||||
print(f' Failed to create archived card "{card["title"]}". Error: {e}')
|
||||
print(f' Response: {e.response.text}')
|
||||
print(f' Created {len(stack["cards"])} archived cards')
|
Loading…
Reference in a new issue