How do i upload a folder containing metadata to pinata using a script in python-brownie?

326 views Asked by At

I've been trying for the past 24 hours but can't find a solution. This is the code:

import os
from pathlib import Path
import requests

PINATA_BASE_URL = "https://api.pinata.cloud/"
endpoint = "pinning/pinFileToIPFS"
# Change this filepath
filepath = "C:/Users/acer/Desktop/Ciao"
filename = os.listdir(filepath)
print(filename)
headers = {
    "pinata_api_key": os.getenv("PINATA_API_KEY"),
    "pinata_secret_api_key": os.getenv("PINATA_API_SECRET"),
}


def main():
    with Path(filepath).open("rb") as fp:
        image_binary = filepath.read()
        print(image_binary)
        response = requests.post(
            PINATA_BASE_URL + endpoint,
            files={"file": (filename, image_binary)},
            headers=headers,
        )
        print(response.json())


if __name__ == "__main__":
    main()

I tried to open the folder where the metadata was stored and than i sent the request with the list of files in the folder. This is the error:

['no.txt', 'yeah.txt']
Traceback (most recent call last):
  File "C:\Users\acer\Desktop\SOLIDITY_PYTHON\nft-bored-ape\scripts\upload_to_pinata.py", line 30, in <module>
    main()
  File "C:\Users\acer\Desktop\SOLIDITY_PYTHON\nft-bored-ape\scripts\upload_to_pinata.py", line 18, in main    
    with Path(filepath).open("rb") as fp:
  File "C:\Users\acer\AppData\Local\Programs\Python\Python310\lib\pathlib.py", line 1119, in open
    return self._accessor.open(self, mode, buffering, encoding, errors,
PermissionError: [Errno 13] Permission denied: 'C:\\Users\\acer\\Desktop\\Ciao'
1

There are 1 answers

0
Tulli On BEST ANSWER

Nevermind... After some research i found the answer to my own question. Here is the code:

# Tulli's script :-)
from brownie import config
import requests, os, typing as tp


PINATA_BASE_URL = "https://api.pinata.cloud/"
endpoint = "pinning/pinFileToIPFS"
# Here you could use os.getenv("VARIABLE_NAME"),
# i used config from my .yaml file. Your choice!
headers = {
    "pinata_api_key": config["pinata"]["api-keys"],
    "pinata_secret_api_key": config["pinata"]["api-private"],
}


def get_all_files(directory: str) -> tp.List[str]:
    """get a list of absolute paths to every file located in the directory"""
    paths: tp.List[str] = []
    for root, dirs, files_ in os.walk(os.path.abspath(directory)):
        for file in files_:
            paths.append(os.path.join(root, file))
    return paths


def upload_folder_to_pinata(filepath):
    all_files: tp.List[str] = get_all_files(filepath)
    # The replace function is a must, 
    # pinata servers doesn't recognize the backslash. 
    # Your filepath is probably different than mine,
    # so in the split function put your "penultimate_file/".
    # Strip the square brackets and the apostrophe,
    # because we don't want it as part of the metadata ipfs name
    files = [
        (
            "file",
            (
                str(file.replace("\\", "/").split("Desktop/")[-1:])
                .strip("[]")
                .strip("'"),
                open(file, "rb"),
            ),
        )
        for file in all_files
    ]
    response: requests.Response = requests.post(
        PINATA_BASE_URL + endpoint,
        files=files,
        headers=headers,
    )
    # If you want to see all the stats then do this: 
    # return/print/do both separately response.json()
    return "ipfs.io/ipfs/" + response.json()["IpfsHash"]


def main():
    upload_folder_to_pinata("Put your full filepath here")


if __name__ == "__main__":
    main()