New very
This commit is contained in:
parent
e2ba34438a
commit
64a48cfac7
BIN
assets/pasted-20251118-044256-eeb6184a.jpg
Normal file
BIN
assets/pasted-20251118-044256-eeb6184a.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 214 KiB |
BIN
assets/pasted-20251118-044502-e7a78f8a.jpg
Normal file
BIN
assets/pasted-20251118-044502-e7a78f8a.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 214 KiB |
Binary file not shown.
@ -15,9 +15,10 @@ import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
load_dotenv(BASE_DIR.parent / ".env")
|
||||
load_dotenv(BASE_DIR / ".env")
|
||||
|
||||
SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", "change-me")
|
||||
YOUTUBE_API_KEY = os.getenv("YOUTUBE_API_KEY", "")
|
||||
DEBUG = os.getenv("DJANGO_DEBUG", "true").lower() == "true"
|
||||
|
||||
ALLOWED_HOSTS = [
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -20,6 +20,6 @@
|
||||
<div class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,25 +1,28 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Testimonials{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<h1>Testimonials</h1>
|
||||
|
||||
<div id="testimonial-container">
|
||||
<div class="testimonial show">
|
||||
<p>"This is the best SEO tool I've ever used! It's helped me rank my videos higher and get more views."</p>
|
||||
<p class="author">- John Doe</p>
|
||||
</div>
|
||||
<div class="testimonial">
|
||||
<p>"I was struggling to grow my YouTube channel, but this tag generator has been a game-changer. I'm finally getting the traffic I deserve."</p>
|
||||
<p class="author">- Jane Smith</p>
|
||||
</div>
|
||||
<div class="testimonial">
|
||||
<p>"I love how easy it is to use this tool. It's saved me so much time and effort."</p>
|
||||
<p class="author">- David Johnson</p>
|
||||
</div>
|
||||
<div class="testimonial">
|
||||
<p>"I was skeptical at first, but this tool really works. I've seen a significant increase in my video's performance since I started using it."</p>
|
||||
<p class="author">- Sarah Williams</p>
|
||||
<div class="container d-flex justify-content-center align-items-center vh-100">
|
||||
<div class="card text-center" style="width: 40rem;">
|
||||
<div class="card-body">
|
||||
<h1 class="card-title">Testimonials</h1>
|
||||
<div id="testimonial-container">
|
||||
<div class="testimonial show">
|
||||
<p>"This is the best SEO tool I've ever used! It's helped me rank my videos higher and get more views."</p>
|
||||
<p class="author">- John Doe</p>
|
||||
</div>
|
||||
<div class="testimonial">
|
||||
<p>"I was struggling to grow my YouTube channel, but this tag generator has been a game-changer. I'm finally getting the traffic I deserve."</p>
|
||||
<p class="author">- Jane Smith</p>
|
||||
</div>
|
||||
<div class="testimonial">
|
||||
<p>"I love how easy it is to use this tool. It's saved me so much time and effort."</p>
|
||||
<p class="author">- David Johnson</p>
|
||||
</div>
|
||||
<div class="testimonial">
|
||||
<p>"I was skeptical at first, but this tool really works. I've seen a significant increase in my video's performance since I started using it."</p>
|
||||
<p class="author">- Sarah Williams</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -3,5 +3,44 @@
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<h1>Website SEO</h1>
|
||||
<p>Enter a URL to analyze its title, meta description, and keywords.</p>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="url" class="form-label">Website URL</label>
|
||||
<input type="url" class="form-control" id="url" name="url" placeholder="https://example.com" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Analyze</button>
|
||||
</form>
|
||||
|
||||
{% if error %}
|
||||
<div class="alert alert-danger mt-3" role="alert">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if title %}
|
||||
<div class="mt-4">
|
||||
<h2>Analysis for {{ url }}</h2>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Title</h5>
|
||||
<p class="card-text">{{ title }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-3">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Meta Description</h5>
|
||||
<p class="card-text">{{ description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-3">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Meta Keywords</h5>
|
||||
<p class="card-text">{{ keywords }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@ -3,5 +3,33 @@
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<h1>YouTube SEO</h1>
|
||||
|
||||
<form method="get" action=".">
|
||||
<input type="text" name="q" placeholder="Search YouTube" value="{{ request.GET.q }}">
|
||||
<button type="submit">Search</button>
|
||||
</form>
|
||||
|
||||
<div class="row">
|
||||
{% for video in videos %}
|
||||
<div class="col-md-4">
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<img src="{{ video.snippet.thumbnails.medium.url }}" class="card-img-top" alt="{{ video.snippet.title }}">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{ video.snippet.title }}</h5>
|
||||
<p class="card-text">{{ video.snippet.description }}</p>
|
||||
{% if video.details.snippet.tags %}
|
||||
<h6>Tags:</h6>
|
||||
<p>
|
||||
{% for tag in video.details.snippet.tags %}
|
||||
<span class="badge bg-secondary">{{ tag }}</span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<a href="https://www.youtube.com/watch?v={{ video.id.videoId }}" target="_blank" class="btn btn-primary">Watch</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@ -1,7 +1,11 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import home
|
||||
from .views import home, faq, testimonials, website_seo, youtube_seo
|
||||
|
||||
urlpatterns = [
|
||||
path("", home, name="home"),
|
||||
path("faq/", faq, name="faq"),
|
||||
path("testimonials/", testimonials, name="testimonials"),
|
||||
path("website-seo/", website_seo, name="website_seo"),
|
||||
path("youtube-seo/", youtube_seo, name="youtube_seo"),
|
||||
]
|
||||
|
||||
@ -2,6 +2,10 @@ from django.http import JsonResponse
|
||||
from django.shortcuts import render
|
||||
from ai.local_ai_api import LocalAIApi
|
||||
import logging
|
||||
from django.conf import settings
|
||||
from googleapiclient.discovery import build
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -41,7 +45,7 @@ def home(request):
|
||||
elif form_type == 'youtube':
|
||||
prompt = {
|
||||
"input": [
|
||||
{"role": "system", "content": "You are a YouTube content expert. Generate a catchy title, a list of relevant keywords, and a list of hashtags for a given video topic. Return the result as a JSON object with three keys: 'title', 'keywords', and 'hashtags'. 'keywords' and 'hashtags' should be lists of strings."},
|
||||
{"role": "system", "content": "You are a YouTube content expert.. Generate a catchy title, a list of relevant keywords, and a list of hashtags for a given video topic. Return the result as a JSON object with three keys: 'title', 'keywords', and 'hashtags'. 'keywords' and 'hashtags' should be lists of strings."},
|
||||
{"role": "user", "content": f"The topic is: {topic}"},
|
||||
],
|
||||
"text": {"format": {"type": "json_object"}},
|
||||
@ -64,3 +68,76 @@ def home(request):
|
||||
return JsonResponse({'error': 'An unexpected error occurred.'}, status=500)
|
||||
|
||||
return render(request, "core/index.html", {})
|
||||
|
||||
def faq(request):
|
||||
return render(request, "core/faq.html")
|
||||
|
||||
def testimonials(request):
|
||||
return render(request, "core/testimonials.html")
|
||||
|
||||
def website_seo(request):
|
||||
if request.method == 'POST':
|
||||
url = request.POST.get('url')
|
||||
if not url:
|
||||
return render(request, 'core/website_seo.html', {'error': 'Please provide a URL.'})
|
||||
|
||||
try:
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
soup = BeautifulSoup(response.content, 'html.parser')
|
||||
|
||||
title = soup.title.string if soup.title else 'No title found'
|
||||
description = soup.find('meta', attrs={'name': 'description'})
|
||||
keywords = soup.find('meta', attrs={'name': 'keywords'})
|
||||
|
||||
description_content = description['content'] if description else 'No description found'
|
||||
keywords_content = keywords['content'] if keywords else 'No keywords found'
|
||||
|
||||
context = {
|
||||
'title': title,
|
||||
'description': description_content,
|
||||
'keywords': keywords_content,
|
||||
'url': url,
|
||||
}
|
||||
return render(request, 'core/website_seo.html', context)
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
return render(request, 'core/website_seo.html', {'error': f'Error fetching URL: {e}'})
|
||||
|
||||
return render(request, "core/website_seo.html")
|
||||
|
||||
def youtube_seo(request):
|
||||
videos = []
|
||||
if request.method == 'GET':
|
||||
search_query = request.GET.get('q', '')
|
||||
if search_query:
|
||||
try:
|
||||
youtube = build('youtube', 'v3', developerKey=settings.YOUTUBE_API_KEY)
|
||||
search_response = youtube.search().list(
|
||||
q=search_query,
|
||||
part='snippet',
|
||||
maxResults=25
|
||||
).execute()
|
||||
|
||||
video_ids = [item['id']['videoId'] for item in search_response.get('items', []) if item['id']['kind'] == 'youtube#video']
|
||||
|
||||
if video_ids:
|
||||
video_details_response = youtube.videos().list(
|
||||
part='snippet,statistics',
|
||||
id=','.join(video_ids)
|
||||
).execute()
|
||||
|
||||
video_details = {item['id']: item for item in video_details_response.get('items', [])}
|
||||
|
||||
videos = []
|
||||
for item in search_response.get('items', []):
|
||||
if item['id']['kind'] == 'youtube#video':
|
||||
video_id = item['id']['videoId']
|
||||
if video_id in video_details:
|
||||
item['details'] = video_details[video_id]
|
||||
videos.append(item)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error fetching YouTube videos: {e}")
|
||||
|
||||
return render(request, "core/youtube_seo.html", {'videos': videos})
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
Django==5.2.7
|
||||
mysqlclient==2.2.7
|
||||
python-dotenv==1.1.1
|
||||
google-api-python-client==2.110.0
|
||||
requests==2.31.0
|
||||
beautifulsoup4==4.12.3
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user