guilhermemfbastos commited on
Commit
e5e28c9
·
verified ·
1 Parent(s): d626194

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -0
app.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sqlite3
3
+ import uvicorn
4
+ import requests
5
+ import threading
6
+ import time
7
+ import random
8
+ from bs4 import BeautifulSoup
9
+ from ddgs import DDGS
10
+ from contextlib import asynccontextmanager
11
+ from fastapi import FastAPI, Query
12
+ from fastapi.staticfiles import StaticFiles
13
+ from fastapi.responses import FileResponse
14
+
15
+ # --- CONFIGURAÇÃO DE DIRETÓRIO ---
16
+ BASE_DIR = "./data"
17
+ if not os.path.exists(BASE_DIR):
18
+ try: os.makedirs(BASE_DIR)
19
+ except: BASE_DIR = "." # Fallback caso não tenha permissão no C:
20
+
21
+ DB_PATH = os.path.join(BASE_DIR, "gm_codesearch.db")
22
+
23
+ # --- LÓGICA DE BANCO DE DATOS ---
24
+ def init_db():
25
+ conn = sqlite3.connect(DB_PATH)
26
+ cursor = conn.cursor()
27
+ cursor.execute('''CREATE TABLE IF NOT EXISTS snippets
28
+ (id INTEGER PRIMARY KEY AUTOINCREMENT,
29
+ title TEXT, code TEXT, language TEXT,
30
+ source_url TEXT UNIQUE,
31
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
32
+ # Sementes iniciais para teste de busca
33
+ cursor.execute("INSERT OR IGNORE INTO snippets (title, code, language, source_url) VALUES (?, ?, ?, ?)",
34
+ ("Bootstrap Navbar", "<nav class='navbar'>...</nav>", "html", "seed_1"))
35
+ cursor.execute("INSERT OR IGNORE INTO snippets (title, code, language, source_url) VALUES (?, ?, ?, ?)",
36
+ ("Python List Comprehension", "[x for x in list if x > 0]", "python", "seed_2"))
37
+ conn.commit()
38
+ conn.close()
39
+
40
+ def add_snippet(title, code, url):
41
+ if not code or len(code) < 60: return False
42
+ try:
43
+ conn = sqlite3.connect(DB_PATH)
44
+ cursor = conn.cursor()
45
+ lang = "python" if "python" in url.lower() else "js"
46
+ if "html" in url.lower(): lang = "html"
47
+
48
+ cursor.execute("INSERT OR IGNORE INTO snippets (title, code, language, source_url) VALUES (?, ?, ?, ?)",
49
+ (title[:100], code.strip(), lang, url))
50
+ conn.commit()
51
+ success = cursor.rowcount > 0
52
+ conn.close()
53
+ return success
54
+ except: return False
55
+
56
+ # --- DUCK HUNTER (O CRAWLER) ---
57
+ CRAWLER_LOGS = []
58
+ def duck_hunter():
59
+ global CRAWLER_LOGS
60
+ print("🦆 Pato saiu para caçar...")
61
+ while True:
62
+ queries = ["python function snippets", "javascript async await", "css flexbox tricks", "fastapi examples"]
63
+ for q in queries:
64
+ try:
65
+ with DDGS() as ddgs:
66
+ results = [r for r in ddgs.text(q, max_results=5)]
67
+ for res in results:
68
+ time.sleep(random.uniform(5, 10))
69
+ try:
70
+ page = requests.get(res['href'], timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
71
+ soup = BeautifulSoup(page.text, 'html.parser')
72
+ blocks = soup.find_all(['pre', 'code'])
73
+ for b in blocks:
74
+ if add_snippet(res['title'], b.get_text(), res['href']):
75
+ CRAWLER_LOGS.insert(0, f"✅ PESCOU: {res['title'][:20]}...")
76
+ break
77
+ except: continue
78
+ CRAWLER_LOGS = CRAWLER_LOGS[:12]
79
+ except: pass
80
+ time.sleep(30)
81
+
82
+ # --- CONFIGURAÇÃO DO FASTAPI ---
83
+ @asynccontextmanager
84
+ async def lifespan(app: FastAPI):
85
+ init_db()
86
+ threading.Thread(target=duck_hunter, daemon=True).start()
87
+ yield
88
+
89
+ app = FastAPI(lifespan=lifespan)
90
+
91
+ # Monta a pasta onde você vai colocar o CSS e o JS
92
+ # Seus arquivos devem estar dentro de uma pasta chamada 'frontend'
93
+ if not os.path.exists("frontend"): os.makedirs("frontend")
94
+ app.mount("/frontend", StaticFiles(directory="frontend"), name="frontend")
95
+
96
+ # Rota principal que entrega o seu HTML
97
+ @app.get("/")
98
+ async def get_index():
99
+ return FileResponse('frontend/index.html')
100
+
101
+ # Endpoint que o JavaScript vai consultar
102
+ @app.get("/api/data")
103
+ def api_data(q: str = ""):
104
+ conn = sqlite3.connect(DB_PATH)
105
+ conn.row_factory = sqlite3.Row
106
+ cursor = conn.cursor()
107
+
108
+ cursor.execute("SELECT COUNT(*) FROM snippets")
109
+ total = cursor.fetchone()[0]
110
+
111
+ search_q = f"%{q}%"
112
+ cursor.execute("SELECT * FROM snippets WHERE title LIKE ? OR code LIKE ? ORDER BY id DESC LIMIT 40",
113
+ (search_q, search_q))
114
+ results = [dict(r) for r in cursor.fetchall()]
115
+ conn.close()
116
+
117
+ return {
118
+ "total": total,
119
+ "results": results,
120
+ "logs": CRAWLER_LOGS
121
+ }
122
+
123
+ if __name__ == "__main__":
124
+ uvicorn.run(app, host="127.0.0.1", port=8000)