File size: 6,030 Bytes
10aaa36
6e6128e
 
09095fe
09dd92c
09095fe
f22964e
164f0a5
 
09dd92c
6e6128e
b3b63d8
 
 
09dd92c
 
 
 
 
 
 
 
 
 
 
 
 
 
b3b63d8
09dd92c
 
6e6128e
 
09dd92c
 
 
 
fe81e0b
09dd92c
 
6e6128e
09dd92c
09095fe
18a8600
6e6128e
09dd92c
6e6128e
09dd92c
6e6128e
 
2a8d7ab
09dd92c
 
55f620f
09095fe
 
b3b63d8
09095fe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
09dd92c
 
09095fe
 
 
 
 
 
 
 
09dd92c
 
b3b63d8
09095fe
09dd92c
 
09095fe
09dd92c
b3b63d8
 
09dd92c
b3b63d8
09dd92c
09095fe
 
 
 
09dd92c
09095fe
 
 
 
 
09dd92c
f0b5677
 
 
09dd92c
6e6128e
09095fe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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 os
import sys
from typing import List, Dict, Any

# Global variables for database session and engine
db_session = None
engine = None
monitoring_task = None
logger = logging.getLogger(__name__)

# Function for dynamically setting the database connection
async def set_db_connection(host: str, port: str, user: str, password: str, db_name: str):
    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()
        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}"

# Periodic feed updater with error handling and logging improvements
async def periodic_update_with_error_handling():
    while True:
        try:
            await asyncio.sleep(300)  # Wait for 5 minutes before updating the feed content.
            await update_feed_content()  # Update the feed content.
        except Exception as e:  # Catch all exceptions for logging purposes.
            logger.error(f"Error in periodic update: {e}")  # Improved logging message format.

# Function to fetch RSS feed content from the provided URL with error handling and logging improvements.
async def fetch_feed_content(feed_url: str) -> Dict[str, Any]:
    try:
        result = await db_session.execute(select(Article).order_by(Article.timestamp.desc()).limit(20))
        articles = result.scalars().all()  # Fetch latest articles
        feed = {
            'title': 'Website Changes Feed',
            'link': feed_url,
            'description': 'Feed of changes detected on monitored websites.',
            'items': [{'title': article.title, 'link': article.url, 'description': article.content, 'pubDate': str(article.timestamp)} for article in articles] if articles else []
        }
        return feed
    except Exception as e:
        logger.error(f"Error fetching feed content: {e}")
        return {}

# Main application that runs Gradio UI and background tasks
async def main():
    global db_session, monitoring_task
    engine = None
    demo = gr.Blocks()
    # Define the Gradio interface
    with demo:
        gr.Markdown("# Website Monitor and Chatbot")
        with gr.Row():
            with gr.Column():
                gr.Markdown("## Database Settings")
                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)
                gr.Markdown("## RSS Feed Reader Settings")
                feed_target_url = gr.Textbox(label="RSS Feed Target URL", placeholder="http://yourwebsite.com/feed")
                view_button = gr.Button("View Feed")
                target_urls = gr.Textbox(label="Target URLs (comma-separated)", placeholder="https://example.com, https://another-site.com")
                storage_location = gr.Textbox(label="Storage Location (CSV file path)", placeholder="/path/to/your/file.csv")
                feed_rss_checkbox = gr.Checkbox(label="Enable RSS Feed")
                start_button = gr.Button("Start Monitoring")
                stop_button = gr.Button("Stop Monitoring")
            with gr.Column():
                feed_content = gr.JSON(label="RSS Feed Content")
                chatbot_interface = gr.Chatbot(type='messages')
                message_input = gr.Textbox(placeholder="Type your message here...")
                send_button = gr.Button("Send")
        # Define button actions
        async def on_start_click(target_urls_str: str, storage_loc: str, feed_enabled: bool, host: str, port: str, user: str, password: str, db_name: str):
            global monitoring_task
            urls = [url.strip() for url in target_urls_str.split(",")]
            await set_db_connection(host, port, user, password, db_name)
            monitoring_task = asyncio.create_task(start_monitoring(urls, storage_loc, feed_enabled))
            return "Monitoring started."
        async def on_stop_click():
            global monitoring_task
            if monitoring_task:
                monitoring_task.cancel()
                monitoring_task = None
            return "Monitoring stopped."
        async def on_view_feed_click(feed_url: str):
            return await fetch_feed_content(feed_url)
        stop_button.click(on_stop_click, outputs=[status_text])
        view_button.click(on_view_feed_click, inputs=[feed_target_url], outputs=[feed_content])
        send_button.click(chatbot_response, inputs=[message_input, chatbot_interface], outputs=[chatbot_interface, message_input])
        # Set up the timer for periodic updates
        feed_updater = gr.Timer(interval=300)
        feed_updater.tick(fn=update_feed_content, outputs=feed_content)
        # Load and check database status when the UI is loaded
        demo.load(update_db_status, outputs=db_status_textbox)
        asyncio.create_task(periodic_update_with_error_handling())
        # Launch the Gradio demo
        await demo.launch()

# Launch the app using asyncio
if __name__ == "__main__":
    asyncio.run(main())