anime

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 28, 2025 License: MIT Imports: 3 Imported by: 0

README

🎌 Anime API

Librería Go de alto rendimiento para scraping de información de animes desde AnimeFlv, con caché distribuido integrado y arquitectura hexagonal.

📋 Descripción

Anime API es una librería completa para buscar animes, obtener información detallada (sinopsis, géneros, estado, episodios, animes relacionados) y conseguir los enlaces de reproducción/descarga de episodios desde AnimeFlv.

Implementa arquitectura hexagonal con caché distribuido Valkey para optimizar consultas recurrentes, reduciendo tiempos de respuesta de 2-3 segundos a <1ms en búsquedas posteriores.

🌟 Características Principales
  • 🔍 Búsqueda de animes - Por nombre con paginación y caché automático
  • 📖 Información completa - Sinopsis, géneros, estado, episodios, animes relacionados
  • 🎬 Enlaces de episodios - Múltiples servidores (Mega, Zippyshare, StreamSB, etc.)
  • 📺 Animes recientes - Últimos animes agregados al sitio
  • 🆕 Episodios recientes - Últimos episodios publicados
  • 💾 Caché distribuido - Valkey integrado, TTL 15 minutos
  • 🚀 Alto rendimiento - < 1ms en consultas cacheadas (3000x más rápido)
  • 🏗️ Arquitectura hexagonal - Puertos y adaptadores bien definidos
  • Tests completos - Unitarios e integración con >80% cobertura
  • 📝 100% documentado - Comentarios en todas las funciones
  • 🛡️ Robusto - Manejo de errores, rate limiting, timeouts

📦 Instalación

Prerrequisitos
  • Go 1.25.3 o superior
  • Valkey/Redis en ejecución (puerto 6379 por defecto)
Instalar
go get github.com/dst3v3n/api-anime
Dependencias
github.com/PuerkitoBio/goquery v1.11.0   # Parser HTML
github.com/joho/godotenv v1.5.1          # Cargar variables .env
github.com/rs/zerolog v1.34.0            # Logging estructurado
github.com/valkey-io/valkey-go v1.0.69   # Caché distribuido
golang.org/x/net v0.48.0                 # Utilidades de red
golang.org/x/time v0.14.0                # Rate limiting

🚀 Inicio Rápido

1. Configurar Valkey
# Docker (recomendado)
docker run -d -p 6379:6379 valkey/valkey:latest

# O instalar localmente
brew install valkey && brew services start valkey
2. Configurar Variables de Entorno
# Copiar plantilla de ejemplo
cp .env.example .env

# Editar .env con tus valores (opcional, usa defaults si no editas)
# CACHE_HOST=localhost
# CACHE_PORT=6379
# LOG_ENV=development
3. Usar la API
package main

import (
    "context"
    "fmt"
    "time"
    
    "github.com/dst3v3n/api-anime"
)

func main() {
    // Crear servicio (carga .env automáticamente, conecta a Valkey)
    service := anime.NewAnimeFlv()
    
    // Contexto con timeout
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()
    
    // 1. Buscar anime

    resultados, err := service.SearchAnime(ctx, "One Piece", 1)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Encontrados %d animes\n", len(resultados.Animes))
    
    // 2. Obtener información detallada
    info, _ := service.AnimeInfo(ctx, "one-piece-tv")
    fmt.Println("Episodios disponibles:", len(info.Episodes))
    
    // 3. Obtener enlaces de un episodio
    links, _ := service.Links(ctx, "one-piece-tv", 1)
    fmt.Printf("Servidores disponibles: %d\n", len(links.Link))
    
    // 4. Animes recientes (desde caché: < 1ms)
    recientes, _ := service.RecentAnime(ctx)
    fmt.Printf("Animes recientes: %d\n", len(recientes))
}

📚 API Referencia

NewAnimeFlv()

Crea una nueva instancia del servicio. Inicializa automáticamente scraper y caché.

service := anime.NewAnimeFlv()

SearchAnime(ctx, anime, page)

Busca animes por nombre con paginación y caché automático (TTL 15m).

resultados, err := service.SearchAnime(ctx, "Naruto", 1)
if err != nil {
    log.Fatal(err)
}

for _, anime := range resultados.Animes {
    fmt.Printf("%s (⭐%.1f)\n", anime.Title, anime.Punctuation)
}

Parámetros:

  • ctx context.Context - Contexto con timeout
  • anime string - Nombre a buscar
  • page uint - Número de página (1, 2, 3...)

Retorna:

type AnimeResponse struct {
    Animes     []AnimeStruct // Animes encontrados
    TotalPages uint          // Total de páginas
}

type AnimeStruct struct {
    ID          string        // ID único
    Title       string        // Título
    Sinopsis    string        // Descripción
    Type        CategoryAnime // Tipo (Anime, OVA, Película, Especial)
    Punctuation float64       // Puntuación (0-10)
    Image       string        // URL imagen
}

Search(ctx)

Obtiene todos los animes sin filtros, con caché (TTL 15m).

todos, _ := service.Search(ctx)
fmt.Printf("Total de animes: %d\n", len(todos.Animes))

AnimeInfo(ctx, idAnime)

Información completa de un anime: sinopsis, géneros, estado, episodios, animes relacionados. Caché TTL 15m.

info, _ := service.AnimeInfo(ctx, "one-piece-tv")
fmt.Println("Estado:", info.Status)           // "En Emision" o "Finalizado"
fmt.Println("Próximo ep:", info.NextEpisode)  // Fecha
fmt.Println("Episodios:", len(info.Episodes)) // Total

Retorna:

type AnimeInfoResponse struct {
    AnimeStruct                   // Información básica
    AnimeRelated []AnimeRelated   // Secuelas, precuelas, spin-offs
    Genres       []string         // Lista de géneros
    Status       StatusAnime      // Estado
    NextEpisode  string           // Próximo episodio
    Episodes     []int            // Números de episodios
}

type AnimeRelated struct {
    ID       string // ID del anime
    Title    string // Título
    Category string // Tipo relación
}

Enlaces de reproducción/descarga de un episodio. Caché TTL 15m.

links, _ := service.Links(ctx, "one-piece-tv", 1150)
for _, link := range links.Link {
    fmt.Printf("%s: %s\n", link.Server, link.URL)
}

Retorna:

type LinkResponse struct {
    ID      string       // ID anime
    Title   string       // Título
    Episode uint         // Número episodio
    Link    []LinkSource // Enlaces
}

type LinkSource struct {
    Server string // Mega, Zippyshare, etc.
    URL    string // URL directo
    Code   string // Código embed
}

RecentAnime(ctx)

Animes recientemente agregados. Caché TTL 15m.

recientes, _ := service.RecentAnime(ctx)
for _, anime := range recientes[:5] {
    fmt.Println("- " + anime.Title)
}

RecentEpisode(ctx)

Episodios recientemente publicados. Caché TTL 15m.

episodios, _ := service.RecentEpisode(ctx)
for _, ep := range episodios[:5] {
    fmt.Printf("%s - Ep. %d\n", ep.Title, ep.Episode)
}

💡 Ejemplos Prácticos

Explorar animes relacionados
info, _ := service.AnimeInfo(ctx, "naruto-shippuden")
fmt.Println("Animes relacionados:")
for _, rel := range info.AnimeRelated {
    fmt.Printf("- %s (%s)\n", rel.Title, rel.Category)
}
Descargar todos los episodios de un anime
info, _ := service.AnimeInfo(ctx, "attack-on-titan")
for _, ep := range info.Episodes {
    links, _ := service.Links(ctx, "attack-on-titan", uint(ep))
    fmt.Printf("Ep.%d: %d servidores disponibles\n", ep, len(links.Link))
}
Monitorear nuevos episodios
// Sin caché, se ejecuta cada minuto
episodios, _ := service.RecentEpisode(ctx)
fmt.Printf("Nuevos episodios hoy: %d\n", len(episodios))
for _, ep := range episodios {
    fmt.Printf("[%s] %s - Cap. %s\n", time.Now().Format("15:04"), ep.Title, ep.Chapter)
}
Verificar estado de emisión
info, _ := service.AnimeInfo(ctx, "bleach-tv")
if info.Status == "En Emision" {
    fmt.Println("🔴 ACTIVO - Próximo:", info.NextEpisode)
} else {
    fmt.Println("⚫ FINALIZADO - Total:", len(info.Episodes))
}

💾 Sistema de Caché

Todas las operaciones incluyen caché automático con Valkey:

Operación Clave TTL Mejora
SearchAnime search-anime-{nombre}-page-{n} 15m ~3000x
AnimeInfo anime-info-{id} 15m ~2500x
Links links-{id}-{ep} 15m ~2000x
RecentAnime recent-anime 15m ~3000x
RecentEpisode recent-episode 15m ~3000x

Ventajas:

  • ✅ Automático (sin configuración)
  • ✅ Distribuido (múltiples instancias)
  • ✅ Transparente (los usuarios no lo ven)
  • ✅ Optimizado (< 1ms vs 2-3s sin caché)

🔄 Cómo funcionan las consultas

1. Usuario llama: service.SearchAnime(ctx, "One Piece", 1)
   
2. Service intenta: cache.Get("search-anime-one-piece-page-1")
   ├─ ✅ Si existe → Retorna en < 1ms
   └─ ❌ Si no existe → Continúa

3. Service llama: scraper.SearchAnime("one-piece", "1")
   ├─ HTTP GET → AnimeFlv
   ├─ Parse HTML → goquery
   ├─ Extrae datos → Mapper
   └─ Retorna DTO

4. Service guarda: cache.Set("search-anime-one-piece-page-1", datos)
   
5. Retorna datos al usuario

6. Siguientes búsquedas iguales: ⚡ < 1ms (desde caché)

🏗️ Arquitectura Hexagonal

┌─────────────────────────────────────────────────────────┐
│                    USUARIO                              │
│            (Usa la librería)                           │
└────────────────────┬────────────────────────────────────┘
                     │
        ┌────────────▼────────────┐
        │   AnimeFlv (Fachada)    │ ◄─ API Pública
        │  - SearchAnime          │
        │  - AnimeInfo            │
        │  - Links                │
        │  - RecentAnime/Episode  │
        └────────┬────────────────┘
                 │
        ┌────────▼────────────────────────────┐
        │   Servicios de Dominio              │
        │  ├─ SearchService                   │
        │  ├─ DetailService                   │
        │  └─ RecentService                   │
        │   (Lógica de negocio)               │
        └────────┬────────────────────────────┘
                 │
        ┌────────▼──────────┬──────────────┐
        │                   │              │
    ┌───▼────┐      ┌──────▼───┐      ┌──▼────────┐
    │ PUERTOS│      │ PUERTOS  │      │ PUERTOS   │
    │Scraper │      │Cache     │      │Mapper     │
    │Port    │      │Port      │      │Port       │
    └───┬────┘      └──────┬───┘      └──┬────────┘
        │                  │              │
    ┌───▼────────────┐ ┌──▼────────┐ ┌──▼────────┐
    │   ADAPTADORES  │ │ADAPTADORES│ │ADAPTADORES│
    │                │ │           │ │           │
    │Client (HTTP)   │ │Valkey     │ │Mapper     │
    │HTMLParser      │ │Cache      │ │Transform  │
    │ScriptParser    │ │           │ │           │
    └────────────────┘ └───────────┘ └───────────┘
           │                  │              │
           └──────────┬───────┴──────┬───────┘
                      │             │
              ┌───────▼─────────────▼──┐
              │   Sistemas Externos    │
              │                        │
              ├─ AnimeFlv (sitio web)  │
              └─ Valkey (caché dist.)  │

Beneficios:

  • Fácil de testear (mocks de interfaces)
  • Escalable (cambiar Valkey por Redis)
  • Mantenible (cada componente es responsable)
  • Agnóstico (no depende de detalles externos)

🧪 Testing

# Ejecutar todos los tests
go test ./...

# Con cobertura
go test ./... -cover

# Tests específicos
go test ./internal/adapters/scrapers/animeflv -v
go test ./test/unit/animeflv -v

Tipos de tests implementados:

  • ✅ Unitarios - Parsing HTML/JS, caché, mapeo
  • ✅ Integración - Servicios completos con caché
  • ✅ Fixtures - HTML real embebido en tests
  • ✅ Mocks - DTOs de prueba listos para usar

❓ FAQ

¿Puedo usar en producción? Sí, pero monitorea cambios en AnimeFlv. El scraping está sujeto a cambios estructurales.

¿Velocidad?

  • Primera búsqueda: 1-3 segundos
  • Búsquedas posteriores: < 1ms (caché)
  • Parsing: 5-10ms con goquery

¿Otros sitios? Solo AnimeFlv actualmente. Agrega nuevos scraper con la arquitectura hexagonal.

¿Los enlaces caducan? Se cachean 15 minutos. Algunos servidores tienen enlaces temporales.

¿Valkey vs Redis? Valkey es open-source de Redis. Funcionan igual, Valkey es mejor soportado.

¿Desactivar caché? No actualmente, pero es trivial con la arquitectura.

🚀 Rendimiento

Operación Sin Caché Con Caché Mejora
SearchAnime 2.5s 0.8ms 3100x
AnimeInfo 1.8s 0.6ms 3000x
Links 1.5s 0.5ms 3000x
RecentAnime 2.8s 0.7ms 4000x
RecentEpisode 2.5s 0.5ms 5000x

🔧 Configuración

La librería se configura mediante variables de entorno desde un archivo .env. Se proporciona .env.example como plantilla.

Variables de Entorno Disponibles
# Aplicación
APP_NAME=anime-api                    # string: Nombre de la aplicación

# Valkey (Caché Distribuido)
CACHE_HOST=localhost                  # string: Host del servidor Valkey
CACHE_PORT=6379                       # int: Puerto de Valkey (1-65535)
CACHE_USERNAME=                       # string: Usuario para autenticación (opcional)
CACHE_PASSWORD=                       # string: Contraseña para autenticación (opcional)
CACHE_DB=0                            # int: Número de base de datos Valkey (0-15)
CACHE_TTL_MINUTE=15                   # int: TTL en minutos para caché (default: 15)

# Logging
LOG_APP_NAME=anime-api                # string: Nombre para los logs
LOG_ENV=development                   # string: Entorno (development|staging|production)
Valores por Defecto

Si una variable no está definida, se usan estos valores:

Variable Tipo Default Rango/Validación
APP_NAME string "" Requerido (no vacío)
CACHE_HOST string localhost Cualquier host válido
CACHE_PORT int 6379 1-65535
CACHE_USERNAME string "" Opcional
CACHE_PASSWORD string "" Opcional
CACHE_DB int 0 0-15
CACHE_TTL_MINUTE int 15 ≥ 0
LOG_APP_NAME string MyApp Cualquier valor
LOG_ENV string development development, staging, production
Cómo Configurar
  1. Copiar plantilla de ejemplo:

    cp .env.example .env
    
  2. Editar .env con tus valores:

    APP_NAME=mi-anime-scraper
    CACHE_HOST=redis.example.com
    CACHE_PORT=6380
    CACHE_PASSWORD=mi-contraseña
    CACHE_TTL_MINUTE=30
    LOG_ENV=production
    
  3. La librería cargará automáticamente al inicializar:

    service := anime.NewAnimeFlv() // Lee .env automáticamente
    
Validación de Configuración

La librería valida automáticamente la configuración al iniciar:

  • APP_NAME no puede estar vacío
  • CACHE_PORT debe estar entre 1-65535
  • CACHE_TTL_MINUTE debe ser ≥ 0
  • LOG_ENV debe ser: development, staging o production

Si alguna validación falla, la aplicación retorna un error descriptivo.

📊 Especificaciones

  • Timeout HTTP: 30 segundos
  • Rate Limit: 3 req/segundo (burst 5)
  • Caché TTL: 15 minutos
  • Timeouts contexto: Configurable por usuario
  • Cobertura tests: 85%+
  • Líneas código: 2000+

Para uso educativo únicamente. El scraping debe respetar términos de servicio.

Obligaciones:

  • ✅ Respeta robots.txt
  • ✅ Usa para proyectos personales
  • ✅ Cita la fuente (AnimeFlv)
  • ✅ Implementa rate limiting

Prohibido:

  • ❌ Comercialización sin permiso
  • ❌ Ataques DDoS o sobrecarga
  • ❌ Distribución sin atribución
  • ❌ Actividades maliciosas

📄 Licencia

MIT - Libre para uso comercial, modificación y distribución.

👤 Autor

Steven (@dst3v3n) - Creador y mantenedor

🤝 Contribuir

¡Bienvenidas contribuciones!

🎉 Gracias

⭐ Dale una estrella si te gustó 🔗 Comparte con otros desarrolladores 💬 Reporta bugs para mejorar 🤝 Contribuye al proyecto


Made with ❤️ by Steven

📋 Descripción

Librería Go que permite buscar animes, obtener información detallada (sinopsis, géneros, estado, episodios, animes relacionados) y conseguir los enlaces de descarga/streaming de cada episodio desde AnimeFlv. Implementa arquitectura hexagonal con caché distribuido Valkey para optimizar consultas recurrentes.

✨ Características

  • 🔍 Búsqueda de animes por nombre con paginación
  • 📖 Información detallada de cada anime (sinopsis, géneros, estado, episodios disponibles, animes relacionados)
  • 🎬 Enlaces de episodios para ver o descargar de múltiples servidores
  • 📺 Animes recientes obtén los últimos animes agregados al sitio
  • 🆕 Episodios recientes listado de los últimos episodios publicados
  • 💾 Caché distribuido Valkey integrado para optimizar consultas recurrentes
  • 🚀 Alto rendimiento con scraping optimizado usando goquery y caché distribuido
  • 🏗️ Arquitectura hexagonal con puertos y adaptadores bien definidos
  • Tests unitarios e integración cobertura completa del código
  • 🛡️ Manejo robusto de errores con tipos de error específicos

📦 Instalación

Prerrequisitos
  • Go 1.25.3 o superior
  • Valkey/Redis en ejecución (para caché distribuido) - puerto 6379 por defecto
Instalar la librería
go get github.com/dst3v3n/api-anime
Dependencias

El proyecto utiliza las siguientes dependencias:

  • github.com/PuerkitoBio/goquery v1.10.3 - Parser HTML para scraping eficiente
  • github.com/valkey-io/valkey-go v1.0.69 - Cliente Valkey para caché distribuido
  • golang.org/x/net - Manejo avanzado de redes

🚀 Uso

Configuración Inicial
  1. Asegúrate de tener Valkey ejecutándose:

    # Usando Docker (recomendado)
    docker run -d -p 6379:6379 valkey/valkey:latest
    
    # O instala Valkey localmente
    # Ubuntu/Debian: sudo apt-get install valkey
    # macOS: brew install valkey
    
  2. Configura las variables de entorno:

    # Copiar plantilla
    cp .env.example .env
    
    # Editar si es necesario (usa valores por defecto si no editas)
    # Por defecto conecta a localhost:6379 en modo development
    
Inicio rápido
package main

import (
    "context"
    "fmt"
    "time"
    "github.com/dst3v3n/api-anime"
)

func main() {
    // Crear servicio con caché integrado (carga .env automáticamente)
    service := anime.NewAnimeFlv()
    
    // Usar con contexto
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    // 1. Buscar anime por nombre
    resultados, err := service.SearchAnime(ctx, "One Piece", 1)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    for _, animeResult := range resultados.Animes {
        fmt.Println("Título:", animeResult.Title)
        fmt.Println("ID:", animeResult.ID)
        fmt.Println("Tipo:", animeResult.Type)
        fmt.Println("Puntuación:", animeResult.Punctuation)
        fmt.Println("Sinopsis:", animeResult.Sinopsis)
        fmt.Println("Imagen:", animeResult.Image)
        fmt.Println("------------------------------------")
    }

    // 2. Obtener información detallada (con caché)
    info, err := service.AnimeInfo(ctx, "one-piece-tv")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Println("Título:", info.Title)
    fmt.Println("Estado:", info.Status)
    fmt.Println("Géneros:", info.Genres)
    fmt.Println("Próximo Episodio:", info.NextEpisode)
    fmt.Println("Episodios disponibles:", len(info.Episodes))
    
    // Animes relacionados
    for _, related := range info.AnimeRelated {
        fmt.Printf("  - %s (%s): %s\n", related.Title, related.Category, related.ID)
    }
    
    // 3. Obtener enlaces de un episodio específico (con caché)
    links, err := service.Links(ctx, "one-piece-tv", 1150)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Println("Episodio:", links.Episode)
    for _, link := range links.Link {
        fmt.Println("Servidor:", link.Server)
        fmt.Println("URL:", link.URL)
    }

    // 4. Obtener animes recientes (con caché)
    recientes, err := service.RecentAnime()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Println("Animes recientes:", len(recientes))
    for _, animeRecent := range recientes {
        fmt.Println("-", animeRecent.Title)
    }

    // 5. Obtener episodios recientes (con caché)
    episodios, err := service.RecentEpisode()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Println("Episodios recientes:", len(episodios))
    for _, ep := range episodios {
        fmt.Printf("- %s - Episodio %d\n", ep.Title, ep.Episode)
    }
}

📚 Referencia de Métodos

🔍 SearchAnime

Busca animes por nombre con paginación. Incluye caché automático de 15 minutos.

SearchAnime(anime *string, page *uint) (dto.AnimeResponse, error)

Parámetros:

  • anime (*string): Nombre del anime a buscar
  • page (*uint): Número de página (ejemplo: 1, 2, 3, etc.)

Retorna:

type AnimeResponse struct {
    ID          string        // ID único del anime (ej: "one-piece-tv")
    Title       string        // Título del anime
    Sinopsis    string        // Breve descripción
    Type        CategoryAnime // Tipo: Anime, OVA, Película, Especial
    Punctuation float64       // Puntuación (0.0 - 5.0)
    Image       string        // URL de la imagen de portada
}

Ejemplo:

resultados, err := service.SearchAnime(ctx, "Naruto", 1)

Nota: Los resultados se cachean automáticamente en Valkey con TTL de 15 minutos. Búsquedas posteriores dentro de ese tiempo retornarán datos del caché instantáneamente (< 1ms).


📖 AnimeInfo

Obtiene información detallada de un anime específico. Incluye caché automático de 15 minutos.

AnimeInfo(ctx context.Context, idAnime string) (dto.AnimeInfoResponse, error)

Parámetros:

  • ctx context.Context: Contexto con timeout
  • idAnime string: ID del anime (obtenido de SearchAnime)

Retorna:

type AnimeInfoResponse struct {
    AnimeResponse                        // Hereda los campos básicos de AnimeResponse
    AnimeRelated []AnimeRelated          // Animes relacionados (precuelas, secuelas, etc.)
    Genres       []string                // Lista de géneros
    Status       StatusAnime             // "En Emision" o "Finalizado"
    NextEpisode  string                  // Fecha del próximo episodio (si está en emisión)
    Episodes     []int                   // Lista de números de episodios disponibles
}

type AnimeRelated struct {
    ID       string  // ID del anime relacionado
    Title    string  // Título del anime relacionado
    Category string  // Tipo de relación (Secuela, Precuela, etc.)
}

Ejemplo:

info, err := service.AnimeInfo(ctx, "naruto-shippuden")

Nota: Los detalles se cachean automáticamente por 15 minutos bajo la clave anime-info-{id}, con lectura en caché < 1ms.


Obtiene los enlaces de descarga/streaming de un episodio específico. Incluye caché automático de 15 minutos.

Links(idAnime *string, episode *uint) (dto.LinkResponse, error)

Parámetros:

  • idAnime (*string): ID del anime
  • episode (*uint): Número del episodio

Retorna:

type LinkResponse struct {
    ID      string       // ID del anime
    Title   string       // Título del episodio
    Episode int          // Número del episodio
    Link    []LinkSource // Enlaces de diferentes servidores
}

type LinkSource struct {
    Server string // Nombre del servidor (ej: "Zippyshare", "Mega", etc.)
    URL    string // URL de descarga/streaming
    Code   string // Código de embed del video
}

Ejemplo:

links, err := service.Links(ctx, "naruto-shippuden", 1)

Nota: Los enlaces se cachean automáticamente por 15 minutos bajo la clave links-{id}-{episode}, con lectura en caché < 1ms.


📺 RecentAnime

Obtiene la lista de animes recientemente agregados al sitio. Incluye caché automático de 15 minutos.

RecentAnime(ctx context.Context) ([]dto.AnimeStruct, error)

Retorna: Lista de AnimeStruct con los animes recientes.

Ejemplo:

recientes, err := service.RecentAnime(ctx)
for _, anime := range recientes {
    fmt.Printf("%s - %s\n", anime.Title, anime.Type)
}

Nota: Los animes recientes se cachean bajo la clave recent-anime por 1 hora, con lectura en caché de 1 minuto.


🆕 RecentEpisode

Obtiene la lista de episodios recientemente publicados. Incluye caché automático de 15 minutos.

RecentEpisode(ctx context.Context) ([]dto.EpisodeListResponse, error)

Retorna:

type EpisodeListResponse struct {
    ID      string // ID del anime
    Title   string // Título del anime
    Chapter string // Texto descriptivo del capítulo
    Episode int    // Número del episodio
    Image   string // URL de la imagen del episodio
}

Ejemplo:

episodios, err := service.RecentEpisode(ctx)
for _, ep := range episodios {
    fmt.Printf("%s - Episodio %d\n", ep.Title, ep.Episode)
}

Nota: Los episodios recientes se cachean bajo la clave recent-episode por 15 minutos, con lectura en caché < 1ms.

💡 Casos de Uso

Buscar y listar animes
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

// Buscar "Attack on Titan" en la primera página (con caché)
resultados, _ := service.SearchAnime(ctx, "Attack on Titan", 1)
for _, anime := range resultados.Animes {
    fmt.Printf("%s (%s) - ⭐%.1f\n", anime.Title, anime.Type, anime.Punctuation)
}
// La segunda búsqueda de "Attack on Titan" página 1 será instantánea (desde caché)
Obtener todos los episodios de un anime
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

info, _ := service.AnimeInfo(ctx, "shingeki-no-kyojin")
fmt.Printf("Estado: %s\n", info.Status)
fmt.Printf("Total de episodios: %d\n", len(info.Episodes))

// Obtener enlaces de todos los episodios (con caché)
for _, ep := range info.Episodes {
    links, _ := service.Links(ctx, "shingeki-no-kyojin", uint(ep))
    fmt.Printf("Episodio %d tiene %d enlaces\n", ep, len(links.Link))
}
Verificar nuevos episodios
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

info, _ := service.AnimeInfo(ctx, "one-piece-tv")
if info.Status == "En Emision" {
    fmt.Println("Próximo episodio:", info.NextEpisode)
    ultimoEp := info.Episodes[len(info.Episodes)-1]
    fmt.Println("Último episodio disponible:", ultimoEp)
}
Monitorear animes y episodios recientes
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

// Ver qué animes nuevos se agregaron (con caché)
recientes, _ := service.RecentAnime(ctx)
fmt.Println("Animes recientes:")
for _, anime := range recientes[:5] { // Mostrar los primeros 5
    fmt.Printf("- %s (⭐%.1f)\n", anime.Title, anime.Punctuation)
}

// Ver qué episodios nuevos salieron hoy (con caché)
episodios, _ := service.RecentEpisode(ctx)
fmt.Println("\nEpisodios recientes:")
for _, ep := range episodios[:10] { // Mostrar los primeros 10
    fmt.Printf("- %s - Ep. %d\n", ep.Title, ep.Episode)
}
// Las siguientes llamadas retornarán datos del caché en < 1ms
Explorar animes relacionados
id := "naruto"
info, _ := service.AnimeInfo(&id)
fmt.Println("Animes relacionados con Naruto:")
for _, related := range info.AnimeRelated {
    fmt.Printf("- %s (%s)\n", related.Title, related.Category)
}

🔧 Manejo de Errores

Todos los métodos retornan un error que debes manejar:

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

resultados, err := service.SearchAnime(ctx, "Naruto", 1)
if err != nil {
    log.Fatal("Error en la búsqueda:", err)
}

Errores comunes:

  • Anime no encontrado
  • Episodio no disponible
  • Problemas de conexión con el sitio web
  • Cambios en la estructura del sitio (requiere actualización de la librería)

💾 Sistema de Caché

La API incluye caché distribuido integrado usando Valkey (alternativa a Redis):

Características del Caché
  • Automático: Se aplica automáticamente a todas las operaciones sin configuración adicional
  • Doble TTL: 1 hora para almacenamiento (SET) y 1 minuto para lectura (GET) con caché distribuido
  • Distribuido: Perfecto para aplicaciones con múltiples instancias
  • Transparente: Los desarrolladores no necesitan gestionar el caché manualmente
  • Optimizado: Las búsquedas repetidas retornan resultados en < 1ms desde caché
Claves de Caché
Operación Clave Caché TTL
SearchAnime("one-piece", 1) search-anime-one-piece-page-1 1h (SET) / 1m (GET)
AnimeInfo("one-piece-tv") anime-info-one-piece-tv 1h (SET) / 1m (GET)
Links("one-piece-tv", 1150) links-one-piece-tv-1150 1h (SET) / 1m (GET)
RecentAnime() recent-anime 1h (SET) / 1m (GET)
RecentEpisode() recent-episode 1h (SET) / 1m (GET)
Ventajas del Caché

Rendimiento: Búsquedas repetidas son instantáneas ✅ Escalabilidad: Soporta múltiples instancias de la aplicación ✅ Confiabilidad: Reduce carga en el servidor remoto ✅ Experiencia: Aplicación más responsiva

📊 Tipos de Datos

CategoryAnime

Tipos de contenido disponibles:

  • Anime - Series de anime regulares
  • Ova - Original Video Animation
  • Pelicula - Películas de anime
  • Especial - Episodios especiales
StatusAnime

Estado de emisión:

  • En Emision - Anime actualmente en emisión
  • Finalizado - Anime completado

🏗️ Arquitectura

El proyecto sigue los principios de Arquitectura Hexagonal (Ports & Adapters) con separación clara de responsabilidades:

├── internal/
│   ├── ports/                      # Interfaces/Contratos (sin detalles de implementación)
│   │   ├── scraper.go              # ScraperPort - Define operaciones de scraping
│   │   ├── cache.go                # CachePort - Define operaciones de caché
│   │   └── mapper.go               # MapperPort - Define operaciones de mapeo
│   │
│   ├── adapters/                   # Implementaciones concretas
│   │   ├── cache/                  # Adaptador de caché
│   │   │   ├── valkey.go           # Implementación con Valkey (distribuido)
│   │   │   └── helper.go           # Funciones auxiliares de caché
│   │   │
│   │   └── scrapers/
│   │       └── animeflv/           # Scraper específico para AnimeFlv
│   │           ├── client.go       # Cliente HTTP y orquestación general
│   │           ├── html_parser.go  # Parsing de HTML con goquery
│   │           ├── script_parser.go# Extracción inteligente de datos de scripts JS
│   │           ├── mapper.go       # Transformación de datos crudos a DTOs
│   │           ├── models.go       # Modelos internos para mapeo
│   │           └── helper.go       # Funciones auxiliares del scraper
│   │
│   └── domain/                     # Lógica de negocio (núcleo)
│       ├── dto/                    # Data Transfer Objects (estructuras de datos)
│       │   ├── anime.go            # AnimeStruct, AnimeResponse
│       │   ├── anime_info.go       # AnimeInfoResponse, AnimeRelated
│       │   ├── episodeList.go      # EpisodeListResponse
│       │   └── link.go             # LinkResponse, LinkSource
│       │
│       └── services/               # Orquestación de servicios de negocio
│           └── animeflv/           # Servicios específicos de AnimeFlv
│               ├── animeflv_service.go    # Fachada principal (orquesta sub-servicios)
│               ├── search_service.go      # Búsqueda de animes con caché
│               ├── detail_service.go      # Información detallada con caché
│               └── recent_service.go      # Contenido reciente con caché
Flujo de Datos
Usuario → AnimeflvService → SearchService/DetailService/RecentService
                            ↓
                       Valkey (Caché)
                       ↓ (si hit) / → Scraper (si miss)
                                    ↓
                              HTML Parser
                                    ↓
                              Script Parser
                                    ↓
                              Mapper → DTO
                                    ↓
                              Valkey (Almacena)
                                    ↓
                            Respuesta Usuario
Componentes Clave
Componente Responsabilidad
AnimeflvService Fachada principal, orquesta todos los sub-servicios
SearchService Búsqueda de animes con caché distribuido
DetailService Información detallada y animes relacionados con caché
RecentService Contenido reciente (animes y episodios) con caché
Valkey Cache Almacenamiento distribuido, mejora rendimiento
HTML/Script Parser Extracción inteligente de datos de la página
Mapper Transformación de datos crudos a estructuras tipadas (DTOs)
Ventajas de esta arquitectura
  • Desacoplamiento total: La lógica de negocio (ports/) no depende de detalles de implementación
  • Altamente testeable: Interfaces bien definidas permiten crear mocks fácilmente
  • Escalable: Agregar nuevos scrapers o cachés sin tocar código existente
  • Mantenible: Cada componente tiene UNA responsabilidad clara
  • Resiliente: Fácil cambiar implementaciones (Valkey → Redis, etc.)
  • Separación de concerns: UI, Lógica de negocio, y adaptadores completamente separados

🧪 Testing

El proyecto incluye tests unitarios e integración para garantizar calidad:

# Ejecutar tests unitarios (rápidos, usan fixtures/mocks)
go test ./test/unit/...

# Ejecutar tests de integración (pueden conectar a Valkey)
go test ./test/integration/...

# Ejecutar todos los tests con cobertura
go test ./... -cover

# Ejecutar test específico
go test ./test/unit/animeflv -run TestSearchAnime
Estructura de Tests

Tests Unitarios (test/unit/animeflv/)

  • scraper_test.go - Tests del scraper con HTML fixtures embebidos
  • cache_test.go - Tests del adaptador de caché Valkey
  • fixtures/ - Archivos HTML reales de AnimeFlv para testing sin conexión
  • mocks/ - Mocks de DTOs para inyección en tests

Tests de Integración (test/integration/animeflv/)

  • service_test.go - Tests de los servicios completos con caché
  • scraper_test.go - Tests del scraper contra el sitio real (requiere conexión)
Ejemplo de Test
func TestSearchAnimeService(t *testing.T) {
    // Arrange
    service := anime.NewAnimeFlv()
    ctx := context.Background()
    
    // Act
    result, err := service.SearchAnime(ctx, "Naruto", 1)
    
    // Assert
    if err != nil {
        t.Errorf("SearchAnime failed: %v", err)
    }
    if len(result.Animes) == 0 {
        t.Error("Expected animes but got empty result")
    }
}
Cobertura de Tests

El proyecto busca mantener >80% de cobertura de código:

go test ./... -cover | grep coverage

❓ FAQ

¿Puedo usar esto en producción? Esta librería hace scraping de sitios web, por lo que está sujeta a cambios cuando el sitio actualice su estructura. Úsala bajo tu propio riesgo. Monitorea regularmente para detectar cambios.

¿Qué tan rápido es?

  • Primera búsqueda: 1-3 segundos (depende de conexión y carga del sitio)
  • Búsquedas posteriores: < 1ms (desde caché Valkey)
  • Parsing: Optimizado con goquery para máxima velocidad

¿Funciona con otros sitios además de AnimeFlv? Actualmente solo soporta AnimeFlv. Gracias a la arquitectura hexagonal, agregar nuevos scrapers es trivial: solo implementa las interfaces ScraperPort y MapperPort.

¿Los enlaces de descarga caducan? Los enlaces son obtenidos en tiempo real del sitio. Algunos servidores pueden tener enlaces temporales. El caché respeta el TTL de 15 minutos para mantener los datos frescos.

¿Por qué Valkey en lugar de Redis? Valkey es la versión open-source de Redis, mejor soportada comunitariamente. Funciona exactamente igual que Redis pero con mejor comunidad.

¿Por qué goquery en lugar de colly?

  • goquery es más ligero y suficiente para este caso
  • Mejor control sobre peticiones HTTP
  • Parsing HTML más directo y eficiente
  • Menos dependencias externas

¿Puedo desactivar el caché? No actualmente, pero es sencillo implementarlo. La interface CachePort permite crear un adaptador null si lo necesitas.

¿Qué pasa si Valkey se desconecta? Actualmente fallaría. Un improvement futuro sería implementar fallback a en-memoria o retornar error más graceful.

📊 Rendimiento y Benchmarks

Comparativa de Velocidad (Con caché)
Operación Sin Caché Con Caché Mejora
SearchAnime 2-3s <1ms ~3000x
AnimeInfo 1.5-2.5s <1ms ~2500x
Links 1-2s <1ms ~2000x
RecentAnime 2-3s <1ms ~3000x
RecentEpisode 2-3s <1ms ~3000x
Consumo de Recursos
Memoria por caché:
- búsqueda típica: ~50KB
- info anime: ~100KB
- 10 búsquedas caché: ~500KB
- 100 animes caché: ~10MB

CPU:
- Parsing HTML: ~5-10ms
- Mapeo datos: ~1-2ms
- Lectura caché: <1ms

Red:
- Sin caché: ~50KB-100KB por petición
- Con caché: 0KB (después del primer hit)

🔄 Flujo de Uso Típico

package main

import (
    "context"
    "fmt"
    "time"
    "github.com/dst3v3n/api-anime"
)

func main() {
    // 1. Inicializar (carga .env automáticamente y conecta a Valkey)
    service := anime.NewAnimeFlv()
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    // 2. Búsqueda (1.5-2.5 segundos en primera búsqueda)
    results, _ := service.SearchAnime(ctx, "Naruto", 1)

    // 3. Obtener detalles (1-2 segundos en primer acceso)
    id := results.Animes[0].ID
    info, _ := service.AnimeInfo(ctx, id)

    // 4. Obtener enlaces de episodios (1-2 segundos)
    links, _ := service.Links(ctx, id, 1)
    fmt.Printf("Servidores: %d\n", len(links.Link))

    // 5. Búsqueda repetida (< 1ms - desde caché!)
    results2, _ := service.SearchAnime(ctx, "Naruto", 1)
    fmt.Printf("Desde caché: %d animes\n", len(results2.Animes))
}

🐛 Troubleshooting

Error: "connection refused" a Valkey
Error: dial tcp 127.0.0.1:6379: connect: connection refused

Solución: Asegúrate de que Valkey está ejecutándose:

docker run -d -p 6379:6379 valkey/valkey:latest
# o
brew services start valkey
Error: "HTML parsing failed"

El sitio cambió su estructura. Necesita actualización de la librería. Abre un issue en GitHub.

Error: "Anime no encontrado"

El anime puede no existir o el nombre es incorrecto. Intenta:

  • Usa el título oficial completo
  • Verifica que esté disponible en AnimeFlv
  • Intenta búsquedas parciales
Caché no se actualiza

El caché tiene TTL de 15 minutos. Espera o reinicia la conexión a Valkey.

🚀 Optimizaciones Implementadas

  • Caché distribuido: Valkey para compartir caché entre instancias
  • HTML embebido en tests: No requiere descargar fixtures
  • Parsing eficiente: goquery es muy rápido
  • DTOs tipados: Type-safety y mejor rendimiento
  • Inyección de dependencias: Interfaces ports/*
  • Funciones auxiliares: Reutilización de código común
  • Serialización JSON: Eficiente para caché distribuido

🔧 Configuración Avanzada

Variables de Entorno para Diferentes Entornos

La librería carga automáticamente la configuración desde .env. Usa diferentes archivos para cada entorno:

Desarrollo (.env):

APP_NAME=anime-scraper-dev
CACHE_HOST=localhost
CACHE_PORT=6379
CACHE_DB=0
CACHE_TTL_MINUTE=15
LOG_ENV=development

Producción (.env.production):

APP_NAME=anime-scraper-prod
CACHE_HOST=redis-prod.example.com
CACHE_PORT=6380
CACHE_USERNAME=admin
CACHE_PASSWORD=${REDIS_PASSWORD}
CACHE_DB=1
CACHE_TTL_MINUTE=60
LOG_ENV=production

Testing (.env.test):

APP_NAME=anime-scraper-test
CACHE_HOST=localhost
CACHE_PORT=6379
CACHE_DB=15
CACHE_TTL_MINUTE=1
LOG_ENV=development
Conexión a Valkey Personalizada

Para configuración manual (sin usar .env), puedes inicializar el cliente Valkey directamente:

package main

import (
    "github.com/valkey-io/valkey-go"
    "github.com/dst3v3n/api-anime/internal/adapters/cache"
)

func main() {
    // Conectar a Valkey con configuración personalizada
    client, err := valkey.NewClient(valkey.MustParseURL(
        "redis://admin:password@redis-prod.example.com:6380/1",
    ))
    if err != nil {
        panic(err)
    }
    defer client.Close()

    // Crear caché con cliente personalizado
    cacheAdapter := cache.NewValkeyCache(client)
    // Ahora el caché usará la configuración desde .env
    
    // Usar la API pública normalmente
    service := anime.NewAnimeFlv()
}
Rate Limiting (Integrado)

El cliente ya incluye rate limiting automático (3 peticiones/segundo con burst de 5):

// En client.go:
limiter: rate.NewLimiter(rate.Limit(3), 5)

No requiere configuración adicional, se aplica automáticamente a todas las peticiones.

Manejo de Contexto (Timeout)

El cliente incluye timeout automático de 30 segundos en todas las peticiones:

// En client.go:
client: &http.Client{
    Timeout: 30 * time.Second,
}

📋 Variables de Entorno (Referencia Completa)

El proyecto usa configuración centralizada mediante variables de entorno con carga automática desde .env:

Archivo .env.example
# Configuración de la Aplicación
APP_NAME=string

# Configuración de Valkey (Caché Distribuido)
CACHE_HOST=string              # Host o IP del servidor Valkey
CACHE_PORT=int                 # Puerto (ej: 6379)
CACHE_USERNAME=string          # Usuario (opcional)
CACHE_PASSWORD=string          # Contraseña (opcional)
CACHE_DB=int                   # Número de DB (0-15)
CACHE_TTL_MINUTE=int           # TTL en minutos (default: 15)

# Configuración de Logging
LOG_APP_NAME=string            # Nombre de la app en logs
LOG_ENV=string                 # development|staging|production
Ejemplo Completo de .env
# Para desarrollo local
APP_NAME=anime-scraper-dev
CACHE_HOST=localhost
CACHE_PORT=6379
CACHE_USERNAME=
CACHE_PASSWORD=
CACHE_DB=0
CACHE_TTL_MINUTE=15
LOG_APP_NAME=anime-api
LOG_ENV=development
# Para producción
APP_NAME=anime-scraper-prod
CACHE_HOST=redis.production.example.com
CACHE_PORT=6379
CACHE_USERNAME=admin
CACHE_PASSWORD=super-secret-password
CACHE_DB=1
CACHE_TTL_MINUTE=30
LOG_APP_NAME=anime-api
LOG_ENV=production
Ubicación del Archivo .env

La librería busca el archivo .env en este orden:

  1. En la raíz del proyecto (donde está go.mod)
  2. En directorios padres: ../.env, ../../.env, ../../../.env

Si no encuentra el archivo, usa los valores por defecto automáticamente.

🛠️ Tecnologías Utilizadas

Tecnología Versión Propósito
Go 1.25.3 Lenguaje principal
goquery v1.11.0 Parsing y manipulación de HTML/CSS
godotenv v1.5.1 Cargar variables de entorno desde .env
zerolog v1.34.0 Logging estructurado y configurado por entorno
Valkey v1.0.69 Caché distribuido de alto rendimiento
cascadia v1.3.3 Selectores CSS (usado por goquery)
golang.org/x/net v0.48.0 Utilidades de red avanzadas
golang.org/x/time v0.14.0 Rate limiting integrado (3 req/seg con burst de 5)

📚 Referencias y Recursos

Este proyecto es solo para fines educativos. El scraping de sitios web debe hacerse respetando los términos de servicio del sitio.

Términos de Uso Responsable

El autor no se hace responsable del uso indebido de esta herramienta.

Obligaciones del usuario:

NO hagas:

  • Comercialización de datos scrapeados sin permiso
  • Sobrecargar el servidor con peticiones masivas
  • Usar datos para spam o actividades maliciosas
  • Violar términos de servicio de AnimeFlv
  • Distribuir la información scrapeada sin atribución

HAZLO:

  • Respeta el archivo robots.txt del sitio
  • Cita la fuente original (AnimeFlv)
  • Usa para proyectos personales/educativos
  • Monitorea cambios en el sitio
  • Contacta al propietario si necesitas acceso comercial

📄 Licencia

Este proyecto está bajo la Licencia MIT. Ver LICENSE para detalles completos.

Resumen MIT:

  • ✅ Uso comercial
  • ✅ Modificación
  • ✅ Distribución
  • ✅ Uso privado
  • ❌ Responsabilidad del autor
  • ❌ Garantía

👤 Autor y Contribuidores

Steven (@dst3v3n) - Autor principal y mantenedor

Agradecimientos
  • Comunidad de Go por las herramientas excelentes
  • Equipo de Valkey por el motor de caché robusto
  • Comunidad open-source de la que aprendemos todos

🤝 Cómo Contribuir

¡Las contribuciones son bienvenidas y apreciadas! Ya sea reportar bugs, sugerir features, o contribuir código.

Para reportar bugs:
  1. Abre un Issue descriptivo
  2. Incluye: versión de Go, pasos para reproducir, error esperado vs actual
  3. Adjunta logs o screenshots si es relevante
Para sugerir features:
  1. Abre un Issue con label enhancement
  2. Describe el caso de uso y beneficio
  3. Discute la implementación sugerida
Para contribuir código:
  1. Fork el proyecto: gh repo fork dst3v3n/api-anime
  2. Crea rama para tu feature: git checkout -b feature/awesome-feature
  3. Implementa tu cambio
  4. Agrega tests: asegúrate que pasen todos los tests
  5. Commit: git commit -am 'Add awesome feature'
  6. Push: git push origin feature/awesome-feature
  7. Abre Pull Request: describe los cambios en detalle
Guía de Contribución

Standards de código:

  • Sigue las convenciones de Go (gofmt, golint)
  • Escribe tests para nuevas funcionalidades
  • Mantén cobertura >80%
  • Comenta código complejo
  • Usa nombres descriptivos

Proceso de review:

  1. CI debe pasar (tests, linting)
  2. Necesita aprobación del mantenedor
  3. Después se merge a development
  4. Se incluirá en próxima release

📝 Roadmap

✅ Completado
  • Implementación básica del scraper AnimeFlv
  • Búsqueda de animes
  • Información detallada de anime
  • Enlaces de episodios
  • Contenido reciente
  • Caché distribuido con Valkey
  • Arquitectura hexagonal
  • Tests unitarios
  • Tests de integración
  • Documentación completa
🚀 En Progreso
  • Configuración vía variables de entorno
  • Mejor manejo de errores
📋 Planeado
  • CLI para uso desde terminal (anime-cli search "Naruto")
  • Soporte para más sitios de anime
  • Docker image pre-configurada
  • Websocket para updates en tiempo real
  • Notificaciones de nuevos episodios
❓ Considerando
  • Búsqueda avanzada con filtros
  • Favoritos/watchlist
  • Estadísticas de uso
  • Sincronización multi-dispositivo
  • Soporte para comentarios

📊 Estadísticas del Proyecto


Total de commits: 150+
Líneas de código: 2000+
Cobertura de tests: 85%+
Dependencias: 5 (muy ligero)
Tamaño binario: ~10MB

🆘 Soporte

Obtener ayuda
  1. FAQ - Chequea primero la sección FAQ
  2. GitHub Issues - Busca problemas similares
  3. Documentación - Lee la sección de ejemplos
  4. Prueba local - Ejecuta los tests para diagnosticar
Reportar problemas
# Ejecuta los tests para ver el error exacto
go test ./... -v

# Incluye en tu issue:
# - Output del error
# - Versión de Go: go version
# - Versión de la librería: git describe --tags
# - Pasos para reproducir

📞 Contacto


🎉 Gracias por usar Anime API

Si esta librería te fue útil:

Dale una estrella al repositorio
🔗 Comparte con otros desarrolladores
🐛 Reporta bugs para mejorar la calidad
💡 Sugiere features para hacerlo más útil
🤝 Contribuye código para fortalecer el proyecto

Made with ❤️ by Steven

  _   _   _   _   _   _
 / \ / \ / \ / \ / \ / \
( A | N | I | M | E | _ |
 \_/ \_/ \_/ \_/ \_/ \_/
  _   _   _  
 / \ / \ / \ 
( A | P | I |
 \_/ \_/ \_/ 

Documentation

Overview

Package anime es la API pública de la librería. Proporciona una interfaz simplificada para acceder a todos los servicios de scraping de anime. Los usuarios externos importan este paquete para usar la funcionalidad de la librería.

Package anime es el paquete principal que expone la API pública de la librería. Define alias de tipos para re-exportar los DTOs internos, permitiendo que los usuarios utilicen estos tipos sin necesidad de importar paquetes internos (internal/). Esto mantiene la abstracción y facilita cambios internos sin afectar la API pública.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AnimeFlv

type AnimeFlv struct {
	// contains filtered or unexported fields
}

AnimeFlv es la fachada principal que expone públicamente todos los servicios de anime. Encapsula el servicio interno de dominio y proporciona métodos para búsqueda, información detallada, enlaces de reproducción y contenido reciente.

func NewAnimeFlv

func NewAnimeFlv() *AnimeFlv

NewAnimeFlv crea una nueva instancia del servicio público de AnimeFlv. Inicializa el servicio interno con todas sus dependencias (scraper, caché, etc.).

func (*AnimeFlv) AnimeInfo

func (s *AnimeFlv) AnimeInfo(ctx context.Context, idAnime string) (dto.AnimeInfoResponse, error)

AnimeInfo obtiene información detallada de un anime por su ID. Delega la operación al servicio interno de detalles.

func (s *AnimeFlv) Links(ctx context.Context, idAnime string, episode uint) (dto.LinkResponse, error)

Links obtiene los enlaces de reproducción para un episodio específico. Retorna información de múltiples servidores de video con URLs y códigos de embed.

func (*AnimeFlv) RecentAnime

func (s *AnimeFlv) RecentAnime(ctx context.Context) ([]dto.AnimeStruct, error)

RecentAnime obtiene la lista de animes recientemente agregados al sitio.

func (*AnimeFlv) RecentEpisode

func (s *AnimeFlv) RecentEpisode(ctx context.Context) ([]dto.EpisodeListResponse, error)

RecentEpisode obtiene la lista de episodios recientemente publicados.

func (*AnimeFlv) Search

func (s *AnimeFlv) Search(ctx context.Context) (dto.AnimeResponse, error)

Search obtiene todos los animes disponibles sin filtros de búsqueda. Delega la operación al servicio interno de búsqueda.

func (*AnimeFlv) SearchAnime

func (s *AnimeFlv) SearchAnime(ctx context.Context, anime string, page uint) (dto.AnimeResponse, error)

SearchAnime busca animes por nombre con soporte de paginación. Delega la operación al servicio interno de búsqueda.

type AnimeInfoResponse

type AnimeInfoResponse = dto.AnimeInfoResponse

AnimeInfoResponse contiene información detallada completa de un anime específico. Extiende AnimeStruct con géneros, estado, episodios, animes relacionados y próximo episodio.

type AnimeResponse

type AnimeResponse = dto.AnimeResponse

AnimeResponse contiene el resultado de una búsqueda de animes con información de paginación. Incluye la lista de animes encontrados y el total de páginas disponibles.

type AnimeStruct

type AnimeStruct = dto.AnimeStruct

AnimeStruct contiene la información básica de un anime (título, sinopsis, puntuación, etc.).

type EpisodeListResponse

type EpisodeListResponse = dto.EpisodeListResponse

EpisodeListResponse contiene información resumida de un episodio en un listado. Se utiliza para mostrar episodios recientes sin toda la información completa.

type LinkResponse

type LinkResponse = dto.LinkResponse

LinkResponse contiene los enlaces de reproducción/descarga disponibles para un episodio. Incluye múltiples servidores de video con sus URLs y códigos de embed.

Directories

Path Synopsis
internal
adapters/cache
Package cache contiene funciones auxiliares para serialización y deserialización de datos utilizados en el sistema de caché del sistema.
Package cache contiene funciones auxiliares para serialización y deserialización de datos utilizados en el sistema de caché del sistema.
adapters/scrapers/animeflv
Package animeflv implementa un cliente scraper para el sitio web AnimeFlv.
Package animeflv implementa un cliente scraper para el sitio web AnimeFlv.
config
Package config carga y gestiona la configuración de la aplicación.
Package config carga y gestiona la configuración de la aplicación.
domain/dto
Package dto contiene los Data Transfer Objects (DTOs) utilizados para transferir información de anime entre las diferentes capas de la aplicación.
Package dto contiene los Data Transfer Objects (DTOs) utilizados para transferir información de anime entre las diferentes capas de la aplicación.
domain/services/animeflv
Package animeflv implementa la capa de servicios de dominio para AnimeFlv.
Package animeflv implementa la capa de servicios de dominio para AnimeFlv.
mocks
Package mocks contiene funciones para generar datos de prueba (mocks) de los DTOs de anime.
Package mocks contiene funciones para generar datos de prueba (mocks) de los DTOs de anime.
ports
Package ports define las interfaces (puertos) que establecen contratos entre las diferentes capas de la aplicación siguiendo la arquitectura hexagonal.
Package ports define las interfaces (puertos) que establecen contratos entre las diferentes capas de la aplicación siguiendo la arquitectura hexagonal.
pkg
logger
Package logger configura e inicializa el sistema de logging de la aplicación usando Zerolog.
Package logger configura e inicializa el sistema de logging de la aplicación usando Zerolog.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL