Skip to content

Instantly share code, notes, and snippets.

@bryanhpchiang
Last active June 30, 2023 22:17
Show Gist options
  • Save bryanhpchiang/b31f0e9740809b6aa1ff8ff1ed3e6b68 to your computer and use it in GitHub Desktop.
Save bryanhpchiang/b31f0e9740809b6aa1ff8ff1ed3e6b68 to your computer and use it in GitHub Desktop.

get prompt

this browser extension lets you retrieve text prompts for images on Pinterest.

it's useful for finding inspo -- new art styles, artists, and terms that you might want to use in your own prompts!

made with Arc Boosts and clip interrogator

note: could be extended to handle any image on any website!

installation

  • click the + button on the bottom right of the left sidebar

image

  • click "inject" and then "all websites"
  • paste in the content.js and styles.css files

you're good to go!


the backend may or may not be working (depends if i updated it lolol)

feel free to host your own backend server

  • install fastapi, pillow, requests, clip_interrogator
  • run main.py with uvicorn
  • ngrok http 8000

then replace url = with your ngrok URL in content.js

const sleep = ms => { return new Promise(resolve => setTimeout(resolve, ms)) }
const injectButton = async () => {
// Similiarly, we also need to wait for the page to load in...
await sleep(1000);
console.log("hey");
const {url} = await fetch("https://bhchiang--get-url-get.modal.run/").then(r => r.json());
const URL = `${url}/get_prompt`;
const imageContainer = document.querySelector('[data-test-id=closeup-image]');
const image = imageContainer.querySelectorAll("img")[1];
const imageUrl = image.src;
console.log(imageUrl);
const nameContainer = document.querySelector('[itemprop=name]');
if (!nameContainer) return;
const exists = nameContainer.querySelector(".get-prompt");
console.log(`exists: ${exists}`);
if (!exists) {
const button = document.createElement("button");
button.classList.add("get-prompt");
button.append("Get Prompt");
button.addEventListener("pointerdown", async () => {
console.log("get the prompt here!");
const { prompt } = await fetch(URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({image_url: imageUrl})
}).then(r => r.json());
const description = document.createElement("div");
description.classList.add("desc");
description.append(prompt);
nameContainer.appendChild(description)
});
nameContainer.appendChild(button);
}
}
injectButton();
// The button is demounted once you go in a child, so we have to observe and re-render
const observer = new MutationObserver(injectButton);
observer.observe(document.body, { childList: true, subtree: true });
from pydantic import BaseModel
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from PIL import Image
import requests
from clip_interrogator import Config, Interrogator
import logging
from fastapi import FastAPI, Request, status
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
app = FastAPI()
origins = [
"https://www.pinterest.com",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
exc_str = f'{exc}'.replace('\n', ' ').replace(' ', ' ')
logging.error(f"{request}: {exc_str}")
content = {'status_code': 10422, 'message': exc_str, 'data': None}
return JSONResponse(content=content, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
class Item(BaseModel):
image_url: str
ci = Interrogator(Config(clip_model_name="ViT-L-14/openai"))
@app.post("/get_prompt")
def post(item: Item):
image_url = item.image_url
image = Image.open(requests.get(image_url, stream=True).raw)
prompt = ci.interrogate_fast(image)
print(prompt)
print(image_url)
return {"prompt": prompt}
/* This is injected after a web page loads */
.get-prompt {
background: black;
margin-top: 8px;
padding-left: 16px;
padding-right: 16px;
padding-bottom: 12px;
padding-top: 12px;
font-size: 14px;
font-weight: 600;
border-radius: 8px;
color: white;
border: none;
/* padding: 0; */
/* font: inherit; */
cursor: pointer;
outline: inherit;
}
.desc {
margin-top: 8px;
}
@andupotorac
Copy link

Doesn't seem to work. I did click on + to create a Content Stylesheet and the button does show up. Nothing happens when clicking it though.

@henrycunh
Copy link

sweet modal credits!

@bryanhpchiang
Copy link
Author

bryanhpchiang commented Jan 17, 2023

@andupotorac sorry! i'm not at my computer right now so the backend might not be up

will fix when i'm back

@qualiaenjoyer
Copy link

Hey, this is cool! Would you mind PRing it here?

For this: https://arcboost-marketplace.vercel.app/

@qualiaenjoyer
Copy link

qualiaenjoyer commented Jan 23, 2023

@roger-rangel this is the Arc browser for Mac. I guess you could do it on other browsers as well, but Arc makes it particularly easy.

@bryanhpchiang
Copy link
Author

@roger-rangel can you DM me on twitter? @bryanhpchiang

i can send you an arc invite to skip the waitlist

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