pass linter and pytest

This commit is contained in:
MuXinCG
2026-02-15 20:57:21 +08:00
parent 358f63994b
commit 91e0cfb7c1
3 changed files with 59 additions and 17 deletions
+40 -11
View File
@@ -715,11 +715,12 @@ class Channel(ChannelPlugin, ABC):
"""Decide whether to process a message based on mention gating."""
if self.require_mention == "off":
return True
# Both "always" and "group" allow DMs through unconditionally
if not raw.is_group:
return True
if self.require_mention == "always":
return raw.was_mentioned
# "group" — require mention only in groups
if not raw.is_group:
return True
return raw.was_mentioned
_mention_pattern: str | None = None
@@ -757,6 +758,42 @@ class Channel(ChannelPlugin, ABC):
# ── Inbound message pipeline ──────────────────────────────────────
async def _build_inbound_async(self, raw: RawIncoming) -> InboundMessage | None:
"""Async version: run *raw* through inbound middlewares and convert."""
context: dict = {"channel": self}
current: RawIncoming | None = raw
for mw in self._inbound_middlewares:
if current is None:
return None
current = await mw.process_inbound(current, context)
if current is None:
return None
return self._raw_to_inbound(current)
def _build_inbound(self, raw: RawIncoming) -> InboundMessage | None:
"""Run *raw* through inbound middlewares and convert to InboundMessage.
Synchronous wrapper around :meth:`_build_inbound_async`. Safe to
call from both sync and async contexts.
"""
import asyncio
import concurrent.futures
try:
asyncio.get_running_loop()
# Inside a running loop — run in a worker thread
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
return pool.submit(
lambda: asyncio.run(self._build_inbound_async(raw))
).result()
except RuntimeError:
# No running loop — safe to create one
loop = asyncio.new_event_loop()
try:
return loop.run_until_complete(self._build_inbound_async(raw))
finally:
loop.close()
def _raw_to_inbound(self, raw: RawIncoming) -> InboundMessage | None:
"""Convert a RawIncoming to InboundMessage (pure transformation, no filtering).
@@ -785,15 +822,7 @@ class Channel(ChannelPlugin, ABC):
Convenience method for subclass ``_on_message`` handlers.
"""
context: dict = {"channel": self}
current: RawIncoming | None = raw
for mw in self._inbound_middlewares:
if current is None:
return
current = await mw.process_inbound(current, context)
if current is None:
return
msg = self._raw_to_inbound(current)
msg = self._build_inbound(raw)
if msg is None:
return
if raw.message_id:
+3 -5
View File
@@ -1,8 +1,6 @@
"""Telegram channel implementation using python-telegram-bot."""
import asyncio
import logging
import re
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
@@ -37,6 +35,9 @@ class TelegramChannel(Channel):
self._bot_username: str = ""
async def start(self) -> None:
if not self.config.bot_token:
raise ChannelError("Telegram bot token is required")
try:
from telegram.ext import (
ApplicationBuilder,
@@ -49,9 +50,6 @@ class TelegramChannel(Channel):
"Install with: pip install evoscientist[telegram]"
)
if not self.config.bot_token:
raise ChannelError("Telegram bot token is required")
builder = ApplicationBuilder().token(self.config.bot_token)
if self.config.proxy:
builder = builder.proxy(self.config.proxy).get_updates_proxy(self.config.proxy)
+16 -1
View File
@@ -2,7 +2,6 @@
import asyncio
import hashlib
import json
import time
import xml.etree.ElementTree as ET
@@ -240,6 +239,22 @@ class TestWeChatCrypto:
Uses a deterministic 43-char EncodingAESKey.
"""
# Skip encryption tests when no crypto backend is available
_has_crypto = False
try:
from Crypto.Cipher import AES as _aes # noqa: F401
_has_crypto = True
except ImportError:
try:
import pyaes as _pyaes # noqa: F401
_has_crypto = True
except ImportError:
pass
pytestmark = pytest.mark.skipif(
not _has_crypto,
reason="pycryptodome or pyaes required for encryption tests",
)
@pytest.fixture
def crypto(self):
# 43 base64 chars → 32 bytes AES key