Ángel Ortega III

Un naufragio personal

On HDMI things that don't exist

I'm the maintainer of several headless servers that very ocassionally need to have a screen attached to them for special cases like boot errors or BIOS tweaking or the like. For this, I need to keep around a fucking screen monitor that is cumbersome and heavy and tedious and serve no other purpose while idle. Instead, tablets (that usually have screens with acceptable size and quality) should include a HDMI input socket that, when plugged, made it to behave like a common monitor.

On the other hand, TV sets are no longer just gadgets that receive signals and convert them to pictures and sounds to be fed to couch potatos. Internally they are computers that also generate content via its internal apps like Netflix and Prime Video and whatever, so they should include a HDMI output socket to connect, for example, another TV in the other side of the room or a projector.

Computers should also have the HDMI input socket mentioned above, as well as reverse-USB connectors for using its keyboard and mouse to control external equipment. This way, a simple laptop could be used as a portable KVM without the stupidly expensive gadgets that are common in server farms.

I don't think any of these features would make equipment much more expensive nor complicated.

Build these things and I'll buy them.

Music that made my 2019

You may like these songs I enjoyed during 2019:

New ActivityPub support in Gruta

I have implemented partial ActivityPub support in pygruta, the Python port of my decades-old web CMS software Gruta. It has been implemented as two big blocks; the first one is a daemon process that, getting queries redirected from the web server,

  • Answers to webfinger GET method requests,
  • Answers to ActivityPub actor (user) GET method requests,
  • Accepts (and confirms) follow commands from POST method requests and registers the follower,
  • Accepts un-following commands from POST method requests and de-registers the follower,
  • Accepts messages (direct or public) from any ActivityPub user from POST method requests and stores them in a special topic as Gruta stories.

On the other hand, a command-line tool (triggered by cron) does the following:

  • Collects a story feed (the same set of stories that would be used in an ATOM or RSS feed) and sends it to all registered followers as public ActivityPub notes.

As of now, you cannot answer to a message sent from this network. I've yet to find a way of doing it, but most probably it would be by writing a standard story and using a special destination field or searching for a mention inside the story content matching the @user@host standard way of mentioning.

It has been a very tedious work, as the documentation is poor and confusing and you never get helpful feedback from errors. I did the development against different software (Mastodon, Friendica and Pleroma), but only got it working for the first one (it's the most common out there, though).

You can follow my id @angel@triptico.com from this network.

El sueño del niño en el pasillo

Hoy he soñado que aparecía un niño en mi casa (que no sé quien era) y que estaba aterrorizado porque había visto en la cocina a una señora que tenía «los ojos largos».

El chico que volvió — Lista de temas


Ver en Youtube
  • Gustav Mahler — Feierlich und gemessen (Sinfonía nº 1, III)
  • Supertramp — Take The Long Way Home
  • The Cure — Boys Don't Cry
  • New Order — True Faith
  • Siouxsie and the Banshees — Israel
  • Bauhaus — Bela Lugosi's Dead
  • The Scavengers — Violence
  • Severed Heads — Dead Eyes Opened
  • Warpaint — Elephants
  • Apollo Sunshine — We Are Born When We Die
  • The Bolshoi — A Way II
  • Ann Hell — The Triumph of Death
  • George McCrae — Rock You Baby
  • Joe Dassin — Et Si Tu N'Existais Pas
  • Counting Crows — Mr. Jones
  • Laura Branigan — Self Control
  • Plastic Bertrand — Ça Plane Pour Moi
  • The Rolling Stones — Sympathy for the Devil
  • The Cranberries — Promises
  • Skin — Kill Everything
  • Giacomo Puccini — Intermezzo (Manon Lescaut)

A function to decode utf-8 in streaming mode

This is my C language function to decode utf-8 into wide characters, a byte at a time. It also detects encoding errors.

/**
 * mpdm_utf8_to_wc - Converts from utf8 to wchar (streaming).
 * @w: convert wide char
 * @s: temporal state
 * @c: char read from stream
 *
 * Converts a stream of utf8 characters to wide char ones. The input
 * stream is read one byte at a time from @c and composed into @w
 * until a Unicode codepoint is ready. The @s integer keeps an internal
 * state change and must be set to 0 before the stream is read. It
 * detects encoding errors; in this case, the special Unicode
 * char U+FFFD is returned.
 *
 * When 0 is returned, a new wide char is available into @w. If
 * the stream is interrupted in the middle of a multibyte character,
 * the @s state variable will not be 0.
 */
int mpdm_utf8_to_wc(wchar_t *w, int *s, char c)
{
    if (!*s && (c & 0x80) == 0) { /* 1 byte char */
        *w = c;
    }
    else
    if (!*s && (c & 0xe0) == 0xc0) { /* 2 byte char */
        *w = (c & 0x1f) << 6; *s = 1;
    }
    else
    if (!*s && (c & 0xf0) == 0xe0) { /* 3 byte char */
        *w = (c & 0x0f) << 12; *s = 2;
    }
    else
    if (!*s && (c & 0xf8) == 0xf0) { /* 4 byte char */
        *w = (c & 0x07) << 18; *s = 3;
    }
    else
    if (*s && (c & 0xc0) == 0x80) { /* continuation byte */
        switch (*s) {
        case 3: *w |= (c & 0x3f) << 12; break;
        case 2: *w |= (c & 0x3f) << 6;  break;
        case 1: *w |= (c & 0x3f);       break;
        }

        (*s)--;
    }
    else {
        *w = L'\xfffd';
        *s = 0;
    }

    return *s;
}

Sobre la creación de canales de Telegram

Hace unos días investigué para un amigo cómo crear y usar canales de Telegram y le envié este email contándole lo que he averiguado. Lo adjunto aquí para que no se pierda:

Hola. He investigado sobre los canales de Telegram y cómo automatizarlo. Como siempre todo es complicado y confuso. Te lo cuento aquí porque mañana seguro que se me ha olvidado.

Lo primero es crear un canal. Eso ya lo has hecho.

Lo segundo es crear un bot. Es una especie de usuario de Telegram que no es un usuario pero que puede postear en canales. Para crearlo hay que hablar con otro bot que se llama BotFather. Ahí hay que darle comandos tipo IRC para crear tu bot (sí, es así de confuso). Hay que mandarle el mensaje /newbot y él (como en un chat robótico) te pide el nombre del bot y el nombre del usuario del bot (no sé muy bien cuál es la diferencia ni por qué hacen falta dos nombres y por qué no puedes ponerle el mismo). Después de esto te da una cadena de texto mágica que es un identificador autenticado del bot para poder postear desde fuera.

Luego tienes que ir al canal y añadir al bot como administrador. Solo funciona si lo haces desde el móvil, desde el ordenador no lo he conseguido. Tienes que buscar el nombre del bot desde la lupa porque no te sale automáticamente tu lista de bots.

Una vez hecho esto un par de veces (a la primera no me ha funcionado), ya le puedes mandar comandos al bot por HTTP para postear en aquellos canales en los que está autorizado. Esto se hace con una query como la que sigue:

 https://api.telegram.org/botIDENTIFICADOR_DEL_BOT/sendMessage?chat_id=@CANAL&text=Hola%20caraculo

Esto se puede hacer directamente con el comando curl del Linux o desde algún programa, es una petición HTTP normal.

Eso publica en modo texto. Hay un modo especial HTML que es MUY limitado y solo acepta negrilla, cursiva, enlaces y poco más. Con eso hay que montárselo todo. En concreto, NO acepta <p> para separar líneas ni títulos <h1>, <h2>, etc ni nada de eso, así que hay que hacer una especie de conversión (no es que ignore los tags, es que casca y te rechaza el envío).

Leyendo por ahí he descubierto que el modo HTML sí acepta cortes de párrafo pero hay que meterlos a pelo, es decir, metiendo %0A (ascii del line feed). Para añadir imágenes hay otro truco, que es ponerlas como enlaces (NO como imágenes). Si dejas el texto del enlace vacío o con un espacio lo ignora. La gente dice que le pone un carácter Unicode especial que es el "separador que no ocupa espacio" pero a mí me lo rechaza.

Este comando funciona y genera una entrada más o menos bonita:

 curl 'https://api.telegram.org/botBLA_BLA_BLA/sendMessage?chat_id=@nutriguia&parse_mode=HTML&disable_web_page_preview=false&text=<b>Title</b>%0AThis is a <i>test</i>. <a href="https://triptico.com/img/mp.png">·</a>'

Así que se podría hacer un programita que instalado en un cron coja, por ejemplo, el feed ATOM o RSS de Nutriguía, magree un poco las entradas, las deje aceptables para el Telegram y las envíe con sendas peticiones HTTP como las que te he comentado arriba.

Quizá alguien ha hecho ya ese programa, no he investigado más allá.

Nada es lo que parece

Esto ocurrió. Un profesor dijo globo ocular. En el margen de un libro yo dibujé esto:

Se lo enseñé a un compañero y dije:

—¿Sabes qué es?

Y él me dijo:

—Pues claro. Una visión global.