initial
This commit is contained in:
commit
3907fb840a
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
config.py
|
BIN
__pycache__/config.cpython-312.pyc
Normal file
BIN
__pycache__/config.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/lib.cpython-312.pyc
Normal file
BIN
__pycache__/lib.cpython-312.pyc
Normal file
Binary file not shown.
44
backup.py
Normal file
44
backup.py
Normal file
|
@ -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')
|
55
clone.py
Normal file
55
clone.py
Normal file
|
@ -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')
|
145
lib.py
Normal file
145
lib.py
Normal file
|
@ -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)
|
||||||
|
|
||||||
|
|
6
sample.config.py
Normal file
6
sample.config.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Inhalt von config.py
|
||||||
|
urlFrom = 'https://cloud.domainfrom.tld'
|
||||||
|
authFrom = ('username', 'password')
|
||||||
|
|
||||||
|
urlTo = 'https://nextcloud.domainto.tld'
|
||||||
|
authTo = ('username', 'password')
|
Loading…
Reference in a new issue