File size: 5,057 Bytes
2862b53
5350da8
 
 
 
b1ae41c
5350da8
c544135
b1ae41c
2862b53
5350da8
8738846
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d9279e
c544135
5d9279e
 
c544135
5d9279e
 
c544135
8738846
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2862b53
 
 
 
b1ae41c
2862b53
 
 
b1ae41c
 
 
 
 
 
 
 
2862b53
b1ae41c
2862b53
 
 
 
 
b1ae41c
 
 
 
 
 
 
 
2862b53
 
b1ae41c
2862b53
b1ae41c
 
2862b53
b1ae41c
2862b53
 
 
 
 
 
 
 
 
b1ae41c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import re
import os
import streamlit as st
import requests
from transformers import pipeline
from typing import Dict, Optional
from together import Together
from gtts import gTTS
from py_mailsender import Mailsender


# Image-to-text
def img2txt(url: str) -> str:
    print("Initializing captioning model...")
    captioning_model = pipeline("image-to-text", model="Salesforce/blip-image-captioning-base")
    
    print("Generating text from the image...")
    text = captioning_model(url, max_new_tokens=20)[0]["generated_text"]
    
    print(text)
    return text

# Text-to-story generation with LLM model
def txt2story(prompt: str, top_k: int, top_p: float, temperature: float) -> str:
    # Load the Together API client
    client = Together(api_key=os.environ.get("TOGETHER_API_KEY"))

    # Modify the prompt based on user inputs and ensure a 250-word limit
    story_prompt = f"Write a short story of no more than 250 words based on the following prompt: {prompt}"

    # Call the LLM model
    stream = client.chat.completions.create(
        model="meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo",
        messages=[
            {"role": "system", "content": '''As an experienced short story writer, write a meaningful story influenced by the provided prompt.
            Ensure the story does not exceed 250 words.'''},
            {"role": "user", "content": story_prompt}
        ],
        top_k=top_k,
        top_p=top_p,
        temperature=temperature,
        stream=True
    )

    # Concatenate story chunks
    story = ''
    for chunk in stream:
        story += chunk.choices[0].delta.content

    return story

# Text-to-speech
def txt2speech(text: str) -> None:
    print("Converting text to speech using gTTS...")
    
    # Generate audio from the text
    tts = gTTS(text=text, lang='en')
    
    # Save the audio output to a file
    tts.save("audio_story.mp3")

# Get user preferences for the story
def get_user_preferences() -> Dict[str, str]:
    preferences = {}

    preferences['continent'] = st.selectbox("Continent", ["North America", "Europe", "Asia", "Africa", "Australia"])
    preferences['genre'] = st.selectbox("Genre", ["Science Fiction", "Fantasy", "Mystery", "Romance"])
    preferences['setting'] = st.selectbox("Setting", ["Future", "Medieval times", "Modern day", "Alternate reality"])
    preferences['plot'] = st.selectbox("Plot", ["Hero's journey", "Solving a mystery", "Love story", "Survival"])
    preferences['tone'] = st.selectbox("Tone", ["Serious", "Light-hearted", "Humorous", "Dark"])
    preferences['theme'] = st.selectbox("Theme", ["Self-discovery", "Redemption", "Love", "Justice"])
    preferences['conflict'] = st.selectbox("Conflict Type", ["Person vs. Society", "Internal struggle", "Person vs. Nature", "Person vs. Person"])
    preferences['twist'] = st.selectbox("Mystery/Twist", ["Plot twist", "Hidden identity", "Unexpected ally/enemy", "Time paradox"])
    preferences['ending'] = st.selectbox("Ending", ["Happy", "Bittersweet", "Open-ended", "Tragic"])
    
    return preferences


def send_story_email(recipient_email: str, story_text: str, audio_file_path: str) -> bool:
    """
    Send the story text and audio file to the specified email address using py-mailsender
    Returns True if successful, False otherwise
    """
    try:
        # Get email credentials from environment variables
        sender_email = os.getenv('SENDER_EMAIL')
        sender_password = os.getenv('SENDER_PASSWORD')
        
        if not sender_email or not sender_password:
            raise ValueError("Email credentials not configured")
            
        # Create email subject and content
        subject = "Your Generated Story"
        content = f"""Here's your generated story:

{story_text}

Enjoy!"""
        
        # Initialize mail sender
        mailer = Mailsender(
            sender_email,
            sender_password,
            recipient_email,
            subject,
            content
        )
        
        # Add audio file attachment
        mailer.add_attachment(audio_file_path)
        
        # Send email
        mailer.send()
        return True
        
    except Exception as e:
        print(f"Error sending email: {str(e)}")
        return False

def validate_email(email: str) -> bool:
    """
    Basic email validation
    """
    pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'
    return re.match(pattern, email) is not None

def validate_gmail_credentials(email: str, password: str) -> Optional[str]:
    """
    Validate Gmail credentials by attempting to create a test mailer
    Returns None if successful, error message if failed
    """
    try:
        test_mailer = Mailsender(
            email,
            password,
            email,  # Send to self for testing
            "Test Connection",
            "Testing credentials"
        )
        # Just initialize the connection without sending
        test_mailer.initialize_connection()
        test_mailer.close_connection()
        return None
    except Exception as e:
        return str(e)