1980s & 1990s BBSing, PDFs, and stuff.
Listen now (34 min) | The Lunduke Journal Podcast - August 17, 2022 ⌘ Read more
GitHub Enterprise Server 3.6 is now generally available
GitHub Discussions and Audit Log Streaming, new automation features, and security enhancements are available now in GitHub Enterprise Server 3.6. ⌘ Read more
Shouldn’t it be called Metacountries? After all it is only available to one country at a time…
Shouldn’t it be called Metacountries? After all it is only available to one country at a time…
nitter.net/ChrisJBakke/status/1559696878530449418#m ⌘ Read more
Amend 3.5 Released
Amend 3.5 has been released: ⌘ Read more
Who did this to my face? 🤔 ⌘ Read more
Gen Z
⌘ Read more
XMPP Providers: XMPP Providers and blabber.im
Easy Onboarding with Android Chat AppA new version of the Android XMPP chat app
blabber.im has been released.
It provides an easy onboarding.
Passwords are generated automatically and XMPP providers are suggested.
Those suggestions are based on our curated list of XMPP providers.
How To Count In Binary | Neil deGrasse Tyson Explains… ⌘ Read more
2022 Transparency Report: January to June
We’re reporting on a six-month period rather than annually to increase our level of transparency. For this report, we’ve continued with the more granular reporting we began in our 2021 reports. ⌘ Read more
The BBS is back On-Line, with more games a-comin’!
One of the chief goals of The House of Lunduke BBS is to preserve the best of 1980’s and 1990s BBS gaming — in all its ANSI, colorful text art glory. With that goal in mind, I recently took the BBS Off-Line for a much needed retro-fit… in order to properly accommodate a wider selection of classic BBS “Door” Games. ⌘ Read more
Coffee with Brian Kernighan - Computerphile ⌘ Read more
Apple Police arrest man for “malicious sideloading of DOOM”
If convicted of “Malicious, Intentional Sideloading” he faces life in Apple Prison ™. ⌘ Read more
RT by @mind_booster: Debian turns 29! #DebianDay #DebianDay2022 http://dlvr.it/SWjsdv
Debian turns 29! #DebianDay #DebianDay2022 dlvr.it/SWjsdv
Lunduke’s History of Computers - Volume 2
Free for all subscribers to The Lunduke Journal. ⌘ Read more
Glassdrive, Rádio Popular, Atum General: perdoem-me mas com equipas de nomes assim, para mim, o desporto praticado na Volta é um bocado… triste.
Glassdrive, Rádio Popular, Atum General: perdoem-me mas com equipas de nomes assim, para mim, o desporto praticado na Volta é um bocado… triste. ⌘ Read more
I was just about to write a long response to a discussion I saw online. But while writing it, I realized that I have an opinion, but I can’t express it properly and somehow I don’t have anything to contribute. So I deleted my draft. I don’t have to give my two cents on everything. 😅 ⌘ Read more
The next step for LGTM.com: GitHub code scanning!
Today, GitHub code scanning has all of LGTM.com’s key features—and more! The time has therefore come to announce the plan for the gradual deprecation of LGTM.com. ⌘ Read more
Linux, Alternative OS, & Retro Computing News - August 14, 2022
Listen now (20 min) | The Lunduke Journal Podcast - August 14, 2022 ⌘ Read more
Unreliable Connection
⌘ Read more
I’ve realized that trying to strictly follow what is on the IndieWeb wiki won’t work well for me. Thus, I have to invent and change some things to make it work better. ⌘ Read more
(cont.)
Just to give some context on some of the components around the code structure.. I wrote this up around an earlier version of aggregate code. This generic bit simplifies things by removing the need of the Crud functions for each aggregate.
Domain ObjectsA domain object can be used as an aggregate by adding the event.AggregateRoot struct and finish implementing event.Aggregate. The AggregateRoot implements logic for adding events after they are either Raised by a command or Appended by the eventstore Load or service ApplyFn methods. It also tracks the uncommitted events that are saved using the eventstore Save method.
type User struct {
Identity string ```json:"identity"`
CreatedAt time.Time
event.AggregateRoot
}
// StreamID for the aggregate when stored or loaded from ES.
func (a *User) StreamID() string {
return "user-" + a.Identity
}
// ApplyEvent to the aggregate state.
func (a *User) ApplyEvent(lis ...event.Event) {
for _, e := range lis {
switch e := e.(type) {
case *UserCreated:
a.Identity = e.Identity
a.CreatedAt = e.EventMeta().CreatedDate
/* ... */
}
}
}
Events
Events are applied to the aggregate. They are defined by adding the event.Meta and implementing the getter/setters for event.Event
type UserCreated struct {
eventMeta event.Meta
Identity string
}
func (c *UserCreated) EventMeta() (m event.Meta) {
if c != nil {
m = c.eventMeta
}
return m
}
func (c *UserCreated) SetEventMeta(m event.Meta) {
if c != nil {
c.eventMeta = m
}
}
Reading Events from EventStore
With a domain object that implements the event.Aggregate the event store client can load events and apply them using the Load(ctx, agg) method.
// GetUser populates an user from event store.
func (rw *User) GetUser(ctx context.Context, userID string) (*domain.User, error) {
user := &domain.User{Identity: userID}
err := rw.es.Load(ctx, user)
if err != nil {
if err != nil {
if errors.Is(err, eventstore.ErrStreamNotFound) {
return user, ErrNotFound
}
return user, err
}
return nil, err
}
return user, err
}
OnX Commands
An OnX command will validate the state of the domain object can have the command performed on it. If it can be applied it raises the event using event.Raise() Otherwise it returns an error.
// OnCreate raises an UserCreated event to create the user.
// Note: The handler will check that the user does not already exsist.
func (a *User) OnCreate(identity string) error {
event.Raise(a, &UserCreated{Identity: identity})
return nil
}
// OnScored will attempt to score a task.
// If the task is not in a Created state it will fail.
func (a *Task) OnScored(taskID string, score int64, attributes Attributes) error {
if a.State != TaskStateCreated {
return fmt.Errorf("task expected created, got %s", a.State)
}
event.Raise(a, &TaskScored{TaskID: taskID, Attributes: attributes, Score: score})
return nil
}
Crud Operations for OnX Commands
The following functions in the aggregate service can be used to perform creation and updating of aggregates. The Update function will ensure the aggregate exists, where the Create is intended for non-existent aggregates. These can probably be combined into one function.
// Create is used when the stream does not yet exist.
func (rw *User) Create(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil && !errors.Is(err, ErrNotFound) {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
// Update is used when the stream already exists.
func (rw *User) Update(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
(cont.)
Just to give some context on some of the components around the code structure.. I wrote this up around an earlier version of aggregate code. This generic bit simplifies things by removing the need of the Crud functions for each aggregate.
Domain ObjectsA domain object can be used as an aggregate by adding the event.AggregateRoot struct and finish implementing event.Aggregate. The AggregateRoot implements logic for adding events after they are either Raised by a command or Appended by the eventstore Load or service ApplyFn methods. It also tracks the uncommitted events that are saved using the eventstore Save method.
type User struct {
Identity string ```json:"identity"`
CreatedAt time.Time
event.AggregateRoot
}
// StreamID for the aggregate when stored or loaded from ES.
func (a *User) StreamID() string {
return "user-" + a.Identity
}
// ApplyEvent to the aggregate state.
func (a *User) ApplyEvent(lis ...event.Event) {
for _, e := range lis {
switch e := e.(type) {
case *UserCreated:
a.Identity = e.Identity
a.CreatedAt = e.EventMeta().CreatedDate
/* ... */
}
}
}
Events
Events are applied to the aggregate. They are defined by adding the event.Meta and implementing the getter/setters for event.Event
type UserCreated struct {
eventMeta event.Meta
Identity string
}
func (c *UserCreated) EventMeta() (m event.Meta) {
if c != nil {
m = c.eventMeta
}
return m
}
func (c *UserCreated) SetEventMeta(m event.Meta) {
if c != nil {
c.eventMeta = m
}
}
Reading Events from EventStore
With a domain object that implements the event.Aggregate the event store client can load events and apply them using the Load(ctx, agg) method.
// GetUser populates an user from event store.
func (rw *User) GetUser(ctx context.Context, userID string) (*domain.User, error) {
user := &domain.User{Identity: userID}
err := rw.es.Load(ctx, user)
if err != nil {
if err != nil {
if errors.Is(err, eventstore.ErrStreamNotFound) {
return user, ErrNotFound
}
return user, err
}
return nil, err
}
return user, err
}
OnX Commands
An OnX command will validate the state of the domain object can have the command performed on it. If it can be applied it raises the event using event.Raise() Otherwise it returns an error.
// OnCreate raises an UserCreated event to create the user.
// Note: The handler will check that the user does not already exsist.
func (a *User) OnCreate(identity string) error {
event.Raise(a, &UserCreated{Identity: identity})
return nil
}
// OnScored will attempt to score a task.
// If the task is not in a Created state it will fail.
func (a *Task) OnScored(taskID string, score int64, attributes Attributes) error {
if a.State != TaskStateCreated {
return fmt.Errorf("task expected created, got %s", a.State)
}
event.Raise(a, &TaskScored{TaskID: taskID, Attributes: attributes, Score: score})
return nil
}
Crud Operations for OnX Commands
The following functions in the aggregate service can be used to perform creation and updating of aggregates. The Update function will ensure the aggregate exists, where the Create is intended for non-existent aggregates. These can probably be combined into one function.
// Create is used when the stream does not yet exist.
func (rw *User) Create(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil && !errors.Is(err, ErrNotFound) {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
// Update is used when the stream already exists.
func (rw *User) Update(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
RT by @mind_booster: As declarações do Chanceler Alemão Olaf Scholz deram ânimo às intenções dos governos de Portugal e Espanha para uma eventual expansão da rede de gás natural fóssil podendo colocar em causa os objetivos europeus de combate às alterações climáticas. https://zero.ong/zero-tem-enormes-duvidas-sobre-expansao-e-interconexao-iberica-da-rede-de-gas/
As declarações do Chanceler Alemão Olaf Scholz deram ânimo às intenções dos governos de Portugal e Espanha para uma eventual expansão da rede de gás na … ⌘ Read more
[47°09′49″S, 126°43′17″W] Reading: 0.84 Sv
[47°09′34″S, 126°43′12″W] Reading: 0.14000 PPM
Linux, Alternative OS, & Retro Computing News - Aug 13, 2022
Haiku, Myst on 2600, ScummVM adds games, & Neofetch themese ⌘ Read more
[47°09′42″S, 126°43′03″W] Reading: 1.86 Sv
Make Linux look like Star Trek LCARS
That’s one seriously next generation desktop environment right there… ⌘ Read more
The XMPP Standards Foundation: Mid Term Evaluation Updates
It’s been a month since I wrote my last blog. For those of you who have been following my blogs, thanks a lot for taking the time to read them. In this blog, I will give the updates post mid-term evaluation and the challenges that I have been facing and how I overcame some of them.
For those of you who don’t know much about GSoC, a mid-term evaluat … ⌘ Read more
Hormones on Steroids with Neil deGrasse Tyson & Dr. Aniket Sidhaye ⌘ Read more
Tailscale SSH
I finally got around to using Tailscale SSH. I’ve been using Tailscale for over a year to access my servers via SSH (my VPS is even available via Tailscale only), but I haven’t used the new Tailscale SSH feature yet. ⌘ Read more
**RT by @mind_booster: [¼]
Terminou ontem a consulta pública do projeto Aproveitamento Hidráulico de Fins Múltiplos do Crato (Barragem do Crato) a que a ZERO dá parecer negativo
❌Dinheiro do PRR vai ser usado p/ projeto sem sentido e promotor de impactes ambientais e sociais negativos
👇(continua)**
[¼]
Terminou ontem a consulta pública do projeto Aproveitamento Hidráulico de Fins Múltiplos do Crato (Barragem do Crato) a que a ZERO dá parecer negativo
❌Dinheiro do PRR vai ser usado p/ projeto sem sentido e p … ⌘ Read more
[47°09′51″S, 126°43′36″W] Reading: 1.22 Sv
“They Don’t Want to Hear the Truth” -John Barilaro href=”https://txt.sour.is/search?q=%23shorts”>#shorts** ⌘ Read more
Coffee Cup Holes
⌘ Read more
The History of Ctrl-Alt-Delete
How the “Three Fingered Salute” came to be. ⌘ Read more
Nuclear Winter, Carl Sagan, & The Drake Equation with Neil deGrasse Tyson, Ann Druyan, & Brian Toon ⌘ Read more
[47°09′51″S, 126°43′52″W] Raw reading: 0x62F52781, offset +/-4
RT by @mind_booster: Two related stories this month show capitalism’s incompatibility with human and non-human flourishing. First, a study found all rainwater on earth is unsafe to drink because it’s contaminated with the ‘forever chemicals’ Per- and poly-fluoroalkyl (PFAS). 🧵https://www.euronews.com/green/2022/08/04/rainwater-everywhere-on-earth-unsafe-to-drink-due-to-forever-chemicals-study-finds
Two related stories this month show capitalism’s incompatibility with human and non-human flourishing. First, a st … ⌘ Read more
E com direito a goodies para quem for presencialmente!
E com direito a goodies para quem for presencialmente!
Nature is Healing ⌘ Read more
Tech Journalism Roundtable - July 25, 2016
Watch now (67 min) | With some of the most prolific Tech Journalists working at the time. ⌘ Read more
GitHub Pages now uses Actions by default
As GitHub Pages, home to 16 million websites, approaches its 15th anniversary, we’re excited to announce that all sites now build and deploy with GitHub Actions. ⌘ Read more
RT by @mind_booster: Amanhã no HopSin Brewpub em Colares entre as 18h30 e as 19h30 apareçam para ajudar a traduzir o Nextcloud @Nextclouders Também se podem juntar online. Vejam aqui como: https://ansol.org/eventos/2022-08-11-traducoes-nextcloud/
Amanhã no HopSin Brewpub em Colares entre as 18h30 e as 19h30 apareçam para ajudar a traduzir o Nextcloud @Nextclouders Também se podem juntar online. Vejam aqui como: [ansol.org/eventos/2022-08-11…](https://ansol.org/ev … ⌘ Read more
RT by @mind_booster: A complacência com que tratamos empresas monopolistas deixa-me sem palavras para qualificar estas práticas. Isto viola quase todas as regras de concorrência e boas práticas de mercado. href=”https://txt.sour.is/search?q=%23microsoft”>#microsoft**
A complacência com que tratamos empresas monopolistas deixa-me sem palavras para qualificar estas práticas. Isto viola quase todas as regras de concorrência e boas práticas de mercado. #microsoft
**
[¼]
✈️Novo passo na expansão ilegal do Aeroporto da Portela prejudicará severamente milhares de cidadãos.
⚠️Foi iniciado processo de consulta pública sobre portaria que passará a permitir voos noturnos sem limites.
(Continua 👇)

I plan to expand it to handle other event sourcing type things like aggregates and projections.
Find it here: sour-is/ev
@prologic@twtxt.net @movq@www.uninformativ.de @lyse@lyse.isobeef.org
Hi, I am playing with making an event sourcing database. Its super alpha but I thought I would share since others are talking about databases and such.
It’s super basic. Using tidwall/wal as the disk backing. The first use case I am playing with is an implementation of msgbus. I can post events to it and read them back in reverse order.

I plan to expand it to handle other event sourcing type things like aggregates and projections.
Find it here: sour-is/ev
@prologic@twtxt.net @movq@www.uninformativ.de @lyse@lyse.isobeef.org
Ignite Realtime Blog: REST API Openfire plugin 1.9.1 released!
Woopsie doodle! It turns out that a rather annoying bug was introduced in version 1.9.0 of the REST API plugin for Openfire, that we released earlier today!
To avoid unnecessary issues, we’ve decided to follow up with an immediate new release that addresses this issue. … ⌘ Read more
RT by @mind_booster: Importante ler⬇️
Cada vez mais, qualquer pessoa ou entidade pode fazer o que quiser neste país, sem regra, nem lei. E os vizinhos que se lixem. O ruído (incluindo actividades de entretenimento) mata a criatividade e dá cabo da saúde, mas ninguém quer saber.
Importante ler⬇️
Cada vez mais, qualquer pessoa ou entidade pode fazer o que quiser neste país, sem regra, nem lei. E os vizinhos que se lixem. O ruído (incluindo actividades de entretenimento) mata a criatividade e dá cabo da saúde, … ⌘ Read more
**R to @mind_booster: “Temos de agir com urgência na denúncia deste caminho insustentável!”
Texto de Francisco Ferreira, na newsletter da @ZEROasts
7/7**
“Temos de agir com urgência na denúncia deste caminho insustentável!”
Texto de Francisco Ferreira, na newsletter da @ZEROasts
7/7 ⌘ Read more
R to @mind_booster: “A par disto, quer ainda retirar quaisquer restrições ao tráfego aéreo noturno em Lisboa, quando os níveis de ruído já excedem imenso, como a ZERO recentemente demonstrou, os valores legais que procuram salvaguardar a saúde pública.” 6/7
“A par disto, quer ainda retirar quaisquer restrições ao tráfego aéreo noturno em Lisboa, quando os níveis de ruído já excedem imenso, como a ZERO recentemente demonstrou, os valores legais que procuram salvaguardar a saúde pública.” 6/7 ⌘ Read more
R to @mind_booster: “retirar a avaliação dos processos de loteamento e a redução dos prazos para emissão de pareceres e licenças, licenças ambientais validadas automaticamente (atualmente as licenças ambientais têm a validade de 10 anos).” 5/7
“retirar a avaliação dos processos de loteamento e a redução dos prazos para emissão de pareceres e licenças, licenças ambientais validadas automaticamente (atualmente as licenças ambientais têm a validade de 10 anos).” 5/7 ⌘ Read more
R to @mind_booster: “O estímulo ao deferimento tácito para facilitar ao máximo a aprovação de qualquer projeto, em que o foco é mesmo aprovar, seja o que for, de qualquer forma e seja onde for;” 4/7
“O estímulo ao deferimento tácito para facilitar ao máximo a aprovação de qualquer projeto, em que o foco é mesmo aprovar, seja o que for, de qualquer forma e seja onde for;” 4/7 ⌘ Read more
R to @mind_booster: “Desinvestiu, deixou que os procedimentos se burocratizassem para depois ter argumentos de desvalorização deste instrumento, ao contrário de o credibilizar, valorizar e modernizar.” 3/7
“Desinvestiu, deixou que os procedimentos se burocratizassem para depois ter argumentos de desvalorização deste instrumento, ao contrário de o credibilizar, valorizar e modernizar.” 3/7 ⌘ Read more
“Com a apresentação do Simplex na área ambiental, o Governo prepara-se para retroceder décadas na política ambiental, fazendo tábua rasa dos valores fundamentais que a política ambiental e o instrumento da avaliação de impacte ambiental visam proteger.” 1/7
“Com a apresentação do Simplex na área ambiental, o Governo prepara-se para retroceder décadas na política ambiental, fazendo tábua rasa dos valores fundamentais que a política ambiental e o instrumento da avaliação de impacte ambiental visam proteger.” … ⌘ Read more
R to @mind_booster: “O Governo está a fazer com a avaliação ambiental, aquilo que fez com a conservação da natureza e a proteção da biodiversidade.” 2/7
“O Governo está a fazer com a avaliação ambiental, aquilo que fez com a conservação da natureza e a proteção da biodiversidade.” 2/7 ⌘ Read more
5 simple things you can do with GitHub Packages to level up your workflows
From hosting private packages in a private repository to tightening your security profile with GITHUB_TOKEN, here are five simple ways you can streamline your workflow with GitHub Packages. ⌘ Read more
Ignite Realtime Blog: REST API Openfire plugin 1.9.0 released!
We have released version 1.9.0 of the Openfire REST API plugin! This version adds functionality and provides some bug fixes that relates to multi-user chat rooms.
The updated plugin should become available for download in your Openfire admin console in the course of the next few hours. Alternatively, you can download the plugin directly, from [the plugin’s archive page](https://www.igniterealtime.org/projects/openfire/pl … ⌘ Read more
[47°09′07″S, 126°43′31″W] Raw reading: 0x62EB5252, offset +/-2