100 lines
3.5 KiB
Python
100 lines
3.5 KiB
Python
"""Auto-routing must queue to subscribed targets WITHOUT replacing the admin review card."""
|
|
import asyncio
|
|
import sys
|
|
|
|
sys.path.insert(0, "/app")
|
|
|
|
from db.database import init_db, close_db_pool
|
|
from db.repository import Repository
|
|
from services.admin_bot import AdminBotService
|
|
|
|
SRC_A = -1009999000020
|
|
SRC_B = -1009999000021
|
|
TRG = -1009999000022
|
|
|
|
|
|
class FakeQueue:
|
|
def __init__(self):
|
|
self.pushed = []
|
|
|
|
async def push_target_post(self, target_id, payload):
|
|
self.pushed.append((target_id, payload))
|
|
|
|
async def get_target_queue_size(self, target_id):
|
|
return 0
|
|
|
|
|
|
class FakeAI:
|
|
async def rewrite_for_target(self, raw_text, target, has_media=False, *args, **kwargs):
|
|
return f"[{target.title}] {raw_text}"
|
|
|
|
|
|
|
|
async def _cleanup(repo):
|
|
pool = await repo._get_pool()
|
|
async with pool.acquire() as conn:
|
|
for cid in (SRC_A, SRC_B):
|
|
await conn.execute("DELETE FROM posts WHERE source_channel_id = $1;", cid)
|
|
await conn.execute("DELETE FROM sources WHERE channel_id = $1;", cid)
|
|
await conn.execute("DELETE FROM targets WHERE channel_id = $1;", TRG)
|
|
|
|
|
|
async def run_tests():
|
|
await init_db()
|
|
repo = Repository()
|
|
await _cleanup(repo)
|
|
|
|
await repo.add_source(SRC_A, "Source A", None)
|
|
await repo.add_source(SRC_B, "Source B", None)
|
|
target_id = await repo.add_target(TRG, "Auto Target", None)
|
|
|
|
# A brand new target routes nothing.
|
|
assert await repo.get_targets_auto_routed_from(SRC_A) == []
|
|
|
|
# Toggle is a switch, not a one-way door.
|
|
assert await repo.toggle_target_auto_source(target_id, SRC_A) is True
|
|
routed = await repo.get_targets_auto_routed_from(SRC_A)
|
|
assert len(routed) == 1 and routed[0].id == target_id
|
|
assert routed[0].auto_source_ids == [SRC_A]
|
|
assert await repo.toggle_target_auto_source(target_id, SRC_A) is False
|
|
assert await repo.get_targets_auto_routed_from(SRC_A) == []
|
|
|
|
# Subscribe to A only; B must stay manual.
|
|
await repo.set_target_auto_sources(target_id, [SRC_A])
|
|
|
|
queue = FakeQueue()
|
|
bot = AdminBotService(repo=repo, ai_processor=FakeAI(), queue=queue,
|
|
review_channel_id=0, admin_user_ids=[1])
|
|
|
|
post_a = await repo.create_raw_post(SRC_A, 1, "post from A", content_hash="auto_a")
|
|
post_b = await repo.create_raw_post(SRC_B, 2, "post from B", content_hash="auto_b")
|
|
|
|
assert await bot.auto_route_post(post_a) == 1, "subscribed source must route"
|
|
assert await bot.auto_route_post(post_b) == 0, "unsubscribed source must not route"
|
|
|
|
assert len(queue.pushed) == 1, f"expected 1 enqueue, got {queue.pushed}"
|
|
tid, payload = queue.pushed[0]
|
|
assert tid == target_id
|
|
assert payload["text"] == "[Auto Target] post from A", f"AI rewrite not applied: {payload['text']}"
|
|
assert payload["post_id"] == post_a
|
|
|
|
# The post is recorded against the target but must NOT be marked published yet.
|
|
stored = await repo.get_post_by_id(post_a)
|
|
assert stored.status == "pending_review", f"auto-routing must not publish, got {stored.status}"
|
|
assert len(stored.published_to) == 1
|
|
assert stored.published_to[0]["target_id"] == target_id
|
|
assert stored.published_to[0]["published_at"] is None
|
|
|
|
# A soft-deleted post is never auto-routed.
|
|
await repo.soft_delete_post(post_b)
|
|
await repo.set_target_auto_sources(target_id, [SRC_A, SRC_B])
|
|
assert await bot.auto_route_post(post_b) == 0, "deleted posts must not route"
|
|
|
|
await _cleanup(repo)
|
|
await close_db_pool()
|
|
print("All auto-routing tests passed successfully!")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(run_tests())
|