notion-py icon indicating copy to clipboard operation
notion-py copied to clipboard

Replacing an image

Open danmcmahill opened this issue 5 years ago • 1 comments

I'm trying to use notion-py to keep some images (ImageBlock) up to date in a notion page. My basic use model is:

  1. Create page
  2. Upload images and arrange how I want
  3. Do things that might make the images out of date
  4. Re-run the python script to upload the images

What I'm finding is that I can do the initial upload with no problem. Then when I try to update, the code is able to search through the page and find the image file name (I'm using that as the identifier that lets me figure out which image I want to update). I have verified that the code reports the same image ID when initially creating the ImageBlock and when I try to update. However, when I try to update, the file upload happens (I can see it on the page) but I get an assertion error in the notion-py code. I tried something simple like:

img = page.children.add_new(ImageBlock, caption="my caption", width=800)
img.upload_file("foo.png")
img.upload_file("tmp/foo.png")
img.upload_file("bar.png")

i.e. all within the same session and in this case I see no problems with replacing the image several times.

Here is a simplified version of the uploader with hard coded (but removed for privacy) token_v2, page_url, and it expects foo.png and bar.png to be available in the run directory. I can run this once and the second time (when it finds the existing image) I get the assertions at the bottom of the issue.

#!/usr/bin/env python

from notion.block import ImageBlock
from notion.client import NotionClient
from pathlib import Path

def find_image(page, fname):
    """Finds the ID of the ImageBlock instance corresponding to a given filename"""

    # the "source" attribute with be a big long URL that
    # includes "/filename.png?" in it.  However, certain characters inthe
    # file name will get dropped.  So this section changes things like
    # "myfile:x=0.png" to "myfile_x0.png" to match what the "source" attribute
    # will have in it
    repl_dict = {":" : "",
        "=" : "",
        " " : "_"}
    for tag in repl_dict:
        fname = fname.replace(tag, repl_dict[tag])

    pattern = "/{}?".format(fname)

    for child in page.children:
        if hasattr(child, "children"):
            r = find_image(child, fname)
            if r is not None:
                return r
        if hasattr(child, "source"):
            if child.source and pattern in child.source:
                return child

    return None


token_v2 = "<my token_v2>"

print("Establishing client")
client = NotionClient(token_v2=token_v2)
print("Client = {}".format(client))

print("Getting page")
page_url = "https://www.notion.so/<rest of my page URL>"
page = client.get_block(page_url)
print("page = {}".format(page))

for img_file in ["foo.png", "bar.png"]:
    img = find_image(page, img_file)

    if img is None:
        print("Creating new ImageBlock")
        img = page.children.add_new(ImageBlock, caption=img_file, width=800)
        print("Created img = {}".format(img))
    else:
        print("Found existing img = {}".format(img))

    print("Uploading {}".format(img_file))
    img.upload_file(img_file)
    print("After upload img = {}".format(img))

print("All done!")

Traceback (most recent call last):
  File "/home/dan/notion-uploader.py", line 252, in <module>
    main()
  File "/home/dan/notion-uploader.py", line 243, in main
    img.upload_file(f)
  File "/home/dan/.pyenv/versions/3.6.3/lib/python3.6/site-packages/notion/block.py", line 631, in upload_file
    self.file_id = data["url"][len(S3_URL_PREFIX) :].split("/")[0]
  File "/home/dan/.pyenv/versions/3.6.3/lib/python3.6/site-packages/notion/maps.py", line 46, in fset
    self.set(path, python_to_api(value, **kwargs))
  File "/home/dan/.pyenv/versions/3.6.3/lib/python3.6/site-packages/notion/records.py", line 116, in set
    build_operation(id=self.id, path=path, args=value, table=self._table)
  File "/home/dan/.pyenv/versions/3.6.3/lib/python3.6/site-packages/notion/client.py", line 214, in submit_transaction
    self._store.run_local_operations(operations)
  File "/home/dan/.pyenv/versions/3.6.3/lib/python3.6/site-packages/notion/store.py", line 359, in run_local_operations
    self.run_local_operation(**operation)
  File "/home/dan/.pyenv/versions/3.6.3/lib/python3.6/site-packages/notion/store.py", line 380, in run_local_operation
    assert isinstance(ref, dict)
AssertionError

Related to this, is there a way to store any metadata on an ImageBlock like a hash so I could run the upload with impunity and detect when a local source image actually changed relative to what is on the notion page? I've played around with just having a table at the end of the page but that seems like a bit of a hack.

danmcmahill avatar Aug 31 '20 16:08 danmcmahill

+1, need help.

kaedea avatar May 26 '21 08:05 kaedea