Javis OS
Javis OS는 기업가를 돕는 에이전시 AI로, 업무를 지원하고 함께 성장합니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Herramienta de prospección comercial en Flask: encuentra, investiga y organiza empresas candidatas a servicios de cargue y descargue en Bogotá y municipios cercanos.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Herramienta de prospección comercial para encontrar, investigar y gestionar empresas ubicadas en Bogotá y municipios cercanos (Funza, Mosquera, Chía, Cajicá, Cota y Madrid) que puedan necesitar servicios de cargue y descargue de mercancías: bodegas, centros de distribución, empresas logísticas, distribuidoras, mayoristas, importadoras, comercializadoras, empresas de alimentos/bebidas, industriales, etc.README 전문 보기 ↗
Herramienta de prospección comercial para encontrar, investigar y gestionar empresas ubicadas en Bogotá y municipios cercanos (Funza, Mosquera, Chía, Cajicá, Cota y Madrid) que puedan necesitar servicios de cargue y descargue de mercancías: bodegas, centros de distribución, empresas logísticas, distribuidoras, mayoristas, importadoras, comercializadoras, empresas de alimentos/bebidas, industriales, etc.
La aplicación no contacta empresas automáticamente ni hace spam. Encuentra empresas en varias fuentes públicas, investiga y completa sus datos de contacto, elimina duplicados/cadenas, y da una herramienta ordenada para hacerles seguimiento comercial manual. El envío final de cualquier mensaje siempre lo hace la persona, desde su propio correo o WhatsApp.
La primera versión solo usaba OpenStreetMap (Overpass API): encontraba muchas empresas, pero casi ninguna tenía teléfono, email o sitio web, y cadenas grandes (Carulla, UNO, etc.) aparecían decenas de veces como si cada sucursal fuera una empresa distinta — cantidad sin calidad. Esta versión convierte el sistema de "buscador de empresas" a "buscador + investigador de empresas": combina varias fuentes, elimina duplicados/cadenas, y completa los datos de contacto que faltan antes de mostrar el resultado.
git clone https://github.com/Mundanesleet/Protector.git
cd Protector
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # Linux/macOS
pip install -r requirements.txt
copy .env.example .env # Windows
# cp .env.example .env # Linux/macOS
python app.py
La aplicación queda disponible en http://127.0.0.1:5000/. La base de datos SQLite se crea automáticamente (instance/prospector.db) en el primer arranque; si ya existía de una versión anterior, las columnas nuevas se agregan solas sin perder datos (ver "Migraciones" más abajo).
Sin configurar ninguna key, la aplicación funciona igual usando solo OpenStreetMap — Google Places y Brave Search son mejoras opcionales.
.env)| Variable | Descripción | Obligatoria |
|---|---|---|
SECRET_KEY | Clave de Flask | No (tiene default de desarrollo) |
DATABASE_URL | URI de SQLAlchemy | No |
OVERPASS_API_URL / OVERPASS_TIMEOUT | Overpass API | No |
GOOGLE_MAPS_API_KEY | Habilita Google Places como fuente de búsqueda | No — sin ella, solo se usa Overpass |
BRAVE_SEARCH_API_KEY | Habilita la investigación con Brave Search | No — sin ella, el botón "Investigar" avisa que falta configurar |
Cómo obtener GOOGLE_MAPS_API_KEY: consola de Google Cloud → crear proyecto → activar facturación (obligatorio aunque el uso quede en $0 dentro del nivel gratis) → habilitar "Places API (New)" → Credentials → Create API Key.
Cómo obtener BRAVE_SEARCH_API_KEY: api-dashboard.search.brave.com → crear cuenta → nueva API key (no requiere tarjeta para el nivel gratis).
protector/
├── app.py # Application factory de Flask + migraciones ligeras
├── config.py # Configuracion via variables de entorno
├── database/__init__.py # Instancia SQLAlchemy (db) + ensure_schema_migrations()
├── models/ # Company, Prospect, Note, Location, Source
├── routes/ # Blueprints: controladores delgados
│ ├── main_routes.py # Vista del dashboard
│ ├── company_routes.py # /api/search, /api/companies*
│ ├── prospect_routes.py # /api/prospects*
│ └── api_routes.py # /api/stats, /api/meta
├── services/
│ ├── data_sources/
│ │ ├── overpass_service.py # Busqueda por tags de OpenStreetMap (gratis)
│ │ ├── google_places_service.py # Busqueda por intencion comercial (Google Places)
│ │ └── brave_search_service.py # Investigacion web (sitio oficial, Facebook, LinkedIn)
│ ├── company_service.py # Dedup/cadenas, filtros, normalizacion, export a Excel
│ ├── company_enrichment_service.py # Orquesta Brave + contact_finder por empresa
│ ├── contact_finder_service.py # Extrae email/WhatsApp de la web propia de una empresa
│ └── message_template_service.py # Mensaje sugerido y editable por categoria
├── templates/ # Jinja2 + Bootstrap 5
└── static/
├── css/style.css
└── js/{app,dashboard,map}.js
Por qué esta separación:
services/data_sources/ aísla cada fuente de búsqueda externa. Las tres exponen la misma forma de resultado (dict con name, address, phone, website, source, source_id, etc.), así que company_service.save_companies() no necesita saber de dónde vino cada empresa.company_enrichment_service.py está separado de company_service.py porque orquesta otro servicio (brave_search_service) más el ya existente contact_finder_service — es lógica de composición, no de persistencia.models/: Company son los datos de la empresa; Location son sucursales legítimas de una empresa con varias sedes reales (no cadenas grandes, esas se excluyen); Source guarda de dónde vino cada dato individual (campo + tipo de fuente + URL + fecha); Prospect/Note son la gestión comercial, separada a propósito de los datos de la empresa.SQLite/db.create_all() crea tablas nuevas pero no agrega columnas a una tabla que ya existe con datos. database/ensure_schema_migrations() corre ALTER TABLE para las columnas nuevas la primera vez que hacen falta, y se llama automáticamente al arrancar la app — no hay que hacer nada manual, y los datos existentes nunca se borran.
Company tiene una restricción única (source, source_id); sin eso, se identifica por nombre + dirección + coordenadas.+57 XXXXXXXXXX) para que "+57 601 1234567", "(601) 1234567" y "6011234567" no se traten como datos distintos.POST /api/search acepta sources: ["overpass", "google_places"]. Si se piden varias, se corren todas y se combinan los resultados; si una falla (incluido "no configurada"), se reporta como advertencia sin tumbar la búsqueda completa mientras al menos una fuente funcione.
website está en "Pro" (5.000 gratis/mes). El teléfono se consigue igual, gratis, desde la propia web de la empresa.Desde la ficha de cada empresa:
Source con su procedencia. No sobreescribe datos ya confirmados, y no vuelve a gastar cuota de Brave si la misma empresa ya se investigó en las últimas 24 horas.Se eligió bajo demanda por empresa (no un proceso automático en lote) para que el usuario controle exactamente cuánta cuota gratuita de Brave Search se gasta, y porque enviar mensajes o investigar cientos de empresas automáticamente sin supervisión iba en contra del alcance original del proyecto (no spam).
Un borrador editable por categoría, con botones Abrir en correo/Abrir en WhatsApp que abren tu propio cliente con el destinatario y mensaje ya cargados — el clic final de enviar siempre lo das tú.
SQLite ya es gratis (es un archivo local, igual que sería un Excel) y evita los problemas reales de usar una hoja de cálculo como almacenamiento de una app web: bloqueo del archivo si lo tienes abierto mientras la app escribe, y tener que reimplementar a mano la deduplicación y las relaciones que aquí ya resuelve el ORM. El botón Exportar a Excel genera un .xlsx bajo demanda como respaldo portable, sin ese riesgo.
| Método | Ruta | Descripción |
|---|---|---|
POST | /api/search | Busca empresas (zones, categories, sources: overpass/google_places) y las guarda sin duplicar |
GET | /api/companies | Lista empresas (filtros: city, category, status, q, has_phone, has_website) |
GET | /api/companies/export | Descarga en .xlsx las empresas (mismos filtros que arriba) |
GET | /api/companies/<id> | Detalle de una empresa (incluye prospecto, notas, fuentes por dato y mensaje sugerido) |
POST | /api/companies/<id>/find-contact | Busca email/WhatsApp en la web ya conocida de la empresa |
POST | /api/companies/<id>/enrich | Investiga con Brave Search + web propia (force: true para saltar el enfriamiento de 24h) |
POST | /api/companies/cleanup-chains | Limpia retroactivamente cadenas/franquicias ya guardadas |
PUT | /api/companies/<id> | Edición manual de una empresa |
POST | /api/companies/<id>/save | Guarda una empresa como prospecto (idempotente) |
PUT | /api/prospects/<id> | Cambia el estado comercial de un prospecto |
POST | /api/prospects/<id>/notes | Agrega una nota comercial |
GET | /api/stats | Estadísticas para las tarjetas del dashboard |
GET | /api/meta | Zonas, categorías y estados disponibles (usado por el frontend) |
Todas las respuestas son JSON. Los errores nunca exponen detalles técnicos al usuario ({"error": "mensaje amigable"}); el detalle técnico queda en el log del servidor. Ninguna API key llega nunca al frontend — todas las llamadas externas se hacen desde el backend.
| Fuente | Nivel gratis | Costo después |
|---|---|---|
| Overpass API (OpenStreetMap) | Ilimitado, pero es un recurso público compartido: puede responder lento o con error en horas de alta demanda | Gratis siempre |
| Google Places Text Search (campos usados: nombre, dirección, ubicación, website — nivel "Pro") | 5.000 solicitudes/mes | US$32 por cada 1.000 adicionales |
| Brave Search API | US$5 en crédito automático/mes (≈1.000 búsquedas) | US$5 por cada 1.000 adicionales |
Recomendaciones para no superar la cuota:
google_places_service.py ya evita relanzar la misma consulta dentro de 6 horas.No implementado todavía (a propósito): login/registro, pagos, envío automático de WhatsApp/email, scraping agresivo de redes sociales, IA generativa, Docker.