d20pfsrd Discord Bot Scraper Tóm tắt và Triển khai

Aug 16 2020

Tôi đã viết một bot bất hòa lắng nghe các liên kết đến sổ quy tắc d20pfsrd trong trò chuyện bất hòa, kiểm tra xem chúng là kỳ công hay phép thuật, sau đó quét trang, định dạng nó và đưa nó trở lại trò chuyện dưới dạng văn bản được định dạng. Các trang tôi đang kiểm tra có đủ công thức, vì vậy mặc dù các bộ chọn cheerio tôi đang sử dụng có thể khá giòn, nhưng nó dường như hoạt động trong hầu hết các trường hợp. Mặc dù vậy, các trình định dạng văn bản là một số con quái vật xấu xí (mặc dù logic có lẽ là duy nhất) và các lệnh gọi axios cũng có thể sử dụng một số thao tác dọn dẹp.

Vấn đề của tôi như sau: Tôi nghi ngờ rằng 40% mã tốt có thể được cấu trúc lại không tồn tại nếu tôi khái quát hóa nó đúng cách. Giải pháp của tôi là làm điều gì đó có thể được mô tả là lạm dụng toán tử 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);
  
}

Một tuần sau, tôi nhận ra rằng tôi đã viết các hàm theo cách khiến chúng đọc ngược? Thẩm mỹ sang một bên, đây là cách nó kết thúc:

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);
}

Ý tưởng là càng nhiều logic duy nhất tôi có thể tách ra tồn tại trong magic.js và feats.js càng tốt. Làm cách nào để làm sạch phần này? Github repo ở đây và tôi rất thích và phản hồi về toàn bộ dự án. Tôi đã làm hầu hết điều đó bởi vì tôi nghĩ thật kỳ lạ khi có một khối if lớn ở đây và sao chép các lệnh gọi axios:

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

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

});

Ngoài ra, tôi đã viết lên ý chính này về cách tôi triển khai nó cho một pi raspberry. Điều đó hoạt động, vì vậy các đề xuất về cách cải thiện nó sẽ được đánh giá cao

Nói chung chương trình này:

  1. Nghe tin nhắn
  2. Xác thực tin nhắn
  3. Lấy nội dung trang tại url tin nhắn
  4. Phân tích nội dung trang
  5. Định dạng lại nội dung trang
  6. Chuyển nội dung trang thành tin nhắn
  7. Gửi tin nhắn

Trả lời

1 TedBrownlow Aug 16 2020 at 10:57

Đây là cách tôi sẽ làm điều đó. Di chuyển logic về các trang mà trình phân tích cú pháp sử dụng vào mã cho trình phân tích cú pháp đó. Ngoài ra, việc tổ chức các tệp trợ giúp của bạn thành các đối tượng có thể làm giảm độ phức tạp về số lượng biến mà bạn chuyển xung quanh nhưng đó là vấn đề sở thích cá nhân nhiều hơn.

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);
    }
  }
```