From d7ee89290ea60160e1af9f35a5104c517a3dce20 Mon Sep 17 00:00:00 2001 From: Priya09023 Date: Thu, 11 Jun 2026 16:50:05 +0530 Subject: [PATCH 1/5] Add custom blog tone selection feature --- backend/ai_core/prompts.py | 40 + backend/main.py | 14 + extension/background.js | 4 +- extension/content.js | 12 +- extension/popup.html | 35 +- extension/popup.js | 34 +- frontend/package-lock.json | 1681 ++++++++++++++++++++++++++++++++++++ 7 files changed, 1808 insertions(+), 12 deletions(-) create mode 100644 frontend/package-lock.json diff --git a/backend/ai_core/prompts.py b/backend/ai_core/prompts.py index 5670097..c117805 100644 --- a/backend/ai_core/prompts.py +++ b/backend/ai_core/prompts.py @@ -1,8 +1,45 @@ from datetime import datetime +TONE_MAP = { + "beginner": """ +Write in a beginner-friendly style. +Explain concepts using simple language. +Avoid unnecessary jargon. +Use examples wherever possible. +""", + + "professional": """ +Write in a professional technical blogging style. +Maintain clarity and industry-standard explanations. +""", + + "academic": """ +Write in an academic and analytical style. +Provide detailed reasoning and technical depth. +""", + + "humorous": """ +Write in a light-hearted and engaging style. +Use appropriate humor while keeping technical accuracy. +""", + + "concise": """ +Write concise explanations. +Avoid unnecessary details. +Focus on key insights only. +""" +} + def build_prompt(problem, current_time: str) -> str: custom_instructions = "" + tone_instructions = "" + + if hasattr(problem, "tone") and problem.tone: + tone_instructions = TONE_MAP.get( + problem.tone.lower(), + "" + ) default_prompt = f""" You are a professional technical writer and competitive programmer. @@ -48,6 +85,9 @@ def build_prompt(problem, current_time: str) -> str: return f""" {default_prompt} +Selected Writing Tone: +{tone_instructions} + {custom_instructions} """ diff --git a/backend/main.py b/backend/main.py index 6156417..e2d3cd0 100644 --- a/backend/main.py +++ b/backend/main.py @@ -114,6 +114,7 @@ class Problem(BaseModel): language: str | None = None client_time: str | None = None custom_prompt: str | None = None + tone: str | None = None platforms: list[str] | None = None publish_as_draft: bool = False share_to_social: bool = True @@ -452,6 +453,19 @@ async def create_blog( status_code=400, detail="Custom prompt exceeds maximum length of 1000 characters.", ) + allowed_tones = [ + "beginner", + "professional", + "academic", + "humorous", + "concise" + ] + + if problem.tone and problem.tone.lower() not in allowed_tones: + raise HTTPException( + status_code=400, + detail="Invalid tone selected." + ) if not problem.code or problem.code.strip() == "": return {"status": "error", "message": "Code is empty, cannot generate blog."} diff --git a/extension/background.js b/extension/background.js index 3ce4bd2..a31678b 100644 --- a/extension/background.js +++ b/extension/background.js @@ -13,7 +13,7 @@ function getUserEmail() { } chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.type === 'GENERATE_BLOG') { - const { title, description, code, author, client_time, custom_prompt, difficulty } = request.payload; + const { title, description, code, author, client_time, custom_prompt,tone, difficulty } = request.payload; chrome.storage.local.get({ publishingPlatforms: ['devto'], publishAsDraft: false, @@ -27,7 +27,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { method: "POST", headers: { "Content-Type": "application/json", "X-User-Email": userEmail }, body: JSON.stringify({ - title, description, code, author, client_time, custom_prompt, difficulty, + title, description, code, author, client_time, custom_prompt, tone, difficulty, platforms: publishingPlatforms, publish_as_draft: publishAsDraft }) diff --git a/extension/content.js b/extension/content.js index 4f42905..d60d6d3 100644 --- a/extension/content.js +++ b/extension/content.js @@ -14,7 +14,10 @@ const AUTO_TRIGGER_MIN_INTERVAL_MS = 60 * 1000; // 1 minute between auto-triggers for same submission // Function to handle data extraction and blog generation - const triggerBlogGeneration = async (custom_prompt = "") => { + const triggerBlogGeneration = async ( + custom_prompt = "", + tone = "beginner" + ) => { if (isProcessing) return; isProcessing = true; @@ -79,7 +82,7 @@ // Send to background script chrome.runtime.sendMessage({ type: 'GENERATE_BLOG', - payload: { title, description, code, author, client_time, custom_prompt, difficulty, language } + payload: { title, description, code, author, client_time, custom_prompt, tone, difficulty, language } }); @@ -129,7 +132,10 @@ // Start of Listener for manual triggers from popup and status updates chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.type === 'MANUAL_TRIGGER') { - triggerBlogGeneration(request.custom_prompt || ""); //usage of custom prompt + triggerBlogGeneration( + request.custom_prompt || "", + request.tone || "beginner" + ); //usage of custom prompt } else if (request.type === 'STATUS_UPDATE') { if (request.status === 'success' || request.status === 'error') { isProcessing = false; diff --git a/extension/popup.html b/extension/popup.html index 5c9dbed..b3a8b32 100644 --- a/extension/popup.html +++ b/extension/popup.html @@ -113,6 +113,29 @@ box-shadow: 0 0 0 3px rgba(247, 160, 26, 0.15); background: rgba(0, 0, 0, 0.4); } + select { + width: 100%; + padding: 12px 14px; + background: rgba(0, 0, 0, 0.2); + border: 1px solid var(--border-glass); + border-radius: 12px; + color: var(--text); + font-size: 13px; + font-family: 'Inter', sans-serif; + outline: none; + transition: all 0.3s ease; + backdrop-filter: blur(10px); + } + + select:focus { + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(247, 160, 26, 0.15); + } + + select option { + background: #1a1d29; + color: white; + } textarea::placeholder { color: #606575; @@ -510,6 +533,16 @@

LeetLog AI

+
+ + +
@@ -552,7 +585,7 @@

LeetLog AI

Generate Blog - -