import requests
import json
import base64
import io
import os
from PIL import Image
import gradio as gr
import uuid
# import tqdm
# import time
theme = gr.themes.Soft().set(
body_background_fill='*primary_50',
# block_border_width='*block_label_border_width',
# block_border_width_dark='*checkbox_border_width',
button_secondary_background_fill='*primary_500',
# button_secondary_background_fill_dark='*primary_700',
button_secondary_background_fill_hover='*primary_400',
button_secondary_border_color='*primary_50',
# button_secondary_border_color_dark='*primary_700',
button_secondary_text_color='*button_primary_text_color'
)
init_html = '''
'''
js_payment = """
function pay() {
const buttonContainer = document.getElementById("buttonContainer");
const payButton = document.getElementById("payButton");
// Set the href attribute
payButton.href = "https://piczify.lemonsqueezy.com/checkout/custom/283c32f2-7635-4809-af0a-6adf8f853cda?signature=4b486a404cf7d5751e7fc8b38f15a63bef909028ccbfc1a97b5efb4121c1f9fd";
payButton.textContent = "Click here to Pay 9.99$";
// Apply button styles
payButton.style.display = "inline-block";
payButton.style.padding = "10px 20px";
payButton.style.backgroundColor = "#007bff";
payButton.style.color = "#fff";
payButton.style.textDecoration = "none";
payButton.style.border = "none";
payButton.style.borderRadius = "5px";
payButton.style.cursor = "pointer";
payButton.style.fontSize = "16px";
// Add the button to the container
buttonContainer.appendChild(payButton);
}
"""
scripts = """
function game() {
var parentX = document.querySelector(".sliding-puzzle").clientHeight;
var baseDistance = 34.5;
var tileMap = {
1: {
tileNumber: 1,
position: 1,
top: 0,
left: 0
},
2: {
tileNumber: 2,
position: 2,
top: 0,
left: baseDistance * 1
},
3: {
tileNumber: 3,
position: 3,
top: 0,
left: baseDistance * 2
},
4: {
tileNumber: 4,
position: 4,
top: baseDistance,
left: 0
},
5: {
tileNumber: 5,
position: 5,
top: baseDistance,
left: baseDistance
},
6: {
tileNumber: 6,
position: 6,
top: baseDistance,
left: baseDistance * 2
},
7: {
tileNumber: 7,
position: 7,
top: baseDistance * 2,
left: 0
},
8: {
tileNumber: 8,
position: 8,
top: baseDistance * 2,
left: baseDistance
},
empty: {
position: 9,
top: baseDistance * 2,
left: baseDistance * 2
}
}
var history = [];
function movementMap(position) {
if (position == 9) return [6, 8];
if (position == 8) return [5, 7, 9];
if (position == 7) return [4, 8];
if (position == 6) return [3, 5, 9];
if (position == 5) return [2, 4, 6, 8];
if (position == 4) return [1, 5, 7];
if (position == 3) return [2, 6];
if (position == 2) return [1, 3, 5];
if (position == 1) return [2, 4];
}
document.querySelector('#shuffle').addEventListener('click', shuffle , true);
document.querySelector('#solve').addEventListener('click', solve , true);
var tiles = document.querySelectorAll('.tile');
var delay = -50;
for(var i = 0; i < tiles.length; i++) {
tiles[i].addEventListener('click', tileClicked ,true );
var tileId = tiles[i].innerHTML;
delay += 50;
setTimeout(setup, delay, tiles[i]);
}
function setup(tile) {
var tileId = tile.innerHTML;
var xMovement = parentX * (tileMap[tileId].left/100);
var yMovement = parentX * (tileMap[tileId].top/100);
var translateString = "translateX(" + xMovement + "px) " + "translateY(" + yMovement + "px)"
tile.style.webkitTransform = translateString;
recolorTile(tile, tileId);
}
function tileClicked(event) {
var tileNumber = event.target.innerHTML;
moveTile(event.target);
if (checkSolution()) {
console.log("You win!");
}
}
function moveTile(tile, recordHistory = true) {
var tileNumber = tile.innerHTML;
if (!tileMovable(tileNumber)) {
console.log("Tile " + tileNumber + " can't be moved.");
return;
}
if (recordHistory == true) {
if (history.length >= 3) {
if (history[history.length-1] != history[history.length-3]) history.push(tileNumber);
} else {
history.push(tileNumber);
}
}
var emptyTop = tileMap.empty.top;
var emptyLeft = tileMap.empty.left;
var emptyPosition = tileMap.empty.position;
tileMap.empty.top = tileMap[tileNumber].top;
tileMap.empty.left = tileMap[tileNumber].left;
tileMap.empty.position = tileMap[tileNumber].position;
var xMovement = parentX * (emptyLeft/100);
var yMovement = parentX * (emptyTop/100);
var translateString = "translateX(" + xMovement + "px) " + "translateY(" + yMovement + "px)"
tile.style.webkitTransform = translateString;
tileMap[tileNumber].top = emptyTop;
tileMap[tileNumber].left = emptyLeft;
tileMap[tileNumber].position = emptyPosition;
recolorTile(tile, tileNumber);
}
function tileMovable(tileNumber) {
var selectedTile = tileMap[tileNumber];
var emptyTile = tileMap.empty;
var movableTiles = movementMap(emptyTile.position);
if (movableTiles.includes(selectedTile.position)) {
return true;
} else {
return false;
}
}
function checkSolution() {
if (tileMap.empty.position !== 9) return false;
for (var key in tileMap) {
if ((key != 1) && (key != "empty")) {
if (tileMap[key].position < tileMap[key-1].position) return false;
}
}
history = [];
return true;
}
function recolorTile(tile, tileId) {
if (tileId == tileMap[tileId].position) {
tile.classList.remove("error");
} else {
tile.classList.add("error");
}
}
shuffleTimeouts = [];
function shuffle() {
clearTimers(solveTimeouts);
var boardTiles = document.querySelectorAll('.tile');
var shuffleDelay = 200;
shuffleLoop();
var shuffleCounter = 0;
while (shuffleCounter < 20) {
shuffleDelay += 200;
shuffleTimeouts.push(setTimeout(shuffleLoop, shuffleDelay));
shuffleCounter++;
}
}
var lastShuffled;
function shuffleLoop() {
var emptyPosition = tileMap.empty.position;
var shuffleTiles = movementMap(emptyPosition);
var tilePosition = shuffleTiles[Math.floor(Math.floor(Math.random()*shuffleTiles.length))];
var locatedTile;
for(var i = 1; i <= 8; i++) {
if (tileMap[i].position == tilePosition) {
var locatedTileNumber = tileMap[i].tileNumber;
locatedTile = tiles[locatedTileNumber-1];
}
}
if (lastShuffled != locatedTileNumber) {
moveTile(locatedTile);
lastShuffled = locatedTileNumber;
} else {
shuffleLoop();
}
}
function clearTimers(timeoutArray) {
for (var i = 0; i < timeoutArray.length; i++) {
clearTimeout(timeoutArray[i])
}
}
solveTimeouts = []
function solve() {
clearTimers(shuffleTimeouts);
repeater = history.length;
for (var i = 0; i < repeater; i++) {
console.log("started");
solveTimeouts.push(setTimeout(moveTile, i*100, tiles[history.pop()-1], false));
}
}
}
"""
git_html_start = f"""
PicZify | Sliding Puzzle
PicZify Puzzle | Shuffle | Solve
"""
# GitHub repository details
username = 'ovi054'
repository = 'puzzle'
access_token = os.getenv("GIT_TOKEN")
# Function to upload a file to GitHub repository
def upload_file(file_path, content):
url = f'https://api.github.com/repos/{username}/{repository}/contents/{file_path}'
headers = {'Authorization': f'token {access_token}'}
data = {
'message': f'Upload {file_path}',
'content': content,
'branch': 'main'
}
response = requests.put(url, headers=headers, json=data)
return response
def perform_operations(image, email_id):
# Get the contents of the 'avipal' folder
# print(target_folder)
# if(target_folder=="" or target_folder==None):
uuid_code = str(uuid.uuid4())
split_rows = 3
split_cols = 3
#Split the input image into sub-images and update the '1.png' to '9.png' in the 'avipal3/css' folder
sub_image_list = []
input_image = Image.fromarray(image)
image_width, image_height = input_image.size
sub_image_width = image_width // split_cols
sub_image_height = image_height // split_rows
for row in range(split_rows):
for col in range(split_cols):
left = col * sub_image_width
upper = row * sub_image_height
right = left + sub_image_width
lower = upper + sub_image_height
sub_image = input_image.crop((left, upper, right, lower))
# Encode the sub-image as base64 string
sub_image_byte_array = io.BytesIO()
sub_image.save(sub_image_byte_array, format='PNG')
sub_image_base64 = base64.b64encode(sub_image_byte_array.getvalue()).decode('utf-8')
sub_image_list.append(sub_image_base64)
# Upload the sub-image to the 'avipal3/css' folder with the desired filename
#filename = f'{row * split_cols + col + 1}.png'
#target_file_path = f'{target_folder}/{css_folder}/{filename}'
#upload_file(target_file_path, sub_image_base64)
git_html = f"""{git_html_start}
.sliding-puzzle-figure .sliding-puzzle .tile#ans1 {{
background-image: url(data:image/png;base64,{sub_image_list[0]});
background-repeat: no-repeat;
background-size: cover;
background-position: center; }}
.sliding-puzzle-figure .sliding-puzzle .tile#ans2 {{
background-image: url(data:image/png;base64,{sub_image_list[1]});
background-repeat: no-repeat;
background-size: cover;
background-position: center;}}
.sliding-puzzle-figure .sliding-puzzle .tile#ans3 {{
background-image: url(data:image/png;base64,{sub_image_list[2]});
background-repeat: no-repeat;
background-size: cover;
background-position: center;}}
.sliding-puzzle-figure .sliding-puzzle .tile#ans4 {{
background-image: url(data:image/png;base64,{sub_image_list[3]});
background-repeat: no-repeat;
background-size: cover;
background-position: center;}}
.sliding-puzzle-figure .sliding-puzzle .tile#ans5 {{
background-image: url(data:image/png;base64,{sub_image_list[4]});
background-repeat: no-repeat;
background-size: cover;
background-position: center;}}
.sliding-puzzle-figure .sliding-puzzle .tile#ans6 {{
background-image: url(data:image/png;base64,{sub_image_list[5]});
background-repeat: no-repeat;
background-size: cover;
background-position: center;}}
.sliding-puzzle-figure .sliding-puzzle .tile#ans7 {{
background-image: url(data:image/png;base64,{sub_image_list[6]});
background-repeat: no-repeat;
background-size: cover;
background-position: center;}}
.sliding-puzzle-figure .sliding-puzzle .tile#ans8 {{
background-image: url(data:image/png;base64,{sub_image_list[7]});
background-repeat: no-repeat;
background-size: cover;
background-position: center;}}
{git_html_end}
"""
file_path = f'{uuid_code}/index.html'
upload_file(file_path,base64.b64encode(git_html.encode('utf-8')).decode('utf-8'))
base_url = "https://piczify.com/"
target_folder_url = base_url + uuid_code
return target_folder_url,sub_image_list
with gr.Blocks(theme=theme) as demo:
# start_btn = gr.Button(value="Preview?")
# start_html = gr.HTML(start)
# demo.load(None,None,None,_js=scripts)
image = gr.Image(label="Upload a square shaped image"
,shape=(600,600)
# ,height=500,width=500
,tool='select')
email = gr.Textbox(label="Email address")
btn = gr.Button(value="Submit")
test_html = gr.HTML()
start_html = gr.HTML(init_html)
demo.load(None,None,None,_js=scripts)
out = gr.HTML(init_html, visible=False)
demo.load(None,None,None,_js=scripts)
# btn2 = gr.Button(value="Pay to Get URL",visible=False)
pay_html = gr.HTML()
def call_api(image, email_id):
# Generate a UUID code
# imgs = [None] * 100
# for img in progress.tqdm(imgs, desc="Generating Puzzle"):
# time.sleep(0.1)
receipt_link_url, sub_image_list = perform_operations(image,email_id)
redirect_url = "https://piczify.com/thank-you/"
# print(sub_image_list)
url = "https://api.lemonsqueezy.com/v1/checkouts"
api_key = os.getenv("LEMON_ACTUAL_KEY")
# Define the request headers
headers = {
'Authorization': f'Bearer {api_key}'
}
# Create the request body
request_body = {
"data": {
"type": "checkouts",
"attributes": {
"product_options": {
"enabled_variants": [],
"redirect_url": redirect_url,
"receipt_link_url": receipt_link_url,
"receipt_button_text": "Puzzle Link",
"receipt_thank_you_note": "Your custom Sliding Puzzle link is : " + str(receipt_link_url) + "\n Click on Puzzle Link button or go to the custom puzzle link to play your Puzzle.",
},
"checkout_options": {
"button_color": "#2DD272"
},
"checkout_data": {},
"preview": True
},
"relationships": {
"store": {
"data": {
"type": "stores",
"id": "33985"
}
},
"variant": {
"data": {
"type": "variants",
"id": "108876"
}
}
}
}
}
# Convert the request body to JSON string
request_json = json.dumps(request_body)
# Make the API call
response = requests.post(url, headers=headers, data=request_json)
# print(response)
# Check the response status code
# Check the response status code
payment_html = f'''
'''
if response.status_code == 201:
# Parse the API response JSON
api_response = response.json()
# Get the URL value from the response
url_value = api_response["data"]["attributes"]["url"]
payment_html = f"""
"""
override_html = f"""
A Sliding Puzzle | Shuffle | Solve
"""
print("ok")
return {
# btn2: gr.update(visible=True),
out: override_html,
test_html: "",
pay_html: payment_html
}
# return gr.Button.update(visible=True),gr.HTML(html2)
# print("ok")
# btn2.update(visible=True)
# return html2
# demo.load(None,None,None,_js=scripts)
btn.click(call_api,inputs=[image,email],outputs=[out,test_html,pay_html])
# btn2.click(None,None,None,_js=js_payment)
# demo.load(None,None,None,_js=scripts)
demo.launch()