fix(avatar): recover BOXIM image replies
This commit is contained in:
@@ -85,6 +85,29 @@ class ConcurrentPollingBoxIM(FakeBoxIM):
|
||||
return []
|
||||
|
||||
|
||||
class ConcurrentMessagePollingBoxIM(ConcurrentPollingBoxIM):
|
||||
async def fetch_private_messages(self, access_token, min_id="0"):
|
||||
await super().fetch_private_messages(access_token, min_id)
|
||||
owner_id = 100 if access_token == "prod-huihui-token" else 101
|
||||
return [
|
||||
{
|
||||
"id": owner_id,
|
||||
"localId": owner_id,
|
||||
"sendId": owner_id + 100,
|
||||
"recvId": owner_id,
|
||||
"sendTime": 1_700_000_000_000,
|
||||
"type": 0,
|
||||
"content": "并发写入测试",
|
||||
}
|
||||
]
|
||||
|
||||
async def mark_private_messages_read(self, access_token, friend_id, message_id):
|
||||
await asyncio.sleep(0.05)
|
||||
self.read_receipts.append(
|
||||
{"friendId": str(friend_id), "messageId": str(message_id)}
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def service_context(tmp_path):
|
||||
engine = create_engine(
|
||||
@@ -202,6 +225,7 @@ async def test_incoming_image_is_analyzed_and_used_in_takeover_reply(service_con
|
||||
assert scheduled.prompt == "请看看这张图片。"
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
clock.advance(3)
|
||||
|
||||
def analyze(db, avatar, content, **kwargs):
|
||||
@@ -262,6 +286,83 @@ async def test_incoming_image_is_analyzed_and_used_in_takeover_reply(service_con
|
||||
db.close()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_followup_text_recovers_recent_image_recorded_without_task(service_context):
|
||||
session_factory, service, boxim, clock = service_context
|
||||
await service.poll_and_process_messages()
|
||||
image_message = {
|
||||
"id": 113,
|
||||
"localId": 113,
|
||||
"sendId": 200,
|
||||
"recvId": 100,
|
||||
"sendTime": clock.millis(),
|
||||
"type": 1,
|
||||
"content": json.dumps(
|
||||
{
|
||||
"originUrl": "https://cdn.example/case.png",
|
||||
"thumbUrl": "https://cdn.example/case-thumb.png",
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
db = session_factory()
|
||||
try:
|
||||
avatar = db.get(Avatar, "avatar-1")
|
||||
service._record_message(db, avatar, "100", image_message, schedule_reply=False)
|
||||
cursor = db.query(TakeoverCursor).one()
|
||||
cursor.last_message_id = "113"
|
||||
db.commit()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
clock.advance(60)
|
||||
boxim.messages.extend(
|
||||
[
|
||||
image_message,
|
||||
{
|
||||
"id": 114,
|
||||
"localId": 114,
|
||||
"sendId": 200,
|
||||
"recvId": 100,
|
||||
"sendTime": clock.millis(),
|
||||
"type": 0,
|
||||
"content": "请帮我看看这张图",
|
||||
},
|
||||
]
|
||||
)
|
||||
await service.poll_messages()
|
||||
|
||||
db = session_factory()
|
||||
try:
|
||||
task = db.query(TakeoverReplyTask).filter_by(trigger_message_id="114").one()
|
||||
assert task.source_message_ids == ["113", "114"]
|
||||
assert task.prompt == "请看看这张图片。\n请帮我看看这张图"
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
clock.advance(1)
|
||||
boxim.messages.append(
|
||||
{
|
||||
"id": 115,
|
||||
"localId": 115,
|
||||
"sendId": 200,
|
||||
"recvId": 100,
|
||||
"sendTime": clock.millis(),
|
||||
"type": 0,
|
||||
"content": "图里写了什么",
|
||||
}
|
||||
)
|
||||
await service.poll_messages()
|
||||
|
||||
db = session_factory()
|
||||
try:
|
||||
latest = db.query(TakeoverReplyTask).filter_by(trigger_message_id="115").one()
|
||||
assert latest.source_message_ids == ["113", "114", "115"]
|
||||
assert latest.source_message_ids.count("113") == 1
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_invalid_image_message_is_recorded_but_not_scheduled(service_context):
|
||||
session_factory, service, boxim, clock = service_context
|
||||
@@ -347,7 +448,7 @@ async def test_multiple_avatar_owners_are_polled_concurrently(service_context):
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
boxim = ConcurrentPollingBoxIM()
|
||||
boxim = ConcurrentMessagePollingBoxIM()
|
||||
service = TakeoverService(
|
||||
session_factory,
|
||||
boxim,
|
||||
@@ -361,6 +462,8 @@ async def test_multiple_avatar_owners_are_polled_concurrently(service_context):
|
||||
db = session_factory()
|
||||
try:
|
||||
assert db.query(TakeoverCursor).filter(TakeoverCursor.initialized.is_(True)).count() == 2
|
||||
assert db.query(TakeoverMessage).count() == 2
|
||||
assert len(boxim.read_receipts) == 2
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user