libs.commands.registry.member
libs/commands/registry/member.py
1""" 2libs/commands/registry/member.py 3""" 4 5import logging 6from typing import TYPE_CHECKING, TypedDict, cast 7 8import libs.global_value as g 9from libs.bootstrap.section import BaseSection 10from libs.domain import modify 11from libs.types import CommandType 12from libs.utils import dbutil, textutil, validator 13 14if TYPE_CHECKING: 15 from configparser import ConfigParser, SectionProxy 16 17 from libs.bootstrap.app_config import AppConfig 18 19 20class MemberDataDict(TypedDict): 21 """メンバー情報格納辞書""" 22 23 id: int 24 """メンバーID""" 25 name: str 26 """メンバー名""" 27 alias: list[str] 28 """別名リスト""" 29 team: str 30 """所属チーム""" 31 last_update: int 32 """最終更新日""" 33 elapsed_day: int 34 """経過日数""" 35 game_count: int 36 """プレイゲーム数""" 37 38 39class MemberSection(BaseSection): 40 """memberセクション処理""" 41 42 default_commandword: str 43 """コマンドワードデフォルト値""" 44 commandword: list[str] 45 """呼び出しキーワード""" 46 command_suffix: list[str] 47 """コマンド接尾辞(登録キーワード+接尾辞を呼び出しキーワードとして扱う)""" 48 49 section: str 50 main_parser: "ConfigParser" 51 52 info: list[MemberDataDict] 53 """メンバー情報(キャッシュデータ)""" 54 registration_limit: int 55 """登録メンバー上限数""" 56 character_limit: int 57 """名前に使用できる文字数""" 58 alias_limit: int 59 """別名登録上限数""" 60 guest_name: str 61 """未登録メンバー名称""" 62 63 def __init__(self, outer: "AppConfig") -> None: 64 self.default_commandword = "メンバー一覧" 65 self.section = str(CommandType.MEMBER_LIST) 66 self.main_parser = outer.main_parser 67 self._reset() 68 69 def _reset(self) -> None: 70 self.info = [] 71 self.commandword = [] 72 self.command_suffix = [] 73 self.registration_limit = int(255) 74 self.character_limit = int(8) 75 self.alias_limit = int(16) 76 self.guest_name = str("ゲスト") 77 78 def config_load(self, section_proxy: "SectionProxy") -> None: 79 """ 80 設定値取り込み 81 82 Args: 83 section_proxy (SectionProxy): 読み込み先(パーサー + セクション名) 84 85 """ 86 self._reset() 87 self.initialization(section_proxy) 88 89 # 呼び出しキーワード取り込み 90 self.commandword = self.getlist("commandword", fallback=self.default_commandword) 91 92 logging.trace("%s: %s", self.section, self) # type: ignore 93 94 def resolve_name(self, name: str) -> str: 95 """ 96 別名からメンバー名を逆引き 97 98 Args: 99 name (str): 変換する名前 100 101 Returns: 102 str: メンバー名(見つからない場合は空欄) 103 104 """ 105 for x in self.info: 106 if name in x["alias"]: 107 return x["name"] 108 109 return "" 110 111 def alias(self, name: str) -> list[str]: 112 """ 113 指定メンバーの別名をリストで返す 114 115 Args: 116 name (str): メンバー名 117 118 Returns: 119 list[str]: 別名リスト 120 121 """ 122 for x in self.info: 123 if x.get("name") == name: 124 return x.get("alias") 125 return [] 126 127 @property 128 def lists(self) -> list[str]: 129 """メンバー名一覧をリストで返す""" 130 return [x.get("name") for x in self.info] 131 132 @property 133 def all_lists(self) -> list[str]: 134 """ 135 メンバー名、別名をすべてリストで返す 136 137 Returns: 138 list[str]: メンバー名、別名のリスト 139 140 """ 141 ret: list[str] = [] 142 for name in self.lists: 143 ret.append(name) 144 ret.extend(self.alias(name)) 145 146 return list(set(ret)) 147 148 @property 149 def get_info(self) -> list[MemberDataDict]: 150 """ 151 全メンバー情報取得 152 153 Returns: 154 list[MemberDataDict]: メンバー情報 155 156 """ 157 ret = g.params.read_data("MEMBER_INFO").to_dict(orient="records") 158 for row in ret: 159 row.update(alias=str(row["alias"]).split(",")) 160 161 return cast(list[MemberDataDict], ret) 162 163 164def append(argument: list[str]) -> str: 165 """ 166 メンバー追加 167 168 Args: 169 argument (list[str]): 登録情報 170 - argument[0]: 登録するメンバー名 171 - argument[1]: 登録する別名 172 173 Returns: 174 str: 処理結果 175 176 """ 177 resultdb = dbutil.connection(g.cfg.setting.database_file) 178 179 ret: bool = False 180 dbupdate_flg: bool = False 181 msg: str = "使い方が間違っています。" 182 183 if len(argument) == 1: # 新規追加 184 new_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 185 rows = resultdb.execute("select count() from member") 186 count = rows.fetchone()[0] 187 if count > g.cfg.member.registration_limit: 188 msg = "登録上限を超えています。" 189 else: # 登録処理 190 ret, msg = validator.check_namepattern(new_name, "member") 191 if ret: 192 resultdb.execute( 193 "insert into member(name) values (?)", 194 (new_name,), 195 ) 196 resultdb.execute( 197 "insert into alias(name, member) values (?,?)", 198 (new_name, new_name), 199 ) 200 msg = f"「{new_name}」を登録しました。" 201 logging.info("add new member: %s", new_name) 202 203 if len(argument) == 2: # 別名登録 204 new_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 205 nic_name = textutil.str_conv(argument[1], textutil.ConversionType.HtoZ) 206 registration_flg = True 207 rows = resultdb.execute( 208 "select count() from alias where member=?", 209 (new_name,), 210 ) 211 count = rows.fetchone()[0] 212 if count == 0: 213 msg = f"「{new_name}」はまだ登録されていません。" 214 registration_flg = False 215 if count > g.cfg.member.alias_limit: 216 msg = "登録上限を超えています。" 217 registration_flg = False 218 219 if registration_flg: # 登録処理 220 ret, msg = validator.check_namepattern(nic_name, "member") 221 if ret: 222 resultdb.execute( 223 "insert into alias(name, member) values (?,?)", 224 (nic_name, new_name), 225 ) 226 msg = f"「{new_name}」に「{nic_name}」を追加しました。" 227 logging.info("add alias: %s -> %s", new_name, nic_name) 228 dbupdate_flg = True 229 230 if dbupdate_flg: 231 rows = resultdb.execute( 232 """ 233 select distinct name from ( 234 select p1_name as name from result 235 union all select p2_name from result 236 union all select p3_name from result 237 union all select p4_name from result 238 union all select name from remarks 239 ); 240 """ 241 ) 242 name_list = [row["name"] for row in rows.fetchall()] 243 244 if { 245 nic_name, 246 textutil.str_conv(nic_name, textutil.ConversionType.KtoH), 247 textutil.str_conv(nic_name, textutil.ConversionType.HtoK), 248 } & set(name_list): 249 msg += modify.db_backup() 250 for tbl, col in [("result", f"p{x}_name") for x in range(1, 5)] + [("remarks", "name")]: 251 resultdb.execute( 252 f"update {tbl} set {col}=? where {col}=?", 253 (new_name, nic_name), 254 ) 255 resultdb.execute( 256 f"update {tbl} set {col}=? where {col}=?", 257 (new_name, textutil.str_conv(nic_name, textutil.ConversionType.KtoH)), 258 ) 259 resultdb.execute( 260 f"update {tbl} set {col}=? where {col}=?", 261 (new_name, textutil.str_conv(nic_name, textutil.ConversionType.HtoK)), 262 ) 263 msg += "\nデータベースを更新しました。" 264 265 resultdb.commit() 266 resultdb.close() 267 268 g.cfg.member.info = g.cfg.member.get_info 269 270 return msg 271 272 273def remove(argument: list[str]) -> str: 274 """ 275 メンバー削除 276 277 Args: 278 argument (list[str]): 削除情報 279 - argument[0]: 削除するメンバー名 280 - argument[1]: 削除する別名 281 282 Returns: 283 str: 処理結果 284 285 """ 286 resultdb = dbutil.connection(g.cfg.setting.database_file) 287 msg = "使い方が間違っています。" 288 289 if len(argument) == 1: # メンバー削除 290 new_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 291 if new_name in g.cfg.member.lists: 292 resultdb.execute( 293 "delete from member where name=?", 294 (new_name,), 295 ) 296 resultdb.execute( 297 "delete from alias where member=?", 298 (new_name,), 299 ) 300 msg = f"「{new_name}」を削除しました。" 301 logging.info("remove member: %s", new_name) 302 else: 303 msg = f"「{new_name}」は登録されていません。" 304 305 if len(argument) == 2: # 別名削除 306 new_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 307 nic_name = textutil.str_conv(argument[1], textutil.ConversionType.HtoZ) 308 if nic_name in g.cfg.member.lists: 309 resultdb.execute( 310 "delete from alias where name=? and member=?", 311 (nic_name, new_name), 312 ) 313 msg = f"「{new_name}」から「{nic_name}」を削除しました。" 314 logging.info("alias remove: %s -> %s", new_name, nic_name) 315 else: 316 msg = f"「{new_name}」に「{nic_name}」は登録されていません。" 317 318 resultdb.commit() 319 resultdb.close() 320 321 g.cfg.member.info = g.cfg.member.get_info 322 323 return msg
class
MemberDataDict(typing.TypedDict):
21class MemberDataDict(TypedDict): 22 """メンバー情報格納辞書""" 23 24 id: int 25 """メンバーID""" 26 name: str 27 """メンバー名""" 28 alias: list[str] 29 """別名リスト""" 30 team: str 31 """所属チーム""" 32 last_update: int 33 """最終更新日""" 34 elapsed_day: int 35 """経過日数""" 36 game_count: int 37 """プレイゲーム数"""
メンバー情報格納辞書
40class MemberSection(BaseSection): 41 """memberセクション処理""" 42 43 default_commandword: str 44 """コマンドワードデフォルト値""" 45 commandword: list[str] 46 """呼び出しキーワード""" 47 command_suffix: list[str] 48 """コマンド接尾辞(登録キーワード+接尾辞を呼び出しキーワードとして扱う)""" 49 50 section: str 51 main_parser: "ConfigParser" 52 53 info: list[MemberDataDict] 54 """メンバー情報(キャッシュデータ)""" 55 registration_limit: int 56 """登録メンバー上限数""" 57 character_limit: int 58 """名前に使用できる文字数""" 59 alias_limit: int 60 """別名登録上限数""" 61 guest_name: str 62 """未登録メンバー名称""" 63 64 def __init__(self, outer: "AppConfig") -> None: 65 self.default_commandword = "メンバー一覧" 66 self.section = str(CommandType.MEMBER_LIST) 67 self.main_parser = outer.main_parser 68 self._reset() 69 70 def _reset(self) -> None: 71 self.info = [] 72 self.commandword = [] 73 self.command_suffix = [] 74 self.registration_limit = int(255) 75 self.character_limit = int(8) 76 self.alias_limit = int(16) 77 self.guest_name = str("ゲスト") 78 79 def config_load(self, section_proxy: "SectionProxy") -> None: 80 """ 81 設定値取り込み 82 83 Args: 84 section_proxy (SectionProxy): 読み込み先(パーサー + セクション名) 85 86 """ 87 self._reset() 88 self.initialization(section_proxy) 89 90 # 呼び出しキーワード取り込み 91 self.commandword = self.getlist("commandword", fallback=self.default_commandword) 92 93 logging.trace("%s: %s", self.section, self) # type: ignore 94 95 def resolve_name(self, name: str) -> str: 96 """ 97 別名からメンバー名を逆引き 98 99 Args: 100 name (str): 変換する名前 101 102 Returns: 103 str: メンバー名(見つからない場合は空欄) 104 105 """ 106 for x in self.info: 107 if name in x["alias"]: 108 return x["name"] 109 110 return "" 111 112 def alias(self, name: str) -> list[str]: 113 """ 114 指定メンバーの別名をリストで返す 115 116 Args: 117 name (str): メンバー名 118 119 Returns: 120 list[str]: 別名リスト 121 122 """ 123 for x in self.info: 124 if x.get("name") == name: 125 return x.get("alias") 126 return [] 127 128 @property 129 def lists(self) -> list[str]: 130 """メンバー名一覧をリストで返す""" 131 return [x.get("name") for x in self.info] 132 133 @property 134 def all_lists(self) -> list[str]: 135 """ 136 メンバー名、別名をすべてリストで返す 137 138 Returns: 139 list[str]: メンバー名、別名のリスト 140 141 """ 142 ret: list[str] = [] 143 for name in self.lists: 144 ret.append(name) 145 ret.extend(self.alias(name)) 146 147 return list(set(ret)) 148 149 @property 150 def get_info(self) -> list[MemberDataDict]: 151 """ 152 全メンバー情報取得 153 154 Returns: 155 list[MemberDataDict]: メンバー情報 156 157 """ 158 ret = g.params.read_data("MEMBER_INFO").to_dict(orient="records") 159 for row in ret: 160 row.update(alias=str(row["alias"]).split(",")) 161 162 return cast(list[MemberDataDict], ret)
memberセクション処理
MemberSection(outer: libs.bootstrap.app_config.AppConfig)
def
config_load(self, section_proxy: configparser.SectionProxy) -> None:
79 def config_load(self, section_proxy: "SectionProxy") -> None: 80 """ 81 設定値取り込み 82 83 Args: 84 section_proxy (SectionProxy): 読み込み先(パーサー + セクション名) 85 86 """ 87 self._reset() 88 self.initialization(section_proxy) 89 90 # 呼び出しキーワード取り込み 91 self.commandword = self.getlist("commandword", fallback=self.default_commandword) 92 93 logging.trace("%s: %s", self.section, self) # type: ignore
設定値取り込み
Arguments:
- section_proxy (SectionProxy): 読み込み先(パーサー + セクション名)
def
resolve_name(self, name: str) -> str:
95 def resolve_name(self, name: str) -> str: 96 """ 97 別名からメンバー名を逆引き 98 99 Args: 100 name (str): 変換する名前 101 102 Returns: 103 str: メンバー名(見つからない場合は空欄) 104 105 """ 106 for x in self.info: 107 if name in x["alias"]: 108 return x["name"] 109 110 return ""
別名からメンバー名を逆引き
Arguments:
- name (str): 変換する名前
Returns:
str: メンバー名(見つからない場合は空欄)
def
alias(self, name: str) -> list[str]:
112 def alias(self, name: str) -> list[str]: 113 """ 114 指定メンバーの別名をリストで返す 115 116 Args: 117 name (str): メンバー名 118 119 Returns: 120 list[str]: 別名リスト 121 122 """ 123 for x in self.info: 124 if x.get("name") == name: 125 return x.get("alias") 126 return []
指定メンバーの別名をリストで返す
Arguments:
- name (str): メンバー名
Returns:
list[str]: 別名リスト
lists: list[str]
128 @property 129 def lists(self) -> list[str]: 130 """メンバー名一覧をリストで返す""" 131 return [x.get("name") for x in self.info]
メンバー名一覧をリストで返す
all_lists: list[str]
133 @property 134 def all_lists(self) -> list[str]: 135 """ 136 メンバー名、別名をすべてリストで返す 137 138 Returns: 139 list[str]: メンバー名、別名のリスト 140 141 """ 142 ret: list[str] = [] 143 for name in self.lists: 144 ret.append(name) 145 ret.extend(self.alias(name)) 146 147 return list(set(ret))
メンバー名、別名をすべてリストで返す
Returns:
list[str]: メンバー名、別名のリスト
get_info: list[MemberDataDict]
149 @property 150 def get_info(self) -> list[MemberDataDict]: 151 """ 152 全メンバー情報取得 153 154 Returns: 155 list[MemberDataDict]: メンバー情報 156 157 """ 158 ret = g.params.read_data("MEMBER_INFO").to_dict(orient="records") 159 for row in ret: 160 row.update(alias=str(row["alias"]).split(",")) 161 162 return cast(list[MemberDataDict], ret)
全メンバー情報取得
Returns:
list[MemberDataDict]: メンバー情報
def
append(argument: list[str]) -> str:
165def append(argument: list[str]) -> str: 166 """ 167 メンバー追加 168 169 Args: 170 argument (list[str]): 登録情報 171 - argument[0]: 登録するメンバー名 172 - argument[1]: 登録する別名 173 174 Returns: 175 str: 処理結果 176 177 """ 178 resultdb = dbutil.connection(g.cfg.setting.database_file) 179 180 ret: bool = False 181 dbupdate_flg: bool = False 182 msg: str = "使い方が間違っています。" 183 184 if len(argument) == 1: # 新規追加 185 new_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 186 rows = resultdb.execute("select count() from member") 187 count = rows.fetchone()[0] 188 if count > g.cfg.member.registration_limit: 189 msg = "登録上限を超えています。" 190 else: # 登録処理 191 ret, msg = validator.check_namepattern(new_name, "member") 192 if ret: 193 resultdb.execute( 194 "insert into member(name) values (?)", 195 (new_name,), 196 ) 197 resultdb.execute( 198 "insert into alias(name, member) values (?,?)", 199 (new_name, new_name), 200 ) 201 msg = f"「{new_name}」を登録しました。" 202 logging.info("add new member: %s", new_name) 203 204 if len(argument) == 2: # 別名登録 205 new_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 206 nic_name = textutil.str_conv(argument[1], textutil.ConversionType.HtoZ) 207 registration_flg = True 208 rows = resultdb.execute( 209 "select count() from alias where member=?", 210 (new_name,), 211 ) 212 count = rows.fetchone()[0] 213 if count == 0: 214 msg = f"「{new_name}」はまだ登録されていません。" 215 registration_flg = False 216 if count > g.cfg.member.alias_limit: 217 msg = "登録上限を超えています。" 218 registration_flg = False 219 220 if registration_flg: # 登録処理 221 ret, msg = validator.check_namepattern(nic_name, "member") 222 if ret: 223 resultdb.execute( 224 "insert into alias(name, member) values (?,?)", 225 (nic_name, new_name), 226 ) 227 msg = f"「{new_name}」に「{nic_name}」を追加しました。" 228 logging.info("add alias: %s -> %s", new_name, nic_name) 229 dbupdate_flg = True 230 231 if dbupdate_flg: 232 rows = resultdb.execute( 233 """ 234 select distinct name from ( 235 select p1_name as name from result 236 union all select p2_name from result 237 union all select p3_name from result 238 union all select p4_name from result 239 union all select name from remarks 240 ); 241 """ 242 ) 243 name_list = [row["name"] for row in rows.fetchall()] 244 245 if { 246 nic_name, 247 textutil.str_conv(nic_name, textutil.ConversionType.KtoH), 248 textutil.str_conv(nic_name, textutil.ConversionType.HtoK), 249 } & set(name_list): 250 msg += modify.db_backup() 251 for tbl, col in [("result", f"p{x}_name") for x in range(1, 5)] + [("remarks", "name")]: 252 resultdb.execute( 253 f"update {tbl} set {col}=? where {col}=?", 254 (new_name, nic_name), 255 ) 256 resultdb.execute( 257 f"update {tbl} set {col}=? where {col}=?", 258 (new_name, textutil.str_conv(nic_name, textutil.ConversionType.KtoH)), 259 ) 260 resultdb.execute( 261 f"update {tbl} set {col}=? where {col}=?", 262 (new_name, textutil.str_conv(nic_name, textutil.ConversionType.HtoK)), 263 ) 264 msg += "\nデータベースを更新しました。" 265 266 resultdb.commit() 267 resultdb.close() 268 269 g.cfg.member.info = g.cfg.member.get_info 270 271 return msg
メンバー追加
Arguments:
- argument (list[str]): 登録情報
- argument[0]: 登録するメンバー名
- argument[1]: 登録する別名
Returns:
str: 処理結果
def
remove(argument: list[str]) -> str:
274def remove(argument: list[str]) -> str: 275 """ 276 メンバー削除 277 278 Args: 279 argument (list[str]): 削除情報 280 - argument[0]: 削除するメンバー名 281 - argument[1]: 削除する別名 282 283 Returns: 284 str: 処理結果 285 286 """ 287 resultdb = dbutil.connection(g.cfg.setting.database_file) 288 msg = "使い方が間違っています。" 289 290 if len(argument) == 1: # メンバー削除 291 new_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 292 if new_name in g.cfg.member.lists: 293 resultdb.execute( 294 "delete from member where name=?", 295 (new_name,), 296 ) 297 resultdb.execute( 298 "delete from alias where member=?", 299 (new_name,), 300 ) 301 msg = f"「{new_name}」を削除しました。" 302 logging.info("remove member: %s", new_name) 303 else: 304 msg = f"「{new_name}」は登録されていません。" 305 306 if len(argument) == 2: # 別名削除 307 new_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 308 nic_name = textutil.str_conv(argument[1], textutil.ConversionType.HtoZ) 309 if nic_name in g.cfg.member.lists: 310 resultdb.execute( 311 "delete from alias where name=? and member=?", 312 (nic_name, new_name), 313 ) 314 msg = f"「{new_name}」から「{nic_name}」を削除しました。" 315 logging.info("alias remove: %s -> %s", new_name, nic_name) 316 else: 317 msg = f"「{new_name}」に「{nic_name}」は登録されていません。" 318 319 resultdb.commit() 320 resultdb.close() 321 322 g.cfg.member.info = g.cfg.member.get_info 323 324 return msg
メンバー削除
Arguments:
- argument (list[str]): 削除情報
- argument[0]: 削除するメンバー名
- argument[1]: 削除する別名
Returns:
str: 処理結果