modified: app.py

modified:   bot.py
	modified:   templates/navigation.html
	modified:   templates/privacy_policy.html
	new file:   templates/user_contact.html
This commit is contained in:
SimolZimol
2025-08-24 22:42:16 +02:00
parent 52739bf189
commit ae57673029
5 changed files with 999 additions and 19 deletions

View File

@@ -52,6 +52,11 @@
<i class="fas fa-server"></i> Server Selection
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('user_contact') }}">
<i class="fas fa-headset"></i> Contact Support
</a>
</li>
<!-- Admin Link nur für Bot-Admins anzeigen -->
{% if g.is_admin %}
<li class="nav-item">

View File

@@ -194,6 +194,15 @@
We are committed to protecting your privacy and being transparent about our data practices.
This policy explains what information we collect, why we collect it, and how you can manage your data.
</p>
<div class="data-type">
<h4><i class="fas fa-building"></i> <span class="highlight">Data Controller Information</span></h4>
<p class="privacy-text">
<strong>Data Controller:</strong> SimolZimol (Individual Developer)<br>
<strong>Contact:</strong> Available through Discord (@simolzimol) or our contact form<br>
<strong>Location:</strong> European Union<br>
<strong>Legal Basis:</strong> Legitimate interest for service operation and user consent for data processing
</p>
</div>
</div>
<div class="privacy-section">
@@ -248,6 +257,20 @@
<i class="fas fa-cogs section-icon"></i>
3. How We Use Your Information
</h2>
<p class="privacy-text">
We process your personal data based on the following legal bases under GDPR:
</p>
<div class="data-type">
<h4><i class="fas fa-balance-scale"></i> <span class="highlight">Legal Basis for Processing</span></h4>
<ul class="privacy-list">
<li><strong>Legitimate Interest (Art. 6(1)(f) GDPR):</strong> Service operation, security, and improvement</li>
<li><strong>Consent (Art. 6(1)(a) GDPR):</strong> Optional features and analytics (where applicable)</li>
<li><strong>Contract Performance (Art. 6(1)(b) GDPR):</strong> Providing the bot service you requested</li>
<li><strong>Legal Obligation (Art. 6(1)(c) GDPR):</strong> Compliance with applicable laws</li>
</ul>
</div>
<p class="privacy-text">
We use the collected information for the following purposes:
</p>
@@ -255,7 +278,7 @@
<li><strong>Service Operation:</strong> To provide moderation, management, and administrative features</li>
<li><strong>User Experience:</strong> To personalize your experience and maintain user preferences</li>
<li><strong>Moderation:</strong> To enforce server rules and maintain community safety</li>
<li><strong>Analytics:</strong> To understand usage patterns and improve service quality</li>
<li><strong>Analytics:</strong> To understand usage patterns and improve service quality (anonymized where possible)</li>
<li><strong>Communication:</strong> To send important updates and respond to support requests</li>
<li><strong>Security:</strong> To detect and prevent abuse, spam, and security threats</li>
</ul>
@@ -290,12 +313,24 @@
We do not sell, trade, or rent your personal information to third parties. We may share your information only in the following circumstances:
</p>
<ul class="privacy-list">
<li><strong>Discord Platform:</strong> As required for bot functionality through Discord's API</li>
<li><strong>Server Administrators:</strong> Moderation data may be visible to server moderators and administrators</li>
<li><strong>Discord Platform:</strong> As required for bot functionality through Discord's API (Discord Inc., USA - adequate protection under Privacy Shield successor)</li>
<li><strong>Server Administrators:</strong> Moderation data may be visible to server moderators and administrators within your Discord server</li>
<li><strong>Legal Requirements:</strong> When required by law, court order, or government regulation</li>
<li><strong>Service Providers:</strong> With trusted third-party services that help us operate (hosting, analytics)</li>
<li><strong>Service Providers:</strong> With trusted third-party services that help us operate (hosting providers within EU/EEA)</li>
<li><strong>Safety and Security:</strong> To protect the rights, property, or safety of our users or others</li>
</ul>
<div class="data-type">
<h4><i class="fas fa-globe"></i> <span class="highlight">International Data Transfers</span></h4>
<p class="privacy-text">
Some of our service providers may be located outside the European Economic Area (EEA). In such cases:
</p>
<ul class="privacy-list">
<li>We ensure adequate protection through approved mechanisms (adequacy decisions, standard contractual clauses)</li>
<li>Discord Inc. (USA) is covered by appropriate safeguards for international transfers</li>
<li>We minimize data transfers outside the EEA where possible</li>
</ul>
</div>
</div>
<div class="privacy-section">
@@ -325,18 +360,37 @@
7. Your Rights and Choices
</h2>
<p class="privacy-text">
You have the following rights regarding your personal information:
Under the General Data Protection Regulation (GDPR), you have the following rights regarding your personal information:
</p>
<ul class="privacy-list">
<li><strong>Access:</strong> Request information about what personal data we have about you</li>
<li><strong>Correction:</strong> Request correction of inaccurate or incomplete data</li>
<li><strong>Deletion:</strong> Request deletion of your personal data (subject to retention requirements)</li>
<li><strong>Portability:</strong> Request a copy of your data in a machine-readable format</li>
<li><strong>Objection:</strong> Object to processing of your data for certain purposes</li>
<li><strong>Restriction:</strong> Request restriction of processing under certain circumstances</li>
</ul>
<div class="data-type">
<h4><i class="fas fa-user-shield"></i> <span class="highlight">Your GDPR Rights</span></h4>
<ul class="privacy-list">
<li><strong>Right of Access (Art. 15):</strong> Request information about what personal data we have about you</li>
<li><strong>Right to Rectification (Art. 16):</strong> Request correction of inaccurate or incomplete data</li>
<li><strong>Right to Erasure (Art. 17):</strong> Request deletion of your personal data ("right to be forgotten")</li>
<li><strong>Right to Restrict Processing (Art. 18):</strong> Request restriction of processing under certain circumstances</li>
<li><strong>Right to Data Portability (Art. 20):</strong> Request a copy of your data in a machine-readable format</li>
<li><strong>Right to Object (Art. 21):</strong> Object to processing of your data for certain purposes</li>
<li><strong>Right to Withdraw Consent (Art. 7):</strong> Withdraw consent at any time where processing is based on consent</li>
</ul>
</div>
<div class="retention-period">
<h4><i class="fas fa-clock"></i> How to Exercise Your Rights</h4>
<p class="privacy-text">
To exercise these rights, please contact us through our <a href="{{ url_for('contact') }}" style="color: #667eea;">contact form</a>
or Discord (@simolzimol). We will respond to your request within 30 days as required by GDPR.
</p>
<p class="privacy-text">
<strong>Right to Lodge a Complaint:</strong> You have the right to lodge a complaint with your local data protection authority
if you believe we have not adequately addressed your concerns.
</p>
</div>
<p class="privacy-text">
To exercise these rights, please contact us through our <a href="{{ url_for('contact') }}" style="color: #667eea;">contact form</a>.
<strong>Note:</strong> Some rights may be limited by applicable law or necessary for the legitimate operation of our service.
We will inform you of any such limitations when responding to your request.
</p>
</div>
@@ -379,19 +433,45 @@
10. Changes to This Privacy Policy
</h2>
<p class="privacy-text">
We may update this Privacy Policy from time to time. We will notify you of any material changes by:
We may update this Privacy Policy from time to time to reflect changes in our practices or applicable law. We will notify you of any material changes by:
</p>
<ul class="privacy-list">
<li>Posting the new Privacy Policy on this page</li>
<li>Updating the "Last Updated" date at the top of this policy</li>
<li>Providing notice through our service or other communication methods</li>
<li>Posting the new Privacy Policy on this page with an updated "Last Updated" date</li>
<li>Providing prominent notice through our service for significant changes</li>
<li>Sending direct notification where we have your contact information (for material changes affecting your rights)</li>
</ul>
<p class="privacy-text">
Your continued use of the Service after the effective date of the revised Privacy Policy
constitutes acceptance of the revised policy.
constitutes acceptance of the revised policy. If you do not agree to the changes, please stop using our service.
</p>
</div>
<div class="privacy-section">
<h2 class="section-title">
<i class="fas fa-balance-scale section-icon"></i>
11. Legal Compliance and Supervisory Authority
</h2>
<div class="data-type">
<h4><i class="fas fa-gavel"></i> <span class="highlight">GDPR Compliance</span></h4>
<p class="privacy-text">
This service is operated in compliance with the General Data Protection Regulation (EU) 2016/679.
As a service primarily targeting EU users, we adhere to GDPR requirements regardless of your location.
</p>
</div>
<div class="retention-period">
<h4><i class="fas fa-shield-alt"></i> Supervisory Authority Contact</h4>
<p class="privacy-text">
If you believe we have not adequately addressed your data protection concerns, you have the right to lodge a complaint with:
</p>
<ul class="privacy-list">
<li><strong>Your local data protection authority</strong> in your EU member state</li>
<li><strong>The lead supervisory authority</strong> where our main establishment is located</li>
<li>You can find your local DPA contact information at: <a href="https://edpb.europa.eu/about-edpb/about-edpb/members_en" target="_blank" style="color: #667eea;">European Data Protection Board</a></li>
</ul>
</div>
</div>
<div class="contact-info">
<h2 class="section-title">
<i class="fas fa-envelope section-icon"></i>

407
templates/user_contact.html Normal file
View File

@@ -0,0 +1,407 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Contact Support - Multus Bot</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
body {
background: linear-gradient(135deg, #0c1426 0%, #1a1f2e 25%, #2d3748 75%, #0c1426 100%);
min-height: 100vh;
color: #e2e8f0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
display: flex;
flex-direction: column;
}
.contact-container {
background: rgba(26, 31, 46, 0.9);
backdrop-filter: blur(15px);
border: 1px solid rgba(102, 126, 234, 0.2);
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
padding: 3rem;
margin: 2rem auto;
max-width: 900px;
flex: 1;
}
.contact-header {
text-align: center;
margin-bottom: 3rem;
padding-bottom: 2rem;
border-bottom: 1px solid rgba(102, 126, 234, 0.1);
}
.contact-title {
color: #f8fafc;
font-weight: 700;
font-size: 2.5rem;
margin-bottom: 1rem;
text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
}
.contact-icon {
color: #667eea;
font-size: 2.5rem;
}
.contact-subtitle {
color: #a0aec0;
font-size: 1.2rem;
font-weight: 400;
}
.user-info-card {
background: rgba(45, 55, 72, 0.6);
border: 1px solid rgba(102, 126, 234, 0.2);
border-radius: 15px;
padding: 1.5rem;
margin-bottom: 2rem;
display: flex;
align-items: center;
gap: 1rem;
}
.user-avatar {
width: 60px;
height: 60px;
border-radius: 50%;
border: 2px solid #667eea;
}
.user-details h5 {
color: #f8fafc;
margin: 0;
font-weight: 600;
}
.user-details p {
color: #a0aec0;
margin: 0;
font-size: 0.9rem;
}
.form-group label {
color: #e2e8f0;
font-weight: 600;
margin-bottom: 0.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.form-control {
background: rgba(45, 55, 72, 0.7);
border: 1px solid rgba(102, 126, 234, 0.3);
border-radius: 10px;
color: #e2e8f0;
font-size: 1rem;
padding: 0.75rem 1rem;
transition: all 0.3s ease;
}
.form-control:focus {
background: rgba(45, 55, 72, 0.9);
border-color: #667eea;
box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
color: #f8fafc;
}
.form-control::placeholder {
color: #a0aec0;
}
textarea.form-control {
min-height: 120px;
resize: vertical;
}
.priority-selector {
display: flex;
gap: 1rem;
margin-top: 0.5rem;
}
.priority-option {
flex: 1;
padding: 0.75rem;
background: rgba(45, 55, 72, 0.7);
border: 1px solid rgba(102, 126, 234, 0.3);
border-radius: 10px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
color: #a0aec0;
}
.priority-option:hover {
border-color: #667eea;
background: rgba(45, 55, 72, 0.9);
}
.priority-option.selected {
background: rgba(102, 126, 234, 0.2);
border-color: #667eea;
color: #f8fafc;
}
.priority-low { border-left: 4px solid #48bb78; }
.priority-medium { border-left: 4px solid #ed8936; }
.priority-high { border-left: 4px solid #f56565; }
.priority-urgent { border-left: 4px solid #e53e3e; }
.submit-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
color: white;
padding: 1rem 2rem;
border-radius: 50px;
font-weight: 600;
font-size: 1.1rem;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
display: flex;
align-items: center;
gap: 0.5rem;
margin: 0 auto;
}
.submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
color: white;
}
.submit-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.info-section {
background: rgba(72, 187, 120, 0.1);
border: 1px solid rgba(72, 187, 120, 0.3);
border-radius: 15px;
padding: 1.5rem;
margin-bottom: 2rem;
}
.info-section h6 {
color: #48bb78;
font-weight: 600;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.alert-success {
background: rgba(72, 187, 120, 0.2);
border: 1px solid rgba(72, 187, 120, 0.4);
border-radius: 15px;
color: #48bb78;
padding: 1rem;
margin-bottom: 2rem;
}
.alert-danger {
background: rgba(245, 101, 101, 0.2);
border: 1px solid rgba(245, 101, 101, 0.4);
border-radius: 15px;
color: #f56565;
padding: 1rem;
margin-bottom: 2rem;
}
@media (max-width: 768px) {
.contact-container {
margin: 1rem;
padding: 2rem;
}
.contact-title {
font-size: 2rem;
}
.priority-selector {
flex-direction: column;
}
}
</style>
</head>
<body>
{% include 'navigation.html' %}
<div class="container-fluid" style="flex: 1;">
<div class="contact-container">
<div class="contact-header">
<h1 class="contact-title">
<i class="fas fa-headset contact-icon"></i>
Contact Support
</h1>
<p class="contact-subtitle">Need help? Send us a message and we'll get back to you soon!</p>
</div>
{% if user_info %}
<div class="user-info-card">
<img src="{{ user_info.avatar_url }}" alt="Avatar" class="user-avatar">
<div class="user-details">
<h5>{{ user_info.global_name or user_info.username }}</h5>
<p><i class="fab fa-discord"></i> {{ user_info.username }}#{{ user_info.discriminator }} (ID: {{ user_info.id }})</p>
</div>
</div>
{% endif %}
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ 'success' if category == 'success' else 'danger' }}">
<i class="fas fa-{{ 'check-circle' if category == 'success' else 'exclamation-triangle' }}"></i>
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="info-section">
<h6><i class="fas fa-info-circle"></i> How it works</h6>
<ul style="color: #a0aec0; margin: 0; padding-left: 1.5rem;">
<li>Your Discord information is automatically included with your message</li>
<li>Messages are sent directly to the bot administrator via Discord DM</li>
<li>We typically respond within 24 hours</li>
<li>For urgent issues, please join our Discord server for faster support</li>
</ul>
</div>
<form method="POST" action="{{ url_for('user_contact') }}">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="subject">
<i class="fas fa-tag"></i> Subject
</label>
<input type="text" class="form-control" id="subject" name="subject"
placeholder="Brief description of your issue" required maxlength="100">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="category">
<i class="fas fa-folder"></i> Category
</label>
<select class="form-control" id="category" name="category" required>
<option value="">Select a category</option>
<option value="bug_report">🐛 Bug Report</option>
<option value="feature_request">💡 Feature Request</option>
<option value="account_issue">👤 Account Issue</option>
<option value="moderation">🛡️ Moderation Help</option>
<option value="giveaway">🎁 Giveaway Support</option>
<option value="privacy">🔒 Privacy/Data Request</option>
<option value="technical">⚙️ Technical Support</option>
<option value="other">❓ Other</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<label for="priority">
<i class="fas fa-exclamation-circle"></i> Priority Level
</label>
<div class="priority-selector">
<div class="priority-option priority-low" onclick="selectPriority('low', this)">
<i class="fas fa-circle" style="color: #48bb78;"></i><br>
<strong>Low</strong><br>
<small>General inquiry</small>
</div>
<div class="priority-option priority-medium" onclick="selectPriority('medium', this)">
<i class="fas fa-circle" style="color: #ed8936;"></i><br>
<strong>Medium</strong><br>
<small>Need assistance</small>
</div>
<div class="priority-option priority-high" onclick="selectPriority('high', this)">
<i class="fas fa-circle" style="color: #f56565;"></i><br>
<strong>High</strong><br>
<small>Important issue</small>
</div>
<div class="priority-option priority-urgent" onclick="selectPriority('urgent', this)">
<i class="fas fa-circle" style="color: #e53e3e;"></i><br>
<strong>Urgent</strong><br>
<small>Critical problem</small>
</div>
</div>
<input type="hidden" id="priority" name="priority" required>
</div>
<div class="form-group">
<label for="message">
<i class="fas fa-comment-alt"></i> Message
</label>
<textarea class="form-control" id="message" name="message" rows="6"
placeholder="Please provide detailed information about your issue or request..."
required maxlength="2000"></textarea>
<small class="text-muted">Maximum 2000 characters</small>
</div>
<div class="form-group">
<label for="server_context">
<i class="fas fa-server"></i> Server Context (Optional)
</label>
<input type="text" class="form-control" id="server_context" name="server_context"
placeholder="If your issue is related to a specific server, mention it here" maxlength="200">
</div>
<div class="text-center">
<button type="submit" class="submit-btn">
<i class="fas fa-paper-plane"></i>
Send Message
</button>
</div>
</form>
</div>
</div>
{% include 'footer.html' %}
<script>
function selectPriority(priority, element) {
// Remove selected class from all options
document.querySelectorAll('.priority-option').forEach(option => {
option.classList.remove('selected');
});
// Add selected class to clicked option
element.classList.add('selected');
// Set hidden input value
document.getElementById('priority').value = priority;
}
// Character counter for message
document.getElementById('message').addEventListener('input', function() {
const maxLength = 2000;
const currentLength = this.value.length;
const remaining = maxLength - currentLength;
// You can add a character counter here if desired
});
// Form validation
document.querySelector('form').addEventListener('submit', function(e) {
const priority = document.getElementById('priority').value;
if (!priority) {
e.preventDefault();
alert('Please select a priority level.');
return;
}
});
</script>
</body>
</html>