Skip to content

Commit

Permalink
Merge pull request #176 from gunthercox/hipchat
Browse files Browse the repository at this point in the history
Add HipChat input and output adapter
  • Loading branch information
gunthercox authored Jun 24, 2016
2 parents 227f213 + ae86a27 commit 19e167d
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 0 deletions.
1 change: 1 addition & 0 deletions chatterbot/adapters/input/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .input_adapter import InputAdapter
from .hipchat import HipChat
from .terminal import TerminalAdapter
from .variable_input_type_adapter import VariableInputTypeAdapter
109 changes: 109 additions & 0 deletions chatterbot/adapters/input/hipchat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from chatterbot.adapters.input import InputAdapter
from chatterbot.conversation import Statement
from time import sleep
import requests


class HipChat(InputAdapter):
"""
An input adapter that allows a ChatterBot instance to get
input statements from a HipChat room.
"""

def __init__(self, **kwargs):
super(HipChat, self).__init__(**kwargs)

self.hipchat_host = kwargs.get("hipchat_host")
self.hipchat_access_token = kwargs.get("hipchat_access_token")
self.hipchat_room = kwargs.get("hipchat_room")

authorization_header = "Bearer {}".format(self.hipchat_access_token)

self.headers = {
'Authorization': authorization_header,
'Content-Type': 'application/json'
}

# This is a list of the messages that have been responded to
self.recent_message_ids = self.get_initial_ids()

def get_initial_ids(self):
"""
Returns a list of the most recent message ids.
"""
data = self.view_recent_room_history(
self.hipchat_room,
max_results=75
)

results = set()

for item in data['items']:
results.add(item['id'])

return results

def view_recent_room_history(self, room_id_or_name, max_results=1):
"""
https://www.hipchat.com/docs/apiv2/method/view_recent_room_history
"""

recent_histroy_url = "{}/v2/room/{}/history?max-results={}".format(
self.hipchat_host,
room_id_or_name,
max_results
)

response = requests.get(
recent_histroy_url,
headers=self.headers
)

return response.json()

def get_most_recent_message(self, room_id_or_name):
data = self.view_recent_room_history(room_id_or_name)

items = data['items']

if not items:
return None
return items[-1]

def process_input(self, statement):

new_message = False

input_statement = self.context.get_last_input_statement()
response_statement = self.context.get_last_response_statement()

if input_statement:
last_message_id = input_statement.extra_data.get(
'hipchat_message_id', None
)
if last_message_id:
self.recent_message_ids.add(last_message_id)

if response_statement:
last_message_id = response_statement.extra_data.get(
'hipchat_message_id', None
)
if last_message_id:
self.recent_message_ids.add(last_message_id)

while not new_message:
data = self.get_most_recent_message(self.hipchat_room)

if data and data['id'] not in self.recent_message_ids:
self.recent_message_ids.add(data['id'])
new_message = True
else:
pass
sleep(3.5)

text = data['message']

statement = Statement(text)
statement.add_extra_data('hipchat_message_id', data['id'])

return statement
1 change: 1 addition & 0 deletions chatterbot/adapters/output/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
from .terminal import TerminalAdapter
from .output_format_adapter import OutputFormatAdapter
from .mailgun import Mailgun
from .hipchat import HipChat
64 changes: 64 additions & 0 deletions chatterbot/adapters/output/hipchat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from chatterbot.adapters.output import OutputAdapter
import requests
import json


class HipChat(OutputAdapter):
"""
An output adapter that allows a ChatterBot instance to send
responses to a HipChat room.
"""

def __init__(self, **kwargs):
super(HipChat, self).__init__(**kwargs)

self.hipchat_host = kwargs.get("hipchat_host")
self.hipchat_access_token = kwargs.get("hipchat_access_token")
self.hipchat_room = kwargs.get("hipchat_room")

authorization_header = "Bearer {}".format(self.hipchat_access_token)

self.headers = {
'Authorization': authorization_header,
'Content-Type': 'application/json'
}

def send_message(self, room_id_or_name, message):
"""
Send a message to a HipChat room.
https://www.hipchat.com/docs/apiv2/method/send_message
"""

message_url = "{}/v2/room/{}/message".format(
self.hipchat_host,
room_id_or_name
)

response = requests.post(
message_url,
headers=self.headers,
data=json.dumps({
'message': message
})
)

return response.json()

def reply_to_message(self):
"""
The HipChat api supports responding to a given message.
This may be a good feature to implement in the future to
help with multi-user conversations.
https://www.hipchat.com/docs/apiv2/method/reply_to_message
"""
pass

def process_response(self, statement):
data = self.send_message(self.hipchat_room, statement.text)

# Update the output statement with the message id
self.context.recent_statements[-1][1].add_extra_data(
'hipchat_message_id', data['id']
)

return statement
23 changes: 23 additions & 0 deletions docs/adapters/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@ communicate with the chat bot.
input_adapter="chatterbot.adapters.input.TerminalAdapter"
)
.. _hipchat-input-adapter:

HipChat Adapter
===============

.. autofunction:: chatterbot.adapters.input.HipChat

This is an input adapter that allows a ChatterBot instance to communicate
through `HipChat`_.

Be sure to also see the documentation for the :ref:`HipChat output adapter <hipchat-output-adapter>`.

.. code-block:: python
chatbot = ChatBot(
"My ChatterBot",
input_adapter="chatterbot.adapters.input.HipChat",
hipchat_host="https://mydomain.hipchat.com",
hipchat_room="my-room-name",
hipchat_access_token="my-hipchat-access-token",
)
Speech recognition
==================

Expand All @@ -67,3 +89,4 @@ the chat bot's constructor.
.. _strings: https://docs.python.org/2/library/string.html
.. _dictionaries: https://docs.python.org/2/tutorial/datastructures.html#dictionaries
.. _chatterbot-voice: https://github.com/gunthercox/chatterbot-voice
.. _HipChat: https://www.hipchat.com/
23 changes: 23 additions & 0 deletions docs/adapters/output.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,28 @@ communicate with the chat bot.
output_adapter="chatterbot.adapters.output.TerminalAdapter"
)
.. _hipchat-output-adapter:

HipChat Adapter
===============

.. autofunction:: chatterbot.adapters.output.HipChat

This is an output adapter that allows a ChatterBot instance to send responses
to a `HipChat`_ room.

Be sure to also see the documentation for the :ref:`HipChat input adapter <hipchat-input-adapter>`.

.. code-block:: python
chatbot = ChatBot(
"My ChatterBot",
input_adapter="chatterbot.adapters.output.HipChat",
hipchat_host="https://mydomain.hipchat.com",
hipchat_room="my-room-name",
hipchat_access_token="my-hipchat-access-token",
)
Mailgun adapter
===============

Expand Down Expand Up @@ -78,3 +100,4 @@ the chat bot's constructor.

.. _chatterbot-voice: https://github.com/gunthercox/chatterbot-voice
.. _`Mailgun API`: https://documentation.mailgun.com/api_reference.html
.. _HipChat: https://www.hipchat.com/
29 changes: 29 additions & 0 deletions examples/hipchat_bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from chatterbot import ChatBot
from chatterbot.training.trainers import ChatterBotCorpusTrainer
from settings import HIPCHAT

'''
See the HipChat api documentation for how to get a user access token.
https://developer.atlassian.com/hipchat/guide/hipchat-rest-api/api-access-tokens
'''

chatbot = ChatBot(
"HipChatBot",
hipchat_host=HIPCHAT["HOST"],
hipchat_room=HIPCHAT["ROOM"],
hipchat_access_token=HIPCHAT["ACCESS_TOKEN"],
input_adapter="chatterbot.adapters.input.HipChat",
output_adapter="chatterbot.adapters.output.HipChat"
)

chatbot.set_trainer(ChatterBotCorpusTrainer)
chatbot.train("chatterbot.corpus.english")

# The following loop will execute each time the user enters input
while True:
try:
response = chatbot.get_response(None)

# Press ctrl-c or ctrl-d on the keyboard to exit
except (KeyboardInterrupt, EOFError, SystemExit):
break

0 comments on commit 19e167d

Please sign in to comment.