Zhu-FaceOnLive's picture
Update app.py
f2da609 verified
import os
import gradio as gr
from io import BytesIO
import zipfile
import tempfile
import random
import json
from gradio_client import Client, handle_file
import base64
from PIL import Image
from datetime import datetime
BUY_PREMIUM = "πŸ₯‡ Get Premium Token to Unlock"
STATUS_MESSAGES = {
201: "Get a Premium Token for full link, deeper results including social profiles.",
301: "Invalid token! Get Premium Token using link in page"
}
BACKEND = os.getenv("BACKEND")
backend = Client(BACKEND)
JS_FUNC = os.getenv("JS_FUNC")
def base64_to_image(base64_str):
return base64.b64decode(base64_str + '=' * (-len(base64_str) % 4))
user_attempts = {}
def clear_old_entries():
today = datetime.now().date()
# Create a list of keys to remove
keys_to_remove = [key for key, value in user_attempts.items() if value != today]
# Remove old entries
for key in keys_to_remove:
del user_attempts[key]
def if_limited(request):
clear_old_entries()
user_ip = None
if request.headers.get("x-forwarded-for"):
user_ip = request.headers["x-forwarded-for"].split(",")[0] # First IP in the list
cookie_value = request.headers.get("cookie", "")
if "user_id=" in cookie_value:
user_id = cookie_value.split("user_id=")[1].split(";")[0]
else:
user_id = None
print("##### Coming", user_id, user_ip)
# Get today's date
today = datetime.now().date()
# Check if the user has already tried today (by IP or cookie)
for key, value in user_attempts.items():
if (key == user_ip or key == user_id) and value == today:
return True
# Record the attempt (store both hashed IP and hashed cookie)
if user_ip:
user_attempts[user_ip] = today
if user_id:
user_attempts[user_id] = today
return False
def search_face(file, token, request: gr.Request):
try:
file_1 = handle_file(file)
except Exception as e:
gr.Info("Please upload an image file.")
return []
if token == "" and if_limited(request):
gr.Info("⏳ Wait for your next free search, or πŸš€ Go Premium for deep search!", duration=12)
return []
result_text = backend.predict(
file=file_1,
token=token,
api_name="/search_face"
)
result = json.loads(result_text)
outarray = []
if result['status'] > 300:
raise gr.Error(STATUS_MESSAGES[result['status']])
for item in result['result']:
image = Image.open(BytesIO(base64_to_image(item['image'])))
outarray.append((image, item['url']))
if result['status'] == 201:
gr.Info(STATUS_MESSAGES[result['status']], duration=12)
return outarray
def export_images(items):
if not items:
return None
# Create a zip file in memory
zip_buffer = BytesIO()
with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
url_text = ""
i = 1
for item in items:
if item[1] == BUY_PREMIUM:
continue
with open(item[0], 'rb') as img_file:
zip_file.writestr(f'image_{i}.jpg', img_file.read())
url_text += f"image_{i}.jpg: {item[1]}\n"
i += 1
zip_file.writestr("urls.txt", url_text)
zip_buffer.seek(0)
with tempfile.NamedTemporaryFile(delete=False, suffix=".zip") as temp_file:
temp_file.write(zip_buffer.getvalue())
temp_file_path = temp_file.name
return temp_file_path
custom_css = """
caption.caption {
user-select: text;
cursor: text;
}
div#export_file {
max-height: 63.39px;
}
.svelte-snayfm {
height: auto;
}
.icon.svelte-snayfm {
width: 48px;
height: 48px;
}
.button-gradient {
background: linear-gradient(45deg, #ff416c, #ff4b2b, #ff9b00, #ff416c);
background-size: 400% 400%;
border: none;
padding: 14px 28px;
font-size: 16px;
font-weight: bold;
color: white;
border-radius: 10px;
cursor: pointer;
transition: 0.3s ease-in-out;
animation: gradientAnimation 2s infinite linear;
box-shadow: 0 4px 10px rgba(255, 65, 108, 0.6);
}
@keyframes gradientAnimation {
0% { background-position: 0% 50%; }
25% { background-position: 50% 100%; }
50% { background-position: 100% 50%; }
75% { background-position: 50% 0%; }
100% { background-position: 0% 50%; }
}
.button-gradient:hover {
transform: scale(1.05);
box-shadow: 0 6px 15px rgba(255, 75, 43, 0.8);
}
@keyframes labelGradientFlow {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
label.svelte-i3tvor.float {
background: linear-gradient(90deg, #555555, #333333, #555555); /* Dark gray gradient */
background-size: 200% 200%;
color: #f1f1f1;
font-weight: bold;
text-align: center;
animation: labelGradientFlow 4s infinite ease-in-out;
box-shadow: 0 0 6px rgba(50, 50, 50, 0.7); /* Subtle dark glow */
transition: all 0.3s ease-in-out;
}
"""
js = """
function aff() {
const links = document.querySelectorAll('a');
const currentUrl = new URL(window.location.href);
const currentParams = currentUrl.searchParams.toString();
links.forEach(link => {
const href = link.getAttribute('href');
if (href && (href.startsWith('https://faceonlive.pocketsflow.com') || href.startsWith('https://faceonlive.com'))) {
const targetUrl = new URL(href);
// Append current page parameters to the link
currentParams.split('&').forEach(param => {
if (param) {
const [key, value] = param.split('=');
targetUrl.searchParams.set(key, value);
}
});
link.setAttribute('href', targetUrl.toString());
}
});
return ''
}
"""
head = """
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-8YPXF4536P"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-8YPXF4536P');
</script>
"""
output = gr.Gallery(label="Search may take a few minutes.", columns=[3], object_fit="contain", height="480px", interactive=False)
col2 = gr.Column(scale=2, visible=False)
def init_ui():
return gr.update(visible=True), gr.update(visible=False)
def search_ui():
return gr.update(visible=False), gr.update(visible=True)
def search_face_examples(image):
return search_face(image), gr.update(visible=False), gr.update(visible=True)
def set_url_token(request: gr.Request):
if request and request.query_params:
params = dict(request.query_params)
if "ptoken" in params:
return params["ptoken"]
return ""
def update_button(token):
if token:
return gr.update(visible=False), gr.update(value="πŸš€ Unlock Deep Search Now!", elem_classes="button-gradient")
else:
return gr.update(visible=True), gr.update(value="πŸ” Free Face Search", elem_classes="")
MARKDOWN0 = """
# Free Face Search Online - ❀️Like above if this space helps
#### [Learn more about our Reverse Face Search](https://faceonlive.com/face-search-online)
#### [Face Search API and Affiliate Program (50%).](https://portfolio.faceonlive.com/#face_search)
"""
MARKDOWN2 = """
### [Why Deep Search with Premium Token?](https://faceonlive.pocketsflow.com/checkout?productId=676c15b1971244a587ca07cb)
βœ… **Search Social Media, Deep Web & Uncover Hidden Profiles**
βœ… **Outperforming PimEyes + FaceCheck.ID Combined!**
"""
MARKDOWN3_2 = """
<div align="right"><a href="https://faceonlive.pocketsflow.com/checkout?productId=677fe2b5aeced2814bc47dd1" target='_blank' style='font-size: 16px;'>Opt-Out From Search</a></div><br/>
<div align="right"><a href="https://faceseek.online" target='_blank' style='font-size: 16px;'>One more free search? πŸ‘‰ FaceSeek Online</div><br/>
<div align="right"><a href="https://faceonlive.com/deepfake-detector" target='_blank' style='font-size: 16px;'>AI Generated Image & Deepfake Detector</div>
"""
PREMIUM_CHECKOUT = "https://faceonlive.pocketsflow.com/checkout?productId=676c15b1971244a587ca07cb"
with gr.Blocks(css=custom_css, head=head, delete_cache=(3600, 3600)) as demo:
gr.Markdown(MARKDOWN0)
with gr.Row():
with gr.Column(scale=1) as col1:
image = gr.Image(type='filepath', height=360)
with gr.Row():
with gr.Column():
token = gr.Textbox(placeholder="(Optional) Input Premium Token here.", label="Premium Token")
with gr.Column():
md_premium1 = gr.Markdown(MARKDOWN2)
gr.HTML("<div id='limit'></div>")
with gr.Row():
with gr.Column():
limit_button = gr.Button("πŸ” Free Face Search")
face_search_button = gr.Button("Face Search", visible=False, elem_id="submit_btn")
with gr.Column():
premium_search_button = gr.Button("πŸš€ Unlock Deep Search Now!", elem_classes="button-gradient", link=PREMIUM_CHECKOUT)
with gr.Row():
with gr.Column():
gr.Examples(['examples/1.jpg', 'examples/2.jpg'], inputs=image, cache_examples=True, fn=search_face_examples, outputs=[output, col1, col2])
with gr.Column():
gr.HTML(MARKDOWN3_2)
with col2.render():
gr.Markdown("> ### **⚠️ Reminder:** Export images before refreshing the page by clicking the 'Export Images' button.")
output.render()
with gr.Row():
with gr.Column():
md_premium2 = gr.Markdown(MARKDOWN2)
with gr.Column():
export_button = gr.Button("Export Images")
export_file = gr.File(label="Download", elem_id="export_file")
with gr.Row():
with gr.Column():
premium_link_button = gr.Button("πŸš€ Unlock Deep Search Now!", elem_classes="button-gradient", link=PREMIUM_CHECKOUT)
with gr.Column():
new_search_button = gr.Button("πŸ” New Search")
gr.HTML(MARKDOWN3_2)
limit_button.click(None, js=JS_FUNC)
face_search_button.click(search_ui, inputs=[], outputs=[col1, col2], api_name=False)
face_search_button.click(search_face, inputs=[image, token], outputs=[output], api_name=False)
export_button.click(export_images, inputs=[output], outputs=export_file, api_name=False)
new_search_button.click(init_ui, inputs=[], outputs=[col1, col2], api_name=False)
token.change(update_button, inputs=[token], outputs=[premium_search_button, limit_button])
with gr.Row():
with gr.Column(scale=1):
gr.HTML('<a href="https://visitorbadge.io/status?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2FFaceOnLive%2FFace-Search-Online"><img src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2FFaceOnLive%2FFace-Search-Online&labelColor=%23ff8a65&countColor=%2337d67a&style=flat&labelStyle=upper" /></a>')
with gr.Column(scale=5):
html = gr.HTML()
demo.load(None, inputs=None, outputs=html, js=js)
demo.load(set_url_token, inputs=None, outputs=[token])
demo.queue(api_open=False, default_concurrency_limit=8).launch(show_api=False)