nirinsbeat / app.py
Razoa's picture
Update app.py
3d8e1ea verified
Raw
History Blame Contribute Delete
6.76 kB
import streamlit as st
import pandas as pd
from huggingface_hub import HfApi, hf_hub_download
import os
# --- CONFIGURATION ---
REPO_ID = "Razoa/nirinsbeat"
TOKEN = os.environ.get("HF_TOKEN")
PAYPAL_EMAIL = "nirinsbeatz@gmail.com"
st.set_page_config(page_title="NIRINSBEATZ", layout="centered")
# --- STYLE CSS (COMPACT & PRO) ---
st.markdown("""
<style>
@import url('https://fonts.googleapis.com/css2?family=Black+Ops+One&family=Poppins:wght@400;700&display=swap');
* { transition: none !important; animation: none !important; }
.stApp { background-color: #fafafa; color: #333; font-family: 'Poppins', sans-serif; }
/* TITRE ANTONONY */
.main-title {
text-align: center;
font-family: 'Black Ops One', cursive;
font-size: clamp(24px, 8vw, 45px);
color: #6f42c1;
padding: 15px 0;
white-space: nowrap;
}
/* CARD ANTONONY */
.beat-card {
background: #ffffff;
border-radius: 12px;
padding: 15px;
margin-bottom: 20px;
text-align: center;
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
border: 1px solid #eee;
}
/* SARY ANTONONY */
.artwork {
width: 100%;
max-width: 220px;
height: 220px;
border-radius: 10px;
object-fit: cover;
margin-bottom: 10px;
border: 2px solid #f0f0f0;
}
.beat-title {
font-size: 20px;
font-weight: 700;
color: #1a1a1a;
margin: 5px 0;
}
.price-tag { color: #6f42c1; font-weight: bold; font-size: 20px; margin-bottom: 10px; }
/* ESORINA NY DOWNLOAD browser */
audio { width: 100%; height: 35px; margin: 10px 0; }
audio::-internal-media-controls-download-button { display:none; }
audio::-webkit-media-controls-enclosure { overflow:hidden; }
audio::-webkit-media-controls-panel { width: calc(100% + 30px); }
.paypal-btn {
background-color: #ffc439;
color: #003087 !important;
border-radius: 25px;
text-align: center;
padding: 10px;
text-decoration: none;
display: block;
font-weight: bold;
font-size: 15px;
}
.download-link-big {
background: linear-gradient(135deg, #28a745 0%, #218838 100%);
color: white !important;
border-radius: 10px;
text-align: center;
padding: 15px;
text-decoration: none;
display: block;
font-weight: bold;
font-size: 18px;
}
</style>
""", unsafe_allow_html=True)
# --- DATABASE ---
@st.cache_data(show_spinner=False)
def load_data():
try:
file_path = hf_hub_download(repo_id=REPO_ID, filename="data.csv", repo_type="space", token=TOKEN)
return pd.read_csv(file_path)
except:
return pd.DataFrame(columns=["titre", "categorie", "prix", "file_url", "image_url"])
def save_and_upload(dataframe):
dataframe.to_csv("data.csv", index=False)
api = HfApi()
api.upload_file(path_or_fileobj="data.csv", path_in_repo="data.csv", repo_id=REPO_ID, repo_type="space", token=TOKEN)
st.cache_data.clear()
df = load_data()
# --- HEADER ---
st.markdown('<div class="main-title">NIRINSBEATZ</div>', unsafe_allow_html=True)
# --- SIDEBAR ---
choice = st.sidebar.selectbox("Genre", ["🏠 Home", "πŸ”₯ Afrobeat", "🎡 Afropop", "⚑ Drill", "πŸ’ƒ Zouk"])
secret_input = st.sidebar.text_input("Search beat...", placeholder="Type here...")
admin_mode = (secret_input == "admin-login")
# --- CATALOGUE ---
if not admin_mode:
q_params = st.query_params
is_success = q_params.get("payment") == "success"
target_id = q_params.get("id")
clean_choice = choice.split(" ")[1] if " " in choice else choice
display_df = df if clean_choice == "Home" else df[df['categorie'] == clean_choice]
if display_df.empty:
st.info("No beats found.")
else:
for index, row in display_df.iterrows():
try:
val = int(''.join(filter(str.isdigit, str(row['prix']))))
usd = round(val / 4500, 2)
except: usd = "19.99"
ret_url = f"https://huggingface.co/spaces/{REPO_ID}?payment=success&id={index}"
pay_url = f"https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business={PAYPAL_EMAIL}&item_name={row['titre']}&amount={usd}&currency_code=USD&return={ret_url}"
st.markdown(f'''
<div class="beat-card">
<img src="{row["image_url"]}" class="artwork">
<div class="beat-title">{row["titre"]}</div>
<div class="price-tag">${usd} <span style="font-size:12px; color:#aaa;">({row["prix"]})</span></div>
''', unsafe_allow_html=True)
st.markdown(f'<audio controls controlsList="nodownload"><source src="{row["file_url"]}" type="audio/mpeg"></audio>', unsafe_allow_html=True)
if is_success and str(target_id) == str(index):
st.markdown(f'<a href="{row["file_url"]}" target="_blank" class="download-link-big">⬇️ DOWNLOAD HQ</a>', unsafe_allow_html=True)
else:
st.markdown(f'<a href="{pay_url}" target="_blank" class="paypal-btn">πŸ’³ Buy Now</a>', unsafe_allow_html=True)
st.markdown('</div>', unsafe_allow_html=True)
# --- ADMIN PANEL ---
else:
st.header("πŸ”‘ Admin")
if st.text_input("Password", type="password") == "admin123":
t1, t2 = st.tabs(["Upload", "Manage"])
with t1:
with st.form("up"):
t = st.text_input("Title"); c = st.selectbox("Cat", ["Afrobeat", "Afropop", "Drill", "Zouk"]); p = st.text_input("Price (Ar)")
a = st.file_uploader("Audio", type=["mp3", "wav"]); i = st.file_uploader("Image", type=["jpg", "png"])
if st.form_submit_button("Publish"):
api = HfApi(); ap = f"beats/{a.name}"; ip = f"images/{i.name}"
api.upload_file(path_or_fileobj=a, path_in_repo=ap, repo_id=REPO_ID, repo_type="space", token=TOKEN)
api.upload_file(path_or_fileobj=i, path_in_repo=ip, repo_id=REPO_ID, repo_type="space", token=TOKEN)
new = pd.DataFrame([{"titre":t, "categorie":c, "prix":p, "file_url":f"https://huggingface.co/spaces/{REPO_ID}/resolve/main/{ap}", "image_url":f"https://huggingface.co/spaces/{REPO_ID}/resolve/main/{ip}"}])
df = pd.concat([df, new], ignore_index=True); save_and_upload(df); st.rerun()
with t2:
for idx, row in df.iterrows():
if st.button(f"Delete {row['titre']}", key=f"del_{idx}"):
df = df.drop(idx); save_and_upload(df); st.rerun()