-
-
Notifications
You must be signed in to change notification settings - Fork 409
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add RESTful web server and webhook parser (#96)
* Added RESTful web server and webhook parser
- Loading branch information
1 parent
7d7a980
commit 5300bc3
Showing
14 changed files
with
396 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Webhook Parser | ||
|
||
Similar to the crontab parser this parser doesn't take a message as an input, it takes a webhook instead. It allows you to trigger the skill by calling a specific URL endpoint. | ||
|
||
## Example | ||
|
||
```python | ||
from aiohttp.web import Request | ||
|
||
from opsdroid.matchers import match_webhook | ||
from opsdroid.message import Message | ||
|
||
@match_webhook('examplewebhook') | ||
async def mycrontabskill(opsdroid, config, message): | ||
|
||
if type(message) is not Message and type(message) is Request: | ||
# Capture the request POST data and set message to a default message | ||
request = await message.post() | ||
message = Message("", None, connector.default_room, | ||
opsdroid.default_connector) | ||
|
||
# Respond | ||
await message.respond('Hey') | ||
``` | ||
|
||
**Config** | ||
|
||
```yaml | ||
skills: | ||
- name: "exampleskill" | ||
``` | ||
|
||
The above skill would be called if you send a POST to `http://localhost:8080/skill/exampleskill/examplewebhook`. As the skill is being triggered by a webhook the `message` argument being passed in will be set to the [aiohttp Request](http://aiohttp.readthedocs.io/en/stable/web_reference.html#aiohttp.web.BaseRequest), this means you need to create an empty message to respond to. You will also need to know which connector, and possibly which room, to send the message back to. For this you can use the `opsdroid.default_connector` and `opsdroid.default_connector.default_room` properties to get some sensible defaults. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# REST API | ||
|
||
There is a RESTful API for opsdroid which by default is only accessible to `localhost` on port `8080`. See the [configuration reference](configuration-reference#web) for config options. | ||
|
||
## Methods | ||
|
||
### `/` _[GET]_ | ||
|
||
A test url you can use to check whether the API is running. | ||
|
||
**Example response** | ||
|
||
```json | ||
{ | ||
"timestamp": "2017-02-05T10:12:51.622981", | ||
"status": 200, | ||
"result": { | ||
"message": "Welcome to the opsdroid API" | ||
} | ||
} | ||
``` | ||
|
||
### `/stats/` _[GET]_ | ||
|
||
This method returns runtime statistics which could be useful in monitoring. | ||
|
||
**Example response** | ||
|
||
```json | ||
{ | ||
"timestamp": "2017-02-05T10:14:37.494541", | ||
"status": 200, | ||
"result": { | ||
"version": "0.6.0", | ||
"messages": { | ||
"total_parsed": 164, | ||
"webhooks_called": 28 | ||
}, | ||
"modules": { | ||
"skills": 13, | ||
"connectors": 1, | ||
"databases": 0 | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### `/skill/{skillname}/{webhookname}` _[POST]_ | ||
|
||
This method family will call skills which have been decorated with the [webhook matcher](parsers/webhook). The URI format includes the name of the skill from the `configuration.yaml` and the name of the webhook set in the decorator. | ||
|
||
The response includes information on whether a skill was successfully triggered or not. | ||
|
||
**Example response** | ||
|
||
```json | ||
{ | ||
"timestamp": "2017-02-04T16:25:01.956323", | ||
"status": 200, | ||
"result": { | ||
"called_skill": "examplewebhookskill" | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
"""Submodule to handle web requests in opsdroid.""" | ||
|
||
import json | ||
import logging | ||
from datetime import datetime | ||
|
||
from aiohttp import web | ||
|
||
from opsdroid.const import __version__ | ||
|
||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
class Web: | ||
"""Web server for opsdroid.""" | ||
|
||
def __init__(self, opsdroid): | ||
"""Setup web object.""" | ||
self.opsdroid = opsdroid | ||
try: | ||
self.config = self.opsdroid.config["web"] | ||
except KeyError: | ||
self.config = {} | ||
self.web_app = web.Application(loop=self.opsdroid.eventloop) | ||
self.web_app.router.add_get('/', self.web_index_handler) | ||
self.web_app.router.add_get('', self.web_index_handler) | ||
self.web_app.router.add_get('/stats', self.web_stats_handler) | ||
self.web_app.router.add_get('/stats/', self.web_stats_handler) | ||
|
||
@property | ||
def get_port(self): | ||
"""Return port from config or the default.""" | ||
try: | ||
port = self.config["port"] | ||
except KeyError: | ||
port = 8080 | ||
return port | ||
|
||
@property | ||
def get_host(self): | ||
"""Return host from config or the default.""" | ||
try: | ||
host = self.config["host"] | ||
except KeyError: | ||
host = '127.0.0.1' | ||
return host | ||
|
||
def start(self): | ||
"""Start web servers.""" | ||
_LOGGER.debug( | ||
"Starting web server with host %s and port %s", | ||
self.get_host, self.get_port) | ||
web.run_app(self.web_app, host=self.get_host, | ||
port=self.get_port, print=_LOGGER.info) | ||
|
||
@staticmethod | ||
def build_response(status, result): | ||
"""Build a json response object.""" | ||
return web.Response(text=json.dumps({ | ||
"timestamp": datetime.now().isoformat(), | ||
"status": status, | ||
"result": result | ||
})) | ||
|
||
def web_index_handler(self, request): | ||
"""Handle root web request.""" | ||
return self.build_response(200, { | ||
"message": "Welcome to the opsdroid API"}) | ||
|
||
def web_stats_handler(self, request): | ||
"""Handle stats request.""" | ||
return self.build_response(200, { | ||
"version": __version__, | ||
"messages": { | ||
"total_parsed": self.opsdroid.stats["messages_parsed"], | ||
"webhooks_called": self.opsdroid.stats["webhooks_called"] | ||
}, | ||
"modules": { | ||
"skills": len(self.opsdroid.skills), | ||
"connectors": len(self.opsdroid.connectors), | ||
"databases": len(self.opsdroid.memory.databases) | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.