miércoles, 22 de abril de 2026

Configurar SMTP gmail en moodle

En config.php:


$CFG->smtphosts = 'smtp.gmail.com:587';

$CFG->smtpuser = 'mai@mail.es';

$CFG->smtppass = ''; // tu app password  https://myaccount.google.com/apppasswords (es necesario tener la cuenta con 2fa https://myaccount.google.com/security )

$CFG->smtpsecure = 'tls';

$CFG->smtpauthtype = 'LOGIN'; 

Configuración Google Meet en Moodle

Para implementar la integración de Google Meet con Moodle mediante OAuth 2, sigue estos pasos:

  1. Creación del proyecto en Google Cloud
    • Se crea un proyecto en Google Cloud Console.
  2. Configuración de credenciales OAuth 2
    • Se genera:
      • Client ID
      • Client Secret
  3. Configuración en Moodle
    • Se accedió a:
      👉 Administración del sitio → Servidor → Servicios OAuth 2
    • Se creó el servicio de Google utilizando:
      • Client ID
      • Client Secret
  4. Configuración de URI de redirección
    • Se configura correctamente en Google Cloud:

      https://tudominio.com/admin/oauth2callback.php
    • Esto resuelve el error redirect_uri_mismatch
  5. Activación de APIs necesarias
    • Se habilita:
      • Google Drive API (necesaria para sincronizar grabaciones)
  6. Validación de conexión
    • Se logra conectar la cuenta de Google con Moodle
    • Se habilita la opción de sincronización de grabaciones

 Resultado

  • Moodle puede:
    • Crear sesiones de Google Meet
    • Conectar con Google Drive
    • Sincronizar grabaciones (tras ejecutar la sincronización)

Subir archivos grandes en Moodle

 Servidor web (NGINX o Apache)

En NGINX

Parámetro clave:

client_max_body_size 512M;
  • Esto define el tamaño máximo de subida
  • Valor típico por defecto: 1M o 2M (muy bajo)
  • Tú puedes subirlo a:
    • 128M (normal)
    • 256M (recomendado)
    • 512M (archivos grandes como videos)

 Se coloca en:

  • /etc/nginx/nginx.conf
  • o en config del sitio

Luego:

sudo systemctl reload nginx

PHP (MUY IMPORTANTE)

En php.ini debes ajustar:

upload_max_filesize = 512M
post_max_size = 512M
max_execution_time = 300
max_input_time = 300
memory_limit = 512M

post_max_size debe ser ≥ upload_max_filesize

Luego reinicia:

sudo systemctl restart php-fpm

(o apache si usas Apache)


Moodle (dentro del sistema)

Ir a:

Administración del sitio → Seguridad → Políticas del sitio

Configurar:

  • Tamaño máximo de archivo → 512MB (o el que quieras)

También en:

  • Curso → Configuración → Tamaño máximo de subida

Resumen rápido

Para subir archivos grandes:

NivelParámetroEjemplo
NGINXclient_max_body_size512M
PHPupload_max_filesize512M
PHPpost_max_size512M
MoodleTamaño máximo archivo512MB

Error típico

Si uno de estos es menor → falla la subida
(Moodle muestra error aunque tengas todo lo demás bien)

Configurar SMTP en Moodle (no gmail)

Si Moodle no envía correos, puedes configurar el SMTP directamente en el archivo config.php. 

1. Editar archivo

Ubica y abre:

/config.php

2. Añadir configuración SMTP

Agrega al final del archivo:

$CFG->directorypermissions = 0777;
$CFG->smtphosts = 'ssl://smtp.serviciodecorreo.es:465';
$CFG->smtpuser = 'tu_correo@tudominio.com';
$CFG->smtppass = 'tu_contraseña';
$CFG->smtpsecure = 'ssl';
$CFG->smtpauthtype = 'LOGIN';


3. Datos necesarios
  • Servidor SMTP: smtp.serviciodecorreo.es
  • Puerto: 465 (SSL)
  • Usuario: correo completo
  • Contraseña: la del correo

Notas importantes

  • Asegúrate de que el servidor permita conexiones SMTP (puerto 465 o 587)
  • Si no funciona con SSL, prueba:
    • tls con puerto 587
  • Verifica que el correo existe y la contraseña es correcta

Resultado

Con esta configuración, Moodle podrá enviar correos correctamente .

domingo, 12 de abril de 2026

Notas: Framework ACHIEVE para el uso de IA

No todos los problemas deben resolverse con IA. El framework ACHIEVE ayuda a identificar cuándo la Inteligencia Artificial es la herramienta correcta, con el fin de aumentar nuestra propia inteligencia y capacidad crítica, en lugar de solo depender de la tecnología.

Los 5 Pilares de ACHIEVE:

  1. A – Aid Human Coordination (Coordinación Humana): La IA como facilitadora entre personas.

    • Ejemplo: Resúmenes de reuniones, agendas compartidas o alineación de equipos.

  2. C – Cut Out Tedious Tasks (Eliminar lo Tedioso): Automatizar tareas repetitivas que no aportan valor creativo.

    • Ejemplo: Clasificar correos masivos o reformatear grandes bases de datos.

  3. H – Help Provide a Safety Net (Red de Seguridad): Usar la IA para revisar, verificar y detectar riesgos.

    • Ejemplo: Auditoría de contratos, detección de errores en código o análisis de "qué podría salir mal".

  4. I-E-V – Inspire bEtter problem solving and creatiVity (Inspiración y Creatividad): Salir de nuestra zona de confort mental.

    • Uso: Evitar resolver todo de la misma forma (sesgo) usando la IA para brainstorming, analogías y ángulos de resolución que no habíamos considerado.

  5. E – Enable Great Ideas to Scale Faster (Escalabilidad): Llevar una buena idea a un impacto mayor rápidamente.

    • Ejemplo: Traducir contenido a varios idiomas o adaptar un solo concepto a múltiples formatos (blog, redes sociales, video)

    • Conclusión: Antes de lanzar un prompt, haz una pausa y pregunta: ¿Este problema encaja en ACHIEVE? El objetivo real de la IA no es reemplazarnos, sino servir de palanca para elevar nuestro pensamiento crítico y nuestra creatividad.

viernes, 13 de febrero de 2026

Consultas SQL valiosas para moodle

 SELECT 

    table_name,

    ROUND((data_length + index_length) / 1024 / 1024 / 1024, 2) AS size_gb

FROM information_schema.TABLES

WHERE table_schema = 'campus'

ORDER BY size_gb DESC;


SELECT

   ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS total_gb

FROM information_schema.TABLES

WHERE table_schema = 'campus';


SELECT table_name,

       ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb

FROM information_schema.TABLES

WHERE table_schema = 'mdlsimb'

ORDER BY size_mb DESC


Borrar logs de antes del 2025

SELECT COUNT(*) AS registros_a_borrar

FROM mdl_logstore_standard_log

WHERE timecreated < UNIX_TIMESTAMP('2025-01-01');


DELETE FROM mdl_logstore_standard_log

WHERE timecreated < UNIX_TIMESTAMP('2025-01-01')

LIMIT 50000;



OPTIMIZE TABLE mdl_logstore_standard_log;

SHOW VARIABLES LIKE 'innodb_file_per_table';

ANALYZE TABLE mdl_logstore_standard_log;


martes, 10 de febrero de 2026

Como bloquear dominio y apuntar a un subdominio con usuario y clave en Cloud Panel AWS

Pasos para  bloquear Dominio y apuntar a un subdominio con usuario y clave en Cloud Panel AWS

1️⃣ DNS (SiteGround)

  • Crear subdominio nuevo (ej: subdominio.abc.com)

  • Apuntarlo a la misma IP del servidor AWS

2️⃣ CloudPanel / Nginx

En security activar basic authentication y crear el usuario con contraseña encriptada

En el mismo site:

  • server_name incluye:

    dominio.abc.com subdominio.abc.com
  • Bloquear dominio viejo:

    if ($host = "dominio.abc.com") { return 403; }
  • Proteger acceso (Basic Auth):

    auth_basic "Acceso restringido"; auth_basic_user_file /etc/nginx/.htpasswd;
  • Añadir noindex:

    add_header X-Robots-Tag "noindex, nofollow" always;

3️⃣ Dónde va la app

  • Ambos dominios apuntan a la misma carpeta del proyecto

  • No duplicar archivos

  • No crear otra instancia

4️⃣ Probar

  • Dominio viejo → 403

  • Subdominio nuevo → pide usuario/clave

  • Sin login → no se carga nada

  • Google → no indexa

RECORDATORIO IMPORTANTE

  • Esto protege el acceso, no el código del front

  • Un usuario autorizado siempre puede ver el JS

  • Para proteger el producto, es necesario crear backend

miércoles, 24 de diciembre de 2025

Flujo para Aceptar presupeusto en Holded

El flujo cuando el presupuesto pasa a aceptado: 

Presupuesto → Convertir a factura

 Factura aprobada dando a guardar

martes, 23 de diciembre de 2025

Restringir por IP aplicativos en Nginx (muy fácil y eficaz)

 

Restringir por IP (muy fácil y eficaz)

Si el cliente accede desde IPs concretas:

location / { allow 123.123.123.123; # IP del cliente allow 111.111.111.111; # otra IP deny all; }

jueves, 25 de septiembre de 2025

Restaurar página con archivo .wpress con all in onw migration

 

Ruta exacta para subir tu .wpress por FTP

  1. Conéctate a tu hosting por FTP (ejemplo con FileZilla).

  2. Ve a la carpeta donde está tu WordPress (normalmente /public_html/ o /www/).

  3. Entra en:

/wp-content/ai1wm-backups/

👉 Si la carpeta no existe, créala manualmente con ese nombre exacto:
ai1wm-backups

  1. Sube tu archivo .wpress completo dentro de esa carpeta.


🔄 Restaurar la copia desde el admin

  1. Ve a tu WordPress admin → All-in-One WP Migration → Copias de seguridad.

  2. Verás tu archivo .wpress en la lista automáticamente.

  3. Haz clic en Restaurar.

  4. El plugin reemplazará todo tu WordPress (archivos, base de datos, plugins, temas).

⚠️ Nota: la versión gratuita de All-in-One WP Migration a veces bloquea restauraciones grandes (>512 MB).

  • Si tu archivo pesa más, necesitas el Unlimited Extension o que tu hosting tenga esa versión habilitada.

domingo, 17 de agosto de 2025

Mensaje para Linkedin

 ¡Hola (Nombre) Me encanta la tecnología y el impacto de (nombre empresa). Me gustaría formar parte de su equipo. ¿Podemos hablar sobre oportunidades? 😊🚀

Prompt para evaluar el código con IA en Chatgpyt

Prompt para evaluar el código con IA en Chatgpyt:

- Buenas prácticas de Moodle

- Seguridad

- Compatibilidad con auditoría (IA, estructura, claridad)

- Código robusto y mantenible


viernes, 25 de julio de 2025

Comandos docker para subir cambios en git en servidor o en local

git pull 

docker ps -a

docker stop vue-app Detiene proceso

docker rm vue-app  Borrar

docker image

docker rmi <id imagen>

docker-compose build --no-cache Reconstruye desde cero SIN CACHÉ

docker-compose up -d lanzar contenedores

docker image prune -f   cache para limpiar  los build anteriores

jueves, 24 de julio de 2025

Cómo instalar apps en Odoo

Para instalar una aplicación en Odoo en un servidor, 

primero debes ubicar la carpeta de addons de Odoo

luego colocar el módulo (descomprimido) en esa carpeta.

Reinicia el servicio de Odoo sudo systemctl restart odoo 

Activa el modo desarrollador, y finalmente, actualiza la lista de aplicaciones desde la interfaz de Odoo para que la nueva aplicación aparezca y puedas instalarla. (a veces no sale con el nombre exacto y hay que buscarlo en  todas las app sin filtro)

Pasos detallados:

1. Localizar la carpeta de addons:

La ubicación de la carpeta de addons puede variar dependiendo de tu configuración, pero generalmente se encuentra dentro del directorio de instalación de Odoo. 

2. Copiar el módulo:

Descarga el módulo que deseas instalar (generalmente en formato zip) y descomprímelo. Luego, copia la carpeta del módulo a la carpeta de addons de Odoo. 

3. Reiniciar el servicio Odoo:

Detén y reinicia el servicio Odoo para que detecte el nuevo módulo. La forma de hacerlo dependerá de tu sistema operativo y configuración. 

4. Activar el modo desarrollador:

En la interfaz de Odoo, ve a "Ajustes" (o "Configuración") y activa el "Modo Desarrollador". 

5. Actualizar la lista de aplicaciones:

En la sección "Aplicaciones", haz clic en "Actualizar lista de aplicaciones". 

6. Instalar el módulo:

Busca el módulo recién instalado en la lista de aplicaciones y haz clic en "Instalar".   en _manifest__.py se encuentra el nombre de la app

lunes, 14 de julio de 2025

Como hacer un login de google en Shopify

📄 Paso 2: Editar el tema Dawn (login.liquid)

Ve a tu panel Shopify:

  1. Online StoreThemes → “Dawn” → Actions → Edit Code

  2. Abre el archivo: sections/main-login.liquid o templates/customers/login.liquid

  3. Agrega este código justo debajo del formulario o donde prefieras mostrar el botón:


<div id="g_id_onload" data-client_id="TU_CLIENT_ID_DE_GOOGLE" data-callback="handleCredentialResponse" data-auto_prompt="false"> </div> <div style="width: 100%; display: flex; justify-content: center; align-items: center; "> <div class="g_id_signin" data-type="standard" data-size="large" data-theme="outline" data-text="sign_in_with" data-shape="rectangular" data-logo_alignment="left" > </div> </div> <script src="https://accounts.google.com/gsi/client" async defer></script> <script> function handleCredentialResponse(response) { // Decodificamos el token JWT const token = response.credential; const payload = JSON.parse(atob(token.split('.')[1])); const email = payload.email; const name = payload.name; // Guardar temporalmente en localStorage localStorage.setItem("google_email", email); localStorage.setItem("google_name", name); // Redirigir al registro window.location.href = "/account/register"; } </script>

🧩 Paso 3: Prefill en /account/register (opcional)

  1. Edita el archivo customers/register.liquid

  2. Agrega este script al final del archivo:


<script> document.addEventListener("DOMContentLoaded", function() { const email = localStorage.getItem("google_email"); const name = localStorage.getItem("google_name"); if (email) { const emailField = document.querySelector('input[name="customer[email]"]'); if (emailField) emailField.value = email; } if (name) { const firstNameField = document.querySelector('input[name="customer[first_name]"]'); if (firstNameField) firstNameField.value = name.split(" ")[0]; const lastNameField = document.querySelector('input[name="customer[last_name]"]'); if (lastNameField) lastNameField.value = name.split(" ").slice(1).join(" "); } }); </script>

Esto rellena automáticamente el formulario de registro con el nombre y correo que el usuario usó en su cuenta de Google.


✅ Resultado final

  • El usuario ve el botón “Sign in with Google”

  • Al hacer clic:

    • Se captura su nombre y correo electrónico

    • Se le redirige a /account/register

    • Se rellena el formulario automáticamente

  • El usuario solo necesita poner una contraseña y hacer clic en "Crear cuenta"

lunes, 30 de junio de 2025

Optimizar BD en phpmyadmin en siteground

 Paso 1: Ir al phpmyadmin a la BD


SELECT * FROM ela_posts

WHERE post_type = 'revision';


DELETE FROM ela_posts

WHERE post_type = 'revision';


Paso 2: 

limpia el postmeta huérfano, de cualquier plugin o metakey

select * FROM ela_postmeta

WHERE post_id NOT IN (SELECT ID FROM ela_posts);


DELETE FROM ela_postmeta

WHERE post_id NOT IN (SELECT ID FROM ela_posts);


Paso 3 (opcional): Optimizar


OPTIMIZE TABLE ela_postmeta;

OPTIMIZE TABLE ela_posts;


lunes, 19 de mayo de 2025

Como resolver el error de puerto de moodle en local

 

Cierra completamente XAMPP

  • Cierra el Panel de Control.

  • Mata cualquier proceso de Apache que haya quedado en segundo plano:

    En CMD (como administrador):

    taskkill /F /IM httpd.exe


docker ps
docker start mariadb10_4
admin tareas detener   e iniciar mysql

/course/modedit.php
/mod/quiz/edit.php


C:\moodle\server\moodle\mod


sábado, 17 de mayo de 2025

lunes, 5 de mayo de 2025

Herramientas fundamentales para aprender para CI/CD

 Herramientas fundamentales para aprender para CI/CD

1. Git (Primero)

  • Qué es: Sistema de control de versiones.

  • Para qué sirve: Te permite llevar el control de los cambios en tu código fuente localmente y en equipo.

  • Aprendizaje clave: git init, git add, git commit, git push, git pull, branch, merge, etc.

  • Es la base. Todo lo demás depende de saber Git.

2. GitLab (Segundo)

  • Qué es: Plataforma de alojamiento de repositorios Git (como GitHub), con herramientas de integración continua y gestión de proyectos.

  • Para qué sirve: Subes tus repositorios, colaboras con otros y automatizas procesos.

  • Aprendizaje clave: cómo subir proyectos, usar issues, pipelines, merge requests, etc.

 Puedes aprender GitHub o GitLab indistintamente, ya que cumplen funciones similares. Si tu empresa usa GitLab, aprende GitLab. Si usas GitHub, sigue con GitHub.

3. GitHub Actions o GitLab CI/CD (Tercero)

  • Qué es: Herramientas de integración y entrega continua (CI/CD).

  • Para qué sirve: Automatizar tareas como pruebas, despliegue de código, compilación, etc.

  • Aprendizaje clave:

    • YAML básico

    • Definir workflows

    • Automatizar builds, tests, deploys


  1. Git → base fundamental.

  2. GitHub o GitLab → elegir una plataforma para alojar repositorios.

  3. GitHub Actions o GitLab CI/CD → automatización avanzada con pipelines.

viernes, 25 de abril de 2025

Cómo crear un plugin básico de actividad en Moodle (paso a paso)

Crear tu propio plugin en Moodle puede sonar complicado al principio, pero con este tutorial te mostraré cómo desarrollar un plugin básico de tipo “actividad” para que puedas entender la estructura y empezar a construir tus propias funcionalidades.

Cómo crear un plugin básico de actividad en Moodle (paso a paso)


 ¿Qué vamos a crear?

Un plugin de actividad llamado Mi Módulo, que aparecerá en el listado de actividades cuando edites un curso y te permitirá crear nuevas instancias con un solo campo: nombre.

 Estructura del plugin

Primero, crea una carpeta en:


moodle/mod/mimodulo

Dentro de esa carpeta, necesitas tener al menos estos archivos:


mimodulo/ ├── db/ │ └── install.xml
         acces.php ├── lang/ │ └── en/ │ └── mimodulo.php ├── lib.php ├── mod_form.php ├── version.php ├── view.php

 1. version.php

Archivo obligatorio que define la versión del plugin.


<?php defined('MOODLE_INTERNAL') || die(); $plugin->component = 'mod_mimodulo'; $plugin->version = 2025042500; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_STABLE; $plugin->release = 'v1.0';

 2. install.xml (estructura de base de datos)

Ubicado en db/install.xml. Define la tabla del plugin.


<?xml version="1.0" encoding="UTF-8" ?> <XMLDB PATH="mod/mimodulo/db" VERSION="2025042500" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"> <TABLES> <TABLE NAME="mimodulo" COMMENT="Tabla del módulo mimodulo"> <FIELDS> <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/> <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true"/> <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true"/> <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="false"/> </FIELDS> <KEYS> <KEY NAME="primary" TYPE="primary" FIELDS="id"/> </KEYS> </TABLE> </TABLES> </XMLDB>

2.5 access.php

<?php defined('MOODLE_INTERNAL') || die(); $capabilities = [ 'mod/mimodulo:addinstance' => [ 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => ['editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW], ], ];

3. lang/en/mimodulo.php

Define los textos visibles.

<?php $string['pluginname'] = 'Mi Módulo'; $string['modulename'] = 'Mi Módulo'; $string['modulenameplural'] = 'Mis Módulos'; $string['mimodulo:addinstance'] = 'Agregar una nueva instancia de Mi Módulo'; $string['name'] = 'Nombre del módulo';

 4. mod_form.php

Formulario que se muestra al crear o editar la actividad.


<?php require_once($CFG->dirroot . '/course/moodleform_mod.php'); class mod_mimodulo_mod_form extends moodleform_mod { function definition() { $mform = $this->_form; $mform->addElement('text', 'name', get_string('name', 'mimodulo'), ['size' => '64']); $mform->setType('name', PARAM_TEXT); $mform->addRule('name', null, 'required', null, 'client'); $this->standard_coursemodule_elements(); $this->add_action_buttons(); } }

5. lib.php

Contiene funciones principales del módulo.


<?php function mimodulo_add_instance($data, $mform) { global $DB; $data->timecreated = time(); return $DB->insert_record('mimodulo', $data); } function mimodulo_update_instance($data, $mform) { global $DB; $data->timemodified = time(); $data->id = $data->instance; return $DB->update_record('mimodulo', $data); } function mimodulo_delete_instance($id) { global $DB; return $DB->delete_records('mimodulo', ['id' => $id]); }

 6. view.php

Lo que el estudiante verá al ingresar a la actividad.


<?php require_once('../../config.php'); $id = required_param('id', PARAM_INT); $cm = get_coursemodule_from_id('mimodulo', $id, 0, false, MUST_EXIST); $context = context_module::instance($cm->id); require_login($cm->course, true, $cm); $PAGE->set_url('/mod/mimodulo/view.php', ['id' => $id]); $PAGE->set_context($context); $PAGE->set_title('Mi Módulo'); $PAGE->set_heading('Mi Módulo'); echo $OUTPUT->header(); echo $OUTPUT->heading('Hola, este es tu nuevo módulo en Moodle 🚀'); echo $OUTPUT->footer();

 Instalación del plugin

  1. Copia la carpeta mimodulo en moodle/mod/.

  2. Ve a tu Moodle como administrador.

  3. Moodle detectará automáticamente el nuevo plugin.

  4. Sigue el asistente de instalación.

  5. ¡Listo! Ya puedes usar tu módulo en cualquier curso.

 Prueba tu plugin

  1. Entra a un curso como administrador o profesor.

  2. Activa edición.

  3. Haz clic en “Agregar una actividad o recurso”.

  4. Verás "Mi Módulo" en la lista.

  5. Agrega una instancia y prueba su vista.


Este tutorial te brinda una base sólida para crear tu propio plugin de tipo actividad en Moodle  con php. A partir de aquí, puedes expandir la funcionalidad, agregar configuraciones, vistas personalizadas, lógica de calificación y mucho más.

Si te gustó este artículo y te fue útil, ¡compártelo!.

Este tutorial fue creado pensando en los desarrolladores que usan Moodle en Colombia, especialmente en Manizales, donde la tecnología educativa sigue creciendo y conectando comunidades de aprendizaje, el objetivo es de aprendizaje para que puedan aprender a crear un plugin y a partir de esto desarrollar el que requieran a medida.

Blogs Colombia