개발일지/던파 쌀먹봇

[던파 쌀먹봇] 2021-02-16 개발일지 - 오픈빌더 -> 메신저봇 변경 및 카드검색 기능 추가

Emil :) 2021. 8. 19. 17:22
728x90
반응형
이 글은 Notion에서 작성 후 재편집한 포스트입니다.

목차

 

개요


정말 오랜만에 포스팅한다... 그동안 회사 리뉴얼 프로젝트가 너무 많았는데, 짬짬이 개발은 했지만 블로그에 포스팅 하진 않았고, 노션으로 따로 적어놨다.

아무튼 프로젝트 끝났으니 다시 조금씩 포스팅 한다! 화이팅..
이전까지 작업했던 내용과 완전히 달라졌다. 일단 그전까지는 카카오톡 채널을 이용한 오픈빌더로 만들려고했는데..
편의성 측면에서 아무래도 차이가 나더라.

예를 들어, 검색을 하고 싶은데 단톡에서 친구들이나 길드원끼리 얘기하다 바로 검색하는게 편하지, 채팅방 나가서 채널(친구) 찾고 검색하면 귀찮지 않은가..

그래서 단톡에서 바로 친구처럼 사용할 수 있는 '채팅 자동응답 봇(초록봇)' 을 사용했다.
해당 봇의 자세한 내용은 아래 포스팅 참조.

https://dulki.tistory.com/56?category=730419 

 

카카오톡 봇 만들기 - 1 - 간단 설명

이 시리즈의 목적은 특정 채팅에 반응해서 대답하는 봇을 카카오톡 단톡방에 추가하는것이다 모든 기본 정보는 앱 제작자 다크토네이도 블로그에서 얻었으니 더 자세한 정보를 원하는 경우 꼭

dulki.tistory.com

jsoup 모듈이 포함된 봇이기에, ajax나 selenium 같은 모듈은 사용을 못한다.. 정 하고싶으면 24시간 돌아가는 로컬 서버를 만들어놓고 집에 돌려놔야 되는데, 그렇게까지 돌리기엔 봇의 규모가 크지 않아서 그냥 안쓰는 핸드폰 하나로 돌리려고 한다.

어쩌다보니 길드원들이 요청하는 기능이 생겨서 던파랑은 상관없는 기능들이 이것저것 들어갔는데,
사실 뭔가 크롤링 결과를 파싱하는게 전부라 생~각만큼 많은 공부는 되지 않았던 것 같다.
아, 카카오 링크를 통해서 응답 form을 바꿀 수 있는데, 이거는 공부가 될 것 같다. 추후 수정 예정.

아무튼, 노션에 작성해둔 개발일지 먼저 끝난 다음, 슥삭 재정비해서 쭉 개발일지 재개해보도록 하자.

이번 작업에선 아이템 검색, 시세검색 기능을 추가하고, 모듈화를 진행했다. (너무 난잡했다.)

스킬칭호를 검색하고 싶을 때, 원하는 스킬과 스킬레벨 까지 검색가능하게 했다.
이건 좀 독자적인 기능이다. 이런 기능 제공해주는 사이트나 공식 API는 없더라.
마찬가지로 카드도 업그레이드 수치까지 알 수 있도록 해줬다.

코드 GIT 주소


https://github.com/kkkapuq/ssalbot

 

GitHub - kkkapuq/ssalbot: 던파 쌀먹봇

던파 쌀먹봇. Contribute to kkkapuq/ssalbot development by creating an account on GitHub.

github.com

진행 과정


1. 아이템 검색


function findItem(itemName, replier) {
  var url = 'https://api.neople.co.kr/df/auction?itemName=' + itemName + '&sort=unitPrice:asc&apikey=' + APIkey;
  var data = org.jsoup.Jsoup.connect(url).ignoreContentType(true).get().text();
  data = JSON.parse(data);

  if (data["rows"].length == 0) {
      replier.reply("존재하지 않는 아이템이거나 매물이 없습니다." + '\n' +
                    "존재하는 아이템이라면 ?시세/아이템명 을 입력해주세요.");
  } else {
    replier.reply(
      "아이템 명 : " + data["rows"][0]["itemName"] + '\n' +
      "최저가 : " + data["rows"][0]["unitPrice"] + '\n' +
      "평균가 : " + data["rows"][0]["averagePrice"] + '\n')
  }
}

function soldItem(itemName, replier) {
  url = 'https://api.neople.co.kr/df/auction-sold?itemName=' + itemName + '&apikey=' + APIkey;
  data = org.jsoup.Jsoup.connect(url).ignoreContentType(true).get().text();
  data = JSON.parse(data);

  if (data["rows"].length == 0) {
    replier.reply("그런건 없음 ㅋㅋ");
  } else {
    replier.reply(
      "거래일시 : " + data["rows"][0]["soldDate"] + '\n' +
      "아이템 명 : " + data["rows"][0]["itemName"] + '\n' +
      "개당 가격 : " + data["rows"][0]["unitPrice"] + '\n' +
      "총합 가격 : " + data["rows"][0]["price"] + '\n')
  }
}


function response(room, msg, sender, isGroupChat, replier, ImageDB, packageName) {
  var replyMsg = '';

  replier.markAsRead()

  //명령어 리스트
  if (msg.includes("?명령어")) {
    try {
      replier.reply(
        "1. 경매장 아이템 실시간 검색 : ?템/아이템명" + '\n' +
        "2. 시세 검색 : ?시세/아이템명" + '\n' +
        "3. 캐릭터 검색(미구현) : ?캐릭터/캐릭명" + '\n' +
        "4. 타임라인 검색(미구현) : ?타임라인/캐릭명" + '\n' +
        "5. 랜덤 채널추천 : ?채널 " + '\n')
    }
    catch (e) {
      replier.reply("에러 발생")
    }
  }

  //아이템 검색
  if (msg.includes("?템/")) {
    try {
      var itemName = msg.split("/")[1];
      itemName = encodeURI(itemName);

      findItem(itemName, replier);
    }
    catch (e) {
      replier.reply("에러 발생");
    }
  }

  //시세 검색
  if (msg.includes("?시세/")) {
    try {
      var itemName = msg.split("/")[1];
      itemName = encodeURI(itemName);

      soldItem(itemName, replier);
    }
    catch (e) {
      replier.reply("에러 발생");
    }
  }
}

현재까지 진행된 코드는 다음과 같다.

아이템이 없다면 시세 검색으로 유도해주는 안내 문구를 추가해줬다.

추가적인 기능으로 '카드', '칭호' 이런식으로 매개변수를 주면
본인이 원하는 업글여부, 칭호마부 등을 검색할 수 있도록 짜주자.
왜냐하면 카드의 경우 업글 여부를 궁금해 하는 사람들이 많기 때문이다.
칭호의 경우도 본인이 원하는 칭호만 사고싶기 때문.

그러기 위해선, api를 호출할 때 분기처리를 해줘야 한다.

설계는 다음 단계에서 후술한다.

2. 카드 검색


먼저, ?템/ 단계에서 분기처리를 해주자. 카드, 칭호에 따라 소스가 바뀌도록.

  1. 입력 형식은 ?템/카드/카드명/업글여부로 가져온다. 각각 변수는 카드 - flag, 카드명 - itemName, 업글단계 - cardUpgradeValue으로 하자.
  2. api를 호출하는데, api를 호출할 때 얘만 찝어서 호출은 불가능하다.. 따라서, 호출해주는 row수가 400개가 최대이므로, 400개까지 불러온 다음, 그 안에서 array에 넣어주기 전에 upgrade 여부가 사용자가 지정한 index만 추려낸다.
  3. 그 후, 해당 array의 0번째 인덱스를 사용자에게 보내주면 된다. 그게 최저가이기 때문. 복수의 경우 사용자가 지정한 row수 만큼 for문을 돌아 array에 넣어주고, 그 array 내용을 출력해주도록 하자.
if (cardUpgradeValue != 999) {
    var cardArray = new Array();
    url = 'https://api.neople.co.kr/df/auction?itemName=' + itemName + '&wordType=front&limit=400&sort=unitPrice:asc&apikey=' + APIkey;
    var data = org.jsoup.Jsoup.connect(url).ignoreContentType(true).get().text();
    data = JSON.parse(data)

    if (data["rows"].length == 0) {
      replier.reply(cannotFindItemMsg);
    } else {
      for (var i = 0; i < data["rows"].length; i++) {
        var obj = data["rows"][i];
        if (obj.hasOwnProperty('upgrade') && obj["upgrade"] == cardUpgradeValue) {
          cardArray.push(obj);
        }
      }

      if (cardArray.length == 0) {
        replier.reply(cannotFindOptionItemMsg);
        return;
      }

      replier.reply(
        "아이템 명 : " + cardArray[0]["itemName"] + '\n' +
        "개수 : " + cardArray[0]["count"] + '\n' +
        "총 가격 : " + cardArray[0]["currentPrice"] + '\n' +
        "개당 가격(최저가) : " + cardArray[0]["unitPrice"] + '\n' +
        "평균가 : " + cardArray[0]["averagePrice"] + '\n' +
        "업그레이드 수치 : " + cardArray[0]["upgrade"]);
    }
  }

칭호 검색 기능은 다음 포스팅에서!

 

오늘의 결과


구독 및 하트는 정보 포스팅 제작에 큰 힘이됩니다♡

728x90
반응형