├── pb_py ├── __init__.py ├── test.aiml ├── test.py └── main.py ├── requirements.txt ├── MANIFEST ├── setup.py ├── CHANGES.txt ├── .gitignore ├── LICENSE └── README.md /pb_py/__init__.py: -------------------------------------------------------------------------------- 1 | #empty 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests >= 2.20.0 2 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | CHANGES.txt 2 | requirements.txt 3 | setup.py 4 | pb_py/__init__.py 5 | pb_py/main.py 6 | -------------------------------------------------------------------------------- /pb_py/test.aiml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | HI 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | name='PbPython', 5 | version='0.2.0', 6 | author='Michael Kunze', 7 | author_email='michael.kunze@pandorabots.com', 8 | packages=['pb_py'], 9 | license='LICENSE.txt', 10 | url="https://developer.pandorabots.com/docs", 11 | description='Code for making API calls to Pandorabots server.', 12 | install_requires=[ 13 | "requests >= 2.20.0", 14 | ] 15 | ) 16 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | v<0.1.0>, <7/10/14> -- Initial release. 2 | v<0.1.2>, <7/25/14> -- changed link in setup.py 3 | v<0.1.3>, <9/5/14> -- added client_name parameter 4 | v<0.1.4>, <9/24/14> -- fixed bug in main 5 | v<0.1.5>, <9/25/14> -- fixed response in main 6 | v<0.1.6>, <10/24/14> -- added list_bots, download_bot, get_files, and delete_file methods, revised upload_file 7 | v<0.1.7>, <11/18/14> -- made upload_file accept files not in current working directory 8 | v<0.1.8>, <12/4/14> -- revised trace processing 9 | v<0.1.9>, <12/18/14> -- added get_file and changed api method name: get_files --> list_files 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | bin/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # Installer logs 26 | pip-log.txt 27 | pip-delete-this-directory.txt 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .coverage 33 | .cache 34 | nosetests.xml 35 | coverage.xml 36 | 37 | # Translations 38 | *.mo 39 | 40 | # Mr Developer 41 | .mr.developer.cfg 42 | .project 43 | .pydevproject 44 | 45 | # Rope 46 | .ropeproject 47 | 48 | # Django stuff: 49 | *.log 50 | *.pot 51 | 52 | # Sphinx documentation 53 | docs/_build/ 54 | 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Pandorabots Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /pb_py/test.py: -------------------------------------------------------------------------------- 1 | from main import Pandorabots 2 | 3 | host = 'YOUR HOST' 4 | botname = 'YOUR BOTNAME' 5 | app_id = 'YOUR APP_ID' 6 | user_key = 'YOUR USER_KEY' 7 | test_filename = 'test.aiml' 8 | botkey = 'YOUR BOTKEY' 9 | 10 | simple_input = {'message':'hi'} 11 | advanced_input = {'message':'hi', 12 | 'trace':True, 13 | 'reset':True, 14 | 'that':'Hello', 15 | 'topic': 'greetings', 16 | 'sessionid': '123', 17 | 'recent': True, 18 | 19 | 'reload':True, 20 | 'extra': True 21 | } 22 | atalk_input = {'message':'hi', 23 | 'sessionid': '123', 24 | 'recent': True 25 | } 26 | 27 | main = Pandorabots(user_key, app_id, host, botname) 28 | 29 | # test create 30 | print(main.create_bot(botname).text) 31 | 32 | # test list_bots 33 | print(main.list_bots().text) 34 | 35 | # upload file 36 | print(main.upload_file(test_filename).text) 37 | 38 | # list files 39 | print(main.list_files().text) 40 | 41 | # get file 42 | print(main.get_file(test_filename).text) 43 | 44 | # download bot 45 | print(main.download_bot().text) 46 | 47 | # compile_bot 48 | print(main.compile_bot().text) 49 | 50 | # talk 51 | print(main.talk(simple_input).text) 52 | 53 | # debug 54 | print(main.talk(advanced_input).text) 55 | 56 | #atalk 57 | print(main.atalk(atalk_input).text) 58 | 59 | #atalk with botkey 60 | print(main.atalk(atalk_input, True).text) 61 | 62 | # delete file 63 | print(main.delete_file(test_filename).text) 64 | 65 | # test delete 66 | print(main.delete_bot(botname).text) 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Pandorabots API module for Python 3 | 4 | 5 | This is a guide for the Pandorabots SDK for the Python programming language. It provides usage guidelines as well as code examples. 6 | 7 | 8 | 9 | Please read the [Documentation](https://developer.pandorabots.com/docs). 10 | 11 | 12 | 13 | 14 | 15 | #### Installation 16 | 17 | ------------ 18 | 19 | The easiest way to install the latest version is to clone the repository from 20 | 21 | Github and install it: 22 | 23 | ``` 24 | git clone https://github.com/pandorabots/pb-python.git 25 | cd pb-python 26 | python setup.py install 27 | ``` 28 | 29 | #### Usage 30 | Import the Pandorabots object and create an instance with your credentials: 31 | 32 | Note: `botname` is not required to create the object but is necessary to run bot-specific APIs, and `botkey` is only necessary if the atalk botkey api instance is used. 33 | 34 | ``` 35 | from main import Pandorabots 36 | 37 | host = 'YOUR HOST' 38 | botname = 'YOUR BOTNAME' 39 | app_id = 'YOUR APP_ID' 40 | user_key = 'YOUR USER_KEY' 41 | botkey = 'YOUR BOTKEY' 42 | 43 | API = Pandorabots(user_key, app_id, host, botname, botkey) 44 | ``` 45 | Each method returns the response from the Pandorabots API. 46 | 47 | To create a bot: 48 | ``` 49 | result = API.create_bot(botname) 50 | ``` 51 | To select a bot (if one not specified in initial object creation): 52 | ``` 53 | API.selectBot(botname) 54 | ``` 55 | To get a list of your bots: 56 | ``` 57 | result = API.list_bots() 58 | ``` 59 | To delete a bot: 60 | ``` 61 | result = API.delete_bot(botname) 62 | ``` 63 | To upload a file to a bot: 64 | ``` 65 | filename = 'test.aiml' 66 | result = API.upload_file(filename) 67 | ``` 68 | To delete a file: 69 | ``` 70 | result = api.delete_file(filename) 71 | ``` 72 | To get a list of all your bot's files: 73 | ``` 74 | result = API.list_files() 75 | ``` 76 | To get a file: 77 | ``` 78 | filename = 'test.aiml' 79 | result = API.get_file(filename) 80 | ``` 81 | To download a bot as a zip file to the current directory: 82 | ``` 83 | API.download_bot() 84 | ``` 85 | To compile a bot: 86 | ``` 87 | result = API.compile_bot() 88 | ``` 89 | There are two routes of using the two talk methods. The first makes use of `app_id`, `userkey`, and `botname`. The second replaces these with `botkey`. To use this second method please ensure `host` is set to `api.pandorabots.com` and `botkey` is set to `YOUR_BOTKEY`. 90 | 91 | To talk to a bot you need to send an input object of the form: 92 | ``` 93 | input_object = {'message':'hi', 94 | 'trace':True, 95 | 'reset':True, 96 | 'that':'Hello', 97 | 'topic': 'greetings', 98 | 'sessionid': '123', 99 | 'recent': True, 100 | 'reload':True, 101 | 'extra': True, 102 | 'client_name': 'client_name'} 103 | 104 | result = API.talk(input_object) 105 | ``` 106 | 107 | To use the `botkey` route: 108 | ``` 109 | usebotkey = True 110 | result = API.talk(input_object, usebotkey) 111 | ``` 112 | In the `input_object` only the `message` parameter is required. The other paramters can be included for debugging purposes. Note: `client_name` and `trace` cannot be specified concurrently for security purposes. 113 | 114 | To talk with your bot via the atalk (anonymous talk) api: 115 | ``` 116 | result = API.atalk(input_object) 117 | ``` 118 | 119 | To use the `botkey` route: 120 | ``` 121 | usebotkey = True 122 | result = API.atalk(input_object, usebotkey) 123 | ``` 124 | Alternatively, there 125 | For more information see the [developer docs](https://developer.pandorabots.com/docs) or the test file `test.py` in the `pb_py` folder. 126 | -------------------------------------------------------------------------------- /pb_py/main.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | class Pandorabots: 4 | def __init__(self, user_key, app_id, host, botname=False, botkey=False): 5 | self.user_key = user_key 6 | self.app_id = app_id 7 | self.host = host 8 | self.botname = botname 9 | self.no_botname_error = {'error':'please set a botname via select_bot("your_botname")'} 10 | self.no_message_error = {'error':'please include a message string input to your bot, ex. {"message":"hello"}")'} 11 | self.no_botkey_error = {'error':'please set a botkey via set_botkey("your_botkey")'} 12 | self.use_api_host_error = {'error':'host must be "api.pandorabots.com" to use atalk with a botkey'} 13 | self.botkey = botkey 14 | 15 | def set_botkey(self, botkey): 16 | self.botkey = botkey 17 | 18 | def select_bot(self, botname): 19 | self.botname = botname 20 | 21 | def create_bot(self, botname): 22 | path = '/bot/' + self.app_id +'/' + self.botname 23 | url = "https://" + self.host + path 24 | query = {"user_key": self.user_key} 25 | response = requests.put(url, params=query) 26 | if response.ok : 27 | self.botname = botname 28 | return response 29 | 30 | def list_bots(self): 31 | path = '/bot/' + self.app_id 32 | url = "https://" + self.host + path 33 | query = {"user_key": self.user_key} 34 | response = requests.get(url, params=query) 35 | return response 36 | 37 | def delete_bot(self, botname): 38 | path = '/bot/' + self.app_id +'/' + self.botname 39 | url = "https://" + self.host + path 40 | query = {"user_key": self.user_key} 41 | response = requests.delete(url, params=query) 42 | return response 43 | 44 | def upload_file(self, filename): 45 | if not self.botname: 46 | return self.no_botname_error 47 | path = '/bot/' + self.app_id + '/' + self.botname + '/' 48 | filepath = filename 49 | if '/' in filename: 50 | filename = filename.split('/')[-1] 51 | file_kind = filename.split('.')[-1] 52 | if file_kind == 'pdefaults' or file_kind =='properties': 53 | path += file_kind 54 | if file_kind == 'map' or file_kind == 'set' or file_kind == 'substitution': 55 | path += file_kind + '/' + filename.split('.')[0] 56 | if file_kind == 'aiml': 57 | path += 'file/' + filename 58 | if path == '/bot/' + self.app_id +'/' + self.botname + '/': 59 | output = 'File type must be one of the following: substitution, properties, aiml, map, set, or pdefaults' 60 | return output 61 | url = "https://" + self.host + path 62 | data = open(filepath,'rb').read() 63 | query = {"user_key": self.user_key} 64 | response = requests.put(url, params=query, data=data) 65 | return response 66 | 67 | def list_files(self): 68 | if not self.botname: 69 | return self.no_botname_error 70 | path = '/bot/' + self.app_id + '/' + self.botname 71 | url = "https://" + self.host + path 72 | query = {"user_key": self.user_key} 73 | response = requests.get(url,params=query) 74 | return response 75 | 76 | def get_file(self, filename): 77 | if not self.botname: 78 | return self.no_botname_error 79 | path = '/bot/' + self.app_id + '/' + self.botname +'/' 80 | file_kind = filename.split('.')[-1] 81 | if file_kind == 'pdefaults' or file_kind =='properties': 82 | path += file_kind 83 | if file_kind == 'map' or file_kind == 'set' or file_kind == 'substitution': 84 | path += file_kind + '/' + filename.split('.')[0] 85 | if file_kind == 'aiml': 86 | path += 'file/' + filename 87 | url = "https://" + self.host + path 88 | query = {"user_key": self.user_key} 89 | response = requests.get(url, params=query) 90 | return response 91 | 92 | def download_bot(self): 93 | if not self.botname: 94 | return self.no_botname_error 95 | path = '/bot/' + self.app_id + '/' + self.botname 96 | url = "https://" + self.host + path 97 | query = {"user_key": self.user_key, 98 | "return": 'zip'} 99 | response = requests.get(url, params=query) 100 | return response 101 | 102 | def delete_file(self, filename): 103 | if not self.botname: 104 | return self.no_botname_error 105 | path = '/bot/' + self.app_id + '/' + self.botname + '/' 106 | file_kind = filename.split('.')[-1] 107 | if file_kind == 'pdefaults' or file_kind =='properties': 108 | path += file_kind 109 | if file_kind == 'map' or file_kind == 'set' or file_kind == 'substitution': 110 | path += file_kind + '/' + filename.split('.')[0] 111 | if file_kind == 'aiml': 112 | path += 'file/' + filename 113 | if path == '/bot/' + self.app_id +'/' + self.botname + '/': 114 | output = 'File type must be one of the following: substitution, properties, aiml, map, set, or pdefaults' 115 | return output 116 | url = "https://" + self.host + path 117 | query = {"user_key": self.user_key} 118 | response = requests.delete(url, params=query) 119 | return response 120 | 121 | def compile_bot(self): 122 | if not self.botname: 123 | return self.no_botname_error 124 | path = '/bot/' + self.app_id +'/' + self.botname + '/verify' 125 | url = "https://" + self.host + path 126 | query = {"user_key": self.user_key} 127 | response = requests.get(url, params=query) 128 | return response 129 | 130 | def talk(self, input, usebotkey=False): 131 | if (usebotkey and not self.botkey) : 132 | return self.no_botkey_error 133 | if (usebotkey and not self.host == 'api.pandorabots.com'): 134 | return self.use_api_host_error 135 | if not usebotkey and not self.botname: 136 | return self.no_botname_error 137 | if not 'message' in input: 138 | return self.no_message_error 139 | path = '/atalk' 140 | if (not usebotkey): 141 | path += '/' + self.app_id + '/' + self.botname 142 | url = "https://" + self.host + path 143 | query = {"user_key": self.user_key} 144 | if usebotkey: 145 | query['botkey'] = self.botkey 146 | else: 147 | query["user_key"] = self.user_key 148 | if 'sessionid' in input: 149 | query['sessionid'] = input['sessionid'] 150 | if 'recent' in input: 151 | query['recent'] = str(input['recent']) 152 | if 'reset' in input: 153 | query['reset'] = str(input['reset']) 154 | if 'trace' in input: 155 | query['trace'] = str(input['trace']) 156 | if 'client_name' in input: 157 | query['client_name'] = input['client_name'] 158 | if 'that' in input: 159 | query['that'] = input['that'] 160 | if 'topic' in input: 161 | query['topic'] = input['topic'] 162 | if 'reload' in input: 163 | query['reload'] = str(input['reload']) 164 | if 'extra' in input: 165 | query['extra'] = str(input['extra']) 166 | response = requests.post(url, params=query) 167 | return response 168 | 169 | def atalk(self, input, usebotkey=False): 170 | if (usebotkey and not self.botkey) : 171 | return self.no_botkey_error 172 | if (usebotkey and not self.host == 'api.pandorabots.com'): 173 | return self.use_api_host_error 174 | if not usebotkey and not self.botname: 175 | return self.no_botname_error 176 | if not 'message' in input: 177 | return self.no_message_error 178 | path = '/atalk' 179 | if (not usebotkey): 180 | path += '/' + self.app_id + '/' + self.botname 181 | url = "https://" + self.host + path 182 | query = {"input": input['message']} 183 | if usebotkey: 184 | query['botkey'] = self.botkey 185 | else: 186 | query["user_key"] = self.user_key 187 | if 'sessionid' in input: 188 | query['sessionid'] = input['sessionid'] 189 | if 'recent' in input: 190 | query['recent'] = str(input['recent']) 191 | if 'client_name' in input: 192 | query['client_name'] = input['client_name'] 193 | response = requests.post(url, params=query) 194 | return response 195 | --------------------------------------------------------------------------------