{"id":50334239,"url":"https://github.com/rricajos/smm","last_synced_at":"2026-05-29T12:09:50.539Z","repository":{"id":359099267,"uuid":"1243646479","full_name":"rricajos/smm","owner":"rricajos","description":"Smart Mail Manager (S.M.M) - Thunderbird extension with AI features","archived":false,"fork":false,"pushed_at":"2026-05-20T10:50:42.000Z","size":198,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-20T14:59:32.347Z","etag":null,"topics":["thunderbird","thunderbird-addon","thunderbird-extension"],"latest_commit_sha":null,"homepage":"","language":"Svelte","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rricajos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-19T14:29:59.000Z","updated_at":"2026-05-20T10:50:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rricajos/smm","commit_stats":null,"previous_names":["rricajos/smm"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/rricajos/smm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rricajos%2Fsmm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rricajos%2Fsmm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rricajos%2Fsmm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rricajos%2Fsmm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rricajos","download_url":"https://codeload.github.com/rricajos/smm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rricajos%2Fsmm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33650845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["thunderbird","thunderbird-addon","thunderbird-extension"],"created_at":"2026-05-29T12:09:49.646Z","updated_at":"2026-05-29T12:09:50.521Z","avatar_url":"https://github.com/rricajos.png","language":"Svelte","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Smart Mail Manager\n\nExtensión para **Thunderbird 128+** que clasifica correos automáticamente y genera respuestas basadas en reglas configurables, plantillas y asistente de IA.\n\n## Características\n\n### Clasificación automática\n- Reglas con condiciones combinables (AND/OR) sobre remitente, destinatario, asunto, cuerpo y adjuntos\n- Operadores: contiene, igual, empieza por, termina en, coincide con regex\n- Acciones: mover a carpeta, etiquetar, cambiar prioridad, marcar como leído, auto-responder\n- `stopProcessing` opcional para detener la evaluación de reglas tras una coincidencia\n- Detección de conflictos entre reglas (movimientos contradictorios, prioridades incompatibles, redundancias)\n- Fusión automática de reglas redundantes desde el panel de conflictos\n- Galería de presets para crear reglas comunes rápidamente (newsletters, redes sociales, bancos, etc.)\n- Detección de referencias rotas (carpetas, etiquetas o plantillas eliminadas)\n\n### Plantillas de respuesta\n- Variables dinámicas: `{{sender_name}}`, `{{subject}}`, `{{date}}`, `{{my_name}}`, y más\n- Modos de envío: borrador, enviar ahora, enviar después\n- Tipos de respuesta: responder al remitente o responder a todos\n- Vista previa en tiempo real con valores de ejemplo\n- Texto plano o HTML\n\n### Asistente de IA\n- Chat conversacional con contexto completo del buzón (reglas, plantillas, carpetas, etiquetas, correos recientes)\n- Propuestas inteligentes con aceptar/rechazar individual:\n  - **Reglas nuevas** — el AI sugiere reglas basadas en el análisis del correo\n  - **Plantillas** — propone plantillas de respuesta adaptadas\n  - **Mover correos** — sugiere mover mensajes a carpetas específicas\n  - **Crear carpetas** — propone nueva organización de carpetas\n  - **Consolidar reglas** — detecta reglas duplicadas/solapadas y propone fusiones\n- Sistema de referencias cruzadas: cuando el AI propone reglas nuevas y su consolidación en la misma respuesta, las referencias `NEW_RULE:NombreRegla` se resuelven automáticamente\n- Historial de conversaciones persistente con múltiples sesiones\n\n### Proveedores de IA soportados\n\n| Proveedor | Endpoint | Modelos destacados |\n|-----------|----------|--------------------|\n| **OpenRouter** | `openrouter.ai/api/v1` | GPT-4o, Claude Sonnet/Opus, Gemini, Llama 4, DeepSeek, Qwen 3 |\n| **OpenAI** (directo) | `api.openai.com/v1` | GPT-4o, GPT-4.1, GPT-4.1 Nano, o4-mini |\n| **Anthropic** (directo) | `api.anthropic.com/v1` | Claude 3.5 Haiku/Sonnet, Claude Sonnet 4, Claude Opus 4 |\n| **Google Gemini** (directo) | `generativelanguage.googleapis.com` | Gemini 2.0/2.5 Flash, Gemini 2.5 Pro |\n| **Custom** (OpenAI-compatible) | Configurable | Ollama, LM Studio, vLLM, etc. |\n\n### Panel de control\n- Dashboard con estadísticas de clasificaciones y respuestas\n- Log de actividad con filtros por tipo (clasificación, respuesta, error), paginación y exportación CSV\n- Búsqueda global de reglas, plantillas y logs (Ctrl+K)\n- Importación/exportación de configuración completa (JSON) con resolución de conflictos\n- Badges de clasificaciones no leídas en la navegación\n\n### Internacionalización\n- Español (es) — idioma principal\n- English (en)\n- Cambio de idioma dinámico sin reinicio desde opciones\n- Más de 200 claves de traducción\n\n## Arquitectura\n\n```\nsrc/\n├── background/              # Service worker (Manifest V2 background page)\n│   ├── index.ts             # Punto de entrada: listeners, polling, limpieza de logs\n│   ├── classifier.ts        # Motor de clasificación: evalúa reglas contra mensajes\n│   ├── autoresponder.ts     # Genera y envía respuestas usando plantillas\n│   └── message-utils.ts     # Utilidades para leer headers y cuerpo de mensajes\n│\n├── lib/\n│   ├── components/          # Componentes Svelte 5 compartidos\n│   │   ├── Button.svelte    # Botón con variantes (primary, secondary, danger)\n│   │   ├── Modal.svelte     # Modal genérico con título y slot\n│   │   └── Toast.svelte     # Notificación toast temporal\n│   │\n│   ├── i18n/                # Sistema de internacionalización\n│   │   ├── index.ts         # Store reactivo `t`, `locale`, `setLocale()`, `translate()`\n│   │   ├── types.ts         # Interfaz Translations (~200 claves)\n│   │   └── locales/\n│   │       ├── es.ts        # Traducciones español\n│   │       └── en.ts        # Traducciones inglés\n│   │\n│   ├── services/\n│   │   └── openai.ts        # Servicio AI: clasificación, respuestas, chat con propuestas\n│   │\n│   ├── stores/              # Stores reactivos (writable + browser.storage, consumidos via $store)\n│   │   ├── settings.ts      # Configuración general\n│   │   ├── rules.ts         # Reglas de clasificación\n│   │   ├── templates.ts     # Plantillas de respuesta\n│   │   ├── activity.ts      # Log de actividad (máx. 500 entradas, rotación automática)\n│   │   ├── chat.ts          # Historial de conversaciones con IA (múltiples sesiones)\n│   │   └── badges.ts        # Contador de clasificaciones no leídas\n│   │\n│   └── utils/\n│       ├── constants.ts     # Modelos AI, providers, variables de plantilla, defaults\n│       ├── config-io.ts     # Validación y merge de importación/exportación\n│       ├── rule-conflicts.ts # Detección de conflictos entre reglas\n│       ├── rule-presets.ts  # Galería de presets de reglas comunes\n│       ├── template-engine.ts # Motor de sustitución de variables en plantillas\n│       ├── markdown.ts      # Renderizado de markdown para el chat\n│       ├── storage.ts       # Wrapper sobre browser.storage.local\n│       └── messenger.d.ts   # Tipos TypeScript para Thunderbird messenger.* APIs\n│\n├── space/                   # Panel principal (Thunderbird tab space)\n│   ├── main.ts\n│   ├── App.svelte           # Router de navegación por pestañas\n│   ├── pages/\n│   │   ├── Dashboard.svelte # Estadísticas y actividad reciente\n│   │   ├── Rules.svelte     # Gestión de reglas + conflictos + presets + importación\n│   │   ├── Templates.svelte # Gestión de plantillas\n│   │   ├── AI.svelte        # Chat con IA + propuestas (reglas, plantillas, carpetas, consolidación)\n│   │   └── Log.svelte       # Log de actividad con filtros y exportación CSV\n│   └── components/\n│       ├── RuleEditor.svelte       # Editor modal de reglas (condiciones + acciones)\n│       ├── ConditionRow.svelte     # Fila de condición en el editor\n│       ├── ActionRow.svelte        # Fila de acción en el editor\n│       ├── TemplateEditor.svelte   # Editor modal de plantillas con preview\n│       ├── ImportModal.svelte      # Modal de importación con resolución de conflictos\n│       ├── ProposalBlock.svelte    # Bloque de propuesta AI (aceptar/rechazar)\n│       ├── ChatPanel.svelte        # Panel de chat (conversaciones, mensajes, propuestas)\n│       ├── QuickPanel.svelte      # Panel de generación rápida (análisis, batch, descripción)\n│       ├── ChatWelcome.svelte     # Pantalla de bienvenida del chat\n│       ├── FolderTree.svelte       # Selector de carpeta en árbol jerárquico\n│       ├── GlobalSearch.svelte     # Búsqueda global (Ctrl+K)\n│       └── PresetGallery.svelte    # Galería de presets de reglas\n│\n├── popup/                   # Popup del botón de la extensión\n│   ├── main.ts\n│   └── App.svelte           # Resumen rápido + enlace al panel principal\n│\n├── options/                 # Página de opciones (pestaña independiente)\n│   ├── main.ts\n│   └── App.svelte           # Configuración: AI, notificaciones, idioma, import/export\n│\n└── types/\n    ├── rules.ts             # Rule, Condition, Action\n    ├── templates.ts         # ResponseTemplate\n    └── settings.ts          # Settings, ActivityEntry, AiProvider\n```\n\n## Stack técnico\n\n| Tecnología | Versión | Uso |\n|------------|---------|-----|\n| Svelte | 5.x | UI con runes (`$state`, `$derived`, `$effect`, `$props`) + `$store` auto-subscription |\n| Vitest | 4.x | Tests unitarios para utilidades y lógica de negocio |\n| TypeScript | 6.x | Tipado estricto en todo el proyecto |\n| Vite | 8.x | Build programático con 4 entry points IIFE |\n| Thunderbird | 128+ | APIs: `messenger.*` (Manifest V2) |\n| web-ext | 10.x | Dev server y empaquetado .xpi |\n\n## Desarrollo\n\n### Requisitos previos\n- Node.js 20+\n- Thunderbird 128+ instalado\n- Clave API de algún proveedor de IA (OpenRouter, OpenAI, Anthropic, Google, o servidor local)\n\n### Instalación\n\n```bash\ngit clone \u003crepo-url\u003e\ncd smm\nnpm install\n```\n\n### Scripts\n\n| Comando | Descripción |\n|---------|-------------|\n| `npm run build` | Build de producción → `dist/` |\n| `npm run watch` | Build + watch de cambios en `src/` |\n| `npm run dev` | Build + watch + `web-ext run` con Thunderbird |\n| `npm test` | Ejecuta tests unitarios con Vitest |\n| `npm run test:watch` | Tests en modo watch |\n| `npm run package` | Build + empaquetado como `smart-mail-manager.xpi` |\n\n### Sistema de build\n\nEl build usa un script custom (`build.ts`) que:\n1. Auto-incrementa la versión patch en `manifest.json` en cada build\n2. Compila 4 entry points como IIFE autocontenidos (requisito de MailExtensions):\n\n| Entry point | Svelte | Output |\n|-------------|--------|--------|\n| `popup` | Sí | `dist/popup.{html,js,css}` |\n| `space` | Sí | `dist/space.{html,js,css}` |\n| `options` | Sí | `dist/options.{html,js,css}` |\n| `background` | No | `dist/background.js` |\n\n3. Genera HTML para cada UI entry point\n4. Copia archivos estáticos de `public/` a `dist/`\n5. En modo watch, recompila al detectar cambios en `src/` (sin re-bump de versión)\n\n### Tests\n\nTests unitarios con [Vitest](https://vitest.dev/):\n\n```bash\nnpm test           # Ejecutar una vez\nnpm run test:watch # Modo watch\n```\n\nCobertura de tests:\n- `rule-conflicts.ts` — Detección de conflictos entre reglas (movimientos contradictorios, prioridades incompatibles, redundancia, solapamiento de condiciones)\n- `config-io.ts` — Exportación, validación de importación, detección de conflictos por ID y nombre\n- `template-engine.ts` — Renderizado de variables `{{}}`, extracción de nombre y email de direcciones\n- `markdown.ts` — Renderizado de markdown a HTML con protección XSS\n\n### Instalación en Thunderbird\n\n**Producción:**\n```bash\nnpm run package\n# Thunderbird → Herramientas → Complementos → ⚙️ → Instalar desde archivo → smart-mail-manager.xpi\n```\n\n**Desarrollo:**\n```bash\nnpm run dev\n# Abre Thunderbird con la extensión cargada y hot-reload\n```\n\n\u003e **Nota:** Ajusta las rutas de Thunderbird y perfil en `package.json` si tu instalación difiere.\n\n## Almacenamiento\n\nTodos los datos se persisten en `browser.storage.local`:\n\n| Clave | Contenido |\n|-------|-----------|\n| `smm_rules` | Array de reglas de clasificación |\n| `smm_templates` | Array de plantillas de respuesta |\n| `smm_settings` | Configuración general (provider, modelo, API key, límites, notificaciones) |\n| `smm_activity_log` | Log de actividad (máx. 500 entradas, rotación automática) |\n| `smm_auto_response_count` | Contador horario de auto-respuestas (rate limiting) |\n| `smm_chat_history` | Historial de conversaciones con IA (múltiples sesiones) |\n| `smm_unread_classifications` | Contador de clasificaciones no leídas (badges) |\n| `smm_locale` | Idioma seleccionado (`es` / `en`) |\n\n## Permisos de la extensión\n\n| Permiso | Uso |\n|---------|-----|\n| `messagesRead` | Leer contenido de correos para clasificar |\n| `messagesMove` | Mover correos a carpetas según reglas |\n| `messagesUpdate` | Cambiar prioridad y marcar como leído |\n| `messagesTags` | Añadir etiquetas a correos |\n| `accountsRead` | Listar cuentas y carpetas del usuario |\n| `accountsFolders` | Crear carpetas nuevas (propuestas del AI) |\n| `compose` / `compose.send` / `compose.save` | Crear borradores y enviar respuestas automáticas |\n| `storage` | Persistir configuración, reglas, plantillas y logs |\n| `notifications` | Notificar clasificaciones y respuestas |\n| `https://openrouter.ai/*` | Llamadas a OpenRouter API |\n| `https://api.openai.com/*` | Llamadas directas a OpenAI |\n| `https://api.anthropic.com/*` | Llamadas directas a Anthropic |\n| `https://generativelanguage.googleapis.com/*` | Llamadas directas a Google Gemini |\n| `http://*/*`, `https://*/*` | Endpoints custom (Ollama, etc.) |\n\n## Flujo de datos\n\n### Clasificación automática\n\n```\nCorreo nuevo → background/index.ts (listener onNewMailReceived)\n  → classifier.ts: evalúa cada regla habilitada contra el mensaje\n    → Compara condiciones (from, to, subject, body, hasAttachments)\n    → Lógica AND (all) / OR (any)\n    → Coincidencia encontrada:\n      → Ejecuta acciones secuencialmente:\n        - moveToFolder → messenger.messages.move()\n        - addTag → messenger.messages.update({ tags })\n        - setPriority → cambio de cabecera X-Priority\n        - markRead → messenger.messages.update({ read: true })\n        - autoRespond → autoresponder.ts\n      → Registra en activity log\n      → Notificación (si habilitada)\n      → Si stopProcessing = true, detiene evaluación de más reglas\n```\n\n### Auto-respuesta\n\n```\nAcción autoRespond activada\n  → autoresponder.ts: verifica rate limit (maxAutoResponsesPerHour)\n    → Carga plantilla por templateId\n    → template-engine.ts: sustituye {{variables}} con datos del mensaje\n    → Según sendMode:\n      - draft → messenger.compose.beginReply() + compose.saveMessage()\n      - sendNow → messenger.compose.beginReply() + compose.sendMessage()\n      - sendLater → messenger.compose.beginReply() + compose.sendMessage({ mode: \"sendLater\" })\n```\n\n### Chat con IA\n\n```\nUsuario escribe mensaje → AI.svelte\n  → openai.ts: chatWithAssistant()\n    → Construye contexto: reglas actuales, plantillas, carpetas, etiquetas, correos recientes\n    → Envía al proveedor AI configurado (OpenRouter/OpenAI/Anthropic/Google/Custom)\n    → Recibe respuesta con texto markdown + bloques JSON de propuestas\n    → Parsea propuestas: FOLDER_PROPOSAL, RULE_PROPOSAL, TEMPLATE_PROPOSAL,\n      MOVE_PROPOSAL, RULE_CONSOLIDATION_PROPOSAL\n    → Resuelve referencias cruzadas (NEW_RULE:Nombre → UUID generado)\n  → ProposalBlock.svelte: renderiza cada propuesta\n    → Aceptar → aplica cambio (guarda regla, crea carpeta, mueve correo, etc.)\n    → Rechazar → descarta\n```\n\n## Tipos principales\n\n### Rule\n```typescript\ninterface Rule {\n  id: string;                    // UUID\n  name: string;\n  enabled: boolean;\n  conditions: Condition[];       // from, to, subject, body, hasAttachments\n  conditionLogic: 'all' | 'any'; // AND / OR\n  actions: Action[];             // moveToFolder, addTag, setPriority, markRead, autoRespond\n  stopProcessing: boolean;       // Detener evaluación tras coincidencia\n  createdAt: number;             // Timestamp\n  updatedAt: number;             // Timestamp\n}\n\ninterface Condition {\n  field: 'from' | 'to' | 'subject' | 'body' | 'hasAttachments';\n  operator: 'contains' | 'equals' | 'startsWith' | 'endsWith' | 'matches' | 'is';\n  value: string;\n  boolValue?: boolean;           // Para hasAttachments\n  caseSensitive: boolean;\n}\n\ninterface Action {\n  type: 'moveToFolder' | 'addTag' | 'setPriority' | 'markRead' | 'autoRespond';\n  folderId?: string;\n  tagKey?: string;\n  priority?: 'highest' | 'high' | 'normal' | 'low' | 'lowest';\n  templateId?: string;           // Referencia a ResponseTemplate\n}\n```\n\n### ResponseTemplate\n```typescript\ninterface ResponseTemplate {\n  id: string;\n  name: string;\n  subject: string;               // Soporta {{variables}}\n  body: string;                  // Soporta {{variables}}\n  isPlainText: boolean;\n  sendMode: 'draft' | 'sendNow' | 'sendLater';\n  replyType: 'replyToSender' | 'replyToAll';\n}\n```\n\n### Settings\n```typescript\ntype AiProvider = 'openrouter' | 'openai' | 'anthropic' | 'google' | 'custom';\n\ninterface Settings {\n  classificationEnabled: boolean;\n  autoResponseEnabled: boolean;\n  processExistingOnStartup: boolean; // Procesar correos existentes al iniciar\n  maxAutoResponsesPerHour: number;   // Rate limit\n  logRetentionDays: number;          // Rotación automática del log\n  notifyOnClassification: boolean;\n  notifyOnAutoResponse: boolean;\n  aiProvider: AiProvider;\n  openaiApiKey: string;\n  openaiModel: string;               // ID del modelo según el provider\n  customBaseUrl: string;             // Solo para provider 'custom'\n}\n```\n\n## Variables de plantilla\n\n| Variable | Ejemplo | Descripción |\n|----------|---------|-------------|\n| `{{sender_name}}` | Juan García | Nombre del remitente |\n| `{{sender_email}}` | juan@example.com | Email del remitente |\n| `{{to}}` | ricard@conexiatec.com | Destinatario |\n| `{{subject}}` | Re: Presupuesto | Asunto original |\n| `{{date}}` | 18/05/2026 | Fecha actual |\n| `{{time}}` | 14:30 | Hora actual |\n| `{{day_of_week}}` | Lunes | Día de la semana |\n| `{{original_body}}` | *(texto completo)* | Cuerpo completo del correo original |\n| `{{original_body_snippet}}` | *(primeras líneas)* | Primeras líneas del cuerpo |\n| `{{my_name}}` | Ricard Penin | Nombre del usuario (de la cuenta) |\n| `{{my_email}}` | ricard@conexiatec.com | Email del usuario (de la cuenta) |\n\n\u003e También se soportan las variables legacy `{{senderName}}`, `{{senderEmail}}`, `{{originalSubject}}` por retrocompatibilidad.\n\n## Autor\n\nRicard Penin Honrubia — [ricard.penin.honrubia@gmail.com](mailto:ricard.penin.honrubia@gmail.com)\n\n## Licencia\n\nEste proyecto está licenciado bajo la [Mozilla Public License 2.0](https://mozilla.org/MPL/2.0/).\nConsulta el archivo [LICENSE](LICENSE) para más detalles.\n\nCopyright © 2025 Ricard Penin Honrubia\n\n## Aviso de privacidad\n\nSmart Mail Manager procesa contenido de correos electrónicos (remitente, asunto, fragmentos del cuerpo) y lo envía a servicios externos de inteligencia artificial (OpenRouter, OpenAI, Anthropic, Google) cuando el usuario utiliza las funcionalidades de IA. Esta comunicación se realiza exclusivamente bajo demanda del usuario y nunca de forma automática en segundo plano sin su consentimiento.\n\n- Los datos se transmiten únicamente al proveedor de IA configurado por el usuario.\n- No se almacenan datos en servidores propios; toda la persistencia es local (`browser.storage.local`).\n- Las claves API son proporcionadas y gestionadas por el usuario.\n- El usuario es responsable de revisar las políticas de privacidad del proveedor de IA que elija.\n\n## Descargo de responsabilidad\n\nEste software se proporciona \"tal cual\", sin garantías de ningún tipo, expresas o implícitas. En ningún caso el autor será responsable de daños derivados del uso de este software, incluyendo pero no limitado a:\n\n- Pérdida o clasificación incorrecta de correos electrónicos.\n- Envío de respuestas automáticas no deseadas.\n- Costes derivados del uso de APIs de terceros (OpenRouter, OpenAI, Anthropic, Google).\n- Pérdida de datos o interrupciones del servicio.\n\nEl usuario asume la totalidad del riesgo en cuanto a la calidad y rendimiento del software.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frricajos%2Fsmm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frricajos%2Fsmm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frricajos%2Fsmm/lists"}