Abstração e implantação do Discord Bot Scraper d20pfsrd
Eu escrevi um bot de discórdia que escuta links para o livro de regras d20pfsrd no chat de discórdia, verifica se são talentos ou magia e, em seguida, raspa a página, formata-a e a coloca de volta no chat como texto formatado. As páginas que estou verificando são estereotipadas o suficiente, portanto, embora os seletores cheerio que estou usando sejam provavelmente bastante frágeis, parece funcionar na maioria dos casos. Os formatadores de texto são bestas feias (embora a lógica seja provavelmente única), e as chamadas axios também precisam de alguma limpeza.
Meu problema é o seguinte: suspeitei que uns bons 40% do código podem ser refatorados se eu generalizá-lo adequadamente. Minha solução foi fazer algo que provavelmente poderia ser descrito como um abuso do operador de 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);
}
Uma semana depois, agora estou percebendo que escrevi as funções de uma maneira que as faz ler de trás para frente? Deixando de lado a estética, acaba ficando assim:
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);
}
A ideia é que o máximo possível de lógica única que eu possa separar existe em magic.js e feats.js. Como posso limpar esta seção? O repositório do github está aqui e eu adoraria receber um feedback sobre todo o projeto. Fiz a maior parte disso porque achei estranho ter um grande bloco if aqui e duplicar as chamadas axios:
client.on('message', msg => {
if(validateUrl(msg.content)){
const siteUrl = encodeURI(msg.content);
getPage(msg, siteUrl);
}
});
Também escrevi esta essência sobre como o implantei em um raspberry pi. Isso funciona, então sugestões sobre como melhorá-lo seriam muito apreciadas
Em linhas gerais, este programa:
- Escuta uma mensagem
- Valida a mensagem
- Obtém o conteúdo da página no URL da mensagem
- Analisa o conteúdo da página
- Reformata o conteúdo da página
- Converte o conteúdo da página em uma mensagem
- Envia a mensagem
Respostas
Aqui está como eu faria isso. Mova a lógica sobre quais páginas um analisador consome no código do referido analisador. Além disso, organizar seus arquivos auxiliares em objetos pode reduzir a complexidade em termos do número de variáveis que você passa, mas isso é mais uma questão de preferência pessoal.
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);
}
}
```