interactive bots: Create Mention bot.
This commit is contained in:
parent
6121002b35
commit
a2557ccbe6
|
@ -74,7 +74,9 @@ force_include = [
|
|||
"zulip_bots/zulip_bots/bots/yoda/yoda.py",
|
||||
"zulip_bots/zulip_bots/bots/yoda/test_yoda.py",
|
||||
"zulip_bots/zulip_bots/bots/dialogflow/dialogflow.py",
|
||||
"zulip_bots/zulip_bots/bots/dialogflow/test_dialogflow.py"
|
||||
"zulip_bots/zulip_bots/bots/dialogflow/test_dialogflow.py",
|
||||
"zulip_bots/zulip_bots/bots/mention/mention.py",
|
||||
"zulip_bots/zulip_bots/bots/mention/test_mention.py"
|
||||
]
|
||||
|
||||
parser = argparse.ArgumentParser(description="Run mypy on files tracked by git.")
|
||||
|
|
0
zulip_bots/zulip_bots/bots/mention/__init__.py
Normal file
0
zulip_bots/zulip_bots/bots/mention/__init__.py
Normal file
BIN
zulip_bots/zulip_bots/bots/mention/assets/mentions_demo.png
Normal file
BIN
zulip_bots/zulip_bots/bots/mention/assets/mentions_demo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 93 KiB |
32
zulip_bots/zulip_bots/bots/mention/doc.md
Normal file
32
zulip_bots/zulip_bots/bots/mention/doc.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Mention bot
|
||||
|
||||
The Mention bot is a Zulip bot that can fetch Mentions associated with
|
||||
a given keyword from the web using [Mention](https://mention.com/en/).
|
||||
|
||||
To use the Mention bot, you can simply call it with `@<botname>` followed
|
||||
by a keyword, like so:
|
||||
|
||||
```
|
||||
@Mention Apple
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
Before you can proceed further, you'll need to go to the
|
||||
[Mention Dev](https://dev.mention.com/login), and get a
|
||||
Mention API Access Token.
|
||||
|
||||
1. Login.
|
||||
2. Enter the **App Name**, **Description**, **Website**, and **Redirect uris**. In this version, there
|
||||
is no actual use of the Redirect Uri and Website.
|
||||
3. After accepting the agreement, click on **Create New App**.
|
||||
4. And you're done! You should now have an Access Token.
|
||||
5. Open up `zulip_bots/bots/mention/mention.conf` in an editor and
|
||||
change the value of the `<access_token>` attribute to the Access Token
|
||||
you generated above.
|
||||
|
||||
## Usage
|
||||
`@Mention <keyword>` - This command will fetch the most recent 20
|
||||
mentions of the keyword on the web (Limitations of a free account).
|
||||
Example:
|
||||
![](assets/mentions_demo.png)
|
125
zulip_bots/zulip_bots/bots/mention/fixtures/create_alert.json
Normal file
125
zulip_bots/zulip_bots/bots/mention/fixtures/create_alert.json
Normal file
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"alert": {
|
||||
"id": "112233",
|
||||
"name": "NASA and competitors",
|
||||
"query": {
|
||||
"type": "basic",
|
||||
"included_keywords": [
|
||||
"NASA",
|
||||
"Arianespace",
|
||||
"SpaceX",
|
||||
"Pockocmoc"
|
||||
],
|
||||
"required_keywords": [
|
||||
"mars"
|
||||
],
|
||||
"excluded_keywords": [
|
||||
"nose",
|
||||
"fil d'ariane"
|
||||
]
|
||||
},
|
||||
"languages": [
|
||||
"en",
|
||||
"fr",
|
||||
"ru"
|
||||
],
|
||||
"countries": [],
|
||||
"sources": [
|
||||
"twitter",
|
||||
"news",
|
||||
"web",
|
||||
"blogs",
|
||||
"videos",
|
||||
"forums",
|
||||
"images"
|
||||
],
|
||||
"blocked_sites": [
|
||||
"www.spaceoflovemagazine.com/"
|
||||
],
|
||||
"role": "admin",
|
||||
"stats": {
|
||||
"mention_sources": {
|
||||
"total": "0"
|
||||
},
|
||||
"mention_folders": {
|
||||
"inbox": {
|
||||
"total": "0"
|
||||
},
|
||||
"archive": {
|
||||
"total": "0"
|
||||
},
|
||||
"spam": {
|
||||
"total": "0"
|
||||
},
|
||||
"trash": {
|
||||
"total": "0"
|
||||
}
|
||||
},
|
||||
"unread_mentions": {
|
||||
"total": "0"
|
||||
},
|
||||
"unseen_mentions": {
|
||||
"total": "0"
|
||||
},
|
||||
"favorite_mentions": {
|
||||
"total": "0"
|
||||
},
|
||||
"important_mentions": {
|
||||
"total": "0"
|
||||
},
|
||||
"tasks": {
|
||||
"total": "0"
|
||||
},
|
||||
"todo_tasks": {
|
||||
"total": "0"
|
||||
},
|
||||
"done_tasks": {
|
||||
"total": "0"
|
||||
},
|
||||
"logs": {
|
||||
"total": "0"
|
||||
}
|
||||
},
|
||||
"shares": [
|
||||
{
|
||||
"id": "THE_ACCOUNT_ID",
|
||||
"account": {
|
||||
"id": "THE_ACCOUNT_ID",
|
||||
"name": "Doe",
|
||||
"email": "john.doe@nasa.com",
|
||||
"language_code": "en",
|
||||
"created_at": "2014-09-30T10:03:54.0+00:00",
|
||||
"updated_at": "2016-01-14T14:55:57.0+00:00",
|
||||
"avatar_url": "https:\/\/d39qsljf883l.cloudfront.net\/f6415b89ef2ljkca5c0c7d464f1b82-088f3dsqlj12lj4.jpg",
|
||||
"timezone": "Europe\/Berlin",
|
||||
"grouped_email_notification": true,
|
||||
"default_email_notification_frequency": "daily",
|
||||
"default_desktop_notification_frequency": "hourly",
|
||||
"default_push_notification_frequency": "hourly"
|
||||
},
|
||||
"role": "admin",
|
||||
"permissions": {
|
||||
"edit": true,
|
||||
"delete": true
|
||||
},
|
||||
"created_at": "2016-01-14T15:31:42.0+00:00",
|
||||
"weight": 88674800
|
||||
}
|
||||
],
|
||||
"noise_detection": true,
|
||||
"created_at": "2016-01-14T15:31:42.0+00:00",
|
||||
"updated_at": "2016-01-14T15:31:44.0+00:00",
|
||||
"quota_used": 0,
|
||||
"index_version": 2,
|
||||
"permissions": {
|
||||
"edit": true,
|
||||
"share": true,
|
||||
"list_tasks": true,
|
||||
"list_logs": true
|
||||
},
|
||||
"description": "Monitor NASA press release.",
|
||||
"color": "#05e363",
|
||||
"connection_type": "related",
|
||||
"connection_id": "12121212"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"mentions": [
|
||||
{...mention...},
|
||||
{...mention...},
|
||||
{...mention...}
|
||||
],
|
||||
"_links": {
|
||||
"more": {
|
||||
"href": "...url to get older mentions..."
|
||||
},
|
||||
"pull": {
|
||||
"href": "...url to get newer mentions..."
|
||||
}
|
||||
}
|
||||
}
|
73
zulip_bots/zulip_bots/bots/mention/fixtures/mention.json
Normal file
73
zulip_bots/zulip_bots/bots/mention/fixtures/mention.json
Normal file
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"id": "527849933",
|
||||
"alert_id": 112233,
|
||||
"title": "NASA image shows 'starburst spider' pattern on Mars",
|
||||
"description": "USA TODAY NASA image shows 'starburst spider' pattern on Mars USA TODAY NASA's Mars Reconnaissance Orbiter captured a stunning image of a \"starburst\" pattern on Mars ' surface. The \u201cstarbursts\u201d can be seen each spring when Mars ' seasonal cap of carbon \u2026",
|
||||
"original_url": "http:\/\/www.usatoday.com\/story\/tech\/nation-now\/2016\/01\/14\/nasa-image-shows-starburst-spider-pattern-mars\/78781074\/",
|
||||
"clickable_url": "https:\/\/web.mention.com\/api\/url?token=eyJ0eXAiOiJKV1QiLChbGciOiJIUzI1NiJ9.eyJ1cmwiOJodHRwOlwvXC93d3cudXNhdG9kYkuY29tXC9zdG9eVwvdGVjaFwvbmF0a9uLW5vd1wvMjAxNlwvMDFcLzE0XC9uYXNLWltYWdlLXNob3dzLXN0YJidXJzdC1zcGlZXItcGF0dGVyb1tYXJzXC83ODc4MTA3NFwvIiwiYWNjb3VudF9pZI6NDM4NDA0LCJhbGVydF9pZI6MTE2NTk5NSwic291cmNlXlkIjo0LCJtZW50a9uX2lkIjoiNzU2NzM5MjMzMIifQ.XH7WJlYkOYTDFysZELmouro__7QVoe5pT9c1qeZw",
|
||||
"displayable_url": "usatoday.com\/story\/tech\/nation-now\/2016\/01\/14\/nasa-image-shows-starburst-spider-pattern-mars\/78781074\/",
|
||||
"unique_id": "http:\/\/www.usatoday.com\/story\/tech\/nation-now\/2016\/01\/14\/nasa-image-shows-starburst-spider-pattern-mars\/78781074\/",
|
||||
"published_at": "2016-01-14T17:16:27.10090700+00:00",
|
||||
"created_at": "2016-01-18T16:05:44.0+00:00",
|
||||
"country": "US",
|
||||
"updated_at": "2016-01-18T16:05:45.0+00:00",
|
||||
"favorite": false,
|
||||
"folder": "inbox",
|
||||
"folder_set_by_user": false,
|
||||
"read": false,
|
||||
"tone": 0,
|
||||
"source_type": "news",
|
||||
"source_name": "USA TODAY",
|
||||
"source_url": "http:\/\/www.usatoday.com\/",
|
||||
"language_code": "en",
|
||||
"tasks": [],
|
||||
"logs": [],
|
||||
"children": {
|
||||
"children": [
|
||||
{...mention...},
|
||||
{...mention...},
|
||||
{...mention...}
|
||||
],
|
||||
"total": 42,
|
||||
"_links": {
|
||||
"more": {
|
||||
"href": "/api/accounts/THE_ACCOUNT_ID/alerts/112233/mentions/527849937/children?limit=20&before_date=2014-03-20T18:10:37.53829200+00:00",
|
||||
"params": {
|
||||
"limit": 20,
|
||||
"before_date": "2014-03-20T18:10:37.53829200+00:00"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"picture_url": "\/\/t3.gstatic.com\/images?q=tbn:ANd9GcQlW3QxiNh2YxxacyF0gR636ViYH6YS_0ONIRj9pf4OhiRZ8hHHyCQqdOYVgMuToZ1Iixhy",
|
||||
"tags": [],
|
||||
"offsets": {
|
||||
"title": [0, 0, 4, 4, 47, 47, 4, 4],
|
||||
"description": [10,10, 4, 4, 57, 57, 4, 4, 72, 72, 4, 4, 79, 79, 4, 4, 161, 161, 4, 4, 223, 223, 4, 4],
|
||||
"url": [],
|
||||
"source_name": [],
|
||||
"source_url": []
|
||||
},
|
||||
"permissions": {
|
||||
"favorite": true,
|
||||
"change_folder": true,
|
||||
"create_task": true
|
||||
},
|
||||
"author_influence": {
|
||||
"id": "3153793048",
|
||||
"alert_id": 112233,
|
||||
"kind": "web",
|
||||
"url": "http:\/\/www.usatoday.com",
|
||||
"name": "usatoday.com",
|
||||
"score": 83,
|
||||
"scored_id": "usatoday.com"
|
||||
},
|
||||
"metadata": {
|
||||
"twitter": {
|
||||
"id_str": "800747234652340224",
|
||||
"user": {
|
||||
"id_str": "188302352"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
zulip_bots/zulip_bots/bots/mention/mention.conf
Normal file
3
zulip_bots/zulip_bots/bots/mention/mention.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
[mention]
|
||||
access_token = <access_token>
|
||||
# create an app here and get the access token from it: https://dev.mention.com/login
|
103
zulip_bots/zulip_bots/bots/mention/mention.py
Normal file
103
zulip_bots/zulip_bots/bots/mention/mention.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
# See readme.md for instructions on running this code.
|
||||
|
||||
import requests
|
||||
from typing import Any, List
|
||||
|
||||
class MentionHandler(object):
|
||||
def initialize(self, bot_handler: Any) -> None:
|
||||
self.config_info = bot_handler.get_config_info('mention')
|
||||
self.access_token = self.config_info['access_token']
|
||||
self.account_id = ''
|
||||
|
||||
def usage(self) -> str:
|
||||
return '''
|
||||
This is a Mention API Bot which will find mentions
|
||||
of the given keyword throughout the web.
|
||||
Version 1.00
|
||||
'''
|
||||
|
||||
def handle_message(self, message: Any, bot_handler: Any) -> None:
|
||||
message['content'] = message['content'].strip()
|
||||
|
||||
if message['content'].lower() == 'help':
|
||||
bot_handler.send_reply(message, self.usage())
|
||||
return
|
||||
|
||||
if message['content'] == '':
|
||||
bot_handler.send_reply(message, 'Empty Mention Query')
|
||||
return
|
||||
|
||||
keyword = message['content']
|
||||
content = self.generate_response(keyword)
|
||||
bot_handler.send_reply(message, content)
|
||||
|
||||
def get_account_id(self) -> str:
|
||||
get_ac_id_header = {
|
||||
'Authorization': 'Bearer ' + self.access_token,
|
||||
'Accept-Version': '1.15',
|
||||
}
|
||||
response = requests.get(
|
||||
'https://api.mention.net/api/accounts/me', headers=get_ac_id_header)
|
||||
data_json = response.json()
|
||||
account_id = data_json['account']['id']
|
||||
return account_id
|
||||
|
||||
def get_alert_id(self, keyword: str) -> str:
|
||||
create_alert_header = {
|
||||
'Authorization': 'Bearer ' + self.access_token,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept-Version': '1.15',
|
||||
}
|
||||
|
||||
create_alert_data = {
|
||||
'name': keyword,
|
||||
'query': {
|
||||
'type': 'basic',
|
||||
'included_keywords': [keyword]
|
||||
},
|
||||
'languages': ['en'],
|
||||
'sources': ['web']
|
||||
} # type: Any
|
||||
|
||||
response = requests.post('https://api.mention.net/api/accounts/' + self.account_id +
|
||||
'/alerts', data=create_alert_data, headers=create_alert_header)
|
||||
data_json = response.json()
|
||||
alert_id = data_json['alert']['id']
|
||||
return alert_id
|
||||
|
||||
def get_mentions(self, alert_id: str) -> List[Any]:
|
||||
get_mentions_header = {
|
||||
'Authorization': 'Bearer ' + self.access_token,
|
||||
'Accept-Version': '1.15',
|
||||
}
|
||||
response = requests.get('https://api.mention.net/api/accounts/' + self.account_id +
|
||||
'/alerts/' + alert_id + '/mentions', headers=get_mentions_header)
|
||||
data_json = response.json()
|
||||
mentions = data_json['mentions']
|
||||
return mentions
|
||||
|
||||
def generate_response(self, keyword: str) -> str:
|
||||
if self.account_id == '':
|
||||
self.account_id = self.get_account_id()
|
||||
|
||||
try:
|
||||
alert_id = self.get_alert_id(keyword)
|
||||
except (TypeError, KeyError):
|
||||
# Usually triggered by invalid token or json parse error when account quote is finished.
|
||||
raise MentionNoResponseException()
|
||||
|
||||
try:
|
||||
mentions = self.get_mentions(alert_id)
|
||||
except (TypeError, KeyError):
|
||||
# Usually triggered by no response or json parse error when account quota is finished.
|
||||
raise MentionNoResponseException()
|
||||
|
||||
reply = 'The most recent mentions of `' + keyword + '` on the web are: \n'
|
||||
for mention in mentions:
|
||||
reply += "[{title}]({id})\n".format(title=mention['title'], id=mention['original_url'])
|
||||
return reply
|
||||
|
||||
handler_class = MentionHandler
|
||||
|
||||
class MentionNoResponseException(Exception):
|
||||
pass
|
34
zulip_bots/zulip_bots/bots/mention/test_mention.py
Normal file
34
zulip_bots/zulip_bots/bots/mention/test_mention.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
from zulip_bots.test_lib import BotTestCase
|
||||
|
||||
class TestMentionBot(BotTestCase):
|
||||
bot_name = "mention"
|
||||
|
||||
def test_bot_responds_to_empty_message(self) -> None:
|
||||
# Offline query.
|
||||
with self.mock_config_info({'access_token': '12345'}):
|
||||
self.verify_reply('', 'Empty Mention Query')
|
||||
|
||||
def test_help_query(self) -> None:
|
||||
# Offline query.
|
||||
with self.mock_config_info({'access_token': '12345'}):
|
||||
self.verify_reply('help', '''
|
||||
This is a Mention API Bot which will find mentions
|
||||
of the given keyword throughout the web.
|
||||
Version 1.00
|
||||
''')
|
||||
|
||||
# Offline query.
|
||||
with self.mock_config_info({'access_token': '12345'}):
|
||||
self.verify_reply('hElp', '''
|
||||
This is a Mention API Bot which will find mentions
|
||||
of the given keyword throughout the web.
|
||||
Version 1.00
|
||||
''')
|
||||
|
||||
# Offline query.
|
||||
with self.mock_config_info({'access_token': '12345'}):
|
||||
self.verify_reply('HELP', '''
|
||||
This is a Mention API Bot which will find mentions
|
||||
of the given keyword throughout the web.
|
||||
Version 1.00
|
||||
''')
|
Loading…
Reference in a new issue