Caffè Italia

0 readers
0 users here now

Caffé italia è la community dove poter parlar di tutto quello che non ha una community specifica in feddit.it

founded 2 years ago
MODERATORS
1
 
 

Non sapevo bene dove postarlo, un BBQ fatto coi Lego!

Link Piped

2
 
 

Interessante vedere che ha 580 view e 535 acquisti. I cryptobro comprano sta robaccia così senza nemmeno pensarci

3
4
 
 

(O Bitwarden, o Aegis, o Authy, a vostra scelta, è un TOTP standard non proprietario)

è troppo più comodo avere lo spid senza un'app dedicata inutile

5
 
 
6
 
 

La7 sta trasmettendo il campionato di calcio arabo in TV????

Ma c'è gente che guarda sta roba?

Probabilmente l'unico evento sportivo con i diritti d'autore pagati al contrario

7
8
 
 

Ho molto chiari i motivi per i quali la gente non ha lasciato in massa Twitter da quando è diventato la cloaca che è, magari in favore di Mastodon o di Misskey; ciò che non comprendo è come mai invece questa cosa non sia successa per Reddit, che somiglia molto di più ad un forum e nel quale vedo molto meno forte l'aspetto di network, e quindi di legami da conservare. Secondo voi?

9
 
 

Grazie alle poste domani mi tocca stare 30 minuti in coda all'ufficio postale e ritirare il pacco perché hanno effettuato la consegna e la riconsegna in orario di chiusura. Ma cazzo, se fai una consegna a un negozio alle 14 durante la pausa pranzo e vedi che è chiuso, riprovi il giorno dopo alla stessa ora????

Anzi, nemmeno domani, va in giacenza tra tre giorni

10
 
 

In alcuni casi lanciare una moneta può servire a ridurre l’ansia e l’indecisione, e a valutare meglio le proprie scelte

Secondo un’opinione abbastanza comune l’azione di prendere una decisione è generalmente guidata e influenzata dagli obiettivi da perseguire e dalle informazioni a disposizione prima della scelta: più se ne hanno, più alta è la probabilità di prendere una decisione corretta. Diverse ricerche indicano tuttavia che anche altri fattori evolutivi, genetici e ambientali condizionano continuamente le nostre scelte. E nella quotidianità ci sono casi in cui avere più informazioni – scorrere per intero un menu particolarmente dettagliato prima di ordinare al ristorante, per esempio – complica la scelta anziché semplificarla, e aumenta il rischio di pentirsi successivamente della decisione presa.

Alcuni studi di scienze sociali hanno esplorato in anni recenti la possibilità che in particolari circostanze, a fronte di scelte difficili, la casualità sia un fattore utile a prendere decisioni soddisfacenti e meno esposte al rischio di successivi ripensamenti. In questi casi includere nei processi decisionali l’influenza di un fattore apertamente fuori dal nostro controllo può contribuire a ridurre l’impressione fallace che ogni cosa lo sia. E può ridurre l’ansia in situazioni di indecisione in cui la valutazione delle scelte possibili e la paura del fallimento diventano paralizzanti.

Secondo lo psicologo statunitense Barry Schwartz una delle principali cause di ciò che in un suo libro del 2004 definiva «il paradosso della scelta» è una cultura dell’individualismo sempre più diffusa e dominante, che induce a pretendere la perfezione dagli altri e da noi stessi generando inevitabili frustrazioni. Nei frequenti casi in cui a seguito delle sue scelte le condizioni di un individuo non migliorano o peggiorano, scrive Schwartz, la cultura dell’individualismo stabilisce come più accettabili le spiegazioni causali che si concentrano su fattori personali piuttosto che universali, che sono anche quelle che incoraggiano le persone a incolpare sé stesse per i propri fallimenti. ... continua a leggere

11
 
 

Giochi il tuo euro ONLINE, quindi senza schedina/ricevuta di gioco (fattore non indifferente, dato che quest'ultima è a tutti gli effetti di un titolo al portatore), e incredibilmente i tuoi sei numeri combaciano con quelli estratti.

La sisal afferma che si può riscuotere in totale autonomia, sicurezza, e nel pieno rispetto della privacy, senza legale, notaio, direttore di banca o altra interposta persona: ma è davvero così?

Il pericolo di esser rapinato è da escludere, dato che la ricevuta vincente è virtuale e intestata al titolare dell'account di gioco, quindi la sisal conosce il/la vincitore/vincitrice, ma tu entreresti in uno dei due uffici/premi sisal sprovvisto di tutela?

Ti fideresti, o prenderesti delle preauzioni?

Se sì, quali?

Dato che bisogna presentarsi con un IBAN, dove faresti versare il malloppo?

Conto deposito? Altro?

Sarebbe possibile versare il malloppo su due o più conti invece di uno?

Insomma, la domanda non è cosa fareste con i soldi, ma cosa esattamente fareste per incassarli.

12
 
 

Mi sto trasferendo fra pochi giorni e devo ancora sottoscrivere un abbonamento a internet. L'appartamento non è coperto dalla fibra diretta quindi devo accontentarmi di offerte con velocità di download a massimo 200 megabit al secondo. Finora ho escluso queste aziende:

  • Fastweb e Vodafone, per la mancanza di un'IP pubblica (su Fastweb sono sicuro, su Vodafone meno)
  • Aruba, non so bene perché ma mi è stato sconsigliato Per adesso le mie contendenti, considerati i prezzi, sono Postemobile, Enel e Sky Wifi. Avete esperienze con una delle tre? Altre proposte?
13
 
 

Ha risposto con un powershell che se uno fosse così pazzo da eseguirlo elimina la partizione di sistema di windows, ne crea una nuova e la riformatta

Ora il tuo sistema è libero da problemi causati dall'DC non più attivo, e i metadati sono stati puliti per evitare futuri inconvenienti. Buon lavoro!

Tecnicamente vero, una volta che è stato piallato tutto a zero, non ho più problemi riguardo quel controller di dominio lì

14
 
 

Stavo cercando degli zaini da viaggio, in grado di contenere roba per star fuori qualche giorno, ma anche esteticamente carini da poter essere usati tutti i giorni (ho comunque uno stile abbastanza utilitarista, quindi non ho problemi a portarmi in giro uno zaino grosso).

Su Amazon però trovo solo marche cinesone, SZLX, Homiee, Bagzy... che costano relativamente poco, quindi sono best seller, ma i materiali sono decisamente inferiori, e la durata nel tempo è sicuramente limitata.

Avete consigli, magari anche di marche italiane?

15
 
 

Articolo pubblicato il 20 Luglio 2023

La collaborazione tra Archivio Storico TCI e Wikimedia Italia parte da una condivisione di obiettivi e di finalità molto affine, quasi naturale. Touring Club Italiano e Wikimedia sono due grandi comunità, l’uno con quasi 130 anni di vita, identificata da solidi valori in cui centinaia di migliaia di soci si sono riconosciuti, l’altra nata per sfruttare le infinite potenzialità del web e diffondere conoscenze. Condividere i materiali d’archivio è per TCI quasi un imperativo etico e i progetti Wikimedia sono uno straordinario diffusore.

Guarda il video: la collaborazione con Touring Club Italiano

Così, dopo l’esperienza molto positiva dello scorso anno, incentrata sulla cartografia, quest’anno abbiamo messo a disposizione più di mille fotografie storiche dell’Archivio Storico TCI (circa 350.000 stampe fotografiche dal 1870 al 1970), appositamente digitalizzate e catalogate per dare modo alla community dei progetti Wikimedia di utilizzarle al meglio: fotografie prevalentemente degli anni 1950-60, archiviate sotto il tema ‘ambiente’, inteso nell’accezione più larga possibile. Molteplici quindi i soggetti delle fotografie, dalle piante agli animali, dai fenomeni atmosferici a ambienti particolari. Molte foto dedicate a quelli che possiamo chiamare disastri e calamità naturali e alle opere dell’uomo su questo tema. Qui la selezione è stata particolarmente ampia e interessante, anche per noi archiviste. Immagini di frane, allagamenti, esondazioni di torrenti e fiumi hanno quasi simmetricamente e in parallelo documentazione fotografica di sistemazioni idrauliche, di bonifiche, di costruzioni di dighe, di rimboschimenti, di manutenzione del suolo. Documenti preziosi che restituiscono un’Italia dei disastri e un’Italia della cura, due facce della stessa medaglia.

Guarda tutte le foto caricate su Wikimedia Commons

...

16
 
 

Spesso passiamo l'anno in attesa di staccare dal lavoro, anche solo per pochi giorni. Le aspettative, però, per quei giorni sono alte e il loro non raggiungimento può influire negativamente sul nostro benessere post vacanza. Ma deve essere per forza così? Secondo uno studio non c'è molta differenza di felicità tra chi va in vacanza e chi no: ha senso quindi andare in vacanza? Assolutamente sì, ma dobbiamo imparare a viaggiare senza pretendere troppo da noi stessi.

Lavoriamo, lavoriamo e lavoriamo tutto l’anno solo in attesa di quei pochi giorni di riposo, le meritate ferie o il tempo che a forza ci siamo ritagliati con un attentissimo e meticoloso piano delle cose da fare. Le aspettative di solito per le vacanze sono molto alte: ci si deve divertire e riposo e relax sono d’obbligo. Non ci sono altre opzioni e, soprattutto, altri tentativi. Ma se non fosse così? Se il benessere che traiamo da questi pochi giorni non fosse sufficiente? Siamo davvero felici dopo che torniamo dalle vacanze? ... continua a leggere

17
 
 

Ho trovato in un cassetto una busta di caramelle SAILA e sono curioso di sapere a che era geologica appartengono.

Indizi:

  • Non c'è scritta alcuna data di scadenza. Risalgono quindi a un'era in cui non era obbligatorio scriverla sulla busta
  • C'è un codice a barre, 80379959, che corrisponde a quello attuale
  • C'è un cartellino del prezzo timbrata con una prezzatrice sopra, "£ 2400" (quindi prima del 2001)
  • Dice "Prodotto da Adams Warner-Lambert Canada inc.". Sperlari ha acquistato SAILA nel 2007, Warner-Lambert è stata acquisita da Pfizer nel 2000 e Pfizer ha venduto Adams nel 2003 a Cadbury.
  • La busta è stata stampata da "Seleprint Lainate" e cercando su LinkedIn ho trovato un paio di curriculum che menzionano di averci lavorato fino al 2001
  • Dice Prodotto nello stabilimento di Silvi Marina Teramo che pare la storica fabbrica originale
  • All'indirizzo della sede legale di Lainate presente in busta c'è ora Cosmo Pharmaceuticals che nel loro sito dicono "terminata la costruzione della sede di Lainate nel 2006"
  • Ne ho mangiata una e non mi sono sentito male (per ora)
18
 
 

Buongiorno a tutti, qualcuno sa dove si compra la RAM ECC unbuffered?

Ho comprato una scheda madre che supporta la RAM ECC unbuffered con processori consumer, volevo fare un Nas con truenas, però non riesco a trovare questo tipo di RAM in vendita da nessuna parte in Italia

Al limite si trova solo la RAM registered ECC ma a prezzi assurdi tipo 80 euro per 4gb, come se fosse una rimanenza di magazzino acquistata per sbaglio 5 anni fa e mai venduta.

Vorrei evitare di prenderla da AliExpress... (l'unico posto dove invece l'ho trovata)

19
 
 

L’allarme del responsabile Immigrazione e sindaco di Prato Matteo Biffoni: «Il governo che doveva azzerare gli sbarchi è in palese difficoltà»

20
 
 

Estate = slow days = il feed delle "notizie" è tutto tipo "Capri, ordina un caffè e lo paga 60 euro", "Como, ordina un tramezzino e lo paga 35 euro", "Modena, ordina degli gnocchi fritti e il conto è di 900 euro"

Ma non ci sono i menu? Quelli di modena che hanno speso 900 euro in taglieri come hanno fatto? Ok che erano in 24 però si può ordinare così alla cieca?

21
 
 

Sta febbretta a 37 mi durava da un paio di giorni, fatto un tampone di quelli da 1 euro al discount e c'è una doppia riga di COVID.... 😭

Dai ma proprio ora che sono in ferie...

22
 
 

Era la mia app preferita per reddit, con la versione lemmy (anche se ancora incompleta) mi sembra di essere finalmente tornato a casa noncelafacciotroppiricordi.gif

23
24
 
 

Cioè, ok ci sono le istanze, ma devo creare un profilo per ogni istanza per postare?

25
 
 

Ciao a tutti! La discussione dell'altro giorno riguardo a Bot per Lemmy mi ha invogliato a perder un po' di tempo libero e buttare giù un semplicissimo script in Rust che crea un nuovo post quando viene invocato, seguendo i dati in un file di configurazione.

Anche se si tratta, fondamentalmente, di qualcosa d'incredibilmente semplice l'ho creato in modo da dar esempi pratici a molti degli argomenti che spesso, chi inizia Rust, ha difficoltà a trovare in un insieme coerente.

Per esser chiari questa non è - volutamente - la più efficiente o idiomatica versione del codice per eseguire il compito, ma ho cercato di mantenerla semplice da capire e tendenzialmente idiomatica, evitando tutte quelle forme che potrebbero intimidire o confondere, anche se migliori.

E, soprattutto, questo non è un tutorial. Vuole solo dare una prospettiva ampia.

Dentro ci sono esempi di:

  • Option
  • match
  • Del crate reqwest, usato per inviare una richiesta POST.
  • Come leggere un file di configurazione con toml e serde.
  • Il random in Rust, che non è integrato direttamente nella Standard Library ma per cui bisogna usare il crate rand (o similari).
  • Come ottenere e formattare una data con il crate time. Normalmente ho sempre usato chrono, quindi questa è stata un'esperienza nuova anche per me! haha
  • Diversi modi per interpolare le stringhe.
  • Come attivare per un crate delle feature non default nel proprio cargo.toml
  • panic! AKA Come far crashare il proprio programma! ...volutamente!
  • expect non è il male! Ha il suo posto anche all'interno di programmi più solidi e non solo per veloce prototipi.

Ora non voglio venderlo per più di quello che è, ma credo sia una buona base di partenza per qualcuno che è interessato a Rust ma non lo ha mai visto con esempi reali, semplici e non mono argomento. Ho aggiunto anche diversi commenti che spero possano aiutare a comprenderne il flusso.

Quindi, per finire, funziona? Sì! È solido e resiliente? Nope. È una buona base per far qualcosa di meglio se volessi imparare e giocare un po' con Rust? Credo di sì.

Se volete provarlo e fare dei test, il metodo migliore è usare le istanze di test ufficiali di Lemmy:

Oppure la palestra qui su feddit.it (credo?)

Una buona alternativa sono anche i servizi come https://httpbun.org/ o https://httpbin.org/ (down al momento dei miei test).

FAQ

Perché non su github?

Al momento non ho un account che posso usare per queste cose, mi dispiace!

Ma basta che copio i file?

Beh, sì, ma sarebbe il caso di creare un nuovo progetto con cargo new --bin simplecofeebot e sovrascrivere/modificare i file.

Cosa succede se faccio cargo run?

Che invii una richiesta errata a feddit.it, perché non c'è alcun token jwt nel file di configurazione. Nel caso in cui tu inserisca un token jwt allora - se non modifichi nulla - dovrebbe inviare una nuova discussione nella comunità del Caffé, chiamata "Caffè Italia DD/MM/AAAA" con la data del giorno d'invio, ed un messaggio fra quelli nella body_pool. Quindi meglio non farlo, o si finisce per spammare il caffé. :D

Perché nel Caffè invece di Informatica?!

Leggendo le regole della comunità [email protected] mi sembra di capire sia solo incentrata sulle notizie!

Puoi compilarlo per me?

Nope. Non consiglio di usarlo seriamente così come è.

Questo codice è un macello!

Grazie, mi sono impegnato! Se hai notato bug, typo o cose insensate per favore commenta qui sotto!

Licenza???

MIT o Apache 2!


Cargo.toml

[package]
name = "simplecofeebot"
version = "0.1.0"
edition = "2021"
publish = false
license = "MIT OR Apache-2.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
toml = "0.7.6"
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
time = { version = "0.3.23", features = ["std", "local-offset", "formatting"] }
serde = { version = "1.0.174", features = ["derive"] }
serde_json = "1.0.103"
rand = "0.8.5"

/simplecofeebot.toml

[instance]
url = "https://feddit.it"
# curl --get -d "name=caffeitalia" https://feddit.it/api/v3/community
community_id = 11869

[authentication]
# curl --header "Content-Type: application/json" --request POST --data '{"username_or_email":"UsernameFigo","password":"PasswordComplicata"}' https://feddit.it/api/v3/user/login
session_token = ""

[text]
body_pool = [
    "Salve!",
    "Che piacere vederla, commendatore, il solito?",
    "Un bel caffettino?",
]
# title_pool = ["hmhm", "oh no"]

src/main.rs

// In poche parole questi sono gli import.
use std::{fs::File, io::Read, path::Path};

use rand::{rngs::ThreadRng, Rng};
use serde::Deserialize;
use serde_json::json;
use time::{format_description, OffsetDateTime};

// Creiamo una serie di Struct per contenere i vari
// dati presenti nel file di configurazione.
// derive è una macro procedurale che
// genererà per noi determinate parti di codice.
// Deserialize è fondamentale e proviene dal crate
// serde, su cui toml fa affidamento.
#[derive(Debug, Deserialize)]
struct Config {
    instance: InstanceConfig,
    authentication: AuthenticationConfig,
    text: TextConfig,
}

#[derive(Debug, Deserialize)]
struct InstanceConfig {
    url: String,
    community_id: i32,
}

#[derive(Debug, Deserialize)]
struct AuthenticationConfig {
    session_token: String,
}

#[derive(Debug, Deserialize)]
struct TextConfig {
    // Perché un Option? Perché la pool di titoli nel file
    // di configurazione può esserci o non esserci, è, per
    // l'appunto, opzionale.
    // Potremo facilmente controllare che il valore sia presente
    // in base al suo tipo:
    //   Some(Vec<String>) - un vettore contenente stringhe
    //   None - un'Option vuota
    title_pool: Option<Vec<String>>,
    body_pool: Option<Vec<String>>,
}

fn main() {
    // Specifica la posizione ed il nome del file di configurazione.
    let path = Path::new("./simplecofeebot.toml");
    // Apri il file di configurazione e controlla che l'operazione non dia errore.
    let (config, title, body): (Config, String, String) = match File::open(path) {
        // Il file è stato aperto con successo, quindi usiamo un pattern
        // per estrarre il contenuto del nostro tipo Result<File, Error>.
        Ok(mut file) => {
            // Creiamo una nuova Stringa che verrà utilizzata come buffer per il contenuto
            // del nostro file di configurazione.
            // Deve esser mut perché dobbiamo modificarla.
            let mut doc = String::new();
            // Ed ora tentiamo di trasportare il contenuto del file dentro la stringa di buffer!
            match file.read_to_string(&mut doc) {
                // Non siamo interessati a quello che read_to_string ritorna dentro l'Ok()
                // quindi usiamo _ per indicare che non serve una variabile dove inserirlo.
                Ok(_) => {
                    // Usiamo il crate Rand per creare un generatore di numeri casuali locale.
                    let mut rng = rand::thread_rng();
                    // Finalmente usiamo il crate toml per analizzare il file di configurazione.
                    let config: Config = match toml::from_str(doc.as_str()) {
                        // Il match può ritornare un valore al suo completamento, quindi,
                        // nel caso sia andato tutto bene, ritorniamo il valore contenuto
                        // all'interno del nostro Ok.
                        Ok(s) => s,
                        Err(err) => {
                            // Oh no!
                            // Qualcosa è andato storto e non ci è possibile recuperare
                            // da questo errore. Ci tocca chiudere il programma con un bel
                            // e salutare crash. Cerchiamo almeno di spiegare il perché...
                            panic!(
                                "Errore! Impossibile analizzare il file di configurazione!\n{}",
                                err
                            );
                        }
                    };
                    // Per rendere il titolo un po' meno monotono aggiungiamo un suffisso
                    // estratto a caso fra le stringhe date nell'apposito spazio nel file di
                    // configurazione.
                    // Useremo una funzione chiamata pick_random, definita poco sotto!
                    let title_suffix = config
                        .text
                        .title_pool
                        .as_ref()
                        .map_or(String::new(), |v| pick_random(&mut rng, v));

                    let body_default = "Salve!".to_owned();

                    let mut body = config
                        .text
                        .body_pool
                        .as_ref()
                        .map_or(body_default.clone(), |v| pick_random(&mut rng, v));

                    // Abbiamo fatto in modo che, in caso il nostro utente non
                    // abbia definito body_pool nella configurazione, allora vi sia
                    // la String "Salve!" come body, ma cosa succede nel caso in cui
                    // il nostro utente abbia passato [""] o []?
                    // Dato che abbiamo preso una decisione esecutiva d'avere come
                    // default "Salve!", allora è il caso d'aggiungere
                    // un altro controllo...
                    if body.is_empty() {
                        body = body_default;
                    }

                    // Rimandiamo indietro una bella Tupla d'elementi.. questo
                    // puzza solo a me?
                    // Se si fa affidamento su un dato strutturato, per muoverlo
                    // in giro, forse sarebbe il caso di creare direttamente una
                    // nuova Struct ed esser sicuri di quel che passiamo!
                    (config, generate_title(title_suffix), body)
                }
                Err(err) => {
                    // Hmm.. probabilmente il file non era codificato in UTF-8! Oh no! Anche qui...
                    // niente configurazione, niente funzionalità!
                    panic!(
                        "Errore! Sei sicuro che il file di configurazione sia in UTF-8 valido?\n{}",
                        err
                    );
                }
            }
        }
        // C'è stato un errore durante l'apertura del file!
        Err(err) => {
            // Niente file di configurazione significa che non abbiamo accesso al token JWT..
            // Anche se avessimo dei default per gli altri elementi non è possibile andare oltre,
            // l'unica via è un bel crash!
            panic!(
                "Errore! Impossibile aprire il file in \"{}\":\n{}",
                path.display(),
                err
            )
        }
    };

    // Ora che abbiamo il nostro titolo ed il nostro corpo del messaggio
    // è arrivato il momento di postarli! Ma come fare?
    // A piccoli passi!
    // Sarebbe opportuno controllare che l'url dell'istanza sia
    // almeno formalmente corretto.
    // Perché non fare tutti i controlli subito appena analizzato
    // il file di configurazione, così da non sprecare
    // tempo e computazioni? È un ottima domanda!
    // E la strategia giusta sarebbe di spostare tutto ciò che
    // riguarda la configurazione in un suo modulo a parte,
    // far tutte le validazioni del caso, e solo dopo procedere!
    // ...ma qui siamo bonari, ci fidiamo del nostro utente!
    // Saltiamo direttamente ad usare un nuovo crate per
    // inviare richieste: reqwest!
    let client = reqwest::blocking::Client::new();
    // Cosa succede se, per caso, l'url dell'istanza è malformato, pieno
    // di spazi bianchi o con un bel / alla fine..? E se non inizia con
    // il protocollo?
    let api_endpoint = format!("{}/api/v3/post", config.instance.url);
    // Questi son un sacco di dati da prendere e di cui fidarsi così, senza
    // pensarci..
    // Però siamo avventurosi! Creiamo direttamente il json sulla fiducia.
    // Per farlo utilizziamo una macro che proviene da serde_json.
    // Esistono molte altre vie, ma questa è quella più semplice da
    // gestire in modo sano, se dovessimo mai decidere d'implementare
    // altre casistiche.
    let req = json!({
        "auth": config.authentication.session_token,
        "name": title,
        "community_id": config.instance.community_id,
        "body": body,
    });
    // Ed ora proviamo ad inviare la richiesta!
    match client.post(api_endpoint).json(&req).send() {
        Ok(response) => {
            // Sembra esser tutto riuscito! Mettiamo un bel messaggino con
            // un sacco d'informazioni inutili nella console, giusto per
            // dar un po' di fastidio al nostro amato utente!
            // In più con un unwrap messo così c'è sempre la possibilità
            // d'avere un divertente crash al momento meno opportuno!
            println!("La discussione con il titolo \"{title}\" è stata inviata correttamente.\nRisposta: {}", response.text().unwrap())
            // Ma un momento... Se l'url era sbagliato e abbiam ricevuto
            // indietro un 404, 503 o qualche altro problema che ha impedito al
            // post d'esser ricevuto? Al momento il nostro script direbbe
            // sempre che tutto è andato bene! Ooooops!
            // Forse potremmo controllare response.status() e fare un bel match...
        }
        Err(err) => eprint!(
            "Errore! Non è stato possibile inviare la discussione!\n{}\n",
            err
        ),
    }
}

fn pick_random(trng: &mut ThreadRng, trg: &Vec<String>) -> String {
    // hmm.. cosa succede se viene passato un vettore vuoto...?
    // Meglio controllare! E in Rust anche l'if può direttamente
    // ritornare un valore.
    if trg.is_empty() {
        // È un po' triste e non esattamente il massimo.. Ma una stringa
        // vuota è pur sempre un'opzione!
        // Notare come trasformiamo "" da una &'static str in una String usando
        // to_owned().
        "".to_owned()
    } else {
        // Invece se c'è almeno un elemento allora procediamo all'estrazione!
        // Notare come len() ritorni la lunghezza del vettore, quindi
        // [0, 1, 2] ha una len() di 3, però l'ultimo elemento ha un'id
        // di 2!
        // Un'altra ottimizzazione possibile sarebbe nel caso avessimo
        // un solo elemento... ma.. Ne vale la pena?
        trg.get(trng.gen_range(0..=(trg.len() - 1)))
            .unwrap()
            .to_owned()
    }
}

fn generate_title(suffix: String) -> String {
    // Creiamo un descrittore per il formato della data da inserire nel titolo.
    // Nel caso ci sia qualche errore crashamo direttamente usando expect,
    // perché siamo bravi mettiamo anche un messaggio che cerca di spiegare il
    // motivo più probabile per il nostro crash.. Potrebbe esser utile in futuro, se
    // qualcuno decidesse di render il descrittore configurabile!
    let date_format = format_description::parse("[day]/[month]/[year]").expect(
        "La stringa che stai cercando di usare per formattare la data non sembra corretta!",
    );
    // Cerchiamo d'ottenere la datetime della macchina locale...
    let date = match OffsetDateTime::now_local() {
        Ok(datetime) => datetime.date(),
        Err(_) => {
            // Impossibile ottenere la data locale, con tristezza usiamo quella UTC.
            // Potrebbe capitare che il giorno sia diverso, per colpa dei fusi orari..
            eprintln!("Errore! Impossibile ottenere la data locale: verrà usata quella UTC.");
            OffsetDateTime::now_utc().date()
        }
    }
    .format(&date_format)
    .expect("Non siamo riusciti a formattare la data..?");

    format!("Caffè Italia {} {}", date, suffix)
        .trim()
        .to_owned()
}


Alcune possibili migliorie semplici ed interessanti potrebbero esser:

  • Una gestione migliore degli errori, usando l'operatore '?', ed il crate anyhow.
  • Potremmo anche creare degli errori migliori con thiserror!
  • Abbiamo già il crate time.. Perché non aggiungere dei timestamp ai messaggi nella console?
  • Creare diversi moduli per gestire in modo più generale e specifico (Ah! Sembra un ossimoro ma non lo è!) le varie funzioni!
  • Dopo aver creato la discussione, se ha accesso ai poteri da mod, pinnarla!
  • Magari sanitizzare un po' le stringe provenienti dal file config? Anche solo un trim sarebbe un bel passo avanti! Anche quando l'utente è fidato cercare di coprire gli errori più comuni è sempre una buona idea!
  • Cosa succede se il session_token è scaduto..? Magari si potrebbe direttamente fare il login?
  • Magari trasformarlo per, oltre al file di configurazione, accettare anche dei parametri da linea di comando, usando un crate come Clap!
  • Attualmente lo script posta quando è invocato.. Magari potremmo creare un loop e una configurazione per postare a determinate date/orari? Certo, un cron job quando disponibile è sempre la scelta migliore.. Ma se proprio ci si sta annoiando...!
view more: next ›