node.js 로 트위터봇을 만들어보자.

일단 node.js 를 알아야하고(이전에 작성한 Node.js 초간단 3분 훝기 글을 참조해도 된다.), 트위터 api 에 대해서 알아야한다.


트위터 api 는 3종류의 api 가 있다. (참조 : https://dev.twitter.com/start )

  • Search API
  • REST API
  • Streaming API

이중 Search API 만 별도의 인증이 필요하지 않으며, 나머지 2개의 API 에서는 oAuth (Open ID Authentication) 을 필요로 한다.


예제로 만들 트위터봇은 계정 1개를 사용하며, 멘션이 날라올 경우 멘션을 날리는 사람에게 리플라이를 하는 기능을 구현한다. 따라서, 다음 2가지 api 가 필요하다

  • 멘션 조회
  • 메세지 작성

이 2개의 API 는 REST API 에서 제공된다. 따라서 2개의 API 모두 oAuth 인증을 필요로 한다.


oAuth 인증을 위해서는 다음 값이 필요하다.


  • Consumer Key
  • Consumer Secret
  • Access Token
  • Access Token Secret

oAuth 에 관한 자세한 정보는 http://dev.naver.com/openapi/apis/oauth/guide 를 참조한다.


1. 트위터 계정 설정하기


access token 을 발급받기 위해서 https://dev.twitter.com/apps 로 들어가 트위터 어플리케이션을 생성한다.


어플리케이션을 생성하면, oAuth 인증 Access Level 이 Read-only 로 되어있다. 트윗을 날리기 위해선, Write Level 이 필요하다. 



settings 메뉴에 들어가서 Application Type 을 'Read and Write' 로 변경한다.



마지막으로 Detail 메뉴로 다시 돌아온 후, 최하단에서 Access Token 을 생성한다.


2. 모듈 설치


프로젝트를 생성한다. 

대몬형태로 띄울 프로그램을 만들기만 하면 되지만, 여기서는 웹서버를 실행시켜놓는 형태로 하겠다. 

expresss [프로젝트명] -s 를 실행한다.



express 모듈을 로컬에 설치한다.

npm install express 를 실행한다.



oAuth 인증을 할 oAuth 모듈을 설치한다.

npm install oauth 를  실행한다.



3. 소스 작성


본격적으로 소스를 작성해보자.


oAuth 객체를 생성한다.


// app.js

var OAuth= require('oauth');

var tokens = {

twitterAccessToken : '579900828-erXEQXRlg0Kx2l9S4uR9OcNT7npsjtwxxxxx',

twitterAccessTokenSecret : 'zQu3VLFp8P6dj1j9W7wmnZ3PS9HVTlhpxtxxxxx',

twitterConsumerKey : 'zASiWXu1F9HqnAb15xxxxx',

twitterConsumerSecret : '5labh3Y1s7iNfyLeraA7UB7vtGme5O5I8qxxxxxx'

};

oAuth= new OAuth.OAuth(

  "http://twitter.com/oauth/request_token",

  "http://twitter.com/oauth/access_token", 

  tokens.twitterConsumerKey, tokens.twitterConsumerSecret, 

  "1.0A", null, "HMAC-SHA1"

);


oAuth 객체를 이용하여 twitter api 를 다루는 twitter.js 를 만들어보자. 해당 위치는 프로젝트 최상위에 둔다. (app.js 와 같은 위치)


사용된 트위터 API 는 다음과 같다.

  • 멘션 조회 : https://dev.twitter.com/docs/api/1/get/statuses/mentions
  • 메세지 작성 : https://dev.twitter.com/docs/api/1/post/statuses/update

// twitter.js


var qs = require('querystring');

/**

 * Twitter Service

 * @param oAuth oAuth

 * @param tokens {twitterAccessToken:'your twitter Access Token', twitterAccessTokenSecret:'your twitter Access Token Secret'}

 * @author slothink. (slothink at gmail.com)

 */

exports.Twitter = function(oAuth, tokens) {

this._oAuth = oAuth;

this._tokens = tokens;

}

var defaultCallbackFunc = function(error, data, cbFunc) {

    if(error) console.log(require('sys').inspect(error))

    else {

    if(typeof cbFunc == "function") {

    console.log(data);

    cbFunc(JSON.parse(data));

    }else {

    console.log(data)

    }

    }

};

exports.Twitter.prototype.tweet = function(message, cbFunc, option) {

var param = {"status":encodeURIComponent(message)};

var param = {"status":message};

for(var key in option) {

param[key] = option[key];

}

this._oAuth.post(

  "http://api.twitter.com/1/statuses/update.json",

this._tokens.twitterAccessToken, this._tokens.twitterAccessTokenSecret,

param, function(error, data) {

defaultCallbackFunc(error, data, cbFunc);

});

}

exports.Twitter.prototype.getMentions = function(cbFunc, params) {

var url = "https://api.twitter.com/1/statuses/mentions.json?" + qs.stringify(params);

console.log(url);

this._oAuth.get(

  url, 

this._tokens.twitterAccessToken, this._tokens.twitterAccessTokenSecret,

function(error, data) {

defaultCallbackFunc(error, data, cbFunc);

}

);

}


다음은 twitter api 를 이용해 트윗봇을 구현한 기능이다.


// twitterbot.js


var fs = require('fs'), Twitter = require('./twitter');

exports.TwitterBot = function(tokens) {

this._twitter = new Twitter.Twitter(oAuth, {twitterAccessToken:tokens.twitterAccessToken, twitterAccessTokenSecret:tokens.twitterAccessTokenSecret});

this._tokens = tokens;

this._messages = [

"어쩌라구",

"자라",

"-_-",

"ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ",

"내가 네 친구냐?",

"나 남자거든",

"현장씨는 소고기를 좋아합니다",

"잇힝=ㅅ=*",

"바보!!",

"아잉~ >_<*",

"허얼...................",

"나랑 데이트할래?",

"누구세요?",

"흥",

"영화 볼래? 뭐가 좋을까?",

"나야",

"별루다",

"잘래",

"연락처 좀 줄래?",

"보고싶다",

"헤헤헤헤"

];

this._lastId = null;

this._work = 0;

}

exports.TwitterBot.prototype.botMessage = function(text) {

var mul = Math.floor(Math.random() * 100000) + 1

var message = this._messages[(this._work * mul)  % this._messages.length];

this._work++;

return message;

}

exports.TwitterBot.prototype.commit = function() {

fs.writeFile('./work.txt', this._lastId, 'utf-8', function(err) {

if(err) {

throw err;

}

});

}

exports.TwitterBot.prototype.waitAndReply = function() {

console.log("wait and reply:" + this._work);

var my = this;

var params = {};

if(this._lastId != null) {

params.since_id = this._lastId;

console.log(params);

}

this._twitter.getMentions(function(data) {

for(var key in data) {

var tweet = data[key];

console.log("["+ tweet.id_str+"] " + tweet.user.name + " (@"+ tweet.user.screen_name+") say : ");

console.log(tweet.text);

if(my._lastId == null || my._lastId != tweet.id_str) {

my._lastId = tweet.id_str;

my.commit();

}

var message = '@'+tweet.user.screen_name +' '+my.botMessage(tweet.text);

my._twitter.tweet(message, function(data) {

my._lastId = data.id_str;

my.commit();

}, {in_reply_to_status_id:tweet.id_str,});

}

}, params);

}


work.txt 파일은 마지막으로 처리한 메세지 id 이다. 이것을 이용함으로써, 한번 메세지 날린 트윗에 대해 중복으로 날라가는 것을 방지한다.


app.js 에 work.txt 파일을 처리한 후, 주기적으로 트위터 봇을 호출하는 로직을 삽입하면 완료다.


// app.js


var fs = require('fs'), TwitterBot = require('./twitterbot');

fs.readFile('./work.txt', encoding='utf-8', function(err, data) {

if(err) {

fs.writeFile('./work.txt', encoding='utf-8', function(err, data) {

bot

});

data = null;

}

var bot = new TwitterBot.TwitterBot(tokens);

bot._lastId = data;

console.log('start at id:'+bot._lastId);

setInterval(function() {

bot.waitAndReply();

}, 1000 * 30);

});


이제 실행해보자.



4. 여자친구 사귀기



잘 된다.. 이쁜 여자친구 사귀십시오..ㅋㅋ


저작자 표시 비영리 변경 금지
신고
  1. deathquin 2012.12.22 22:52 신고

    소스를 보면서 연습중입니다..
    근데..제가 실행을 하면은 값이 안넘어가네요..
    콘솔에는
    wait and reply
    https://api.....?since_id=.....
    []
    이렇게만 계속 반복적으로뜨는데..
    무엇이문제인가요!?조언좀 부탁드립니다
    key와 이런거는 제껄로 다 바꿨습니다!
    혹시 전체소스를 보내주실수 있으시면은
    deathquin@dreamwiz.com으로좀 부탁드리겠습니다.
    소스를 보면서 연구해보고싶네요!

    • BlogIcon slothink 편현장 2013.01.23 10:00 신고

      답변이 늦어서 죄송합니다. 이 봇의 특징은 계속 대기하다가 해당 계정으로 멘션이 날라 올 때에 다시 멘션으로 반응합니다. 제 생각에 잘 만드셨을거 같은데요, 한번 멘션 날려보세요. 그리고 메일로 소스 보내드렸습니다. :)

  2. 제갈식 2013.05.30 18:26 신고

    내용이 좋아 좀 퍼가겠습니다.

    좋은 팁입니다. 감사합니다.

    http://cafe.naver.com/iphonediy

+ Recent posts