|
|
@@ -43,7 +43,7 @@ class PatternExpression(metaclass=ABCMeta):
|
|
43
|
43
|
pass
|
|
44
|
44
|
|
|
45
|
45
|
@abstractmethod
|
|
46
|
|
- def matches(self, message: Message, other_fields: dict[str: Any]) -> bool:
|
|
|
46
|
+ def matches(self, message: Message, other_fields: dict[str, Any]) -> bool:
|
|
47
|
47
|
"""
|
|
48
|
48
|
Whether a message matches this expression. other_fields are additional
|
|
49
|
49
|
fields that can be queried not contained in the message itself.
|
|
|
@@ -57,9 +57,9 @@ class PatternSimpleExpression(PatternExpression):
|
|
57
|
57
|
"""
|
|
58
|
58
|
def __init__(self, field: str, operator: str, value: Any):
|
|
59
|
59
|
super().__init__()
|
|
60
|
|
- self.field = field
|
|
61
|
|
- self.operator = operator
|
|
62
|
|
- self.value = value
|
|
|
60
|
+ self.field: str = field
|
|
|
61
|
+ self.operator: str = operator
|
|
|
62
|
+ self.value: Any = value
|
|
63
|
63
|
|
|
64
|
64
|
def __field_value(self, message: Message, other_fields: dict[str: Any]) -> Any:
|
|
65
|
65
|
if self.field in ('content.markdown', 'content'):
|
|
|
@@ -149,7 +149,7 @@ class PatternStatement:
|
|
149
|
149
|
the given actions should be performed.
|
|
150
|
150
|
"""
|
|
151
|
151
|
|
|
152
|
|
- DEFAULT_PRIORITY = 100
|
|
|
152
|
+ DEFAULT_PRIORITY: int = 100
|
|
153
|
153
|
|
|
154
|
154
|
def __init__(self,
|
|
155
|
155
|
name: str,
|
|
|
@@ -157,11 +157,11 @@ class PatternStatement:
|
|
157
|
157
|
expression: PatternExpression,
|
|
158
|
158
|
original: str,
|
|
159
|
159
|
priority: int = DEFAULT_PRIORITY):
|
|
160
|
|
- self.name = name
|
|
161
|
|
- self.actions = list(actions) # PatternAction[]
|
|
162
|
|
- self.expression = expression
|
|
163
|
|
- self.original = original
|
|
164
|
|
- self.priority = priority
|
|
|
160
|
+ self.name: str = name
|
|
|
161
|
+ self.actions: list[PatternAction] = list(actions) # PatternAction[]
|
|
|
162
|
+ self.expression: PatternExpression = expression
|
|
|
163
|
+ self.original: str = original
|
|
|
164
|
+ self.priority: int = priority
|
|
165
|
165
|
|
|
166
|
166
|
def check_deprecations(self) -> None:
|
|
167
|
167
|
"""
|
|
|
@@ -181,7 +181,7 @@ class PatternStatement:
|
|
181
|
181
|
for oper in c.operands:
|
|
182
|
182
|
cls.__check_deprecations(oper)
|
|
183
|
183
|
|
|
184
|
|
- def to_json(self) -> dict:
|
|
|
184
|
+ def to_json(self) -> dict[str, Any]:
|
|
185
|
185
|
"""
|
|
186
|
186
|
Returns a JSON representation of this statement.
|
|
187
|
187
|
"""
|
|
|
@@ -192,7 +192,7 @@ class PatternStatement:
|
|
192
|
192
|
}
|
|
193
|
193
|
|
|
194
|
194
|
@classmethod
|
|
195
|
|
- def from_json(cls, json: dict):
|
|
|
195
|
+ def from_json(cls, json: dict[str, Any]):
|
|
196
|
196
|
"""
|
|
197
|
197
|
Gets a PatternStatement from its JSON representation.
|
|
198
|
198
|
"""
|
|
|
@@ -204,13 +204,13 @@ class PatternCompiler:
|
|
204
|
204
|
"""
|
|
205
|
205
|
Parses a user-provided message filter statement into a PatternStatement.
|
|
206
|
206
|
"""
|
|
207
|
|
- TYPE_FLOAT = 'float'
|
|
208
|
|
- TYPE_ID = 'id'
|
|
209
|
|
- TYPE_INT = 'int'
|
|
210
|
|
- TYPE_MEMBER = 'Member'
|
|
211
|
|
- TYPE_REGEX = 'regex'
|
|
212
|
|
- TYPE_TEXT = 'text'
|
|
213
|
|
- TYPE_TIMESPAN = 'timespan'
|
|
|
207
|
+ TYPE_FLOAT: str = 'float'
|
|
|
208
|
+ TYPE_ID: str = 'id'
|
|
|
209
|
+ TYPE_INT: str = 'int'
|
|
|
210
|
+ TYPE_MEMBER: str = 'Member'
|
|
|
211
|
+ TYPE_REGEX: str = 'regex'
|
|
|
212
|
+ TYPE_TEXT: str = 'text'
|
|
|
213
|
+ TYPE_TIMESPAN: str = 'timespan'
|
|
214
|
214
|
|
|
215
|
215
|
FIELD_TO_TYPE: dict[str, str] = {
|
|
216
|
216
|
'author': TYPE_MEMBER,
|
|
|
@@ -235,13 +235,13 @@ class PatternCompiler:
|
|
235
|
235
|
|
|
236
|
236
|
OPERATORS_IDENTITY: set[str] = set([ '==', '!=' ])
|
|
237
|
237
|
OPERATORS_COMPARISON: set[str] = set([ '<', '>', '<=', '>=' ])
|
|
238
|
|
- OPERATORS_NUMERIC = OPERATORS_IDENTITY | OPERATORS_COMPARISON
|
|
239
|
|
- OPERATORS_TEXT = OPERATORS_IDENTITY | set([
|
|
|
238
|
+ OPERATORS_NUMERIC: set[str] = OPERATORS_IDENTITY | OPERATORS_COMPARISON
|
|
|
239
|
+ OPERATORS_TEXT: set[str] = OPERATORS_IDENTITY | set([
|
|
240
|
240
|
'contains', '!contains',
|
|
241
|
241
|
'containsword', '!containsword',
|
|
242
|
242
|
'matches', '!matches',
|
|
243
|
243
|
])
|
|
244
|
|
- OPERATORS_ALL = OPERATORS_IDENTITY | OPERATORS_COMPARISON | OPERATORS_TEXT
|
|
|
244
|
+ OPERATORS_ALL: set[str] = OPERATORS_IDENTITY | OPERATORS_COMPARISON | OPERATORS_TEXT
|
|
245
|
245
|
|
|
246
|
246
|
TYPE_TO_OPERATORS: dict[str, set[str]] = {
|
|
247
|
247
|
TYPE_ID: OPERATORS_IDENTITY,
|
|
|
@@ -252,20 +252,20 @@ class PatternCompiler:
|
|
252
|
252
|
TYPE_TIMESPAN: OPERATORS_NUMERIC,
|
|
253
|
253
|
}
|
|
254
|
254
|
|
|
255
|
|
- WHITESPACE_CHARS = ' \t\n\r'
|
|
256
|
|
- STRING_QUOTE_CHARS = '\'"'
|
|
257
|
|
- SYMBOL_CHARS = 'abcdefghijklmnopqrstuvwxyz.'
|
|
258
|
|
- VALUE_CHARS = '0123456789dhms<@!>'
|
|
259
|
|
- OP_CHARS = '<=>!(),'
|
|
|
255
|
+ WHITESPACE_CHARS: str = ' \t\n\r'
|
|
|
256
|
+ STRING_QUOTE_CHARS: str = '\'"'
|
|
|
257
|
+ SYMBOL_CHARS: str = 'abcdefghijklmnopqrstuvwxyz.'
|
|
|
258
|
+ VALUE_CHARS: str = '0123456789dhms<@!>'
|
|
|
259
|
+ OP_CHARS: str = '<=>!(),'
|
|
260
|
260
|
|
|
261
|
|
- MAX_EXPRESSION_NESTING = 8
|
|
|
261
|
+ MAX_EXPRESSION_NESTING: int = 8
|
|
262
|
262
|
|
|
263
|
263
|
@classmethod
|
|
264
|
264
|
def expression_str_from_context(cls, context: Context, name: str) -> str:
|
|
265
|
265
|
"""
|
|
266
|
266
|
Extracts the statement string from an "add" command context.
|
|
267
|
267
|
"""
|
|
268
|
|
- pattern_str = context.message.content
|
|
|
268
|
+ pattern_str: str = context.message.content
|
|
269
|
269
|
command_chain = [ name ]
|
|
270
|
270
|
cmd = context.command
|
|
271
|
271
|
while cmd:
|
|
|
@@ -285,8 +285,8 @@ class PatternCompiler:
|
|
285
|
285
|
Parses a user-provided message filter statement into a PatternStatement.
|
|
286
|
286
|
Raises PatternError on failure.
|
|
287
|
287
|
"""
|
|
288
|
|
- tokens = cls.__tokenize(statement)
|
|
289
|
|
- token_index = 0
|
|
|
288
|
+ tokens: list[str] = cls.__tokenize(statement)
|
|
|
289
|
+ token_index: int = 0
|
|
290
|
290
|
actions, token_index = cls.__read_actions(tokens, token_index)
|
|
291
|
291
|
expression, token_index = cls.__read_expression(tokens, token_index)
|
|
292
|
292
|
return PatternStatement(name, actions, expression, statement)
|
|
|
@@ -297,11 +297,11 @@ class PatternCompiler:
|
|
297
|
297
|
Converts a message filter statement into a list of tokens.
|
|
298
|
298
|
"""
|
|
299
|
299
|
tokens: list[str] = []
|
|
300
|
|
- in_quote = False
|
|
301
|
|
- in_escape = False
|
|
302
|
|
- all_token_types = set([ 'sym', 'op', 'val' ])
|
|
303
|
|
- possible_token_types = set(all_token_types)
|
|
304
|
|
- current_token = ''
|
|
|
300
|
+ in_quote: bool = False
|
|
|
301
|
+ in_escape: bool = False
|
|
|
302
|
+ all_token_types: set[str] = set([ 'sym', 'op', 'val' ])
|
|
|
303
|
+ possible_token_types: set[str] = set(all_token_types)
|
|
|
304
|
+ current_token: str = ''
|
|
305
|
305
|
for ch in statement:
|
|
306
|
306
|
if in_quote:
|
|
307
|
307
|
if in_escape:
|