link_shortener: Migrate from goo.gl to bit.ly service.
Shorten URLs by using bit.ly service instead of goo.gl service.
Fixes
MODIFY
zulip_bots/zulip_bots/bots/link_shortener/doc.md
zulip_bots/zulip_bots/bots/link_shortener/doc.md
# Link Shortener Bot
Link Shortener Bot is a Zulip bot that will shorten URLs ("links") in a
-conversation. It uses the [goo.gl URL shortener API] to shorten its links.
+conversation. It uses the [bitly URL shortener API] to shorten its links.
-Use [this](https://developers.google.com/url-shortener/v1/getting_started) to get
-your API Key.
+Use [this](https://dev.bitly.com/get_started.html) to get your API Key.
Links can be anywhere in the message, for example,
@@ -15,6 +14,6 @@ Links can be anywhere in the message, for example,
and LS Bot would respond
> https://github.com/zulip/python-zulip-api/tree/master/zulip_bots/zulip_bots/bots:
- > **https://goo.gl/NjLZZH**
+ > **https://bit.ly/2FF3QHu**
-[goo.gl URL shortener API]: https://goo.gl
+[bitly URL shortener API]: https://bitly.com/

ADD
zulip_bots/zulip_bots/bots/link_shortener/fixtures/test_invalid_access_token.json
+{
+ "request": {
+ "api_url": "https://api-ssl.bitly.com/v3/shorten",
+ "method": "GET",
+ "params": {
+ "access_token": "qwertyuiopx",
+ "longUrl": "www.youtube.com/watch"
+ }
+ },
+ "response": {
+ "status_code": 500,
+ "status_txt": "INVALID_ARG_ACCESS_TOKEN",
+ "data": []
+ },
+ "response-headers": {
+ "content-type": "application/json; charset=utf-8"
+ }
+}

DELETE
zulip_bots/zulip_bots/bots/link_shortener/fixtures/test_invalid_key.json
-{
- "request": {
- "api_url": "https://www.googleapis.com/urlshortener/v1/url",
- "method": "POST",
- "params": {
- "key": "qwertyuiopx"
- },
- "json": {
- "longUrl": "www.youtube.com/watch"
- }
- },
- "response": {
- "error":{
- "errors":[
- {
- "reason":"keyInvalid"
- }
- ]
- },
- "code": 400,
- "message": "Bad Request"
- },
- "response-headers": {
- "status": 400,
- "content-type": "application/json; charset=utf-8"
- }
-}

MODIFY
zulip_bots/zulip_bots/bots/link_shortener/fixtures/test_normal.json
zulip_bots/zulip_bots/bots/link_shortener/fixtures/test_normal.json
{
"request": {
- "api_url": "https://www.googleapis.com/urlshortener/v1/url",
- "method": "POST",
+ "api_url": "https://api-ssl.bitly.com/v3/shorten",
+ "method": "GET",
"params": {
- "key": "qwertyuiop"
- },
- "json": {
+ "access_token": "qwertyuiop",
"longUrl": "https://www.github.com/zulip/zulip"
}
},
"response": {
- "id": "https://goo.gl/6uoWKb"
+ "status_code": 200,
+ "status_txt": "OK",
+ "data": {
+ "url": "http://bit.ly/2Ht2hOI",
+ "hash": "2Ht2hOI",
+ "global_hash": "3j4ir4",
+ "long_url": "https://www.github.com/zulip/zulip/",
+ "new_hash": 0
+ }
},
"response-headers": {
"status": 200,

MODIFY
zulip_bots/zulip_bots/bots/link_shortener/link_shortener.py
zulip_bots/zulip_bots/bots/link_shortener/link_shortener.py
@@ -20,18 +20,16 @@ class LinkShortenerHandler(object):
self.check_api_key(bot_handler)
def check_api_key(self, bot_handler: Any) -> None:
- test_request = requests.post(
- 'https://www.googleapis.com/urlshortener/v1/url',
- json={'longUrl': 'www.youtube.com/watch'},
- params={'key': self.config_info['key']}
- ) # type: Any
- test_request_data = test_request.json()
+ test_request_data = self.call_link_shorten_service('www.youtube.com/watch') # type: Any
try:
- if test_request_data['error']['errors'][0]['reason'] == 'keyInvalid':
+ if self.is_invalid_token_error(test_request_data):
bot_handler.quit('Invalid key. Follow the instructions in doc.md for setting API key.')
except KeyError:
pass
+ def is_invalid_token_error(self, response_json: Any) -> bool:
+ return response_json['status_code'] == 500 and response_json['status_txt'] == 'INVALID_ARG_ACCESS_TOKEN'
+
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None:
REGEX_STR = (
'('
@@ -83,15 +81,24 @@ class LinkShortenerHandler(object):
long_url (str): The original URL to shorten.
'''
- body = {'longUrl': long_url}
- params = {'key': self.config_info['key']}
-
- request = requests.post(
- 'https://www.googleapis.com/urlshortener/v1/url',
- json=body,
- params=params
+ response_json = self.call_link_shorten_service(long_url)
+ if response_json['status_code'] == 200 and self.has_shorten_url(response_json):
+ shorten_url = self.get_shorten_url(response_json)
+ else:
+ shorten_url = ''
+ return shorten_url
+
+ def call_link_shorten_service(self, long_url: str) -> Any:
+ response = requests.get(
+ 'https://api-ssl.bitly.com/v3/shorten',
+ params={'access_token': self.config_info['key'], 'longUrl': long_url}
)
+ return response.json()
+
+ def has_shorten_url(self, response_json: Any) -> bool:
+ return 'data' in response_json and 'url' in response_json['data']
- return request.json().get('id', '')
+ def get_shorten_url(self, response_json: Any) -> str:
+ return response_json['data']['url']
handler_class = LinkShortenerHandler

MODIFY
zulip_bots/zulip_bots/bots/link_shortener/test_link_shortener.py
zulip_bots/zulip_bots/bots/link_shortener/test_link_shortener.py
@@ -12,19 +12,19 @@ class TestLinkShortenerBot(BotTestCase):
self.verify_reply(message, response)
def test_bot_responds_to_empty_message(self) -> None:
- with patch('requests.post'):
+ with patch('requests.get'):
self._test('', 'No links found. Send "help" to see usage instructions.')
def test_normal(self) -> None:
with self.mock_http_conversation('test_normal'):
self._test('Shorten https://www.github.com/zulip/zulip please.',
- 'https://www.github.com/zulip/zulip: https://goo.gl/6uoWKb')
+ 'https://www.github.com/zulip/zulip: http://bit.ly/2Ht2hOI')
def test_no_links(self) -> None:
# No `mock_http_conversation` is necessary because the bot will
# recognize that no links are in the message and won't make any HTTP
# requests.
- with patch('requests.post'):
+ with patch('requests.get'):
self._test('Shorten nothing please.',
'No links found. Send "help" to see usage instructions.')
@@ -32,7 +32,7 @@ class TestLinkShortenerBot(BotTestCase):
# No `mock_http_conversation` is necessary because the bot will
# recognize that the message is 'help' and won't make any HTTP
# requests.
- with patch('requests.post'):
+ with patch('requests.get'):
self._test('help',
('Mention the link shortener bot in a conversation and then '
'enter any URLs you want to shorten in the body of the message.'))
@@ -40,6 +40,6 @@ class TestLinkShortenerBot(BotTestCase):
def test_exception_when_api_key_is_invalid(self)-> None:
bot_test_instance = LinkShortenerHandler()
with self.mock_config_info({'key': 'qwertyuiopx'}):
- with self.mock_http_conversation('test_invalid_key'):
+ with self.mock_http_conversation('test_invalid_access_token'):
with self.assertRaises(StubBotHandler.BotQuitException):
bot_test_instance.initialize(StubBotHandler())

link_shortener: Migrate from goo.gl to bit.ly service.

Shorten URLs by using bit.ly service instead of goo.gl service.

Fixes #367