This commit is contained in:
Анатолий Богомолов 2024-03-08 16:39:04 +10:00
parent dd1518b69c
commit 2f67e1cea6
11 changed files with 111 additions and 61 deletions

View File

@ -5,6 +5,26 @@ from app.extensions import db
collections = Blueprint("collections", __name__, url_prefix="/collections", template_folder="templates")
@collections.route('/', methods=["POST"])
def create_collection():
data = request.form
name = data.get('collection_name')
if not name:
return render_template('collections/create_form.j2', collections_error='Введите название базы!')
if Collection.exists(name):
return render_template('collections/create_form.j2', collections_error='База уже существует!')
swap = 'afterbegin' if len(Collection.query.all()) > 0 else 'innerHTML'
collection = Collection(name=name)
db.session.add(collection)
db.session.commit()
return f"<option value=\"{collection.id}\" selected>{ collection.name }</option>", 200, {'Hx-Reswap': swap, 'HX-Retarget': '#collection-select'}
@collections.route("/<int:id>", methods=["DELETE"])
def delete_collection(id: int):
@ -18,4 +38,4 @@ def delete_collection(id: int):
if length <= 0:
return "<small class=\"form-text\">Здесь ничего нет</small>", 200
return "", 204
return "", 200

View File

@ -1,18 +1,20 @@
<div data-collection-id="{{ collection.id }}" class="card">
<div class="card-header"><h5>{{ collection.name }}</h5></div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Кол-во пользрвателей: {{ collection.users|length }}</li>
</ul>
<form action="/api/collections/{{ collection.id }}" method="DELETE" class="card-footer px-2 pt-2">
<button
type="submit"
hx-delete="/api/collections/{{ collection.id }}"
hx-swap="outerHTML"
hx-target='[data-collection-id="{{ collection.id }}"]'
hx-confirm="Вы уверены, что хотите удалить коллекцию?"
class="btn btn-outline-danger"
>
Удалить
</button>
</form>
<div data-collection-id="{{ collection.id }}" class="col mb-3">
<div class="card">
<div class="card-header"><h5>{{ collection.name }}</h5></div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Кол-во пользрвателей: {{ collection.users|length }}</li>
</ul>
<form action="/api/collections/{{ collection.id }}" method="DELETE" class="card-footer px-2 pt-2">
<button
type="submit"
hx-delete="/api/collections/{{ collection.id }}"
hx-swap="outerHTML"
hx-target='[data-collection-id="{{ collection.id }}"]'
hx-confirm="Вы уверены, что хотите удалить коллекцию?"
class="btn btn-outline-danger"
>
Удалить
</button>
</form>
</div>
</div>

View File

@ -0,0 +1,2 @@
{% include "collections/create_form.j2" %}
{% include "collections/select.j2" %}

View File

@ -0,0 +1,33 @@
<div id="collection-create-form" class="input-group has-validation">
<input
type="text"
{% if collections_error is defined %}
class="form-control is-invalid"
{% else %}
class="form-control"
{% endif %}
name="collection_name"
id="collection-name-input"
placeholder="Название базы"
aria-describedby="collection-feedback"
required
>
<button
type="submit"
class="btn btn-outline-primary"
hx-post="/api/collections"
hx-swap="outerHTML"
hx-target="#collection-create-form"
hx-indicator="#indicator"
>
Добавить
</button>
{% if collections_error is defined %}
<div id="collection-feedback" class="invalid-feedback">
{{ collections_error }}
</div>
{% endif %}
</div>

View File

@ -1,8 +1,6 @@
<div id="cards-grid" class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4">
{% for collection in collections %}
<div class="col mb-3">
{% include "collections/card.j2" %}
</div>
{% include "collections/card.j2" %}
{% else %}
<small class="form-text">Здесь ничего нет.</small>
{% endfor %}

View File

@ -0,0 +1,7 @@
<select name="collection" id="collection-select" class="form-select flex-fill" size="3">
{% for collection in collections %}
<option value="{{collection.id}}">{{ collection.name }}</option>
{% else %}
<option disabled>Добавьте новую базу пользователей</option>
{% endfor %}
</select>

View File

@ -16,10 +16,6 @@ def get_tasks():
return render_template("tasks_cards.j2", tasks=tasks, sessions=sessions)
@tasks.route("/<int:task_id>", methods=["GET"])
def get_task(task_id: int):
...
@tasks.route("/session/<int:session_id>", methods=["POST"])
def create_task(session_id: int):
info = request.form

View File

@ -1,6 +1,5 @@
from flask import Blueprint, render_template
from app.blueprints.api.sessions.routes import get_sessions
from app.blueprints.api.users.routes import get_users
from app.blueprints.api.tasks.routes import get_tasks
from app.models.collection import Collection
@ -21,7 +20,8 @@ def tasks():
@frontend.route("/parse/<int:id>")
def parse(id: int):
return render_template("parse.j2", session_id=id, users_template=get_users(id))
collections = Collection.query.all()
return render_template("parse.j2", session_id=id, collections=collections)
@frontend.route("/collections")
def collections():

View File

@ -5,12 +5,19 @@
{% endblock title %}
{% block main %}
<form method="post" action="/test" class="container">
<form method="post" action="/api/tasks/session/{{ session_id }}" class="container">
<div class="row">
<!-- Actions -->
<section class="col-lg mb-3">
<div class="separator">
<h2>Действия</h2>
<div class="d-flex gap-2">
<h2>Действия</h2>
<div id="indicator" class="htmx-indicator">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
<hr class="divider">
</div>
<nav class="mb-3">
@ -24,14 +31,14 @@
<section class="tab-pane fade show active" id="actions-parse-section">
<div class="form-floating">
<input type="text" class="form-control" name="group" id="group-from-input" placeholder="Группа для парсинга">
<input type="text" class="form-control" name="parse" id="group-from-input" placeholder="Группа для парсинга">
<label for="group-from-input">Группа для парсинга</label>
</div>
</section>
<section class="tab-pane fade" id="actions-add-section">
<div class="form-floating">
<input type="text" name="url" class="form-control" id="group-to-input"
<input type="text" name="url" name="add" class="form-control" id="group-to-input"
placeholder="Группа для добавлнеия">
<label for="group-to-input">Группа для добавления</label>
</div>
@ -63,7 +70,7 @@
<input
type="text"
class="form-control"
name="collection"
name="task_name"
id="task-name-input"
placeholder="Название задачи"
>
@ -71,29 +78,9 @@
</div>
<section class="d-flex flex-column gap-3 mb-3">
<div class="input-group">
<div class="form-floating">
<input
type="text"
class="form-control"
name="collection"
id="collection-name-input"
placeholder="Группа для парсинга"
>
<label for="collection-name-input">Название базы пользователей</label>
</div>
<button type="submit" class="btn btn-outline-primary">Добавить</button>
</div>
<select class="form-select flex-fill" size="3">
{% for collection in collections %}
<option value="{{collection.id}}">{{ collection.name }}</option>
{% else %}
<option disabled>Добавьте новую базу пользователей</option>
{% endfor %}
</select>
{% include "collections/collections_section.j2" %}
</section>
<button type="submit" class="w-100 btn btn-primary">Создать задачу</button>
<button type="submit" hx-post="/api/tasks/session/{{ session_id }}" hx-indicator="#indicator" class="w-100 btn btn-primary">Создать задачу</button>
</section>
</div>
</form>

View File

@ -9,4 +9,9 @@ class Collection(db.Model):
name: Mapped[str] = mapped_column(unique=True, nullable=False)
tasks: Mapped[List['Task']] = relationship("Task", back_populates="collection")
users: Mapped[List['User']] = relationship("User", cascade="all, delete-orphan", back_populates="collection")
users: Mapped[List['User']] = relationship("User", cascade="all, delete-orphan", back_populates="collection")
def exists(name: str):
collections = Collection.query.filter_by(name=name).all()
return len(collections) > 0

View File

@ -1,11 +1,9 @@
import asyncio
import os
from loguru import logger
from paper.client import PaperClient
from paper.errors import IgnoreException, NeedPasswordException, UserPrivacyException
from paper.models import Message
class PaperParser:
@ -17,7 +15,7 @@ class PaperParser:
self.users_to_delete = []
async def invite_users(self, users, group, task = None):
async def invite_users(self, users, group, task):
await self.client.invite_self(group)
group_participants = await self.client.get_participants(group)
@ -33,7 +31,7 @@ class PaperParser:
await self.client.invite_user(user, group)
except (UserPrivacyException, IgnoreException) as e:
except (UserPrivacyException, IgnoreException):
self.users_to_delete.append(user)
logger.warning("Exception occurred. Skipping user...")
@ -47,6 +45,8 @@ class PaperParser:
# if dialog.is_user:
# messages = tuple(filter(lambda chat_message: message.text == chat_message.text, await self.client.get_messages(dialog)))
# print(messages)
if not task:
return
for user in users:
try:
@ -55,7 +55,7 @@ class PaperParser:
await self.client.send_message(user, message, file)
except (UserPrivacyException, IgnoreException) as e:
except (UserPrivacyException, IgnoreException):
self.users_to_delete.append(user)
logger.warning("Exception occurred. Skipping user...")
@ -84,4 +84,4 @@ class PaperParser:
return self
async def __aexit__(self, *args, **kwargs):
await self.client.disconnect()
await self.client.disconnect()