import os
import aiohttp
import asyncio
import dotenv
import google.generativeai as genai
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

with open("sysprompt.txt", "r") as f:
    sysprompt = f.read()

dotenv.load_dotenv()
NEWS_API_KEY = os.environ.get("NEWS_API_KEY")
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")

genai.configure(api_key=GEMINI_API_KEY)
model = genai.GenerativeModel(
    model_name="gemini-1.5-flash", system_instruction=sysprompt
)


async def generate_summary(text):
    summary = await model.generate_content_async(text)
    return summary


async def get_news(query):
    async with aiohttp.ClientSession() as session:
        try:
            async with session.get(
                f"https://newsapi.org/v2/everything?q={query}&apiKey={NEWS_API_KEY}"
            ) as response:
                response.raise_for_status()
                response_data = await response.json()
                return response_data
        except aiohttp.ClientResponseError as e:
            print(f"Error fetching for {query}: {e}")
            return None


def extract_links(news_data):
    return [article.get("url", "no link found") for article in news_data["articles"]]


def extract_headlines(news_data):
    return [article.get("title", "no title found") for article in news_data["articles"]]


def extract_image_urls(news_data):
    return [
        article.get("urlToImage", "no image found") for article in news_data["articles"]
    ]


async def scrape_link(url):
    jina_url = "https://r.jina.ai/" + url
    async with aiohttp.ClientSession() as session:
        try:
            async with session.get(jina_url) as response:
                response.raise_for_status()
                return await response.text()
        except aiohttp.ClientResponseError as e:
            print(f"Error fetching for {url}: {e}")
            return None


async def generate_single_news_data(news_data, news_data_index):
    link, headline, image_url = news_data[news_data_index]
    scrape = await scrape_link(link)
    summary = await generate_summary(scrape)
    return [link, headline, image_url, summary.text]


async def process_search(query):
    news = await get_news(query)
    links = extract_links(news)
    headlines = extract_headlines(news)
    image_urls = extract_image_urls(news)
    news_data = list(zip(links, headlines, image_urls))
    new1_data = await generate_single_news_data(news_data, 0)
    return new1_data


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/search", methods=["POST"])
def search():
    query = request.form.get("query")
    new1_data = asyncio.run(process_search(query))
    return jsonify(new1_data)


if __name__ == "__main__":
    app.run(debug=True)

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>News Summarizer</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/alpinejs/3.10.3/cdn.min.js"
      defer
    ></script>
  </head>
  <body
    class="bg-gray-100 min-h-screen flex items-center justify-center"
    x-data="{ newsData: null, loading: false }"
  >
    <div class="container mx-auto px-4 py-8">
      <h1 class="text-4xl font-bold text-center mb-8 text-blue-600">
        News Summarizer
      </h1>
      <form @submit.prevent="submitSearch" class="mb-8 flex justify-center">
        <input
          type="text"
          name="query"
          placeholder="Enter search term"
          class="px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
        />
        <button
          type="submit"
          class="bg-blue-500 text-white px-6 py-2 rounded-r-lg hover:bg-blue-600 transition duration-300"
        >
          Search
        </button>
      </form>
      <div x-show="loading" class="text-center">
        <div
          class="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-blue-500 mx-auto"
        ></div>
      </div>
      <div x-show="newsData" class="bg-white rounded-lg shadow-lg p-6">
        <h2 x-text="newsData[1]" class="text-2xl font-semibold mb-4"></h2>
        <img
          :src="newsData[2]"
          :alt="newsData[1]"
          class="w-full h-64 object-cover rounded-lg mb-4"
        />
        <p x-text="newsData[3]" class="text-gray-700 mb-4"></p>
        <a
          :href="newsData[0]"
          target="_blank"
          class="text-blue-500 hover:underline"
          >Read full article</a
        >
      </div>
    </div>

    <script>
      function submitSearch() {
        const query = document.querySelector('input[name="query"]').value;
        this.loading = true;
        fetch("/search", {
          method: "POST",
          headers: {
            "Content-Type": "application/x-www-form-urlencoded",
          },
          body: `query=${encodeURIComponent(query)}`,
        })
          .then((response) => response.json())
          .then((data) => {
            this.newsData = data;
            this.loading = false;
          })
          .catch((error) => {
            console.error("Error:", error);
            this.loading = false;
          });
      }
    </script>
  </body>
</html>
after the first search the server doesnt respond and says 
RuntimeError: Event loop is closed