Fix source import parsing and AI settings UI
This commit is contained in:
@@ -897,6 +897,22 @@ def parse_source_line(line: str) -> dict[str, str]:
|
||||
raw = (line or "").strip()
|
||||
if not raw:
|
||||
return {"name": "", "tag": "", "url": "", "error": "Пустая строка"}
|
||||
delimiter = next((sep for sep in ("\t", "|", ";") if sep in raw), "")
|
||||
if delimiter:
|
||||
fields = [part.strip() for part in raw.split(delimiter)]
|
||||
fields = [part for part in fields if part]
|
||||
if len(fields) == 2:
|
||||
name, url = fields
|
||||
tag = name
|
||||
elif len(fields) == 3:
|
||||
name, tag, url = fields
|
||||
else:
|
||||
return {"name": "", "tag": "", "url": "", "error": "Формат: Название | тэг | ссылка"}
|
||||
if url.startswith(("vk.com/", "vk.ru/", "m.vk.com/")):
|
||||
url = f"https://{url}"
|
||||
url = url.replace("https://vk.ru/", "https://vk.com/", 1).replace("https://m.vk.com/", "https://vk.com/", 1)
|
||||
return {"name": name, "tag": normalize_hash_tag(tag, ""), "url": url, "error": ""}
|
||||
|
||||
parts = re.split(r"\s+", raw)
|
||||
url_index = next(
|
||||
(
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-app-textMuted mb-1 flex justify-between">
|
||||
<span>Список (Название Тэг Ссылка)</span>
|
||||
<span>Список (Название | тэг | ссылка)</span>
|
||||
<span class="text-[10px] text-app-textMuted/60 font-normal">По 1 на строку</span>
|
||||
</label>
|
||||
<textarea name="bulk_text" class="textarea font-mono text-xs h-40 leading-relaxed" placeholder="Academy Gear academy_gear https://vk.com/academy_gear A2 Technologies a2technologies https://vk.com/a2technologies">{{ bulk_text }}</textarea>
|
||||
<textarea name="bulk_text" class="textarea font-mono text-xs h-40 leading-relaxed" placeholder="Academy Gear | academy_gear | https://vk.com/academy_gear A2 Technologies | a2technologies | https://vk.com/a2technologies Название без тэга | https://vk.com/source">{{ bulk_text }}</textarea>
|
||||
</div>
|
||||
|
||||
<label class="flex items-center gap-3 mt-2 cursor-pointer group">
|
||||
|
||||
@@ -320,7 +320,7 @@
|
||||
<option value="{{ m.value }}" {% if s.value_json == m.value %}selected{% endif %}>{{ m.label }}</option>
|
||||
{% endfor %}
|
||||
{% if s.value_json and s.value_json not in ai_model_options|map(attribute="value")|list %}
|
||||
<option value="{{ s.value_json }}">{{ s.value_json }} · текущее значение</option>
|
||||
<option value="{{ s.value_json }}" selected>{{ s.value_json }} · текущее значение</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
|
||||
@@ -330,7 +330,7 @@
|
||||
<option value="{{ m.value }}" {% if s.value_json == m.value %}selected{% endif %}>{{ m.label }}</option>
|
||||
{% endfor %}
|
||||
{% if s.value_json and s.value_json not in writer_model_options|map(attribute="value")|list %}
|
||||
<option value="{{ s.value_json }}">{{ s.value_json }} · текущее значение</option>
|
||||
<option value="{{ s.value_json }}" selected>{{ s.value_json }} · текущее значение</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
|
||||
|
||||
@@ -146,33 +146,6 @@ class AIQualifierWorker:
|
||||
async def claim_posts(self, batch_size: int) -> list[dict]:
|
||||
async with self.pool.acquire() as conn:
|
||||
async with conn.transaction():
|
||||
count = await conn.fetchval(
|
||||
"""
|
||||
SELECT COUNT(*)
|
||||
FROM raw_posts
|
||||
WHERE status='storage_ready'
|
||||
AND COALESCE(qualification_status, 'pending') = 'pending'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM raw_post_media m
|
||||
WHERE m.raw_post_id=raw_posts.id
|
||||
AND COALESCE(m.editor_hidden, FALSE)=FALSE
|
||||
AND m.media_type IN ('photo', 'video')
|
||||
AND COALESCE(m.tg_file_id, m.storage_attachment_id, '') <> ''
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM raw_post_media m
|
||||
WHERE m.raw_post_id=raw_posts.id
|
||||
AND COALESCE(m.editor_hidden, FALSE)=FALSE
|
||||
AND m.media_type IN ('photo', 'video')
|
||||
AND COALESCE(m.tg_file_id, m.storage_attachment_id, '') = ''
|
||||
)
|
||||
"""
|
||||
)
|
||||
if int(count or 0) < batch_size:
|
||||
return []
|
||||
|
||||
rows = await conn.fetch(
|
||||
"""
|
||||
WITH cte AS (
|
||||
|
||||
@@ -245,34 +245,6 @@ class AIWriterWorker:
|
||||
async def claim_posts(self, batch_size: int) -> list[dict]:
|
||||
async with self.pool.acquire() as conn:
|
||||
async with conn.transaction():
|
||||
count = await conn.fetchval(
|
||||
"""
|
||||
SELECT COUNT(*)
|
||||
FROM raw_posts
|
||||
WHERE status='storage_ready'
|
||||
AND qualification_status='accepted'
|
||||
AND COALESCE(rewrite_status, 'pending') = 'pending'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM raw_post_media m
|
||||
WHERE m.raw_post_id=raw_posts.id
|
||||
AND COALESCE(m.editor_hidden, FALSE)=FALSE
|
||||
AND m.media_type IN ('photo', 'video')
|
||||
AND COALESCE(m.tg_file_id, m.storage_attachment_id, '') <> ''
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM raw_post_media m
|
||||
WHERE m.raw_post_id=raw_posts.id
|
||||
AND COALESCE(m.editor_hidden, FALSE)=FALSE
|
||||
AND m.media_type IN ('photo', 'video')
|
||||
AND COALESCE(m.tg_file_id, m.storage_attachment_id, '') = ''
|
||||
)
|
||||
"""
|
||||
)
|
||||
if int(count or 0) < batch_size:
|
||||
return []
|
||||
|
||||
rows = await conn.fetch(
|
||||
"""
|
||||
WITH cte AS (
|
||||
|
||||
Reference in New Issue
Block a user