commit 3907fb840ac7c6a5c923d0c8f134da13a2b8c878 Author: Joachim Happel Date: Mon May 27 16:51:26 2024 +0200 initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4acd06b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.py diff --git a/__pycache__/config.cpython-312.pyc b/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000..18dd579 Binary files /dev/null and b/__pycache__/config.cpython-312.pyc differ diff --git a/__pycache__/lib.cpython-312.pyc b/__pycache__/lib.cpython-312.pyc new file mode 100644 index 0000000..b8dda97 Binary files /dev/null and b/__pycache__/lib.cpython-312.pyc differ diff --git a/backup.py b/backup.py new file mode 100644 index 0000000..634d900 --- /dev/null +++ b/backup.py @@ -0,0 +1,44 @@ +from .lib import * + +boards = getBoards() + +# create boards +for board in boards: + boardIdFrom = board['id'] + # create board + createdBoard = createBoard(board['title'], board['color']) + boardIdTo = createdBoard['id'] + print('Created board', board['title']) + + # create labels + boardDetails = getBoardDetails(board['id']) + labelsMap = {} + for label in boardDetails['labels']: + createdLabel = createLabel(label['title'], label['color'], boardIdTo) + labelsMap[label['id']] = createdLabel['id'] + + # copy stacks + stacks = getStacks(boardIdFrom) + stacksMap = {} + for stack in stacks: + createdStack = createStack(stack['title'], stack['order'], boardIdTo) + stackIdTo = createdStack['id'] + stacksMap[stack['id']] = stackIdTo + print(' Created stack', stack['title']) + # copy cards + if not 'cards' in stack: + continue + for card in stack['cards']: + copyCard(card, boardIdTo, stackIdTo, labelsMap) + print(' Created', len(stack['cards']), 'cards') + + # copy archived stacks + stacks = getStacksArchived(boardIdFrom) + for stack in stacks: + # copy cards + if not 'cards' in stack: + continue + print(' Stack', stack['title']) + for card in stack['cards']: + copyCard(card, boardIdTo, stacksMap[stack['id']], labelsMap) + print(' Created', len(stack['cards']), 'archived cards') \ No newline at end of file diff --git a/clone.py b/clone.py new file mode 100644 index 0000000..6bb7feb --- /dev/null +++ b/clone.py @@ -0,0 +1,55 @@ +import argparse +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.') +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() + +# Finde das gewünschte Board +board_to_clone_data = next((board for board in boards 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 + createdBoard = lib.createBoard(board_to_clone_data['title'], board_to_clone_data['color']) + boardIdTo = createdBoard['id'] + print(f'Board "{board_to_clone}" erstellt') + + # Kopiere die Labels des Boards + boardDetails = lib.getBoardDetails(boardIdFrom) + labelsMap = {} + for label in boardDetails['labels']: + createdLabel = lib.createLabel(label['title'], label['color'], boardIdTo) + labelsMap[label['id']] = createdLabel['id'] + + # Kopiere die Stacks und Karten des Boards + stacks = lib.getStacks(boardIdFrom) + stacksMap = {} + for stack in stacks: + createdStack = lib.createStack(stack['title'], stack['order'], boardIdTo) + stackIdTo = createdStack['id'] + stacksMap[stack['id']] = stackIdTo + print(f' Stapel "{stack['title']}" erstellt') + + if 'cards' in stack: + for card in stack['cards']: + lib.copyCard(card, boardIdTo, stackIdTo, labelsMap) + print(f' {len(stack["cards"])} Karten erstellt') + + # Kopiere die archivierten Stacks und Karten des Boards + stacks = lib.getStacksArchived(boardIdFrom) + for stack in stacks: + if 'cards' in stack: + 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') diff --git a/lib.py b/lib.py new file mode 100644 index 0000000..c1b01e0 --- /dev/null +++ b/lib.py @@ -0,0 +1,145 @@ +import requests +import config + +urlFrom = config.urlFrom +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) + 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 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 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 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() + 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() + 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() + +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() + +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() + +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() + +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() + +def copyCard(card, boardIdTo, stackIdTo, labelsMap): + createdCard = createCard( + card['title'], + card['type'], + card['order'], + card['description'], + card['duedate'], + boardIdTo, + stackIdTo + ) + + # copy card labels + if card['labels']: + for label in card['labels']: + assignLabel(labelsMap[label['id']], createdCard['id'], boardIdTo, stackIdTo) + + if card['archived']: + archiveCard(createdCard, boardIdTo, stackIdTo) + + diff --git a/sample.config.py b/sample.config.py new file mode 100644 index 0000000..56e250a --- /dev/null +++ b/sample.config.py @@ -0,0 +1,6 @@ +# Inhalt von config.py +urlFrom = 'https://cloud.domainfrom.tld' +authFrom = ('username', 'password') + +urlTo = 'https://nextcloud.domainto.tld' +authTo = ('username', 'password')