guilhermemfbastos's picture
Update app.py
47087ac verified
raw
history blame
4.53 kB
import os
import sqlite3
import uvicorn
import requests
import threading
import time
import random
from bs4 import BeautifulSoup
from ddgs import DDGS
from contextlib import asynccontextmanager
from fastapi import FastAPI, Query
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
# --- CONFIGURAÇÃO DE DIRETÓRIO ---
BASE_DIR = "./data"
if not os.path.exists(BASE_DIR):
try: os.makedirs(BASE_DIR)
except: BASE_DIR = "." # Fallback caso não tenha permissão no C:
DB_PATH = os.path.join(BASE_DIR, "gm_codesearch.db")
# --- LÓGICA DE BANCO DE DATOS ---
def init_db():
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS snippets
(id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT, code TEXT, language TEXT,
source_url TEXT UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
# Sementes iniciais para teste de busca
cursor.execute("INSERT OR IGNORE INTO snippets (title, code, language, source_url) VALUES (?, ?, ?, ?)",
("Bootstrap Navbar", "<nav class='navbar'>...</nav>", "html", "seed_1"))
cursor.execute("INSERT OR IGNORE INTO snippets (title, code, language, source_url) VALUES (?, ?, ?, ?)",
("Python List Comprehension", "[x for x in list if x > 0]", "python", "seed_2"))
conn.commit()
conn.close()
def add_snippet(title, code, url):
if not code or len(code) < 60: return False
try:
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
lang = "python" if "python" in url.lower() else "js"
if "html" in url.lower(): lang = "html"
cursor.execute("INSERT OR IGNORE INTO snippets (title, code, language, source_url) VALUES (?, ?, ?, ?)",
(title[:100], code.strip(), lang, url))
conn.commit()
success = cursor.rowcount > 0
conn.close()
return success
except: return False
# --- DUCK HUNTER (O CRAWLER) ---
CRAWLER_LOGS = []
def duck_hunter():
global CRAWLER_LOGS
print("🦆 Pato saiu para caçar...")
while True:
queries = ["python function snippets", "javascript async await", "css flexbox tricks", "fastapi examples"]
for q in queries:
try:
with DDGS() as ddgs:
results = [r for r in ddgs.text(q, max_results=5)]
for res in results:
time.sleep(random.uniform(5, 10))
try:
page = requests.get(res['href'], timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
soup = BeautifulSoup(page.text, 'html.parser')
blocks = soup.find_all(['pre', 'code'])
for b in blocks:
if add_snippet(res['title'], b.get_text(), res['href']):
CRAWLER_LOGS.insert(0, f"✅ PESCOU: {res['title'][:20]}...")
break
except: continue
CRAWLER_LOGS = CRAWLER_LOGS[:12]
except: pass
time.sleep(30)
# --- CONFIGURAÇÃO DO FASTAPI ---
@asynccontextmanager
async def lifespan(app: FastAPI):
init_db()
threading.Thread(target=duck_hunter, daemon=True).start()
yield
app = FastAPI(lifespan=lifespan)
# Monta a pasta onde você vai colocar o CSS e o JS
# Seus arquivos devem estar dentro de uma pasta chamada 'frontend'
if not os.path.exists("frontend"): os.makedirs("frontend")
app.mount("/frontend", StaticFiles(directory="frontend"), name="frontend")
# Rota principal que entrega o seu HTML
@app.get("/")
async def get_index():
return FileResponse('frontend/index.html')
# Endpoint que o JavaScript vai consultar
@app.get("/api/data")
def api_data(q: str = ""):
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM snippets")
total = cursor.fetchone()[0]
search_q = f"%{q}%"
cursor.execute("SELECT * FROM snippets WHERE title LIKE ? OR code LIKE ? ORDER BY id DESC LIMIT 40",
(search_q, search_q))
results = [dict(r) for r in cursor.fetchall()]
conn.close()
return {
"total": total,
"results": results,
"logs": CRAWLER_LOGS
}
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=7860)