Skip to content

Instantly share code, notes, and snippets.

@svbergerem
Created June 24, 2020 09:50
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save svbergerem/5914d7f87764901aefddba125af99938 to your computer and use it in GitHub Desktop.
Save svbergerem/5914d7f87764901aefddba125af99938 to your computer and use it in GitHub Desktop.
Nextcloud Deck Export/Import
import requests
urlFrom = 'https://cloud.domainfrom.tld'
authFrom = ('username', 'password')
urlTo = 'https://nextcloud.domainto.tld'
authTo = ('username', 'password')
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)
# get boards list
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')
@CodeShakingSheep
Copy link

please, how to change urlTo = 'https://nextcloud.domainto.tld' authTo = ('username', 'password') to save on a pc Thank you

You have to open the file with a text editor. If you're on Windows you can just right-click --> 'Open with' --> 'Editor'. Alternatively, you can download Notepad++ and then right click --> 'Edit with Notepad++'.

I know that! what I don't know is how to enter the correct information so that the data can be saved on my pc. example: c:\documents\deck

What you want is not possible with this script as it only transfers decks from one Nextcloud instance to another. You can check out this fork. May be it'll work for you. I have never tested myself.

@Jeanoo
Copy link

Jeanoo commented Oct 12, 2023

Thanks!

@MonkeysAreEvil
Copy link

I had trouble transferring large stacks due to the api request being cut off (and thus being invalid json). A quick hack to fix this:

def get_response(url):
    response = requests.get(
            url,
            auth=authFrom,
            headers=headers, stream=True, timeout=30)

    response_content = []

    for chunk in response.iter_content(101024):
        if len(chunk)>10000000:
            response_content.append(chunk)
            response.close()
            break
        else:
            response_content.append(chunk)
            break
    return json.loads(response_content[0])


def getStacks(boardId):
    return get_response(f'{urlFrom}/index.php/apps/deck/api/v1.0/boards/{boardId}/stacks')

@PrintLukas
Copy link

Hey there!
Awesome Script! Thank you so much for your work! Unfortunately I ran into an error:

File "/usr/lib/python3/dist-packages/requests/models.py", line 943, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://mydomain.tld/index.php/apps/deck/api/v1.0/boards
User@server:~/import/nextcloud-deck-export-import$

Thank you in advance!
lukas

@PrintLukas
Copy link

I use a cloudflare tunnel for this domain… Could that be the problem? Is there a way to enter the ipaddr without a certificate?
Lg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment