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 session_select_user(bot): """:point_left: *kp select member*\n`/cc kp select`""" body = read_user_data(bot.team_id, bot.user_id, KP_FILE_PATH) dict_kp = json.loads(body) lst_user = dict_kp["lst_user"] user_target = random.choices(lst_user) user_target_param = get_user_param(bot.team_id, user_target[0][0], user_target[0][1]) return user_target_param["name"], yig.config.COLOR_ATTENTION
def easteregg_dump_data(bot): """debug command """ user_param = get_user_param(bot.team_id, bot.user_id) user_param.pop("memo") add_payload = { "text": "```" + json.dumps(user_param, ensure_ascii=False) + "```", "response_type": "ephemeral" } return add_payload, None
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 gui_confirm_select_receiver(bot): """gui not help string""" command_url = "https://slack.com/api/views.update" user_param = get_user_param(bot.team_id, bot.user_id) block_content = [] bot.key = bot.key.replace('+', ' ') # "Do you want to add a correction value?\n" # "For example\n" # "%s+10, %s-20, %s*2, %s/2" % (bot.key, bot.key, bot.key, bot.key) block_content.append( build_plain_text_content(("ロールの補正値がある場合、補正値を入れて下さい\n" "例)\n" "%s+10, %s-20, %s*2, %s/2" % (bot.key, bot.key, bot.key, bot.key)))) block_content.append( build_input_content('Roll correction value', "%s" % bot.key)) map_id = json.loads(read_user_data(bot.team_id, bot.user_id, "key_id")) view_id = map_id["view_id"] channel_id = map_id["channel_id"] view_content = { "type": "modal", "callback_id": "modal-dispatch_in_select", "title": { "type": "plain_text", "text": "Call Of Cthulhu GUI Mode" }, "submit": { "type": "plain_text", "text": "ROLL!", "emoji": True }, "private_metadata": channel_id, "blocks": block_content } payload = { "token": bot.token, "channel": channel_id, "trigger_id": bot.trigger_id, "view_id": view_id, "private_metadata": channel_id, "response_action": "clear", "view": json.dumps(view_content, ensure_ascii=False) } res = requests.post(command_url, data=payload) logging.info(json.dumps(res.text))
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_memo(bot): """:spiral_note_pad: *show user memo*\n`/cc memo`""" user_param = get_user_param(bot.team_id, bot.user_id) return user_param[bot.message], yig.config.COLOR_ATTENTION
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
def gui_receiver(bot): """gui not help string""" command_url = "https://slack.com/api/views.open" user_param = get_user_param(bot.team_id, bot.user_id) block_content = [] block_content.append(build_channel_select_content()) # 'Init your character sheet' block_content.append( build_input_content('キャラクターシートのURLからデータを初期化します', "https://~")) if user_param != {}: # Update your character sheet block_content.append( build_button_content('update', 'キャラクターシートの変更点を反映させます', "modal-dispatch_go_button_0")) # Your Sanity check block_content.append( build_button_content('SAN Check', 'SANチェックを行います', "modal-confirm_button_with_sanc")) # Change the , of the character. block_content.append( build_radio_button_content(['HP', 'MP', 'SAN'], 'PCの', 'を変更します')) block_content.append(divider_builder()) block_content.append(build_skill_content(user_param)) block_content.append(build_skill_content(user_param, 'hide ')) block_content.append(build_param_content()) block_content.append(divider_builder()) # session join or leave. block_content.append( build_button_content('join/leave session', 'セッションに参加/離脱します', "modal-confirm_button_with_session")) # Save your icon image block_content.append( build_button_content('saveimg', 'アイコンの画像を保存します', "modal-dispatch_go_button_1")) block_content.append( build_button_content('result', 'セッション中のロール結果を表示します\n(ゲーム終了後に押しましょう)', "modal-dispatch_go_button_2")) # More command block_content.append( build_button_content('help', 'それ以外のコマンドを確認します', "modal-dispatch_go_button_3")) block_content.append(divider_builder()) now = datetime.now() view_content = { "type": "modal", "callback_id": "modal-identifier", "title": { "type": "plain_text", "text": "Call Of Cthulhu GUI Mode" }, "submit": { "type": "plain_text", "text": "Init Your Charasheet.", "emoji": True }, "blocks": block_content } payload = { "token": bot.token, "trigger_id": bot.trigger_id, "view": json.dumps(view_content, ensure_ascii=False) } res = requests.post(command_url, data=payload) res_json = json.loads(res.text) logging.info(json.dumps(res_json)) for k, data in res_json["view"]["state"]["values"].items(): for kk, datum in data.items(): if datum["type"] == "conversations_select": bot.channel_id = datum["selected_conversation"] write_user_data( bot.team_id, bot.user_id, "key_id", json.dumps({ "view_id": res_json["view"]["id"], "channel_id": bot.channel_id }))