feat: remove all unnecessary fields in GroupMember and implement MessageEvent field for pipeline events

This commit is contained in:
Junyan Qin
2025-12-05 17:24:58 +08:00
parent dbfcb70f8d
commit b06b32306f
17 changed files with 28 additions and 79 deletions
+1
View File
@@ -237,6 +237,7 @@ class RuntimePipeline:
launcher_type=query.launcher_type.value, launcher_type=query.launcher_type.value,
launcher_id=query.launcher_id, launcher_id=query.launcher_id,
sender_id=query.sender_id, sender_id=query.sender_id,
message_event=query.message_event,
message_chain=query.message_chain, message_chain=query.message_chain,
) )
@@ -40,6 +40,7 @@ class ChatMessageHandler(handler.MessageHandler):
launcher_id=query.launcher_id, launcher_id=query.launcher_id,
sender_id=query.sender_id, sender_id=query.sender_id,
text_message=str(query.message_chain), text_message=str(query.message_chain),
message_event=query.message_event,
message_chain=query.message_chain, message_chain=query.message_chain,
query=query, query=query,
) )
@@ -327,9 +327,6 @@ class AiocqhttpEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title=event.sender['title'] if 'title' in event.sender else '', special_title=event.sender['title'] if 'title' in event.sender else '',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
), ),
message_chain=yiri_chain, message_chain=yiri_chain,
time=event.time, time=event.time,
@@ -119,9 +119,6 @@ class DingTalkEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
) )
time = event.incoming_message.create_at time = event.incoming_message.create_at
return platform_events.GroupMessage( return platform_events.GroupMessage(
@@ -769,9 +769,6 @@ class DiscordEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
), ),
message_chain=message_chain, message_chain=message_chain,
time=event.created_at.timestamp(), time=event.created_at.timestamp(),
-3
View File
@@ -219,9 +219,6 @@ class KookEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
), ),
message_chain=message_chain, message_chain=message_chain,
time=event_time, time=event_time,
+15 -21
View File
@@ -55,9 +55,7 @@ class AESCipher(object):
class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter): class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod @staticmethod
async def upload_image_to_lark( async def upload_image_to_lark(msg: platform_message.Image, api_client: lark_oapi.Client) -> typing.Optional[str]:
msg: platform_message.Image, api_client: lark_oapi.Client
) -> typing.Optional[str]:
"""Upload an image to Lark and return the image_key, or None if upload fails.""" """Upload an image to Lark and return the image_key, or None if upload fails."""
image_bytes = None image_bytes = None
@@ -95,7 +93,9 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
return None return None
if image_bytes is None: if image_bytes is None:
print(f'No image data available for Image message (url={msg.url}, base64={bool(msg.base64)}, path={msg.path})') print(
f'No image data available for Image message (url={msg.url}, base64={bool(msg.base64)}, path={msg.path})'
)
return None return None
try: try:
@@ -113,10 +113,7 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
request = ( request = (
CreateImageRequest.builder() CreateImageRequest.builder()
.request_body( .request_body(
CreateImageRequestBody.builder() CreateImageRequestBody.builder().image_type('message').image(open(temp_file_path, 'rb')).build()
.image_type('message')
.image(open(temp_file_path, 'rb'))
.build()
) )
.build() .build()
) )
@@ -143,7 +140,7 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
message_chain: platform_message.MessageChain, api_client: lark_oapi.Client message_chain: platform_message.MessageChain, api_client: lark_oapi.Client
) -> typing.Tuple[list, list]: ) -> typing.Tuple[list, list]:
"""Convert message chain to Lark format. """Convert message chain to Lark format.
Returns: Returns:
Tuple of (text_elements, image_keys): Tuple of (text_elements, image_keys):
- text_elements: List of paragraphs for post message format - text_elements: List of paragraphs for post message format
@@ -159,24 +156,24 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
async def process_text_with_images(text: str) -> typing.Tuple[str, list]: async def process_text_with_images(text: str) -> typing.Tuple[str, list]:
"""Extract Markdown images from text and return cleaned text + image URLs.""" """Extract Markdown images from text and return cleaned text + image URLs."""
extracted_urls = [] extracted_urls = []
# Find all Markdown images # Find all Markdown images
matches = list(markdown_image_pattern.finditer(text)) matches = list(markdown_image_pattern.finditer(text))
if not matches: if not matches:
return text, [] return text, []
# Extract URLs and remove image syntax from text # Extract URLs and remove image syntax from text
cleaned_text = text cleaned_text = text
for match in reversed(matches): # Reverse to maintain correct positions for match in reversed(matches): # Reverse to maintain correct positions
url = match.group(2) url = match.group(2)
extracted_urls.insert(0, url) # Insert at beginning since we're going in reverse extracted_urls.insert(0, url) # Insert at beginning since we're going in reverse
# Replace image syntax with empty string or a placeholder # Replace image syntax with empty string or a placeholder
cleaned_text = cleaned_text[:match.start()] + cleaned_text[match.end():] cleaned_text = cleaned_text[: match.start()] + cleaned_text[match.end() :]
# Clean up multiple consecutive newlines that might result from removing images # Clean up multiple consecutive newlines that might result from removing images
cleaned_text = re.sub(r'\n{3,}', '\n\n', cleaned_text) cleaned_text = re.sub(r'\n{3,}', '\n\n', cleaned_text)
cleaned_text = cleaned_text.strip() cleaned_text = cleaned_text.strip()
return cleaned_text, extracted_urls return cleaned_text, extracted_urls
for msg in message_chain: for msg in message_chain:
@@ -189,14 +186,14 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
text = msg.text.encode('latin1').decode('utf-8') text = msg.text.encode('latin1').decode('utf-8')
except UnicodeError: except UnicodeError:
text = msg.text.encode('utf-8', errors='replace').decode('utf-8') text = msg.text.encode('utf-8', errors='replace').decode('utf-8')
# Check for and extract Markdown images from text # Check for and extract Markdown images from text
cleaned_text, extracted_urls = await process_text_with_images(text) cleaned_text, extracted_urls = await process_text_with_images(text)
# Add cleaned text if not empty # Add cleaned text if not empty
if cleaned_text: if cleaned_text:
pending_paragraph.append({'tag': 'md', 'text': cleaned_text}) pending_paragraph.append({'tag': 'md', 'text': cleaned_text})
# Process extracted image URLs # Process extracted image URLs
for url in extracted_urls: for url in extracted_urls:
# Create a temporary Image message to upload # Create a temporary Image message to upload
@@ -204,7 +201,7 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
image_key = await LarkMessageConverter.upload_image_to_lark(temp_image, api_client) image_key = await LarkMessageConverter.upload_image_to_lark(temp_image, api_client)
if image_key: if image_key:
image_keys.append(image_key) image_keys.append(image_key)
elif isinstance(msg, platform_message.At): elif isinstance(msg, platform_message.At):
pending_paragraph.append({'tag': 'at', 'user_id': msg.target, 'style': []}) pending_paragraph.append({'tag': 'at', 'user_id': msg.target, 'style': []})
elif isinstance(msg, platform_message.AtAll): elif isinstance(msg, platform_message.AtAll):
@@ -369,9 +366,6 @@ class LarkEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
), ),
message_chain=message_chain, message_chain=message_chain,
time=event.event.message.create_time, time=event.event.message.create_time,
@@ -437,9 +437,6 @@ class GewechatEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
), ),
message_chain=message_chain, message_chain=message_chain,
time=event['Data']['CreateTime'], time=event['Data']['CreateTime'],
@@ -153,9 +153,6 @@ class NakuruProjectEventConverter(abstract_platform_adapter.AbstractEventConvert
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title=event.sender.title, special_title=event.sender.title,
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
), ),
message_chain=yiri_chain, message_chain=yiri_chain,
time=event.time, time=event.time,
@@ -279,11 +279,6 @@ class OfficialEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=int(
datetime.datetime.strptime(event.member.joined_at, '%Y-%m-%dT%H:%M:%S%z').timestamp()
),
last_speak_timestamp=datetime.datetime.now().timestamp(),
mute_time_remaining=0,
), ),
message_chain=OfficialMessageConverter.extract_message_chain_from_obj(event, event.id), message_chain=OfficialMessageConverter.extract_message_chain_from_obj(event, event.id),
time=int(datetime.datetime.strptime(event.timestamp, '%Y-%m-%dT%H:%M:%S%z').timestamp()), time=int(datetime.datetime.strptime(event.timestamp, '%Y-%m-%dT%H:%M:%S%z').timestamp()),
@@ -312,9 +307,6 @@ class OfficialEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=int(0),
last_speak_timestamp=datetime.datetime.now().timestamp(),
mute_time_remaining=0,
), ),
message_chain=OfficialMessageConverter.extract_message_chain_from_obj(event, event.id), message_chain=OfficialMessageConverter.extract_message_chain_from_obj(event, event.id),
time=int(datetime.datetime.strptime(event.timestamp, '%Y-%m-%dT%H:%M:%S%z').timestamp()), time=int(datetime.datetime.strptime(event.timestamp, '%Y-%m-%dT%H:%M:%S%z').timestamp()),
-3
View File
@@ -108,9 +108,6 @@ class LINEEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
), ),
message_chain=message_chain, message_chain=message_chain,
time=event.timestamp, time=event.timestamp,
@@ -94,9 +94,6 @@ class QQOfficialEventConverter(abstract_platform_adapter.AbstractEventConverter)
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
) )
time = int(datetime.datetime.strptime(event.timestamp, '%Y-%m-%dT%H:%M:%S%z').timestamp()) time = int(datetime.datetime.strptime(event.timestamp, '%Y-%m-%dT%H:%M:%S%z').timestamp())
return platform_events.GroupMessage( return platform_events.GroupMessage(
@@ -117,9 +114,6 @@ class QQOfficialEventConverter(abstract_platform_adapter.AbstractEventConverter)
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
) )
time = int(datetime.datetime.strptime(event.timestamp, '%Y-%m-%dT%H:%M:%S%z').timestamp()) time = int(datetime.datetime.strptime(event.timestamp, '%Y-%m-%dT%H:%M:%S%z').timestamp())
return platform_events.GroupMessage( return platform_events.GroupMessage(
+9 -14
View File
@@ -76,9 +76,6 @@ class SlackEventConverter(abstract_platform_adapter.AbstractEventConverter):
id=event.channel_id, name='MEMBER', permission=platform_entities.Permission.Member id=event.channel_id, name='MEMBER', permission=platform_entities.Permission.Member
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
) )
time = int(datetime.datetime.utcnow().timestamp()) time = int(datetime.datetime.utcnow().timestamp())
return platform_events.GroupMessage( return platform_events.GroupMessage(
@@ -112,10 +109,7 @@ class SlackAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
raise command_errors.ParamNotEnoughError('Slack机器人缺少相关配置项,请查看文档或联系管理员') raise command_errors.ParamNotEnoughError('Slack机器人缺少相关配置项,请查看文档或联系管理员')
bot = SlackClient( bot = SlackClient(
bot_token=config['bot_token'], bot_token=config['bot_token'], signing_secret=config['signing_secret'], logger=logger, unified_mode=True
signing_secret=config['signing_secret'],
logger=logger,
unified_mode=True
) )
super().__init__( super().__init__(
@@ -199,19 +193,20 @@ class SlackAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
if self.bot_uuid and hasattr(self.logger, 'ap'): if self.bot_uuid and hasattr(self.logger, 'ap'):
try: try:
api_port = self.logger.ap.instance_config.data['api']['port'] api_port = self.logger.ap.instance_config.data['api']['port']
webhook_url = f"http://127.0.0.1:{api_port}/bots/{self.bot_uuid}" webhook_url = f'http://127.0.0.1:{api_port}/bots/{self.bot_uuid}'
webhook_url_public = f"http://<Your-Public-IP>:{api_port}/bots/{self.bot_uuid}" webhook_url_public = f'http://<Your-Public-IP>:{api_port}/bots/{self.bot_uuid}'
await self.logger.info(f"Slack 机器人 Webhook 回调地址:") await self.logger.info('Slack 机器人 Webhook 回调地址:')
await self.logger.info(f" 本地地址: {webhook_url}") await self.logger.info(f' 本地地址: {webhook_url}')
await self.logger.info(f" 公网地址: {webhook_url_public}") await self.logger.info(f' 公网地址: {webhook_url_public}')
await self.logger.info(f"请在 Slack 后台配置此回调地址") await self.logger.info('请在 Slack 后台配置此回调地址')
except Exception as e: except Exception as e:
await self.logger.warning(f"无法生成 webhook URL: {e}") await self.logger.warning(f'无法生成 webhook URL: {e}')
async def keep_alive(): async def keep_alive():
while True: while True:
await asyncio.sleep(1) await asyncio.sleep(1)
await keep_alive() await keep_alive()
async def kill(self) -> bool: async def kill(self) -> bool:
@@ -120,9 +120,6 @@ class TelegramEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
), ),
message_chain=lb_message, message_chain=lb_message,
time=event.message.date.timestamp(), time=event.message.date.timestamp(),
@@ -501,9 +501,6 @@ class WeChatPadEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
), ),
message_chain=message_chain, message_chain=message_chain,
time=event['create_time'], time=event['create_time'],
@@ -67,9 +67,6 @@ class WecomBotEventConverter(abstract_platform_adapter.AbstractEventConverter):
permission=platform_entities.Permission.Member, permission=platform_entities.Permission.Member,
), ),
special_title='', special_title='',
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
) )
time = datetime.datetime.now().timestamp() time = datetime.datetime.now().timestamp()
return platform_events.GroupMessage( return platform_events.GroupMessage(
+2
View File
@@ -139,6 +139,8 @@ class RuntimeConnectionHandler(handler.Handler):
message_chain_obj = platform_message.MessageChain.model_validate(message_chain) message_chain_obj = platform_message.MessageChain.model_validate(message_chain)
self.ap.logger.debug(f'Reply message: {message_chain_obj.model_dump(serialize_as_any=False)}')
await query.adapter.reply_message( await query.adapter.reply_message(
query.message_event, query.message_event,
message_chain_obj, message_chain_obj,