dev@locazia: add blockchain routes, edit resolve content system to cid class, add web2 docs
This commit is contained in:
1 parent
78a4a84c2b
commit
d7ebc26bce
14 files changed
+314
-61
No files matched your search
+4
-2
@@ -16,7 +16,8 @@ from app.api.routes.auth import s_api_v1_auth_twa
|
||||
from app.api.routes.tonconnect import s_api_tonconnect_manifest
|
||||
from app.api.routes.node_storage import s_api_v1_storage_post, s_api_v1_storage_get
|
||||
from app.api.routes.account import s_api_v1_account_get
|
||||
from app.api.routes.custodial import s_api_v1_custodial_upload_content
|
||||
from app.api.routes._blockchain import s_api_v1_blockchain_send_new_content_message, \
|
||||
s_api_v1_blockchain_send_purchase_content_message
|
||||
|
||||
app.add_route(s_index, "/")
|
||||
|
||||
@@ -31,7 +32,8 @@ app.add_route(s_api_v1_storage_get, "/api/v1/storage/<file_hash>", methods=["GET
|
||||
|
||||
app.add_route(s_api_v1_account_get, "/api/v1/account", methods=["GET", "OPTIONS"])
|
||||
|
||||
app.add_route(s_api_v1_custodial_upload_content, "/api/v1/custodial.uploadContent", methods=["POST", "OPTIONS"])
|
||||
app.add_route(s_api_v1_blockchain_send_new_content_message, "/api/v1/blockchain.sendNewContentMessage", methods=["POST", "OPTIONS"])
|
||||
app.add_route(s_api_v1_blockchain_send_purchase_content_message, "/api/v1/blockchain.sendPurchaseContentMessage", methods=["POST", "OPTIONS"])
|
||||
|
||||
|
||||
@app.exception(BaseException)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
from sanic import response
|
||||
|
||||
|
||||
def valid_royalty_params(royalty_params):
|
||||
assert sum([x['value'] for x in royalty_params]) == 10000, "Values of royalties should sum to 10000"
|
||||
for field_key, field_value in {
|
||||
'address': lambda x: isinstance(x, str),
|
||||
'value': lambda x: (isinstance(x, int) and 0 <= x <= 10000)
|
||||
}.items():
|
||||
assert field_key in royalty_params, f"No {field_key} provided"
|
||||
assert field_value(royalty_params[field_key]), f"Invalid {field_key} provided"
|
||||
return True
|
||||
|
||||
|
||||
async def s_api_v1_blockchain_send_new_content_message(request):
|
||||
assert request.json, "No data provided"
|
||||
|
||||
for field_key, field_value in {
|
||||
'title': lambda x: isinstance(x, str),
|
||||
'authors': lambda x: isinstance(x, list),
|
||||
'content': lambda x: isinstance(x, str),
|
||||
'image': lambda x: isinstance(x, str),
|
||||
'description': lambda x: isinstance(x, str),
|
||||
'price': lambda x: (isinstance(x, str) and x.isdigit()),
|
||||
'allowResale': lambda x: isinstance(x, bool),
|
||||
'royaltyParams': lambda x: (isinstance(x, dict) and valid_royalty_params(x)),
|
||||
|
||||
}.items():
|
||||
assert field_key in request.json, f"No {field_key} provided"
|
||||
assert field_value(request.json[field_key]), f"Invalid {field_key} provided"
|
||||
|
||||
assert request.json.get("title"), "No title provided"
|
||||
return response.json({"message": "Transaction requested"})
|
||||
|
||||
|
||||
async def s_api_v1_blockchain_send_purchase_content_message(request):
|
||||
assert request.json, "No data provided"
|
||||
|
||||
for field_key, field_value in {
|
||||
'content_address': lambda x: isinstance(x, str),
|
||||
'price': lambda x: (isinstance(x, str) and x.isdigit()),
|
||||
}.items():
|
||||
assert field_key in request.json, f"No {field_key} provided"
|
||||
assert field_value(request.json[field_key]), f"Invalid {field_key} provided"
|
||||
|
||||
return response.json({"message": "Transaction requested"})
|
||||
@@ -1,36 +0,0 @@
|
||||
from sanic import response
|
||||
from app.core._config import TELEGRAM_API_KEY
|
||||
from app.core.models.user import User
|
||||
from app.core.logger import make_log
|
||||
from datetime import datetime
|
||||
import os
|
||||
import hashlib
|
||||
|
||||
|
||||
async def s_api_v1_custodial_upload_content(request):
|
||||
if not request.json:
|
||||
return response.json({"error": "No data provided"}, status=400)
|
||||
|
||||
if not request.json.get('content'):
|
||||
return response.json({"error": "No content provided"}, status=400)
|
||||
|
||||
if not request.json.get('content_hash'):
|
||||
return response.json({"error": "No content hash provided"}, status=400)
|
||||
|
||||
content = request.json['content']
|
||||
content_hash = request.json['content_hash']
|
||||
|
||||
known_user = request.ctx.db_session.query(User).filter(User.telegram_id == request.ctx.user.telegram_id).first()
|
||||
if not known_user:
|
||||
return response.json({"error": "User not found"}, status=400)
|
||||
|
||||
content_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), f"../../../content/{content_hash}")
|
||||
if os.path.exists(content_path):
|
||||
return response.json({"error": "Content already exists"}, status=400)
|
||||
|
||||
with open(content_path, "wb") as f:
|
||||
f.write(content)
|
||||
|
||||
return response.json({
|
||||
'content_hash': content_hash
|
||||
})
|
||||
@@ -1,10 +1,13 @@
|
||||
from sanic import response
|
||||
from app.core._config import UPLOADS_DIR
|
||||
from app.core.storage import db_session
|
||||
from app.core.content.content_id import ContentId
|
||||
from app.core._utils.resolve_content import resolve_content
|
||||
from app.core.models.node_storage import StoredContent
|
||||
from app.core.logger import make_log
|
||||
from datetime import datetime
|
||||
from base58 import b58encode, b58decode
|
||||
from mimetypes import guess_type
|
||||
import os
|
||||
import hashlib
|
||||
|
||||
@@ -22,13 +25,21 @@ async def s_api_v1_storage_post(request):
|
||||
else:
|
||||
return response.json({"error": "No file provided"}, status=400)
|
||||
|
||||
file_meta = {}
|
||||
file_mimetype, file_encoding = guess_type(file_name)[0]
|
||||
if file_mimetype:
|
||||
file_meta["content_type"] = file_mimetype
|
||||
|
||||
if file_encoding:
|
||||
file_meta["extension_encoding"] = file_encoding
|
||||
|
||||
try:
|
||||
file_hash = b58encode(hashlib.sha256(file_content).digest()).decode()
|
||||
new_content = StoredContent(
|
||||
hash=file_hash,
|
||||
filename=file_name,
|
||||
user_id=None,
|
||||
meta={},
|
||||
meta=file_meta,
|
||||
created=datetime.now(),
|
||||
key_id=None
|
||||
)
|
||||
@@ -39,19 +50,30 @@ async def s_api_v1_storage_post(request):
|
||||
with open(file_path, "wb") as file:
|
||||
file.write(file_content)
|
||||
|
||||
return response.json({"content_sha256": file_hash})
|
||||
new_content_id = new_content.cid
|
||||
new_cid = new_content_id.serialize_v1()
|
||||
|
||||
return response.json({
|
||||
"content_sha256": file_hash,
|
||||
"content_id_v1": new_cid,
|
||||
"content_url": f"dmy://storage?cid={new_cid}",
|
||||
})
|
||||
except BaseException as e:
|
||||
return response.json({"error": f"Error: {e}"}, status=500)
|
||||
|
||||
|
||||
async def s_api_v1_storage_get(request, file_hash):
|
||||
content = request.ctx.db_session.query(StoredContent).filter(StoredContent.hash == file_hash).first()
|
||||
async def s_api_v1_storage_get(request, content_id):
|
||||
cid, errmsg = resolve_content(content_id)
|
||||
if errmsg:
|
||||
return response.json({"error": errmsg}, status=400)
|
||||
|
||||
content_sha256 = b58encode(cid.content_hash).decode()
|
||||
content = request.ctx.db_session.query(StoredContent).filter(StoredContent.hash == content_sha256).first()
|
||||
if not content:
|
||||
return response.json({"error": "File not found"}, status=404)
|
||||
|
||||
make_log(f"File {file_hash} requested by {request.ip}")
|
||||
|
||||
file_path = os.path.join(UPLOADS_DIR, file_hash)
|
||||
make_log(f"File {content_sha256} requested by {request.ip}")
|
||||
file_path = os.path.join(UPLOADS_DIR, content_sha256)
|
||||
if not os.path.exists(file_path):
|
||||
return response.json({"error": "File not found"}, status=404)
|
||||
|
||||
|
||||
Reference in new issue
Block a user