Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a bot to fetch crytpo information. #753

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
87 changes: 87 additions & 0 deletions zulip_bots/zulip_bots/bots/crypto/crypto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# bot to fetch crypto information from coinbase API.
# No API key authentication is required for pricing
# and time information.

from datetime import datetime
from typing import Any, Dict

import requests
from requests.exceptions import ConnectionError, HTTPError

from zulip_bots.lib import BotHandler


class CryptoHandler:
"""
This bot will get the current spot "market" exchange rate for a given
cryptocurrency in USD.
"""
def usage(self):
return """
This bot allows users to get spot prices for requested cryptocurrencies in USD.
Users should @-mention the bot with the following format:
@-mention <cryptocurrency abbreviation> <optional: date in format YYYY-MM-DD>
i.e., "@-mention BTC 2022-04-16" or just "@-mention BTC"
"""

def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler):
original_content = message["content"]
args = original_content.split()
if len(args) == 0 or len(args) > 2:
bot_handler.send_reply(message, self.usage())
return

date_param = None
if len(args) == 2:
date_param = {"date": args[1]}

# check format of date input
if date_param:
format = "%Y-%m-%d"

try:
datetime.strptime(date_param["date"], format)
except ValueError:
reply = "Dates should be in the form YYYY-MM-DD."
bot_handler.send_reply(message, reply)
return

currency_param = args[0]

try:
if date_param:
response = requests.get(
"https://api.coinbase.com/v2/prices/{}-USD/spot".format(currency_param),
params=date_param
)
else:
response = requests.get(
"https://api.coinbase.com/v2/prices/{}-USD/spot".format(currency_param)
)

# raise exception for bad status codes
response.raise_for_status()
except (HTTPError, ConnectionError):
reply = (
"Sorry, I wasn't able to find anything on {}. "
"Check your spelling and try again."
).format(currency_param)

bot_handler.send_reply(message, reply)
return

market_price = response.json()["data"]["amount"]

if date_param:
reply = (
"The market price for {} on {} was ${}"
).format(currency_param, date_param["date"], market_price)
else:
reply = (
"The current market price for {} is ${}"
).format(currency_param, market_price)

bot_handler.send_reply(message, reply)


handler_class = CryptoHandler
18 changes: 18 additions & 0 deletions zulip_bots/zulip_bots/bots/crypto/doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# crypto bot

The crypto bot is a Zulip bot that can fetch the
current market price for a specified cryptocurrency in USD.
The crypto bot can also retrieve a market price for
a cryptocurrency from a given date in the form YYYY-MM-DD.

To get the current market price:
```
@crypto BTC
> The current market price for BTC is $40696.73
```

To get the price on a given date:
```
@crypto BTC 2022-04-16
> The market price for BTC on 2022-04-16 was $40554.6
```
11 changes: 11 additions & 0 deletions zulip_bots/zulip_bots/bots/crypto/fixtures/test_404.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"request": {
"api_url": "https://api.coinbase.com/v2/prices/XYZ-USD/spot"
},
"response": {},
"response-headers": {
"status": 404,
"ok": false,
"content-type": "application/json; charset=utf-8"
}
}
22 changes: 22 additions & 0 deletions zulip_bots/zulip_bots/bots/crypto/fixtures/test_normal_date.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"request": {
"api_url": "https://api.coinbase.com/v2/prices/BTC-USD/spot",
"params": {
"date": "2022-04-16"
}
},
"response": {
"meta": {
"status": 200
},
"data": {
"amount": 40554.6,
"base" : "BTC",
"currency": "USD"
}
},
"response-headers": {
"status": 200,
"content-type": "application/json; charset=utf-8"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"request": {
"api_url": "https://api.coinbase.com/v2/prices/BTC-USD/spot"
},
"response": {
"meta": {
"status": 200
},
"data": {
"amount": 40696.73,
"base" : "BTC",
"currency": "USD"
}
},
"response-headers": {
"status": 200,
"content-type": "application/json; charset=utf-8"
}
}
57 changes: 57 additions & 0 deletions zulip_bots/zulip_bots/bots/crypto/test_crypto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from zulip_bots.test_lib import BotTestCase, DefaultTests


class TestCryptoBot(BotTestCase, DefaultTests):
bot_name = "crypto"

# Test for correct behavior given proper crypto and date
def test_normal_date(self):
bot_response = "The market price for BTC on 2022-04-16 was $40554.6"

with self.mock_http_conversation("test_normal_date"):
self.verify_reply("BTC 2022-04-16", bot_response)

# test for "current" price
def test_normal_no_date(self):
bot_response = "The current market price for BTC is $40696.73"

with self.mock_http_conversation("test_normal_no_date"):
self.verify_reply("BTC", bot_response)

# test malformatted date
def test_bad_date(self):
bot_response = "Dates should be in the form YYYY-MM-DD."

self.verify_reply("BTC 04-16-2022", bot_response)

# test typo --> Not Found
def test_400_error(self):
bot_response = (
"Sorry, I wasn't able to find anything on XYZ. "
"Check your spelling and try again."
)

with self.mock_http_conversation("test_404"):
self.verify_reply("XYZ", bot_response)

# test empty message
def test_no_inputs(self):
bot_reponse = """
This bot allows users to get spot prices for requested cryptocurrencies in USD.
Users should @-mention the bot with the following format:
@-mention <cryptocurrency abbreviation> <optional: date in format YYYY-MM-DD>
i.e., "@-mention BTC 2022-04-16" or just "@-mention BTC"
"""

self.verify_reply("", bot_reponse)

# test too many arguments
def test_too_many_inputs(self):
bot_response = """
This bot allows users to get spot prices for requested cryptocurrencies in USD.
Users should @-mention the bot with the following format:
@-mention <cryptocurrency abbreviation> <optional: date in format YYYY-MM-DD>
i.e., "@-mention BTC 2022-04-16" or just "@-mention BTC"
"""

self.verify_reply("BTC ETH 2022-04-16", bot_response)