Kategorie: Programming

Discord: Der Umgang mit Bot Entwicklern

Discord: Der Umgang mit Bot Entwicklern

Hallo zusmamen,

nach nun wirklich einer Ewigkeit ohne neue Beiträge auf meinem Blog, bin ich mal wieder motiviert etwas zu verfassen.

Im folgenden wird es sich um eine Kritik an der Art und Weise der Verifizierung oder besser der Freischaltung von Bots für den erweiterten API Zugriff seitens Discord handeln.

Als Grundlage dient hier meine eigen Erfahrung und Ärger, den mir dieses Verfahren bereits bereitet hat.

Zum Hintergrund
Ich habe auf Basis von Erfahrungen aus meiner freiwilligen Arbeit als Discordmoderator bei The Cycle: Frontier, einen Bot entwickelt, der die Discordseitige Suche nach Gruppen für Spiele, grundlegend vereinfacht.
Viele kompetitive Spiele haben große Discords mit vielen Sprachkanälen, nun ist es für viele User aufgrund von Unkenntnis der Discord funktionsweise sehr schwer ihren Sprachkanal in einer Gruppensuche Nachricht zu verlinken, um schnell gefunden werden zu können.
Für genau diesen Zweck habe ich den Bot entwickelt, der den Vorgang automatisiert.

Der Bot wurde aufgrund seiner einfachheit auch sehr schnell in durchaus große Communities aufgenommen und wird dort aktiv genutzt.
Dies hatte nun aber auch zur Folge, dass er sehr schnell die Obergrenze von 100 Servern erreicht hatte. Mehr Server sind erst nach Freischaltung für die erweiterte API möglich.
Ich habe also den Antrag der Verifizierung, bei dem man seine Identität mittels Ausweiseinsendung offen legen muss, eingereicht. Dieser wurde auch überraschend schnell bearbeitet und der Bot wurde verifiziert, ohne aber Zugang zur erweiterten API zu bekommen.

Ich stellte also den Antrag erneut und bekam folgende Antwort:

„Unfortunately, I am denying your Guild Members and Message Content Privileged Intent request. This is because we are only providing access to our privileged gateway intents to power unique, compelling, user-facing functionality, and we do not believe your use-case meet this criteria.“

Ein Bot, der in rekordzeit das Limit erreicht hat, auf wirklich großen Servern eingesetzt wird hat also keine einzigartigen und nutzerfreundlichen Funktionen … aha … interessant.

Ich hatte den Bot absichtlich einfach und ressourcenschonend gestaltet, da er eben nur den Zweck der Gruppensuche enorm vereinfachen sollte.
Für mich zählte Stabilität mehr als Featurereichtum.

Aber OK, ich erweiteret den Bot zusätzlich um eine logging Funktion und ein paar nutzerfreundlichen Anpassungsmöglichkeiten in der Optik der Ausgabe. Also alles Dinge, die meines Erachtens die Nutzerorientierung un -freundlichkeit steigern, ohne aber die Stabilität massiv zu beeinträchtigen.

Also Antrag erneut ausgefull, nur um ein paar Minuten später die exakt gleiche Antwort erneut im Postfach zu finden.
Da fühlt man sich als Entwickler nun wirklich etwas verarscht… klar verstehe ich, dass sie nicht jeden 0815 Bot annehmen können, aber einen Bot prüfen kann man nicht in ein paar Minuten. Ich wette diese Prüfung ist nie erfolgt. Man schaut hier nicht auf die Qualität eines Bots, sondern rein auf die Anzahl an Funktionen.

Da muss man sich nicht wundern, dass sehr viele Bots derzeit einfach nur instabil laufen und ständig Ausfälle haben, da sie mit sinnlosen Features zugemüllt werden (müssen), um den erweiterten Zugang zu bekommen.

Ich habe nun die Funktionen erneut etwas erweitert und werde demnächst einen nächstn und vermutlich letzten Versuch starten den Zugang zu bekommen. Andernfalls kann mich Discord wirklich kreuzweise.
Mit diesem Verfahren macht das Entwickeln einfach keinen Spaß mehr. Bots sind das, was diese Plattform einzigartig macht und vermutlich auch am Leben hält, aber als Entwickler bekommt man nur dicke Steine in den Weg gelegt.

D.JS: Herausfiltern von Discord Invites & Informationen des Zielservers

D.JS: Herausfiltern von Discord Invites & Informationen des Zielservers

Die neuste Erweiterung meines The Cycle Discord Bots sollte ein Filter sein, der Discord Einladungen automatisch löscht bzw. mit einer Whitelist abgleicht, ob ein Link zugelassen ist..

Die Idee war recht simpel, doch in der Umsetzung stand ich auf einmal vor dem Problem einen Discord Link überhaupt zu identifizieren, auch wenn er in einen Text verpackt ist.
Als wäre das nicht schon Aufgabe genug, gibt es ja zig Variationen diese Links. Zusätzlich wollte ich ja dann auch nicht nur den Link selbst auf eine Whitelist setzen, sondern bestenfalls den Zielserver, sodass letztlich alle generierten Links zu einem solchen Server zugelassen sind.

Meine Suche verlief jedoch zunächst nicht sehr erfolgreich. Viele gefundene Ansätze passte nicht wirklich in mein Konzept. Im letzten Schritt kontaktierte ich dann auf dem offiziellen Discord von D.JS die Community und hatte innerhalb von 2 Minuten doch tatsächlich einen brauchbaren Ansatz, der letztlich auch eine Lösung lieferte.

Um vielleicht Anderen, die vor dem gleichen Problem stehen, die Suche zu vereinfachen, hier ein Auszug, wie ich das gelöst habe.

Zur Identifikation des Links in einer Nachricht verwendet man RegEx (Regular Expression) das genaue Suchmuster für Discord Links wurde mir glücklicher Weise direkt von einem Communitymitglied mit geliefert.

Letztlich sieht dann die Suche wie folgt aus:

let DiscordInvite = /(https:\/\/)?(www\.)?(discord\.gg|discord\.me|discordapp\.com\/invite|discord\.com\/invite)\/([a-z0-9-.]+)?/i;
DiscordInvite = DiscordInvite.exec(message.content);

Dies gibt in dann in DiscordInviteein Array mit diversen Informationen zum gefundenen Link aus. Der Link selbst befindet sich dabei auf Position 0.

discordInvite = discordInvite[0];

Der Erste Teil meines Ziels war somit Erreicht. Möchte man übrigens nur feststellen, ob ein Link vorhanden ist, kann man auch einfach nur

DiscordInvite = DiscordInvite.test(message.content);

nutzen. Hier bekommt man dann ein true bzw. false.

Die letztlichen Informationen über den Zielserver kann man dann über

client.fetchInvite(discordInvite).then(invite => { }

abrufen. invite.guild.id liefert dann zum Beispiel die ID des Zielservers, invite.guild.name den Namen, und so weiter.

Ich hoffe ich konnte mit diesem kurzen Abriss dem Einen oder Anderen helfen. In diesem Sinne viel Spaß mit eurem Discord Bot.

WoWs Skillplaner: Zusammenfassung der letzten Tage

WoWs Skillplaner: Zusammenfassung der letzten Tage

Nachdem ich gestern den ganzen Tag damit verbracht habe, das Problem eines Bluscreens beim Booten meines PCs zu beheben, läuft er inzwischen wieder.
Die Grafiktreiber hatten scheinbar einen Fehler, weshalb der Startvorgang nicht durchgeführt werden konnte.

Das hatte der Entwicklung des Skillplaners, der ja momentan durch meinen Motivationsschub schwer Rückenwind hatte, kurzzeitig etwas den Schwung genommen. Doch jetzt läuft alles wieder und es kann weiter gehen.

Derzeit bin ich dran, die verschiedenen Upgrademöglichkeiten der Schiffe einzubinden. Es wäre so einfach, wenn die Upgrades einfach nur einheitlich wären. Wenn also jedes Upgrade Boni auf die gleichen Parameter geben würde.
Aber nein, dann gibt es ja so Schiffe wie die Myogi, die nicht nur über das Upgrade der Feuerleitanlage einen Bonus auf die Reichweite bekommt, sondern auch über den C-Rumpf.

Diese Tatsache verkompliziert das Umsetzen der Werte im Planer natürlich erheblich.

Auch muss ich mir eine Möglichkeit suchen, wie ich Pflichtupgrades identifizieren kann. Also Upgrades, die als Voraussetzung für andere Upgrades gelten, wie zum Beispiel der B-Rumpf der Farragut für das Upgrade der Torpedowerfer.
In der API ist leider nicht direkt vermerkt, welche Voraussetzung ein gewisses Upgrade hat.

Diese Punkte stehen bei mir momentan ganz vorne auf der Agenda.

 

WoWs Skillplaner: Durchbruch in der Analyse der API

WoWs Skillplaner: Durchbruch in der Analyse der API

Lange Zeit stand ich vor dem riesigen Problem, dass ich zwar die Stockwerte und Anzahl der einzelnen Sekundär- und Flugabwehrgeschütze aus der API herausziehen konnte, die Upgrademöglichkeiten der Hüllen, diese auf den Schiffen aber bekanntlich verändern.

Die neuen Werte der alternativen Hüllen habe ich nur als gesamte Werte gefunden. Also zum Beispiel „Flugabwergeschütze: 39“.
Das brachte mich allerdings nicht weiter, da ich ja die genauen Werte brauche welche Anzahl von welchem Kaliber mit welcher DPS vorhanden ist, um die Veränderungen durch die gewählten Skills anzeigen lassen zu können.

Rückfrage beim Wargaming API Support brachte mir nur die Antwort, dass diese nicht aus der API zu beziehen sind, sondern nur die von mit gefundenen, aufsummierten Gesamtzahlen.
Ich hatte somit das Einbinden der Hüllenupgrades schon abgeschrieben und ich muss auch gestehen, dass mich diese Rückmeldung durch den Support extrem demotiviert hat, das Projekt noch weiter zu führen, weshalb sich das letzte Jahr auch nicht sonderlich viel getan hat.

Ich fand das eine massive Schwachstelle der API, die ich eigentlich nicht für wahr halten konnte. Somit habe ich mich nun nach einem Jahr Pause noch einmal hin gesetzt und habe die API Abfragen nochmal in alle Richtungen getestet.

Und siehe da, ich scheine etwas gefunden zu haben. Wie es aussieht sind diese Werte über Umwege doch zu bekommen.
Das war eindeutig eine Falschmeldung des Supports. Entweder hatte der Mitarbeiter keine Ahnung oder keine Lust darüber nach zu denken. In jedem Fall ärgerlich.

Ich will jetzt nicht direkt sagen, dass die Hüllenupgrades innerhalb von kürzester Zeit ihren Weg in den Planer finden, denn es ist eine menge Arbeit allein die Abfrage für alle Daten zu erstellen.

Ebenso werde ich vermutlich zur Umsetzung die komplette Datenbankstruktur des Planers ändern müssen, aber es wird kommen!
Ich bin wieder voll motiviert das zu schaffen.

Zum Planer: https://wows-skills.p4web.de

Also stay tuned!

Raspberry Pi Zero W: WLAN Konfiguration headless

Raspberry Pi Zero W: WLAN Konfiguration headless

Hallo zusammen, mal wieder eine kleine Hilfestellung von meiner Seite bei einem Problem, mit dem ich mich vor ein paar Tagen auseinander setzen musste.

Ich habe mir für ein Projekt, was ich hier auch bald noch vorstellen werde, einen Raspberry Pi Zero W zugelegt ohne jedoch ein mini-HDMI kabel oder einen Adapter zu besitzen. Ich muss zugeben, das war von meiner Seite zunächst einfach nur ein Fehler bzw das „mini“ in der Produktbeschreibung überlesen.

Jedoch stand ich nun vor der Problematik, wie ich den Pi nun headless konfiguriere.
Zunächst habe ich mir das neuste Raspbian in der Lite Version auf mittels des Tools Etcher auf meine SD Karte Geschrieben.
Einen Desktop brauche ich für mein Vorhaben nicht, daher nur die Light Version.

Nach erfolgreichem Schreiben habe ich die SD Karte erneut in meinen Kartenleser gesteckt. Nun konnte ich auf die boot Sektion von Raspbian zugreifen.
Über Tutorials im Internet habe ich erfahren, dass ich nun einfach nur eine leere Datei mit dem Dateinamen „ssh“ ohne “ und ohne Dateiendung anlegen muss, um ssh auf dem Pi zu aktivieren. Das war nun weniger das Problem.
Etwas geklemmt hat es bei der Konfiguration des WLAN Zugangs.

Hier findet man zwar auch viele Beschreibungen, die sagen man solle eine Datei Namens „wpa_supplicant.conf“ und folgendem Inhalt anlegen:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
ssid=“NAME DES NETZWERKS“
psk=“NETZWERKSCHLÜSSEL“
key_mgmt=WPA-PSK
}

Jedoch stellte mein Pi damit nie eine Verbindung her. Ich nutze eine Fritzbox mit WPA2 Verschlüsselung.
Lange habe ich gesucht und schließlich in den Kommentaren eines Tutorials die Lösung gefunden. Ich musste die Datei um eine Zeile erweitern und siehe da, der Pi stellte eine Verbindung her.

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=DE

network={
ssid=“NAME DES NETZWERKS“
psk=“NETZWERKSCHLÜSSEL“
key_mgmt=WPA-PSK
}

Vielleicht kann ich mit dieser Beschreibung jemandem das stundenlange Suchen ersparen.

Viel Erfolg!

php / js: Lightbox ohne viel Schnickschnack

php / js: Lightbox ohne viel Schnickschnack

In einem meiner Projekte stand ich vor der Frage, wie ich es schaffe, ein Formular zur Eingabe von Daten in eine Liste, die ich dann komplett ausgebe, möglichst schön und platzsparend unter zu bringen.
Gleichzeitig soll das Eingabefeld eines Datums über ein Kalender-Overlay befüllt werden.

Ich entschloss mich also das Formular in eine Lightbox zu packen und somit nur sichtbar werden zu lassen, wenn der User auch wirklich was eingeben möchte.
Lightboxen findet man im Internet nahezu wie Sand am Meer. Meist werden diese mittels einer Javascript Datei (.js) eingebunden. Hier hatte ich allerdings jedes Mal das Problem, dass Kalender-Overlay hinter der Lightbox öffnete, was eine Bedienung unmöglich macht.

Ich suchte also nach weiteren Möglichkeiten und fand schließlich eine Lightbox zur Darstellung einer Bildergalerie, die weitestgehend auf html und CSS setzte und nur minimal Javascript beinhaltete.
Diese habe ich mir dann dahingehend modifiziert, dass sie meinen optischen Ansprüchen genügte und mein html Formular statt dem Bild anzeigte.
Falls jemand ein eine ähnliche Anwendung hat, möchte ich hier meinen modifizierten Code zur Verfügung stellen.

Zunächst packt man in den Header das einzige an Javascript, was für diese Lightbox nötig ist:

<script>
function openmodul() {
         document.getElementById("modulbox").style.display = "block";
}

function closemodul() {
         document.getElementById("modulbox").style.display = "none";
}
</script>

Es handelt sich hierbei ausschließlich um Aufrufe, die die BoxID ein- bzw. ausblenden.

Anschließend braucht man einen Trigger, der die Lightbox aufruft. Ich habe hier einen einfachen Linktext genommen. Der eigentliche Link werweißt auf „javascript:;“.
Das onclick Event verweist auf das zuvor angelegte Script und führt dazu, dass der html-Container eingeblendet wird.

<a href="javascript:;" onclick="openmodul();"> Neuer Eintrag </a>

Nun kommt der Abschnitt des eigentlichen Contents. Dieser ist in diverse DIV-Container geschachtelt, die ein Styling erlauben.

<div class="mod-content">
         <div id="modulbox" align="center" class="modul">
                  <span class="close cursor" onclick="closemodul()">&times;</span>
                  <div class="hidden-content">
                           Hier steht dein html/php Code
                  </div>
         </div>
</div>

Mehr ist es prinzipiell nicht, alles Weitere wird nun über CSS im Styling erreicht.

.close {
         color: white;
         position: absolute;
         top: 10px;
         right: 25px;
         font-size: 50px;
         font-weight: bold;
}

.close:hover, .close:focus {
         color: #999;
         text-decoration: none;
         cursor: pointer;
}

Dies erstellt das bekannte X in weiß zum Schließen der Lightbox mit einer netten Hover Opitk.

Anschließend noch das Styling der DIV-Container

.mod-content {
         position: relative;
         background-color: #fefefe;
         margin: auto;
         padding: 0;
         width: 90%;
         max-width: 1200px;
}

.modul {
         display: none;
         position: fixed;
         z-index: 1;
         padding-top: 100px;
         left: 0;
         top: 0;
         width: 100%;
         height: 100%;
         overflow: auto;
         background-image:url(../img/blackpixel.png);
         background-repeat:repeat;
         /* background-color: black;*/
}

Bei der Modulbox habe ich die Hintergrundfarbe „black“ auskommentiert. Das Stellt den Hintergrund der Lightbox dar. Ein flächiges Schwarz war mir da aber zu mächtig.
Statt dessen habe ich mir einen schwarzen Pixel mit einer Farbsättigung von ca 80% (Link anklicken, auf der neuen Seite Rechtsklick – Speichern unter) erstellt und dieses als Hintergrund eingebunden und flächig wiederholt. Dieses bildet dann eine Art verdunkelten Hintergrund, durch den man aber noch die eigentliche Seite sehen kann.
Anschließend habe ich die Box für den Inhalt noch mit einem weißen Hintergrund versehen, die Breite angepasst und einen inneren „Rahmen“ von 10px gesetzt.

#hidden-content {
         background-color: #ffffff;
         width: 400px;
         padding: 10px 10px 10px 10px;
}

Schon sollte die Lightbox funktionieren.
Ich hoffe, dass ich in meiner Beschreibung nichts vergessen habe. Viel Spaß damit!

Archive

Kategorien