Nahrát soubory do „telegram_bot“

This commit is contained in:
Tetiana Mohorian 2025-05-20 11:00:55 +00:00
parent 6d5cd85408
commit b467759c09
13 changed files with 2494 additions and 0 deletions

1
telegram_bot/.env Normal file
View File

@ -0,0 +1 @@
TOKEN=7293191565:AAF70PTx9QgkIvt3BDQGFY64p-ngiaPLAMA

12
telegram_bot/Dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM python:3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app
COPY static/ ./static/
WORKDIR /app
CMD ["python", "bot.py"]

97
telegram_bot/bot.py Normal file
View File

@ -0,0 +1,97 @@
import os
import torch
import logging
from transformers import AutoModelForSequenceClassification, AutoTokenizer
from telegram import Update
from telegram.ext import Application, MessageHandler, filters, CommandHandler, CallbackContext
from dotenv import load_dotenv
import mysql.connector
# Загрузка переменных окружения из .env
load_dotenv()
TOKEN = os.getenv("TOKEN")
# Путь к модели
MODEL_PATH = "./hate_speech_model/final_model"
db_config = {
"host": "mysql",
"user": "root",
"password": "0674998280tanya",
"database": "telegram_bot"
}
def save_violator(username, message):
"""Сохраняет нарушителя в базу данных"""
try:
conn = mysql.connector.connect(**db_config)
cursor = conn.cursor()
query = "INSERT INTO violators (username, message) VALUES (%s, %s)"
cursor.execute(query, (username, message))
conn.commit()
cursor.close()
conn.close()
except mysql.connector.Error as err:
logging.error(f"Ошибка MySQL: {err}")
# Настройка логирования
logging.basicConfig(
format="%(asctime)s - %(levelname)s - %(message)s",
level=logging.INFO,
handlers=[
logging.FileHandler("log.txt"),
logging.StreamHandler()
]
)
# Загрузка модели и токенизатора
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
model = AutoModelForSequenceClassification.from_pretrained(MODEL_PATH).to(device)
def classify_text(text):
"""Функция для классификации текста"""
model.eval()
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding="max_length", max_length=128).to(device)
with torch.no_grad():
outputs = model(**inputs)
logits = outputs.logits
pred = torch.argmax(logits, dim=-1).item()
return "🛑 Nenávistná reč" if pred == 1 else "✅ OK"
async def check_message(update: Update, context: CallbackContext):
"""Проверяет сообщения в чате и реагирует на токсичные сообщения"""
message_text = update.message.text
result = classify_text(message_text)
if result == "🛑 Nenávistná reč":
username = update.message.from_user.username or "unknown"
await update.message.reply_text("⚠️ Upozornenie! Dodržiavajte kultúru komunikácie.")
await update.message.delete() # Автоматическое удаление токсичных сообщений
# Логирование токсичного сообщения
logging.warning(f"Toxická správa od {update.message.from_user.username}: {message_text}")
save_violator(username, message_text)
async def start(update: Update, context: CallbackContext):
"""Отправляет приветственное сообщение при запуске бота"""
await update.message.reply_text("Ahoj! Sledujem kultúru komunikácie v chate!")
def main():
"""Запуск бота"""
app = Application.builder().token(TOKEN).build()
# Добавление обработчиков команд и сообщений
app.add_handler(CommandHandler("start", start))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, check_message))
# Запуск бота
app.run_polling()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,24 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: bot-deployment
namespace: botspace
spec:
replicas: 1
selector:
matchLabels:
app: bot
template:
metadata:
labels:
app: bot
spec:
containers:
- name: hate-speech-bot
image: tetianamohorian/hate-speech-bot:latest
env:
- name: TOKEN
valueFrom:
secretKeyRef:
name: bot-secret
key: TOKEN

View File

@ -0,0 +1,35 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-web
namespace: botspace
spec:
replicas: 1
selector:
matchLabels:
app: flask-web
template:
metadata:
labels:
app: flask-web
spec:
containers:
- name: flask-container
image: tetianamohorian/hate-speech-bot:latest
command: ["python"]
args: ["web_app.py"]
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: flask-service
namespace: botspace
spec:
selector:
app: flask-web
ports:
- port: 5000
targetPort: 5000
protocol: TCP

2063
telegram_bot/log.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
#!/bin/bash
# Zostavenie Docker obrazu
docker build -t tetianamohorian/hate-speech-bot:latest .
# Push obrazu
docker push tetianamohorian/hate-speech-bot:latest

View File

@ -0,0 +1,6 @@
python-telegram-bot==20.3
transformers
torch
python-dotenv
mysql-connector-python
flask

11
telegram_bot/service.yaml Normal file
View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: botspace
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306

13
telegram_bot/start-app.sh Normal file
View File

@ -0,0 +1,13 @@
#!/bin/bash
kubectl create namespace botspace
kubectl create configmap init-sql --from-file=sql/init.sql -n botspace
kubectl create secret generic bot-secret --from-literal=TOKEN=7293191565:AAF70PTx9QgkIvt3BDQGFY64p-ngiaPLAMA -n botspace --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f statefulset.yaml
kubectl apply -f service.yaml
kubectl apply -f deployment.yaml
kubectl apply -f flask-web.yaml
echo "🌐 Spúšťam port-forward na http://localhost:8888"
kubectl port-forward svc/flask-service 8888:5000 -n botspace

View File

@ -0,0 +1,76 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
namespace: botspace
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data/mysql"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
namespace: botspace
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: botspace
spec:
serviceName: "mysql"
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
initContainers:
- name: init-sql-copy
image: busybox
command: ["sh", "-c", "cp /config/init.sql /tmp/init.sql"]
volumeMounts:
- name: init-sql
mountPath: /config
- name: tmp-sql
mountPath: /tmp
containers:
- name: mysql
image: mysql:8
env:
- name: MYSQL_ROOT_PASSWORD
value: "0674998280tanya"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
- name: tmp-sql
mountPath: /docker-entrypoint-initdb.d
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: mysql-pvc
- name: init-sql
configMap:
name: init-sql
- name: tmp-sql
emptyDir: {}

3
telegram_bot/stop-app.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/bash
pkill -f "kubectl port-forward"
kubectl delete namespace botspace

141
telegram_bot/web_app.py Normal file
View File

@ -0,0 +1,141 @@
from flask import Flask, render_template_string, jsonify
import mysql.connector
app = Flask(__name__)
DB_CONFIG = {
"host": "mysql",
"user": "root",
"password": "0674998280tanya",
"database": "telegram_bot"
}
TEMPLATE = """
<!doctype html>
<html lang="sk">
<head>
<meta charset="UTF-8">
<title>Zoznam porušovateľov</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
min-height: 100vh;
width: 100vw;
background: url('/static/bg.png') no-repeat center center/cover;
backdrop-filter: blur(8px);
animation: rotateBackground 60s linear infinite;
display: flex;
align-items: center;
justify-content: center;
font-family: 'Segoe UI', sans-serif;
}
@keyframes rotateBackground {
0% { background-position: 20% 20%; }
50% { background-position: 60% 60%; }
100% { background-position: 20% 20%; }
}
.container {
background-color: rgba(0, 0, 0, 0.6);
padding: 2rem 3rem;
border-radius: 12px;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.8);
text-align: center;
color: white;
max-height: 90vh;
overflow-y: auto;
}
h1 {
margin-bottom: 2rem;
font-size: 2.5rem;
text-shadow: 2px 2px 10px black;
}
table {
margin: 0 auto;
border-collapse: collapse;
}
th, td {
border: 1px solid #999;
padding: 1rem 2rem;
}
th {
background-color: rgba(255, 255, 255, 0.2);
}
td {
color: #eee;
}
</style>
</head>
<body>
<div class="container">
<h1>Zoznam porušovateľov</h1>
<table>
<thead>
<tr><th>Používateľ</th><th>Správa</th></tr>
</thead>
<tbody id="violators-body">
{% for row in data %}
<tr><td>{{ row[0] }}</td><td>{{ row[1] }}</td></tr>
{% endfor %}
</tbody>
</table>
</div>
<script>
async function refreshTable() {
try {
const response = await fetch('/data');
const data = await response.json();
const tbody = document.getElementById('violators-body');
tbody.innerHTML = '';
data.forEach(row => {
const tr = document.createElement('tr');
tr.innerHTML = `<td>${row[0]}</td><td>${row[1]}</td>`;
tbody.appendChild(tr);
});
} catch (error) {
console.error("Nepodarilo sa načítať dáta:", error);
}
}
setInterval(refreshTable, 1000); // každých 5 sekúnd
window.onload = refreshTable;
</script>
</body>
</html>
"""
@app.route('/')
def index():
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
cursor.execute("SELECT username, message FROM violators ORDER BY id DESC")
data = cursor.fetchall()
cursor.close()
conn.close()
return render_template_string(TEMPLATE, data=data)
@app.route('/data')
def data():
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
cursor.execute("SELECT username, message FROM violators ORDER BY id DESC")
data = cursor.fetchall()
cursor.close()
conn.close()
return jsonify(data)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)