mirror of
https://github.com/NovaOSS/nova-api.git
synced 2024-11-25 16:13:58 +01:00
Compare commits
4 commits
0d0453291f
...
d3d9ead8f4
Author | SHA1 | Date | |
---|---|---|---|
d3d9ead8f4 | |||
1384b3add8 | |||
453c6e7430 | |||
4673b23055 |
|
@ -4,7 +4,7 @@
|
|||
# git commit -am "Auto-trigger - Production server started" && git push origin Production
|
||||
|
||||
# backup database
|
||||
/usr/local/bin/python /home/nova-api/backup_manager/main.py pre_prodpush
|
||||
/usr/local/bin/python /home/nova-api/api/backup_manager/main.py pre_prodpush
|
||||
|
||||
# Kill production server
|
||||
fuser -k 2333/tcp
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
from dotenv import load_dotenv
|
||||
import os
|
||||
from motor.motor_asyncio import AsyncIOMotorClient
|
||||
from bson import json_util
|
||||
import json
|
||||
from sys import argv
|
||||
import asyncio
|
||||
|
||||
from sys import argv
|
||||
from bson import json_util
|
||||
from dotenv import load_dotenv
|
||||
from motor.motor_asyncio import AsyncIOMotorClient
|
||||
|
||||
load_dotenv()
|
||||
|
||||
MONGO_URI = os.getenv("MONGO_URI")
|
||||
MONGO_URI = os.environ['MONGO_URI']
|
||||
FILE_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
async def main(output_dir):
|
||||
async def main(output_dir: str):
|
||||
await make_backup(output_dir)
|
||||
|
||||
async def make_backup(output_dir):
|
||||
output_dir = os.path.join(FILE_DIR, "..", "backups", output_dir)
|
||||
async def make_backup(output_dir: str):
|
||||
output_dir = os.path.join(FILE_DIR, '..', 'backups', output_dir)
|
||||
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
@ -25,26 +26,29 @@ async def make_backup(output_dir):
|
|||
databases = {db: await client[db].list_collection_names() for db in databases}
|
||||
|
||||
for database in databases:
|
||||
if not os.path.exists(f"{output_dir}/{database}"):
|
||||
os.mkdir(f"{output_dir}/{database}")
|
||||
if database == 'local':
|
||||
continue
|
||||
|
||||
if not os.path.exists(f'{output_dir}/{database}'):
|
||||
os.mkdir(f'{output_dir}/{database}')
|
||||
|
||||
for collection in databases[database]:
|
||||
print(f"Making backup for {database}/{collection}")
|
||||
print(f'Making backup for {database}/{collection}')
|
||||
await make_backup_for_collection(database, collection, output_dir)
|
||||
|
||||
async def make_backup_for_collection(database, collection, output_dir):
|
||||
path = f"{output_dir}/{database}/{collection}.json"
|
||||
path = f'{output_dir}/{database}/{collection}.json'
|
||||
|
||||
client = AsyncIOMotorClient(MONGO_URI)
|
||||
collection = client[database][collection]
|
||||
documents = await collection.find({}).to_list(length=None)
|
||||
|
||||
with open(path, "w") as f:
|
||||
with open(path, 'w') as f:
|
||||
json.dump(documents, f, default=json_util.default)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
if len(argv) < 2 or len(argv) > 2:
|
||||
print("Usage: python3 main.py <output_dir>")
|
||||
print('Usage: python3 main.py <output_dir>')
|
||||
exit(1)
|
||||
|
||||
output_dir = argv[1]
|
||||
|
|
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,8 @@ 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:
|
||||
config = yaml.safe_load(f)
|
||||
|
@ -70,6 +71,9 @@ async def handle(incoming_request: fastapi.Request):
|
|||
if ban_reason:
|
||||
return await errors.error(403, f'Your NovaAI account has been banned. Reason: \'{ban_reason}\'.', 'Contact the staff for an appeal.')
|
||||
|
||||
if 'account/credits' in path:
|
||||
return fastapi.responses.JSONResponse({'credits': user['credits']})
|
||||
|
||||
costs = config['costs']
|
||||
cost = costs['other']
|
||||
|
||||
|
@ -149,6 +153,9 @@ async def handle(incoming_request: fastapi.Request):
|
|||
|
||||
media_type = 'text/event-stream' if payload.get('stream', False) else 'application/json'
|
||||
|
||||
if (model := payload.get('model')) not in models and model is not None:
|
||||
return await errors.error(404, 'Model not found.', 'Check the model name and try again.')
|
||||
|
||||
return fastapi.responses.StreamingResponse(
|
||||
content=responder.respond(
|
||||
user=user,
|
||||
|
|
|
@ -217,8 +217,8 @@ async def demo():
|
|||
print('Checking streamed chat completions...')
|
||||
print(await test_chat_stream_gpt3())
|
||||
|
||||
print('[lightblue]Checking if image generation works...')
|
||||
print(await test_image_generation())
|
||||
# print('[lightblue]Checking if image generation works...')
|
||||
# print(await test_image_generation())
|
||||
|
||||
print('Checking the models endpoint...')
|
||||
print(await test_models())
|
||||
|
|
Loading…
Reference in a new issue