Giter Site home page Giter Site logo

chatterbox's Introduction

Chatterbox

license pypi pyversions travis appveyor codecov


Chatterbox카카오톡 플러스친구 자동응답 API를 활용하여 챗봇을 만들 때 사용되는 파이썬 라이브러리입니다.

Table of Contents

📝 Installation

$ pip install chatterbox.py

🚀 Example

더 다양한 예제는 examples를 참고해주세요.

from flask import Flask, request, jsonify
from chatterbox import Chatter
from chatterbox.response import Text, Keyboard, MessageButton


app = Flask(__name__)
chatter = Chatter()


@chatter.base(name='홈')
def home_keyboard():
    home_buttons = ['자기소개', '사이트로 이동하기']
    return Keyboard(home_buttons)


@chatter.rule(action='자기소개', src='홈', dest='홈')
def intro(data):
    message = 'chatterbox를 통해 더 쉽게 카카오톡 봇을 만들 수 있습니다!'
    return Text(message) + chatter.home()


@chatter.rule(action='사이트로 이동하기', src='홈', dest='홈')
def web(data):
    text = Text('자세한 정보를 보고싶으면 사이트로 이동해주세요!')
    msg_button = MessageButton(label='이동하기',
                               url='https://github.com/jungwinter/chatterbox')
    keyboard = chatter.home()
    return text + msg_button + keyboard


@app.route('/keyboard', methods=['GET'])
def keyboard():
    return jsonify(chatter.home())


@app.route('/message', methods=['POST'])
def message():
    return jsonify(chatter.route(request.json))


if __name__ == '__main__':
    app.run(debug=True)

💎 Usage

Chatter

FSM(finite-state machine)을 사용해 유저들의 state를 내부에 저장하고, 요청에 맞는 response를 반환합니다.

Chatter.route(data)

카카오톡 자동응답 api 명세에 맞는 json 데이터를 인자로 받습니다. user_key로 가져온 state와 content값을 action으로 적절한 rule을 찾아 등록된 함수를 실행한 후 api 명세에 맞는 response를 반환합니다. rule에 관해선 아래에 서술되어 있습니다.

예제
@app.route('/message', methods=['POST'])
def message():
    response = chatter.route(request.json)
    return jsonify(response)

input 데이터로 다음과 같은 형식의 dict 객체를 인자로 받습니다.

{
  "user_key": "encryptedUserKey",
  "type": "text",
  "content": "자기소개"
}

output 데이터로 다음과 같은 형식의 Response 객체(dict로 동작함)를 반환합니다.

{
  "message": {
    "text": "안녕하세요! 무엇을 도와드릴까요?"
  },
  "keyboard": {
    "buttons": [
      "오늘의 날씨",
      "취소"
    ],
    "type": "buttons"
  }
}

Response

chatterbox.response에서 카카오톡 response object 명세를 만족하는 클래스를 가져올 수 있습니다.

Text(text)

다음과 같은 dict like 객체를 반환합니다. 멤버 변수로 text, message를 갖습니다.

Text(text='안녕!')
{
  "message": {
    "text": "안녕!"
  }
}

Photo(url, width, height)

다음과 같은 dict like 객체를 반환합니다. 멤버 변수로 url, width, height, message를 갖습니다.

Photo(url='https://image/url.png',
      width=500,
      height=400)
{
  "message": {
    "photo": {
      "url": "https://image/url.png",
      "width": 500,
      "height": 400
    }
  }
}

MessageButton(label, url)

다음과 같은 dict like 객체를 반환합니다. 멤버 변수로 label, url, message를 갖습니다.

MessageButton(label='이동하기',
              url='https://github.com/jungwinter/chatterbox')
{
  "message": {
    "message_button": {
      "label": "이동하기",
      "url": "https://github.com/jungwinter/chatterbox"
    }
  }
}

Keyboard(buttons, type)

자세한 명세는 Keyboard object 문서에서 확인할 수 있습니다. 멤버 변수로 type, buttons, keyboard를 갖습니다.

주관식 입력
Keyboard(type='text')
{
  "keyboard": {
    "type": "text"
  }
}
버튼 입력
Keyboard(['버튼1', '버튼2'])  # type='buttons'는 생략할 수 있음
{
  "keyboard": {
    "buttons": [
      "버튼1",
      "버튼2"
    ],
    "type": "buttons"
  }
}

조합

def intro():
    text = Text('안녕!')
    photo = Photo('https://image/url.png', 500, 400)
    keyboard = Keyboard(['날씨', '시간'])
    return text + photo + keyboard

위 코드는 아래와 같은 dict 객체를 반환합니다.

{
  "message": {
    "text": "안녕!",
    "photo": {
        "url": "https://image/url.png",
        "width": 500,
        "height": 400
    }
  },
  "keyboard": {
    "buttons": [
      "날씨",
      "시간"
    ],
    "type": "buttons"
  }
}
관계
Response
├── Message
│   ├── Text
│   ├── Photo
│   └── MessageButton
└── Keyboard
    ├── ButtonType
    └── TextType

Message + Message = Message
Message + Keyboard = Response
Response + Message = Response

Base

Chatter.add_base(name, func)

name으로 유저가 시작할 state 이름을 지정할 수 있습니다.

func은 인자가 없어야하며 Keyboard를 반환해야합니다.

예제
def func():
    return Keyboard(['버튼1', '버튼2'])
chatter.add_base(name='홈', func=func)

@Chatter.base(name)

Chatter.add_base()의 wrapper입니다. 데코레이터로 사용할 수 있습니다.

예제
@chatter.base(name='홈')
def func():
    return Keyboard(['버튼1', '버튼2'])

Chatter.home()

Chatter.add_base()를 통해 등록된 함수 func을 실행해 Keyboard를 반환합니다.

예제
>>> chatter.home()
{
  "keyboard": {
    "buttons": [
      "버튼1",
      "버튼2"
    ],
    "type": "buttons"
  }
}

Rule

Chatter.add_rule(action, src, dest, func)

유저의 현재 state가 src이고 input으로 받은 데이터에서 content가 action일 때, func 함수를 실행하고 유저의 state를 dest로 변경합니다. state를 활용하여 1 depth 이상의 자동응답 시나리오를 구성할 수 있습니다.

func 함수는 반드시 data를 인자로 받아야하며 Response를 반환해야합니다.

예제
def intro(data):
    message = 'chatterbox를 통해 더 쉽게 카카오톡 봇을 만들 수 있습니다!'
    return Text(message) + chatter.home()

chatter.add_rule(action='자기소개', src='홈', dest='홈', func=intro)

@Chatter.rule(action, src, dest)

Chatter.add_rule()의 wrapper입니다. 데코레이터로 사용할 수 있습니다.

예제
@chatter.rule(action='자기소개', src='홈', dest='홈')
def intro(data):
    message = 'chatterbox를 통해 더 쉽게 카카오톡 봇을 만들 수 있습니다!'
    return Text(message) + chatter.home()

주관식 답변 처리하기

Keyboard(type='text')를 반환해 유저의 주관식 답변을 받는 경우 action='*'을 사용해 처리할 수 있습니다. 자세한 방법은 examples/flask_advance.py를 참고해주세요.

fallback 처리하기

src='*'를 사용해 유저가 어떤 state에 있더라도 특정 dest로 이동시킬 수 있습니다.

예제
@chatter.rule(action='취소', src='*', dest='홈')
def cancel(data):
    message = '취소하셨습니다.'
    return Text(message) + chatter.home()

🙏 Contribution

CONTRIBUTING.md을 참고해주세요.

🔗 Related projects

chatterbox's People

Contributors

mooncinnamon avatar winterjung avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chatterbox's Issues

Bug: python2.7 + mac os 에서 chatter.py 구문 오류

  • OS: mac os sierra
  • Python 버전: 2.7
  • Chatterbox 버전: chatterbox.py-0.2.1

flask 예제를 실행하니 File "/Users/round/PycharmProjects/dkitBot/venv/lib/python2.7/site-packages/chatterbox/chatter.py", line 10
memory: str = 'dict',
^
SyntaxError: invalid syntax

이라고 발생이 됩니다.

Bug: 카카오톡 플러스친구에서 keyboard 테스트 실패

📝 Description

카카오톡 플러스친구 관리자페이지에서 제공하는 자동응답 API 테스트로 동작을 테스트할 경우 keyboard 테스트가 실패함

Keyboard(['버튼1', '버튼2'])

Keyboard 객체는 다음과 동일한데

{
  "keyboard": {
    "buttons": [
      "버튼1",
      "버튼2"
    ],
    "type": "buttons"
  }
}

/keyboard 에서 반환해야하는 json 형식은 아래와 같아야 하기에 단순히 json.dumps(chatter.home())
을 하면 'keyboard' key까지 포함되기 때문에 형식과 맞지 않게된다.

{
    "buttons": [
        "버튼1",
        "버튼2"
    ],
    "type": "buttons"
}

Bug: chatterbox 앱을 여러개 구동시 memory의 db path 충돌

📝 Description

현재 chatterbox.memory.SqliteMemory를 생성할 때 db 경로가 tempdirchatterbox.db로 고정되어 있어 두개 이상의 chatterbox 앱을 구동시킬 때 같은 db를 공유해 나중에 실행된 앱이 먼저 생성된 앱의 db를 삭제하는 문제가 발생한다.

💻 System

  • Chatterbox 버전: 0.2.1

Question: Different behavior of fallback than described in the README

📝 Description

💻 System

  • OS: Windows 10 Home (x86-64) / Ubuntu 18.04.1 LTS (GNU/Linux 4.14.43-138 armv7l)
  • Python 버전: 3.6.4 / 3.6.5
  • Chatterbox 버전: 0.2.5
  • pip freeze 결과물:
asn1crypto==0.24.0
cffi==1.11.5
chatterbox.py==0.2.5
click==6.7
cryptography==2.3.1
Flask==1.0.2
idna==2.7
itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
pycparser==2.18
PyMySQL==0.9.2
six==1.11.0
Werkzeug==0.14.1

🔥 Error

action="*" 인 rule 이 있는 상태일때 failback 함수의 action을 만족하더라도 action="*"이 달린 함수가 실행이 됩니다. 이게 README 파일에 잘못 적힌것인지, 구현이 잘못된것인지 모르겠네요.

👀 Expected behaviour

기대했던 동작은 README.md에 적힌대로 유저가 어떤 상태에 있더라도 원하는 dest로 이동을 하는 것이였는데 그렇지 않네요.

🏗️ Steps to recreate

image
처음에 chatter 객체 만들때 fallback=True 해뒀습니다.

image
이 그림판으로 그린 그림처럼 만들었습니다.

Question: 10분이 지난 유저 상태가 만료되지않음

📝 Description

💻 System

  • OS: Windows 10 Home (64비트) 1803
  • Python 버전: 3.6.4
  • Chatterbox 버전: 0.2.5
  • pip freeze 결과물:
altgraph==0.15
asn1crypto==0.24.0
astroid==1.6.5
autopep8==1.3.5
beautifulsoup4==4.6.0
bs4==0.0.1
certifi==2018.1.18
cffi==1.11.5
chardet==3.0.4
chatterbox.py==0.2.5
click==6.7
clipboard==0.0.4
colorama==0.3.9
cryptography==2.2.2
cycler==0.10.0
Cython==0.28.3
decrunch==0.3.0
deprecation==2.0
ez-setup==0.9
Flask==1.0.2
fsb5==1.0
future==0.16.0
hcapy==0.0.2
idna==2.6
imutils==0.4.5
isort==4.2.15
itsdangerous==0.24
Jinja2==2.10
kiwisolver==1.0.1
lazy-object-proxy==1.3.1
lz4==1.0.0
macholib==1.9
MarkupSafe==1.0
matplotlib==2.2.3
mccabe==0.6.1
myModule==1.0
mysql-connector-python==8.0.11
numpy==1.14.5+mkl
opencv-python==3.4.0
packaging==17.1
pefile==2017.11.5
pep8==1.7.1
Pillow==5.0.0
pycodestyle==2.4.0
pycparser==2.18
PyInstaller==3.3.1
pylint==1.9.2
PyMySQL==0.9.0
pyparsing==2.2.0
pyperclip==1.6.2
pypiwin32==223
pypng==0.0.18
PyQRCode==1.2.1
pytesseract==0.2.2
python-dateutil==2.7.3
pytz==2018.5
pywin32==223
rc4-python3==1.1.3
requests==2.19.1
rope==0.10.7
scipy==1.1.0
six==1.11.0
unitypack==0.9.0
urllib3==1.23
virtualenv==16.0.0
Werkzeug==0.14.1
wrapt==1.10.11

(테스트 할때 venv를 사용하지 않고 해서 좀 난잡하네요.)

🔥 Error

image

카카오톡에서는 10분이 지나면 상태가 만료되어 /keyboard 를 호출하는데 챗봇에서는 만료된 상태가 반영이 되지 않네요. 언제부턴지 모르겠지만 갑자기 이럽니다.

👀 Expected behaviour

🏗️ Steps to recreate

flask_advance.py 의 마지막줄app.run(debug=True)에서 host=0.0.0.0만 추가한 후 그대로 사용해서 PowerShell 실행 후 python flask_advance.py 로 실행.
테스트에 이용한 플러스친구 계정은 버려진 친구를 이용했습니다.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.