Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/300dpi-co_pixly.json
T

1 line
22 KiB
JSON

{"repo": "300dpi-co/pixly", "files": {"app/Services/BlogAIService.php": {"99e7b33467817c60024f776bd28554aa74d4d15d": {"t": 1785746146.9516237, "n": 10838, "h": "3a34e1f53e91c405", "c": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Services;\n\n/**\n * Blog AI Service\n *\n * Handles AI-powered content generation for blog posts.\n */\nclass BlogAIService\n{\n private string $apiKey;\n private string $endpoint;\n private string $model;\n\n public function __construct()\n {\n $this->apiKey = config('api.deepseek.key', '');\n $this->endpoint = config('api.deepseek.endpoint', 'https://api.deepseek.com');\n $this->model = config('api.deepseek.model', 'deepseek-chat');\n }\n\n /**\n * Generate a complete blog post\n */\n public function generatePost(string $topic, string $tone = 'professional', string $length = 'medium', string $keywords = ''): array\n {\n $wordCounts = [\n 'short' => '500-700',\n 'medium' => '1000-1200',\n 'long' => '1800-2200',\n ];\n\n $targetWords = $wordCounts[$length] ?? '1000-1200';\n\n $prompt = $this->buildGenerationPrompt($topic, $tone, $targetWords, $keywords);\n\n $response = $this->callAPI($prompt);\n\n return $this->parseGeneratedContent($response, $topic);\n }\n\n /**\n * Improve existing content\n */\n public function improveContent(string $content, string $action = 'improve'): array\n {\n $prompts = [\n 'improve' => \"Improve the following blog content. Make it more engaging, clear, and well-structured while maintaining the original message. Fix any grammatical errors and improve the flow:\\n\\n{$content}\\n\\nProvide only the improved content, no explanations.\",\n\n 'expand' => \"Expand the following content with more details, examples, and explanations. Add relevant information to make it more comprehensive. Double the length while keeping it focused:\\n\\n{$content}\\n\\nProvide only the expanded content.\",\n\n 'summarize' => \"Summarize the following content into a concise version that retains the key points. Reduce it to about 30% of the original length:\\n\\n{$content}\\n\\nProvide only the summarized content.\",\n\n 'seo' => \"Optimize the following content for SEO. Add relevant keywords naturally, improve headings for better structure, and make it more search-engine friendly while maintaining readability:\\n\\n{$content}\\n\\nProvide only the optimized content.\",\n ];\n\n $prompt = $prompts[$action] ?? $prompts['improve'];\n\n $response = $this->callAPI($prompt);\n\n return [\n 'content' => $this->cleanContent($response),\n ];\n }\n\n /**\n * Generate SEO metadata\n */\n public function generateMetadata(string $title, string $content): array\n {\n $prompt = \"Based on this blog post, generate SEO metadata:\n\nTitle: {$title}\nContent (excerpt): \" . substr(strip_tags($content), 0, 500) . \"\n\nProvide in this exact JSON format:\n{\n \\\"meta_title\\\": \\\"SEO optimized title under 60 chars\\\",\n \\\"meta_description\\\": \\\"Compelling meta description under 160 chars\\\",\n \\\"keywords\\\": \\\"keyword1, keyword2, keyword3, keyword4, keyword5\\\"\n}\n\nReturn ONLY the JSON, no other text.\";\n\n $response = $this->callAPI($prompt);\n\n try {\n $data = json_decode($response, true);\n if ($data) {\n return $data;\n }\n } catch (\\Exception $e) {\n // Fall through to defaults\n }\n\n return [\n 'meta_title' => substr($title, 0, 60),\n 'meta_description' => substr(strip_tags($content), 0, 160),\n 'keywords' => '',\n ];\n }\n\n /**\n * Generate tags from content\n */\n public function generateTags(string $title, string $content): array\n {\n $prompt = \"Analyze this blog post and suggest 5-8 relevant tags (single words or short phrases).\n\nTitle: {$title}\nContent: \" . substr(strip_tags($content), 0, 1000) . \"\n\nReturn ONLY a comma-separated list of tags, nothing else. Example: technology, artificial intelligence, machine learning, data science\";\n\n $response = $this->callAPI($prompt);\n\n $tags = array_filter(array_map('trim', explode(',', $response)));\n return array_slice($tags, 0, 8);\n }\n\n /**\n * Build generation prompt\n */\n private function buildGenerationPrompt(string $topic, string $tone, string $wordCount, string $keywords): string\n {\n $toneInstructions = [\n 'professional' => 'Use a professional, authoritative tone. Be informative and credible.',\n 'casual' => 'Use a casual, conversational tone. Be friendly and approachable.',\n 'friendly' => 'Use a warm, friendly tone. Be encouraging and supportive.',\n 'authoritative' => 'Use an expert, authoritative tone. Demonstrate deep knowledge.',\n 'humorous' => 'Use a light, humorous tone where appropriate. Keep it engaging and fun.',\n ];\n\n $toneGuide = $toneInstructions[$tone] ?? $toneInstructions['professional'];\n\n $keywordGuide = $keywords ? \"\\n\\nIncorporate these SEO keywords naturally: {$keywords}\" : '';\n\n return \"Write a comprehensive blog post about: {$topic}\n\nREQUIREMENTS:\n- Word count: {$wordCount} words\n- {$toneGuide}\n- Use proper HTML formatting with <h2>, <h3>, <p>, <ul>, <li>, <strong>, <em> tags\n- Include an engaging introduction that hooks the reader\n- Use subheadings (h2, h3) to organize content\n- Include practical examples or tips where relevant\n- End with a conclusion or call-to-action\n- Make it original, valuable, and SEO-friendly{$keywordGuide}\n\nAfter the blog content, provide on separate lines:\nTITLE: [engaging title under 70 chars]\nEXCERPT: [compelling excerpt under 200 chars]\nMETA_DESC: [SEO meta description under 160 chars]\nTAGS: [5-8 relevant tags, comma separated]\n\nWrite the blog post now:\";\n }\n\n /**\n * Parse generated content\n */\n private function parseGeneratedContent(string $response, string $fallbackTitle): array\n {\n $result = [\n 'title' => $fallbackTitle,\n 'content' => '',\n 'excerpt' => '',\n 'meta_description' => '',\n 'tags' => '',\n ];\n\n // Try to extract metadata from the end\n $lines = explode(\"\\n\", $response);\n $contentLines = [];\n $metadataStarted = false;\n\n foreach ($lines as $line) {\n $line = trim($line);\n\n if (preg_match('/^TITLE:\\s*(.+)$/i', $line, $matches)) {\n $result['title'] = trim($matches[1]);\n $metadataStarted = true;\n } elseif (preg_match('/^EXCERPT:\\s*(.+)$/i', $line, $matches)) {\n $result['excerpt'] = trim($matches[1]);\n $metadataStarted = true;\n } elseif (preg_match('/^META_DESC:\\s*(.+)$/i', $line, $matches)) {\n $result['meta_description'] = trim($matches[1]);\n $metadataStarted = true;\n } elseif (preg_match('/^TAGS:\\s*(.+)$/i', $line, $matches)) {\n $result['tags'] = trim($matches[1]);\n $metadataStarted = true;\n } elseif (!$metadataStarted) {\n $contentLines[] = $line;\n }\n }\n\n $content = implode(\"\\n\", $contentLines);\n $result['content'] = $this->cleanContent($content);\n\n // Generate excerpt if not provided\n if (empty($result['excerpt']) && !empty($result['content'])) {\n $text = strip_tags($result['content']);\n $result['excerpt'] = substr($text, 0, 200);\n if (strlen($text) > 200) {\n $result['excerpt'] = substr($result['excerpt'], 0, strrpos($result['excerpt'], ' ')) . '...';\n }\n }\n\n return $result;\n }\n\n /**\n * Clean generated content\n */\n private function cleanContent(string $content): string\n {\n // Remove markdown code blocks if present\n $content = preg_replace('/```html?\\s*/i', '', $content);\n $content = preg_replace('/```\\s*/', '', $content);\n\n // Ensure proper HTML structure\n $content = trim($content);\n\n // Convert markdown-style headings if present\n $content = preg_replace('/^##\\s+(.+)$/m', '<h2>$1</h2>', $content);\n $content = preg_replace('/^###\\s+(.+)$/m', '<h3>$1</h3>', $content);\n\n // Convert markdown bold/italic if present\n $content = preg_replace('/\\*\\*(.+?)\\*\\*/', '<strong>$1</strong>', $content);\n $content = preg_replace('/\\*(.+?)\\*/', '<em>$1</em>', $content);\n\n // Wrap plain paragraphs\n $lines = explode(\"\\n\\n\", $content);\n $processed = [];\n\n foreach ($lines as $line) {\n $line = trim($line);\n if (empty($line)) continue;\n\n // Skip if already has block-level tags\n if (preg_match('/^<(h[1-6]|p|ul|ol|li|div|blockquote)/i', $line)) {\n $processed[] = $line;\n } else {\n $processed[] = '<p>' . $line . '</p>';\n }\n }\n\n return implode(\"\\n\\n\", $processed);\n }\n\n /**\n * Call the AI API\n */\n private function callAPI(string $prompt): string\n {\n if (empty($this->apiKey)) {\n throw new \\Exception('AI API key is not configured');\n }\n\n $payload = [\n 'model' => $this->model,\n 'messages' => [\n [\n 'role' => 'system',\n 'content' => 'You are an expert blog writer and content strategist. You create engaging, well-structured, SEO-optimized content.',\n ],\n [\n 'role' => 'user',\n 'content' => $prompt,\n ],\n ],\n 'temperature' => 0.7,\n 'max_tokens' => 4000,\n ];\n\n $ch = curl_init($this->endpoint . '/chat/completions');\n curl_setopt_array($ch, [\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_POST => true,\n CURLOPT_POSTFIELDS => json_encode($payload),\n CURLOPT_HTTPHEADER => [\n 'Content-Type: application/json',\n 'Authorization: Bearer ' . $this->apiKey,\n ],\n CURLOPT_TIMEOUT => 120,\n ]);\n\n $response = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n $error = curl_error($ch);\n curl_close($ch);\n\n if ($error) {\n throw new \\Exception('API request failed: ' . $error);\n }\n\n if ($httpCode !== 200) {\n $errorData = json_decode($response, true);\n throw new \\Exception('API error: ' . ($errorData['error']['message'] ?? 'Unknown error'));\n }\n\n $data = json_decode($response, true);\n\n if (!isset($data['choices'][0]['message']['content'])) {\n throw new \\Exception('Invalid API response format');\n }\n\n return $data['choices'][0]['message']['content'];\n }\n}\n"}, "472aa5764620259e9291ed099da1a87f7bbf0f80": {"t": 1785760170.6794844, "n": 10838, "h": "3a34e1f53e91c405", "c": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Services;\n\n/**\n * Blog AI Service\n *\n * Handles AI-powered content generation for blog posts.\n */\nclass BlogAIService\n{\n private string $apiKey;\n private string $endpoint;\n private string $model;\n\n public function __construct()\n {\n $this->apiKey = config('api.deepseek.key', '');\n $this->endpoint = config('api.deepseek.endpoint', 'https://api.deepseek.com');\n $this->model = config('api.deepseek.model', 'deepseek-chat');\n }\n\n /**\n * Generate a complete blog post\n */\n public function generatePost(string $topic, string $tone = 'professional', string $length = 'medium', string $keywords = ''): array\n {\n $wordCounts = [\n 'short' => '500-700',\n 'medium' => '1000-1200',\n 'long' => '1800-2200',\n ];\n\n $targetWords = $wordCounts[$length] ?? '1000-1200';\n\n $prompt = $this->buildGenerationPrompt($topic, $tone, $targetWords, $keywords);\n\n $response = $this->callAPI($prompt);\n\n return $this->parseGeneratedContent($response, $topic);\n }\n\n /**\n * Improve existing content\n */\n public function improveContent(string $content, string $action = 'improve'): array\n {\n $prompts = [\n 'improve' => \"Improve the following blog content. Make it more engaging, clear, and well-structured while maintaining the original message. Fix any grammatical errors and improve the flow:\\n\\n{$content}\\n\\nProvide only the improved content, no explanations.\",\n\n 'expand' => \"Expand the following content with more details, examples, and explanations. Add relevant information to make it more comprehensive. Double the length while keeping it focused:\\n\\n{$content}\\n\\nProvide only the expanded content.\",\n\n 'summarize' => \"Summarize the following content into a concise version that retains the key points. Reduce it to about 30% of the original length:\\n\\n{$content}\\n\\nProvide only the summarized content.\",\n\n 'seo' => \"Optimize the following content for SEO. Add relevant keywords naturally, improve headings for better structure, and make it more search-engine friendly while maintaining readability:\\n\\n{$content}\\n\\nProvide only the optimized content.\",\n ];\n\n $prompt = $prompts[$action] ?? $prompts['improve'];\n\n $response = $this->callAPI($prompt);\n\n return [\n 'content' => $this->cleanContent($response),\n ];\n }\n\n /**\n * Generate SEO metadata\n */\n public function generateMetadata(string $title, string $content): array\n {\n $prompt = \"Based on this blog post, generate SEO metadata:\n\nTitle: {$title}\nContent (excerpt): \" . substr(strip_tags($content), 0, 500) . \"\n\nProvide in this exact JSON format:\n{\n \\\"meta_title\\\": \\\"SEO optimized title under 60 chars\\\",\n \\\"meta_description\\\": \\\"Compelling meta description under 160 chars\\\",\n \\\"keywords\\\": \\\"keyword1, keyword2, keyword3, keyword4, keyword5\\\"\n}\n\nReturn ONLY the JSON, no other text.\";\n\n $response = $this->callAPI($prompt);\n\n try {\n $data = json_decode($response, true);\n if ($data) {\n return $data;\n }\n } catch (\\Exception $e) {\n // Fall through to defaults\n }\n\n return [\n 'meta_title' => substr($title, 0, 60),\n 'meta_description' => substr(strip_tags($content), 0, 160),\n 'keywords' => '',\n ];\n }\n\n /**\n * Generate tags from content\n */\n public function generateTags(string $title, string $content): array\n {\n $prompt = \"Analyze this blog post and suggest 5-8 relevant tags (single words or short phrases).\n\nTitle: {$title}\nContent: \" . substr(strip_tags($content), 0, 1000) . \"\n\nReturn ONLY a comma-separated list of tags, nothing else. Example: technology, artificial intelligence, machine learning, data science\";\n\n $response = $this->callAPI($prompt);\n\n $tags = array_filter(array_map('trim', explode(',', $response)));\n return array_slice($tags, 0, 8);\n }\n\n /**\n * Build generation prompt\n */\n private function buildGenerationPrompt(string $topic, string $tone, string $wordCount, string $keywords): string\n {\n $toneInstructions = [\n 'professional' => 'Use a professional, authoritative tone. Be informative and credible.',\n 'casual' => 'Use a casual, conversational tone. Be friendly and approachable.',\n 'friendly' => 'Use a warm, friendly tone. Be encouraging and supportive.',\n 'authoritative' => 'Use an expert, authoritative tone. Demonstrate deep knowledge.',\n 'humorous' => 'Use a light, humorous tone where appropriate. Keep it engaging and fun.',\n ];\n\n $toneGuide = $toneInstructions[$tone] ?? $toneInstructions['professional'];\n\n $keywordGuide = $keywords ? \"\\n\\nIncorporate these SEO keywords naturally: {$keywords}\" : '';\n\n return \"Write a comprehensive blog post about: {$topic}\n\nREQUIREMENTS:\n- Word count: {$wordCount} words\n- {$toneGuide}\n- Use proper HTML formatting with <h2>, <h3>, <p>, <ul>, <li>, <strong>, <em> tags\n- Include an engaging introduction that hooks the reader\n- Use subheadings (h2, h3) to organize content\n- Include practical examples or tips where relevant\n- End with a conclusion or call-to-action\n- Make it original, valuable, and SEO-friendly{$keywordGuide}\n\nAfter the blog content, provide on separate lines:\nTITLE: [engaging title under 70 chars]\nEXCERPT: [compelling excerpt under 200 chars]\nMETA_DESC: [SEO meta description under 160 chars]\nTAGS: [5-8 relevant tags, comma separated]\n\nWrite the blog post now:\";\n }\n\n /**\n * Parse generated content\n */\n private function parseGeneratedContent(string $response, string $fallbackTitle): array\n {\n $result = [\n 'title' => $fallbackTitle,\n 'content' => '',\n 'excerpt' => '',\n 'meta_description' => '',\n 'tags' => '',\n ];\n\n // Try to extract metadata from the end\n $lines = explode(\"\\n\", $response);\n $contentLines = [];\n $metadataStarted = false;\n\n foreach ($lines as $line) {\n $line = trim($line);\n\n if (preg_match('/^TITLE:\\s*(.+)$/i', $line, $matches)) {\n $result['title'] = trim($matches[1]);\n $metadataStarted = true;\n } elseif (preg_match('/^EXCERPT:\\s*(.+)$/i', $line, $matches)) {\n $result['excerpt'] = trim($matches[1]);\n $metadataStarted = true;\n } elseif (preg_match('/^META_DESC:\\s*(.+)$/i', $line, $matches)) {\n $result['meta_description'] = trim($matches[1]);\n $metadataStarted = true;\n } elseif (preg_match('/^TAGS:\\s*(.+)$/i', $line, $matches)) {\n $result['tags'] = trim($matches[1]);\n $metadataStarted = true;\n } elseif (!$metadataStarted) {\n $contentLines[] = $line;\n }\n }\n\n $content = implode(\"\\n\", $contentLines);\n $result['content'] = $this->cleanContent($content);\n\n // Generate excerpt if not provided\n if (empty($result['excerpt']) && !empty($result['content'])) {\n $text = strip_tags($result['content']);\n $result['excerpt'] = substr($text, 0, 200);\n if (strlen($text) > 200) {\n $result['excerpt'] = substr($result['excerpt'], 0, strrpos($result['excerpt'], ' ')) . '...';\n }\n }\n\n return $result;\n }\n\n /**\n * Clean generated content\n */\n private function cleanContent(string $content): string\n {\n // Remove markdown code blocks if present\n $content = preg_replace('/```html?\\s*/i', '', $content);\n $content = preg_replace('/```\\s*/', '', $content);\n\n // Ensure proper HTML structure\n $content = trim($content);\n\n // Convert markdown-style headings if present\n $content = preg_replace('/^##\\s+(.+)$/m', '<h2>$1</h2>', $content);\n $content = preg_replace('/^###\\s+(.+)$/m', '<h3>$1</h3>', $content);\n\n // Convert markdown bold/italic if present\n $content = preg_replace('/\\*\\*(.+?)\\*\\*/', '<strong>$1</strong>', $content);\n $content = preg_replace('/\\*(.+?)\\*/', '<em>$1</em>', $content);\n\n // Wrap plain paragraphs\n $lines = explode(\"\\n\\n\", $content);\n $processed = [];\n\n foreach ($lines as $line) {\n $line = trim($line);\n if (empty($line)) continue;\n\n // Skip if already has block-level tags\n if (preg_match('/^<(h[1-6]|p|ul|ol|li|div|blockquote)/i', $line)) {\n $processed[] = $line;\n } else {\n $processed[] = '<p>' . $line . '</p>';\n }\n }\n\n return implode(\"\\n\\n\", $processed);\n }\n\n /**\n * Call the AI API\n */\n private function callAPI(string $prompt): string\n {\n if (empty($this->apiKey)) {\n throw new \\Exception('AI API key is not configured');\n }\n\n $payload = [\n 'model' => $this->model,\n 'messages' => [\n [\n 'role' => 'system',\n 'content' => 'You are an expert blog writer and content strategist. You create engaging, well-structured, SEO-optimized content.',\n ],\n [\n 'role' => 'user',\n 'content' => $prompt,\n ],\n ],\n 'temperature' => 0.7,\n 'max_tokens' => 4000,\n ];\n\n $ch = curl_init($this->endpoint . '/chat/completions');\n curl_setopt_array($ch, [\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_POST => true,\n CURLOPT_POSTFIELDS => json_encode($payload),\n CURLOPT_HTTPHEADER => [\n 'Content-Type: application/json',\n 'Authorization: Bearer ' . $this->apiKey,\n ],\n CURLOPT_TIMEOUT => 120,\n ]);\n\n $response = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n $error = curl_error($ch);\n curl_close($ch);\n\n if ($error) {\n throw new \\Exception('API request failed: ' . $error);\n }\n\n if ($httpCode !== 200) {\n $errorData = json_decode($response, true);\n throw new \\Exception('API error: ' . ($errorData['error']['message'] ?? 'Unknown error'));\n }\n\n $data = json_decode($response, true);\n\n if (!isset($data['choices'][0]['message']['content'])) {\n throw new \\Exception('Invalid API response format');\n }\n\n return $data['choices'][0]['message']['content'];\n }\n}\n"}}}}