integrations.slack.events.home_tab.ui_parts

integrations/slack/events/home_tab/ui_parts.py

  1"""
  2integrations/slack/events/home_tab/ui_parts.py
  3"""
  4
  5import logging
  6from typing import TYPE_CHECKING, Any, Optional
  7
  8import libs.global_value as g
  9from libs.functions.lookup import read_memberslist
 10
 11if TYPE_CHECKING:
 12    from integrations.protocols import MessageParserProtocol
 13    from integrations.slack.adapter import ServiceAdapter
 14
 15
 16def plain_text(msg: str) -> dict[str, Any]:
 17    """
 18    プレーンテキストの埋め込み
 19
 20    Args:
 21        msg (str): テキスト
 22
 23    Returns:
 24        dict[str, Any]: ブロック要素
 25
 26    """
 27    view: dict[str, Any] = {"type": "home", "blocks": []}
 28    view["blocks"].append({"type": "section", "text": {}})
 29    view["blocks"][0]["text"] = {"type": "mrkdwn", "text": msg}
 30
 31    return view
 32
 33
 34def divider(adapter: "ServiceAdapter") -> None:
 35    """
 36    境界線を引く
 37
 38    Args:
 39        adapter (ServiceAdapter): アダプタインターフェース
 40
 41    """
 42    adapter.conf.tab_var["view"]["blocks"].append(
 43        {
 44            "type": "divider",
 45        }
 46    )
 47    adapter.conf.tab_var["no"] += 1
 48
 49
 50def header(adapter: "ServiceAdapter", text: str = "dummy") -> None:
 51    """
 52    ヘッダ生成
 53
 54    Args:
 55        adapter (ServiceAdapter): アダプタインターフェース
 56        text (str, optional): ヘッダテキスト. Defaults to "dummy".
 57
 58    """
 59    adapter.conf.tab_var["view"]["blocks"].append({"type": "header", "text": {}})
 60    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["text"] = {"type": "plain_text", "text": text}
 61    adapter.conf.tab_var["no"] += 1
 62
 63
 64def button(adapter: "ServiceAdapter", text: str, action_id: str, style: str | bool = False) -> None:
 65    """
 66    ボタン配置
 67
 68    Args:
 69        adapter (ServiceAdapter): アダプタインターフェース
 70        text (str, optional): 表示テキスト
 71        action_id (str): action_id
 72        style (str | bool, optional): 表示スタイル. Defaults to False.
 73
 74    """
 75    adapter.conf.tab_var["view"]["blocks"].append({"type": "actions", "elements": [{}]})
 76    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["elements"][0] = {
 77        "type": "button",
 78        "text": {},
 79        "action_id": action_id,
 80    }
 81    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["elements"][0]["text"] = {
 82        "type": "plain_text",
 83        "text": text,
 84    }
 85    if style:
 86        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["elements"][0].update({"style": style})
 87
 88    adapter.conf.tab_var["no"] += 1
 89
 90
 91def radio_buttons(adapter: "ServiceAdapter", id_suffix: str, title: str, flag: dict[str, Any]) -> None:
 92    """
 93    オプション選択メニュー
 94
 95    Args:
 96        adapter (ServiceAdapter): アダプタインターフェース
 97        id_suffix (str): block_id, action_id
 98        title (str): 表示タイトル
 99        flag (dict[str, Any]): 表示する選択項目
100
101    """
102    adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": f"bid-{id_suffix}", "element": {}})
103    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"] = {"type": "plain_text", "text": title}
104    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["type"] = "radio_buttons"
105    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["action_id"] = f"aid-{id_suffix}"
106    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["initial_option"] = {  # 先頭の選択肢はチェック済みにする
107        "text": {"type": "plain_text", "text": flag[next(iter(flag))]},
108        "value": next(iter(flag)),
109    }
110    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"] = []
111    for k, v in flag.items():
112        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append({"text": {"type": "plain_text", "text": v}, "value": k})
113    adapter.conf.tab_var["no"] += 1
114
115
116def checkboxes(
117    adapter: "ServiceAdapter",
118    id_suffix: str,
119    title: str,
120    flag: Optional[dict[str, Any]] = None,
121    initial: Optional[list[str]] = None,
122) -> None:
123    """
124    チェックボックス選択メニュー
125
126    Args:
127        adapter (ServiceAdapter): アダプタインターフェース
128        id_suffix (str): block_id, action_id
129        title (str): 表示タイトル
130        flag (Optional[dict[str, Any]): 表示する選択項目. Defaults to None.
131        initial (Optional[list[str]]): チェック済み項目. Defaults to None.
132
133    """
134    if flag is None:
135        flag = {}
136
137    adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": f"bid-{id_suffix}", "element": {}})
138    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"] = {"type": "plain_text", "text": title}
139    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["type"] = "checkboxes"
140    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["action_id"] = f"aid-{id_suffix}"
141    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"] = []
142    if initial:
143        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["initial_options"] = []
144    else:
145        initial = []  # None -> list
146
147    for k, v in flag.items():
148        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append({"text": {"type": "plain_text", "text": v}, "value": k})
149        if k in initial:
150            adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["initial_options"].append(
151                {"text": {"type": "plain_text", "text": v}, "value": k}
152            )
153
154    adapter.conf.tab_var["no"] += 1
155
156
157def user_select_pulldown(
158    adapter: "ServiceAdapter",
159    text: str = "dummy",
160    add_list: Optional[list[str]] = None,
161) -> None:
162    """
163    プレイヤー選択プルダウンメニュー
164
165    Args:
166        adapter (ServiceAdapter): アダプタインターフェース
167        text (str, optional): 表示テキスト. Defaults to "dummy".
168        add_list (Optional[list[str]]): プレイヤーリスト. Defaults to None.
169
170    """
171    read_memberslist()
172
173    adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": "bid-user_select", "element": {}})
174    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["type"] = "static_select"
175    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["action_id"] = "player"
176    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["placeholder"] = {
177        "type": "plain_text",
178        "text": "Select an item",
179    }
180    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"] = []
181
182    if add_list:
183        for val in add_list:
184            adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append(
185                {"text": {"type": "plain_text", "text": val}, "value": val}
186            )
187
188    for name in g.cfg.member.lists:
189        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append(
190            {"text": {"type": "plain_text", "text": name}, "value": name}
191        )
192
193    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"] = {"type": "plain_text", "text": text}
194
195    adapter.conf.tab_var["no"] += 1
196
197
198def multi_select_pulldown(
199    adapter: "ServiceAdapter",
200    text: str = "dummy",
201    add_list: Optional[list[str]] = None,
202) -> None:
203    """
204    複数プレイヤー選択プルダウンメニュー
205
206    Args:
207        adapter (ServiceAdapter): アダプタインターフェース
208        text (str, optional): 表示テキスト. Defaults to "dummy".
209        add_list (Optional[list[str]]): プレイヤーリスト. Defaults to None.
210
211    """
212    read_memberslist()
213
214    adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": "bid-multi_select", "element": {}})
215    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["type"] = "multi_static_select"
216    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["action_id"] = "player"
217    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["placeholder"] = {
218        "type": "plain_text",
219        "text": "Select an item",
220    }
221    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"] = []
222
223    if add_list:
224        for val in add_list:
225            adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append(
226                {"text": {"type": "plain_text", "text": val}, "value": val}
227            )
228
229    for name in g.cfg.member.lists:
230        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append(
231            {"text": {"type": "plain_text", "text": name}, "value": name}
232        )
233
234    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"] = {"type": "plain_text", "text": text}
235
236    adapter.conf.tab_var["no"] += 1
237
238
239def input_ranked(adapter: "ServiceAdapter", block_id: str | bool = False) -> None:
240    """
241    ランキング上限入力テキストボックス
242
243    Args:
244        adapter (ServiceAdapter): アダプタインターフェース
245        block_id (str | bool, optional): block_id. Defaults to False.
246
247    """
248    if block_id:
249        adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": block_id, "element": {}, "label": {}})
250    else:
251        adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "element": {}, "label": {}})
252
253    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"type": "number_input"})
254    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"is_decimal_allowed": True})
255    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"initial_value": str(g.cfg.ranking.ranked)})
256    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"min_value": "1"})
257    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"action_id": "aid-ranked"})
258    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"].update({"type": "plain_text", "text": "出力順位上限"})
259
260    adapter.conf.tab_var["no"] += 1
261
262
263def modalperiod_selection(adapter: "ServiceAdapter") -> dict[str, Any]:
264    """
265    日付選択
266
267    Args:
268        adapter (ServiceAdapter): アダプタインターフェース
269
270    Returns:
271        dict[str, Any]: ブロック要素
272
273    """
274    view: dict[str, Any] = {"type": "modal", "callback_id": f"{adapter.conf.tab_var['screen']}_ModalPeriodSelection"}
275    view["title"] = {"type": "plain_text", "text": "検索範囲指定"}
276    view["submit"] = {"type": "plain_text", "text": "決定"}
277    view["close"] = {"type": "plain_text", "text": "取消"}
278
279    view["blocks"] = []
280    view["blocks"].append({"type": "input", "element": {}, "label": {}})
281    view["blocks"][0]["element"].update({"type": "datepicker"})
282    view["blocks"][0]["element"].update({"initial_date": adapter.conf.tab_var["sday"]})
283    view["blocks"][0]["element"].update({"placeholder": {"type": "plain_text", "text": "Select a date"}})
284    view["blocks"][0]["element"].update({"action_id": "aid-sday"})
285    view["blocks"][0]["label"].update({"type": "plain_text", "text": "開始日"})
286    view["blocks"].append({"type": "input", "element": {}, "label": {}})
287    view["blocks"][1]["element"].update({"type": "datepicker"})
288    view["blocks"][1]["element"].update({"initial_date": adapter.conf.tab_var["eday"]})
289    view["blocks"][1]["element"].update({"placeholder": {"type": "plain_text", "text": "Select a date"}})
290    view["blocks"][1]["element"].update({"action_id": "aid-eday"})
291    view["blocks"][1]["label"].update({"type": "plain_text", "text": "終了日"})
292
293    return view
294
295
296def set_command_option(
297    adapter: "ServiceAdapter",
298    body: dict[str, Any],
299) -> tuple[list[str], list[str], dict[str, Any]]:
300    """
301    選択オプションの内容のフラグをセット
302
303    Args:
304        adapter (ServiceAdapter): アダプタインターフェース
305        body (dict[str, Any]): イベント内容
306
307    Returns:
308        tuple[list[str], list[str], dict[str, Any]]:
309        - list[str]: コマンドに追加する文字列
310        - list[str]: viewに表示するメッセージ
311        - dict[str, Any]: 変更されるフラグ
312
313    """
314    update_flag: dict[str, Any] = {}
315
316    # 検索設定
317    argument: list[str] = []
318    search_options = body["view"]["state"]["values"]
319    logging.debug("search options: %s", search_options)
320
321    app_msg: list[str] = []
322    adapter.conf.tab_var.update(operation=None)
323
324    if "bid-user_select" in search_options:
325        user_select = search_options["bid-user_select"]["player"]["selected_option"]
326        if user_select is not None:
327            if "value" in user_select:
328                player = str(user_select["value"])
329                app_msg.append(f"対象プレイヤー:{player}")
330                argument.append(player)
331
332    if "bid-multi_select" in search_options:
333        user_list = search_options["bid-multi_select"]["player"]["selected_options"]
334        for _, val in enumerate(user_list):
335            argument.append(str(val["value"]))
336
337    if "bid-search_range" in search_options:
338        match str(search_options["bid-search_range"]["aid-search_range"]["selected_option"]["value"]):
339            case "指定":
340                app_msg.append(f"集計範囲:{adapter.conf.tab_var['sday']}{adapter.conf.tab_var['eday']}")
341                argument.extend([str(adapter.conf.tab_var["sday"]), str(adapter.conf.tab_var["eday"])])
342            case "全部":
343                app_msg.append("集計範囲:全部")
344                argument.append("全部")
345            case _ as select_item:
346                app_msg.append(f"集計範囲:{select_item}")
347                argument.append(select_item)
348
349    for id_suffix in ("search_option", "display_option", "output_option"):
350        if f"bid-{id_suffix}" in search_options:
351            match search_options[f"bid-{id_suffix}"][f"aid-{id_suffix}"].get("type"):
352                case "checkboxes":
353                    selected_options = search_options[f"bid-{id_suffix}"][f"aid-{id_suffix}"].get("selected_options")
354                case "radio_buttons":
355                    selected_options = [search_options[f"bid-{id_suffix}"][f"aid-{id_suffix}"].get("selected_option")]
356                case _:
357                    continue
358
359            for _, val in enumerate(selected_options):
360                match val["value"]:
361                    case "unregistered_replace":
362                        update_flag.update(unregistered_replace=False)
363                    case "versus_matrix":
364                        update_flag.update(versus_matrix=True)
365                    case "game_results":
366                        update_flag.update(game_results=True)
367                    case "verbose":
368                        update_flag.update(game_results=True)
369                        update_flag.update(verbose=True)
370                    case "score_comparisons":
371                        update_flag.update(score_comparisons=True)
372                        adapter.conf.tab_var.update(operation=None)
373                    case _ as option:
374                        adapter.conf.tab_var.update(operation=option)
375
376    app_msg.append("集計中…")
377    return (argument, app_msg, update_flag)
378
379
380def update_view(adapter: "ServiceAdapter", m: "MessageParserProtocol", msg: list[str]) -> None:
381    """
382    viewを更新する
383
384    Args:
385        adapter (ServiceAdapter): アダプター
386        m (MessageParserProtocol): メッセージデータ
387        msg (list[str]): 表示テキスト
388
389    """
390    text = ""
391    if m.post.headline:
392        header_data, header_option = m.post.headline
393        if isinstance(header_data, str):
394            text = f"\n{header_option.title}\n{header_data}"
395
396    adapter.api.appclient.views_update(
397        view_id=adapter.conf.tab_var["view_id"],
398        view=plain_text(f"{chr(10).join(msg)}\n\n{text}".strip()),
399    )
def plain_text(msg: str) -> dict[str, typing.Any]:
17def plain_text(msg: str) -> dict[str, Any]:
18    """
19    プレーンテキストの埋め込み
20
21    Args:
22        msg (str): テキスト
23
24    Returns:
25        dict[str, Any]: ブロック要素
26
27    """
28    view: dict[str, Any] = {"type": "home", "blocks": []}
29    view["blocks"].append({"type": "section", "text": {}})
30    view["blocks"][0]["text"] = {"type": "mrkdwn", "text": msg}
31
32    return view

プレーンテキストの埋め込み

Arguments:
  • msg (str): テキスト
Returns:

dict[str, Any]: ブロック要素

def divider(adapter: integrations.slack.adapter.ServiceAdapter) -> None:
35def divider(adapter: "ServiceAdapter") -> None:
36    """
37    境界線を引く
38
39    Args:
40        adapter (ServiceAdapter): アダプタインターフェース
41
42    """
43    adapter.conf.tab_var["view"]["blocks"].append(
44        {
45            "type": "divider",
46        }
47    )
48    adapter.conf.tab_var["no"] += 1

境界線を引く

Arguments:
  • adapter (ServiceAdapter): アダプタインターフェース
def button( adapter: integrations.slack.adapter.ServiceAdapter, text: str, action_id: str, style: str | bool = False) -> None:
65def button(adapter: "ServiceAdapter", text: str, action_id: str, style: str | bool = False) -> None:
66    """
67    ボタン配置
68
69    Args:
70        adapter (ServiceAdapter): アダプタインターフェース
71        text (str, optional): 表示テキスト
72        action_id (str): action_id
73        style (str | bool, optional): 表示スタイル. Defaults to False.
74
75    """
76    adapter.conf.tab_var["view"]["blocks"].append({"type": "actions", "elements": [{}]})
77    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["elements"][0] = {
78        "type": "button",
79        "text": {},
80        "action_id": action_id,
81    }
82    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["elements"][0]["text"] = {
83        "type": "plain_text",
84        "text": text,
85    }
86    if style:
87        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["elements"][0].update({"style": style})
88
89    adapter.conf.tab_var["no"] += 1

ボタン配置

Arguments:
  • adapter (ServiceAdapter): アダプタインターフェース
  • text (str, optional): 表示テキスト
  • action_id (str): action_id
  • style (str | bool, optional): 表示スタイル. Defaults to False.
def radio_buttons( adapter: integrations.slack.adapter.ServiceAdapter, id_suffix: str, title: str, flag: dict[str, typing.Any]) -> None:
 92def radio_buttons(adapter: "ServiceAdapter", id_suffix: str, title: str, flag: dict[str, Any]) -> None:
 93    """
 94    オプション選択メニュー
 95
 96    Args:
 97        adapter (ServiceAdapter): アダプタインターフェース
 98        id_suffix (str): block_id, action_id
 99        title (str): 表示タイトル
100        flag (dict[str, Any]): 表示する選択項目
101
102    """
103    adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": f"bid-{id_suffix}", "element": {}})
104    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"] = {"type": "plain_text", "text": title}
105    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["type"] = "radio_buttons"
106    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["action_id"] = f"aid-{id_suffix}"
107    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["initial_option"] = {  # 先頭の選択肢はチェック済みにする
108        "text": {"type": "plain_text", "text": flag[next(iter(flag))]},
109        "value": next(iter(flag)),
110    }
111    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"] = []
112    for k, v in flag.items():
113        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append({"text": {"type": "plain_text", "text": v}, "value": k})
114    adapter.conf.tab_var["no"] += 1

オプション選択メニュー

Arguments:
  • adapter (ServiceAdapter): アダプタインターフェース
  • id_suffix (str): block_id, action_id
  • title (str): 表示タイトル
  • flag (dict[str, Any]): 表示する選択項目
def checkboxes( adapter: integrations.slack.adapter.ServiceAdapter, id_suffix: str, title: str, flag: dict[str, Any] | None = None, initial: list[str] | None = None) -> None:
117def checkboxes(
118    adapter: "ServiceAdapter",
119    id_suffix: str,
120    title: str,
121    flag: Optional[dict[str, Any]] = None,
122    initial: Optional[list[str]] = None,
123) -> None:
124    """
125    チェックボックス選択メニュー
126
127    Args:
128        adapter (ServiceAdapter): アダプタインターフェース
129        id_suffix (str): block_id, action_id
130        title (str): 表示タイトル
131        flag (Optional[dict[str, Any]): 表示する選択項目. Defaults to None.
132        initial (Optional[list[str]]): チェック済み項目. Defaults to None.
133
134    """
135    if flag is None:
136        flag = {}
137
138    adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": f"bid-{id_suffix}", "element": {}})
139    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"] = {"type": "plain_text", "text": title}
140    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["type"] = "checkboxes"
141    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["action_id"] = f"aid-{id_suffix}"
142    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"] = []
143    if initial:
144        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["initial_options"] = []
145    else:
146        initial = []  # None -> list
147
148    for k, v in flag.items():
149        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append({"text": {"type": "plain_text", "text": v}, "value": k})
150        if k in initial:
151            adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["initial_options"].append(
152                {"text": {"type": "plain_text", "text": v}, "value": k}
153            )
154
155    adapter.conf.tab_var["no"] += 1

チェックボックス選択メニュー

Arguments:
  • adapter (ServiceAdapter): アダプタインターフェース
  • id_suffix (str): block_id, action_id
  • title (str): 表示タイトル
  • flag (Optional[dict[str, Any]): 表示する選択項目. Defaults to None.
  • initial (Optional[list[str]]): チェック済み項目. Defaults to None.
def user_select_pulldown( adapter: integrations.slack.adapter.ServiceAdapter, text: str = 'dummy', add_list: list[str] | None = None) -> None:
158def user_select_pulldown(
159    adapter: "ServiceAdapter",
160    text: str = "dummy",
161    add_list: Optional[list[str]] = None,
162) -> None:
163    """
164    プレイヤー選択プルダウンメニュー
165
166    Args:
167        adapter (ServiceAdapter): アダプタインターフェース
168        text (str, optional): 表示テキスト. Defaults to "dummy".
169        add_list (Optional[list[str]]): プレイヤーリスト. Defaults to None.
170
171    """
172    read_memberslist()
173
174    adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": "bid-user_select", "element": {}})
175    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["type"] = "static_select"
176    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["action_id"] = "player"
177    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["placeholder"] = {
178        "type": "plain_text",
179        "text": "Select an item",
180    }
181    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"] = []
182
183    if add_list:
184        for val in add_list:
185            adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append(
186                {"text": {"type": "plain_text", "text": val}, "value": val}
187            )
188
189    for name in g.cfg.member.lists:
190        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append(
191            {"text": {"type": "plain_text", "text": name}, "value": name}
192        )
193
194    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"] = {"type": "plain_text", "text": text}
195
196    adapter.conf.tab_var["no"] += 1

プレイヤー選択プルダウンメニュー

Arguments:
  • adapter (ServiceAdapter): アダプタインターフェース
  • text (str, optional): 表示テキスト. Defaults to "dummy".
  • add_list (Optional[list[str]]): プレイヤーリスト. Defaults to None.
def multi_select_pulldown( adapter: integrations.slack.adapter.ServiceAdapter, text: str = 'dummy', add_list: list[str] | None = None) -> None:
199def multi_select_pulldown(
200    adapter: "ServiceAdapter",
201    text: str = "dummy",
202    add_list: Optional[list[str]] = None,
203) -> None:
204    """
205    複数プレイヤー選択プルダウンメニュー
206
207    Args:
208        adapter (ServiceAdapter): アダプタインターフェース
209        text (str, optional): 表示テキスト. Defaults to "dummy".
210        add_list (Optional[list[str]]): プレイヤーリスト. Defaults to None.
211
212    """
213    read_memberslist()
214
215    adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": "bid-multi_select", "element": {}})
216    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["type"] = "multi_static_select"
217    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["action_id"] = "player"
218    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["placeholder"] = {
219        "type": "plain_text",
220        "text": "Select an item",
221    }
222    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"] = []
223
224    if add_list:
225        for val in add_list:
226            adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append(
227                {"text": {"type": "plain_text", "text": val}, "value": val}
228            )
229
230    for name in g.cfg.member.lists:
231        adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"]["options"].append(
232            {"text": {"type": "plain_text", "text": name}, "value": name}
233        )
234
235    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"] = {"type": "plain_text", "text": text}
236
237    adapter.conf.tab_var["no"] += 1

複数プレイヤー選択プルダウンメニュー

Arguments:
  • adapter (ServiceAdapter): アダプタインターフェース
  • text (str, optional): 表示テキスト. Defaults to "dummy".
  • add_list (Optional[list[str]]): プレイヤーリスト. Defaults to None.
def input_ranked( adapter: integrations.slack.adapter.ServiceAdapter, block_id: str | bool = False) -> None:
240def input_ranked(adapter: "ServiceAdapter", block_id: str | bool = False) -> None:
241    """
242    ランキング上限入力テキストボックス
243
244    Args:
245        adapter (ServiceAdapter): アダプタインターフェース
246        block_id (str | bool, optional): block_id. Defaults to False.
247
248    """
249    if block_id:
250        adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "block_id": block_id, "element": {}, "label": {}})
251    else:
252        adapter.conf.tab_var["view"]["blocks"].append({"type": "input", "element": {}, "label": {}})
253
254    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"type": "number_input"})
255    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"is_decimal_allowed": True})
256    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"initial_value": str(g.cfg.ranking.ranked)})
257    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"min_value": "1"})
258    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["element"].update({"action_id": "aid-ranked"})
259    adapter.conf.tab_var["view"]["blocks"][adapter.conf.tab_var["no"]]["label"].update({"type": "plain_text", "text": "出力順位上限"})
260
261    adapter.conf.tab_var["no"] += 1

ランキング上限入力テキストボックス

Arguments:
  • adapter (ServiceAdapter): アダプタインターフェース
  • block_id (str | bool, optional): block_id. Defaults to False.
def modalperiod_selection( adapter: integrations.slack.adapter.ServiceAdapter) -> dict[str, typing.Any]:
264def modalperiod_selection(adapter: "ServiceAdapter") -> dict[str, Any]:
265    """
266    日付選択
267
268    Args:
269        adapter (ServiceAdapter): アダプタインターフェース
270
271    Returns:
272        dict[str, Any]: ブロック要素
273
274    """
275    view: dict[str, Any] = {"type": "modal", "callback_id": f"{adapter.conf.tab_var['screen']}_ModalPeriodSelection"}
276    view["title"] = {"type": "plain_text", "text": "検索範囲指定"}
277    view["submit"] = {"type": "plain_text", "text": "決定"}
278    view["close"] = {"type": "plain_text", "text": "取消"}
279
280    view["blocks"] = []
281    view["blocks"].append({"type": "input", "element": {}, "label": {}})
282    view["blocks"][0]["element"].update({"type": "datepicker"})
283    view["blocks"][0]["element"].update({"initial_date": adapter.conf.tab_var["sday"]})
284    view["blocks"][0]["element"].update({"placeholder": {"type": "plain_text", "text": "Select a date"}})
285    view["blocks"][0]["element"].update({"action_id": "aid-sday"})
286    view["blocks"][0]["label"].update({"type": "plain_text", "text": "開始日"})
287    view["blocks"].append({"type": "input", "element": {}, "label": {}})
288    view["blocks"][1]["element"].update({"type": "datepicker"})
289    view["blocks"][1]["element"].update({"initial_date": adapter.conf.tab_var["eday"]})
290    view["blocks"][1]["element"].update({"placeholder": {"type": "plain_text", "text": "Select a date"}})
291    view["blocks"][1]["element"].update({"action_id": "aid-eday"})
292    view["blocks"][1]["label"].update({"type": "plain_text", "text": "終了日"})
293
294    return view

日付選択

Arguments:
  • adapter (ServiceAdapter): アダプタインターフェース
Returns:

dict[str, Any]: ブロック要素

def set_command_option( adapter: integrations.slack.adapter.ServiceAdapter, body: dict[str, typing.Any]) -> tuple[list[str], list[str], dict[str, typing.Any]]:
297def set_command_option(
298    adapter: "ServiceAdapter",
299    body: dict[str, Any],
300) -> tuple[list[str], list[str], dict[str, Any]]:
301    """
302    選択オプションの内容のフラグをセット
303
304    Args:
305        adapter (ServiceAdapter): アダプタインターフェース
306        body (dict[str, Any]): イベント内容
307
308    Returns:
309        tuple[list[str], list[str], dict[str, Any]]:
310        - list[str]: コマンドに追加する文字列
311        - list[str]: viewに表示するメッセージ
312        - dict[str, Any]: 変更されるフラグ
313
314    """
315    update_flag: dict[str, Any] = {}
316
317    # 検索設定
318    argument: list[str] = []
319    search_options = body["view"]["state"]["values"]
320    logging.debug("search options: %s", search_options)
321
322    app_msg: list[str] = []
323    adapter.conf.tab_var.update(operation=None)
324
325    if "bid-user_select" in search_options:
326        user_select = search_options["bid-user_select"]["player"]["selected_option"]
327        if user_select is not None:
328            if "value" in user_select:
329                player = str(user_select["value"])
330                app_msg.append(f"対象プレイヤー:{player}")
331                argument.append(player)
332
333    if "bid-multi_select" in search_options:
334        user_list = search_options["bid-multi_select"]["player"]["selected_options"]
335        for _, val in enumerate(user_list):
336            argument.append(str(val["value"]))
337
338    if "bid-search_range" in search_options:
339        match str(search_options["bid-search_range"]["aid-search_range"]["selected_option"]["value"]):
340            case "指定":
341                app_msg.append(f"集計範囲:{adapter.conf.tab_var['sday']}{adapter.conf.tab_var['eday']}")
342                argument.extend([str(adapter.conf.tab_var["sday"]), str(adapter.conf.tab_var["eday"])])
343            case "全部":
344                app_msg.append("集計範囲:全部")
345                argument.append("全部")
346            case _ as select_item:
347                app_msg.append(f"集計範囲:{select_item}")
348                argument.append(select_item)
349
350    for id_suffix in ("search_option", "display_option", "output_option"):
351        if f"bid-{id_suffix}" in search_options:
352            match search_options[f"bid-{id_suffix}"][f"aid-{id_suffix}"].get("type"):
353                case "checkboxes":
354                    selected_options = search_options[f"bid-{id_suffix}"][f"aid-{id_suffix}"].get("selected_options")
355                case "radio_buttons":
356                    selected_options = [search_options[f"bid-{id_suffix}"][f"aid-{id_suffix}"].get("selected_option")]
357                case _:
358                    continue
359
360            for _, val in enumerate(selected_options):
361                match val["value"]:
362                    case "unregistered_replace":
363                        update_flag.update(unregistered_replace=False)
364                    case "versus_matrix":
365                        update_flag.update(versus_matrix=True)
366                    case "game_results":
367                        update_flag.update(game_results=True)
368                    case "verbose":
369                        update_flag.update(game_results=True)
370                        update_flag.update(verbose=True)
371                    case "score_comparisons":
372                        update_flag.update(score_comparisons=True)
373                        adapter.conf.tab_var.update(operation=None)
374                    case _ as option:
375                        adapter.conf.tab_var.update(operation=option)
376
377    app_msg.append("集計中…")
378    return (argument, app_msg, update_flag)

選択オプションの内容のフラグをセット

Arguments:
  • adapter (ServiceAdapter): アダプタインターフェース
  • body (dict[str, Any]): イベント内容
Returns:

tuple[list[str], list[str], dict[str, Any]]:

  • list[str]: コマンドに追加する文字列
  • list[str]: viewに表示するメッセージ
  • dict[str, Any]: 変更されるフラグ
def update_view( adapter: integrations.slack.adapter.ServiceAdapter, m: integrations.protocols.MessageParserProtocol, msg: list[str]) -> None:
381def update_view(adapter: "ServiceAdapter", m: "MessageParserProtocol", msg: list[str]) -> None:
382    """
383    viewを更新する
384
385    Args:
386        adapter (ServiceAdapter): アダプター
387        m (MessageParserProtocol): メッセージデータ
388        msg (list[str]): 表示テキスト
389
390    """
391    text = ""
392    if m.post.headline:
393        header_data, header_option = m.post.headline
394        if isinstance(header_data, str):
395            text = f"\n{header_option.title}\n{header_data}"
396
397    adapter.api.appclient.views_update(
398        view_id=adapter.conf.tab_var["view_id"],
399        view=plain_text(f"{chr(10).join(msg)}\n\n{text}".strip()),
400    )

viewを更新する

Arguments:
  • adapter (ServiceAdapter): アダプター
  • m (MessageParserProtocol): メッセージデータ
  • msg (list[str]): 表示テキスト