from bot import loaded_modules_dict from os import path, pardir from collections import OrderedDict module_name = path.basename(path.normpath(path.join(path.abspath(__file__), pardir, pardir))) widget_name = path.basename(path.abspath(__file__))[:-3] def get_player_table_row_css_class(player_dict): css_classes = [] if player_dict.get("is_online", False): css_classes.append("is_online") if player_dict.get("in_limbo", False): css_classes.append("in_limbo") if int(player_dict.get("health", 0)) > 0: css_classes.append("has_health") if player_dict.get("is_initialized", False): css_classes.append("is_initialized") permission_level = player_dict.get("permission_level", False) if permission_level: css_classes.append("has_level_" + permission_level.zfill(4)) else: css_classes.append("has_no_level") return " ".join(css_classes) def select_view(*args, **kwargs): module = args[0] dispatchers_steamid = kwargs.get('dispatchers_steamid', None) current_view = module.get_current_view(dispatchers_steamid) if current_view == "options": options_view(module, dispatchers_steamid=dispatchers_steamid) elif current_view == "info": show_info_view(module, dispatchers_steamid=dispatchers_steamid) elif current_view == "delete-modal": frontend_view(module, dispatchers_steamid=dispatchers_steamid) delete_modal_view(module, dispatchers_steamid=dispatchers_steamid) elif current_view == "kick-modal": frontend_view(module, dispatchers_steamid=dispatchers_steamid) kick_modal_view(module, dispatchers_steamid=dispatchers_steamid) else: frontend_view(module, dispatchers_steamid=dispatchers_steamid) def delete_modal_view(*args, **kwargs): module = args[0] dispatchers_steamid = kwargs.get('dispatchers_steamid', None) all_available_player_dicts = module.dom.data.get(module.get_module_identifier(), {}).get("elements", {}) all_selected_elements_count = 0 active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None) for map_identifier, player_dicts in all_available_player_dicts.items(): if active_dataset == map_identifier: for player_steamid, player_dict in player_dicts.items(): player_is_selected_by = player_dict.get("selected_by", []) if dispatchers_steamid in player_is_selected_by: all_selected_elements_count += 1 modal_confirm_delete = module.dom_management.get_delete_confirm_modal( module, count=all_selected_elements_count, target_module="module_players", dom_element_id="player_table_modal_action_delete_button", dom_action="delete_selected_dom_elements", dom_element_root=module.dom_element_root, dom_element_select_root=module.dom_element_select_root, confirmed="True" ) data_to_emit = modal_confirm_delete module.webserver.send_data_to_client_hook( module, payload=data_to_emit, data_type="modal_content", clients=[dispatchers_steamid], target_element={ "id": "manage_players_widget_modal", "type": "div", "selector": "body > main > div" } ) def kick_modal_view(*args, **kwargs): module = args[0] dispatchers_steamid = kwargs.get('dispatchers_steamid', None) current_view_steamid = ( module.dom.data .get("module_players", {}) .get("visibility", {}) .get(dispatchers_steamid, {}) .get("current_view_steamid", None) ) modal_confirm_kick = module.template_render_hook( module, template=module.templates.get_template('manage_players_widget/modal_confirm_kick.html'), confirmed=kwargs.get("confirmed", "False"), reason=( "no reason provided, " "try again in a few minutes and check if perhaps a bloodmoon is in progress ^^ " "or something ^^" ), steamid=current_view_steamid ) module.webserver.send_data_to_client_hook( module, payload=modal_confirm_kick, data_type="modal_content", clients=[dispatchers_steamid], target_element={ "id": "manage_players_widget_modal", "type": "div", "selector": "body > main > div" } ) def frontend_view(*args, **kwargs): module = args[0] dispatchers_steamid = kwargs.get('dispatchers_steamid', None) template_frontend = module.templates.get_template('manage_players_widget/view_frontend.html') template_table_rows = module.templates.get_template('manage_players_widget/table_row.html') template_table_header = module.templates.get_template('manage_players_widget/table_header.html') template_table_footer = module.templates.get_template('manage_players_widget/table_footer.html') control_info_link = module.templates.get_template('manage_players_widget/control_info_link.html') control_kick_link = module.templates.get_template('manage_players_widget/control_kick_link.html') template_options_toggle = module.templates.get_template('manage_players_widget/control_switch_view.html') template_options_toggle_view = module.templates.get_template( 'manage_players_widget/control_switch_options_view.html' ) active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None) all_available_player_dicts = module.dom.data.get(module.get_module_identifier(), {}).get("elements", {}) # Build table rows efficiently using list + join table_rows_list = [] all_selected_elements_count = 0 for map_identifier, player_dicts in all_available_player_dicts.items(): if active_dataset == map_identifier: # have the recently online players displayed first initially! ordered_player_dicts = OrderedDict( sorted( player_dicts.items(), key=lambda x: x[1].get('last_updated_servertime', ""), reverse=True ) ) for player_steamid, player_dict in ordered_player_dicts.items(): player_is_selected_by = player_dict.get("selected_by", []) player_entry_selected = False if dispatchers_steamid in player_is_selected_by: player_entry_selected = True all_selected_elements_count += 1 # Sanitize dataset for HTML ID (replace spaces with underscores, lowercase) player_dict_for_template = player_dict.copy() player_dict_for_template["dataset"] = module.dom_management.sanitize_for_html_id(player_dict.get("dataset", "")) player_dict_for_template["dataset_original"] = player_dict.get("dataset", "") control_select_link = module.dom_management.get_selection_dom_element( module, target_module="module_players", dom_element=player_dict_for_template, dom_element_select_root=["selected_by"], dom_element_entry_selected=player_entry_selected, dom_action_active="deselect_dom_element", dom_action_inactive="select_dom_element" ) table_rows_list.append(module.template_render_hook( module, template=template_table_rows, player=player_dict_for_template, css_class=get_player_table_row_css_class(player_dict), control_info_link=module.template_render_hook( module, template=control_info_link, player=player_dict_for_template ), control_kick_link=module.template_render_hook( module, template=control_kick_link, player=player_dict_for_template, ), control_select_link=control_select_link )) rendered_table_rows = ''.join(table_rows_list) current_view = module.get_current_view(dispatchers_steamid) options_toggle = module.template_render_hook( module, template=template_options_toggle, control_switch_options_view=module.template_render_hook( module, template=template_options_toggle_view, options_view_toggle=(current_view in ["frontend", "delete-modal"]), steamid=dispatchers_steamid ) ) dom_element_delete_button = module.dom_management.get_delete_button_dom_element( module, count=all_selected_elements_count, target_module="module_players", dom_element_id="player_table_widget_action_delete_button", dom_action="delete_selected_dom_elements", dom_element_root=module.dom_element_root, dom_element_select_root=module.dom_element_select_root ) data_to_emit = module.template_render_hook( module, template=template_frontend, options_toggle=options_toggle, table_header=module.template_render_hook( module, template=template_table_header ), table_rows=rendered_table_rows, table_footer=module.template_render_hook( module, template=template_table_footer, action_delete_button=dom_element_delete_button ) ) module.webserver.send_data_to_client_hook( module, payload=data_to_emit, data_type="widget_content", clients=[dispatchers_steamid], method="update", target_element={ "id": "manage_players_widget", "type": "table", "selector": "body > main > div" } ) def options_view(*args, **kwargs): module = args[0] dispatchers_steamid = kwargs.get('dispatchers_steamid', None) template_frontend = module.templates.get_template('manage_players_widget/view_options.html') template_options_toggle = module.templates.get_template('manage_players_widget/control_switch_view.html') template_options_toggle_view = module.templates.get_template('manage_players_widget/control_switch_options_view.html') options_toggle = module.template_render_hook( module, template=template_options_toggle, control_switch_options_view=module.template_render_hook( module, template=template_options_toggle_view, options_view_toggle=False, steamid=dispatchers_steamid ) ) data_to_emit = module.template_render_hook( module, template=template_frontend, options_toggle=options_toggle, widget_options=module.options ) module.webserver.send_data_to_client_hook( module, payload=data_to_emit, data_type="widget_content", clients=[dispatchers_steamid], method="update", target_element={ "id": "manage_players_widget", "type": "table", "selector": "body > main > div" } ) def show_info_view(*args, **kwargs): module = args[0] dispatchers_steamid = kwargs.get('dispatchers_steamid', None) template_frontend = module.templates.get_template('manage_players_widget/view_info.html') template_options_toggle = module.templates.get_template('manage_players_widget/control_switch_view.html') template_options_toggle_view = module.templates.get_template( 'manage_players_widget/control_switch_options_view.html' ) current_view_steamid = ( module.dom.data .get("module_players", {}) .get("visibility", {}) .get(dispatchers_steamid, {}) .get("current_view_steamid", "frontend") ) options_toggle = module.template_render_hook( module, template=template_options_toggle, control_switch_options_view=module.template_render_hook( module, template=template_options_toggle_view, options_view_toggle=False, steamid=dispatchers_steamid ) ) active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None) player_dict = ( module.dom.data .get("module_players", {}) .get("elements", {}) .get(active_dataset, {}) .get(current_view_steamid, None) ) data_to_emit = module.template_render_hook( module, template=template_frontend, options_toggle=options_toggle, player=player_dict ) module.webserver.send_data_to_client_hook( module, payload=data_to_emit, data_type="widget_content", clients=[dispatchers_steamid], method="update", target_element={ "id": "manage_players_widget", "type": "table", "selector": "body > main > div" } ) def table_rows(*args, ** kwargs): module = args[0] updated_values_dict = kwargs.get("updated_values_dict", None) method = kwargs.get("method", None) active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None) if method in ["upsert", "edit", "insert"]: for clientid in module.webserver.connected_clients.keys(): current_view = module.get_current_view(clientid) if current_view == "frontend": template_table_rows = module.templates.get_template('manage_players_widget/table_row.html') control_info_link = module.templates.get_template('manage_players_widget/control_info_link.html') control_kick_link = module.templates.get_template('manage_players_widget/control_kick_link.html') for player_steamid, player_dict in updated_values_dict.items(): try: # Sanitize dataset for HTML ID (replace spaces with underscores, lowercase) sanitized_dataset = module.dom_management.sanitize_for_html_id(player_dict["dataset"]) table_row_id = "player_table_row_{}_{}".format( sanitized_dataset, str(player_steamid) ) # Update player_dict with sanitized dataset for template player_dict = player_dict.copy() player_dict["dataset"] = sanitized_dataset player_dict["dataset_original"] = updated_values_dict[player_steamid].get("dataset", "") except KeyError: table_row_id = "manage_players_widget" player_entry_selected = False if clientid in player_dict.get("selected_by", []): player_entry_selected = True control_select_link = module.dom_management.get_selection_dom_element( module, target_module="module_players", dom_element_select_root=["selected_by"], dom_element=player_dict, dom_element_entry_selected=player_entry_selected, dom_action_inactive="select_dom_element", dom_action_active="deselect_dom_element" ) table_row = module.template_render_hook( module, template=template_table_rows, player=player_dict, css_class=get_player_table_row_css_class(player_dict), control_info_link=module.template_render_hook( module, template=control_info_link, player=player_dict ), control_kick_link=module.template_render_hook( module, template=control_kick_link, player=player_dict, ), control_select_link=control_select_link ) module.webserver.send_data_to_client_hook( module, payload=table_row, data_type="table_row", clients=[clientid], target_element={ "id": table_row_id, "type": "tr", "class": get_player_table_row_css_class(player_dict), "selector": "body > main > div > div#manage_players_widget > main > table > tbody" } ) elif method == "remove": player_origin = updated_values_dict[2] player_steamid = updated_values_dict[3] # Sanitize dataset for HTML ID (replace spaces with underscores, lowercase) sanitized_origin = module.dom_management.sanitize_for_html_id(player_origin) module.webserver.send_data_to_client_hook( module, data_type="remove_table_row", clients="all", target_element={ "id": "player_table_row_{}_{}".format( sanitized_origin, str(player_steamid) ) } ) update_delete_button_status(module, *args, **kwargs) def update_widget(*args, **kwargs): module = args[0] updated_values_dict = kwargs.get("updated_values_dict", None) active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None) method = kwargs.get("method", None) if method in ["update"]: original_player_dict = ( module.dom.data .get("module_players", {}) .get("elements", {}) .get(active_dataset, {}) .get(updated_values_dict.get("steamid", None), {}) ) player_clients_to_update = list(module.webserver.connected_clients.keys()) for clientid in player_clients_to_update: try: module_players = module.dom.data.get("module_players", {}) current_view = module.get_current_view(clientid) # Sanitize dataset for HTML ID (replace spaces with underscores, lowercase) sanitized_dataset = module.dom_management.sanitize_for_html_id(original_player_dict.get("dataset", "")) table_row_id = "player_table_row_{}_{}".format( sanitized_dataset, str(original_player_dict.get("steamid", None)) ) # Update dicts with sanitized dataset original_dataset = original_player_dict.get("dataset", "") updated_values_dict_sanitized = updated_values_dict.copy() updated_values_dict_sanitized["dataset"] = sanitized_dataset updated_values_dict_sanitized["dataset_original"] = original_dataset original_player_dict_sanitized = original_player_dict.copy() original_player_dict_sanitized["dataset"] = sanitized_dataset original_player_dict_sanitized["dataset_original"] = original_dataset if current_view == "frontend": module.webserver.send_data_to_client_hook( module, payload=updated_values_dict_sanitized, data_type="table_row_content", clients=[clientid], method="update", target_element={ "id": table_row_id, "parent_id": "manage_players_widget", "module": "players", "type": "tr", "selector": "body > main > div > div#manage_players_widget", "class": get_player_table_row_css_class(original_player_dict_sanitized), } ) elif current_view == "info": module.webserver.send_data_to_client_hook( module, payload=updated_values_dict_sanitized, data_type="table_row_content", clients=[clientid], method="update", target_element={ "id": table_row_id, "parent_id": "manage_players_widget", "module": "players", "type": "tr", "selector": "body > main > div > div#manage_players_widget", "class": get_player_table_row_css_class(updated_values_dict_sanitized), } ) except AttributeError as error: # probably dealing with a player_dict here, not the players dict pass except KeyError as error: pass def update_selection_status(*args, **kwargs): module = args[0] updated_values_dict = kwargs.get("updated_values_dict", None) # Sanitize dataset for HTML ID (replace spaces with underscores, lowercase) sanitized_dataset = module.dom_management.sanitize_for_html_id(updated_values_dict["dataset"]) module.dom_management.update_selection_status( *args, **kwargs, target_module=module, dom_action_active="deselect_dom_element", dom_action_inactive="select_dom_element", dom_element_id={ "id": "player_table_row_{}_{}_control_select_link".format( sanitized_dataset, updated_values_dict["owner"] ) } ) update_delete_button_status(module, *args, **kwargs) def update_delete_button_status(*args, **kwargs): module = args[0] module.dom_management.update_delete_button_status( *args, **kwargs, dom_element_root=module.dom_element_root, dom_element_select_root=module.dom_element_select_root, target_module=module, dom_action="delete_selected_dom_elements", dom_element_id={ "id": "player_table_widget_action_delete_button" } ) def update_actions_status(*args, **kwargs): """ we want to update the action status here not all actions can work all the time, some depend on a player being online for example""" module = args[0] control_info_link = module.templates.get_template('manage_players_widget/control_info_link.html') control_kick_link = module.templates.get_template('manage_players_widget/control_kick_link.html') player_dict = kwargs.get("updated_values_dict", None) # Sanitize dataset for HTML ID (replace spaces with underscores, lowercase) original_dataset = player_dict.get("dataset", "") player_dict_sanitized = player_dict.copy() player_dict_sanitized["dataset"] = module.dom_management.sanitize_for_html_id(original_dataset) player_dict_sanitized["dataset_original"] = original_dataset rendered_control_info_link = module.template_render_hook( module, template=control_info_link, player=player_dict_sanitized ) rendered_control_kick_link = module.template_render_hook( module, template=control_kick_link, player=player_dict_sanitized ) payload = rendered_control_info_link + rendered_control_kick_link module.webserver.send_data_to_client_hook( module, payload=payload, data_type="element_content", clients="all", method="update", target_element={ "id": "player_table_row_{}_{}_actions".format( player_dict_sanitized.get("dataset"), player_dict_sanitized.get("steamid") ) } ) widget_meta = { "description": "sends and updates a table of all currently known players", "main_widget": select_view, "handlers": { # the %abc% placeholders can contain any text at all, it has no effect on anything but code-readability # the third line could just as well read # "module_players/elements/%x%/%x%/%x%/selected_by": update_selection_status # and would still function the same as # "module_players/elements/%map_identifier%/%steamid%/%element_identifier%/selected_by": # update_selection_status "module_players/visibility/%steamid%/current_view": select_view, "module_players/elements/%map_identifier%/%steamid%": table_rows, "module_players/elements/%map_identifier%/%steamid%/pos": update_widget, "module_players/elements/%map_identifier%/%steamid%/selected_by": update_selection_status, "module_players/elements/%map_identifier%/%steamid%/is_initialized": update_actions_status # "module_players/elements/%map_identifier%/%steamid%/%element_identifier%/is_enabled": # update_enabled_flag, }, "enabled": True } loaded_modules_dict["module_" + module_name].register_widget(widget_name, widget_meta)