libs.functions.message
libs/functions/message.py
1""" 2libs/functions/message.py 3""" 4 5import logging 6import random 7import textwrap 8from configparser import ConfigParser 9from pathlib import Path 10from typing import TYPE_CHECKING 11 12import libs.global_value as g 13from libs.functions.compose import text_item 14from libs.types import CommandType 15from libs.utils.timekit import ExtendedDatetime as ExtDt 16 17if TYPE_CHECKING: 18 from integrations.protocols import MessageParserProtocol 19 from libs.domain.datamodels import GameInfo 20 21 22def random_reply(m: "MessageParserProtocol", message_type: str) -> str: 23 """ 24 メッセージをランダムに返す 25 26 Args: 27 m (MessageParserProtocol): メッセージデータ 28 message_type (str): 応答メッセージの種類 29 30 Returns: 31 str: 応答メッセージ 32 33 """ 34 parser = ConfigParser() 35 parser.read(g.cfg.config_file, encoding="utf-8") 36 37 correct_score = g.params.origin_point * 4 # 配給原点 38 rpoint_diff = abs(correct_score - m.status.rpoint_sum) 39 40 default_message_type = { 41 "invalid_argument": "使い方が間違っています。", 42 "no_hits": "{start} ~ {end} に成績記録ワードが見つかりません。", 43 "no_target": "集計対象データがありません。", 44 "invalid_score": "素点合計:{rpoint_sum}\n点数差分:{rpoint_diff}", 45 "restricted_channel": "<@{user_id}> この投稿はデータベースに反映されません。", 46 "inside_thread": "<@{user_id}> スレッド内から成績登録はできません。", 47 "same_player": "同名のプレイヤーがいます。", 48 "not_implemented": "未実装", 49 "access_denied": "アクセスが拒否されました。", 50 "rule_mismatch": "集計モード(四人打/三人打)の指定と集計対象ルールに矛盾があります。", 51 } 52 53 msg = default_message_type.get(message_type, "invalid_argument") 54 55 if g.cfg.main_parser.has_section(m.status.source): 56 if channel_config := g.cfg.main_parser[m.status.source].get("channel_config"): 57 parser.read(Path(channel_config), encoding="utf-8") 58 59 if parser.has_section("custom_message"): 60 msg_list = [] 61 for key, val in parser.items("custom_message"): 62 if key.startswith(message_type): 63 msg_list.append(val) 64 if msg_list: 65 msg = random.choice(msg_list) 66 67 if keywords := g.cfg.rule.keywords(g.params.rule_version): 68 keyword = list(keywords)[0] 69 else: 70 keyword = list(g.cfg.rule.keyword_mapping.keys())[0] 71 72 try: 73 msg = str( 74 # 文字列置き換え 75 msg.format( 76 user_id=m.data.user_id, 77 keyword=keyword, 78 start=ExtDt(g.params.starttime).format(ExtDt.FMT.YMD), 79 end=ExtDt(g.params.onday).format(ExtDt.FMT.YMD), 80 rpoint_diff=rpoint_diff * 100, 81 rpoint_sum=m.status.rpoint_sum * 100, 82 ) 83 ) 84 except KeyError as err: 85 logging.warning("[unknown keywords] %s: %s", err, msg) 86 msg = msg.replace("{user_id}", m.data.user_id) 87 88 return msg 89 90 91def header(game_info: "GameInfo", m: "MessageParserProtocol", add_text: str = "", indent: int = 1) -> str: 92 """ 93 見出し生成 94 95 Args: 96 game_info (GameInfo): 集計範囲のゲーム情報 97 m (MessageParserProtocol): メッセージデータ 98 add_text (str, optional): 追加表示するテキスト. Defaults to "". 99 indent (int, optional): 先頭のタブ数. Defaults to 1. 100 101 Returns: 102 str: 生成した見出し 103 104 """ 105 msg = "" 106 assert isinstance(game_info.first_game, ExtDt) 107 assert isinstance(game_info.last_game, ExtDt) 108 109 # 集計範囲 110 if g.params.search_word: # コメント検索の場合はコメントで表示 111 game_range1 = f"最初のゲーム:{game_info.first_comment}\n" 112 game_range1 += f"最後のゲーム:{game_info.last_comment}\n" 113 else: 114 game_range1 = f"最初のゲーム:{game_info.first_game.format(ExtDt.FMT.YMDHMS)}\n" 115 game_range1 += f"最後のゲーム:{game_info.last_game.format(ExtDt.FMT.YMDHMS)}\n" 116 game_range2 = f"集計範囲:{text_item.aggregation_range(game_info)}\n" 117 118 # ゲーム数 119 if game_info.count == 0: 120 msg += f"{random_reply(m, 'no_hits')}" 121 else: 122 match m.status.command_type: 123 case CommandType.RESULTS: 124 if g.params.target_count: # 直近指定がない場合は検索範囲を付ける 125 msg += game_range1 126 msg += f"集計対象:{game_info.count} ゲーム {add_text}\n" 127 else: 128 msg += f"検索範囲:{str(text_item.search_range(time_pattern='time'))}\n" 129 msg += game_range1 130 msg += f"集計対象:{game_info.count} ゲーム {add_text}\n" 131 case CommandType.RANKING | CommandType.REPORT: 132 msg += game_range2 133 msg += f"集計対象:{game_info.count} ゲーム\n" 134 case _: 135 msg += game_range2 136 msg += f"集計対象:{game_info.count} ゲーム\n" 137 138 if remarks_text := text_item.remarks(True): 139 msg += f"{remarks_text}\n" 140 if word_text := text_item.search_word(True): 141 msg += f"{word_text}\n" 142 143 return textwrap.indent(msg, "\t" * indent)
23def random_reply(m: "MessageParserProtocol", message_type: str) -> str: 24 """ 25 メッセージをランダムに返す 26 27 Args: 28 m (MessageParserProtocol): メッセージデータ 29 message_type (str): 応答メッセージの種類 30 31 Returns: 32 str: 応答メッセージ 33 34 """ 35 parser = ConfigParser() 36 parser.read(g.cfg.config_file, encoding="utf-8") 37 38 correct_score = g.params.origin_point * 4 # 配給原点 39 rpoint_diff = abs(correct_score - m.status.rpoint_sum) 40 41 default_message_type = { 42 "invalid_argument": "使い方が間違っています。", 43 "no_hits": "{start} ~ {end} に成績記録ワードが見つかりません。", 44 "no_target": "集計対象データがありません。", 45 "invalid_score": "素点合計:{rpoint_sum}\n点数差分:{rpoint_diff}", 46 "restricted_channel": "<@{user_id}> この投稿はデータベースに反映されません。", 47 "inside_thread": "<@{user_id}> スレッド内から成績登録はできません。", 48 "same_player": "同名のプレイヤーがいます。", 49 "not_implemented": "未実装", 50 "access_denied": "アクセスが拒否されました。", 51 "rule_mismatch": "集計モード(四人打/三人打)の指定と集計対象ルールに矛盾があります。", 52 } 53 54 msg = default_message_type.get(message_type, "invalid_argument") 55 56 if g.cfg.main_parser.has_section(m.status.source): 57 if channel_config := g.cfg.main_parser[m.status.source].get("channel_config"): 58 parser.read(Path(channel_config), encoding="utf-8") 59 60 if parser.has_section("custom_message"): 61 msg_list = [] 62 for key, val in parser.items("custom_message"): 63 if key.startswith(message_type): 64 msg_list.append(val) 65 if msg_list: 66 msg = random.choice(msg_list) 67 68 if keywords := g.cfg.rule.keywords(g.params.rule_version): 69 keyword = list(keywords)[0] 70 else: 71 keyword = list(g.cfg.rule.keyword_mapping.keys())[0] 72 73 try: 74 msg = str( 75 # 文字列置き換え 76 msg.format( 77 user_id=m.data.user_id, 78 keyword=keyword, 79 start=ExtDt(g.params.starttime).format(ExtDt.FMT.YMD), 80 end=ExtDt(g.params.onday).format(ExtDt.FMT.YMD), 81 rpoint_diff=rpoint_diff * 100, 82 rpoint_sum=m.status.rpoint_sum * 100, 83 ) 84 ) 85 except KeyError as err: 86 logging.warning("[unknown keywords] %s: %s", err, msg) 87 msg = msg.replace("{user_id}", m.data.user_id) 88 89 return msg
メッセージをランダムに返す
Arguments:
- m (MessageParserProtocol): メッセージデータ
- message_type (str): 応答メッセージの種類
Returns:
str: 応答メッセージ
def
header( game_info: libs.domain.datamodels.GameInfo, m: integrations.protocols.MessageParserProtocol, add_text: str = '', indent: int = 1) -> str:
92def header(game_info: "GameInfo", m: "MessageParserProtocol", add_text: str = "", indent: int = 1) -> str: 93 """ 94 見出し生成 95 96 Args: 97 game_info (GameInfo): 集計範囲のゲーム情報 98 m (MessageParserProtocol): メッセージデータ 99 add_text (str, optional): 追加表示するテキスト. Defaults to "". 100 indent (int, optional): 先頭のタブ数. Defaults to 1. 101 102 Returns: 103 str: 生成した見出し 104 105 """ 106 msg = "" 107 assert isinstance(game_info.first_game, ExtDt) 108 assert isinstance(game_info.last_game, ExtDt) 109 110 # 集計範囲 111 if g.params.search_word: # コメント検索の場合はコメントで表示 112 game_range1 = f"最初のゲーム:{game_info.first_comment}\n" 113 game_range1 += f"最後のゲーム:{game_info.last_comment}\n" 114 else: 115 game_range1 = f"最初のゲーム:{game_info.first_game.format(ExtDt.FMT.YMDHMS)}\n" 116 game_range1 += f"最後のゲーム:{game_info.last_game.format(ExtDt.FMT.YMDHMS)}\n" 117 game_range2 = f"集計範囲:{text_item.aggregation_range(game_info)}\n" 118 119 # ゲーム数 120 if game_info.count == 0: 121 msg += f"{random_reply(m, 'no_hits')}" 122 else: 123 match m.status.command_type: 124 case CommandType.RESULTS: 125 if g.params.target_count: # 直近指定がない場合は検索範囲を付ける 126 msg += game_range1 127 msg += f"集計対象:{game_info.count} ゲーム {add_text}\n" 128 else: 129 msg += f"検索範囲:{str(text_item.search_range(time_pattern='time'))}\n" 130 msg += game_range1 131 msg += f"集計対象:{game_info.count} ゲーム {add_text}\n" 132 case CommandType.RANKING | CommandType.REPORT: 133 msg += game_range2 134 msg += f"集計対象:{game_info.count} ゲーム\n" 135 case _: 136 msg += game_range2 137 msg += f"集計対象:{game_info.count} ゲーム\n" 138 139 if remarks_text := text_item.remarks(True): 140 msg += f"{remarks_text}\n" 141 if word_text := text_item.search_word(True): 142 msg += f"{word_text}\n" 143 144 return textwrap.indent(msg, "\t" * indent)
見出し生成
Arguments:
- game_info (GameInfo): 集計範囲のゲーム情報
- m (MessageParserProtocol): メッセージデータ
- add_text (str, optional): 追加表示するテキスト. Defaults to "".
- indent (int, optional): 先頭のタブ数. Defaults to 1.
Returns:
str: 生成した見出し