interactive bots: Create Mention bot.

This commit is contained in:
Viraat Chandra 2017-12-24 17:38:45 +05:30 committed by showell
parent 6121002b35
commit a2557ccbe6
10 changed files with 388 additions and 1 deletions

View file

@ -74,7 +74,9 @@ force_include = [
"zulip_bots/zulip_bots/bots/yoda/yoda.py", "zulip_bots/zulip_bots/bots/yoda/yoda.py",
"zulip_bots/zulip_bots/bots/yoda/test_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/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.") parser = argparse.ArgumentParser(description="Run mypy on files tracked by git.")

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

View 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)

View 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"
}
}

View file

@ -0,0 +1,15 @@
{
"mentions": [
{...mention...},
{...mention...},
{...mention...}
],
"_links": {
"more": {
"href": "...url to get older mentions..."
},
"pull": {
"href": "...url to get newer mentions..."
}
}
}

View 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"
}
}
}
}

View 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

View 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

View 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
''')