il wincane pigliacane (per id)

Dopo mesi e mesi in cui mi sono semplicemente ROTTA di lavorarci, l’altro giorno è stato momento di migliorare un po’ il #WinDog delle berve… Precisamente, aggiungere altri strumentopoli al suo interno, che saranno a brevissimo utili per costruire altri strumentopoli, che ci serviranno più tardi. 🤫

Mi serviva una API interna per ottenere qualsiasi messaggio raggiungibile dal bot, in qualsiasi momento, sapendone l’ID suo e della stanza. Su Matrix e da altre parti, questo sarebbe una chiamata REST stupida, ma su Telegram… l’immensa insaggezza di Pavel Durov colpisce un’altra volta: vari dei metodi carini per recuperare vecchi messaggi non sono accessibili ai bot… 😩

Per fortuna, al di là di salvare sul server tutti i messaggi man mano che arrivano o sono modificati, cosa che non voglio assolutamente fare, perché fa schifissimo per almeno 5 motivi diversi… Gli ingegneri hanno lasciato in bella vista un segreto, ossia che un bot può accedere a dei messaggi, date le loro coordinate assolute, con i metodi forwardMessage[s] e copyMessage[s]… 🦄

Precisamente, forwardMessage è il migliore di tutti i tempi perché, a parte effettuare l’azione descritta dal nome, restituisce nel corpo JSON le varie informazioni interessanti sul messaggio specificato. E quindi, semplicemente il bot chiede al server di #Telegram di fare l’inoltro di un dato messaggio su di un canale di servizio, e appena letti i dati cancella la copia (ma il canale ha anche la cancellazione automatica, per ogni evenienza). Wow!!! 🍾

Alla fine non fa manco troppo schifo come metodo, e il codice è venuto anche piccolo. Peccato solo che non funzioni per leggere messaggi da gruppi e canali con la funzione di DRM/copyright/anti-copia attiva… ma per il momento non mi serve. TUTTAVIA, i metodi copyMessage[s] questo limite non lo hanno… 😛

…e avrei implementato direttamente questi ultimi allora, se non fosse che loro invece non restituiscono i dati del messaggio via HTTP, ma solo l’ID della copia. E quindi non si può in realtà usare…… se non collegando un gruppo al canale di servizio, ascoltando quindi tra i vari update del bot i messaggi che appaiono in quello (e da questo punto in poi il codice diventerebbe strutturalmente asincrono e spaghetti), associando ogni dato ID di messaggio ricevuto lì a quelli inviati nel canale (che non è un problema se gruppo e canale sono sincronizzati, ma potrebbero andare fuori asse se un giorno il server di Telegram è sovraccarico), e sperare. 🤌

CHE BORDELLO. Quindi, per ora penso a gestire solo le chat normali, dove almeno so che funziona bene (ma comunque non nelle chat private, ossia tra bot e utente, dove proprio non funziona… ma non mi freca)… poi vedremo. Il comando /getmessage è dunque stato aggiunto, e /dump è stato aggiornato per supportare le richieste con ID… ma per ora solo per gli admin del bot (io!), perché bisogna prima implementare la sicurezza (!!!) 🙌

#Telegram #WinDog

messages.Messages

Object contains information on list of messages with auxiliary data.

Damn. Pensavo di postare questo prima, ma mi seccava fare tantissimo rumore per un obiettivo al di sotto del mio ideale inizialmente prefissato, quindi… ho dovuto programmare per qualche ora in più. Beh, dopo altri 2 giorni di lavoro a tempo più che pieno, ma retribuzione monetaria pari allo zero spaccato, la versione #web di #WinDog è già molto più del proof-of-concept del mese scorso… 😌

Ora ha una UI decente (al buono ci arriveremo con calma) e un backend arronzato meno, che permette di aprire stanze di chat col bot anche ad URL personalizzati, e… da diversi client insieme; vale a dire che praticamente ho, senza volerlo, implementato una chat vera a propria, anche tra utenti web diversi. In effetti volevo semplicemente rendere “riciclabili” le stanze, per preparare il server a future migliorie, ma nel farlo è uscita fuori una problematica tale che mi è quindi convenuto fare come ho fatto. Quindi, ogni client riceve un colore a caso, e un username generato dall’hash di alcuni header HTTP, e boh buffo chat anonima kek. 🤪 (Non abusatene…)

La persistenza dei messaggi la implementerò più avanti, così come utenti non-anonimi, account, o stanze private/riservate… per ora appunto è tutto pubblico, ma generato casualmente; aprendo la root del sito viene creata una nuova stanza con un UUID sicuro, e aprendo qualunque stanza viene istanziato un utente con un altro UUID (che è segreto, non è l’username). Stanza di esempio, magari se la aprite tutti insieme beccate me o qualcun altro, idk: windog.octt.eu.org/fritto-misto-019143d9bf9b7337adca0cbf2fe2efb9. 😈

Questa è una delle più potenti manifestazioni della mia #magia… Il fatto che la codebase di questo coso sia vecchia di almeno 3 anni, e che ciò che prima era un banale #bot Telegram ora è un multiforme multipiattaforma, ad un livello che altri bot in giro non ne ho visti, è già tanto, ma… questa interfaccia in particolare, che gira nel browser, ancora senza alcuno script client-side (sans-JS), è proprio lo scopo della mia esistenza, la più valorosa e autogratificante espressione dei miei poteri di puella magica!!! (Sono davvero stranamente felice.) A dire il vero, eh, oggi del JS l’ho aggiunto, ma giusto per far comportare meglio la casella di testo, sfruttando la logica del miglioramento progressivo: chi ha JavaScript funzionante nel browser avrà la textbox che si allarga e si restringe in automatico con la scrittura, e potrà inviare il messaggio facendo Ctrl+Enter, ma la #chat funge lo stesso senza. 🕷️

Comunque… che voi siate veri fan di HTML5, o che invece senza JavaScript non riusciste a combinare un accidente (maledetti #webdev moderni), concordete che è assurdo come io abbia potuto usare una #hack basata su una funzione di #HTTP e dei browser risalente al millennio scorso (!!!) per creare una live chat che funziona in #HTML puro, con addirittura meno lag di Telegram o qualsiasi cosa… Però poi bisogna cringiare per una casella di testo multilinea come si deve… E, ancora, non c’è modo di far scrollare in automatico in basso man mano che ci sono nuovi messaggi (per ovviare a quello si nota come ho scelto il male di UX minore, cioè invertire l’ordine della chat, per ora). Almeno, però, commettendo abusi sugli iFrame, due (2) problemi li ho risolti: mostrare un messaggio di errore in caso di caduta della connessione, e non far apparire la finestra come continuamente in caricamento… 🙏

https://octospacc.altervista.org/2024/08/12/wincane-con-il-web-reale/

#bot #chat #hack #HTML #HTTP #magia #sansJs #web #webdev #WinDog

wincan do be funnying - fritto misto di octospacc

Oggi dico: caspita, perché l’attuale è il postaggiobuco più grosso che io abbia mai creato. Almeno, quello che non scrivo qui in italiano lo scrivo nelle mie repo in millemila (3) linguaggi interpretati. A parte uno strumentopolo complicato che ho iniziato ieri, credo finirò domani, e posterò domai, la #programmazione sta andando alla grande per […]

fritto misto di octospacc

Oggi dico: caspita, perché l’attuale è il postaggiobuco più grosso che io abbia mai creato. Almeno, quello che non scrivo qui in italiano lo scrivo nelle mie repo in millemila (3) linguaggi interpretati. A parte uno strumentopolo complicato che ho iniziato ieri, credo finirò domani, e posterò domai, la #programmazione sta andando alla grande per mezzo delle mie manine e fine di #WinDog… 🤗

Detto al volo perché devo mimir: in questi 3 giorni nel #bot ho implementato un’altra funzione inutile (questa per fare [de]codifica di testo), e una utile che me lo fa riavviare (per quando modifico il codice) senza passare dal terminale del server; ho magicamente fixato l’invio di messaggi bridgiati, ho ripulito gran parte del codice togliendo anche delle cose più che deprecate, ho aggiunto funzioni alla API per standardizzare i messaggi di aiuto e quelli di errore, sistemato qualche comando vecchio, e insomma funziona già tutto meglio di prima. 🤑

L’unica cosa che richiederà ancora non poco sforzo in realtà è proprio il bridging, perché, seppur ora i messaggi li può mandare avanti e indietro, non può sincronizzare cose come modifiche o cancellazioni, oltre a non poter leggere reazioni o qualunque evento di messaggistica speciale… quindi non è utilizzabile. Oltre a questo, voglio in realtà rendere programmabili i ponti usando la runtime Lua (che già è nel bot!), così da rendere possibile la configurazione più estrema del loro comportamento (filtrare messaggi per testo, farlo andare solo ad una certa ora… le possibilità sono troppe).

Poi… sia per far andare bene i bridge, che per renderli programmabili a qualunque utente senza obbligo di self-hosting, che per aggiungere ancora altre cose al bot (tra cui minigiochi con uno stato e insomma cose epiche), dovrei anche finire il database, credo… yikes, difficile perché non so mai in anticipo cosa mi serve, quindi devo farlo via via, con tutte le scocciature del caso. Comunque, qualcosa a proposito di quello funzionerebbe già: per ora dopo il mio fix c’è il comando /config che permette almeno di cambiare la lingua del bot (wow). Darò a ciascun utente ben 512 KB di spazio per conservare script Lua… godi popolo per la mia generosità!!!

L’ultima cosa, che però ho già finito, appunto ora, è una API più specifica per inviare messaggi di servizio, come errori e aiuto… anziché ogni volta nei moduli richiamare invio di un messaggio generico, uso queste specifiche per avere meno boilerplate e, soprattutto, avere dei comandi che sembrano effettivamente parte dello stesso bot, non un’accozzaglia di funzioni ognuna con estetica di testo diversa. Andatevi a vedere i sorgenti se vi interessa, ma in pratica ho tutte le stringhe (anche per tante lingue) in dei file YAML con una struttura particolare, e insomma il programma fa il suo. Sorprendentemente, YAML è un ottimo formato per conservare piccole stringhe HTML, e HTML è un ottimo formato quando il testo fa così tanti giri che non puoi tenere traccia di come fare escaping di eventuali simboli speciali… (Markdown cacca).

Share this page from your fediverse server

https:// Share

This server does not support sharing. Please visit .

https://octospacc.altervista.org/2024/08/10/wincan-do-be-funnying/

#programmazione #bot #WinDog

programmazione fumosa - fritto misto di octospacc

Sempre a dir poco #mistico svegliarsi dal mimire notturno e sentire così l’aria della mia stanza che puzza di marcio, il mio alito da vulcano, la testolina che gira perché l’ossigeno è solo un ricordo di prima di andare a dormire… nonostante questo, riesco comunque tranquillamente a posticipare le sveglie, e non sento particolare fretta […]

fritto misto di octospacc

Stavo quasi per finire la parte di base del bridging di messaggi oggi in #WinDog, che grazie alla API cross-platform che ho costruito dovrebbe in realtà essere questione di poco conto… perché si tratta di usare funzioni già esistenti per elaborare strutture dati già pronte, ma in modo diverso. Peccato che c’è qualche inconveniente per come i messaggi vengono sdoppiati, oltre al fatto che per le varie piattaforme ho ancora da implementare una marea di metodi (su tutte mancano modifica e cancellazione dei messaggi, pensa te), quindi mi sono scocciata oggi pomeriggio e ho pensato… ma quasi quasi ci vuole un bel proof-of-concept della futura versione #web del #bot, totalmente funzionante senza #JavaScript… 👽️

Beh, dopo essermi fatta distrarre da altri esperimenti in realtà ho già fatto e finito qualcosa di molto grezzo, però neanche io credevo di riuscirci a questa maniera… Il punto è che, prendendo ispirazione da github.com/kkuchta/css-only-chat (anche se io ho implementato tutto in modo molto diverso, senza la brutta #hack CSS), ho creato una live chat in HTML puro, che si aggiorna di continuo e con latenza bassissima, senza costringere a ricaricamenti della pagina, ma sfruttando il meccanismo pazzoide che ho fatto meglio a illustrare in video. Fatto al volo eh, senza manco il tempo di sistemarlo, tant’è che ci sono dei memory leak sicuri, ma questo sarà un problema dell’Octt del futuro (di domani o chissà quando). 💨️

Non so se lo lascerò ancora prima di sistemare estetica e codice, ma nel dubbio, dovrebbe stare su WinDog.octt.eu.org. Il meccanismo per cui la pagina si aggiorna senza script e senza flickering, lo spiego meglio, è fighissimo: con l’header HTTP Content-Encoding: chunked, il browser è forzato a renderizzare l’HTML senza aspettare che la connessione si chiuda; dall’altro lato, il server non termina mai la connessione (infatti c’è un loop infinito che preleva dati da una coda, e wow, quella struttura ritorna dopo appena un giorno…), inviando via via frammenti di #HTML che vengono appesi in fondo alla pagina. Stranamente, questo comportamento si vede funzionare correttamente solo collegandosi con normali browser o client TCP grezzi (netcat)… curl semplicemente si blocca, invece. E, ancora, il Content-Type deve essere esattamente text/html; charset=UTF-8, basta anche solo omettere il charset per rompere tutto! La casella di invio, invece, è banalmente dentro un iframe. Direi allora che questo è abbastanza #HTTP 1.1 per oggi… 🥰️

https://octospacc.altervista.org/2024/07/01/wincane-no-js/

#bot #chatbot #demo #hack #HTML #HTTP #JavaScript #noJs #POC #sansJs #web #WinDog

GitHub - kkuchta/css-only-chat: A truly monstrous async web chat using no JS whatsoever on the frontend

A truly monstrous async web chat using no JS whatsoever on the frontend - kkuchta/css-only-chat

GitHub

Oggi #rant allucinante, è la prima volta che Python mi fa venire così tanta voglia di #piangere… mi farebbe proprio molto piacere conoscere chi sono i PAZZI pazzoidi che hanno completamente ROVINATO il linguaggio introducendo asyncio. Maremma trogolaia, è un merdaio allucinante secondo me, un’implementazione apparentemente furba di async/await, che però è estremamente malata: nel momento in cui si hanno davanti problemi reali, la presenza di anche un solo po’ di codice asyncio va a contaminare tutto il resto che ne dipende, ed è un incubo… Sento già il “beh, se fa schifo questa funzione di Piton allora non usarla…“; peccato che tutte le librerie di terze parti che adottano questa maledizione per il loro funzionamento, puntualmente, vanno a deprecare il vecchio codice normale. Quindi si può solo piangere, concedetemelo. Fortunatamente, sembra che io non sia l’unica ad odiarlo… 😭️

Apparentemente, asyncio sembra appunto simile all’asincronicità che si ha su JavaScript da ES6, ma è molto, molto peggio. Il problema più grosso è che costringe alla propagazione, cioè: funzioni async possono essere chiamate solo usando await, ma la parola await può essere specificata solo dentro funzioni async… quindi, tutto un dato stack di chiamata deve essere fatto tenendo conto di asyncio, e questo significa dover ristrutturare per intero vecchi programmi (mentre, su JavaScript, funzioni asincrone possono essere richiamate anche senza attenderle, semplicemente omettendo await). Io il restructuring non la farò, perché non andrò a perdere ore solo per il risultato di rendere il mio codice ancora più complicato da mantenere, quindi… Per fortuna, esiste il metodo .create_task() per avviare qualcosa di asincrono da un contesto asincrono e lavarsene le mani… però, aspetta, esiste anche .ensure_future(), e… non se ne esce… 🥴️

Ecco un altro problema di asyncio che, coincidentalmente, fa anche rendere conto di quanto brutta di una hack sia la sua implementazione… è letteralmente costruita alla bene e meglio al di sopra di parti già esistenti di Python e che non avrebbero mai dovuto accomodare niente di simile. E, nel corso dei vari major update, questo modulo ha accumulato così tanta roba, teoricamente tutta diversa ma nella pratica indistinguibile per le differenze troppo sottili, che a questo punto non mi stupisco di come mai ho perso ore e ore appresso al mio problema oggi. Non ho letto il codice che ci sta dietro eh, mi risparmierò questa tortura, ma ho come il presentimento che sarà proprio la sagra del lasagna code… persino la documentazione ufficiale fa parecchio paura, e ciò fa pensare, perché in genere quella di Python mi pare tutto sommato buona — ho visto di meglio eh, però certamente non è malvagia. ⛏️

Addirittura asyncio avrebbe tecnicamente una specie di stato globale (bad!!!), al di sopra di cui è costruito un event loop. È per questo motivo che ha una serie spaventosa di metodi globali per gestirne il funzionamento (che non posso realisticamente elencare nella totalità), ed è questo che poi fa scaturire i problemi pratici nel mischiare codice asincrono con tradizionale. Soprattutto quando, come nel mio caso, il codice tradizionale gira molto attorno all’uso di thread secondari (perché deve lavorare in un modo che è sempre non bloccante, che non ha mai da awaitare niente). Vi giuro, ci ho provato in tutti i modi più strani letti da una decina di discussioni online diverse, ma no, non c’è verso di richiamare metodi gestiti da asyncio da un thread diverso da quello in cui questi risiedono (o partono errori, oppure addirittura comportamento indefinito). Su #Python non si può abusare il sistema degli eventi come su JavaScript per mettere una pezza a ciò, quindi la situazione è nera. 🕋️

Mi disp, dovevo sfogarmi, visto che tutto questo è stato semplicemente per… mettere le fondamenta per il bridging dei messaggi tra piattaforme diverse in #WinDog… nello specifico, verso Matrix (@windog:matrix.org), perché è con la libreria matrix-nio che sto sclerando. Maledetti loro che hanno fatto a pezzi il vecchio HttpClient, continuando a mantenere solo l’AsyncClient. Ancora non ho caricato il nuovo commit, ma comunque, questo è il codice che alla fine ho scritto per risolvere il problema… bruttissimo, non volevo davvero ricorrere a ciò, ma non voglio nemmeno ristrutturare l’intero bot, né tantomeno buttare questa libreria e reimplementare a manina in HTTP le tantissime API che mi servono. Quindi, la mia soluzione è stata usare una coda in cui inserire i dati che vengono da thread separati, e questa poi verrà gestita dall’unico thread dove gira il #codice di Matrix… tutto con un uso molto specifico dei vari metodi di asyncio. È dolore. 👇️

def handler(...): async def queue_handler(): asyncio.ensure_future(queue_handler()) if not len(queue): # evitare che la CPU vada al 100% ☠️ time.sleep(0.01) while len(queue): sender(*queue.pop(0)) async def client(): # [...] asyncio.ensure_future(queue_handler()) # [...]def sender(...): try: asyncio.get_event_loop() except RuntimeError: queue.append(...) return None asyncio.create_task(...room_send(...))

https://octospacc.altervista.org/2024/06/29/odio-asyncio/

#async #asyncio #codice #piangere #problemi #programmazione #Python #rant #WinDog

Ecosia - the search engine that plants trees

Ecosia uses 100% of its profits for the planet and produces enough renewable energy to power all searches twice over.

Novità dal fronte @WinDogBot sviluppo? A parte il fatto che tutti vogliono feature a non finire, ma nessuno e dico nessuno vuole collaborare alla programmazione (cosa che appunto non è una novità per i miei progetti), e che sto rimaneggiando praticamente tutto il codice perché non che fosse scritto male, ma comunque certe cose non si capiscono bene… ieri e oggi ho aggiunto altri comandi per generare contenuti spazzatura, che /dalle da solo già non bastava più. 😤

Il fatto è che ieri pomeriggio ci siamo messi a fare non so quante richieste più o meno ambigue a Copilot, tutte rifiutate in tronco con l’avviso riguardo i termini di servizio. A un certo punto ha iniziato a dare errori di continuo… “sarà di nuovo il bug del mio codice, ora riavvio”… peccato che riavviare il bot non ha sistemato nulla, quindi vado a vedere dal mio browser… e scopro questo bellissimo ban!!! Ho aspettato l’ora, e adesso funziona di nuovo, ma ho aggiornato il messaggio di errore del bot per far notare con più forza che bisogna evitare certi prompt. 😰

Nota a margine: ma perché Microsoft mette così tante restrizioni? Io posso anche capire nel momento in cui mi blocca il prompt dove chiedo delle bombe nucleari, ma già inizio a storcere realmente il naso quando quelle bombe non vanno bene nemmeno se sono in Minecraft o Animal Crossing… anche se poi una normale bomba senza aggettivi te la fa, con pure le farfalle attorno. Però non capisco, che problemi ci sono con i femboy con la faccia sporca di colla??? Oh io ho detto colla, non cumma, voglio semplicemente vedere la sua faccia sporca di colla… se quella colla poi sembra sborra non è colpa mia, uffa!!! Ora anche la colla non è più politicamente corretta, e non so più a chi chiedere per avere disegni non-espliciti (se volessi la cumma, allora la cercherei sul web, ma io voglio la colla, zzzzzz…)! 😭

E praticamente stavo cercando un modo di valutare se un dato prompt in input dagli utenti sia buono o cattivo per gli standard di Microsoft, ma, purtroppo, non c’è stato verso. Persino la mia unica vera speranza, cioè chiedere ogni volta a ChatGPT, non funziona bene, caccia decisamente troppi falsi positivi. Però, sperimentare con GPT4Free è stato buono perché ho potuto aggiungere il comando /gpt senza creare il mio scraper, e ora ci si diverte ancora di più… E, già che non ci voleva nulla, ho usato sempre SeleniumBase per creare uno scraper per /craiyon, che ha qualità decisamente più bassa ma niente vincoli di sicurezza. 😈

https://octospacc.altervista.org/2024/06/20/artificial-impertinence/

#ban #BingAI #BingCopilot #ChatGPT #Copilot #Craiyon #DALLE #GAN #GPT #GPT3 #IA #ImageCreator #Microsoft #MicrosoftCopilot #programming #scraping #WinDog

WinDog

WinDog multi-purpose chatbot, released under AGPLv3: https://gitlab.com/octospacc/WinDog

Telegram

Sto sclerando talmente tanto appresso al WinCane da stamattina (leggi come: ieri sera; comprendi come: sono quindi anche in quel caso andata a mimire più tardi del previsto) che, stando appresso anche all’esame di domani, mi sto trovando a dover scrivere questo messaggio mentre cammino ora per strada, per distrarmi. Spero vivamente le mura non ci restino male, tanto tra poco torno, anche perché comunque gli #scleri sono serviti a qualcosa. ❤️‍🔥

Ieri è uscita fuori la voglia di aggiungere la generazione di immagini tramite #GAN al bot, per sostituirne un altro che coi suoi ratelimit ha subito scocciato. TLDR: dopo aver imparato Selenium il giusto, e ora pure aver creato un account Microsoft dedicato per evitare che i loro sistemi si insospettiscano del traffico e mi bannino (NON perderò l’account con 100K+ punti accumulati), ora c’è il comando /dalle che prende i risultati direttamente da #Copilot, senza alcun compromesso. Provate su @WinDogBot, noi abbiamo generato merda per ore… 💩

Sorprendentemente, è accettabile veloce (10-15 secondi?), e restituisce tutte le immagini che #Bing genera (da 2 a 4; purtroppo con la libreria di merda dei #bot #Telegram ho un errore quando provo a inviare le foto raggruppate, quindi vado una alla volta con buona pace dello spam), e pur avendo ampiamente finito i fulmini non sto avendo rallentamenti. E tutto questo il bot lo fa comandando una finestra di Chrome, lol, perché alla fine #Selenium è questo, e proprio per questo si riesce a fare tutto con poche righe di codice: bisogna solo dire al software cosa cliccare nel modo in cui lo farebbe un umano, non c’è da avere a che fare con strambe strutture dati. 🕊️ (Lo chiamo “metodo Rabbit R1”, perché questo è…)

Per chi non avesse capito perché faccio in questo modo: NON PAGO UN CAZZO. Anziché dare a #OpenAI quei soldini per DALL-E, che subito mi farebbero finire sul lastrico con il ritmo con cui richiediamo immagini nel gruppo (oltre al fatto che credo OpenAI non accetti criptovalute), mi accontento di consumare qualche centinaio di MB di RAM e disco in più per far girare dei browser headless, e il cane mi automatizza tutto, a #scrocco. Dei, appunto perché per ora ho permesso al programma di aprirne fino a 2 in parallelo, cosa che coprirà bene i momenti più concitati senza però saturare il mio server. E questa soluzione sembra quasi magia, però ho dovuto nello specifico usare #SeleniumBase con la sua modalità che blocca il rilevamento dei bot perché, a quanto pare, con Selenium normale headless il form di #Microsoft non veniva correttamente inviato… L’importante è che ora va tutto. 😋

https://octospacc.altervista.org/2024/06/18/il-cane-da-li/

#AI #Bing #BingAI #BingCopilot #bot #Copilot #GAN #IA #ImageCreator #Microsoft #OpenAI #programming #Python #scleri #scraping #scrocco #Selenium #SeleniumBase #spacctorium #Telegram #WinDog

WinDog

WinDog multi-purpose chatbot, released under AGPLv3: https://gitlab.com/octospacc/WinDog

Telegram