본문 바로가기

Node.js

[카톡봇] 카카오톡 API를 이용해 사진 자동 전송하기


var express=require('express');
var app=express();
var cheerio=require('cheerio');
var request=require('request');
var requestP=require('request-promise');
var phantom=require('phantom');
var bodyParser=require('body-parser');
var fs=require('fs');

//to set router
function setRouter(){
//public 내의 파일들 업로드
  app.use(express.static('public'));

  app.get('/', function(req, res){
    res.send('kakaobot Jinsu')
  })
}

//to get a screenshot to send
//in this case, it's naver weather
async function autoWeather(){
  var url = 'https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=1&ie=utf8&query=%EB%82%A0%EC%94%A8';
  var instance=await phantom.create();
  var page=await instance.createPage();
  var status=await page.open(url);
  console.log("page status : "+status);
  var clipRect=await page.evaluate(function () {
    return document.querySelector('[class="table_info weekly _weeklyWeather"]').getBoundingClientRect();
  });

  page.property('clipRect', {
    top:    clipRect.top,
    left:   clipRect.left,
    width:  clipRect.width,
    height: clipRect.height
  });
  page.render('./public/weather.png');

  console.log('autoWeahter finished in funciton')
}


//to get naver searching ranks
//this returns a Promise
async function autoSearch(){
  var url="https://www.naver.com/";
  var rank_str="";

//@@여기를 callback말고 Promise, await으로 구성해보는 게 깔끔할듯?
		await requestP(url, function(error, response, html){
		    if (error) {
          console.log('search request err : '+err);
          throw error;
        }

		    var $ = cheerio.load(html);
		    var cnt=0;

		    $('.ah_item').each(function(){
		    	if(cnt<10){
		    		var str=$(this).text();
					cnt++;
					rank_str+=cnt+" : "+str.substr(4, str.length-6)+"\n";
		    	}
		    })
		    //console.log("autoSearch finished in the function");
		});

		return new Promise((resolve, reject)=>{
      //console.log('rank : '+rank_str)
      resolve(rank_str);
    });
}


setRouter();
autoWeather();
autoSearch();

//to parse application/json
app.use(bodyParser.json());
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));



//the object to be sent as keyboard data
const keyboardContents = {
    type: 'buttons',
    buttons: ["날씨", "네이버 검색 순위", "Bus", "Jinsu--^_^"]
};


//the inital state
app.get('/keyboard', function(req, res){
  res.set({
      'content-type': 'application/json'
  }).send(JSON.stringify(keyboardContents));
  console.log("someone GET /keyboard");
});

//response to clients' msg
app.post('/message',async function (req, res) {
    const _obj = {
        userKey: req.body.userKey,
        type: req.body.type,
        content: req.body.content
    };

    //keyboardContents는 항상 들어감
    var responseContents={
      keyboard:keyboardContents
    };

    //확인용
    //console.log('userType : '+_obj.type)
    console.log('userContents : '+_obj.content)


    //네이버 검색 순위
    if(_obj.content == '날씨')
    {
      var rank=await autoSearch();
      //console.log('autoSearch finished in message')

      //@@message에 keyboard안넣으면 다시 default인 텍스트로 감??
      responseContents.message={
                "photo": {
                  //@@내 컴퓨터에 있는 이미지는 불가능한듯..
                  "url": "http://124.50.93.166:3500/weather.png",
                  "width": 588,
                  "height": 228
                }
      };
    }
    else if(_obj.content == '네이버 검색 순위')
    {
        var rank=await autoSearch();
        //console.log('autoSearch finished in message')

        //@@message에 keyboard안넣으면 다시 default인 텍스트로 감??
        responseContents.message={
                "text": rank
        };
    }


    //추후에 버스 도착정보 넣을 것
    else if(_obj.content =='Bus'){
      responseContents.message={
              "text": '준비 중...ㅎㅎㅎ'
      };
    }

    else if(_obj.content == 'Jinsu--^_^'){
      responseContents.message={
              "text": '진수는 정말.. 멋져...',
              "photo": {
                //@@내 컴퓨터에 있는 이미지는 불가능한듯..
                "url": "http://124.50.93.166:3500/jinsu.png",
                "width": 457,
                "height": 133
              }
      };
    }

    //send response
    res.set({
        'content-type': 'application/json'
    }).send(JSON.stringify(responseContents));

});
app.listen(3500, function() {
  console.log('app is listening to 3500')
});



코드를 좀 더 다듬었다. 공통적인 내용은 묶어서, 함수 정의는 함수정의 끼리,

프로그램 진행 부분은 진행 부분끼리 정리했다

      responseContents.message={
                "photo": {
                  //@@내 컴퓨터에 있는 이미지는 불가능한듯..
                  "url": "http://124.50.93.166:3500/weather.png",
                  "width": 588,
                  "height": 228
                }
      };


수정내용 및 메모
: 카카오톡 봇의 기능에 사진 보내는 기능을 추가했다 - 상당히 쉽다
어려운 것은 웹 크롤링이었다.
사진 보내는 것 자체는 쉽지만 웹 크롤링을 해서 그 사진을 보내는 게 어렵다.
  - request모듈로 사진을 내 로컬에 저장하고,
express모듈을 이용해 그 사진에 대한 라우터를 만들었다.
버스 도착 정보를 추가하려한다.