d20pfsrd Astrazione e distribuzione di Discord Bot Scraper

Aug 16 2020

Ho scritto un bot discord che ascolta i collegamenti al regolamento d20pfsrd nella chat discord, controlla se sono talenti o magia, quindi raschia la pagina, la formatta e la risputa nella chat come testo formattato. Le pagine che sto controllando sono abbastanza formulate, quindi anche se i selettori cheerio che sto usando sono probabilmente piuttosto fragili, sembra funzionare nella maggior parte dei casi. Tuttavia, i formattatori di testo sono delle brutte bestie (sebbene la logica sia probabilmente unica) e anche le chiamate axios potrebbero richiedere un po 'di pulizia.

Il mio problema è il seguente: sospettavo che un buon 40% del codice potesse essere rifattorizzato dall'esistenza se lo avessi generalizzato correttamente. La mia soluzione era fare qualcosa che potrebbe probabilmente essere descritto come un abuso dell'operatore spread:

async function getPage(msg, url){
  let message = "placeholder";
  await axios.get(url).then( (response) => {
      message = responder(...selectResponder(url), response);
    } 
    ).catch((error) => {
      console.error(error.message);
    });
  sendMessage(message, msg);
  
}

Una settimana dopo mi rendo conto di aver scritto le funzioni in un modo che le fa leggere al contrario? Estetica a parte, ecco come funziona:

function selectResponder(siteUrl){
  if (siteUrl.startsWith("https://www.d20pfsrd.com/feats/")){
      return feats.featsConfig;
    } else if (siteUrl.startsWith("https://www.d20pfsrd.com/magic/")){
      return magic.magicConfig;
  }
}

function responder(parser, formatter, messageFormatter, response){
    const replyData = parser(response.data);
    const formattedData = formatter(replyData);
    return messageFormatter(formattedData);
}

L'idea è che in magic.js e feats.js esista quanta più logica unica possibile. Come posso ripulire questa sezione? Il repository github è qui e mi piacerebbe ricevere feedback sull'intero progetto. Ho fatto la maggior parte di questo perché ho pensato che fosse strano avere un grande blocco if qui e duplicare le chiamate axios:

client.on('message', msg => {
  

  if(validateUrl(msg.content)){
    const siteUrl = encodeURI(msg.content);
    getPage(msg, siteUrl);
  }
  

});

Inoltre ho scritto questo succo su come l'ho distribuito su un Raspberry Pi. Funziona, quindi i suggerimenti su come migliorarlo sarebbero molto apprezzati

A grandi linee questo programma:

  1. Ascolta un messaggio
  2. Convalida il messaggio
  3. Ottiene il contenuto della pagina all'URL del messaggio
  4. Analizza il contenuto della pagina
  5. Riformatta il contenuto della pagina
  6. Converte il contenuto della pagina in un messaggio
  7. Invia il messaggio

Risposte

1 TedBrownlow Aug 16 2020 at 10:57

Ecco come lo farei. Sposta la logica su quali pagine consuma un parser nel codice per detto parser. Anche l'organizzazione dei tuoi file helper in oggetti potrebbe ridurre la complessità in termini di numero di variabili che passi, ma è più una questione di preferenze personali.

class SpecificPageParser {
    match(url) {
        return (
           url.startswith('https://www.d20pfsrd.com/magic/') &&
           !url.endsWith('/magic/')
        );
    }
    format(response) {
        // do your parsing stuff
        const formatted = {...response,'extra':'info'};
        return formatted;
    }
}

const responders = [new SpecificPageParser(),new SomeOtherParser()];

async function getPage(msg, url){
    try {
        const responder = responders.find(responder=>responder.match(url));
        if (!responder) return;
        const response = await axios.get(url);
        const message = responder.format(response);
        sendMessage(message, msg);
    }
    catch(error) {
        console.error(error);
    }
  }
```