def update_charasheet_with_vampire(bot): """:arrows_counterclockwise: *update charasheet* `/cc u` `/cc update` """ state_data = get_state_data(bot.team_id, bot.user_id) tz = datetime.timezone.utc now = datetime.datetime.now(tz) state_data["ts"] = now.timestamp() user_param_old = get_user_param(bot.team_id, bot.user_id, state_data["pc_id"]) url = state_data["url"] res = requests.get(url) request_json = json.loads(res.text) if user_param_old["game"] == "coc": user_param = format_param_json_with_6(bot, request_json) elif user_param_old["game"] == "coc7": user_param = format_param_json_with_7(bot, request_json) user_param["url"] = user_param_old["url"] pc_id = user_param["pc_id"] key = f"{pc_id}.json" write_pc_json = json.dumps(user_param, ensure_ascii=False).encode('utf-8') write_user_data(bot.team_id, bot.user_id, key, write_pc_json) return build_chara_response(user_param, state_data, "UPDATE CHARACTER", bot.team_id, bot.user_id, pc_id), None
def icon_save_image(bot): """:art: *save slack icon*\n`/cc saveimg`""" state_data = get_state_data(bot.team_id, bot.user_id) icon_url = bot.data_user["profile"]["image_512"] image_path = write_pc_image(bot.team_id, bot.user_id, state_data["pc_id"], icon_url) tz = datetime.timezone.utc now = datetime.datetime.now(tz) state_data["ts"] = now.timestamp() set_state_data(bot.team_id, bot.user_id, state_data) return "アイコンを保存しました。", yig.config.COLOR_ATTENTION
def sanity_check(bot): """:ghost: *san check*\n`/cc sanc`\n`/cc sanc [safe_point]/[fail_point]`""" state_data = get_state_data(bot.team_id, bot.user_id) param = get_user_param(bot.team_id, bot.user_id, state_data["pc_id"]) c_san = int(param["現在SAN"]) if "SAN" in state_data: d_san = int(state_data["SAN"]) else: d_san = 0 sum_san = c_san + d_san message, color = get_sanc_result(bot.key, sum_san) return message, color
def icon_load_image(bot): """:frame_with_picture: *load icon image*\n`/cc loadimg`""" state_data = get_state_data(bot.team_id, bot.user_id) image = get_charaimage(bot.team_id, bot.user_id, state_data["pc_id"]) param = { 'token': bot.token, "channels": bot.channel_id } res = requests.post(url="https://slack.com/api/files.upload", params=param, files={'files': image}) return "アイコン画像をロードしました。", yig.config.COLOR_ATTENTION
def session_leave(bot): """:wave: *leave TRPG session*\n`/cc leave [SESSION_ID]`""" color = yig.config.COLOR_ATTENTION if bot.channel_name == "": bot.channel_name = get_channel_name(bot.channel_id, bot.token) state_data = get_state_data(bot.team_id, bot.user_id) kp_id = analyze_join_command(bot.key) if kp_id: reduce_gamesession_user(bot.team_id, kp_id, bot.user_id, state_data['pc_id']) state_data.pop("kp_id") set_state_data(bot.team_id, bot.user_id, state_data) return "セッションから退出しました", color else: return "%s\nLEAVEコマンドが不正です" % bot.message, color
def session_join(bot): """:+1: *join TRPG session*\n`/cc join [SESSION_ID]`""" color = yig.config.COLOR_ATTENTION if bot.channel_name == "": bot.channel_name = get_channel_name(bot.channel_id, bot.token) state_data = get_state_data(bot.team_id, bot.user_id) user_param = get_user_param(bot.team_id, bot.user_id, state_data['pc_id']) kp_id = analyze_join_command(bot.key) if kp_id: add_gamesession_user(bot.team_id, kp_id, bot.user_id, user_param['name'], state_data['pc_id'], bot.channel_name, bot.data_user) state_data["kp_id"] = kp_id set_state_data(bot.team_id, bot.user_id, state_data) return "セッションに参加しました", color else: return "%s\nJOINコマンドが不正です" % bot.message, color
def get_lst_player_data(team_id, user_id, roll_targ): dict_kp = json.loads( read_user_data(team_id, user_id, KP_FILE_PATH).decode('utf-8')) lst_user = dict_kp["lst_user"] lst_user_data = [] for user in lst_user: state_data = get_state_data(team_id, user[0]) user_param = get_user_param(team_id, user[0], user[1]) name = user_param['name'] lst_user_data.append({ 'name': name, 'user_id': user[0], 'user_param': user_param, 'state_data': state_data, }) lst_user_data.sort(key=lambda x: int(x['user_param'][roll_targ])) lst_user_data.reverse() return lst_user_data
def update_user_status(bot): """:arrows_clockwise: *update user status* `/cc u [STATUS][+|-][POINT]` `/cc update [STATUS][+|-][POINT]` """ result = analyze_update_command(bot.key) state_data = get_state_data(bot.team_id, bot.user_id) user_param = get_user_param(bot.team_id, bot.user_id, state_data["pc_id"]) if result: status_name, operator, arg = result if status_name in state_data: val_targ = state_data[status_name] else: val_targ = "0" num_targ = eval(f'{val_targ}{operator}{arg}') state_data[status_name] = num_targ set_state_data(bot.team_id, bot.user_id, state_data) return get_status_message("UPDATE STATUS", user_param, state_data), yig.config.COLOR_ATTENTION
def help_content_builder(team_id, user_id, listener): about = "This is the command to play Call of Cthulhu.\nEnjoy!" refer = "*<https://github.com/cahlchang/CoCNonKP/blob/main/command_reference.md|All Documents.>*\n\n" dict_function = {} for list_function in listener.values(): for datum in list_function: if datum["function"].__name__ == "roll_skill"\ or datum["function"].__name__.startswith("easteregg")\ or datum["function"].__name__.startswith("gui"): continue dict_function[ datum["function"].__name__] = datum["function"].__doc__ user_param = None try: state_data = get_state_data(team_id, user_id) if state_data != {}: user_param = get_user_param(team_id, user_id, state_data["pc_id"]) except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'NoSuchKey': print('new_participant') else: raise Exception(e) except Exception as e: raise Exception(e) block_content = [{ "type": "header", "text": { "type": "plain_text", "text": about } }, { "type": "section", "text": { "type": "mrkdwn", "text": refer } }] skill_list = [] if user_param is not None: block_content.append(divider_builder()) pc_name = user_param['name'] max_hp = user_param['HP'] now_hp = get_now_status('HP', user_param, state_data) max_mp = user_param['MP'] now_mp = get_now_status('MP', user_param, state_data) max_san = user_param['現在SAN'] now_san = get_now_status('SAN', user_param, state_data, '現在SAN') db = user_param['DB'] user_content = { "type": "section", "text": { "type": "mrkdwn", "text": f"*PC INFO*\n\n*Name:* {pc_name}\n*HP:* {now_hp}/{max_hp} *MP:* {now_mp}/{max_mp} *SAN:* {now_san}/{max_san} *DB:* {db}" }, "accessory": { "type": "image", "image_url": get_pc_image_url(team_id, user_id, state_data["pc_id"], state_data['ts']), "alt_text": "image" } } block_content.append(user_content) for k, v in user_param.items(): if isinstance(v, list): skill_list.append((k, v[-1])) block_content.append(divider_builder()) block_content.append( section_builder([ dict_function.pop('init_charasheet'), dict_function.pop('init_charasheet_with_vampire'), dict_function.pop('update_charasheet_with_vampire') ])) block_content.append( section_builder([ dict_function.pop('show_status'), dict_function.pop('update_user_status'), dict_function.pop('show_memo') ])) block_content.append(divider_builder()) block_content.append( section_builder([ dict_function.pop('sanity_check'), dict_function.pop('dice_roll') ])) block_content.append( section_builder([ dict_function.pop('icon_save_image'), dict_function.pop('icon_load_image') ])) block_content.append( section_builder([ dict_function.pop('hide_roll'), dict_function.pop('show_list_chara') ])) block_content.append(divider_builder()) block_content.append(section_builder([dict_function.pop('session_start')])) lst_session = [k for k in dict_function.keys() if k.startswith('session')] lst_session_docs = list(map(dict_function.pop, lst_session)) block_content.append(section_builder(lst_session_docs)) block_content.append(divider_builder()) block_content.append(section_builder(dict_function.values())) help_content = [{'blocks': json.dumps(block_content, ensure_ascii=False)}] if user_param is not None: help_content.extend( user_roll_help_content(skill_list, user_param, state_data)) return help_content
def show_status(bot): """:eyes: *show status*\n`/cc s`\n`/cc status`""" dict_state = get_state_data(bot.team_id, bot.user_id) user_param = get_user_param(bot.team_id, bot.user_id, dict_state["pc_id"]) return get_status_message("STATUS", user_param, dict_state), yig.config.COLOR_ATTENTION
def session_result(bot): """:bell: *Result session Data*\n`/cc result`""" user_id = bot.user_id state_data = get_state_data(bot.team_id, bot.user_id) user_param = get_user_param(bot.team_id, bot.user_id, state_data['pc_id']) dex = user_param["DEX"] pc_name = user_param["name"] job = user_param["job"] age = user_param["age"] sex = user_param["sex"] now_hp, max_hp, now_mp, max_mp, now_san, max_san, db = get_basic_status( user_param, state_data) if bot.channel_name == "": bot.channel_name = get_channel_name(bot.channel_id, bot.token) session_data = json.loads( read_session_data( bot.team_id, "%s/%s.json" % (bot.channel_name, state_data["pc_id"]))) block_content = [] image_url = get_pc_image_url(bot.team_id, bot.user_id, state_data['pc_id'], state_data['ts']) chara_url = user_param["url"] user_content = { "type": "section", "text": { "type": "mrkdwn", "text": (f"<@{user_id}> *ROLL RESULT*\n*Name: * <{chara_url}|{pc_name}> *LINK: * <{image_url}|image>\n" f"*JOB: * {job} *AGE: * {age} *SEX :* {sex}\n" f"*HP: * *{now_hp}*/{max_hp} *MP:* *{now_mp}*/{max_mp} *SAN:* *{now_san}*/{max_san} *DEX: * *{dex}* *DB:* *{db}*\n" ) }, "accessory": { "type": "image", "image_url": image_url, "alt_text": "image" } } block_content.append(user_content) result_message = "" is_first = True lst_result = [] cnt_msg = 60 # map_symbol = {"クリティカル": 0, "成功": 0 for idx, data in enumerate(session_data): symbols = { "クリティカル": ":sparkles:", "成功": ":large_blue_circle:", "失敗": ":x:", "ファンブル": ":skull_and_crossbones:" } result_message += "%s *%s* *%s* *%s* (%s)\n" % ( symbols[data["result"]], data["result"], data["roll"], data["num_rand"], data["num_targ"]) if idx % cnt_msg == cnt_msg - 1: lst_result.append(result_message) result_message = "" elif idx == len(session_data) - 1: lst_result.append(result_message) lst_content = [] if len(lst_result) == 0 and is_first == True: result_message = "No Result" else: for idx, result in enumerate(lst_result): if idx == 0: block_content.append({ "type": "section", "text": { "type": "mrkdwn", "text": result } }) lst_content.append( {'blocks': json.dumps(block_content, ensure_ascii=False)}) else: other_content = [{ "type": "section", "text": { "type": "mrkdwn", "text": result } }] lst_content.append( {'blocks': json.dumps(other_content, ensure_ascii=False)}) return lst_content, None
def post_hide(user_id): post_url = 'https://slack.com/api/chat.postMessage' state_data = get_state_data(bot.team_id, bot.user_id) user_param = get_user_param(bot.team_id, bot.user_id, state_data["pc_id"]) channel = '@' + state_data["kp_id"] key = bot.key text = "" m = re.match(r"HIDE\s(.*?)(\+|\-|\*|\/)?(\d{,})?$", key) if m.group(1) not in user_param.keys(): text = f"<@{user_id}> try talk" post_message = f"{key}" color = "gray" else: hide_message = "".join( ['' if v is None else v for v in m.groups()]) roll, operant, num_arg, difficult = analysis_roll_and_calculation( hide_message) alias_roll = {"こぶし": "こぶし(パンチ)"} if roll in alias_roll.keys(): roll = alias_roll[roll] data = user_param[roll] num_rand = int(random.randint(1, 100)) if roll.upper() in yig.config.LST_USER_STATUS_NAME: num = int(data) else: num = int(data[-1]) num_targ = calculation(num, operant, num_arg) if user_param["game"] == "coc": result, color = judge_1d100_with_6_ver(num_targ, num_rand) else: result, color = judge_1d100_with_7_ver(num_targ, num_rand) raw_session_data = read_session_data( bot.team_id, "%s/%s.json" % (bot.channel_name, state_data["pc_id"])) if raw_session_data: session_data = json.loads(raw_session_data) session_data.append({ "roll": "hide " + roll.upper(), "num_targ": f"{num}{operant}{num_arg}", "num_rand": num_rand, "result": result }) write_session_data( bot.team_id, "%s/%s.json" % (bot.channel_name, state_data["pc_id"]), json.dumps(session_data, ensure_ascii=False)) text = f"<@{user_id}> try {roll}" post_message = f"{result} 【{roll}】 {num_rand}/{num_targ} ({num}{operant}{num_arg})" payload = { 'text': text, "attachments": json.dumps([{ "text": post_message, "type": "mrkdwn", "color": color }]) } post_result(bot.token, user_id, channel, payload, "gray")
def roll_skill(bot): state_data = get_state_data(bot.team_id, bot.user_id) user_param = get_user_param(bot.team_id, bot.user_id, state_data["pc_id"]) roll, operant, num_arg, difficult = analysis_roll_and_calculation( bot.message) alias_roll = {"こぶし": "こぶし(パンチ)"} if roll in alias_roll.keys(): roll = alias_roll[roll] if roll.upper() not in user_param: return f"{roll} その技能は覚えていません", "gray" data = user_param[roll.upper()] num_rand = int(random.randint(1, 100)) if roll.upper() in yig.config.LST_USER_STATUS_NAME: num = int(data) else: num = int(data[-1]) num_targ = calculation(num, operant, num_arg) if user_param["game"] == "coc": result, color = judge_1d100_with_6_ver(num_targ, num_rand) else: result, color = judge_1d100_with_7_ver(num_targ, num_rand, difficult) raw_session_data = read_session_data( bot.team_id, "%s/%s.json" % (bot.channel_name, state_data["pc_id"])) if raw_session_data: session_data = json.loads(raw_session_data) session_data.append({ "roll": roll.upper(), "num_targ": f"{num}{operant}{num_arg}", "num_rand": num_rand, "result": result }) write_session_data( bot.team_id, "%s/%s.json" % (bot.channel_name, state_data["pc_id"]), json.dumps(session_data, ensure_ascii=False)) now_hp, max_hp, now_mp, max_mp, now_san, max_san, db = get_basic_status( user_param, state_data) payload = { "attachments": json.dumps([{ "thumb_url": get_pc_image_url(bot.team_id, bot.user_id, state_data["pc_id"], state_data["ts"]), "color": color, "footer": "<%s|%s>\nHP: *%s*/%s MP: *%s*/%s SAN: *%s*/%s DB: *%s*" % (user_param["url"], user_param["name"], now_hp, max_hp, now_mp, max_mp, now_san, max_san, db), "fields": [{ "value": "<@%s>" % (bot.user_id), "type": "mrkdwn" }, { "title": f"*{result}* 【{roll}】 *{num_rand}*/{num_targ} ({num}{operant}{num_arg})", "type": "mrkdwn" }] }]) } return payload, None