integrations.slack.events.home_tab.summary

integrations/slack/events/home_tab/summary.py

  1"""
  2integrations/slack/events/home_tab/summary.py
  3"""
  4
  5import logging
  6from typing import TYPE_CHECKING, Any, cast
  7
  8import libs.global_value as g
  9from integrations.slack.adapter import ServiceAdapter
 10from integrations.slack.events.handler_registry import register
 11from integrations.slack.events.home_tab import ui_parts
 12from libs.commands.graph import summary as graph_summary
 13from libs.commands.ranking import rating
 14from libs.commands.results import summary as results_summary
 15from libs.types import CommandType
 16from libs.utils import dictutil
 17from libs.utils.timekit import Delimiter, Format
 18from libs.utils.timekit import ExtendedDatetime as ExtDt
 19
 20if TYPE_CHECKING:
 21    from slack_bolt import App
 22    from slack_sdk.models.views import View
 23
 24    from integrations.protocols import MessageParserProtocol
 25
 26
 27def build_summary_menu(adapter: ServiceAdapter) -> "View":
 28    """サマリメニュー生成"""
 29    adapter.conf.tab_var["screen"] = "SummaryMenu"
 30    adapter.conf.tab_var["no"] = 0
 31    adapter.conf.tab_var["view"] = {"type": "home", "blocks": []}
 32    adapter.conf.tab_var.setdefault("sday", ExtDt().format(Format.YMD, Delimiter.HYPHEN))
 33    adapter.conf.tab_var.setdefault("eday", ExtDt().format(Format.YMD, Delimiter.HYPHEN))
 34    ui_parts.header(adapter, text="【成績サマリ】")
 35
 36    # 検索範囲設定
 37    date_dict = {x: ExtDt(hours=-g.cfg.setting.time_adjust).range(x).dict_format(Format.YMD, Delimiter.HYPHEN) for x in ["今月", "先月", "全部"]}
 38    ui_parts.divider(adapter)
 39    ui_parts.radio_buttons(
 40        adapter=adapter,
 41        id_suffix="search_range",
 42        title="検索範囲",
 43        flag={
 44            "今月": f"今月:{date_dict['今月']['start']}{date_dict['今月']['end']}",
 45            "先月": f"先月:{date_dict['先月']['start']}{date_dict['先月']['end']}",
 46            "全部": f"全部:{date_dict['全部']['start']}{date_dict['全部']['end']}",
 47            "指定": f"範囲指定:{adapter.conf.tab_var['sday']}{adapter.conf.tab_var['eday']}",
 48        },
 49    )
 50    ui_parts.button(adapter, text="検索範囲設定", action_id="modal-open-period")
 51
 52    # オプション
 53    ui_parts.divider(adapter)
 54    ui_parts.checkboxes(
 55        adapter=adapter,
 56        id_suffix="search_option",
 57        title="検索オプション",
 58        flag={
 59            "unregistered_replace": "ゲスト無効",
 60        },
 61        initial=["unregistered_replace"],
 62    )
 63    ui_parts.radio_buttons(
 64        adapter=adapter,
 65        id_suffix="output_option",
 66        title="出力オプション",
 67        flag={
 68            "normal": "通算ポイント",
 69            "score_comparisons": "通算ポイント比較",
 70            "point": "ポイント推移グラフ",
 71            "rank": "順位変動グラフ",
 72            "rating": "レーティング",
 73        },
 74    )
 75
 76    ui_parts.divider(adapter)
 77    ui_parts.button(adapter, text="集計", action_id="summary_aggregation", style="primary")
 78    ui_parts.button(adapter, text="戻る", action_id="actionId-back", style="danger")
 79
 80    return cast("View", adapter.conf.tab_var)
 81
 82
 83@register
 84def register_summary_handlers(app: "App", adapter: ServiceAdapter) -> None:
 85    """サマリメニュー"""
 86
 87    @app.action("summary_menu")
 88    def handle_menu_action(ack: Any, body: Any) -> None:
 89        """
 90        メニュー項目生成
 91
 92        Args:
 93            ack (Any): ack
 94            body (Any): イベント内容
 95
 96        """
 97        ack()
 98        logging.trace(body)  # type: ignore
 99
100        adapter.conf.tab_var["user_id"] = body["user"]["id"]
101        adapter.conf.tab_var["view_id"] = body["view"]["id"]
102        logging.debug("[summary_menu] %s", adapter.conf.tab_var)
103
104        build_summary_menu(adapter)
105        adapter.api.appclient.views_publish(
106            user_id=adapter.conf.tab_var["user_id"],
107            view=adapter.conf.tab_var["view"],
108        )
109
110    @app.action("summary_aggregation")
111    def handle_aggregation_action(ack: Any, body: Any) -> None:
112        """
113        成績サマリ集計
114
115        Args:
116            ack (Any): ack
117            body (Any): イベント内容
118
119        """
120        ack()
121        logging.trace(body)  # type: ignore
122
123        m = cast("MessageParserProtocol", adapter.parser())
124
125        m.parser(body)
126        add_argument, app_msg, update_flag = ui_parts.set_command_option(adapter, body)
127        m.data.text = f"dummy {' '.join(add_argument)}"  # 引数の位置を調整
128        g.params = dictutil.placeholder(g.cfg.results, m)
129        g.params.update_from_dict(update_flag)
130
131        adapter.api.appclient.views_update(
132            view_id=adapter.conf.tab_var["view_id"],
133            view=ui_parts.plain_text(f"{chr(10).join(app_msg)}"),
134        )
135
136        app_msg.pop()
137        app_msg.append("集計完了")
138
139        match adapter.conf.tab_var.get("operation"):
140            case "point":
141                m.status.command_type = CommandType.GRAPH
142                graph_summary.point_plot(m)
143                adapter.api.post(m)
144            case "rank":
145                m.status.command_type = CommandType.GRAPH
146                graph_summary.rank_plot(m)
147                adapter.api.post(m)
148            case "rating":
149                m.status.command_type = CommandType.RATING
150                g.params.command = "ranking"
151                rating.aggregation(m)
152                adapter.api.post(m)
153            case _:
154                if g.params.score_comparisons:
155                    m.status.command_type = CommandType.COMPARISON
156                    results_summary.difference(m)
157                else:
158                    m.status.command_type = CommandType.RESULTS
159                    results_summary.aggregation(m)
160                adapter.api.post(m)
161
162        ui_parts.update_view(adapter, m, app_msg)
163
164    @app.view("SummaryMenu_ModalPeriodSelection")
165    def handle_view_submission(ack: Any, view: Any) -> None:
166        """
167        view更新
168
169        Args:
170            ack (Any): ack
171            view (Any): 描写内容
172
173        """
174        ack()
175
176        for i in view["state"]["values"].keys():
177            if "aid-sday" in view["state"]["values"][i]:
178                adapter.conf.tab_var["sday"] = view["state"]["values"][i]["aid-sday"]["selected_date"]
179            if "aid-eday" in view["state"]["values"][i]:
180                adapter.conf.tab_var["eday"] = view["state"]["values"][i]["aid-eday"]["selected_date"]
181
182        logging.debug("[global var] %s", adapter.conf.tab_var)
183
184        adapter.api.appclient.views_update(
185            view_id=adapter.conf.tab_var["view_id"],
186            view=build_summary_menu(adapter),
187        )
def build_summary_menu( adapter: integrations.slack.adapter.ServiceAdapter) -> slack_sdk.models.views.View:
28def build_summary_menu(adapter: ServiceAdapter) -> "View":
29    """サマリメニュー生成"""
30    adapter.conf.tab_var["screen"] = "SummaryMenu"
31    adapter.conf.tab_var["no"] = 0
32    adapter.conf.tab_var["view"] = {"type": "home", "blocks": []}
33    adapter.conf.tab_var.setdefault("sday", ExtDt().format(Format.YMD, Delimiter.HYPHEN))
34    adapter.conf.tab_var.setdefault("eday", ExtDt().format(Format.YMD, Delimiter.HYPHEN))
35    ui_parts.header(adapter, text="【成績サマリ】")
36
37    # 検索範囲設定
38    date_dict = {x: ExtDt(hours=-g.cfg.setting.time_adjust).range(x).dict_format(Format.YMD, Delimiter.HYPHEN) for x in ["今月", "先月", "全部"]}
39    ui_parts.divider(adapter)
40    ui_parts.radio_buttons(
41        adapter=adapter,
42        id_suffix="search_range",
43        title="検索範囲",
44        flag={
45            "今月": f"今月:{date_dict['今月']['start']}{date_dict['今月']['end']}",
46            "先月": f"先月:{date_dict['先月']['start']}{date_dict['先月']['end']}",
47            "全部": f"全部:{date_dict['全部']['start']}{date_dict['全部']['end']}",
48            "指定": f"範囲指定:{adapter.conf.tab_var['sday']}{adapter.conf.tab_var['eday']}",
49        },
50    )
51    ui_parts.button(adapter, text="検索範囲設定", action_id="modal-open-period")
52
53    # オプション
54    ui_parts.divider(adapter)
55    ui_parts.checkboxes(
56        adapter=adapter,
57        id_suffix="search_option",
58        title="検索オプション",
59        flag={
60            "unregistered_replace": "ゲスト無効",
61        },
62        initial=["unregistered_replace"],
63    )
64    ui_parts.radio_buttons(
65        adapter=adapter,
66        id_suffix="output_option",
67        title="出力オプション",
68        flag={
69            "normal": "通算ポイント",
70            "score_comparisons": "通算ポイント比較",
71            "point": "ポイント推移グラフ",
72            "rank": "順位変動グラフ",
73            "rating": "レーティング",
74        },
75    )
76
77    ui_parts.divider(adapter)
78    ui_parts.button(adapter, text="集計", action_id="summary_aggregation", style="primary")
79    ui_parts.button(adapter, text="戻る", action_id="actionId-back", style="danger")
80
81    return cast("View", adapter.conf.tab_var)

サマリメニュー生成

register_summary_handlers = None

サマリメニュー