fixes
This commit is contained in:
parent
3035a39083
commit
a836196a47
|
|
@ -139,6 +139,9 @@ async def t_inline_query_node_content(query: types.InlineQuery, memory=None, use
|
||||||
audio_url=decrypted_content.web_url + '?seconds_limit=30',
|
audio_url=decrypted_content.web_url + '?seconds_limit=30',
|
||||||
title=title,
|
title=title,
|
||||||
performer=performer,
|
performer=performer,
|
||||||
|
caption=user.translated('p_playerContext_preview'),
|
||||||
|
# audio_duration=
|
||||||
|
parse_mode='html',
|
||||||
reply_markup=get_inline_keyboard([
|
reply_markup=get_inline_keyboard([
|
||||||
[{
|
[{
|
||||||
'text': user.translated('shareTrack_button'),
|
'text': user.translated('shareTrack_button'),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from pydub import AudioSegment
|
||||||
|
|
||||||
|
from app.core._config import UPLOADS_DIR
|
||||||
|
from app.core.logger import make_log
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
class AudioContentMixin:
|
||||||
|
def as_audio_segment(self) -> AudioSegment:
|
||||||
|
audio = None
|
||||||
|
open_log = f"StoredContent.as_audio_segment({self.id}): " + '\n'
|
||||||
|
file_ext = self.filename.split('.')[-1]
|
||||||
|
if not audio:
|
||||||
|
try:
|
||||||
|
if file_ext == 'mp3':
|
||||||
|
audio = AudioSegment.from_mp3(self.filepath)
|
||||||
|
elif file_ext == 'wav':
|
||||||
|
audio = AudioSegment.from_wav(self.filepath)
|
||||||
|
elif file_ext == 'ogg':
|
||||||
|
audio = AudioSegment.from_ogg(self.filepath)
|
||||||
|
elif file_ext == 'flv':
|
||||||
|
audio = AudioSegment.from_flv(self.filepath)
|
||||||
|
except BaseException as e:
|
||||||
|
open_log += f"Error loading audio from file (using encoding): {e}" + '\n' + traceback.format_exc()
|
||||||
|
|
||||||
|
if not audio:
|
||||||
|
try:
|
||||||
|
audio = AudioSegment.from_file(self.filepath)
|
||||||
|
except BaseException as e:
|
||||||
|
open_log += f"Error loading audio from file: {e}" + '\n' + traceback.format_exc()
|
||||||
|
|
||||||
|
if not audio:
|
||||||
|
try:
|
||||||
|
audio = AudioSegment(self.file_bin)
|
||||||
|
except BaseException as e:
|
||||||
|
open_log += f"Error loading audio from binary: {e}" + '\n' + traceback.format_exc()
|
||||||
|
|
||||||
|
make_log("Storage", open_log, level="debug")
|
||||||
|
assert audio, "Can't load audio as AudioSegment"
|
||||||
|
return audio
|
||||||
|
|
||||||
|
def as_mp3(self, seconds_limit=None):
|
||||||
|
tempfile_path = os.path.join(UPLOADS_DIR, f"temporary_{self.hash}.mp3")
|
||||||
|
audio = self.as_audio_segment()
|
||||||
|
if seconds_limit:
|
||||||
|
seconds_limit = int(seconds_limit)
|
||||||
|
tempfile_path += f"_f{seconds_limit}"
|
||||||
|
|
||||||
|
if not os.path.exists(tempfile_path):
|
||||||
|
try:
|
||||||
|
cover_content = self.__class__.from_cid(self.meta.get('cover_cid'))
|
||||||
|
cover_tempfile_path = cover_content.as_jpeg()
|
||||||
|
except BaseException as e:
|
||||||
|
make_log("Storage", f"Error getting cover content: {e}", level="debug")
|
||||||
|
cover_content = None
|
||||||
|
cover_tempfile_path = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
audio = audio[:seconds_limit * 1000] if seconds_limit else audio
|
||||||
|
audio.export(tempfile_path, format="mp3", cover=cover_tempfile_path)
|
||||||
|
except BaseException as e:
|
||||||
|
make_log("Storage", f"Error converting audio: {e}" + '\n' + traceback.format_exc(), level="error")
|
||||||
|
|
||||||
|
assert os.path.exists(tempfile_path), "Can't convert audio to mp3"
|
||||||
|
|
||||||
|
return tempfile_path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
from app.core._config import UPLOADS_DIR
|
||||||
|
from app.core.logger import make_log
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
class ImageContentMixin:
|
||||||
|
def as_jpeg(self) -> str:
|
||||||
|
tempfile_path = os.path.join(UPLOADS_DIR, f"temporary_{self.hash}.jpeg")
|
||||||
|
if not os.path.exists(tempfile_path):
|
||||||
|
cover_image = Image.open(self.filepath)
|
||||||
|
cover_image = cover_image.convert('RGB')
|
||||||
|
quality = 95
|
||||||
|
while quality > 10:
|
||||||
|
cover_image.save(tempfile_path, 'JPEG', quality=quality)
|
||||||
|
if os.path.getsize(tempfile_path) <= 200 * 1024:
|
||||||
|
break
|
||||||
|
|
||||||
|
quality -= 5
|
||||||
|
|
||||||
|
assert os.path.exists(tempfile_path), "Image not found"
|
||||||
|
|
||||||
|
return tempfile_path
|
||||||
|
|
@ -28,6 +28,7 @@ class UserContent(AlchemyBase, UserContentIndexationMixin):
|
||||||
wallet_connection = relationship('WalletConnection', uselist=False, foreign_keys=[wallet_connection_id])
|
wallet_connection = relationship('WalletConnection', uselist=False, foreign_keys=[wallet_connection_id])
|
||||||
content = relationship('StoredContent', uselist=False, foreign_keys=[content_id])
|
content = relationship('StoredContent', uselist=False, foreign_keys=[content_id])
|
||||||
|
|
||||||
|
|
||||||
class UserAction(AlchemyBase):
|
class UserAction(AlchemyBase):
|
||||||
__tablename__ = 'users_actions'
|
__tablename__ = 'users_actions'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,13 @@ from app.core.logger import make_log
|
||||||
from app.core._config import UPLOADS_DIR, PROJECT_HOST
|
from app.core._config import UPLOADS_DIR, PROJECT_HOST
|
||||||
import os
|
import os
|
||||||
from app.core.content.content_id import ContentId
|
from app.core.content.content_id import ContentId
|
||||||
|
from app.core.content.audio import AudioContentMixin
|
||||||
|
from app.core.content.image import ImageContentMixin
|
||||||
# from app.core.models.content.indexation_mixins import NodeStorageIndexationMixin
|
# from app.core.models.content.indexation_mixins import NodeStorageIndexationMixin
|
||||||
from .base import AlchemyBase
|
from .base import AlchemyBase
|
||||||
|
|
||||||
|
|
||||||
class StoredContent(AlchemyBase):
|
class StoredContent(AlchemyBase, AudioContentMixin):
|
||||||
__tablename__ = 'node_storage'
|
__tablename__ = 'node_storage'
|
||||||
|
|
||||||
id = Column(Integer, autoincrement=True, primary_key=True)
|
id = Column(Integer, autoincrement=True, primary_key=True)
|
||||||
|
|
@ -68,6 +70,31 @@ class StoredContent(AlchemyBase):
|
||||||
|
|
||||||
return bool(self.key_id or self.decrypted_content_id)
|
return bool(self.key_id or self.decrypted_content_id)
|
||||||
|
|
||||||
|
def open_content(self, db_session, content_type=None):
|
||||||
|
try:
|
||||||
|
# Получение StoredContent в прод-виде с указанием типа данных и доступный для перевода в другие форматы
|
||||||
|
decrypted_content = self if not self.encrypted else None
|
||||||
|
encrypted_content = self if self.encrypted else None
|
||||||
|
content_type = None
|
||||||
|
if not decrypted_content:
|
||||||
|
decrypted_content = db_session.query(StoredContent).filter(StoredContent.id == self.decrypted_content_id).first()
|
||||||
|
else:
|
||||||
|
encrypted_content = db_session.query(StoredContent).filter(StoredContent.decrypted_content_id == self.id).first()
|
||||||
|
|
||||||
|
assert decrypted_content, "Can't get decrypted content"
|
||||||
|
assert encrypted_content, "Can't get encrypted content"
|
||||||
|
content_type = content_type or decrypted_content.json_format()['content_type']
|
||||||
|
content_type, content_encoding = content_type.split('/')
|
||||||
|
|
||||||
|
return {
|
||||||
|
'encrypted_content': encrypted_content,
|
||||||
|
'decrypted_content': decrypted_content,
|
||||||
|
'content_type': content_type or 'application/x-binary'
|
||||||
|
}
|
||||||
|
except BaseException as e:
|
||||||
|
make_log("NodeStorage.open_content", f"Can't open content: {self.id} {e}", level='error')
|
||||||
|
raise e
|
||||||
|
|
||||||
def json_format(self):
|
def json_format(self):
|
||||||
extra_fields = {}
|
extra_fields = {}
|
||||||
if self.btfs_cid:
|
if self.btfs_cid:
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -128,7 +128,8 @@ msgstr "⚠️ <b>Unsupported content</b>"
|
||||||
#: app/core/models/_telegram/templates/player.py:111
|
#: app/core/models/_telegram/templates/player.py:111
|
||||||
msgid "p_playerContext_purchaseRequested"
|
msgid "p_playerContext_purchaseRequested"
|
||||||
msgstr "Confirm the purchase in your wallet. After that, you will be able to "
|
msgstr "Confirm the purchase in your wallet. After that, you will be able to "
|
||||||
"listen to the full track version."
|
"listen to the full track version.\n\n"
|
||||||
|
"<b>This can take up to few minutes</b>"
|
||||||
|
|
||||||
#: app/core/models/_telegram/templates/player.py:114
|
#: app/core/models/_telegram/templates/player.py:114
|
||||||
msgid "buyTrackListenLicense_button"
|
msgid "buyTrackListenLicense_button"
|
||||||
|
|
@ -149,7 +150,7 @@ msgstr "Error: content price is not set"
|
||||||
|
|
||||||
#: app/client_bot/routers/content.py:133
|
#: app/client_bot/routers/content.py:133
|
||||||
msgid "viewTrack_button"
|
msgid "viewTrack_button"
|
||||||
msgstr "View track"
|
msgstr "Buy track"
|
||||||
|
|
||||||
#: app/client_bot/routers/content.py:138
|
#: app/client_bot/routers/content.py:138
|
||||||
msgid "cancelPurchase_button"
|
msgid "cancelPurchase_button"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue