knuspermagier.de

Since 2005.

Sunsetting kirby-activitypub-lite

Nach langem Überlegen, ob ich mein Kirby-ActivityPub-Plugin noch weiterentwickle und Dinge wie Likes und Boosts einbaue, habe ich beschlossen es nicht zu tun und es zu archivieren. Ich werde es auch hier im Blog entfernen und nicht weiter benutzen, der knuspermagier@knuspermagier.de Account wird damit auch nicht weiter befüllt werden.

Warum, fragt ihr euch vielleicht. Tja. Die Antwort ist vielschichtig, aber ich glaube, es ist einfach Quatsch. Erstens booste ich eh jeden Post vom Blog-Account, da kann ich die Links zu den Blogposts auch direkt posten, oder mit einem Script automatisch zu meinem Mastodon-Account schieben.

Zwar war es ganz lustig, das Plugin zu entwickeln und dabei viel über ActivityPub zu lernen, aber um einen richtigen Mehrwert daraus zu ziehen, hätte ich noch einiges einbauen müssen. Wäre ja zum Beispiel ganz nett, wenn ich als der Blog-Account mit Leuten reden könnte, die zum Beispiel auf einen der Posts per Reply reagiert haben. Letztendlich müsste das Kirby-Plugin ein kompletter ActivityPub-Client sein. Im Idealfall müsste er auch noch die Mastodon REST-API nachbauen, damit ich z.B. mit einem iOS-Client wie Ivory damit schreiben kann. Das ist alles völlig out of scope für ein Kirby-Plugin.

Die Frage ist auch, was es mir bringt, den Blog als eigenes ActivityPub-Ding zu haben. Aktuell gefühlt wirklich gar nichts. Der Blog wird ja hauptsächlich über RSS gelesen, oder über diese Webseite und nicht in einem ActivityPub-Client. Wäre auch etwas kurios, da ganze Blogposts in einer Timeline zu haben.

07db8cd7-fd68-4b82-8efd-3a45c2a1ce5b.png
Sei nicht traurig, Mastodon.

Ich habe noch kurz darüber nachgedacht, den Blog-Account weiterleben zu lassen und zum Beispiel einen leichtgewichtigen ActivityPub-Server wie GoToSocial aufzusetzen. Dort könnte ich auch automatisiert meine Posts hinschicken und… von meinem Hauptaccount boosten. Da seht ihrs, es wäre auch Quatsch. Wer pwa@norden.social folgt, der wird eh alle Blogposts mitbekommen und wer sollte meinem Blog folgen, ohne auch Zugriff auf meine sonstigen, sehr wichtigen und gehaltvollen Toots haben zu wollen?


Es war eine schöne Woche, in der ich das Plugin baute, aber nun bin ich auch froh, dass ich mir keine Gedanken mehr darüber machen muss! Bye, bye!

Models richtig recyclen in Eloquent Factories

Heute hatte ich ein kleines Verständnisproblem in meinem Seeder und wollte daher mal notieren, wie es richtig geht.

Folgendes Problem: Ich habe, sagen wir mal, ein Model Post, das eine user_id hat.

Wenn ich nun ganz viele Posts in die Datenbank seede, möchte ich zwar, dass jeder mit einem User verbunden ist, aber ich will nicht, dass jeder Post auch seinen ganz eigenen User erstellt. Da kommt nun die recycle-Methode zur Anwendung

// PostFactory.php
public function definition(): array
{
    return [
        'text' => 'Hallo!',
        'user_id' => User::factory(),
    ];
}

// DatabaseSeeder.php
$users = User::factory()->count(10)->create();

Post::factory()
    ->recycle($users)
    ->count(100)
    ->create();

Nutzt man bei der PostFactory, wie dargestellt, nun recycle, führt das dazu, dass er die entsprechenden Models nutzt, statt Neue zu erstellen, wie toll ist das denn!


Damit der Post nicht nur hilfreich, sondern auch unterhaltsam ist, hier noch den Fehler, den ich machte, weshalb alles nicht funktionierte:

// DatabaseSeeder.php
$users = User::factory()->count(10)->create();

Post::factory()
    ->recycle($users)
    ->for(User::factory())
    ->count(100)
    ->create();

Ich versuchte recycle gemeinsam mit for zu benutzen. Das klappt zwar an sich auch, aber jeder Post bekommt leider den gleichen User, weil das for für alles gilt, was aus der Factory fällt. Ist also gar kein Fehler von recycle, sondern nur ganz allein meiner.

UI-Komponenten in mehreren Projekten nutzen mit Tailwind

Wenn man kurz nacheinander mehrere Projekte startet, möchte man ungern immer wieder alles von vorne bauen. Vor allem Formularfelder, oder so einen Quatsch.

Ich schrieb mir bei Kioski also schon ein paar Blade-Komponenten und wollte die in Konpasu nun weiterverwenden, doch wie mache ich das am Besten?

Composer

Der erste Schritt war erstmal, die Komponenten in ein eigenes Composer-Package auszulagern. Dazu kopierte ich alles in einen Ordner und legte einen ServiceProvider an, der Laravel mitteilt, wo der Kram nun liegt:

final class PwaBluiServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Blade::anonymousComponentPath(__DIR__ . '/../resources/views/components', 'pwablui');
        Blade::componentNamespace('PwaBlui\\Views\\Components', 'pwablui');
    }
}

Ja, das ganze heißt PwaBlui. Für Philipp Waldhauer Blade UI. Ich muss das ja abgrenzen von meinen Vue-Componenten, die nur PWUI heißen. Ohne a. Was ist eigentlich los.

Jedenfalls kann ich die Komponenten nun benutzen:

<x-pwablui::form.row>
    <x-pwablui::form.label for="username">Username</x-pwablui::form.label>
    <x-pwablui::form.text name="username" type="text" placeholder=""/>
</x-pwablui::form.row>

Das Composer-Package habe ich mit diesem Trick für die lokale Entwicklung installiert, so wird es direkt lokal per Symlink installiert.


Ich hab noch keine Ahnung, wie das funktioniert, wenn man das jetzt von Github läd, composer install macht und die Daten nicht lokal liegen hat. Muss ich mal noch ausprobieren.


pwaldhauer_an_orc_with_a_sword_looking_like_a_fox_tail_illustra_1c19b0eb-e173-4305-a5ce-77aed7dc06bd.png
Das versteht Midjourney unter Tailwind und Blade. Sorry, ich hab einen Monat subscribed und muss die Stunden leer kriegen.

Tailwind

Nach der kurzen Freude kam direkt die Ernüchterung: Natürlich war im neuen Projekt jetzt auch alles Lila, denn die Komponenten benutzten alle bg-indigo als Farbe. Doch auch dafür gibt es eine Lösung, danke an den Tailwind-Experten Nils an dieser Stelle, denn über die Theme-API kann man Tailwind überzeugen, sowas ganz schlau zu handeln:

theme: {
    extend: {
        backgroundColor: ({ theme }) => ({
            primary:  theme('colors.emerald'),
        }),
        ringColor: ({ theme }) => ({
            primary:  theme('colors.emerald'),
        }),
        textColor: ({ theme }) => ({
            primary:  theme('colors.emerald'),
        }),
        borderColor: ({ theme }) => ({
            primary:  theme('colors.emerald'),
        })
    },
},

Nun kann ich in den Komponenten einfach bg-primary benutzen und in den Projekten einfach die entsprechenden Farben in der Konfiguration einstellen. Fast als würde man eine normale CSS-Datei nehmen und dort Variablen überschreiben.

Verrückt!

Seitdem ich letztens die Silo-Trilogie hörte verspüre ich so eine Podcast-Müdigkeit. Immer dieses sinnlose Gelaber von irgendwelchen Leuten. Dagegen ist ein Hörbuch doch wenigstens was handfestes.

Moves-Lücke

Vor ein paar Tagen habe ich angefangen, das Backend, das aktuell meine Locationdaten sammelt neu zu bauen. Nicht, dass es nötig wäre, aber mich stören so ein paar Sache an Compass, einer Software, die seit Jahren völlig problemlos funktioniert. Never change a running system, außer naja, man will dringend ein, zwei Features einbauen, oder ein süßes Bild was Midjourney generiert hat, auf dem Login-Screen verwenden.

screenshot-2023-03-18-at-14.26.11.png
コンパス ist natürlich einfach konpasu auf Japanisch.

Jedenfalls wollte ich mal meine uralten Daten aus der Moves.app, der/die ein/e oder andere erinnert sich vielleicht, importieren und dabei musste ich feststellen, dass in den ganzen Exportformaten, die sich in dem riesigen Zipfile verbergen, überall die Koordinaten fehlen! Zwar gibts die Koordinaten der Orte, an denen ich mich länger aufgehalten habe, aber für die Wege dazwischen fehlte alles. Furchtbar!

screenshot-2023-03-18-at-14.29.23.png

Nach ein wenig Sucherei fand ich die Daten zum Glück im GPX-Export. Nochmal Glück gehabt.

Testing Coolify

Letztens empfahl Felix auf Mastodon eine Software namens Coolify. Das ist so eine Art self-hosted… Heroku. Also es ist vor allem eine schöne UI um Docker Container zu managen. Ich werde es die nächsten Tage mal ausprobieren, also im Zuge meiner großen Server-Konsolidierung und berichten, wie es sich schlägt. Abgesehen vom Namen bin ich schon ziemlich angetan bisher!

Die Silo-Frage

Letztens kam der Trailer für die Apple TV+-Adaption der Roman-Trilogie Silo von Hugh Howey raus. Ich wollte die Bücher schon länger lesen, kam aber nicht dazu und wollte mir den Trailer auch nicht angucken, bevor ich es nicht gelesen habe um mir nicht meine Fantasie von Tim Apples Vorstellung kaputt zu machen.

Also griff ich zum Hörbuch-Service meines Vertrauens, nämlich Bookbeat, und schaute, ob sie das Buch zufällig da haben. Vorzugsweise in Deutsch, da ich verdammt faul geworden bin, seitdem ich mich nicht mehr selbst gatekeepe.

Ich hörte also Buch eins durch und war sehr begeistert. Bevor ich das nächste Buch startete schaute ich erstmal auf die Längen der Hörfassungen und war etwas durcheinander. Die deutsche Version des ersten Buchs ist ähnlich lang wie die englische, die des zweiten Buchs allerdings um einiges kürzer. Wie ist das zu erklären? Das deutsche Buch hat zwar ein paar Seiten weniger, als das Englische, aber nichts, was diesen Unterschied erklären würde.

Hier eine hilfreiche Tabelle:

Buch Seiten (de) Seiten (en) Länge (de) Länge (en)
Wool 531 594 16h 03min 15h 00min
Shift 412 579 10h 51min 14h 35min
Dust 462 482 12h 54min 10h 53min

(Mal von alllem anderen abgesehen, woher kommt diese Faszination, Bücher im Deutschen einfach andere englische Namen zu geben? Silo, Level, Exit? Ist doch einfach nur verwirrend.)


Jetzt fällt mir beim Erstellen dieses Blogposts auf, das ich anscheinend von einer falschen Zahl ausging. Irgendwo fand ich wohl eine englische Hörbuchversion von Shift, die um die 16 Stunden lang war und sechs Stunden Unterschied zur deutschen Version fand ich mysteriös genug um nachzuforschen, ich fragte sogar beim Verlag nach, der mir bestätigte, dass nichts gekürzt wurde.

Bei der Recherche für die Tabelle schaute ich bei Audible und da ist die Länge mit 14h 35min angegeben, was ja nur noch so dreieinhalb Stunden unterschied wären. Das deckt sich nun etwa mit dem Unterschied der Seitenzahlen, was ja immerhin beträchtlichen 30% entspricht.

Statt mich zu wundern, warum die deutsche Hörbuch-Version so kurz ist, frage ich mich also eher, warum das deutsche Buch 30% kürzer ist, während die anderen beiden Bände nur wenige Seiten weniger enhalten. Aber gut, Seitenzahlen sind eh komische Angaben, die von verschiedensten Sachen abhängig sind.

Case also direkt wieder closed. Sorry, für die gestohlene Zeit. Statt diesem Blogpost solltet ihr lieber diese wundervolle Trilogie lesen!

OpenAI im Tagebuch

Eine kleine Abendspielerei: Ich wollte, nun auch mal eine der OpenAI-APIs in einem meiner Projekte benutzen! Zum Glück gestaltet sich das sehr einfach.

composer require openai-php/client

Doch welches Projekt eignet sich? Eigentlich dachte ich zuerst an einen Knopf hier im Blog, der Posts zusammenfasst und einen Text für den Toot erzeugt, oder so. Aber es kam mir noch eine Idee, die schneller ging und vielleicht auch günstiger ist, denn jeder Token, der verarbeitet werden muss kostet bares Geld! Wie wäre es, wenn mein Tagebuch mir inspirierende Fragen zu meinem Tag stellt?

$client = \OpenAI::client('xyz');

$result = $client->completions()->create([
            'model' => 'text-davinci-003',
            'temperature' => 0.9,
            'max_tokens' => 100,
            'prompt' => 'Stelle mir eine inspirierende Frage über meinen Tag, die ich beantworten kann um eine gute Seite in meinem Tagebuch zu verfassen. Bitte sprich mich immer mit "du" oder "dich" an. Es sollte sich immer um den vergangenen Tag handeln.',
]);

Zuerst gab er mir nur sehr kurze und abgeschnittene Fragen zurück, das lag daran, dass max_tokens standardmäßig wohl sehr kurz ist. Hier ein Video vom Ergebnis:

Verrückt, wie schnell das geht.

Natürlich müsste ich für jeden Button-Click jetzt noch so einen Katsching-Soundeffekt einbauen, denn jeder Klick spült OpenAI Bruchstücke von Cents in die Taschen. Da muss ich vorsichtig sein!

Eine iPad-Sonos-Steuerapp

Vor ein paar Monden fand ich ein altes iPad Mini, welches ich mir 2014 kaufte. Es funktionierte noch blendend und es wäre ja schade, wenn es weiter sein Dasein im Schrank fristen müsste, bis der Akku sich entscheidet aufzuplatzen, wie bei allen meinen sonstigen alten Apple-Geräten.

Also suchte ich nach einem Verwendungszweck. Ich fand so herumhängender Smart-Home-Steuerzentralen schon immer ganz nett, aber ich will mit kein iPad an die Wand hängen und eigentlich muss ich nichts in meinem Smart Home wirklich steuern.

Was aber ganz cool wäre, wäre ein Ding, mit dem man schnell Musik oder Hörspiele anmachen kann, ohne ewig zu überlegen, ob man es nun bei Spotity hat oder in der Plex-Bibliothek oder wo auch immer. Einfach so ein Speed-Dial für die drei Lieblingsalben, -playlists oder die neuste Folge der Drei Fragezeichen.

Weiterlesen →

DNS außerhalb des Registrars

Wie viele Internet-Leute bin ich Domain-Messi. Also zumindest habe ich ziemlich viele. Immerhin sind sie nur auf zwei oder drei Registrare verteilt, trotzdem ist es ab und zu nervig, wenn man mal wieder einen DNS-Eintrag verändern will und nicht sofort weiß, wo man jetzt die Domain gekauft hat. Ganz abgesehen davon sind die Interfaces sowohl bei INWX, als auch bei Gandi ziemlich schrottig.

Wie wäre es also, die DNS-Server-Sachen komplett unabhängig vom Registrar, in einem wunderschönen Interface zu managen, am besten noch per API und alles? Ich dachte schon ab und zu mal über Amazon Route 53 oder so nach, aber die 50 Cent extra pro Domain, die das damals kostete schreckten mich immer ab. Vor allem, weil das ja mehr ist, als eine .de-Domain im Jahr überhaupt kostet.

dalle-2023-03-06-00.20.02-a-network-of-computers-on-the-internet-connected-by-a-series-of-tubes-in-the-background-is-a-rising-su.png
Das Internet, schematische Darstellung

Ich machte mal wieder eine kleine Mastodon-Umfrage und erlangte ein paar Einsichten.


Allgemein frage ich öfter mal was bei Mastodon und zumindest in diesem ganzen Programmier/Sysadmin-Space funktioniert das fast besser als jede Twitter-#followerpower damals. Ich mag das sehr! Da Mastodon aber ja so ein kleines Such-Problem hat, man also Sachen nicht so gut wiederfindet, habe ich nun vor, auch mal über die Ergebnisse zu schreiben. Damit wir alle was davon haben!


Zurück zum Thema. Folgende Dinge wurden mir von verschiedenen Personen empfohlen, die ich jetzt nicht nochmal gesondert verlinken werde, da man die genaue Zuordnung ja oben im Thread entnehmen kann. Danke an alle!

Bei Scaleway habe ich sonst nichts, Cloudflare ist mir nicht europäisch genug und einen eigenen DNS-Server hosten will ich auf keinen Fall. Bleiben also noch zwei Anbieter für eine tiefere Recherche: desec.io und die Hetzner DNS Console.

Ersteres sieht ganz nett aus und wird von einem Verein aus Berlin betrieben. Tatsächlich gibt es aber anscheinend noch kein Two-Factor Auth (immerhin auf der Roadmap). Wäre der zweite Kandidat jetzt nicht Hetzner gewesen, die ich ja eh schon für den ganzen Server-Kram benutze, hätte ich es mir vielleicht nochmal genauer angeschaut, aber so war meine Entscheidung relativ schnell gefallen.

Ich habe gerade die Zone für die erste meiner Domains angelegt und es hat geklappt! Also das anlegen. Ich bin begeistert. Gegebenenfalls werde ich mich vielleicht auch nochmal mit DNSControl beschäftigen, damit ich die ganze Sache vielleicht in ein Git-Repo schieben kann, falls ich doch nochmal von Hetzner wegwechseln will.

Update

Jan hat mir mitgeteilt, dass desec doch schon 2FA hat und Hetzner kein DNSEC unterstützt. Ich werd mich mal genauer damit beschäftigen, ob man letzteres wirklich braucht und meine Entscheidung gegebenenfalls nochmal überdenken! Hätte ich nur schon eine DNSControl-Datei angelegt!!