• 디스코드 웹훅으로 티스토리 알림 봇 만들기

    2022. 8. 13.

    by. 카유.

    1. 티스토리 RSS를 Node.js에서 Json으로 가져오기

    2. 디스코드 웹훅 Node.js로 연동하기

    3. 디스코드 웹훅 AWS Lambda로 자동화

     

    본문을 보기 전에 위 글들을 참고해주세요

     

     

    Node.js 모듈 설치

    1. HTTP 비동기 요청

    npm install axios

    2. XML을 Json으로 변환

    npm install xml2js

     

     

    코드로 구현

    먼저 구현하기에 앞서 변수를 저장하고
    다시 실행될 때에도 유지되는지 확인해야하는데요

    다음과 같이 작성하고 업로드 해보겠습니다.

     

    const axios = require("axios");
    
    const webhookURL = "웹훅 URL";
    
    let testNum = 0;
    
    exports.handler = async (event) => {
        try {
            await axios.post(webhookURL, {
                "content": `${testNum++} 테스트`
            });
        }
        catch (err) {
            console.error(err);
        }
    
        const response = {
            statusCode: 200,
            body: JSON.stringify('Hello from Lambda!'),
        };
        return response;
    }

    변수를 핸들러 밖에 선언하고
    웹훅으로 보내면서 변수를 증가시키게 했고

     

    의도한대로 변수가 증가하며 메시지를 보내게됩니다.

    이 변수는 코드를 바꾸거나
    다시 업로드 할때마다 초기화됩니다.

    이걸 이용해서 rss를 읽고 저장한 후
    다시 읽었을때 비교해서
    새로 올라온 글인지 확인할 수 있습니다.

     

    const axios = require("axios").default;
    const xml2js = require("xml2js");
    
    const webhookURLs = [
        "웹훅 URL"
    ];
    
    const avatarURL = "프로필 이미지 URL";
    
    /**
     * 티스토리 RSS 가져오기
     * @param {String} rssURL 
     * @returns {{
     * title: String,
     * items: Array.<{
     *  title: String[],
     *  link: String[],
     *  description: String[],
     *  category: String[],
     *  author: String[],
     *  coments: String[],
     *  pubDate: String[]
     * }>}} Json
     */
    async function getTistoryRSS(rssURL) {
        const rssXML = (await axios.get(rssURL)).data;
        const jsonData = await xml2js.parseStringPromise(rssXML);
        const rssObject = jsonData.rss.channel[0];
    
        return {
            "title": rssObject.title[0],
            "items": rssObject.item
        };
    }
    
    let lastPubDate = null;
    
    exports.handler = async (event) => {
        try {
            // 티스토리 RSS를 Json으로 가져온다.
            const rss = await getTistoryRSS("https://answn.tistory.com/rss");
    
            // 초기 실행시 마지막으로 쓰인 글의 시간을 저장하고 끝낸다.
            if (lastPubDate == null) {
                lastPubDate = new Date(rss.items[0].pubDate[0]);
                return;
            }
    
            const embeds = [];
            rss.items.reverse().forEach((item) => {
                const currentPubDate = new Date(item.pubDate[0]);
    
                // 예전에 쓰여진 글이면 아무것도 하지않고 다음 글로 넘어간다.
                if (lastPubDate >= currentPubDate) return;
                lastPubDate = currentPubDate;
    
                // 새로 쓰여진 글이면 embed 객체로 배열에 넣고
                const category = (item.category == undefined) ? "" : item.category[0];
                embeds.push({
                    "title": item.title[0],
                    "url": item.link[0],
                    "description": category,
                    "color": 3447003
                });
            });
    
            // 배열을 한번에 웹훅으로 보낸다.
            if (embeds.length > 0) {
                for await (const webhook of webhookURLs) {
                    await axios.post(webhook, {
                        "embeds": embeds,
                        "username": "[알림] 카유 티스토리 새 글 업로드",
                        "avatar_url": avatarURL
                    });
                }
            }
        }
        catch (err) {
            console.error(err);
        }
    
        const response = {
            statusCode: 200,
            body: JSON.stringify('Hello from Lambda!'),
        };
        return response;
    }

    가장 최근글의 시간을 저장해서
    다시 읽을때 그 시간보다 최근이라면
    새로 저장하고, 웹훅으로 보내게 했습니다.

     

    며칠 전에 만들어서 업로드하고
    티스토리 글을 쓰며 관찰했고 잘 작동됩니다.

     

    제가 사용중인 봇은 깃허브에 올려두었습니다.

    댓글