changed style

This commit is contained in:
Orson 2025-04-16 12:41:23 -06:00
parent ad8e28697a
commit 00f54327d5
10 changed files with 346 additions and 184 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 KiB

View File

@ -25,9 +25,15 @@ body, html, canvas {
background-size: 20px 20px;
{% block bgstuff %}
background-color: white;
background-color: black;
color: green;
{% endblock %}
font-family: 'Quicksand', sans-serif;
cursor: crosshair;
}
body a {
color:color-mix(in hsl shorter hue, color percentage, color percentage)
}
canvas {
display:block;
@ -58,7 +64,7 @@ canvas {
}
a {
font-size: large;
color: black;
color: red;
}
.button:hover {
background-color: #888;
@ -141,16 +147,43 @@ header nav ul li {
div.page {
background: #f1fbfe;
}
#grid-canvas,
#particle-canvas {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
pointer-events: none;
}
#grid {
position: absolute;
width: 100%;
height: 100%;
background: radial-gradient(circle closest-side, transparent 98%, #000 100%) 50% 50% / 10% 10%;
background-repeat: no-repeat;
#grid-canvas {
z-index: -20; /* bottom layer */
}
#particle-canvas {
background-color: rgba(0, 0, 0, 0);
z-index: 10002; /* above grid, below everything else */
}
#coords {
position: fixed;
bottom: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.6);
color: #0f0;
padding: 6px 10px;
border-radius: 5px;
font-family: monospace;
z-index: 1001;
transition: all 0.2s ease;
cursor: crosshair;
user-select: none;
}
#coords.decrypted {
background: rgba(0, 0, 0, 0.85);
color: #fff;
}

View File

@ -0,0 +1 @@
image:

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

View File

@ -0,0 +1,23 @@
image:
---
author: st4t3
---
body:
Cada año que no vamos al Chaos Communication Congress es otro año en el que soñamos con estar allá. Por si no saben de qué se trata ~~shame on you~~, es el congreso más grande de hackers en Europa, y el segundo más grande del mundo, sólo después de Defcon. La gran distinción es que mientras Defcon se enfoca en el aspecto corpo-cibersecuritario de la comunidad, el CCC es para hackers en el sentido amplio de la palabra. Sí, por supuesto que hay charlas respecto a cómo entrar en sistemas a la fuerza, o romper barreras electrónicas, o descomponer los planes maliciosos de terceros de irrumpir en lugares donde no deberían. Sin embargo, el congreso alemán se nutre también del arte electrónico, la cultura libre decentralizada y los proyectos comunitarios que se presentan, se presumen y se propagan desde allá.
Nuestra participación, desde KPR, en los congresos que hemos visitado en México en este último par de años ha sido un intento de acercar esa clase de ideas a la banda de por acá. En particular, la propuesta que llevamos a BugCON oficialmente este año y luego compartimos también en Posadev se trató justamente de la necesidad de crear redes de espacios permanentes en nuestro país, donde claramente nos hacen mucha falta.
El CCC no se siente simplemente como un congreso y ya. Se vive como una gran kermés, como una ciudad de los niños, pero para hackers. Como un universo mágico que se puede propagar, con tan solo intentarlo, más allá de los confines del centro de congresos de Hamburgo, hasta los lugares más recónditos del planeta. Afortunadamente, habemus internet, y la gente que organiza el congreso tiene a bien montar streams de las pláticas en tiempo real y luego subirlas a su archivo. No es posible transmitir la vibra del evento remotamente, pero sí las ideas que se comparten por allá. Por eso nos tomamos muy en serio sentarnos a ver esas transmisiones en el momento, para tener al menos una oportunidad de combatir el insoportable, inevitable FOMO de no estar por allá.
Esperemos que con cada año nuestras comunidades de este lado del charco se hagan más grandes y más fuertes. Es momento de apoyar con todo los congresos nacionales, el Bugcon, HackGDL, Posadev, Bsides, Pwnterrey, que apenas va arrancando, así como los espacios que tenemos malamente repartidos por el país, incluyendo el Rancho Electrónico y HackerGarage, pero también los espacios emergentes como Pwntacles o el hacklab de Colima.
Somos suficientes para hacer una cosa GRANDE, pero nos falta juntarnos y apoyarnos en grande también.
¡Feliz y próspero año nuevo! Que este nuevo ciclo alrededor del Sol nos traiga lo que queremos, pero también lo que necesitamos
---
pub_date: 2024-12-31
---
title: FOMO of the con-less mind
---
twitter_handle: @botkernel

View File

@ -0,0 +1,26 @@
image: https://external-content.duckduckgo.com/iu/?u=http%3A%2F%2Fi2.kym-cdn.com%2Fphotos%2Fimages%2Ffacebook%2F001%2F085%2F385%2Fd33.png&f=1&nofb=1&ipt=3cc5c477011123db2292c249b7b4f813d340ee8a3e009e3376620df7bac69677&ipo=images
---
author: st4t3
---
body:
Todos los años hay quien anuncia que finalmente ha llegado el "año del Linux de escritorio", pero a pesar de todo el progreso que han hecho las comunidades (y algunas empresas) alrededor de la familia de distribuciones de GNU/Linux, la gran mayoría sigue prefiriendo uno de los sistemas operativos "tradicionales", SteveOS o Winblows. En parte, por supuesto, tiene que ver con el halo de dificultad y ocultismo que conllevan las palabras "software libre" y "sistema operativo distinto". Sin embargo, la barrera técnica de entrada al mundo de GNU/Linux ha mejorado incansablemente durante las décadas de su exitencia, y la mejora se afianza, y se acelera cada vez más.
Un problema más serio, quizá, en el mundo mediatizado y comercialmente viable en el que vivimos, es que las soluciones "alternativas", comunitarias como tu distro favorita, no son tan "amigables" en el sentido de la integración "semaless", sin pedos pues, entre los distintos dispositivos (espías) que nos hemos acostumbrado a cargar (pun intended) todos los días. Esa también ha mejorado, pero no existe una sola cosa que unifique, por ejemplo, todo el software en GNU/Linux que simule una experiencia estilo AirDrop entre dos máquinas. La "nube personal" es relativamente difícil de conseguir, requiriendo comprensión de algunas cosas, pero sobre todo ganas de RTFM, cosa que no mucha gente tiene hoy en día, con el implacable avance de ~~la estupidificación~~ la "user-friendlinezación" de la tecnología.
Encontré una combinación de elementos que me parece suficientemente integrada y fácil de utilizar como para poder competir con soluciones corporativas. La "nube personal" se trata de tener documentos compartidos entre máquinas personales con el menor contacto/dependencia posible de las computadoras de alguien más, incluyendo, pero no limitándose a, servidores privados en renta. El stack que utilizo es el siguiente:
- - **Headscale + Tailscale / Innernet** - uno de los problemas centrales de conectar máquinas entre ellas es que las IPs que son asignadas por los routers locales en cada red son siempre dinámicas. Para poder contactar con certeza un dispositivo remoto, metemos todos nuestros dispositivos a una sola red virtual que les asigna una dirección estática. Además, tanto Tailscale como Innernet están basados en el protocólo Wireguard, que es la punta de lanza en este tipo de software. La mejor manera de ejemplificar cómo funciona es lanzando un ping a cualquier IP existente en la subred. El primer paquete va al servidor de headscale, pero de ahí en adelante, la conexión es directamente con la máquina solicitada.
- - **Syncthing** - una solución de software libre, peer-to-peer, que ter permite crear directorios compartidos entre máquinas y actualizar esos directorios fácilmente por medio de la VPN o red local.
- - **scrcpy** - un programa miniatura que sirve para controlar tu dispositivo móvil por medio de la computadora, con la pantalla del celular en una ventanita en tu escritorio.
- - **KDE Connect** - para conectar directamente tu celular y tu computadora y poder recibir notificaciones del primero en la segunda.
¿Qué más falta en tu opinión para hacer de esto un sistema total? ¿Qué funciones estamos obviando que te parecen cruciales? Cuéntanos en el Twatter o Telegram.
---
pub_date: 2024-12-27
---
title: Otro año más de la desktop con Linux.
---
twitter_handle: @botkernel

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

View File

@ -0,0 +1,32 @@
_model: page
---
title: FLISoL 2025 en Kernel Panic Room
---
_slug: flisol2025
---
body:
== Acción ==
Plancha esa USB y destroza su sistema de archivos. Fórzala a retener entre sus átomos de silicio el código genético de un sistema operativo libre y luego obliga a tu laptop a hablar nuevos lenguajes
== Suspenso ==
Minutos cardiácos, momentos de incertidumbre cuando la pantalla se pone negra, sólo muestra una barrita blanca, pero cada instante llega a su fin. De pronto, la laptop se ilumina de colores nuevos que jamás habías visto en lugar del negro o el azul de siempre. ¡La máquina vive y su vida es nueva!
== Diversión ==
Aprender a hablar con una máquina de maneras distintas nunca ha sido más emocionante. El mundo del software libre no sólo implica el acceso a tecnologías distintas, sino también a un universo cultural único e inigualable. No podría ser de otra manera - para que millones de personas trabajando voluntariamente y en conjunto logren producir sistemas operativos y programas, generar y resolver retos, explorar la vastedad del mundo interconectado, tienen que tener a fuerza buen sentido del humor.
= Actividades =
El FLISoL es un evento autogestivo, gratuito y libre. Si tienes una actividad que quisieras proponer, agregate al pad que tenemos aquí - https://pad.riseup.net/p/FLISoLQueretaro2025-keep y danos un rango de tiempo que te funcione para presentar. Si sólo quieres venir a escuchar, o a husmear, también se vale, ¡nos dará gusto conocerte!
= Contacto =
Síguenos en X (@botkernel)
Únete a nuestro espacio en Matrix (https://matrix.to/#/!gthFfWXxCWzeFTjxKL:matrix.org)
Búscanos en Telegram (@kprftw)

View File

@ -31,7 +31,13 @@
</head>
<body>
<canvas id="grid-canvas"></canvas>
<canvas id="particle-canvas"></canvas>
<!-- Llegaste al código, a ver cáele al telegram -> [arroba]kprftw -->
<div id="banner">
<a href="{{'flisol2025'|url}}" style="max-width:100%"><img style="max-width: inherit;" src="/static/bannerflisol.png" alt="Libera tu máquina, tu alma es la siguiente"></a>
</div>
<div id="topbar">
{% block topbar %}
<a href="/"><div class="button">a casa</div></a>
@ -40,6 +46,7 @@
<a href="{{'/about'|url}}"><div class="button">qué es esto</div></a>
<a href="{{'/somos/'|url}}"><div class="button">quiénes somos</div></a>
<a href="{{'/blog'|url}}"><div class="button">blog</div></a>
<a href="https://eventos.kernelpanic.lol"><div class="button">calendario</div></a>
<a href="https://box.kernelpanic.lol"><div class="button">proyectos</div></a>
<!--<a href="/censo-hacker-latinoamericane-2023"><div class="button">participa en el censo</div></a>-->
<!--<a href="https://pat.kernelpanic.lol/calendar/#/2/calendar/view/CH1zbFeFKLPO5SPle5JNxjKqdSaidbYPYBKFC4PDSus/embed/"><div class="button">calendario</div></a> -->
@ -52,169 +59,213 @@
{% block body %}{% endblock %}
</div>
<script>
const gridCanvas = document.getElementById('grid-canvas');
const gridCtx = gridCanvas.getContext('2d');
function resizeGridCanvas() {
gridCanvas.width = window.innerWidth;
gridCanvas.height = window.innerHeight;
}
resizeGridCanvas();
window.addEventListener('resize', resizeGridCanvas);
function drawGrid(centerX, centerY) {
const spacing = 180;
const size = 20;
const distortion = 10;
gridCtx.clearRect(0, 0, gridCanvas.width, gridCanvas.height);
for (let i = 0; i < gridCanvas.width; i += spacing) {
for (let j = 0; j < gridCanvas.height; j += spacing) {
let dx = i - centerX;
let dy = j - centerY;
let dist = Math.sqrt(dx * dx + dy * dy);
let offset = dist / distortion;
let x = i + dx / offset;
let y = j + dy / offset;
gridCtx.fillRect(x, y, size, size);
if (i > 0) {
gridCtx.beginPath();
gridCtx.moveTo(x, y + size / 2);
gridCtx.lineTo(x - spacing, j + dy / (dist / (distortion * spacing)) + size / 2);
gridCtx.stroke();
}
if (j > 0) {
gridCtx.beginPath();
gridCtx.moveTo(x + size / 2, y);
gridCtx.lineTo(i + dx / (dist / (distortion * spacing)) + size / 2, y - spacing);
gridCtx.stroke();
}
}
}
}
gridCanvas.addEventListener('mousemove', (e) => {
drawGrid(e.clientX, e.clientY);
});
drawGrid(gridCanvas.width / 2, gridCanvas.height / 2);
</script>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
#vertical-line, #horizontal-line {
position: fixed;
background-color: red;
pointer-events: none;
z-index: 1000;
}
#vertical-line {
width: 1px;
height: 100%;
top: 0;
}
#horizontal-line {
height: 1px;
width: 100%;
left: 0;
}
</style>
<script>
document.body.addEventListener('click', function () {
var randomColor = 'rgb(' +
Math.floor(Math.random() * 256) + ',' +
Math.floor(Math.random() * 256) + ',' +
Math.floor(Math.random() * 256) + ')';
document.body.style.backgroundColor = randomColor;
document.getElementById('topbar').style.backgroundColor = randomColor;
var rgb = randomColor.match(/\d+/g).map(Number);
// Calculate the brightness of the color
var brightness = Math.round((parseInt(rgb[0]) * 299 + parseInt(rgb[1]) * 587 + parseInt(rgb[2]) * 114) / 1000);
// Choose black or white for the font color based on the brightness
var randomFontColor = brightness > 150 ? 'black' : 'white';
document.body.style.color = randomFontColor;
});
var buttons = document.querySelectorAll('.button');
buttons.forEach(function(button) {
button.addEventListener('mouseover', function() {
var randomColor = 'rgb(' +
Math.floor(Math.random() * 256) + ',' +
Math.floor(Math.random() * 256) + ',' +
Math.floor(Math.random() * 256) + ')';
const canvas = document.getElementById('particle-canvas');
const ctx = canvas.getContext('2d');
ctx.globalCompositeOperation = 'xor';
let particles = [];
// Convert the RGB color to an array of numbers
var rgb = randomColor.match(/\d+/g).map(Number);
// Calculate the brightness of the color
var brightness = Math.round((parseInt(rgb[0]) * 299 + parseInt(rgb[1]) * 587 + parseInt(rgb[2]) * 114) / 1000);
// Choose black or white for the font color based on the brightness
var randomFontColor = brightness > 150 ? 'black' : 'white';
this.style.backgroundColor = randomColor;
this.style.color = randomFontColor;
});
});
</script>
<!-- THIS IS THE GRADIENT MORPHING BUTTON
<script>
const button = document.getElementById('colorButton');
let t = 0;
function generateColor(t, phase) {
return Math.floor((Math.sin(t + phase) + 1) * 128);
const glitchColors = ['#00ff00', '#66ff66', '#ccffcc'];
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function updateGradient() {
const r1 = generateColor(t, 0);
const g1 = generateColor(t, 2);
const b1 = generateColor(t, 4);
const color1 = `rgb(${r1}, ${g1}, ${b1})`;
const r2 = generateColor(t, 6);
const g2 = generateColor(t, 8);
const b2 = generateColor(t, 10);
const color2 = `rgb(${r2}, ${g2}, ${b2})`;
button.style.background = `linear-gradient(to right, ${color1}, ${color2})`;
t += 0.01;
}
setInterval(updateGradient, 1000 / 600); // 60 frames per second for a smooth transition
</script>-->
<!--<script>
document.addEventListener('DOMContentLoaded', function() {
const endpoint = "https://kernelpanic.lol/spacestats"; // Replace with your actual endpoint
const button = document.getElementById('spaceStatusButton');
fetch(endpoint)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
updateButtonStatus(button, data.state.open);
})
.catch(error => {
console.error('There has been a problem with your fetch operation:', error);
button.textContent = 'Error fetching status';
});
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
document.addEventListener('mousemove', (e) => {
for (let i = 0; i < 1; i++) {
particles.push({
x: e.clientX,
y: e.clientY,
dx: (Math.random() - 0.5) * 1.5,
dy: (Math.random() - 0.5) * 1.5,
size: Math.floor(Math.random() * 4 + 2), // Pixel chunk
alpha: 1,
color: glitchColors[Math.floor(Math.random() * glitchColors.length)]
});
}
});
function updateButtonStatus(button, status) {
if (status === 'true') {
button.textContent = 'Estamos aquí';
button.style.backgroundColor = 'green';
} else if (status === 'false') {
button.textContent = 'No estamos';
button.style.backgroundColor = 'red';
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.x += p.dx + (Math.random() - 0.5) * 2; // glitch flicker
p.y += p.dy + (Math.random() - 0.5) * 2;
p.alpha -= 0.02;
if (p.alpha <= 0) {
particles.splice(i, 1);
} else {
button.textContent = 'Algo raro sucede';
button.style.backgroundColor = 'grey';
ctx.fillStyle = p.color;
ctx.globalAlpha = p.alpha;
ctx.fillRect(Math.floor(p.x), Math.floor(p.y), p.size, p.size);
ctx.globalAlpha = 1;
}
}
requestAnimationFrame(animate);
}
</script>-->
<script>
var canvas = document.getElementById('body');
var ctx = canvas.getContext('2d');
animate();
</script>
var gridSpacing = 180; // --s: 80px; /* control the size of the grid */
var gridSize = 20;
var distortionFactor = 10;
<div id="vertical-line"></div>
<div id="horizontal-line"></div>
<div id="coords">ΞX=000000 ΨY=000000</div>
<script>
const coordsDisplay = document.getElementById('coords');
let isDecrypted = false;
function drawGrid(centerX, centerY) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const glitchGlyphs = ['Ξ','∆','⟁','✷','∞','ƒ','ꙮ','⊗','✦','Ψ','⧖','λ','β','µ','∇','Ω','⎊','₿','≡','','▒','░','✗','','⧘'];
const hex = '0123456789ABCDEF';
for (var i = 0; i < canvas.width; i += gridSpacing) {
for (var j = 0; j < canvas.height; j += gridSpacing) {
var dx = i - centerX;
var dy = j - centerY;
var dist = Math.sqrt(dx*dx + dy*dy);
var offset = dist / distortionFactor;
function rand(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
var x = i + dx / offset;
var y = j + dy / offset;
function generateGlitchString(prefix, realVal) {
const hexVal = realVal.toString(16).toUpperCase().padStart(3, '0');
let str = `${prefix}=`;
for (let i = 0; i < 4; i++) {
str += Math.random() > 0.5 && i < hexVal.length
? hexVal[i]
: rand(glitchGlyphs);
}
return str;
}
ctx.fillRect(x, y, gridSize, gridSize);
document.addEventListener('mousemove', (e) => {
if (isDecrypted) return;
// Connect the points with lines
if (i > 0) {
// Horizontal line
ctx.beginPath();
ctx.moveTo(x, y + gridSize / 2);
ctx.lineTo(x - gridSpacing, j + dy / (dist / (distortionFactor * gridSpacing)) + gridSize / 2);
ctx.stroke();
}
const glitchX = generateGlitchString('ΞX', e.clientX);
const glitchY = generateGlitchString('ΨY', e.clientY);
coordsDisplay.textContent = `${glitchX} ${glitchY}`;
});
if (j > 0) {
// Vertical line
ctx.beginPath();
ctx.moveTo(x + gridSize / 2, y);
ctx.lineTo(i + dx / (dist / (distortionFactor * gridSpacing)) + gridSize / 2, y - gridSpacing);
ctx.stroke();
}
}
}
}
// Decrypt on hover
coordsDisplay.addEventListener('mouseenter', () => {
isDecrypted = true;
coordsDisplay.classList.add('decrypted');
});
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
coordsDisplay.addEventListener('mousemove', (e) => {
if (!isDecrypted) return;
coordsDisplay.textContent = `X: ${e.clientX} Y: ${e.clientY}`;
});
window.onresize = resizeCanvas;
resizeCanvas();
coordsDisplay.addEventListener('mouseleave', () => {
isDecrypted = false;
coordsDisplay.classList.remove('decrypted');
});
canvas.onmousemove = function(e) {
drawGrid(e.clientX, e.clientY);
};
drawGrid(canvas.width / 2, canvas.height / 2);
</script>
const vLine = document.getElementById('vertical-line');
const hLine = document.getElementById('horizontal-line');
// Background color change on click
// document.body.addEventListener('click', () => {
// document.body.style.backgroundColor = `hsl(${Math.random()}, 70%, 80%)`;
// });
// Update crosshairs and coords
document.addEventListener('mousemove', (e) => {
vLine.style.left = `${e.clientX}px`;
hLine.style.top = `${e.clientY}px`;
});
</script>
<div id="footer">
{% block footer %}
<p>Por la gracia de San iGNUcio desde el Cuarto de Máquinas @ 2023.</p>
<p>Contáctanos en <a href="https://twitter.com/botkernel">el twatter</a> para lo que se ocupe.</p>
{% endblock %}
</div>
</body>
</html>

View File

@ -12,62 +12,58 @@ color:white;
<div id="wikipedia-data">
<h2>Y ahora, unas cuantas palabras de Wikipedia</h2>
<p>Cargando...</p>
<h3 id="article-title"></h3>
</div>
<!-- JavaScript code to fetch and display Wikipedia data -->
<script>
// Wikipedia API endpoint with a CORS proxy
const wikipediaAPI = 'https://cors-anywhere.herokuapp.com/https://en.wikipedia.org/w/api.php';
// Array of Wikipedia page titles
const wikipediaAPI = 'https://en.wikipedia.org/w/api.php';
const pageTitles = ['List_of_hackers', 'Cybersecurity', 'Open-source_software', 'History_of_Linux'];
// Randomly select a page title from the array
const pageTitle = pageTitles[Math.floor(Math.random() * pageTitles.length)];
// Parameters for the API request
const params = {
origin: '*', // Required for CORS from Wikipedia
action: 'query',
format: 'json',
titles: pageTitle,
prop: 'extracts|pageimages',
exintro: true, // Get the introductory section
explaintext: true, // Get plain text
exintro: true,
explaintext: true,
piprop: 'original',
pithumbsize: 400, // Size of the thumbnail image
pithumbsize: 400,
};
// Construct the URL with query parameters
const url = `${wikipediaAPI}?${new URLSearchParams(params)}`;
// Fetch data from Wikipedia using the API
fetch(url,{
method:"GET",
headers: {
"Origin": "https://kernelpanic.lol"
}
})
fetch(url)
.then((response) => response.json())
.then((data) => {
// Extract data from the API response
const pageId = Object.keys(data.query.pages)[0];
const articleTitle = data.query.pages[pageId].title;
const articleIntro = data.query.pages[pageId].extract;
const articleImage = data.query.pages[pageId].original ? data.query.pages[pageId].original.source : '';
// Display the results
const page = data.query.pages[pageId];
const articleTitle = page.title;
const articleIntro = page.extract;
const articleImage = page.original ? page.original.source : '';
console.log('Article Title:', articleTitle);
console.log('Article Intro:', articleIntro);
console.log('Article Image:', articleImage);
// Update your webpage with the retrieved data
document.getElementById('article-title').textContent = articleTitle;
document.getElementById('article-intro').textContent = articleIntro;
document.getElementById('article-image').src = articleImage;
if (articleImage) {
document.getElementById('article-image').src = articleImage;
document.getElementById('article-image').style.display = 'block';
} else {
document.getElementById('article-image').style.display = 'none';
}
})
.catch((error) => {
console.error('Error:', error);
});
</script>
</script>
{% endblock %}