Skip to content

Commit eb3729e

Browse files
committed
rm useless functions
1 parent 8f4f151 commit eb3729e

15 files changed

Lines changed: 186 additions & 373 deletions

File tree

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ on:
44
push:
55
branches:
66
- build
7-
# schedule:
8-
# - cron: '*/10 * * * *'
7+
schedule:
8+
- cron: '*/10 * * * *'
99

1010
jobs:
1111
deploy:
@@ -54,7 +54,7 @@ jobs:
5454
env:
5555
CLOUD_ID: ${{ secrets.CLOUD_ID }}
5656
ELASTIC_PASSWORD: ${{ secrets.ELASTIC_PASSWORD }}
57-
run: python elastic_script.py
57+
run: python elastic/elastic_script.py
5858

5959
- name: Run FastAPI and test endpoint
6060
env:

README.md

Lines changed: 100 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,76 @@
11
# Evently – Event Scraper + FastAPI + Elasticsearch + GitHub Actions Cron
22

3-
Evently is a project that scrapes event data, indexes it into Elasticsearch, and serves it through a FastAPI backend with a front-end UI.
3+
Evently is a platform that scrapes event data from multiple Moroccan sources, enriches each event with nearby bus and tramway transport info, indexes everything into Elasticsearch, and serves it through a FastAPI backend with a frontend UI.
44
All scraping and indexing are automated using GitHub Actions on a scheduled cron job.
55

6-
76
---
87

9-
## 📌 Features :
8+
## 📌 Features
109

1110
### 🔍 Scraping
12-
- Collects events from multiple sources
11+
- Collects events in parallel from multiple sources (Casaevents, Eventbrite, Events.ma, Guichet)
12+
- Parallel scraping for faster data collection
13+
14+
### 🚌 Transport Integration
15+
- Each event is automatically enriched with nearby **Casabus** and **Tramway** lines at indexing time
16+
- Uses a **KDTree spatial index** for near-instant transport lookups
17+
- Transport data is precomputed and stored directly in the event document — no per-request calculation
1318

1419
### 🧠 Elasticsearch
15-
- Events are indexed
16-
- Prevents duplicates using hashed unique IDs
20+
- Events are indexed with duplicate prevention using hashed unique IDs (MD5)
21+
- Full-text search with filters by city, category, and date
22+
- Aggregations for stats, filters, trending, and recommendations
1723

1824
### ⚡ FastAPI Backend
1925

20-
Endpoints:
21-
- `/` – serves the frontend
22-
- `/events` – paginated events
23-
- `/indexing` – manually trigger indexing
24-
- `/stream` – test server-sent event streaming
26+
| Method | Endpoint | Description |
27+
|--------|----------|-------------|
28+
| GET | `/` | Frontend homepage |
29+
| GET | `/events?page=X&size=Y` | Paginated events |
30+
| GET | `/event/{event_id}` | Single event detail |
31+
| GET | `/search` | Search with filters (city, category, date) |
32+
| GET | `/transport/{event_id}` | Bus and tramway lines near an event |
33+
| GET | `/filters` | Available cities and categories |
34+
| GET | `/stats` | Total events, upcoming, cities, categories |
35+
| GET | `/trending` | Trending upcoming events |
36+
| GET | `/recommendations` | Similar events by category and city |
37+
| GET | `/calendar` | Events grouped by date for a given month |
38+
| POST | `/favorites/{event_id}` | Add event to favorites |
39+
| DELETE | `/favorites/{event_id}` | Remove event from favorites |
40+
| GET | `/favorites` | Get favorite events |
41+
| POST | `/export` | Export events as JSON or CSV |
42+
| GET | `/reindex` | Manually trigger full reindex |
43+
| GET | `/health` | Elasticsearch health check |
2544

2645
### 🎨 Frontend
27-
- Dynamic event loading from API
28-
- Pagination support
46+
- Dynamic event loading from API
47+
- Pagination, search, and filter support
2948

3049
### 🔄 GitHub Actions Automation
31-
A scheduled workflow runs:
32-
- All scrapers
33-
- Elasticsearch indexing script
34-
- Based on a cron schedule
50+
A scheduled workflow runs all scrapers and Elasticsearch indexing automatically on a cron schedule.
3551

3652
---
3753

3854
## 🗂️ Project Structure
55+
3956
```
4057
Events_Project/
4158
4259
├── elastic/
43-
│ ├── __init__.py # exports global 'es' instance
44-
│ └── elastic_client.py # creates Elasticsearch client
60+
│ ├── elastic_script.py # indexing + transport enrichment
61+
│ └── elastic_client.py # Elasticsearch client setup
62+
63+
├── main.py # FastAPI routes + lifespan startup
64+
65+
├── static/
66+
│ ├── script.js
67+
│ └── style.css
68+
69+
├── templates/
70+
│ └── index.html # Frontend UI
4571
46-
├── main.py # FastAPI routes
47-
├── elastic_script.py # indexing script
48-
├── index.html # Frontend UI
4972
├── requirements.txt
50-
├── .env # Environment variables
73+
├── .env # Environment variables (not committed)
5174
5275
├── .github/
5376
│ └── workflows/
@@ -56,88 +79,96 @@ Events_Project/
5679
├── Dockerfile
5780
├── docker-compose.yml
5881
59-
├── scrape/ # All scrapers
82+
├── scrape/ # Scrapers (run in parallel)
6083
│ ├── casaevents.py
6184
│ ├── eventbrit.py
62-
│ ├── events.ma
85+
│ ├── eventsma.py
6386
│ └── guichet.py
6487
6588
├── struct_events/
66-
│ └── models.py # Events model
67-
89+
│ ├── get_coords.py # Geocoding utility
90+
│ └── models.py # Events Pydantic model
91+
92+
├── transport/
93+
│ ├── bus.py # KDTree transport lookup
94+
│ ├── cleaned_lines/
95+
│ └── overpass/
6896
```
6997

7098
---
7199

72-
73-
74100
## ⚙️ Installation & Setup
75101

102+
### 1️⃣ Pull the Docker image OR Clone the repo
76103

77-
### 1️⃣ Pull the Docker image
78104
```bash
79105
docker pull chaimaaeljerrar/scraping-image:latest
80106
```
81-
82-
83-
### 2️⃣ Create your .env file
84-
```
85-
ELASTIC_PASSWORD=(your elasic password)
86-
CLOUD_ID=(your elastic cloud id)
107+
OR
108+
```bash
109+
git clone <repo_url>
87110
```
88111

112+
### 2️⃣ (Optional) Create a `.env` file
113+
114+
Only needed if connecting to Elastic Cloud or if security is enabled:
89115

90-
### 3️⃣ Install dependencies
91116
```
92-
docker run -d -p 8000:8000 --env-file .env chaimaaeljerrar/scraping-image:latest
117+
ELASTIC_PASSWORD=your_password_here
118+
CLOUD_ID=your_cloud_id_here
93119
```
94120

121+
> When running locally with Docker Compose, Elasticsearch security is disabled by default — no `.env` is required.
95122
96-
### 4️⃣ Access the frontend
97-
```
98-
👉 http://localhost:8000
99-
🔌 Elasticsearch Connection
100-
```
123+
### 3️⃣ Build and run the container
101124

125+
```bash
126+
docker compose up
127+
```
102128

129+
The app will:
130+
1. Wait for Elasticsearch to be healthy
131+
2. Automatically start scraping and indexing events in the background
132+
3. Serve the frontend at `http://localhost:8000`
103133

104-
### 🤖 GitHub Actions – Scheduled Scraping
105-
This automatically indexes new events every 10mins.
134+
### 4️⃣ Access the app
106135

136+
```
137+
http://localhost:8000
138+
```
107139

140+
---
108141

109-
### 🖥️ Frontend – Usage
110-
The frontend fetches events
111-
Pagination is fully managed on the client side.
142+
## 🧪 Testing Locally
112143

144+
```bash
145+
# Check the UI
146+
http://localhost:8000
113147

148+
# Check events API
149+
http://localhost:8000/events
114150

115-
### 🔧 API Endpoints
116-
| Method | Endpoint | Description |
117-
|--------|--------------------------|-----------------------------------|
118-
| GET | `/` | Frontend homepage |
119-
| GET | `/events?page=X&size=Y` | Paginated events |
120-
| GET | `/indexing` | Manually trigger event indexing |
121-
| GET | `/stream` | Server-sent events (debug) |
151+
# Check health
152+
http://localhost:8000/health
122153

154+
# Manually trigger reindex
155+
http://localhost:8000/reindex
156+
```
123157

158+
---
124159

160+
## 🔧 How Transport Works
125161

126-
### 🧪 Testing locally
127-
```
128-
Run FastAPI
129-
Call: http://localhost:8000/events
130-
If you see JSON, everything works.
131-
Use the frontend to browse events visually.
132-
```
162+
At indexing time, each event's coordinates are used to query a **KDTree** built from all bus and tramway stop coordinates. The nearest lines (within 0.5km) are stored directly on the event document in Elasticsearch.
133163

164+
This means `/transport/{event_id}` is just a simple document read — no spatial computation happens at request time.
134165

166+
---
135167

168+
## 📝 Future Improvements
136169

137-
### 📝 Future Improvements
138-
```
139-
1️⃣ Add categories & filters
140-
2️⃣ Add search by city / date
141-
3️⃣ Add infinite scrolling
142-
4️⃣ Add AI-based event deduplication
143-
```
170+
1. Add infinite scrolling to the frontend
171+
2. Store favorites in Elasticsearch instead of in-memory
172+
3. Add AI-based event deduplication
173+
4. Add user authentication
174+
5. Deploy to cloud with security enabled

elastic/__init__.py

Whitespace-only changes.
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
from elasticsearch import Elasticsearch, helpers
1+
from elasticsearch import helpers
22
from into_db.connection import get_db_events
33
from scrape.casaevents import get_casa_events
44
from scrape.eventbrit import get_event_brit
55
from scrape.eventsma import get_events_ma
66
from scrape.guichet import get_guichet
77
import hashlib
8-
from elastic.elastic_client import get_es_client
8+
from elastic_client import get_es_client
99
import logging
1010
import os
1111
from concurrent.futures import ThreadPoolExecutor, as_completed
12+
from transport.bus import get_transport_info
1213

1314

1415

@@ -21,7 +22,6 @@
2122

2223

2324
def normalize_coordinates(coords):
24-
"""Safely normalize coordinates to [lon, lat] list or return empty list."""
2525
if coords is None:
2626
return []
2727
if isinstance(coords, list):
@@ -35,7 +35,6 @@ def normalize_coordinates(coords):
3535

3636
def indexing():
3737
try:
38-
logger.info("starting the indexing process ------")
3938
logger.info("testing Elasticsearch connection--------")
4039
if not es.ping():
4140
logger.error("cant connect to Elasticsearch !!!")
@@ -77,6 +76,7 @@ def indexing():
7776
doc_id = hashlib.md5(
7877
(str(event.get("name", "")) + str(event.get("date", "")) + str(event.get("city", ""))).encode()
7978
).hexdigest()
79+
transport = get_transport_info(normalize_coordinates(event.get("coordinates")))
8080

8181
doc = {
8282
"id": event.get("id", ""),
@@ -87,6 +87,8 @@ def indexing():
8787
"city": event.get("city", ""),
8888
"place": event.get("place", ""),
8989
"coordinates": normalize_coordinates(event.get("coordinates")),
90+
"bus_lines": transport.get("bus_lines", []),
91+
"tramway_lines": transport.get("tramway_lines", []),
9092
"location": event.get("city", "") + " " + event.get("place", ""),
9193
"producer": event.get("producer", ""),
9294
"category": event.get("category", []),

into_db/connection.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)