Spaces:
Runtime error
Runtime error
import asyncio | |
import gradio as gr | |
from sqlalchemy.exc import SQLAlchemyError | |
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession | |
from sqlalchemy.future import select | |
from sqlalchemy.orm import sessionmaker | |
import logging | |
import threading | |
import time | |
import requests | |
from bs4 import BeautifulSoup | |
logger = logging.getLogger(__name__) | |
logging.basicConfig(level=logging.INFO) | |
# Global variables | |
db_session = None | |
engine = None | |
# Function for dynamically setting the database connection | |
async def set_db_connection(host, port, user, password, db_name): | |
global db_session, engine | |
try: | |
engine = create_async_engine( | |
f"mysql+aiomysql://{user}:{password}@{host}:{port}/{db_name}", | |
echo=False | |
) | |
Session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) | |
db_session = Session() | |
logger.info("Database connection established.") | |
return "Database connection established." | |
except Exception as e: | |
logger.error(f"Failed to establish database connection: {e}") | |
return f"Failed to connect to database: {e}" | |
# Function to update database status | |
def update_db_status(): | |
global db_session | |
try: | |
if db_session: | |
asyncio.run(db_session.execute(select(1))) | |
return "Connected" | |
else: | |
return "Not connected" | |
except SQLAlchemyError as e: | |
logger.error(f"SQLAlchemyError: {e}") | |
return "Disconnected" | |
except Exception as e: | |
logger.error(f"Unexpected error: {e}") | |
return "Disconnected" | |
# Background task to update status | |
def background_update(db_status_textbox): | |
while True: | |
status = update_db_status() | |
db_status_textbox.update(value=status) | |
logger.info(f"Database status updated: {status}") | |
time.sleep(60) | |
# Function to scrape data from a URL | |
def scrape_data(url): | |
try: | |
response = requests.get(url) | |
response.raise_for_status() | |
soup = BeautifulSoup(response.text, 'html.parser') | |
# Extract data as needed, e.g., headlines, articles, etc. | |
data = [element.text for element in soup.find_all('h1')] # Example: extracting all h1 tags | |
return data | |
except requests.RequestException as e: | |
logger.error(f"Failed to scrape data from {url}: {e}") | |
return [] | |
# Function to store scraped data in the database | |
async def store_data(data): | |
global db_session | |
try: | |
async with db_session() as session: | |
async with session.begin(): | |
# Example: Assuming a table 'feeds' with a column 'content' | |
for item in data: | |
await session.execute( | |
"INSERT INTO feeds (content) VALUES (:content)", | |
{"content": item} | |
) | |
await session.commit() | |
logger.info("Data stored in the database.") | |
except SQLAlchemyError as e: | |
logger.error(f"Failed to store data in the database: {e}") | |
# Function to serve data to a target URL | |
def serve_data(target_url, data): | |
try: | |
response = requests.post(target_url, json={"data": data}) | |
response.raise_for_status() | |
logger.info(f"Data served to {target_url} successfully.") | |
return "Data served successfully." | |
except requests.RequestException as e: | |
logger.error(f"Failed to serve data to {target_url}: {e}") | |
return f"Failed to serve data: {e}" | |
# Function to monitor and autopost data | |
def monitor_and_autopost(scrape_url, target_url): | |
while True: | |
data = scrape_data(scrape_url) | |
asyncio.run(store_data(data)) | |
serve_data(target_url, data) | |
time.sleep(3600) # Run every hour | |
# Main application that runs Gradio UI and background tasks | |
def main(): | |
with gr.Blocks(css=".gradio-container {background: linear-gradient(135deg, #6a0dad, #ffd700);}") as demo: | |
gr.Markdown("# Website Monitor and Chatbot", elem_id="title") | |
with gr.Row(): | |
with gr.Column(): | |
gr.Markdown("## Database Settings", elem_id="subtitle") | |
db_host = gr.Textbox(label="Database Host", placeholder="localhost", value="localhost") | |
db_port = gr.Textbox(label="Database Port", placeholder="3306", value="3306") | |
db_user = gr.Textbox(label="Database User", placeholder="username", value="") | |
db_pass = gr.Textbox(label="Database Password", placeholder="password", type="password", value="") | |
db_name = gr.Textbox(label="Database Name", placeholder="database_name", value="monitoring") | |
db_status_textbox = gr.Textbox(label="Database Status", interactive=False) | |
status_text = gr.Textbox(label="Status", interactive=False) | |
connect_button = gr.Button("Connect to Database") | |
gr.Markdown("## Scraping and Serving Settings", elem_id="subtitle") | |
scrape_url = gr.Textbox(label="Scrape URL", placeholder="https://example.com") | |
target_url = gr.Textbox(label="Target URL", placeholder="https://target.com/api") | |
start_monitoring_button = gr.Button("Start Monitoring and Autoposting") | |
# Connect button click event | |
def on_connect_click(host, port, user, password, db_name): | |
loop = asyncio.new_event_loop() | |
asyncio.set_event_loop(loop) | |
result = loop.run_until_complete(set_db_connection(host, port, user, password, db_name)) | |
return result | |
connect_button.click( | |
on_connect_click, | |
inputs=[db_host, db_port, db_user, db_pass, db_name], | |
outputs=[status_text] | |
) | |
# Start monitoring and autoposting button click event | |
def on_start_monitoring_click(scrape_url, target_url): | |
threading.Thread(target=monitor_and_autopost, args=(scrape_url, target_url), daemon=True).start() | |
return "Monitoring and autoposting started." | |
start_monitoring_button.click( | |
on_start_monitoring_click, | |
inputs=[scrape_url, target_url], | |
outputs=[] | |
) | |
# Start background task to update status | |
threading.Thread(target=background_update, args=(db_status_textbox,), daemon=True).start() | |
# Launch the Gradio interface with a timeout | |
logger.info("Launching Gradio interface...") | |
demo.launch(prevent_thread_lock=True) | |
logger.info("Gradio interface launched successfully.") | |
if __name__ == "__main__": | |
main() | |
logger.info("Main function completed. App is running.") |