keepalive / app.py
datamk's picture
Update app.py
1a6e8e4 verified
Raw
History Blame
3.58 kB
import streamlit as st
import threading
import time
import schedule
import random
import datetime
from playwright.sync_api import sync_playwright
# ── Streamlit UI Page Config ──
# Must be the first Streamlit command called on the page
st.set_page_config(page_title="Keep-Alive Console", page_icon="πŸš€", layout="wide")
TARGET_URL = "https://streamer1-hsd7neqlzku825vdo6rtkz.streamlit.app/"
# ── Shared log list (thread-safe for appends in CPython) ──
logs = ["πŸš€ System initialized – service starting…"]
def add_log(msg):
ts = datetime.datetime.now().strftime("%H:%M:%S")
entry = f"[{ts}] {msg}"
print(entry)
logs.append(entry)
if len(logs) > 50:
logs.pop(0)
# ── Keep-alive routine ──
def visit_and_scroll():
add_log(f"Opening {TARGET_URL}")
try:
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
args=["--no-sandbox", "--disable-dev-shm-usage", "--disable-gpu"],
)
try:
page = browser.new_page(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36"
)
page.goto(TARGET_URL, wait_until="networkidle", timeout=60_000)
add_log("Page loaded – waiting 10 s for hydration…")
time.sleep(10)
for i in range(1, 6):
y = i * 800
page.evaluate(f"window.scrollTo(0, {y});")
add_log(f"Scrolled to {y}px")
time.sleep(random.uniform(1.5, 3.0))
page.evaluate("window.scrollTo(0, 0);")
add_log("Visit completed successfully βœ…")
finally:
browser.close()
except Exception as e:
add_log(f"ERROR: {e}")
# ── Background scheduler (one thread, runs forever) ──
def _loop():
visit_and_scroll()
schedule.every(10).minutes.do(visit_and_scroll)
while True:
schedule.run_pending()
time.sleep(10) # check for scheduled tasks more frequently
# Guard: start the thread only once per Streamlit process using cache_resource
@st.cache_resource
def start_scheduler():
thread = threading.Thread(target=_loop, daemon=True)
thread.start()
return thread
start_scheduler()
# ── Streamlit UI layout ──
st.title("πŸ€– Keep-Alive Cloud Console")
st.caption(f"Target: **{TARGET_URL}** β€’ Frequency: every 10 minutes")
st.divider()
# Fragment for non-blocking UI logs refresh if supported (Streamlit >= 1.33)
if hasattr(st, "fragment"):
@st.fragment(run_every="30s")
def display_logs_fragment():
st.text_area("Logs (newest first)", "\n".join(reversed(logs)), height=400, disabled=True)
else:
def display_logs_fragment():
st.text_area("Logs (newest first)", "\n".join(reversed(logs)), height=400, disabled=True)
c1, c2 = st.columns([3, 1])
with c1:
st.subheader("Activity Log")
display_logs_fragment()
with c2:
st.subheader("Controls")
if st.button("πŸš€ Push Now"):
with st.spinner("Visiting…"):
visit_and_scroll()
st.success("Done!")
st.rerun() # Force rerun to refresh logs immediately on manual push
st.info("Background scheduler is active.")
# Page level auto-refresh fallback for older Streamlit versions (< 1.33)
if not hasattr(st, "fragment"):
time.sleep(30)
st.rerun()