¡Bienvenido! ¿Aún no estás registrado?, deberás registrarte antes de poder usar el Chat, Comentar y Descargar en el Foro. Usa un email válido para la activación.
Últimos temas

Estadísticas del foro


Enviado por: edrien
01-11-2025, 12:45 AM
Foro: Pedido de Diseños
- Respuestas (3)

Hola chicoas, alguien tiene las comunidades responsive?

Imprimir


Enviado por: crassito
01-07-2025, 07:50 PM
Foro: Ayuda y Soporte
- Respuestas (6)

No me carga la imagen en el post, la de portada si, pero la de la portada, y en el movil no me carga la pagina el diseño.[img]Registrate o inicia tu sesión para ver este contenido[/img]

Imprimir


Enviado por: York0x
01-01-2025, 01:36 PM
Foro: Ayuda y Soporte
- Respuestas (2)

[img]Registrate o inicia tu sesión para ver este contenido[/img]
Tanto en las notificaciones como en los MPs tengo ese error, no se a que se debe, he buscado en Google y según ellos el fallo es de PHP.

Revisando el archivo "error_logs" no muestra el fallo, tampoco ha sido modificado ningún archivo.

Versión de PHP: 7.4

Imprimir


Enviado por: Miguel92
12-16-2024, 09:02 PM
Foro: Complementos Terminados
- Respuestas (1)

Pedido: Identificación con RRSS
Autor: York0x
 

Identificación con RRSS

Bueno, en realidad es algo que había creado para ZCode, lo pude haber hecho con alguna librería php para facilitarlo, pero como solamente requeria algunos servicios, poner un monton de archivos para no usarlo, se me hacia una perdida de recursos innecesarios, por lo cual he decidido dejar: Google, Discord, Github y Facebook.

A este 'MOD' lo hice para ZCode, por lo cual algunas cosas deberán adaptarlos ustedes a su tema, como por ejemplo la configuración de las redes sociales.

Solo colocaré enlaces de youtube para obtener las claves de cada uno, ya que se convertiría en un tutorial demasiado extenso.

Google: http://Registrate o inicia tu sesión par... contenido (Min. 12:49)
Twitter: http://Registrate o inicia tu sesión par... contenido (Min. 26:03) [sin uso, por el momento]
Facebook: http://Registrate o inicia tu sesión par... contenido (Min. 32:07)
Discord: http://Registrate o inicia tu sesión par... contenido (Hasta el min 02:05)
Github: http://Registrate o inicia tu sesión par... contenido

En el servidor de discord accediendo a este mensaje tendrás las formas de obtener las claves en modo guía, solo los pasos sin imágenes (y también están fijados en el canal "#actualizaciones")

Lo que realmente necesitaremos usar es Client-ID, Client-Secret y en RedirectURL/Callback le colocarás la url que da la administración de tu sitio.

1 - Ejecutar las siguentes consultas
 
Código PHP:
CREATE TABLE IF NOT EXISTS `miembros_social` (
`
social_idint(11NOT NULL AUTO_INCREMENT,
`
social_user_idint(11NOT NULL DEFAULT 0,
`
social_namevarchar(20NOT NULL DEFAULT '',
`
social_nickvarchar(24NOT NULL DEFAULT '',
`
social_emailvarchar(80NOT NULL DEFAULT '',
PRIMARY KEY (`social_id`)
ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=;

CREATE TABLE IF NOT EXISTS `settings_social` (
`
social_idint(11NOT NULL AUTO_INCREMENT,
`
social_namevarchar(22NOT NULL DEFAULT '',
`
social_client_idtinytext NULL,
`
social_client_secrettinytext NULL,
`
social_redirect_uritinytext NULL,
PRIMARY KEY (`social_id`)
ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=


2 - Agregar en .htaccess debajo de
 
Código PHP:
RewriteRule ^agregar.phpinc/php/agregar.php [QSA,L

añadir esto
 
Código PHP:
# CALLBACK PARA REDES SOCIALES
RewriteRule ^(github|discord|google|facebook|twitter)\.phpinc/callback/$1.php [QSA,L


3 - Agregar en header.php debajo de
 
Código PHP:
$smarty->assign('tsConfig'$tsCore->settings); 

esto
 
Código PHP:
$smarty->assign('SocialMager'$tsCore->OAuth()); 


4 - Ir a inc/class/c.core.php y arriba de la última llave } agregan lo siguiente
 
Código PHP:
    public function getEndPoints(string $social ''string $type '') {
        
$getEndPoints = [
            
'github' => [
                
'authorize' => 'Registrate o inicia tu sesión para ver este contenido
                '
token' => "Registrate o inicia tu sesión para ver este contenido",
                '
revoke' => "",
                '
user' => "Registrate o inicia tu sesión para ver este contenido",
                '
scope' => "user"
            ],
            '
discord' => [
                '
authorize' => 'Registrate o inicia tu sesión para ver este contenido
                
'token' => "Registrate o inicia tu sesión para ver este contenido",
                
'revoke' => "Registrate o inicia tu sesión para ver este contenido",
                
'user' => "Registrate o inicia tu sesión para ver este contenido@me",
                
'scope' => "email identify"
            
],
            
'google' => [
                
'authorize' => 'Registrate o inicia tu sesión para ver este contenido
                '
token' => "Registrate o inicia tu sesión para ver este contenido",
                '
user' => "Registrate o inicia tu sesión para ver este contenido",
                '
revoke' => "",
                '
scope' => "Registrate o inicia tu sesión para ver este contenido Registrate o inicia tu sesión para ver este contenido"
            ],
            '
facebook' => [
                '
authorize' => "Registrate o inicia tu sesión para ver este contenido",
                '
token' => "Registrate o inicia tu sesión para ver este contenido",
                '
revoke' => "",
                '
user' => "Registrate o inicia tu sesión para ver este contenido",
                '
scope' => "email,public_profile"
            ]
        ];
        return $getEndPoints[$social][$type];
    }

    /**
     * Genera URLs de autorización OAuth para diferentes proveedores sociales.
     *
     * @return array Un array asociativo con el nombre del proveedor como clave y la URL de autorización como valor.
     */
    public function OAuth(string $redirect = ''): array {
       // Obtener la lista de proveedores OAuth
       $OAuths = result_array(db_exec([__FILE__, __LINE__], '
query', 'SELECT social_namesocial_client_idsocial_client_secretsocial_redirect_uri FROM settings_social'));
       $routes = [];
        
       foreach ($OAuths as $auth) {
          // Preparar los parámetros para la solicitud OAuth
          $parameters['
client_id'] = $auth['social_client_id'];
          $parameters['
scope'] = $this->getEndPoints($auth['social_name'], 'scope');
          $parameters['
response_type'] = ($auth['social_name'] === 'github') ? '' : 'code';
          $parameters['
redirect_uri'] = $auth['social_redirect_uri'];
          // Eliminar el parámetro response_type si es '
github'
          if ($auth['
social_name'] === 'github') {
             unset($parameters['
response_type']);
          }
          if(in_array($auth['
social_name'], ['google', 'discord'])) {
                $parameters['
prompt'] = 'consent';
            }
          // Construir la URL de autorización
          $queryString = http_build_query(array_filter($parameters));
          $authorizeUrl = $this->getEndPoints($auth['
social_name'], 'authorize');
          $routes[$auth['
social_name']] = "$authorizeUrl?$queryString";
       }
       return $routes;
    } 


5 - Ir a inc/class/c.cuenta.php y justo debajo de
 
Código PHP:
class tsCuenta 

agregan
 
Código PHP:
    private function getSocialUser(int $user_id 0) {
        
// Redes viculadas
        
$socials result_array(db_exec([__FILE____LINE__], 'query'"SELECT social_name as name FROM miembros_social WHERE social_user_id = $user_id"));
        
$array_social = [
            
'discord' => false,
            
'facebook' => false,
            
'github' => false,
            
'google' => false
        
];
        foreach(
$socials as $sn) {
            
$name $sn['name'];
            if (isset(
$array_social[$name])) {
                
$array_social[$name] = true;
            }
        }
        return 
$array_social;
    } 

Luego dentro de la función
 
Código PHP:
public function loadPerfil($user_id 0){ 

buscar
 
Código PHP:
$perfilInfo $this->unData($perfilInfo); 

y agregar debajo
 
Código PHP:
$perfilInfo['socials'] = $this->getSocialUser($user_id); 


6 - Luego en inc/class/c.user.php y arriba de la funcion
 
Código PHP:
public function loginUser(...) 

agregar lo siguiente
 
Código PHP:
    /*
     * Desconectar la red social de nuestra cuenta
    */
    
public function unlinkAccount() {
        global 
$tsCore;
        
# Buscamos para desactivar
        
$delete $tsCore->setSecure($_POST['social']);
        if(
$this->is_member) {
            
$data db_exec('fetch_assoc'db_exec([__FILE____LINE__], 'query'"SELECT u.user_id, m.social_id, m.social_name FROM u_miembros AS u LEFT JOIN miembros_social AS m ON m.social_user_id = u.user_id WHERE u.user_id = {$this->uid} AND m.social_name = '$delete' LIMIT 1"));
            
$sid = (int)$data['social_id'];
            
// Actualizamos la tabla
            
return (db_exec([__FILE____LINE__], 'query'"DELETE FROM miembros_social WHERE social_id = $sid AND social_name = '$delete' AND social_user_id = {$this->uid}")) ? true false;
        }
    }
    
/**
     * Se repiten en 2 funciones diferentes
    */
    
public function sessionUpdate(int $id 0bool $rem true) {
        
// Actualizamos la session
        
$this->session->update($id$remTRUE);
        
$this->loadUser(true);
        
$this->DarMedalla();
    } 

luego buscar en la funcion
 
Código PHP:
public function loginUser(...) 

buscamos
 
Código PHP:
$this->session->update($data['user_id'], $rememberTRUE);
$this->loadUser(true);
$this->DarMedalla(); 

y reemplazamos
 
Código PHP:
$this->sessionUpdate($data['user_id'], $remember); 


7 - Ir a inc/php/admin.php y arriba de
 
Código PHP:
} elseif($action == 'configs'){ 

añadir
 
Código PHP:
    // Redes sociales
    
} elseif($action === 'socials') {
        
// CLASE MEDAL
        
require_once TS_CLASS "c.socials.php";
        
$tsSocials = new tsSocials();
        
$smarty->assign('tsNetsSocials', [
            
'discord' => 'Discord',
            
'facebook' => 'Facebook',
            
'github' => 'Github',
            
'google' => 'Google'
        
]);
        
//
        
$tsTitle 'Configurar redes sociales';
        if(empty(
$act)) $smarty->assign('tsSocials'$tsSocials->getSocials());
        
// Editar o Nuevo tema
        
elseif(in_array($act, ['editar''nueva'])) {
            
$tsTitle ucfirst($act) . ' red social';
            if(!empty(
$_POST['save']) OR !empty($_POST['edit'])) {
                
$social = ($act === 'editar') ? $tsSocials->saveSocial() : $tsSocials->newSocial();
                if(
$social$tsCore->redirectTo($tsCore->settings['url'].'/admin/socials?save=true');
            } else {
                if(
$act === 'editar'$smarty->assign("tsSocial"$tsSocials->getSocial());
                if(
$act === 'nuevo'$smarty->assign("tsError"$tsSocials->newSocial());
            } 
        } elseif(
$act === 'borrar') {
            if(
$tsSocials->eliminarRed()) $tsCore->redirectTo($tsCore->settings['url'].'/admin/socials?save=true');
        } 


8 - Ir a themes/TUTEMA/js/admin.js y agregar al final
 
Código PHP:
$(document).ready(() => {
    
let redirectURI = $('#redirect_uri');
    if(empty(
redirectURI.val())) redirectURI.val(`${global_data.url}/discord.php`)
   $(
'#social_name').on('change', () => {
       
let replace = $('#social_name option:selected').val() ;
       
redirectURI.val(`${global_data.url}/${replace}.php`);
   });
   $(
"#botonCopiar").on("click", function() {
      
redirectURI.select();
      
document.execCommand("copy");
      
window.getSelection().removeAllRanges();
      $(
this).html("Redirect URL ha sido copiado correctamente!");
      
setTimeout(() => $(this).html('Copiar'), 5000);
   });
}); 


9 - Ir a themes/TUTEMA/js/cuenta.js al principio o final (donde quieran) agregan
 
Código PHP:
function desvincular(social) {
    $.
post(`${global_data.url}/cuenta-desvincular.php`, { social }, req => {
        if(
req) {
            
mydialog.show();
            
mydialog.title('Bien');
            
mydialog.body('Ha sido desvinculado correctamente.');
            
mydialog.buttons(truetrue'Listo''mydialog.close();'truetruefalse);
            
mydialog.center();
        }
    });



10 - Ir a themes/TUTEMA/sections/main_header.tpl y arriba de
 
Código PHP:
<link href="{$tsConfig.tema.t_url}/estilos.css" rel="stylesheet" type="text/css"

esto
 
Código PHP:
<link href="{$tsConfig.tema.t_url}/socialButton.css" rel="stylesheet" type="text/css"


11 - Ir a themes/TUTEMA/templates/t.admin.tpl y debajo de
 
Código PHP:
{include file='admin_mods/m.admin_configs.tpl'

agregar
 
Código PHP:
{elseif $tsAction == 'socials'}
{include 
file='admin_mods/m.admin_socials.tpl'


12 - Ir a themes/TUTEMA/templates/admin_mods/m.admin_sidebar.tpl y debajo de
 
Código PHP:
<li id="a_creditos"><span class="cat-title"><a href="{$tsConfig.url}/admin/creditos">Soporte y Cr&eacute;ditos</a></span></li

añadir
 
Código PHP:
<li id="a_socials"><span class="cat-title"><a href="{$tsConfig.url}/admin/socials">Configurar redes</a></span></li


13 - Ir a themes/TUTEMA/template/modules/m.cuenta_sidebar.tpl (agregalo donde quieras)
 
Código PHP:
<div class="">
    <
h4>Tus redes sociales</h4>
    {foreach 
from=$SocialMager key=nombre item=social}
       <
div class="btn-group-socials d-block">
             <
class="btn btn--{$nombre}href="{if $tsPerfil.socials.$nombre}javascript:desvincular('{$nombre}'){else}{$social}{/if}">
                 <
span class="btn--icon"><span class="icon_social icon_{$nombre}"></span></span>
                <
span class="btn--text">{if $tsPerfil.socials.$nombre}Desv{else}V{/if}incular {$nombre}</span>
             </
a>
       </
div>
    {
foreachelse}
        <
div class="empty">Conexiones a tus redes socialespero aun {$tsConfig.titulono las ha configurado!</div>
    {/foreach}
</
div


14 - Ir a themes/TUTEMA/template/t.login.tpl añaden, ya que con esto podrán iniciar sesión desde alguna red social
 
Código PHP:
{if $SocialMager}
    <
div class="buttons-social">
        {foreach 
from=$SocialMager key=nombre item=social}
            <
class="btn btn--{$nombre} btn--only-icon btn-active" href="{$social}">
                <
span class="btn--icon"><span class="icon_social icon_{$nombre}"></span></span>
                <
span class="btn--text">Iniciar con {$nombre}</span>
            </
a>
        {/foreach}
    </
div>
{/if} 


15 - Ir a themes/TUTEMA/template/t.registro.tpl añaden, ya que con esto podrán crear cuenta desde alguna red social
 
Código PHP:
{if $SocialMager}
    <
div class="buttons-social">
        {foreach 
from=$SocialMager key=nombre item=social}
            <
class="btn btn--{$nombre} btn--only-icon btn-active" href="{$social}">
                <
span class="btn--icon"><span class="icon_social icon_{$nombre}"></span></span>
                <
span class="btn--text">Crear cuenta con {$nombre}</span>
            </
a>
        {/foreach}
    </
div>
{/if} 


En el punto 14 y 15 tiene la clase 'btn--only-icon', el cual claramente muestra solo el icono, si quieren visualizar el texto deberán borrar dicha clase

Descargar los archivos 
c.socials.php en inc/class/
m.admin_socials.tpl en themes/TUTEMA/templates/admin_mods
socialButtons.css en themes/TUTEMA/

Imprimir


Enviado por: York0x
12-16-2024, 02:30 PM
Foro: Pedido de Complementos
- Sin respuestas

¡Hola a todos! 👋
He estado pensando en una mejora que podría hacer más fácil y accesible nuestra comunidad de PHPost: implementar la posibilidad de registrarse e iniciar sesión usando redes sociales como Facebook, Google, Twitter, entre otras.
 
💡 ¿Por qué sería útil?

  • Más rápido y sencillo: No sería necesario llenar formularios largos, solo unos clics y listo.
  • Mayor comodidad: Muchas personas prefieren usar una cuenta existente en lugar de recordar otro usuario/contraseña.
  • Aumenta la cantidad de usuarios: La facilidad de registro podría atraer a más personas a unirse y participar en la comunidad.
  • Actualización del sistema: Esto también haría que PHPost se mantenga actualizado con tendencias modernas en plataformas web.

Imprimir


Enviado por: EZZIFY
12-01-2024, 10:29 PM
Foro: Librerías JavaScript
- Respuestas (1)

¡Hola a todos!
Esta mañana, mientras navegaba por aqui, me encontré con un interesante efecto de veladoras que me inspiró a desarrollar un pequeño código que genera un efecto de nieve.
Quiero compartirlo con ustedes, ya que puede darle un toque especial a sus sitios web.

Ligero:
El script pesa apenas 3 KB sin minificar, por lo que no impactará significativamente en el rendimiento de tu sitio.
Responsivo:
El número de copos de nieve se ajusta automáticamente según el tamaño de la pantalla, con un máximo de 200 copos para evitar sobrecargas.
Interactivo:
si un usuario hace clic en uno, este se elimina. Esto garantiza que no interfiera con la interacción del usuario en tu sitio, como hacer clic en botones o enlaces.
Fácil de personalizar:
El código está diseñado para ser sencillo y claro, permitiéndote personalizar fácilmente aspectos como tamaño, velocidad o cantidad de copos.
Seguro y optimizado:
Incluye medidas para evitar la sobrecarga del DOM, gracias a un manejo eficiente de temporizadores y la limpieza de elementos no necesarios.

Demo:
http://Registrate o inicia tu sesión par... contenido

Instalación:

  1. Copia el fragmento de código y pégalo en tu archivo HTML.
  2. Ubicación recomendada:
    Puedes colocarlo dentro de las etiquetas 
    <head> o al final de <body>, dependiendo de tus necesidades:
    • Dentro de <head> 
      si quieres que los estilos y animaciones estén disponibles desde el inicio de la carga de la página.
    • Dentro de <body>
       si prefieres cargar el efecto después del contenido principal.
Código:
<script>
    (async function () {
        const loadStyles = () => {
            const style = document.createElement("style");
            style.innerHTML = `.snowflake {position: fixed;width: 11px;height: 11px;background: white;border-radius: 50%;animation: fall linear infinite;top: -16px;transition: width 0.6s ease, height 0.6s ease;}.small-snowflakes .snowflake {width: 7px;height: 7px;}@keyframes fall {0% {transform: translate(var(--start-x), -10px) scale(var(--scale));opacity: var(--opacity);}50% {transform: translate(var(--end-x), var(--mid-y)) scale(var(--scale));opacity: var(--opacity);}100% {transform: translate(var(--end-x-final), 100vh) scale(var(--scale));opacity: 0;}}`;
            document.head.appendChild(style);
        };
        const generateSnowflakes = () => {
            const screenWidth = window.innerWidth;
            const baseCount = 200;
            const snowflakeCount = Math.min(baseCount, Math.floor(screenWidth / 5));
            for (let i = 0; i < snowflakeCount; i++) {
                const snowflake = document.createElement('div');
                snowflake.className = 'snowflake';
                const startX = Math.random() * 100 + 'vw';
                snowflake.style.setProperty('--start-x', startX);
                snowflake.style.setProperty('--end-x', `calc(${startX} + ${(Math.random() - 0.5) * 20}vw)`);
                snowflake.style.setProperty('--end-x-final', `calc(${startX} + ${(Math.random() - 0.5) * 10}vw)`);
                snowflake.style.setProperty('--mid-y', Math.random() * 50 + 50 + '%');
                snowflake.style.setProperty('--scale', Math.random() * 0.5 + 0.5);
                snowflake.style.setProperty('--opacity', Math.random() * 0.5 + 0.5);
                snowflake.style.animationDuration = Math.random() * 15 + 10 + 's';
                snowflake.style.animationDelay = Math.random() * -30 + 's';
                document.body.appendChild(snowflake);
            }
            clearTimeout(window.snowTimer);
            window.snowTimer = setTimeout(() => {
                document.body.classList.add('small-snowflakes');
            }, 3000);
        };
        const debounceResize = (func, delay = 300) => {
            let timer;
            return function (...args) {
                clearTimeout(timer);
                timer = setTimeout(() => func.apply(this, args), delay);
            };
        };
        const init = () => {
            loadStyles();
            generateSnowflakes();
            document.body.addEventListener('click', event => {
                if (event.target.classList.contains('snowflake')) {
                    event.target.remove();
                }
            });
            const handleResize = debounceResize(() => {
                document.querySelectorAll('.snowflake').forEach(snowflake => snowflake.remove());
                generateSnowflakes();
            });
            window.addEventListener('resize', handleResize);
        };
        while (true) {
            if (document.readyState === 'complete') {
                init();
                break;
            }
            await new Promise(resolve => setTimeout(resolve, 100));
        }
    })();
</script>

Imprimir


Enviado por: jocker
11-21-2024, 12:14 AM
Foro: Preséntanos tu web
- Respuestas (1)

bueno ya creo que todos ya saben de mi y de mis webs
bueno despues de estar tanto tiempo en las sombras quise volver a resubir una web que tenia hace años atras
ya creo que muchos conocieron a   Rompela!  una web que sus tiempos fue grande y deje de albergar ...
bueno la re abri nuevamente y quien quiera unirse bien y
de a poco ire haciendola crecer
estamos arrancando con el script de @Miguel92#23  el cual encuentro bueno y estable y sera el que quedara en la web

unete a rompela.net

[img]Registrate o inicia tu sesión para ver este contenido[/img]

Imprimir


Enviado por: moyo
09-27-2024, 02:05 AM
Foro: Ayuda y Soporte
- Respuestas (4)

¿Cómo mostrar la portada en la página del post?

Teniendo lo siguiente:
 

Código:
<img title="{$p.post_title}" src="{$tsConfig.url}/files/portadas/toup{$p.post_portada}P240X180.jpg">

Imprimir


Enviado por: Krsh
09-23-2024, 08:21 AM
Foro: Ayuda y Soporte
- Respuestas (5)

Hola, me di cuenta que me salen varios errores en la administración, quería saber si alguien me puede ayudar a resolver, los errores son en varias secciones

Sesiones: 
 

Código:
Fatal error: Uncaught Error: Call to undefined method tsAdmin::GetAdminStats() in D:\xampp\htdocs\inc\php\admin.php:145 Stack trace: #0 {main} thrown in D:\xampp\htdocs\inc\php\admin.php on line 145


Blacklist
 
Código:
Fatal error: Uncaught Error: Call to undefined method tsAdmin::getBlackList() in D:\xampp\htdocs\inc\php\admin.php:157 Stack trace: #0 {main} thrown in D:\xampp\htdocs\inc\php\admin.php on line 157


Censuras:
 
Código:
Fatal error: Uncaught Error: Call to undefined method tsAdmin::getBadWords() in D:\xampp\htdocs\inc\php\admin.php:174 Stack trace: #0 {main} thrown in D:\xampp\htdocs\inc\php\admin.php on line 174


Todos los post;
 
Código:
Fatal error: Uncaught Error: Call to undefined method tsAdmin::GetAdminPosts() in D:\xampp\htdocs\inc\php\admin.php:135 Stack trace: #0 {main} thrown in D:\xampp\htdocs\inc\php\admin.php on line 135


Sesiones:
 
Código:
Fatal error: Uncaught Error: Call to undefined method tsAdmin::GetSessions() in D:\xampp\htdocs\inc\php\admin.php:191 Stack trace: #0 {main} thrown in D:\xampp\htdocs\inc\php\admin.php on line 191


Cambio de nick:
 
Código:
Fatal error: Uncaught Error: Call to undefined method tsAdmin::getChangeNicks() in D:\xampp\htdocs\inc\php\admin.php:150 Stack trace: #0 {main} thrown in D:\xampp\htdocs\inc\php\admin.php on line 150


alguien me pudiera ayudar a saber porque paso? 
les adjunto mi archivo de admin.php

Imprimir


Enviado por: edrien
09-16-2024, 12:23 AM
Foro: Presentaciones
- Respuestas (2)

Hola a todos me presento, soy Edrien, un nuevo usuario en el foro.

Imprimir