5
5
from collections import defaultdict
6
6
from functools import total_ordering
7
7
from threading import RLock
8
+ from typing import List , MutableMapping , Optional
8
9
9
10
from irclib .util .compare import match_mask
10
11
from sqlalchemy import (
33
34
PrimaryKeyConstraint ("network" , "chan" , "hook" ),
34
35
)
35
36
36
- optout_cache = DefaultKeyFoldDict (list )
37
+ optout_cache : MutableMapping [ str , List [ "OptOut" ]] = DefaultKeyFoldDict (list )
37
38
38
39
cache_lock = RLock ()
39
40
@@ -47,16 +48,18 @@ def __init__(self, channel, hook_pattern, allow):
47
48
48
49
def __lt__ (self , other ):
49
50
if isinstance (other , OptOut ):
50
- diff = len (self .channel ) - len (other .channel )
51
- if diff :
52
- return diff < 0
53
-
54
- return len (self .hook ) < len (other .hook )
51
+ return (self .channel .rstrip ("*" ), self .hook .rstrip ("*" )) < (
52
+ other .channel .rstrip ("*" ),
53
+ other .hook .rstrip ("*" ),
54
+ )
55
55
56
56
return NotImplemented
57
57
58
- def __str__ (self ):
59
- return f"{ self .channel } { self .hook } { self .allow } "
58
+ def __eq__ (self , other ):
59
+ if isinstance (other , OptOut ):
60
+ return self .channel == other .channel and self .hook == other .hook
61
+
62
+ return NotImplemented
60
63
61
64
def __repr__ (self ):
62
65
return "{}({}, {}, {})" .format (
@@ -82,12 +85,12 @@ async def check_channel_permissions(event, chan, *perms):
82
85
return allowed
83
86
84
87
85
- def get_conn_optouts (conn_name ):
88
+ def get_conn_optouts (conn_name ) -> List [ OptOut ] :
86
89
with cache_lock :
87
90
return optout_cache [conn_name .casefold ()]
88
91
89
92
90
- def get_channel_optouts (conn_name , chan = None ):
93
+ def get_channel_optouts (conn_name , chan = None ) -> List [ OptOut ] :
91
94
with cache_lock :
92
95
return [
93
96
opt
@@ -96,6 +99,14 @@ def get_channel_optouts(conn_name, chan=None):
96
99
]
97
100
98
101
102
+ def get_first_matching_optout (conn_name , chan , hook_name ) -> Optional [OptOut ]:
103
+ for optout in get_conn_optouts (conn_name ):
104
+ if optout .match (chan , hook_name ):
105
+ return optout
106
+
107
+ return None
108
+
109
+
99
110
def format_optout_list (opts ):
100
111
headers = ("Channel Pattern" , "Hook Pattern" , "Allowed" )
101
112
table = [
@@ -186,19 +197,12 @@ def optout_sieve(bot, event, _hook):
186
197
return event
187
198
188
199
hook_name = _hook .plugin .title + "." + _hook .function_name
189
- with cache_lock :
190
- optouts = get_conn_optouts (event .conn .name )
191
- for _optout in optouts :
192
- if _optout .match (event .chan , hook_name ):
193
- if not _optout .allow :
194
- if _hook .type == "command" :
195
- event .notice (
196
- "Sorry, that command is disabled in this channel."
197
- )
198
-
199
- return None
200
-
201
- break
200
+ _optout = get_first_matching_optout (event .conn .name , event .chan , hook_name )
201
+ if _optout and not _optout .allow :
202
+ if _hook .type == "command" :
203
+ event .notice ("Sorry, that command is disabled in this channel." )
204
+
205
+ return None
202
206
203
207
return event
204
208
0 commit comments