Merged in release/async (pull request #49)
Release/async Approved-by: Tiago Ribeiro
This commit is contained in:
13
firebase-debug.log
Normal file
13
firebase-debug.log
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[debug] [2025-01-05T18:01:58.255Z] ----------------------------------------------------------------------
|
||||||
|
[debug] [2025-01-05T18:01:58.257Z] Command: /usr/bin/node /usr/local/bin/firebase login --reauth
|
||||||
|
[debug] [2025-01-05T18:01:58.257Z] CLI Version: 13.28.0
|
||||||
|
[debug] [2025-01-05T18:01:58.257Z] Platform: linux
|
||||||
|
[debug] [2025-01-05T18:01:58.257Z] Node Version: v18.19.1
|
||||||
|
[debug] [2025-01-05T18:01:58.258Z] Time: Sun Jan 05 2025 18:01:58 GMT+0000 (Western European Standard Time)
|
||||||
|
[debug] [2025-01-05T18:01:58.258Z] ----------------------------------------------------------------------
|
||||||
|
[debug]
|
||||||
|
[info]
|
||||||
|
[info] Visit this URL on this device to log in:
|
||||||
|
[info] https://accounts.google.com/o/oauth2/auth?client_id=563584335869-fgrhgmd47bqnekij5i8b5pr03ho849e6.apps.googleusercontent.com&scope=email%20openid%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloudplatformprojects.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Ffirebase%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&response_type=code&state=211115440&redirect_uri=http%3A%2F%2Flocalhost%3A9005&login_hint=carlos.mesquita%40ecrop.dev
|
||||||
|
[info]
|
||||||
|
[info] Waiting for authentication...
|
||||||
@@ -30,7 +30,7 @@ class ConversationPayload(BaseModel):
|
|||||||
name: str
|
name: str
|
||||||
gender: str
|
gender: str
|
||||||
text: str
|
text: str
|
||||||
voice: str
|
voice: Optional[str] = None
|
||||||
|
|
||||||
class Dialog(BaseModel):
|
class Dialog(BaseModel):
|
||||||
conversation: Optional[List[ConversationPayload]] = Field(default_factory=list)
|
conversation: Optional[List[ConversationPayload]] = Field(default_factory=list)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class Entity(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class UserDTO(BaseModel):
|
class UserDTO(BaseModel):
|
||||||
id: uuid.UUID = Field(default_factory=uuid.uuid4)
|
id: str
|
||||||
email: str
|
email: str
|
||||||
name: str
|
name: str
|
||||||
type: str
|
type: str
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import random
|
import random
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any, Union
|
||||||
|
|
||||||
from starlette.datastructures import UploadFile
|
from starlette.datastructures import UploadFile
|
||||||
|
|
||||||
@@ -111,6 +111,15 @@ class ListeningService(IListeningService):
|
|||||||
return dialog
|
return dialog
|
||||||
|
|
||||||
async def generate_mp3(self, dto: Dialog) -> bytes:
|
async def generate_mp3(self, dto: Dialog) -> bytes:
|
||||||
|
convo = dto.conversation
|
||||||
|
voices_assigned = True
|
||||||
|
for segment in convo:
|
||||||
|
if segment.voice is None:
|
||||||
|
voices_assigned = False
|
||||||
|
|
||||||
|
if not voices_assigned:
|
||||||
|
dto = self._get_conversation_voices(dto, True)
|
||||||
|
|
||||||
return await self._tts.text_to_speech(dto)
|
return await self._tts.text_to_speech(dto)
|
||||||
|
|
||||||
async def create_instructions(self, text: str) -> bytes:
|
async def create_instructions(self, text: str) -> bytes:
|
||||||
@@ -263,7 +272,13 @@ class ListeningService(IListeningService):
|
|||||||
)
|
)
|
||||||
return {"dialog": response["monologue"]}
|
return {"dialog": response["monologue"]}
|
||||||
|
|
||||||
def _get_conversation_voices(self, response: Dict, unique_voices_across_segments: bool):
|
# TODO: This was a refactor from the previous ielts-be, don't know why there is a distinction between
|
||||||
|
# section 1 and 3, I think it would make sense to only keep only the section 1 logic, only bringing this up since
|
||||||
|
# there would need to be a refactor of the POST /api/listening/media endpoint which imo is pointless
|
||||||
|
# https://bitbucket.org/ecropdev/ielts-be/src/676f660f3e80220e3db0418dbeef0b1c0f257edb/helper/exercises.py?at=release%2Fmongodb-migration
|
||||||
|
"""
|
||||||
|
def generate_listening_1_conversation(topic: str):
|
||||||
|
...
|
||||||
chosen_voices = []
|
chosen_voices = []
|
||||||
name_to_voice = {}
|
name_to_voice = {}
|
||||||
for segment in response['conversation']:
|
for segment in response['conversation']:
|
||||||
@@ -273,17 +288,69 @@ class ListeningService(IListeningService):
|
|||||||
voice = name_to_voice[name]
|
voice = name_to_voice[name]
|
||||||
else:
|
else:
|
||||||
voice = None
|
voice = None
|
||||||
|
while voice is None:
|
||||||
|
if segment['gender'].lower() == 'male':
|
||||||
|
available_voices = MALE_NEURAL_VOICES
|
||||||
|
else:
|
||||||
|
available_voices = FEMALE_NEURAL_VOICES
|
||||||
|
|
||||||
|
chosen_voice = random.choice(available_voices)['Id']
|
||||||
|
if chosen_voice not in chosen_voices:
|
||||||
|
voice = chosen_voice
|
||||||
|
chosen_voices.append(voice)
|
||||||
|
name_to_voice[name] = voice
|
||||||
|
segment['voice'] = voice
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def generate_listening_3_conversation(topic: str):
|
||||||
|
...
|
||||||
|
name_to_voice = {}
|
||||||
|
for segment in response['conversation']:
|
||||||
|
if 'voice' not in segment:
|
||||||
|
name = segment['name']
|
||||||
|
if name in name_to_voice:
|
||||||
|
voice = name_to_voice[name]
|
||||||
|
else:
|
||||||
|
if segment['gender'].lower() == 'male':
|
||||||
|
voice = random.choice(MALE_NEURAL_VOICES)['Id']
|
||||||
|
else:
|
||||||
|
voice = random.choice(FEMALE_NEURAL_VOICES)['Id']
|
||||||
|
name_to_voice[name] = voice
|
||||||
|
segment['voice'] = voice
|
||||||
|
return response
|
||||||
|
"""
|
||||||
|
def _get_conversation_voices(self, response: Union[Dict, Dialog], unique_voices_across_segments: bool):
|
||||||
|
chosen_voices = []
|
||||||
|
name_to_voice = {}
|
||||||
|
|
||||||
|
is_model = isinstance(response, Dialog)
|
||||||
|
conversation = response.conversation if is_model else response['conversation']
|
||||||
|
|
||||||
|
for segment in conversation:
|
||||||
|
voice_check = (segment.voice is None) if is_model else ('voice' not in segment)
|
||||||
|
if voice_check:
|
||||||
|
name = segment.name if is_model else segment['name']
|
||||||
|
if name in name_to_voice:
|
||||||
|
voice = name_to_voice[name]
|
||||||
|
else:
|
||||||
|
voice = None
|
||||||
|
gender = segment.gender if is_model else segment['gender']
|
||||||
# section 1
|
# section 1
|
||||||
if unique_voices_across_segments:
|
if unique_voices_across_segments:
|
||||||
while voice is None:
|
while voice is None:
|
||||||
chosen_voice = self._get_random_voice(segment['gender'])
|
chosen_voice = self._get_random_voice(gender)
|
||||||
if chosen_voice not in chosen_voices:
|
if chosen_voice not in chosen_voices:
|
||||||
voice = chosen_voice
|
voice = chosen_voice
|
||||||
chosen_voices.append(voice)
|
chosen_voices.append(voice)
|
||||||
# section 3
|
# section 3
|
||||||
else:
|
else:
|
||||||
voice = self._get_random_voice(segment['gender'])
|
voice = self._get_random_voice(gender)
|
||||||
name_to_voice[name] = voice
|
name_to_voice[name] = voice
|
||||||
|
|
||||||
|
if is_model:
|
||||||
|
segment.voice = voice
|
||||||
|
else:
|
||||||
segment['voice'] = voice
|
segment['voice'] = voice
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ class UserService(IUserService):
|
|||||||
error_msg = f"Couldn't upload users. Failed to run command firebase auth import -> ```cmd {result.stdout}```"
|
error_msg = f"Couldn't upload users. Failed to run command firebase auth import -> ```cmd {result.stdout}```"
|
||||||
self._logger.error(error_msg)
|
self._logger.error(error_msg)
|
||||||
return error_msg
|
return error_msg
|
||||||
|
|
||||||
await self._init_users(batch_dto)
|
await self._init_users(batch_dto)
|
||||||
|
|
||||||
FileHelper.remove_file(path)
|
FileHelper.remove_file(path)
|
||||||
@@ -68,7 +67,7 @@ class UserService(IUserService):
|
|||||||
|
|
||||||
for user in batch_dto.users:
|
for user in batch_dto.users:
|
||||||
user_data = {
|
user_data = {
|
||||||
'UID': str(user.id),
|
'UID': user.id,
|
||||||
'Email': user.email,
|
'Email': user.email,
|
||||||
'Email Verified': False,
|
'Email Verified': False,
|
||||||
'Password Hash': user.passwordHash,
|
'Password Hash': user.passwordHash,
|
||||||
@@ -142,7 +141,7 @@ class UserService(IUserService):
|
|||||||
'subscriptionExpirationDate': user.expiryDate,
|
'subscriptionExpirationDate': user.expiryDate,
|
||||||
'entities': user.entities
|
'entities': user.entities
|
||||||
}
|
}
|
||||||
await self._db.save_to_db("users", new_user, str(user.id))
|
await self._db.save_to_db("users", new_user, user.id)
|
||||||
|
|
||||||
async def _create_code(self, user: UserDTO, maker_id: str) -> str:
|
async def _create_code(self, user: UserDTO, maker_id: str) -> str:
|
||||||
code = shortuuid.ShortUUID().random(length=6)
|
code = shortuuid.ShortUUID().random(length=6)
|
||||||
@@ -174,6 +173,7 @@ class UserService(IUserService):
|
|||||||
'name': user.groupName.strip(),
|
'name': user.groupName.strip(),
|
||||||
'participants': [user_id],
|
'participants': [user_id],
|
||||||
'disableEditing': False,
|
'disableEditing': False,
|
||||||
|
'entity': user.entities[0]['id']
|
||||||
}
|
}
|
||||||
await self._db.save_to_db("groups", new_group, str(uuid.uuid4()))
|
await self._db.save_to_db("groups", new_group, str(uuid.uuid4()))
|
||||||
else:
|
else:
|
||||||
|
|||||||
1
tmp/110e7ab1-bba5-4768-8775-5e7a37f38a12.csv
Normal file
1
tmp/110e7ab1-bba5-4768-8775-5e7a37f38a12.csv
Normal file
@@ -0,0 +1 @@
|
|||||||
|
8e44d32a-b921-4650-a0a5-2ad773356b61,batchentitytest1@ecrop.dev,False,5eoALGIXxSmwj8wRc3U7RGFM4tROrWs/+qJv6O9puXKoCCiniWlDQeWnCFXG8RJBrD48Hoqqoojso6rg31bTXA==,s76hIKNUacTPo8JqYx+7NA==,,,,,,,,,,,,,,,,,,,1736100072082,,
|
||||||
|
Reference in New Issue
Block a user