mirror of
https://github.com/NovaOSS/nova-api.git
synced 2024-11-25 16:13:58 +01:00
Added finances endpoint
This commit is contained in:
parent
453c6e7430
commit
1384b3add8
1
api/cache/crypto_prices.json
vendored
Normal file
1
api/cache/crypto_prices.json
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"LTC": 64.665, "_last_updated": 1695334741.4905503, "BTC": 26583.485, "MATIC": 0.52075, "XMR": 146.46058828041404, "ADA": 0.2455, "USDT": 1.000005, "ETH": 1586.115, "USD": 1.0, "EUR": 1.0662838016640013}
|
0
api/models.json → api/cache/models.json
vendored
0
api/models.json → api/cache/models.json
vendored
68
api/core.py
68
api/core.py
|
@ -8,9 +8,12 @@ sys.path.append(project_root)
|
|||
|
||||
# the code above is to allow importing from the root folder
|
||||
|
||||
import time
|
||||
import json
|
||||
import hmac
|
||||
import httpx
|
||||
import fastapi
|
||||
import functools
|
||||
|
||||
from dhooks import Webhook, Embed
|
||||
from dotenv import load_dotenv
|
||||
|
@ -18,7 +21,7 @@ from dotenv import load_dotenv
|
|||
import checks.client
|
||||
|
||||
from helpers import errors
|
||||
from db.users import UserManager
|
||||
from db import users, finances
|
||||
|
||||
load_dotenv()
|
||||
router = fastapi.APIRouter(tags=['core'])
|
||||
|
@ -62,9 +65,7 @@ async def get_users(discord_id: int, incoming_request: fastapi.Request):
|
|||
auth = await check_core_auth(incoming_request)
|
||||
if auth: return auth
|
||||
|
||||
# Get user by discord ID
|
||||
manager = UserManager()
|
||||
user = await manager.user_by_discord_id(discord_id)
|
||||
user = await users.manager.user_by_discord_id(discord_id)
|
||||
if not user:
|
||||
return await errors.error(404, 'Discord user not found in the API database.', 'Check the `discord_id` parameter.')
|
||||
|
||||
|
@ -88,9 +89,7 @@ async def create_user(incoming_request: fastapi.Request):
|
|||
except (json.decoder.JSONDecodeError, AttributeError):
|
||||
return await errors.error(400, 'Invalid or no payload received.', 'The payload must be a JSON object with a `discord_id` key.')
|
||||
|
||||
# Create the user
|
||||
manager = UserManager()
|
||||
user = await manager.create(discord_id)
|
||||
user = await users.manager.create(discord_id)
|
||||
await new_user_webhook(user)
|
||||
|
||||
user['_id'] = str(user['_id'])
|
||||
|
@ -114,9 +113,7 @@ async def update_user(incoming_request: fastapi.Request):
|
|||
'The payload must be a JSON object with a `discord_id` key and an `updates` key.'
|
||||
)
|
||||
|
||||
# Update the user
|
||||
manager = UserManager()
|
||||
user = await manager.update_by_discord_id(discord_id, updates)
|
||||
user = await users.manager.update_by_discord_id(discord_id, updates)
|
||||
|
||||
return user
|
||||
|
||||
|
@ -147,3 +144,54 @@ async def run_checks(incoming_request: fastapi.Request):
|
|||
results[func.__name__] = result
|
||||
|
||||
return results
|
||||
|
||||
async def get_crypto_price(cryptocurrency: str) -> float:
|
||||
"""Gets the price of a cryptocurrency using coinbase's API."""
|
||||
|
||||
if os.path.exists('cache/crypto_prices.json'):
|
||||
with open('cache/crypto_prices.json', 'r') as f:
|
||||
cache = json.load(f)
|
||||
else:
|
||||
cache = {}
|
||||
|
||||
is_old = time.time() - cache.get('_last_updated', 0) > 60 * 60
|
||||
|
||||
if is_old or cryptocurrency not in cache:
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(f'https://api.coinbase.com/v2/prices/{cryptocurrency}-USD/spot')
|
||||
usd_price = float(response.json()['data']['amount'])
|
||||
|
||||
cache[cryptocurrency] = usd_price
|
||||
cache['_last_updated'] = time.time()
|
||||
|
||||
with open('cache/crypto_prices.json', 'w') as f:
|
||||
json.dump(cache, f)
|
||||
|
||||
return cache[cryptocurrency]
|
||||
|
||||
@router.get('/finances')
|
||||
async def get_finances(incoming_request: fastapi.Request):
|
||||
"""Return financial information. Requires a core API key."""
|
||||
|
||||
auth_error = await check_core_auth(incoming_request)
|
||||
if auth_error: return auth_error
|
||||
|
||||
transactions = await finances.manager.get_entire_financial_history()
|
||||
|
||||
for table in transactions:
|
||||
for transaction in transactions[table]:
|
||||
currency = transaction['currency']
|
||||
|
||||
if '-' in currency:
|
||||
currency = currency.split('-')[0]
|
||||
|
||||
amount = transaction['amount']
|
||||
|
||||
if currency == 'mBTC':
|
||||
currency = 'BTC'
|
||||
amount = transaction['amount'] / 1000
|
||||
|
||||
amount_in_usd = await get_crypto_price(currency) * amount
|
||||
transactions[table][transactions[table].index(transaction)]['amount_usd'] = amount_in_usd
|
||||
|
||||
return transactions
|
||||
|
|
39
api/db/finances.py
Normal file
39
api/db/finances.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
import os
|
||||
import asyncio
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from motor.motor_asyncio import AsyncIOMotorClient
|
||||
|
||||
load_dotenv()
|
||||
|
||||
class FinanceManager:
|
||||
def __init__(self):
|
||||
self.conn = AsyncIOMotorClient(os.environ['MONGO_URI'])
|
||||
|
||||
async def _get_collection(self, collection_name: str):
|
||||
return self.conn['finances'][collection_name]
|
||||
|
||||
async def get_entire_financial_history(self):
|
||||
donations_db = await self._get_collection('donations')
|
||||
expenses_db = await self._get_collection('expenses')
|
||||
|
||||
# turn both into JSON-like lists of dicts at once (make sure to fix the _id)
|
||||
history = {'donations': [], 'expenses': []}
|
||||
|
||||
async for donation in donations_db.find():
|
||||
donation['_id'] = str(donation['_id'])
|
||||
history['donations'].append(donation)
|
||||
|
||||
async for expense in expenses_db.find():
|
||||
expense['_id'] = str(expense['_id'])
|
||||
history['expenses'].append(expense)
|
||||
|
||||
# sort all by timestamp
|
||||
history['donations'] = sorted(history['donations'], key=lambda x: x['timestamp'])
|
||||
|
||||
return history
|
||||
|
||||
manager = FinanceManager()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(asyncio.run(manager.get_entire_financial_history()))
|
|
@ -19,7 +19,7 @@ from helpers import tokens, errors, network
|
|||
load_dotenv()
|
||||
|
||||
users = UserManager()
|
||||
models_list = json.load(open('models.json', encoding='utf8'))
|
||||
models_list = json.load(open('cache/models.json', encoding='utf8'))
|
||||
models = [model['id'] for model in models_list['data']]
|
||||
|
||||
with open('config/config.yml', encoding='utf8') as f:
|
||||
|
|
Loading…
Reference in a new issue