libs.utils.validator
libs/utils/validator.py
1""" 2libs/utils/validator.py 3""" 4 5import re 6from typing import Literal 7 8import libs.global_value as g 9from cls.parser import CommandParser 10from cls.score import GameResult 11from cls.timekit import ExtendedDatetime as ExtDt 12from libs.utils import formatter, textutil 13 14 15def check_namepattern(name: str, kind: Literal["member", "team"]) -> tuple[bool, str]: 16 """登録制限チェック 17 18 Args: 19 name (str): チェックする名前 20 kind (str): チェック種別 21 - member 22 - team 23 24 Returns: 25 tuple[bool, str]: 判定結果 26 - bool: 制限チェック結果真偽 27 - str: 制限理由 28 """ 29 30 def _pattern_gen(check_list: list[str]) -> list[str]: 31 ret: list = [] 32 for x in check_list: 33 ret.append(x) 34 ret.append(textutil.str_conv(x, "k2h")) # ひらがな 35 ret.append(textutil.str_conv(x, "h2k")) # カタカナ 36 37 return list(set(ret)) 38 39 check_pattern = _pattern_gen([name, formatter.honor_remove(name)]) # 入力パターン 40 ret_flg: bool = True 41 ret_msg: str = "OK" 42 43 # 名前チェック 44 check_list = _pattern_gen(list(g.member_list.keys())) # メンバーチェック 45 if ret_flg and any(x in check_list for x in check_pattern): 46 ret_flg, ret_msg = False, f"「{name}」は存在するメンバーです。" 47 48 check_list = _pattern_gen([x["team"] for x in g.team_list]) # チームチェック 49 if ret_flg and any(x in check_list for x in check_pattern): 50 ret_flg, ret_msg = False, f"「{name}」は存在するチームです。" 51 52 if ret_flg and g.cfg.member.guest_name in check_pattern: # ゲストチェック 53 ret_flg, ret_msg = False, "使用できない名前です。" 54 55 # 登録規定チェック 56 if ret_flg and len(name) > int(getattr(g.cfg, kind).character_limit): # 文字制限 57 ret_flg, ret_msg = False, "登録可能文字数を超えています。" 58 59 if ret_flg and re.search("[\\;:<>(),!@#*?/`\"']", name) or not name.isprintable(): # 禁則記号 60 ret_flg, ret_msg = False, "使用できない記号が含まれています。" 61 62 # 引数と同名になっていないかチェック 63 if ret_flg and name in ExtDt.valid_keywords(): 64 ret_flg, ret_msg = False, "検索範囲指定に使用される単語では登録できません。" 65 66 if ret_flg and CommandParser().is_valid_command(name): 67 ret_flg, ret_msg = False, "オプションに使用される単語では登録できません。" 68 69 if ret_flg and name in g.cfg.word_list(): 70 ret_flg, ret_msg = False, "コマンドに使用される単語では登録できません。" 71 72 return (ret_flg, ret_msg) 73 74 75def pattern(text: str) -> GameResult: 76 """成績記録用フォーマットチェック 77 78 Args: 79 text (str): slackにポストされた内容 80 81 Returns: 82 GameResult: スコアデータ 83 """ 84 85 # 記号を置換 86 replace_chr = [ 87 (chr(0xff0b), "+"), # 全角プラス符号 88 (chr(0x2212), "-"), # 全角マイナス符号 89 (chr(0xff08), "("), # 全角丸括弧 90 (chr(0xff09), ")"), # 全角丸括弧 91 (chr(0x2017), "_"), # DOUBLE LOW LINE(半角) 92 ] 93 for z, h in replace_chr: 94 text = text.replace(z, h) 95 96 text = "".join(text.split()) 97 98 # パターンマッチング 99 pattern1 = re.compile( 100 rf"^({g.cfg.search.keyword})" + r"([^0-9()+-]+)([0-9+-]+)" * 4 + r"$" 101 ) 102 pattern2 = re.compile( 103 r"^" + r"([^0-9()+-]+)([0-9+-]+)" * 4 + rf"({g.cfg.search.keyword})$" 104 ) 105 pattern3 = re.compile( 106 rf"^({g.cfg.search.keyword})\((.+?)\)" + r"([^0-9()+-]+)([0-9+-]+)" * 4 + r"$" 107 ) 108 pattern4 = re.compile( 109 r"^" + r"([^0-9()+-]+)([0-9+-]+)" * 4 + rf"({g.cfg.search.keyword})\((.+?)\)$" 110 ) 111 112 # 情報取り出し 113 result = GameResult(rule_version=g.cfg.mahjong.rule_version) 114 position: dict[str, int] = {} 115 match text: 116 case text if pattern1.findall(text): 117 msg = pattern1.findall(text)[0] 118 position = { 119 "p1_name": 1, "p1_str": 2, 120 "p2_name": 3, "p2_str": 4, 121 "p3_name": 5, "p3_str": 6, 122 "p4_name": 7, "p4_str": 8, 123 } 124 comment = None 125 case text if pattern2.findall(text): 126 msg = pattern2.findall(text)[0] 127 position = { 128 "p1_name": 0, "p1_str": 1, 129 "p2_name": 2, "p2_str": 3, 130 "p3_name": 4, "p3_str": 5, 131 "p4_name": 6, "p4_str": 7, 132 } 133 comment = None 134 case text if pattern3.findall(text): 135 msg = pattern3.findall(text)[0] 136 position = { 137 "p1_name": 2, "p1_str": 3, 138 "p2_name": 4, "p2_str": 5, 139 "p3_name": 6, "p3_str": 7, 140 "p4_name": 8, "p4_str": 9, 141 } 142 comment = str(msg[1]) 143 case text if pattern4.findall(text): 144 msg = pattern4.findall(text)[0] 145 position = { 146 "p1_name": 0, "p1_str": 1, 147 "p2_name": 2, "p2_str": 3, 148 "p3_name": 4, "p3_str": 5, 149 "p4_name": 6, "p4_str": 7, 150 } 151 comment = str(msg[9]) 152 case _: 153 return result 154 155 g.params.update(unregistered_replace=False) # ゲスト無効 156 g.params.update(individual=True) # チーム戦オフ 157 158 result.set(comment=comment) 159 for k, p in position.items(): 160 if str(k).endswith("_name"): 161 result.set(**{k: formatter.name_replace(str(msg[p]), False)}) 162 continue 163 result.set(**{k: str(msg[p])}) 164 165 return result
def
check_namepattern(name: str, kind: Literal['member', 'team']) -> tuple[bool, str]:
16def check_namepattern(name: str, kind: Literal["member", "team"]) -> tuple[bool, str]: 17 """登録制限チェック 18 19 Args: 20 name (str): チェックする名前 21 kind (str): チェック種別 22 - member 23 - team 24 25 Returns: 26 tuple[bool, str]: 判定結果 27 - bool: 制限チェック結果真偽 28 - str: 制限理由 29 """ 30 31 def _pattern_gen(check_list: list[str]) -> list[str]: 32 ret: list = [] 33 for x in check_list: 34 ret.append(x) 35 ret.append(textutil.str_conv(x, "k2h")) # ひらがな 36 ret.append(textutil.str_conv(x, "h2k")) # カタカナ 37 38 return list(set(ret)) 39 40 check_pattern = _pattern_gen([name, formatter.honor_remove(name)]) # 入力パターン 41 ret_flg: bool = True 42 ret_msg: str = "OK" 43 44 # 名前チェック 45 check_list = _pattern_gen(list(g.member_list.keys())) # メンバーチェック 46 if ret_flg and any(x in check_list for x in check_pattern): 47 ret_flg, ret_msg = False, f"「{name}」は存在するメンバーです。" 48 49 check_list = _pattern_gen([x["team"] for x in g.team_list]) # チームチェック 50 if ret_flg and any(x in check_list for x in check_pattern): 51 ret_flg, ret_msg = False, f"「{name}」は存在するチームです。" 52 53 if ret_flg and g.cfg.member.guest_name in check_pattern: # ゲストチェック 54 ret_flg, ret_msg = False, "使用できない名前です。" 55 56 # 登録規定チェック 57 if ret_flg and len(name) > int(getattr(g.cfg, kind).character_limit): # 文字制限 58 ret_flg, ret_msg = False, "登録可能文字数を超えています。" 59 60 if ret_flg and re.search("[\\;:<>(),!@#*?/`\"']", name) or not name.isprintable(): # 禁則記号 61 ret_flg, ret_msg = False, "使用できない記号が含まれています。" 62 63 # 引数と同名になっていないかチェック 64 if ret_flg and name in ExtDt.valid_keywords(): 65 ret_flg, ret_msg = False, "検索範囲指定に使用される単語では登録できません。" 66 67 if ret_flg and CommandParser().is_valid_command(name): 68 ret_flg, ret_msg = False, "オプションに使用される単語では登録できません。" 69 70 if ret_flg and name in g.cfg.word_list(): 71 ret_flg, ret_msg = False, "コマンドに使用される単語では登録できません。" 72 73 return (ret_flg, ret_msg)
登録制限チェック
Arguments:
- name (str): チェックする名前
- kind (str): チェック種別
- member
- team
Returns:
tuple[bool, str]: 判定結果
- bool: 制限チェック結果真偽
- str: 制限理由
76def pattern(text: str) -> GameResult: 77 """成績記録用フォーマットチェック 78 79 Args: 80 text (str): slackにポストされた内容 81 82 Returns: 83 GameResult: スコアデータ 84 """ 85 86 # 記号を置換 87 replace_chr = [ 88 (chr(0xff0b), "+"), # 全角プラス符号 89 (chr(0x2212), "-"), # 全角マイナス符号 90 (chr(0xff08), "("), # 全角丸括弧 91 (chr(0xff09), ")"), # 全角丸括弧 92 (chr(0x2017), "_"), # DOUBLE LOW LINE(半角) 93 ] 94 for z, h in replace_chr: 95 text = text.replace(z, h) 96 97 text = "".join(text.split()) 98 99 # パターンマッチング 100 pattern1 = re.compile( 101 rf"^({g.cfg.search.keyword})" + r"([^0-9()+-]+)([0-9+-]+)" * 4 + r"$" 102 ) 103 pattern2 = re.compile( 104 r"^" + r"([^0-9()+-]+)([0-9+-]+)" * 4 + rf"({g.cfg.search.keyword})$" 105 ) 106 pattern3 = re.compile( 107 rf"^({g.cfg.search.keyword})\((.+?)\)" + r"([^0-9()+-]+)([0-9+-]+)" * 4 + r"$" 108 ) 109 pattern4 = re.compile( 110 r"^" + r"([^0-9()+-]+)([0-9+-]+)" * 4 + rf"({g.cfg.search.keyword})\((.+?)\)$" 111 ) 112 113 # 情報取り出し 114 result = GameResult(rule_version=g.cfg.mahjong.rule_version) 115 position: dict[str, int] = {} 116 match text: 117 case text if pattern1.findall(text): 118 msg = pattern1.findall(text)[0] 119 position = { 120 "p1_name": 1, "p1_str": 2, 121 "p2_name": 3, "p2_str": 4, 122 "p3_name": 5, "p3_str": 6, 123 "p4_name": 7, "p4_str": 8, 124 } 125 comment = None 126 case text if pattern2.findall(text): 127 msg = pattern2.findall(text)[0] 128 position = { 129 "p1_name": 0, "p1_str": 1, 130 "p2_name": 2, "p2_str": 3, 131 "p3_name": 4, "p3_str": 5, 132 "p4_name": 6, "p4_str": 7, 133 } 134 comment = None 135 case text if pattern3.findall(text): 136 msg = pattern3.findall(text)[0] 137 position = { 138 "p1_name": 2, "p1_str": 3, 139 "p2_name": 4, "p2_str": 5, 140 "p3_name": 6, "p3_str": 7, 141 "p4_name": 8, "p4_str": 9, 142 } 143 comment = str(msg[1]) 144 case text if pattern4.findall(text): 145 msg = pattern4.findall(text)[0] 146 position = { 147 "p1_name": 0, "p1_str": 1, 148 "p2_name": 2, "p2_str": 3, 149 "p3_name": 4, "p3_str": 5, 150 "p4_name": 6, "p4_str": 7, 151 } 152 comment = str(msg[9]) 153 case _: 154 return result 155 156 g.params.update(unregistered_replace=False) # ゲスト無効 157 g.params.update(individual=True) # チーム戦オフ 158 159 result.set(comment=comment) 160 for k, p in position.items(): 161 if str(k).endswith("_name"): 162 result.set(**{k: formatter.name_replace(str(msg[p]), False)}) 163 continue 164 result.set(**{k: str(msg[p])}) 165 166 return result
成績記録用フォーマットチェック
Arguments:
- text (str): slackにポストされた内容
Returns:
GameResult: スコアデータ