Date : 20/12/2025 04:37 Status : En attente de validation Objectif : Mettre en place le collector NeedFinder avec workflow complet
Setup du projet NeedFinder Collector avec :
# Sur gitlab.local
Nom: needfinder
Branches: main + develop
Visibilité: Private
needfinder/
├── package.json
├── tsconfig.json
├── Dockerfile
├── docker-compose.yml
├── conf.prod.gouroubleu.yml
├── conf.dev.gouroubleu.yml
├── src/
│ ├── index.ts # Entry point API
│ ├── collectors/
│ │ ├── reddit.ts # Collector Reddit
│ │ └── hackernews.ts # Collector HN
│ ├── db/
│ │ └── schema.sql # Tables Supabase
│ ├── services/
│ │ └── analyzer.ts # Analyse IA (futur)
│ └── cron/
│ └── scheduler.ts # Cron jobs
└── .env.example
Principe : Chaque projet a son propre schéma PostgreSQL + son propre user avec accès limité.
-- ============================================
-- CRÉATION SCHÉMA DÉDIÉ
-- ============================================
-- Créer le schéma
CREATE SCHEMA IF NOT EXISTS needfinder;
-- Créer un rôle dédié pour ce projet
CREATE ROLE needfinder_service WITH LOGIN PASSWORD 'xxx';
-- Donner accès uniquement au schéma needfinder
GRANT USAGE ON SCHEMA needfinder TO needfinder_service;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA needfinder TO needfinder_service;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA needfinder TO needfinder_service;
ALTER DEFAULT PRIVILEGES IN SCHEMA needfinder GRANT ALL ON TABLES TO needfinder_service;
ALTER DEFAULT PRIVILEGES IN SCHEMA needfinder GRANT ALL ON SEQUENCES TO needfinder_service;
-- ============================================
-- TABLES DANS LE SCHÉMA NEEDFINDER
-- ============================================
-- Sources de données
CREATE TABLE needfinder.sources (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(100) NOT NULL,
is_active BOOLEAN DEFAULT true,
last_collected_at TIMESTAMPTZ
);
-- Posts collectés
CREATE TABLE needfinder.posts (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
source_id UUID REFERENCES needfinder.sources(id),
external_id VARCHAR(200) UNIQUE,
external_url TEXT,
title TEXT,
content TEXT,
author VARCHAR(200),
subreddit VARCHAR(100),
score INTEGER,
comment_count INTEGER,
posted_at TIMESTAMPTZ,
collected_at TIMESTAMPTZ DEFAULT NOW(),
is_processed BOOLEAN DEFAULT false
);
-- Besoins détectés
CREATE TABLE needfinder.needs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
need_statement TEXT NOT NULL,
category VARCHAR(100),
mention_count INTEGER DEFAULT 1,
first_seen_at TIMESTAMPTZ DEFAULT NOW(),
last_seen_at TIMESTAMPTZ DEFAULT NOW(),
opportunity_score INTEGER DEFAULT 0
);
-- Lien posts → needs
CREATE TABLE needfinder.mentions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
need_id UUID REFERENCES needfinder.needs(id),
post_id UUID REFERENCES needfinder.posts(id),
extracted_text TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(need_id, post_id)
);
-- Logs de collection
CREATE TABLE needfinder.collection_logs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
source VARCHAR(50),
status VARCHAR(20),
posts_collected INTEGER DEFAULT 0,
error_message TEXT,
started_at TIMESTAMPTZ DEFAULT NOW(),
completed_at TIMESTAMPTZ
);
-- Index
CREATE INDEX idx_posts_source ON needfinder.posts(source_id, posted_at DESC);
CREATE INDEX idx_posts_processed ON needfinder.posts(is_processed) WHERE is_processed = false;
CREATE INDEX idx_needs_score ON needfinder.needs(opportunity_score DESC);
# Dans /mnt/stock_36to/data/33800-stack/docker/secrets/dev.env
# Section: NEEDFINDER
NEEDFINDER_DB_HOST=192.168.1.51
NEEDFINDER_DB_PORT=5432
NEEDFINDER_DB_NAME=postgres
NEEDFINDER_DB_SCHEMA=needfinder
NEEDFINDER_DB_USER=needfinder_service
NEEDFINDER_DB_PASSWORD=<généré>
NEEDFINDER_DB_URL=postgresql://needfinder_service:<password>@192.168.1.51:5432/postgres?schema=needfinder
| Composant | Techno |
|---|---|
| Runtime | Bun |
| API | Elysia |
| DB | Supabase DEV |
| Cron | Bun cron / node-cron |
| Container | Docker |
| Propriété | Valeur |
|---|---|
| Container | needfinder-collector-dev |
| Port | 5200 |
| Image | needfinder-collector:dev |
| Restart | always |
| Cron | Toutes les 6h |
# needfinder-api-dev.33800.nowhere84.com → dev-portainer:5200
server {
listen 443 ssl http2;
server_name needfinder-api-dev.33800.nowhere84.com;
ssl_certificate /etc/letsencrypt/live/33800.nowhere84.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/33800.nowhere84.com/privkey.pem;
location / {
proxy_pass http://192.168.1.51:5200;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
GET /health # Health check
GET /api/stats # Stats collection
POST /api/collect/reddit # Trigger collecte Reddit
POST /api/collect/hn # Trigger collecte HN
GET /api/posts # Liste posts collectés
GET /api/needs # Liste besoins détectés (futur)
# .env.dev
SUPABASE_URL=https://supabase-api-dev.33800.nowhere84.com
SUPABASE_KEY=<service_role_key>
REDDIT_USER_AGENT=NeedFinder/1.0
CRON_INTERVAL=6h
PORT=5200
needfinder ✅