Files
CyberPanel/pluginHolder/templates/pluginHolder/help.html
master3395 d388e993d5 Fix help.html template - escape Django template tags in code examples
- Replace {% with {%% in code examples to prevent template parsing errors
- Fixes 'block tag with name title appears more than once' error
- Code examples now display correctly without being parsed as actual template blocks
2026-01-20 01:01:40 +01:00

660 lines
23 KiB
HTML

{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% load static %}
{% block title %}{% trans "Plugin Development Help - CyberPanel" %}{% endblock %}
{% block header_scripts %}
<style>
.help-wrapper {
background: transparent;
padding: 20px;
max-width: 1400px;
margin: 0 auto;
}
.help-header {
background: var(--bg-primary, white);
border-radius: 12px;
padding: 30px;
margin-bottom: 25px;
box-shadow: var(--shadow-md, 0 2px 8px rgba(0,0,0,0.08));
border: 1px solid var(--border-primary, #e8e9ff);
}
.help-header h1 {
font-size: 32px;
font-weight: 700;
color: var(--text-primary, #2f3640);
margin: 0 0 10px 0;
display: flex;
align-items: center;
gap: 15px;
}
.help-header .icon {
width: 56px;
height: 56px;
background: #5856d6;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 28px;
box-shadow: 0 4px 12px rgba(88,86,214,0.3);
}
.help-header p {
font-size: 16px;
color: var(--text-secondary, #64748b);
margin: 0;
line-height: 1.6;
}
.help-content {
background: var(--bg-primary, white);
border-radius: 12px;
padding: 40px;
box-shadow: var(--shadow-md, 0 2px 8px rgba(0,0,0,0.08));
border: 1px solid var(--border-primary, #e8e9ff);
}
.help-content h2 {
font-size: 24px;
font-weight: 700;
color: var(--text-primary, #2f3640);
margin: 30px 0 15px 0;
padding-bottom: 10px;
border-bottom: 2px solid #5856d6;
}
.help-content h3 {
font-size: 20px;
font-weight: 600;
color: var(--text-primary, #2f3640);
margin: 25px 0 12px 0;
}
.help-content h4 {
font-size: 18px;
font-weight: 600;
color: var(--text-primary, #2f3640);
margin: 20px 0 10px 0;
}
.help-content p {
font-size: 15px;
color: var(--text-secondary, #64748b);
line-height: 1.8;
margin: 12px 0;
}
.help-content ul, .help-content ol {
margin: 15px 0;
padding-left: 30px;
}
.help-content li {
font-size: 15px;
color: var(--text-secondary, #64748b);
line-height: 1.8;
margin: 8px 0;
}
.help-content code {
background: var(--bg-secondary, #f8f9ff);
padding: 2px 6px;
border-radius: 4px;
font-family: 'Courier New', monospace;
font-size: 14px;
color: #5856d6;
}
.help-content pre {
background: #1e1e1e;
color: #d4d4d4;
padding: 20px;
border-radius: 8px;
overflow-x: auto;
margin: 20px 0;
font-family: 'Courier New', monospace;
font-size: 14px;
line-height: 1.6;
}
.help-content pre code {
background: transparent;
color: inherit;
padding: 0;
}
.help-content blockquote {
border-left: 4px solid #5856d6;
padding-left: 20px;
margin: 20px 0;
font-style: italic;
color: var(--text-secondary, #64748b);
}
.help-content table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.help-content table th,
.help-content table td {
padding: 12px;
border: 1px solid var(--border-primary, #e8e9ff);
text-align: left;
}
.help-content table th {
background: var(--bg-secondary, #f8f9ff);
font-weight: 600;
color: var(--text-primary, #2f3640);
}
.help-content table td {
color: var(--text-secondary, #64748b);
}
.help-content .alert {
padding: 15px 20px;
border-radius: 8px;
margin: 20px 0;
border-left: 4px solid;
}
.help-content .alert-info {
background: #e0f2fe;
border-color: #0ea5e9;
color: #0c4a6e;
}
.help-content .alert-warning {
background: #fef3c7;
border-color: #f59e0b;
color: #92400e;
}
.help-content .alert-success {
background: #d1fae5;
border-color: #10b981;
color: #065f46;
}
.help-content .alert-danger {
background: #fee2e2;
border-color: #ef4444;
color: #991b1b;
}
.toc {
background: var(--bg-secondary, #f8f9ff);
border-radius: 8px;
padding: 20px;
margin: 30px 0;
border: 1px solid var(--border-primary, #e8e9ff);
}
.toc h3 {
margin-top: 0;
color: var(--text-primary, #2f3640);
}
.toc ul {
list-style: none;
padding-left: 0;
}
.toc li {
margin: 8px 0;
}
.toc a {
color: #5856d6;
text-decoration: none;
font-size: 15px;
}
.toc a:hover {
text-decoration: underline;
}
.code-block {
position: relative;
}
.code-block::before {
content: attr(data-language);
position: absolute;
top: 10px;
right: 15px;
background: rgba(255,255,255,0.1);
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
color: #d4d4d4;
}
.badge {
display: inline-block;
padding: 4px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
}
.badge-required {
background: #fee2e2;
color: #991b1b;
}
.badge-optional {
background: #d1fae5;
color: #065f46;
}
.back-link {
display: inline-flex;
align-items: center;
gap: 8px;
color: #5856d6;
text-decoration: none;
font-weight: 600;
margin-bottom: 20px;
transition: all 0.3s ease;
}
.back-link:hover {
color: #4a90e2;
text-decoration: underline;
}
@media (max-width: 768px) {
.help-wrapper {
padding: 15px;
}
.help-content {
padding: 25px;
}
.help-header h1 {
font-size: 24px;
flex-direction: column;
}
.help-content pre {
font-size: 12px;
padding: 15px;
}
}
</style>
{% endblock %}
{% block content %}
<div class="help-wrapper">
<a href="/plugins/installed" class="back-link">
<i class="fas fa-arrow-left"></i>
{% trans "Back to Installed Plugins" %}
</a>
<div class="help-header">
<h1>
<div class="icon">
<i class="fas fa-book"></i>
</div>
{% trans "Plugin Development Guide" %}
</h1>
<p>{% trans "Comprehensive guide to creating plugins for CyberPanel. Learn how to build, package, and distribute your own plugins." %}</p>
</div>
<div class="help-content">
<div class="toc">
<h3>{% trans "Table of Contents" %}</h3>
<ul>
<li><a href="#introduction">{% trans "Introduction" %}</a></li>
<li><a href="#prerequisites">{% trans "Prerequisites" %}</a></li>
<li><a href="#architecture">{% trans "Plugin Architecture Overview" %}</a></li>
<li><a href="#first-plugin">{% trans "Creating Your First Plugin" %}</a></li>
<li><a href="#structure">{% trans "Plugin Structure & Files" %}</a></li>
<li><a href="#components">{% trans "Core Components" %}</a></li>
<li><a href="#advanced">{% trans "Advanced Features" %}</a></li>
<li><a href="#best-practices">{% trans "Best Practices" %}</a></li>
<li><a href="#security">{% trans "Security Guidelines" %}</a></li>
<li><a href="#testing">{% trans "Testing & Debugging" %}</a></li>
<li><a href="#packaging">{% trans "Packaging & Distribution" %}</a></li>
<li><a href="#troubleshooting">{% trans "Troubleshooting" %}</a></li>
<li><a href="#examples">{% trans "Examples & References" %}</a></li>
</ul>
</div>
<h2 id="introduction">{% trans "Introduction" %}</h2>
<p>{% trans "CyberPanel's plugin system allows developers to extend the control panel's functionality with custom features. Plugins integrate seamlessly with CyberPanel's Django-based architecture, providing access to the full power of the platform while maintaining security and consistency." %}</p>
<h3>{% trans "What Can Plugins Do?" %}</h3>
<ul>
<li>{% trans "Add new administrative features" %}</li>
<li>{% trans "Integrate with external services (APIs, webhooks, etc.)" %}</li>
<li>{% trans "Customize the user interface" %}</li>
<li>{% trans "Extend database functionality" %}</li>
<li>{% trans "Add automation and monitoring capabilities" %}</li>
<li>{% trans "Create custom reporting tools" %}</li>
<li>{% trans "Integrate security features" %}</li>
</ul>
<h2 id="prerequisites">{% trans "Prerequisites" %}</h2>
<h3>{% trans "Required Knowledge" %}</h3>
<ul>
<li><strong>Python 3.6+</strong>: {% trans "Basic to intermediate Python knowledge" %}</li>
<li><strong>Django Framework</strong>: {% trans "Understanding of Django views, URLs, templates, and models" %}</li>
<li><strong>HTML/CSS/JavaScript</strong>: {% trans "For creating user interfaces" %}</li>
<li><strong>Linux/Unix</strong>: {% trans "Basic command-line familiarity" %}</li>
<li><strong>XML</strong>: {% trans "Understanding of XML structure for meta.xml" %}</li>
</ul>
<h2 id="architecture">{% trans "Plugin Architecture Overview" %}</h2>
<h3>{% trans "How Plugins Work" %}</h3>
<ol>
<li><strong>{% trans "Plugin Source Location" %}</strong>: <code>/home/cyberpanel/plugins/</code>
<ul>
<li>{% trans "Plugins are stored here before installation" %}</li>
<li>{% trans "Can be uploaded as ZIP files or placed directly" %}</li>
</ul>
</li>
<li><strong>{% trans "Installed Location" %}</strong>: <code>/usr/local/CyberCP/</code>
<ul>
<li>{% trans "After installation, plugins are copied here" %}</li>
<li>{% trans "This is where CyberPanel loads plugins from" %}</li>
</ul>
</li>
</ol>
<h2 id="first-plugin">{% trans "Creating Your First Plugin" %}</h2>
<h3>{% trans "Step 1: Create Plugin Directory Structure" %}</h3>
<pre><code># Navigate to plugins directory
cd /home/cyberpanel/plugins
# Create your plugin directory
mkdir myFirstPlugin
cd myFirstPlugin
# Create required subdirectories
mkdir -p templates/myFirstPlugin
mkdir -p static/myFirstPlugin/css
mkdir -p static/myFirstPlugin/js
mkdir -p migrations</code></pre>
<h3>{% trans "Step 2: Create meta.xml (REQUIRED)" %}</h3>
<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;cyberpanelPluginConfig&gt;
&lt;name&gt;My First Plugin&lt;/name&gt;
&lt;type&gt;Utility&lt;/type&gt;
&lt;description&gt;A simple example plugin&lt;/description&gt;
&lt;version&gt;1.0.0&lt;/version&gt;
&lt;url&gt;/plugins/myFirstPlugin/&lt;/url&gt;
&lt;settings_url&gt;/plugins/myFirstPlugin/settings/&lt;/settings_url&gt;
&lt;/cyberpanelPluginConfig&gt;</code></pre>
<h3>{% trans "Step 3: Create urls.py" %}</h3>
<pre><code>from django.urls import path
from . import views
app_name = 'myFirstPlugin'
urlpatterns = [
path('', views.main_view, name='main'),
path('settings/', views.settings_view, name='settings'),
]</code></pre>
<h3>{% trans "Step 4: Create views.py" %}</h3>
<pre><code>from django.shortcuts import render, redirect
from functools import wraps
def cyberpanel_login_required(view_func):
"""Custom decorator for CyberPanel session authentication"""
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
try:
userID = request.session['userID']
return view_func(request, *args, **kwargs)
except KeyError:
from loginSystem.views import loadLoginPage
return redirect(loadLoginPage)
return _wrapped_view
@cyberpanel_login_required
def main_view(request):
context = {
'plugin_name': 'My First Plugin',
'version': '1.0.0'
}
return render(request, 'myFirstPlugin/main.html', context)</code></pre>
<h3>{% trans "Step 5: Create Templates" %}</h3>
<p>{% trans "Templates must extend baseTemplate/index.html:" %}</p>
<pre><code>&lt;!-- Example template code (replace {% with HTML entities) --&gt;
{%% extends "baseTemplate/index.html" %%}
{%% load static %%}
{%% load i18n %%}
{%% block title %%}
My First Plugin - {%% trans "CyberPanel" %%}
{%% endblock %%}
{%% block content %%}
&lt;div class="container"&gt;
&lt;h1&gt;{{ plugin_name }}&lt;/h1&gt;
&lt;p&gt;Version {{ version }}&lt;/p&gt;
&lt;/div&gt;
{%% endblock %%}</code></pre>
<div class="alert alert-info">
<strong>{% trans "Important" %}:</strong> {% trans "Always use the @cyberpanel_login_required decorator for all views to ensure users are authenticated." %}
</div>
<h2 id="structure">{% trans "Plugin Structure & Files" %}</h2>
<h3>{% trans "Required Files" %}</h3>
<ul>
<li><code>__init__.py</code> - <span class="badge badge-required">{% trans "Required" %}</span> - {% trans "Python package marker" %}</li>
<li><code>meta.xml</code> - <span class="badge badge-required">{% trans "Required" %}</span> - {% trans "Plugin metadata" %}</li>
<li><code>urls.py</code> - <span class="badge badge-required">{% trans "Required" %}</span> - {% trans "URL routing" %}</li>
<li><code>views.py</code> - <span class="badge badge-required">{% trans "Required" %}</span> - {% trans "View functions" %}</li>
</ul>
<h3>{% trans "Optional Files" %}</h3>
<ul>
<li><code>models.py</code> - <span class="badge badge-optional">{% trans "Optional" %}</span> - {% trans "Database models" %}</li>
<li><code>forms.py</code> - <span class="badge badge-optional">{% trans "Optional" %}</span> - {% trans "Django forms" %}</li>
<li><code>utils.py</code> - <span class="badge badge-optional">{% trans "Optional" %}</span> - {% trans "Utility functions" %}</li>
<li><code>templates/</code> - <span class="badge badge-optional">{% trans "Optional" %}</span> - {% trans "HTML templates" %}</li>
<li><code>static/</code> - <span class="badge badge-optional">{% trans "Optional" %}</span> - {% trans "CSS, JS, images" %}</li>
</ul>
<h2 id="components">{% trans "Core Components" %}</h2>
<h3>{% trans "1. Authentication & Security" %}</h3>
<p>{% trans "Always use the cyberpanel_login_required decorator:" %}</p>
<pre><code>@cyberpanel_login_required
def my_view(request):
# Your view code
pass</code></pre>
<h3>{% trans "2. URL Routing" %}</h3>
<pre><code>from django.urls import path
from . import views
app_name = 'myPlugin'
urlpatterns = [
path('', views.main_view, name='main'),
path('item/&lt;int:item_id&gt;/', views.item_detail, name='item_detail'),
]</code></pre>
<h3>{% trans "3. Templates" %}</h3>
<p>{% trans "Always extend baseTemplate/index.html:" %}</p>
<pre><code>{% extends "baseTemplate/index.html" %}
{% load static %}
{% load i18n %}</code></pre>
<h2 id="advanced">{% trans "Advanced Features" %}</h2>
<h3>{% trans "Database Models" %}</h3>
<pre><code>from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'my_plugin_mymodel'</code></pre>
<h3>{% trans "Forms" %}</h3>
<pre><code>from django import forms
class MyForm(forms.Form):
name = forms.CharField(max_length=255, required=True)
email = forms.EmailField(required=True)</code></pre>
<h3>{% trans "API Endpoints" %}</h3>
<pre><code>from django.http import JsonResponse
@cyberpanel_login_required
def api_endpoint(request):
data = {'status': 'success'}
return JsonResponse(data)</code></pre>
<h2 id="best-practices">{% trans "Best Practices" %}</h2>
<ul>
<li>{% trans "Keep files under 500 lines - split into modules if needed" %}</li>
<li>{% trans "Use descriptive names for functions and variables" %}</li>
<li>{% trans "Follow PEP 8 Python style guide" %}</li>
<li>{% trans "Add comments for complex logic" %}</li>
<li>{% trans "Always validate user input" %}</li>
<li>{% trans "Use Django ORM instead of raw SQL" %}</li>
<li>{% trans "Test your plugin thoroughly before distribution" %}</li>
</ul>
<h2 id="security">{% trans "Security Guidelines" %}</h2>
<div class="alert alert-warning">
<strong>{% trans "Security is Critical" %}:</strong> {% trans "Always validate input, use parameterized queries, sanitize output, and check user permissions." %}
</div>
<ul>
<li>{% trans "Always validate and sanitize user input" %}</li>
<li>{% trans "Use Django ORM or parameterized queries" %}</li>
<li>{% trans "Escape HTML in templates (Django does this by default)" %}</li>
<li>{% trans "Validate file uploads (type, size, content)" %}</li>
<li>{% trans "Use HTTPS for sensitive operations" %}</li>
<li>{% trans "Implement rate limiting for API endpoints" %}</li>
</ul>
<h2 id="testing">{% trans "Testing & Debugging" %}</h2>
<h3>{% trans "Common Issues" %}</h3>
<ul>
<li><strong>{% trans "Template Not Found" %}</strong>: {% trans "Check template path and name" %}</li>
<li><strong>{% trans "URL Not Found" %}</strong>: {% trans "Verify URL patterns and app_name" %}</li>
<li><strong>{% trans "Import Errors" %}</strong>: {% trans "Check Python syntax and import paths" %}</li>
<li><strong>{% trans "Static Files Not Loading" %}</strong>: {% trans "Run collectstatic command" %}</li>
</ul>
<h3>{% trans "Debugging Commands" %}</h3>
<pre><code># Check Python syntax
python3 -m py_compile views.py
# Check XML validity
xmllint --noout meta.xml
# View logs
tail -f /usr/local/lscp/logs/error.log</code></pre>
<h2 id="packaging">{% trans "Packaging & Distribution" %}</h2>
<h3>{% trans "Create Plugin Package" %}</h3>
<pre><code>cd /home/cyberpanel/plugins/myPlugin
zip -r myPlugin-v1.0.0.zip . \
-x "*.pyc" \
-x "__pycache__/*" \
-x "*.log"</code></pre>
<h2 id="troubleshooting">{% trans "Troubleshooting" %}</h2>
<h3>{% trans "Installation Issues" %}</h3>
<ul>
<li>{% trans "Check meta.xml format and validity" %}</li>
<li>{% trans "Verify plugin directory exists" %}</li>
<li>{% trans "Check file permissions" %}</li>
<li>{% trans "Review CyberPanel logs" %}</li>
</ul>
<h3>{% trans "Runtime Issues" %}</h3>
<ul>
<li>{% trans "Verify URL routing" %}</li>
<li>{% trans "Check authentication decorator" %}</li>
<li>{% trans "Review template paths" %}</li>
<li>{% trans "Check for JavaScript errors" %}</li>
</ul>
<h2 id="examples">{% trans "Examples & References" %}</h2>
<h3>{% trans "Reference Plugins" %}</h3>
<ul>
<li><strong>examplePlugin</strong>: {% trans "Basic plugin structure" %}
<ul>
<li>{% trans "Location" %}: <code>/usr/local/CyberCP/examplePlugin/</code></li>
<li>{% trans "URL" %}: <code>/plugins/examplePlugin/</code></li>
</ul>
</li>
<li><strong>testPlugin</strong>: {% trans "Comprehensive example" %}
<ul>
<li>{% trans "Location" %}: <code>/usr/local/CyberCP/testPlugin/</code></li>
<li>{% trans "URL" %}: <code>/plugins/testPlugin/</code></li>
<li>{% trans "Author" %}: <strong>usmannasir</strong></li>
</ul>
</li>
<li><strong>discordWebhooks</strong>: {% trans "Discord webhook integration plugin" %}
<ul>
<li>{% trans "Location" %}: <code>/usr/local/CyberCP/discordWebhooks/</code></li>
<li>{% trans "URL" %}: <code>/plugins/discordWebhooks/</code></li>
<li>{% trans "Author" %}: <strong>Master3395</strong></li>
</ul>
</li>
</ul>
<h3>{% trans "Useful Resources" %}</h3>
<ul>
<li><a href="https://cyberpanel.net/KnowledgeBase/" target="_blank">{% trans "CyberPanel Documentation" %}</a></li>
<li><a href="https://docs.djangoproject.com/" target="_blank">{% trans "Django Documentation" %}</a></li>
<li><a href="https://github.com/master3395/cyberpanel/tree/v2.5.5-dev" target="_blank">{% trans "CyberPanel GitHub Repository" %}</a></li>
<li><a href="https://github.com/master3395/cyberpanel/tree/v2.5.5-dev/docs/PLUGIN_DEVELOPMENT_GUIDE.md" target="_blank">{% trans "Full Plugin Development Guide (Markdown)" %}</a></li>
</ul>
<div class="alert alert-success">
<strong>{% trans "Ready to Start?" %}</strong> {% trans "Begin with a simple plugin and gradually add more features as you become familiar with the system. Check the examplePlugin and testPlugin directories for complete working examples." %}
</div>
<div style="margin-top: 40px; padding-top: 20px; border-top: 2px solid var(--border-primary, #e8e9ff);">
<p style="text-align: center; color: var(--text-secondary, #64748b);">
<strong>{% trans "Author" %}:</strong> master3395 |
<strong>{% trans "Version" %}:</strong> 2.0.0 |
<strong>{% trans "Last Updated" %}:</strong> 2026-01-04
</p>
</div>
</div>
</div>
<script>
// Smooth scrolling for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
</script>
{% endblock %}