libs.bootstrap.configuration
libs/bootstrap/configuration.py
1""" 2libs/bootstrap/configuration.py 3""" 4 5import argparse 6import logging 7import os 8import shutil 9import sys 10from functools import partial 11from pathlib import Path 12from typing import TYPE_CHECKING, Any, cast 13 14import libs.commands.graph.entry 15import libs.commands.help.entry 16import libs.commands.ranking.entry 17import libs.commands.report.entry 18import libs.commands.results.entry 19import libs.global_value as g 20from integrations import factory 21from libs.bootstrap import initialization 22from libs.bootstrap.app_config import AppConfig 23from libs.commands.registry import member, team 24from libs.domain.datamodels import Args 25from libs.functions import lookup 26from libs.functions.compose import text_item 27from libs.types import ServiceType, StyleOptions 28 29if TYPE_CHECKING: 30 from integrations.protocols import MessageParserProtocol 31 from libs.bootstrap.section import SubCommands 32 33 34def set_loglevel() -> None: 35 """ログレベル追加""" 36 # DEBUG : 10 37 # INFO : 20 38 # WARNING : 30 39 # ERROR : 40 40 # CRITICAL : 50 41 42 # TRACE 43 logging.TRACE = 5 # type: ignore 44 logging.trace = partial(logging.log, logging.TRACE) # type: ignore 45 logging.addLevelName(logging.TRACE, "TRACE") # type: ignore 46 47 48def arg_parser() -> Args: 49 """ 50 コマンドライン解析 51 52 Returns: 53 Args : ArgumentParserオブジェクト 54 55 """ 56 prog_name = os.path.basename(sys.argv[0]) 57 p = argparse.ArgumentParser( 58 formatter_class=argparse.RawTextHelpFormatter, 59 add_help=True, 60 allow_abbrev=False, 61 ) 62 63 p.add_argument( 64 "-c", 65 "--config", 66 type=Path, 67 default=Path("config.ini"), 68 help="設定ファイル(default: %(default)s)", 69 ) 70 p.add_argument( 71 "--no-cleanup", 72 dest="no_cleanup", 73 action="store_false", 74 help="作業ディレクトリの内容を削除しない", 75 ) 76 p.add_argument( 77 "-s", 78 "--service", 79 choices=[ 80 "slack", 81 "discord", 82 "standard_io", 83 "std", 84 "web", 85 "flask", 86 ], 87 type=str, 88 default="slack", 89 help="連携先サービス", 90 ) 91 92 logging_group = p.add_argument_group("logging options") 93 logging_group.add_argument( 94 "-d", 95 "--debug", 96 action="count", 97 default=0, 98 help="デバッグレベル(-d, -dd)", 99 ) 100 logging_group.add_argument( 101 "-v", 102 "--verbose", 103 action="count", 104 default=0, 105 help="動作ログ出力レベル(-v, -vv, -vvv)", 106 ) 107 logging_group.add_argument( 108 "--moderate", 109 action="store_true", 110 help="ログレベルがエラー以下のもを非表示", 111 ) 112 logging_group.add_argument( 113 "--notime", 114 action="store_true", 115 help="ログフォーマットから日時を削除", 116 ) 117 118 match prog_name: 119 case "app.py": 120 service_stdio = p.add_argument_group("Only allowed when --service=standard_io") 121 service_stdio.add_argument( 122 "--text", 123 type=str, 124 help="input text strings", 125 ) 126 service_web = p.add_argument_group("Only allowed when --service=web") 127 service_web.add_argument( 128 "--host", 129 type=str, 130 default="127.0.0.1", 131 help="listen address(default: %(default)s)", 132 ) 133 service_web.add_argument( 134 "--port", 135 type=int, 136 default=8000, 137 help="bind port(default: %(default)s)", 138 ) 139 case "dbtools.py": # dbtools専用オプション 140 required = p.add_argument_group("Required options(amutually exclusive)") 141 exclusive = required.add_mutually_exclusive_group() 142 exclusive.add_argument( 143 "--compar", 144 action="store_true", 145 help="データ突合", 146 ) 147 exclusive.add_argument( 148 "--unification", 149 type=Path, 150 nargs="?", 151 const="rename.ini", 152 help="ファイルの内容に従って記録済みのメンバー名を修正する(default: %(const)s)", 153 ) 154 exclusive.add_argument( 155 "--recalculation", 156 action="store_true", 157 help="ポイント再計算", 158 ) 159 exclusive.add_argument( 160 "--export", 161 dest="export_data", 162 type=str, 163 nargs="?", 164 const="export", 165 metavar="PREFIX", 166 help="メンバー設定情報をエクスポート(default prefix: %(const)s)", 167 ) 168 exclusive.add_argument( 169 "--import", 170 dest="import_data", 171 type=str, 172 nargs="?", 173 const="export", 174 metavar="PREFIX", 175 help="メンバー設定情報をインポート(default prefix: %(const)s)", 176 ) 177 exclusive.add_argument( 178 "--vacuum", 179 action="store_true", 180 help="database vacuum", 181 ) 182 exclusive.add_argument( 183 "--gen-test-data", 184 type=int, 185 dest="gen_test_data", 186 nargs="?", 187 const=1, 188 default=None, 189 metavar="count", 190 help="テスト用サンプルデータ生成(count=生成回数, default: %(const)s)", 191 ) 192 case "test.py": # 動作テスト用オプション 193 p.add_argument( 194 "-t", 195 "--testcase", 196 dest="testcase", 197 type=Path, 198 ) 199 200 args, unknown = p.parse_known_args() 201 if unknown and prog_name in ["app.py", "dbtools.py"]: 202 p.print_usage() 203 sys.exit(f"\ninvalid args: {unknown}") 204 205 return cast(Args, args) 206 207 208def setup(init_db: bool = True) -> None: 209 """ 210 設定ファイル読み込み処理 211 212 Args: 213 init_db (bool, optional): resultdbの初期化処理を行う Defaults to True. 214 215 """ 216 set_loglevel() 217 218 g.args = arg_parser() 219 220 # ログフォーマット 221 if g.args.notime: 222 fmt = "" 223 else: 224 fmt = "[%(asctime)s]" 225 226 # デバッグレベル 227 match g.args.debug: 228 case 1: 229 fmt += "[%(levelname)s][%(module)s:%(funcName)s] %(message)s" 230 logging.basicConfig(level=logging.DEBUG, format=fmt) 231 logging.info("DEBUG MODE") 232 case 2: 233 fmt += "[%(levelname)s][%(module)s:%(funcName)s] %(message)s" 234 logging.basicConfig(level=logging.TRACE, format=fmt) # type: ignore 235 logging.info("TRACE MODE") 236 case _: 237 fmt += "[%(levelname)s][%(module)s:%(funcName)s] %(message)s" 238 if g.args.moderate: 239 logging.basicConfig(level=logging.WARNING, format=fmt) 240 else: 241 logging.basicConfig(level=logging.INFO, format=fmt) 242 243 g.cfg = AppConfig(g.args.config) 244 245 # 連携サービス 246 match g.args.service: 247 case "slack": 248 g.cfg.selected_service = ServiceType.SLACK 249 case "discord": 250 g.cfg.selected_service = ServiceType.DISCORD 251 case "standard_io" | "std": 252 g.cfg.selected_service = ServiceType.STANDARD_IO 253 case "web" | "flask": 254 g.cfg.selected_service = ServiceType.WEB 255 case _: 256 sys.exit() 257 258 if not hasattr(g.args, "testcase"): 259 g.args.testcase = None 260 else: 261 g.cfg.selected_service = ServiceType.STANDARD_IO 262 263 g.adapter = factory.select_adapter(g.cfg.selected_service, g.cfg) 264 265 # ディレクトリ作成 266 if not g.args.testcase: 267 if g.cfg.setting.work_dir.is_dir() and g.args.no_cleanup: 268 shutil.rmtree(g.cfg.setting.work_dir) 269 try: 270 g.cfg.setting.work_dir.mkdir(exist_ok=True) 271 except FileExistsError as err: 272 sys.exit(str(err)) 273 274 if isinstance(g.cfg.setting.backup_dir, Path): 275 try: 276 g.cfg.setting.backup_dir.mkdir(exist_ok=True) 277 except FileExistsError as err: 278 sys.exit(str(err)) 279 280 # 初期化 281 initialization.main(init_db) 282 lookup.read_memberslist() 283 284 register() 285 286 # キーワード重複チェック 287 g.cfg.rule.check( 288 chk_commands=set( 289 g.cfg.results.commandword 290 + g.cfg.graph.commandword 291 + g.cfg.ranking.commandword 292 + g.cfg.report.commandword 293 + g.cfg.help.commandword 294 + g.cfg.rule.remarks_words 295 + list(g.keyword_dispatcher) 296 ), 297 chk_members=set(lookup.enumeration_all_members()), 298 default_rule=g.cfg.setting.default_rule, 299 ) 300 301 # 設定情報 302 logging.info("main_config: %s", g.cfg.config_file.absolute()) 303 if g.cfg.setting.rule_config: 304 logging.info("rule_config: %s", g.cfg.setting.rule_config.absolute()) 305 if isinstance(g.cfg.setting.database_file, Path): 306 logging.info("resultdb: %s", g.cfg.setting.database_file.absolute()) 307 logging.info( 308 "service: %s, graph_library: %s, time_adjust: %sh", 309 g.cfg.selected_service, 310 g.adapter.conf.plotting_backend, 311 g.cfg.setting.time_adjust, 312 ) 313 314 g.cfg.rule.info() 315 316 drop_items = ["section", "default_commandword", "command_suffix", "main_parser", "section_proxy", "info"] 317 logging.debug("setting: %s", g.cfg.setting.to_dict(drop_items)) 318 logging.debug("member: %s", g.cfg.member.to_dict(drop_items)) 319 logging.debug("team: %s", g.cfg.team.to_dict(drop_items)) 320 logging.debug("results: %s", g.cfg.results.to_dict(drop_items)) 321 logging.debug("graph: %s", g.cfg.graph.to_dict(drop_items)) 322 logging.debug("ranking: %s", g.cfg.ranking.to_dict(drop_items)) 323 logging.debug("report: %s", g.cfg.report.to_dict(drop_items)) 324 logging.debug("help: %s", g.cfg.help.to_dict(drop_items)) 325 logging.debug("rule_set: %s", vars(g.cfg.rule)) 326 327 328def register() -> None: 329 """ディスパッチテーブル登録""" 330 331 def dispatch_download(m: "MessageParserProtocol") -> None: 332 m.set_message(g.cfg.setting.database_file, StyleOptions(title="成績記録DB")) 333 334 def dispatch_members_list(m: "MessageParserProtocol") -> None: 335 m.set_message(text_item.get_members_list(), StyleOptions(title="登録済みメンバー", codeblock=True)) 336 m.post.ts = m.data.event_ts 337 m.post.thread_title = "登録済みメンバー" 338 339 def dispatch_team_list(m: "MessageParserProtocol") -> None: 340 m.set_message(text_item.get_team_list(), StyleOptions(title="登録済みチーム", codeblock=True)) 341 m.post.ts = m.data.event_ts 342 m.post.thread_title = "登録済みチーム" 343 344 def dispatch_member_append(m: "MessageParserProtocol") -> None: 345 m.set_message(member.append(m.argument), StyleOptions(title="メンバー追加", key_title=False)) 346 347 def dispatch_member_remove(m: "MessageParserProtocol") -> None: 348 m.set_message(member.remove(m.argument), StyleOptions(title="メンバー削除", key_title=False)) 349 350 def dispatch_team_create(m: "MessageParserProtocol") -> None: 351 m.set_message(team.create(m.argument), StyleOptions(title="チーム作成", key_title=False)) 352 353 def dispatch_team_delete(m: "MessageParserProtocol") -> None: 354 m.set_message(team.delete(m.argument), StyleOptions(title="チーム削除", key_title=False)) 355 356 def dispatch_team_append(m: "MessageParserProtocol") -> None: 357 m.set_message(team.append(m.argument), StyleOptions(title="チーム所属", key_title=False)) 358 359 def dispatch_team_remove(m: "MessageParserProtocol") -> None: 360 m.set_message(team.remove(m.argument), StyleOptions(title="チーム脱退", key_title=False)) 361 362 def dispatch_team_clear(m: "MessageParserProtocol") -> None: 363 m.set_message(team.clear(), StyleOptions(title="全チーム削除", key_title=False)) 364 365 dispatch_table: dict[str, Any] = { 366 "results": libs.commands.results.entry.main, 367 "graph": libs.commands.graph.entry.main, 368 "ranking": libs.commands.ranking.entry.main, 369 "report": libs.commands.report.entry.main, 370 "help": libs.commands.help.entry.main, 371 "member": dispatch_members_list, 372 "team": dispatch_team_list, 373 "team_list": dispatch_team_list, 374 "download": dispatch_download, 375 "add": dispatch_member_append, 376 "delete": dispatch_member_remove, 377 "team_create": dispatch_team_create, 378 "team_del": dispatch_team_delete, 379 "team_add": dispatch_team_append, 380 "team_remove": dispatch_team_remove, 381 "team_clear": dispatch_team_clear, 382 } 383 384 commandword_list: list[str] 385 for command, ep in dispatch_table.items(): 386 # 呼び出しキーワード登録 387 if hasattr(g.cfg, command): 388 commandword_list = [] 389 sub_command = cast("SubCommands", getattr(g.cfg, command)) 390 if not any([sub_command.commandword, sub_command.command_suffix]): # 何も設定されていない 391 commandword_list.append(sub_command.default_commandword) 392 elif sub_command.commandword: 393 commandword_list.extend(sub_command.commandword) 394 elif sub_command.command_suffix: # コマンドサフィックス登録 395 for rule_version in g.cfg.rule.rule_list: 396 commandword_list.extend( 397 [f"{prefix}{suffix}" for prefix in g.cfg.rule.keywords(rule_version) for suffix in sub_command.command_suffix], 398 ) 399 sub_command.commandword = commandword_list 400 for commandword in commandword_list: 401 g.keyword_dispatcher.update({commandword: ep}) 402 # スラッシュコマンド登録 403 if hasattr(g.cfg.alias, command): 404 for alias in cast(list[str], getattr(g.cfg.alias, command)): 405 g.command_dispatcher.update({alias: ep}) 406 407 # サービス別コマンド登録 408 g.command_dispatcher.update(g.adapter.conf.command_dispatcher) 409 g.keyword_dispatcher.update(g.adapter.conf.keyword_dispatcher) 410 411 logging.debug("keyword_dispatcher:\n%s", "\n".join([f"\t{k}: {v}" for k, v in g.keyword_dispatcher.items()])) 412 logging.debug("command_dispatcher:\n%s", "\n".join([f"\t{k}: {v}" for k, v in g.command_dispatcher.items()]))
def
set_loglevel() -> None:
35def set_loglevel() -> None: 36 """ログレベル追加""" 37 # DEBUG : 10 38 # INFO : 20 39 # WARNING : 30 40 # ERROR : 40 41 # CRITICAL : 50 42 43 # TRACE 44 logging.TRACE = 5 # type: ignore 45 logging.trace = partial(logging.log, logging.TRACE) # type: ignore 46 logging.addLevelName(logging.TRACE, "TRACE") # type: ignore
ログレベル追加
49def arg_parser() -> Args: 50 """ 51 コマンドライン解析 52 53 Returns: 54 Args : ArgumentParserオブジェクト 55 56 """ 57 prog_name = os.path.basename(sys.argv[0]) 58 p = argparse.ArgumentParser( 59 formatter_class=argparse.RawTextHelpFormatter, 60 add_help=True, 61 allow_abbrev=False, 62 ) 63 64 p.add_argument( 65 "-c", 66 "--config", 67 type=Path, 68 default=Path("config.ini"), 69 help="設定ファイル(default: %(default)s)", 70 ) 71 p.add_argument( 72 "--no-cleanup", 73 dest="no_cleanup", 74 action="store_false", 75 help="作業ディレクトリの内容を削除しない", 76 ) 77 p.add_argument( 78 "-s", 79 "--service", 80 choices=[ 81 "slack", 82 "discord", 83 "standard_io", 84 "std", 85 "web", 86 "flask", 87 ], 88 type=str, 89 default="slack", 90 help="連携先サービス", 91 ) 92 93 logging_group = p.add_argument_group("logging options") 94 logging_group.add_argument( 95 "-d", 96 "--debug", 97 action="count", 98 default=0, 99 help="デバッグレベル(-d, -dd)", 100 ) 101 logging_group.add_argument( 102 "-v", 103 "--verbose", 104 action="count", 105 default=0, 106 help="動作ログ出力レベル(-v, -vv, -vvv)", 107 ) 108 logging_group.add_argument( 109 "--moderate", 110 action="store_true", 111 help="ログレベルがエラー以下のもを非表示", 112 ) 113 logging_group.add_argument( 114 "--notime", 115 action="store_true", 116 help="ログフォーマットから日時を削除", 117 ) 118 119 match prog_name: 120 case "app.py": 121 service_stdio = p.add_argument_group("Only allowed when --service=standard_io") 122 service_stdio.add_argument( 123 "--text", 124 type=str, 125 help="input text strings", 126 ) 127 service_web = p.add_argument_group("Only allowed when --service=web") 128 service_web.add_argument( 129 "--host", 130 type=str, 131 default="127.0.0.1", 132 help="listen address(default: %(default)s)", 133 ) 134 service_web.add_argument( 135 "--port", 136 type=int, 137 default=8000, 138 help="bind port(default: %(default)s)", 139 ) 140 case "dbtools.py": # dbtools専用オプション 141 required = p.add_argument_group("Required options(amutually exclusive)") 142 exclusive = required.add_mutually_exclusive_group() 143 exclusive.add_argument( 144 "--compar", 145 action="store_true", 146 help="データ突合", 147 ) 148 exclusive.add_argument( 149 "--unification", 150 type=Path, 151 nargs="?", 152 const="rename.ini", 153 help="ファイルの内容に従って記録済みのメンバー名を修正する(default: %(const)s)", 154 ) 155 exclusive.add_argument( 156 "--recalculation", 157 action="store_true", 158 help="ポイント再計算", 159 ) 160 exclusive.add_argument( 161 "--export", 162 dest="export_data", 163 type=str, 164 nargs="?", 165 const="export", 166 metavar="PREFIX", 167 help="メンバー設定情報をエクスポート(default prefix: %(const)s)", 168 ) 169 exclusive.add_argument( 170 "--import", 171 dest="import_data", 172 type=str, 173 nargs="?", 174 const="export", 175 metavar="PREFIX", 176 help="メンバー設定情報をインポート(default prefix: %(const)s)", 177 ) 178 exclusive.add_argument( 179 "--vacuum", 180 action="store_true", 181 help="database vacuum", 182 ) 183 exclusive.add_argument( 184 "--gen-test-data", 185 type=int, 186 dest="gen_test_data", 187 nargs="?", 188 const=1, 189 default=None, 190 metavar="count", 191 help="テスト用サンプルデータ生成(count=生成回数, default: %(const)s)", 192 ) 193 case "test.py": # 動作テスト用オプション 194 p.add_argument( 195 "-t", 196 "--testcase", 197 dest="testcase", 198 type=Path, 199 ) 200 201 args, unknown = p.parse_known_args() 202 if unknown and prog_name in ["app.py", "dbtools.py"]: 203 p.print_usage() 204 sys.exit(f"\ninvalid args: {unknown}") 205 206 return cast(Args, args)
コマンドライン解析
Returns:
Args : ArgumentParserオブジェクト
def
setup(init_db: bool = True) -> None:
209def setup(init_db: bool = True) -> None: 210 """ 211 設定ファイル読み込み処理 212 213 Args: 214 init_db (bool, optional): resultdbの初期化処理を行う Defaults to True. 215 216 """ 217 set_loglevel() 218 219 g.args = arg_parser() 220 221 # ログフォーマット 222 if g.args.notime: 223 fmt = "" 224 else: 225 fmt = "[%(asctime)s]" 226 227 # デバッグレベル 228 match g.args.debug: 229 case 1: 230 fmt += "[%(levelname)s][%(module)s:%(funcName)s] %(message)s" 231 logging.basicConfig(level=logging.DEBUG, format=fmt) 232 logging.info("DEBUG MODE") 233 case 2: 234 fmt += "[%(levelname)s][%(module)s:%(funcName)s] %(message)s" 235 logging.basicConfig(level=logging.TRACE, format=fmt) # type: ignore 236 logging.info("TRACE MODE") 237 case _: 238 fmt += "[%(levelname)s][%(module)s:%(funcName)s] %(message)s" 239 if g.args.moderate: 240 logging.basicConfig(level=logging.WARNING, format=fmt) 241 else: 242 logging.basicConfig(level=logging.INFO, format=fmt) 243 244 g.cfg = AppConfig(g.args.config) 245 246 # 連携サービス 247 match g.args.service: 248 case "slack": 249 g.cfg.selected_service = ServiceType.SLACK 250 case "discord": 251 g.cfg.selected_service = ServiceType.DISCORD 252 case "standard_io" | "std": 253 g.cfg.selected_service = ServiceType.STANDARD_IO 254 case "web" | "flask": 255 g.cfg.selected_service = ServiceType.WEB 256 case _: 257 sys.exit() 258 259 if not hasattr(g.args, "testcase"): 260 g.args.testcase = None 261 else: 262 g.cfg.selected_service = ServiceType.STANDARD_IO 263 264 g.adapter = factory.select_adapter(g.cfg.selected_service, g.cfg) 265 266 # ディレクトリ作成 267 if not g.args.testcase: 268 if g.cfg.setting.work_dir.is_dir() and g.args.no_cleanup: 269 shutil.rmtree(g.cfg.setting.work_dir) 270 try: 271 g.cfg.setting.work_dir.mkdir(exist_ok=True) 272 except FileExistsError as err: 273 sys.exit(str(err)) 274 275 if isinstance(g.cfg.setting.backup_dir, Path): 276 try: 277 g.cfg.setting.backup_dir.mkdir(exist_ok=True) 278 except FileExistsError as err: 279 sys.exit(str(err)) 280 281 # 初期化 282 initialization.main(init_db) 283 lookup.read_memberslist() 284 285 register() 286 287 # キーワード重複チェック 288 g.cfg.rule.check( 289 chk_commands=set( 290 g.cfg.results.commandword 291 + g.cfg.graph.commandword 292 + g.cfg.ranking.commandword 293 + g.cfg.report.commandword 294 + g.cfg.help.commandword 295 + g.cfg.rule.remarks_words 296 + list(g.keyword_dispatcher) 297 ), 298 chk_members=set(lookup.enumeration_all_members()), 299 default_rule=g.cfg.setting.default_rule, 300 ) 301 302 # 設定情報 303 logging.info("main_config: %s", g.cfg.config_file.absolute()) 304 if g.cfg.setting.rule_config: 305 logging.info("rule_config: %s", g.cfg.setting.rule_config.absolute()) 306 if isinstance(g.cfg.setting.database_file, Path): 307 logging.info("resultdb: %s", g.cfg.setting.database_file.absolute()) 308 logging.info( 309 "service: %s, graph_library: %s, time_adjust: %sh", 310 g.cfg.selected_service, 311 g.adapter.conf.plotting_backend, 312 g.cfg.setting.time_adjust, 313 ) 314 315 g.cfg.rule.info() 316 317 drop_items = ["section", "default_commandword", "command_suffix", "main_parser", "section_proxy", "info"] 318 logging.debug("setting: %s", g.cfg.setting.to_dict(drop_items)) 319 logging.debug("member: %s", g.cfg.member.to_dict(drop_items)) 320 logging.debug("team: %s", g.cfg.team.to_dict(drop_items)) 321 logging.debug("results: %s", g.cfg.results.to_dict(drop_items)) 322 logging.debug("graph: %s", g.cfg.graph.to_dict(drop_items)) 323 logging.debug("ranking: %s", g.cfg.ranking.to_dict(drop_items)) 324 logging.debug("report: %s", g.cfg.report.to_dict(drop_items)) 325 logging.debug("help: %s", g.cfg.help.to_dict(drop_items)) 326 logging.debug("rule_set: %s", vars(g.cfg.rule))
設定ファイル読み込み処理
Arguments:
- init_db (bool, optional): resultdbの初期化処理を行う Defaults to True.
def
register() -> None:
329def register() -> None: 330 """ディスパッチテーブル登録""" 331 332 def dispatch_download(m: "MessageParserProtocol") -> None: 333 m.set_message(g.cfg.setting.database_file, StyleOptions(title="成績記録DB")) 334 335 def dispatch_members_list(m: "MessageParserProtocol") -> None: 336 m.set_message(text_item.get_members_list(), StyleOptions(title="登録済みメンバー", codeblock=True)) 337 m.post.ts = m.data.event_ts 338 m.post.thread_title = "登録済みメンバー" 339 340 def dispatch_team_list(m: "MessageParserProtocol") -> None: 341 m.set_message(text_item.get_team_list(), StyleOptions(title="登録済みチーム", codeblock=True)) 342 m.post.ts = m.data.event_ts 343 m.post.thread_title = "登録済みチーム" 344 345 def dispatch_member_append(m: "MessageParserProtocol") -> None: 346 m.set_message(member.append(m.argument), StyleOptions(title="メンバー追加", key_title=False)) 347 348 def dispatch_member_remove(m: "MessageParserProtocol") -> None: 349 m.set_message(member.remove(m.argument), StyleOptions(title="メンバー削除", key_title=False)) 350 351 def dispatch_team_create(m: "MessageParserProtocol") -> None: 352 m.set_message(team.create(m.argument), StyleOptions(title="チーム作成", key_title=False)) 353 354 def dispatch_team_delete(m: "MessageParserProtocol") -> None: 355 m.set_message(team.delete(m.argument), StyleOptions(title="チーム削除", key_title=False)) 356 357 def dispatch_team_append(m: "MessageParserProtocol") -> None: 358 m.set_message(team.append(m.argument), StyleOptions(title="チーム所属", key_title=False)) 359 360 def dispatch_team_remove(m: "MessageParserProtocol") -> None: 361 m.set_message(team.remove(m.argument), StyleOptions(title="チーム脱退", key_title=False)) 362 363 def dispatch_team_clear(m: "MessageParserProtocol") -> None: 364 m.set_message(team.clear(), StyleOptions(title="全チーム削除", key_title=False)) 365 366 dispatch_table: dict[str, Any] = { 367 "results": libs.commands.results.entry.main, 368 "graph": libs.commands.graph.entry.main, 369 "ranking": libs.commands.ranking.entry.main, 370 "report": libs.commands.report.entry.main, 371 "help": libs.commands.help.entry.main, 372 "member": dispatch_members_list, 373 "team": dispatch_team_list, 374 "team_list": dispatch_team_list, 375 "download": dispatch_download, 376 "add": dispatch_member_append, 377 "delete": dispatch_member_remove, 378 "team_create": dispatch_team_create, 379 "team_del": dispatch_team_delete, 380 "team_add": dispatch_team_append, 381 "team_remove": dispatch_team_remove, 382 "team_clear": dispatch_team_clear, 383 } 384 385 commandword_list: list[str] 386 for command, ep in dispatch_table.items(): 387 # 呼び出しキーワード登録 388 if hasattr(g.cfg, command): 389 commandword_list = [] 390 sub_command = cast("SubCommands", getattr(g.cfg, command)) 391 if not any([sub_command.commandword, sub_command.command_suffix]): # 何も設定されていない 392 commandword_list.append(sub_command.default_commandword) 393 elif sub_command.commandword: 394 commandword_list.extend(sub_command.commandword) 395 elif sub_command.command_suffix: # コマンドサフィックス登録 396 for rule_version in g.cfg.rule.rule_list: 397 commandword_list.extend( 398 [f"{prefix}{suffix}" for prefix in g.cfg.rule.keywords(rule_version) for suffix in sub_command.command_suffix], 399 ) 400 sub_command.commandword = commandword_list 401 for commandword in commandword_list: 402 g.keyword_dispatcher.update({commandword: ep}) 403 # スラッシュコマンド登録 404 if hasattr(g.cfg.alias, command): 405 for alias in cast(list[str], getattr(g.cfg.alias, command)): 406 g.command_dispatcher.update({alias: ep}) 407 408 # サービス別コマンド登録 409 g.command_dispatcher.update(g.adapter.conf.command_dispatcher) 410 g.keyword_dispatcher.update(g.adapter.conf.keyword_dispatcher) 411 412 logging.debug("keyword_dispatcher:\n%s", "\n".join([f"\t{k}: {v}" for k, v in g.keyword_dispatcher.items()])) 413 logging.debug("command_dispatcher:\n%s", "\n".join([f"\t{k}: {v}" for k, v in g.command_dispatcher.items()]))
ディスパッチテーブル登録