smashed updated

This commit is contained in:
root committed 2025-10-16 16:23:36 +00:00
1 parent 77921ba6a8
commit 1da0b26320
14 files changed
+321 -96

No files matched your search

+48 -8
View File
@@ -8,7 +8,7 @@ from datetime import datetime
from pathlib import Path
from typing import List, Optional, Tuple
from sqlalchemy import select
from sqlalchemy import select, and_, or_
from app.core.logger import make_log
from app.core.storage import db_session
@@ -196,17 +196,45 @@ async def _convert_content(ec: EncryptedContent, staging: PlainStaging):
plain_filename = f"{ec.encrypted_cid}.{input_ext}" if input_ext else ec.encrypted_cid
async with db_session() as session:
existing = (await session.execute(select(StoredContent).where(StoredContent.hash == file_hash))).scalars().first()
if not existing:
if existing:
sc = existing
sc.type = sc.type or "local/content_bin"
sc.filename = plain_filename
sc.meta = {
**(sc.meta or {}),
'encrypted_cid': ec.encrypted_cid,
'kind': 'original',
'content_type': ec.content_type,
}
sc.updated = datetime.utcnow()
else:
sc = StoredContent(
type="local/content_bin",
hash=file_hash,
user_id=None,
filename=plain_filename,
meta={'encrypted_cid': ec.encrypted_cid, 'kind': 'original'},
meta={
'encrypted_cid': ec.encrypted_cid,
'kind': 'original',
'content_type': ec.content_type,
},
created=datetime.utcnow(),
)
session.add(sc)
await session.flush()
encrypted_records = (await session.execute(select(StoredContent).where(StoredContent.hash == encrypted_hash_b58))).scalars().all()
for encrypted_sc in encrypted_records:
meta = dict(encrypted_sc.meta or {})
converted = dict(meta.get('converted_content') or {})
converted['original'] = file_hash
meta['converted_content'] = converted
if 'content_type' not in meta:
meta['content_type'] = ec.content_type
encrypted_sc.meta = meta
encrypted_sc.decrypted_content_id = sc.id
encrypted_sc.updated = datetime.utcnow()
derivative = ContentDerivative(
content_id=ec.id,
kind='decrypted_original',
@@ -341,10 +369,17 @@ async def _convert_content(ec: EncryptedContent, staging: PlainStaging):
async def _pick_pending(limit: int) -> List[Tuple[EncryptedContent, PlainStaging]]:
async with db_session() as session:
# Find A/V contents with preview_enabled and no ready low/low_preview derivatives yet
ecs = (await session.execute(select(EncryptedContent).where(
EncryptedContent.preview_enabled == True
).order_by(EncryptedContent.created_at.desc()))).scalars().all()
# Include preview-enabled media and non-media content that need decrypted originals
non_media_filter = and_(
EncryptedContent.content_type.isnot(None),
~EncryptedContent.content_type.like('audio/%'),
~EncryptedContent.content_type.like('video/%'),
)
ecs = (await session.execute(
select(EncryptedContent)
.where(or_(EncryptedContent.preview_enabled == True, non_media_filter))
.order_by(EncryptedContent.created_at.desc())
)).scalars().all()
picked: List[Tuple[EncryptedContent, PlainStaging]] = []
for ec in ecs:
@@ -365,7 +400,12 @@ async def _pick_pending(limit: int) -> List[Tuple[EncryptedContent, PlainStaging
# Check if derivatives already ready
rows = (await session.execute(select(ContentDerivative).where(ContentDerivative.content_id == ec.id))).scalars().all()
kinds_ready = {r.kind for r in rows if r.status == 'ready'}
required = {'decrypted_low', 'decrypted_high'} if ec.content_type.startswith('audio/') else {'decrypted_low', 'decrypted_high', 'decrypted_preview'}
if ec.content_type.startswith('audio/'):
required = {'decrypted_low', 'decrypted_high'}
elif ec.content_type.startswith('video/'):
required = {'decrypted_low', 'decrypted_high', 'decrypted_preview'}
else:
required = {'decrypted_original'}
if required.issubset(kinds_ready):
continue
# Always decrypt from IPFS using local or remote key
+4 -1
View File
@@ -86,11 +86,14 @@ async def indexer_loop(memory, platform_found: bool, seqno: int) -> [bool, int]:
wallet_owner_user = await session.get(User, wallet_owner_connection.user_id) if wallet_owner_connection else None
if wallet_owner_user.telegram_id:
wallet_owner_bot = Wrapped_CBotChat(memory._telegram_bot, chat_id=wallet_owner_user.telegram_id, user=wallet_owner_user, db_session=session)
meta_title = content_metadata.get('title') or content_metadata.get('name') or 'Unknown'
meta_artist = content_metadata.get('artist')
formatted_title = f"{meta_artist} – {meta_title}" if meta_artist else meta_title
await wallet_owner_bot.send_message(
user.translated('p_licenseWasBought').format(
username=user.front_format(),
nft_address=f'"https://tonviewer.com/{new_license.onchain_address}"',
content_title=content_metadata.get('name', 'Unknown'),
content_title=formatted_title,
),
message_type='notification',
)
+21 -7
View File
@@ -115,6 +115,7 @@ def _clean_text_content(text: str, is_hashtag: bool = False) -> str:
async def create_metadata_for_item(
db_session,
title: str = None,
artist: str = None,
cover_url: str = None,
authors: list = None,
hashtags: list = [],
@@ -128,6 +129,15 @@ async def create_metadata_for_item(
cleaned_title = cleaned_title[:100].strip() # Truncate and strip after cleaning
assert len(cleaned_title) > 3, f"Cleaned title '{cleaned_title}' (from original '{title}') is too short or became empty after cleaning."
cleaned_artist = None
if artist:
cleaned_artist = _clean_text_content(artist, is_hashtag=False)
cleaned_artist = cleaned_artist[:100].strip()
if not cleaned_artist:
cleaned_artist = None
display_name = f"{cleaned_artist} – {cleaned_title}" if cleaned_artist else cleaned_title
# Process and clean hashtags
processed_hashtags = []
if hashtags and isinstance(hashtags, list):
@@ -142,17 +152,21 @@ async def create_metadata_for_item(
processed_hashtags = list(dict.fromkeys(processed_hashtags))[:10]
item_metadata = {
'name': cleaned_title,
'attributes': [
# {
# 'trait_type': 'Artist',
# 'value': 'Unknown'
# },
],
'name': display_name,
'title': cleaned_title,
'display_name': display_name,
'downloadable': downloadable,
'tags': processed_hashtags, # New field for storing the list of cleaned hashtags
'attributes': [],
}
if cleaned_artist:
item_metadata['artist'] = cleaned_artist
item_metadata['attributes'].append({
'trait_type': 'Artist',
'value': cleaned_artist,
})
# Generate description from the processed hashtags
item_metadata['description'] = ' '.join([f"#{h}" for h in processed_hashtags if h])
+17 -25
View File
@@ -1,4 +1,3 @@
import html
from sqlalchemy import and_, select
from app.core.models.node_storage import StoredContent
from app.core.models.content.user_content import UserContent, UserAction
@@ -26,7 +25,6 @@ class PlayerTemplates:
text = ""
content_metadata_json = {}
description_block = ""
status_hint = ""
if content:
assert content.type.startswith('onchain/content'), "Invalid nodeStorage content type"
cd_log = f"Content (SHA256: {content.hash}), Encrypted: {content.encrypted}, TelegramCID: {content.telegram_cid}. "
@@ -114,9 +112,6 @@ class PlayerTemplates:
if encrypted_content_row:
break
if not local_content:
status_hint = self.user.translated('p_playerContext_contentNotReady')
description = (content_metadata_json.get('description') or '').strip()
encrypted_description = (encrypted_content_row.description or '').strip() if encrypted_content_row and encrypted_content_row.description else ''
if not description and encrypted_description:
@@ -124,18 +119,24 @@ class PlayerTemplates:
if description:
description_block = f"{description}\n"
title = (
content_metadata_json.get('name')
or (encrypted_content_row.title if encrypted_content_row and encrypted_content_row.title else None)
or (local_content.filename if local_content else None)
or (content.filename if content else None)
or content.cid.serialize_v2()
)
status_block = f"{status_hint}\n" if status_hint else ""
metadata_title = content_metadata_json.get('title') or content_metadata_json.get('name')
if not metadata_title:
metadata_title = (
(encrypted_content_row.title if encrypted_content_row and encrypted_content_row.title else None)
or (local_content.filename if local_content else None)
or (content.filename if content else None)
or content.cid.serialize_v2()
)
metadata_artist = content_metadata_json.get('artist')
if metadata_artist in ('', None):
metadata_artist = None
if not metadata_artist:
encrypted_artist = getattr(encrypted_content_row, 'artist', None)
metadata_artist = encrypted_artist if encrypted_artist else metadata_artist
title = f"{metadata_artist} – {metadata_title}" if metadata_artist else metadata_title
text = f"""<b>{title}</b>
{description_block}{status_block}Этот контент был загружен в MY
{description_block}Этот контент был загружен в MY
\t/ p2p content market /
<blockquote><a href="{content_share_link['url']}">🔴 «открыть в MY»</a></blockquote>"""
@@ -152,16 +153,7 @@ class PlayerTemplates:
)
)).scalars().all()
if not local_content:
if not processing_messages:
notice = f"Контент «{html.escape(title)}» обрабатывается. Как только всё будет готово, отправим полную публикацию."
await self.send_message(
notice,
message_type='content/processing',
message_meta={'content_id': content.id},
content_id=content.id,
)
else:
if local_content and processing_messages:
for msg in processing_messages:
await self.delete_message(msg.message_id)
+1
View File
@@ -16,6 +16,7 @@ class EncryptedContent(AlchemyBase):
# Public metadata
title = Column(String(512), nullable=False)
artist = Column(String(512), nullable=True)
description = Column(String(4096), nullable=True)
content_type = Column(String(64), nullable=False) # e.g. audio/flac, video/mp4, application/octet-stream