Skip to content

Commit

Permalink
Merge pull request #38 from dcSpark/refactor-youtube-summary
Browse files Browse the repository at this point in the history
Refactor youtube summary & imap/smtp ssl flag
  • Loading branch information
Yiakman authored Jan 8, 2025
2 parents edb6d36 + 1eae560 commit 86d5725
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 154 deletions.
5 changes: 5 additions & 0 deletions tools/email-imap-fetcher/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
"type": "integer",
"description": "The port number for the IMAP server (defaults to 993 for IMAPS)",
"default": 993
},
"ssl": {
"type": "boolean",
"description": "Whether to use SSL for the IMAP connection (defaults to true)",
"default": true
}
},
"required": [
Expand Down
31 changes: 31 additions & 0 deletions tools/email-imap-fetcher/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import asyncio
from tool import run, CONFIG, INPUTS
# Assuming the classes and functions are imported from your module
# from your_module import CONFIG, INPUTS, run

async def test_imap_connection():
# Create a CONFIG instance with fake credentials
config = CONFIG()
config.imap_server = "server.fakemail.com" # Replace with a valid IMAP server for testing
config.username = "shinkai.dev@fakemail.com" # Fake username
config.password = "fakepassword" # Fake password
config.port = 993 # Common port for IMAPS
config.ssl = True # Use SSL

# Create an INPUTS instance
inputs = INPUTS()
inputs.from_date = None # Optional: set to a date string if needed
inputs.to_date = None # Optional: set to a date string if needed

# Run the function and capture the output
output = await run(config, inputs)
print("Hello World")
# Print the output
print("Login Status:", output.login_status)
print("Emails Retrieved:", len(output.emails))
for email in output.emails:
print(email['subject'] + " " + email['sender'] + " " + str(email['date']))

# Run the test
if __name__ == "__main__":
asyncio.run(test_imap_connection())
8 changes: 7 additions & 1 deletion tools/email-imap-fetcher/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class CONFIG:
username: str
password: str
port: int = 143 # Default port for IMAPS
ssl: bool = False # New flag to specify SSL usage

class INPUTS:
from_date: Optional[str]
Expand All @@ -25,9 +26,14 @@ class Email:

async def run(config: CONFIG, inputs: INPUTS) -> OUTPUT:
output = OUTPUT()
output.login_status = "N/A"
output.emails = []
try:
imap = imaplib.IMAP4(config.imap_server, config.port) # Use config port
# Use SSL if the ssl flag is set to True
if config.ssl:
imap = imaplib.IMAP4_SSL(config.imap_server, config.port)
else:
imap = imaplib.IMAP4(config.imap_server, config.port) # Use config port
except Exception as ee:
output.login_status = 'IMAP4 INIT FAILED - ' + str(ee)
return output
Expand Down
2 changes: 1 addition & 1 deletion tools/email-responder/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type OUTPUT = {

// Helper function to escape user input
function escapeSqlString(str: string): string {
return `'${str.replace(/'/g, "''")}'`; // Replaces single quotes with two single quotes
return `'${str.replace(/'/g, "''").replace('--', '').replace(';', '')}'`; // Replaces single quotes with two single quotes
}

export async function run(config: CONFIG, inputs: INPUTS): Promise<OUTPUT> {
Expand Down
5 changes: 5 additions & 0 deletions tools/email-sender/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
"sender_password": {
"type": "string",
"description": "The sender's email password"
},
"ssl": {
"type": "boolean",
"description": "Whether to use SSL for the SMTP connection (defaults to false)",
"default": false
}
},
"required": [
Expand Down
28 changes: 28 additions & 0 deletions tools/email-sender/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import asyncio
from tool import CONFIG, INPUTS, run # Adjust the import based on your module structure

async def test_email_sender():
# Create a CONFIG instance with fake credentials
config = CONFIG()
config.smtp_server = "smtp.fakeemail.com" # Replace with a valid SMTP server for testing
config.port = 465 # Common port for SMTP with STARTTLS
config.sender_email = "shinkai.dev@fakeemail.com" # Fake sender email
config.sender_password = "fakepassword" # Fake password
config.ssl = True # Set to True if you want to test SSL

# Create an INPUTS instance
inputs = INPUTS()
inputs.recipient_email = "eduardo@fakeemail.com" # Fake recipient email
inputs.subject = "Test Email"
inputs.body = "This is a test email sent using fake credentials."

# Run the function and capture the output
output = await run(config, inputs)

# Print the output
print("Email Sending Status:", output.status)
print("Message:", output.message)

# Run the test
if __name__ == "__main__":
asyncio.run(test_email_sender())
28 changes: 23 additions & 5 deletions tools/email-sender/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime
import logging

# Configure logging
logging.basicConfig(level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')

class CONFIG:
smtp_server: str
port: int = 465 # Default port for SMTP
sender_email: str
sender_password: str
ssl: bool = False # New flag to specify SSL usage for SMTP

class INPUTS:
recipient_email: str
Expand All @@ -33,11 +39,23 @@ async def run(config: CONFIG, inputs: INPUTS) -> OUTPUT:
msg.attach(MIMEText(inputs.body, 'plain'))

try:
with smtplib.SMTP(config.smtp_server, config.port) as server:
server.login(config.sender_email, config.sender_password)
server.send_message(msg)
output.status = "success"
output.message = "Email sent successfully"
# Use SSL if the ssl flag is set to True
if config.ssl:
with smtplib.SMTP_SSL(config.smtp_server, config.port) as server:
server.login(config.sender_email, config.sender_password)
server.send_message(msg)
else:
with smtplib.SMTP(config.smtp_server, config.port) as server:
try:
server.starttls() # Upgrade to a secure connection
except Exception as e:
logging.error(f"Failed to upgrade to a secure connection: {e}")
# Attempt to login and send the message regardless of starttls success
server.login(config.sender_email, config.sender_password)
server.send_message(msg)

output.status = "success"
output.message = "Email sent successfully"
except Exception as e:
output.message = f"An error occurred: {e}"

Expand Down
14 changes: 2 additions & 12 deletions tools/youtube-summary/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
import { expect } from 'jsr:@std/expect/expect';
import { definition, run } from './index.ts';

Deno.test('exists definition', () => {
expect(definition).toBeInstanceOf(Object);
});
import { run } from './tool.ts';

Deno.test({
name: 'transcript video',
ignore: Deno.env.get('CI') === 'true',
fn: async () => {
const result = await run(
{
apiUrl:
Deno.env.get('CI') === 'true'
? 'https://api.openai.com/v1'
: 'http://127.0.0.1:11434',
apiKey:
Deno.env.get('CI') === 'true' ? Deno.env.get('OPEN_API_API_KEY') : '',
model: Deno.env.get('CI') === 'true' ? 'gpt-4o-mini' : '',
// No configuration needed
},
{
url: 'https://www.youtube.com/watch?v=SUj34OWkjXU',
Expand Down
115 changes: 49 additions & 66 deletions tools/youtube-summary/metadata.json
Original file line number Diff line number Diff line change
@@ -1,70 +1,53 @@
{
"id": "youtube-summary",
"name": "YouTube Video Summary",
"description": "Summarizes a YouTube video. Provides a summary with organized sections and clickable timestamp links. Useful for quickly grasping main points, preparing for discussions, or efficient research. Example uses: summarizing tech talks, product reviews, or educational lectures. Parameters: url (string) - The full YouTube video URL to process.",
"author": "Shinkai",
"keywords": [
"youtube",
"transcript",
"video",
"summary",
"sections",
"timestamp",
"links"
],
"configurations": {
"type": "object",
"properties": {
"apiUrl": {
"type": "string",
"description": "The URL of the OpenAI compatible API endpoint for summary generation. Optional. Default: \"http://127.0.0.1:11435\".",
"nullable": true,
"example": "https://api.openai.com/v1"
},
"apiKey": {
"type": "string",
"description": "The API key for the OpenAI compatible endpoint. Required if using a service that needs authentication.",
"nullable": true,
"example": "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"model": {
"type": "string",
"description": "The name of the language model for summary generation. Optional. Default: \"llama3.1:8b-instruct-q4_1\".",
"nullable": true,
"example": "gpt-3.5-turbo"
}
"id": "youtube-summary",
"name": "Youtube Transcript Summarizer",
"description": "Fetches the transcript of a YouTube video and generates a formatted summary using an LLM.",
"author": "@@eduardosotomontaner.arb-sep-shinkai",
"version": "1.0.0",
"keywords": [
"youtube",
"transcript",
"summary",
"video",
"LLM"
],
"configurations": {
"type": "object",
"properties": {},
"required": []
},
"parameters": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The URL of the YouTube video"
},
"required": []
"lang": {
"type": "string",
"description": "The language for the transcript (optional)"
}
},
"parameters": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The full URL of the YouTube video to transcribe and summarize. Must be a valid and accessible YouTube video link.",
"example": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
"lang": {
"type": "string",
"description": "The language code for the transcript in ISO 639-1 format (e.g. \"en\" for English). Optional. If not specified, will use the default available transcript.",
"example": "en",
"nullable": true
}
},
"required": [
"url"
]
"required": [
"url"
]
},
"result": {
"type": "object",
"properties": {
"summary": {
"type": "string",
"description": "The generated summary of the video"
}
},
"result": {
"type": "object",
"properties": {
"summary": {
"type": "string",
"description": "A markdown-formatted summary of the video content, divided into sections with timestamp links to relevant parts of the video."
}
},
"required": [
"summary"
]
}
}
"required": [
"summary"
]
},
"sqlTables": [],
"sqlQueries": [],
"tools": [
"local:::rust_toolkit:::shinkai_llm_prompt_processor"
],
"oauth": []
}
Loading

0 comments on commit 86d5725

Please sign in to comment.