integrations.base.interface

integrations/base/interface.py

  1"""
  2integrations/base/interface.py
  3"""
  4
  5from abc import ABC, abstractmethod
  6from configparser import ConfigParser
  7from dataclasses import dataclass, field
  8from types import NoneType
  9from typing import TYPE_CHECKING, Any, Generic, Literal, Optional, Type, TypeVar
 10
 11import pandas as pd
 12
 13if TYPE_CHECKING:
 14    from pathlib import Path
 15
 16    from integrations.protocols import MessageParserProtocol, MsgData, PostData, StatusData
 17    from libs.types import MessageType, StyleOptions
 18
 19ConfigT = TypeVar("ConfigT", bound="IntegrationsConfig")
 20ApiT = TypeVar("ApiT", bound="APIInterface")
 21FunctionsT = TypeVar("FunctionsT", bound="FunctionsInterface")
 22ParserT = TypeVar("ParserT", bound="MessageParserInterface")
 23
 24
 25class AdapterInterface(ABC, Generic[ConfigT, ApiT, FunctionsT, ParserT]):
 26    """アダプタインターフェース"""
 27
 28    interface_type: str
 29    """サービス識別子"""
 30
 31    conf: ConfigT
 32    """個別設定データクラス"""
 33    api: ApiT
 34    """インターフェース操作APIインスタンス"""
 35    functions: FunctionsT
 36    """サービス専用関数インスタンス"""
 37    parser: Type[ParserT]
 38    """メッセージパーサクラス"""
 39
 40
 41@dataclass
 42class IntegrationsConfig(ABC):
 43    """個別設定値"""
 44
 45    _parser: Optional[ConfigParser] = field(default=None)
 46
 47    # ディスパッチテーブル用
 48    _command_dispatcher: dict[str, Any] = field(default_factory=dict)
 49    _keyword_dispatcher: dict[str, Any] = field(default_factory=dict)
 50
 51    # 共通設定
 52    main_conf: Optional[ConfigParser] = field(default=None)
 53    """設定ファイル"""
 54    channel_config: Optional["Path"] = field(default=None)
 55    """チャンネル個別設定状況
 56    - *Path*: チャンネル個別設定ファイルパス
 57    - *None*: 個別設定を利用していない
 58    """
 59
 60    slash_command: str = field(default="")
 61    """スラッシュコマンド名"""
 62    badge_degree: bool = field(default=False)
 63    """プレイしたゲーム数に対して表示される称号
 64    - *True*: 表示する
 65    - *False*: 表示しない
 66    """
 67    badge_status: bool = field(default=False)
 68    """勝率に対して付く調子バッジ
 69    - *True*: 表示する
 70    - *False*: 表示しない
 71    """
 72    badge_grade: bool = field(default=False)
 73    """段位表示
 74    - *True*: 表示する
 75    - *False*: 表示しない
 76    """
 77
 78    separate: bool = field(default=False)
 79    """スコア入力元識別子別集計フラグ
 80    - *True*: 識別子別に集計
 81    - *False*: すべて集計
 82    """
 83    channel_id: Optional[str] = field(default=None)
 84    """チャンネルIDを上書きする"""
 85
 86    plotting_backend: Literal["matplotlib", "plotly"] = field(default="matplotlib")
 87    """グラフ描写ライブラリ"""
 88
 89    @property
 90    def command_dispatcher(self) -> dict[str, Any]:
 91        """
 92        コマンドディスパッチテーブルを辞書で取得
 93
 94        Returns:
 95            dict[str, Any]: コマンドディスパッチテーブル
 96
 97        """
 98        return self._command_dispatcher
 99
100    @property
101    def keyword_dispatcher(self) -> dict[str, Any]:
102        """
103        キーワードディスパッチテーブルを辞書で取得
104
105        Returns:
106            dict[str, Any]: キーワードディスパッチテーブル
107
108        """
109        return self._keyword_dispatcher
110
111
112class FunctionsInterface(ABC):
113    """個別関数インターフェース"""
114
115    @abstractmethod
116    def post_processing(self, m: "MessageParserProtocol") -> None:
117        """
118        後処理
119
120        Args:
121            m (MessageParserProtocol): メッセージデータ
122
123        """
124
125    @abstractmethod
126    def get_conversations(self, m: "MessageParserProtocol") -> dict[str, Any]:
127        """
128        スレッド情報の取得
129
130        Args:
131            m (MessageParserProtocol): メッセージデータ
132
133        Returns:
134            dict: API response
135
136        """
137        return {}
138
139
140class APIInterface(ABC):
141    """アダプタAPIインターフェース"""
142
143    @abstractmethod
144    def post(self, m: "MessageParserProtocol") -> None:
145        """
146        メッセージを出力する
147
148        Args:
149            m (MessageParserProtocol): メッセージデータ
150
151        """
152
153
154class MessageParserDataMixin:
155    """メッセージ解析共通処理"""
156
157    data: "MsgData"
158    post: "PostData"
159    status: "StatusData"
160
161    def reset(self) -> None:
162        """初期化"""
163        self.data.reset()
164        self.post.reset()
165        self.status.reset()
166
167    def set_headline(
168        self,
169        data: "MessageType",
170        options: "StyleOptions",
171    ) -> None:
172        """
173        ヘッドラインメッセージをセット
174
175        Args:
176            data (MessageType): 内容
177            options (StyleOptions): 表示オプション
178
179        """
180        # 空データは登録しない
181        if isinstance(data, NoneType) or (isinstance(data, pd.DataFrame) and data.empty):
182            self.post.headline = None
183        else:
184            self.post.headline = (data, options)
185
186    def set_message(
187        self,
188        data: "MessageType",
189        options: "StyleOptions",
190    ) -> None:
191        """
192        本文メッセージをセット
193
194        Args:
195            data (MessageType): 内容
196            options (StyleOptions): 表示オプション
197
198        """
199        # 空データは登録しない
200        if isinstance(data, NoneType) or (isinstance(data, pd.DataFrame) and data.empty):
201            return
202
203        self.post.message.append((data, options))
204
205
206class MessageParserInterface(ABC):
207    """メッセージ解析インターフェース"""
208
209    data: "MsgData"
210    post: "PostData"
211    status: "StatusData"
212
213    @abstractmethod
214    def parser(self, body: Any) -> None:
215        """
216        メッセージ解析
217
218        Args:
219            body (Any): 解析データ
220
221        """
222
223    @property
224    @abstractmethod
225    def in_thread(self) -> bool:
226        """
227        元メッセージへのリプライとなっているか
228
229        Returns:
230            bool: 真偽値
231            - *True*: リプライの形(リプライ/スレッドなど)
232            - *False*: 通常メッセージ
233
234        """
235
236    @property
237    @abstractmethod
238    def is_bot(self) -> bool:
239        """
240        botのポストかチェック
241
242        Returns:
243            bool: 真偽値
244            - *True*: botのポスト
245            - *False*: ユーザのポスト
246
247        """
248
249    @property
250    @abstractmethod
251    def check_updatable(self) -> bool:
252        """
253        DB操作の許可チェック
254
255        Returns:
256            bool: 真偽値
257            - *True*: 許可
258            - *False*: 禁止
259
260        """
261
262    @property
263    @abstractmethod
264    def ignore_user(self) -> bool:
265        """
266        ignore_useridに存在するユーザかチェック
267
268        Returns:
269            bool: 真偽値
270            - *True*: 存在する(操作禁止ユーザ)
271            - *False*: 存在しない
272
273        """
274
275    @property
276    def is_command(self) -> bool:
277        """
278        コマンドで実行されているかチェック
279
280        Returns:
281            bool: 真偽値
282            - *True*: コマンド実行
283            - *False*: 非コマンド(キーワード呼び出し)
284
285        """
286        return self.status.command_flg
287
288    @property
289    def keyword(self) -> str:
290        """
291        コマンドとして認識している文字列を返す
292
293        Returns:
294            str: コマンド名
295
296        """
297        if ret := self.data.text.split():
298            return ret[0]
299        return self.data.text
300
301    @property
302    def argument(self) -> list[str]:
303        """
304        コマンド引数として認識している文字列をリストで返す
305
306        Returns:
307            list[str]: 引数リスト
308
309        """
310        if ret := self.data.text.split():
311            return ret[1:]
312        return ret
313
314    @property
315    def reply_ts(self) -> str:
316        """
317        リプライ先のタイムスタンプを取得する
318
319        Returns:
320            str: タイムスタンプ
321
322        """
323        ret_ts: str = "0"
324
325        # tsが指定されていれば最優先
326        if self.post.ts != "undetermined":
327            return self.post.ts
328
329        # スレッドに返すか
330        if self.post.thread and self.in_thread:  # スレッド内
331            if self.data.thread_ts != "undetermined":
332                ret_ts = self.data.thread_ts
333        elif self.post.thread and not self.in_thread:  # スレッド外
334            ret_ts = self.data.event_ts
335
336        return ret_ts
class AdapterInterface(abc.ABC, typing.Generic[~ConfigT, ~ApiT, ~FunctionsT, ~ParserT]):
26class AdapterInterface(ABC, Generic[ConfigT, ApiT, FunctionsT, ParserT]):
27    """アダプタインターフェース"""
28
29    interface_type: str
30    """サービス識別子"""
31
32    conf: ConfigT
33    """個別設定データクラス"""
34    api: ApiT
35    """インターフェース操作APIインスタンス"""
36    functions: FunctionsT
37    """サービス専用関数インスタンス"""
38    parser: Type[ParserT]
39    """メッセージパーサクラス"""

アダプタインターフェース

interface_type: str

サービス識別子

conf: ~ConfigT

個別設定データクラス

api: ~ApiT

インターフェース操作APIインスタンス

functions: ~FunctionsT

サービス専用関数インスタンス

parser: Type[~ParserT]

メッセージパーサクラス

@dataclass
class IntegrationsConfig(abc.ABC):
 42@dataclass
 43class IntegrationsConfig(ABC):
 44    """個別設定値"""
 45
 46    _parser: Optional[ConfigParser] = field(default=None)
 47
 48    # ディスパッチテーブル用
 49    _command_dispatcher: dict[str, Any] = field(default_factory=dict)
 50    _keyword_dispatcher: dict[str, Any] = field(default_factory=dict)
 51
 52    # 共通設定
 53    main_conf: Optional[ConfigParser] = field(default=None)
 54    """設定ファイル"""
 55    channel_config: Optional["Path"] = field(default=None)
 56    """チャンネル個別設定状況
 57    - *Path*: チャンネル個別設定ファイルパス
 58    - *None*: 個別設定を利用していない
 59    """
 60
 61    slash_command: str = field(default="")
 62    """スラッシュコマンド名"""
 63    badge_degree: bool = field(default=False)
 64    """プレイしたゲーム数に対して表示される称号
 65    - *True*: 表示する
 66    - *False*: 表示しない
 67    """
 68    badge_status: bool = field(default=False)
 69    """勝率に対して付く調子バッジ
 70    - *True*: 表示する
 71    - *False*: 表示しない
 72    """
 73    badge_grade: bool = field(default=False)
 74    """段位表示
 75    - *True*: 表示する
 76    - *False*: 表示しない
 77    """
 78
 79    separate: bool = field(default=False)
 80    """スコア入力元識別子別集計フラグ
 81    - *True*: 識別子別に集計
 82    - *False*: すべて集計
 83    """
 84    channel_id: Optional[str] = field(default=None)
 85    """チャンネルIDを上書きする"""
 86
 87    plotting_backend: Literal["matplotlib", "plotly"] = field(default="matplotlib")
 88    """グラフ描写ライブラリ"""
 89
 90    @property
 91    def command_dispatcher(self) -> dict[str, Any]:
 92        """
 93        コマンドディスパッチテーブルを辞書で取得
 94
 95        Returns:
 96            dict[str, Any]: コマンドディスパッチテーブル
 97
 98        """
 99        return self._command_dispatcher
100
101    @property
102    def keyword_dispatcher(self) -> dict[str, Any]:
103        """
104        キーワードディスパッチテーブルを辞書で取得
105
106        Returns:
107            dict[str, Any]: キーワードディスパッチテーブル
108
109        """
110        return self._keyword_dispatcher

個別設定値

IntegrationsConfig( _parser: configparser.ConfigParser | None = None, _command_dispatcher: dict[str, typing.Any] = <factory>, _keyword_dispatcher: dict[str, typing.Any] = <factory>, main_conf: configparser.ConfigParser | None = None, channel_config: pathlib.Path | None = None, slash_command: str = '', badge_degree: bool = False, badge_status: bool = False, badge_grade: bool = False, separate: bool = False, channel_id: str | None = None, plotting_backend: Literal['matplotlib', 'plotly'] = 'matplotlib')
main_conf: configparser.ConfigParser | None = None

設定ファイル

channel_config: pathlib.Path | None = None

チャンネル個別設定状況

  • Path: チャンネル個別設定ファイルパス
  • None: 個別設定を利用していない
slash_command: str = ''

スラッシュコマンド名

badge_degree: bool = False

プレイしたゲーム数に対して表示される称号

  • True: 表示する
  • False: 表示しない
badge_status: bool = False

勝率に対して付く調子バッジ

  • True: 表示する
  • False: 表示しない
badge_grade: bool = False

段位表示

  • True: 表示する
  • False: 表示しない
separate: bool = False

スコア入力元識別子別集計フラグ

  • True: 識別子別に集計
  • False: すべて集計
channel_id: str | None = None

チャンネルIDを上書きする

plotting_backend: Literal['matplotlib', 'plotly'] = 'matplotlib'

グラフ描写ライブラリ

command_dispatcher: dict[str, typing.Any]
90    @property
91    def command_dispatcher(self) -> dict[str, Any]:
92        """
93        コマンドディスパッチテーブルを辞書で取得
94
95        Returns:
96            dict[str, Any]: コマンドディスパッチテーブル
97
98        """
99        return self._command_dispatcher

コマンドディスパッチテーブルを辞書で取得

Returns:

dict[str, Any]: コマンドディスパッチテーブル

keyword_dispatcher: dict[str, typing.Any]
101    @property
102    def keyword_dispatcher(self) -> dict[str, Any]:
103        """
104        キーワードディスパッチテーブルを辞書で取得
105
106        Returns:
107            dict[str, Any]: キーワードディスパッチテーブル
108
109        """
110        return self._keyword_dispatcher

キーワードディスパッチテーブルを辞書で取得

Returns:

dict[str, Any]: キーワードディスパッチテーブル

class FunctionsInterface(abc.ABC):
113class FunctionsInterface(ABC):
114    """個別関数インターフェース"""
115
116    @abstractmethod
117    def post_processing(self, m: "MessageParserProtocol") -> None:
118        """
119        後処理
120
121        Args:
122            m (MessageParserProtocol): メッセージデータ
123
124        """
125
126    @abstractmethod
127    def get_conversations(self, m: "MessageParserProtocol") -> dict[str, Any]:
128        """
129        スレッド情報の取得
130
131        Args:
132            m (MessageParserProtocol): メッセージデータ
133
134        Returns:
135            dict: API response
136
137        """
138        return {}

個別関数インターフェース

@abstractmethod
def post_processing(self, m: integrations.protocols.MessageParserProtocol) -> None:
116    @abstractmethod
117    def post_processing(self, m: "MessageParserProtocol") -> None:
118        """
119        後処理
120
121        Args:
122            m (MessageParserProtocol): メッセージデータ
123
124        """

後処理

Arguments:
  • m (MessageParserProtocol): メッセージデータ
@abstractmethod
def get_conversations( self, m: integrations.protocols.MessageParserProtocol) -> dict[str, typing.Any]:
126    @abstractmethod
127    def get_conversations(self, m: "MessageParserProtocol") -> dict[str, Any]:
128        """
129        スレッド情報の取得
130
131        Args:
132            m (MessageParserProtocol): メッセージデータ
133
134        Returns:
135            dict: API response
136
137        """
138        return {}

スレッド情報の取得

Arguments:
  • m (MessageParserProtocol): メッセージデータ
Returns:

dict: API response

class APIInterface(abc.ABC):
141class APIInterface(ABC):
142    """アダプタAPIインターフェース"""
143
144    @abstractmethod
145    def post(self, m: "MessageParserProtocol") -> None:
146        """
147        メッセージを出力する
148
149        Args:
150            m (MessageParserProtocol): メッセージデータ
151
152        """

アダプタAPIインターフェース

@abstractmethod
def post(self, m: integrations.protocols.MessageParserProtocol) -> None:
144    @abstractmethod
145    def post(self, m: "MessageParserProtocol") -> None:
146        """
147        メッセージを出力する
148
149        Args:
150            m (MessageParserProtocol): メッセージデータ
151
152        """

メッセージを出力する

Arguments:
  • m (MessageParserProtocol): メッセージデータ
class MessageParserDataMixin:
155class MessageParserDataMixin:
156    """メッセージ解析共通処理"""
157
158    data: "MsgData"
159    post: "PostData"
160    status: "StatusData"
161
162    def reset(self) -> None:
163        """初期化"""
164        self.data.reset()
165        self.post.reset()
166        self.status.reset()
167
168    def set_headline(
169        self,
170        data: "MessageType",
171        options: "StyleOptions",
172    ) -> None:
173        """
174        ヘッドラインメッセージをセット
175
176        Args:
177            data (MessageType): 内容
178            options (StyleOptions): 表示オプション
179
180        """
181        # 空データは登録しない
182        if isinstance(data, NoneType) or (isinstance(data, pd.DataFrame) and data.empty):
183            self.post.headline = None
184        else:
185            self.post.headline = (data, options)
186
187    def set_message(
188        self,
189        data: "MessageType",
190        options: "StyleOptions",
191    ) -> None:
192        """
193        本文メッセージをセット
194
195        Args:
196            data (MessageType): 内容
197            options (StyleOptions): 表示オプション
198
199        """
200        # 空データは登録しない
201        if isinstance(data, NoneType) or (isinstance(data, pd.DataFrame) and data.empty):
202            return
203
204        self.post.message.append((data, options))

メッセージ解析共通処理

def reset(self) -> None:
162    def reset(self) -> None:
163        """初期化"""
164        self.data.reset()
165        self.post.reset()
166        self.status.reset()

初期化

def set_headline( self, data: None | str | pathlib.Path | pandas.DataFrame, options: libs.types.StyleOptions) -> None:
168    def set_headline(
169        self,
170        data: "MessageType",
171        options: "StyleOptions",
172    ) -> None:
173        """
174        ヘッドラインメッセージをセット
175
176        Args:
177            data (MessageType): 内容
178            options (StyleOptions): 表示オプション
179
180        """
181        # 空データは登録しない
182        if isinstance(data, NoneType) or (isinstance(data, pd.DataFrame) and data.empty):
183            self.post.headline = None
184        else:
185            self.post.headline = (data, options)

ヘッドラインメッセージをセット

Arguments:
  • data (MessageType): 内容
  • options (StyleOptions): 表示オプション
def set_message( self, data: None | str | pathlib.Path | pandas.DataFrame, options: libs.types.StyleOptions) -> None:
187    def set_message(
188        self,
189        data: "MessageType",
190        options: "StyleOptions",
191    ) -> None:
192        """
193        本文メッセージをセット
194
195        Args:
196            data (MessageType): 内容
197            options (StyleOptions): 表示オプション
198
199        """
200        # 空データは登録しない
201        if isinstance(data, NoneType) or (isinstance(data, pd.DataFrame) and data.empty):
202            return
203
204        self.post.message.append((data, options))

本文メッセージをセット

Arguments:
  • data (MessageType): 内容
  • options (StyleOptions): 表示オプション
class MessageParserInterface(abc.ABC):
207class MessageParserInterface(ABC):
208    """メッセージ解析インターフェース"""
209
210    data: "MsgData"
211    post: "PostData"
212    status: "StatusData"
213
214    @abstractmethod
215    def parser(self, body: Any) -> None:
216        """
217        メッセージ解析
218
219        Args:
220            body (Any): 解析データ
221
222        """
223
224    @property
225    @abstractmethod
226    def in_thread(self) -> bool:
227        """
228        元メッセージへのリプライとなっているか
229
230        Returns:
231            bool: 真偽値
232            - *True*: リプライの形(リプライ/スレッドなど)
233            - *False*: 通常メッセージ
234
235        """
236
237    @property
238    @abstractmethod
239    def is_bot(self) -> bool:
240        """
241        botのポストかチェック
242
243        Returns:
244            bool: 真偽値
245            - *True*: botのポスト
246            - *False*: ユーザのポスト
247
248        """
249
250    @property
251    @abstractmethod
252    def check_updatable(self) -> bool:
253        """
254        DB操作の許可チェック
255
256        Returns:
257            bool: 真偽値
258            - *True*: 許可
259            - *False*: 禁止
260
261        """
262
263    @property
264    @abstractmethod
265    def ignore_user(self) -> bool:
266        """
267        ignore_useridに存在するユーザかチェック
268
269        Returns:
270            bool: 真偽値
271            - *True*: 存在する(操作禁止ユーザ)
272            - *False*: 存在しない
273
274        """
275
276    @property
277    def is_command(self) -> bool:
278        """
279        コマンドで実行されているかチェック
280
281        Returns:
282            bool: 真偽値
283            - *True*: コマンド実行
284            - *False*: 非コマンド(キーワード呼び出し)
285
286        """
287        return self.status.command_flg
288
289    @property
290    def keyword(self) -> str:
291        """
292        コマンドとして認識している文字列を返す
293
294        Returns:
295            str: コマンド名
296
297        """
298        if ret := self.data.text.split():
299            return ret[0]
300        return self.data.text
301
302    @property
303    def argument(self) -> list[str]:
304        """
305        コマンド引数として認識している文字列をリストで返す
306
307        Returns:
308            list[str]: 引数リスト
309
310        """
311        if ret := self.data.text.split():
312            return ret[1:]
313        return ret
314
315    @property
316    def reply_ts(self) -> str:
317        """
318        リプライ先のタイムスタンプを取得する
319
320        Returns:
321            str: タイムスタンプ
322
323        """
324        ret_ts: str = "0"
325
326        # tsが指定されていれば最優先
327        if self.post.ts != "undetermined":
328            return self.post.ts
329
330        # スレッドに返すか
331        if self.post.thread and self.in_thread:  # スレッド内
332            if self.data.thread_ts != "undetermined":
333                ret_ts = self.data.thread_ts
334        elif self.post.thread and not self.in_thread:  # スレッド外
335            ret_ts = self.data.event_ts
336
337        return ret_ts

メッセージ解析インターフェース

@abstractmethod
def parser(self, body: Any) -> None:
214    @abstractmethod
215    def parser(self, body: Any) -> None:
216        """
217        メッセージ解析
218
219        Args:
220            body (Any): 解析データ
221
222        """

メッセージ解析

Arguments:
  • body (Any): 解析データ
in_thread: bool
224    @property
225    @abstractmethod
226    def in_thread(self) -> bool:
227        """
228        元メッセージへのリプライとなっているか
229
230        Returns:
231            bool: 真偽値
232            - *True*: リプライの形(リプライ/スレッドなど)
233            - *False*: 通常メッセージ
234
235        """

元メッセージへのリプライとなっているか

Returns:

bool: 真偽値

  • True: リプライの形(リプライ/スレッドなど)
  • False: 通常メッセージ
is_bot: bool
237    @property
238    @abstractmethod
239    def is_bot(self) -> bool:
240        """
241        botのポストかチェック
242
243        Returns:
244            bool: 真偽値
245            - *True*: botのポスト
246            - *False*: ユーザのポスト
247
248        """

botのポストかチェック

Returns:

bool: 真偽値

  • True: botのポスト
  • False: ユーザのポスト
check_updatable: bool
250    @property
251    @abstractmethod
252    def check_updatable(self) -> bool:
253        """
254        DB操作の許可チェック
255
256        Returns:
257            bool: 真偽値
258            - *True*: 許可
259            - *False*: 禁止
260
261        """

DB操作の許可チェック

Returns:

bool: 真偽値

  • True: 許可
  • False: 禁止
ignore_user: bool
263    @property
264    @abstractmethod
265    def ignore_user(self) -> bool:
266        """
267        ignore_useridに存在するユーザかチェック
268
269        Returns:
270            bool: 真偽値
271            - *True*: 存在する(操作禁止ユーザ)
272            - *False*: 存在しない
273
274        """

ignore_useridに存在するユーザかチェック

Returns:

bool: 真偽値

  • True: 存在する(操作禁止ユーザ)
  • False: 存在しない
is_command: bool
276    @property
277    def is_command(self) -> bool:
278        """
279        コマンドで実行されているかチェック
280
281        Returns:
282            bool: 真偽値
283            - *True*: コマンド実行
284            - *False*: 非コマンド(キーワード呼び出し)
285
286        """
287        return self.status.command_flg

コマンドで実行されているかチェック

Returns:

bool: 真偽値

  • True: コマンド実行
  • False: 非コマンド(キーワード呼び出し)
keyword: str
289    @property
290    def keyword(self) -> str:
291        """
292        コマンドとして認識している文字列を返す
293
294        Returns:
295            str: コマンド名
296
297        """
298        if ret := self.data.text.split():
299            return ret[0]
300        return self.data.text

コマンドとして認識している文字列を返す

Returns:

str: コマンド名

argument: list[str]
302    @property
303    def argument(self) -> list[str]:
304        """
305        コマンド引数として認識している文字列をリストで返す
306
307        Returns:
308            list[str]: 引数リスト
309
310        """
311        if ret := self.data.text.split():
312            return ret[1:]
313        return ret

コマンド引数として認識している文字列をリストで返す

Returns:

list[str]: 引数リスト

reply_ts: str
315    @property
316    def reply_ts(self) -> str:
317        """
318        リプライ先のタイムスタンプを取得する
319
320        Returns:
321            str: タイムスタンプ
322
323        """
324        ret_ts: str = "0"
325
326        # tsが指定されていれば最優先
327        if self.post.ts != "undetermined":
328            return self.post.ts
329
330        # スレッドに返すか
331        if self.post.thread and self.in_thread:  # スレッド内
332            if self.data.thread_ts != "undetermined":
333                ret_ts = self.data.thread_ts
334        elif self.post.thread and not self.in_thread:  # スレッド外
335            ret_ts = self.data.event_ts
336
337        return ret_ts

リプライ先のタイムスタンプを取得する

Returns:

str: タイムスタンプ