File size: 9,506 Bytes
a74b879
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
"""
Meta Description Generator
AI-powered meta description generation for SEO
"""

import os
import re
from typing import Dict, List

def generate_meta_description(page: Dict, api_keys: Dict = None) -> str:
    """
    Generate SEO-optimized meta description for a page
    Uses AI if available, falls back to smart extraction
    """
    title = page.get('title', '')
    text = page.get('text', '')
    headings = page.get('headings', [])
    url = page.get('url', '')
    
    # Try AI generation first
    ai_description = _generate_with_ai(title, text, headings, api_keys)
    if ai_description:
        return ai_description
    
    # Fallback to smart extraction
    return _generate_smart_description(title, text, headings)


def _generate_with_ai(title: str, text: str, headings: List, api_keys: Dict = None) -> str:
    """Generate meta description using AI (Groq or OpenAI)"""
    try:
        # Try Groq first (faster and free)
        groq_key = (api_keys or {}).get('groq') or os.getenv('GROQ_API_KEY')
        if groq_key:
            return _generate_with_groq(title, text, headings, groq_key)
        
        # Fallback to OpenAI
        openai_key = (api_keys or {}).get('openai') or os.getenv('OPENAI_API_KEY')
        if openai_key:
            return _generate_with_openai(title, text, headings, openai_key)
        
        return None
        
    except Exception as e:
        print(f"AI meta generation failed: {e}")
        return None


def _generate_with_groq(title: str, text: str, headings: List, api_key: str) -> str:
    """Generate using Groq API"""
    try:
        import requests
        
        # Extract key points from text
        text_sample = text[:1000] if text else ''
        headings_text = ' '.join([h.get('text', '') if isinstance(h, dict) else str(h) for h in headings[:5]])
        
        prompt = f"""اكتب وصف meta description مثالي لصفحة ويب بالمواصفات التالية:
- العنوان: {title}
- المحتوى: {text_sample}
- العناوين: {headings_text}

المتطلبات:
- الطول: 150-160 حرف بالضبط
- يجب أن يكون جذاب ومقنع
- يحتوي على كلمات مفتاحية
- يشجع على النقر
- بدون علامات تنصيص

اكتب الوصف فقط بدون أي نص إضافي:"""

        response = requests.post(
            'https://api.groq.com/openai/v1/chat/completions',
            headers={
                'Authorization': f'Bearer {api_key}',
                'Content-Type': 'application/json'
            },
            json={
                'model': 'llama-3.3-70b-versatile',
                'messages': [{'role': 'user', 'content': prompt}],
                'temperature': 0.7,
                'max_tokens': 100
            },
            timeout=15
        )
        
        if response.status_code == 200:
            data = response.json()
            description = data['choices'][0]['message']['content'].strip()
            # Clean up
            description = description.replace('"', '').replace("'", '').strip()
            # Ensure proper length
            if len(description) > 160:
                description = description[:157] + '...'
            return description
        
        return None
        
    except Exception as e:
        print(f"Groq meta generation error: {e}")
        return None


def _generate_with_openai(title: str, text: str, headings: List, api_key: str) -> str:
    """Generate using OpenAI API"""
    try:
        import requests
        
        text_sample = text[:1000] if text else ''
        headings_text = ' '.join([h.get('text', '') if isinstance(h, dict) else str(h) for h in headings[:5]])
        
        prompt = f"""Write a perfect meta description for a webpage with these details:
- Title: {title}
- Content: {text_sample}
- Headings: {headings_text}

Requirements:
- Exactly 150-160 characters
- Compelling and click-worthy
- Contains keywords
- No quotation marks

Write only the description:"""

        response = requests.post(
            'https://api.openai.com/v1/chat/completions',
            headers={
                'Authorization': f'Bearer {api_key}',
                'Content-Type': 'application/json'
            },
            json={
                'model': 'gpt-3.5-turbo',
                'messages': [{'role': 'user', 'content': prompt}],
                'temperature': 0.7,
                'max_tokens': 100
            },
            timeout=15
        )
        
        if response.status_code == 200:
            data = response.json()
            description = data['choices'][0]['message']['content'].strip()
            description = description.replace('"', '').replace("'", '').strip()
            if len(description) > 160:
                description = description[:157] + '...'
            return description
        
        return None
        
    except Exception as e:
        print(f"OpenAI meta generation error: {e}")
        return None


def _generate_smart_description(title: str, text: str, headings: List) -> str:
    """Generate meta description using smart extraction (no AI)"""
    # Clean text
    text = re.sub(r'\s+', ' ', text).strip()
    
    # Try to find first meaningful paragraph
    sentences = re.split(r'[.!?]+', text)
    
    description = ''
    for sentence in sentences:
        sentence = sentence.strip()
        if len(sentence) > 50 and len(sentence) < 200:
            description = sentence
            break
    
    # If no good sentence, use title + first heading
    if not description and headings:
        first_heading = headings[0]
        heading_text = first_heading.get('text', '') if isinstance(first_heading, dict) else str(first_heading)
        description = f"{title} - {heading_text}"
    
    # If still nothing, use title + generic text
    if not description:
        description = f"{title} - اكتشف خدماتنا ومنتجاتنا المتميزة"
    
    # Ensure proper length
    if len(description) > 160:
        description = description[:157] + '...'
    elif len(description) < 120:
        description += ' - تواصل معنا الآن للمزيد من المعلومات'
    
    return description


def generate_meta_descriptions_for_audit(audit: Dict, api_keys: Dict = None) -> List[Dict]:
    """Generate meta descriptions for all pages in audit"""
    pages = audit.get('pages', [])
    results = []
    
    for page in pages:
        url = page.get('url', '')
        title = page.get('title', '')
        
        # Check if page already has meta description
        html = page.get('html', '')
        existing_meta = re.search(r'<meta\s+name=["\']description["\']\s+content=["\']([^"\']+)["\']', html, re.IGNORECASE)
        
        has_meta = bool(existing_meta)
        existing_description = existing_meta.group(1) if existing_meta else None
        
        # Generate new description
        new_description = generate_meta_description(page, api_keys)
        
        # Analyze existing if present
        issues = []
        if has_meta:
            if len(existing_description) < 120:
                issues.append('قصير جداً (أقل من 120 حرف)')
            elif len(existing_description) > 160:
                issues.append('طويل جداً (أكثر من 160 حرف)')
            
            if not any(keyword in existing_description.lower() for keyword in title.lower().split()[:3]):
                issues.append('لا يحتوي على كلمات مفتاحية من العنوان')
        
        results.append({
            'url': url,
            'title': title,
            'has_meta': has_meta,
            'existing': existing_description,
            'suggested': new_description,
            'issues': issues,
            'status': 'جيد ✓' if has_meta and not issues else 'يحتاج تحسين ⚠️' if has_meta else 'مفقود ❌'
        })
    
    return results


def get_meta_description_recommendations(audit: Dict) -> Dict:
    """Get summary and recommendations for meta descriptions"""
    pages = audit.get('pages', [])
    
    total_pages = len(pages)
    pages_with_meta = 0
    pages_with_good_meta = 0
    pages_missing_meta = 0
    
    for page in pages:
        html = page.get('html', '')
        meta_match = re.search(r'<meta\s+name=["\']description["\']\s+content=["\']([^"\']+)["\']', html, re.IGNORECASE)
        
        if meta_match:
            pages_with_meta += 1
            description = meta_match.group(1)
            if 120 <= len(description) <= 160:
                pages_with_good_meta += 1
        else:
            pages_missing_meta += 1
    
    score = int((pages_with_good_meta / total_pages * 100)) if total_pages > 0 else 0
    
    recommendations = []
    if pages_missing_meta > 0:
        recommendations.append(f'أضف meta description لـ {pages_missing_meta} صفحة')
    
    if pages_with_meta - pages_with_good_meta > 0:
        recommendations.append(f'حسّن meta description لـ {pages_with_meta - pages_with_good_meta} صفحة')
    
    return {
        'score': score,
        'total_pages': total_pages,
        'pages_with_meta': pages_with_meta,
        'pages_with_good_meta': pages_with_good_meta,
        'pages_missing_meta': pages_missing_meta,
        'status': 'ممتاز ✅' if score >= 90 else 'جيد ✓' if score >= 70 else 'يحتاج تحسين ⚠️',
        'recommendations': recommendations
    }