1
1
import logging
2
2
from time import time
3
+ from typing import Optional
3
4
4
5
from cloudbot import hook
6
+ from cloudbot .bot import CloudBot
7
+ from cloudbot .event import CommandEvent , Event
8
+ from cloudbot .plugin_hooks import Hook
5
9
from cloudbot .util .tokenbucket import TokenBucket
6
10
7
11
ready = False
@@ -16,29 +20,36 @@ def task_clear():
16
20
del buckets [uid ]
17
21
18
22
19
- @hook .sieve (priority = 100 )
20
- async def sieve_suite (bot , event , _hook ):
23
+ # noinspection PyUnusedLocal
24
+ @hook .sieve ()
25
+ def check_acls (bot : CloudBot , event : Event , _hook : Hook ) -> Optional [Event ]:
26
+ """
27
+ Handle config ACLs
28
+ """
21
29
conn = event .conn
22
30
23
31
# check acls
24
- acl = conn .config .get ('acls' , {}).get (_hook .function_name )
25
- if acl :
26
- if 'deny-except' in acl :
27
- allowed_channels = list (map (str .lower , acl ['deny-except' ]))
28
- if event .chan .lower () not in allowed_channels :
29
- return None
30
- if 'allow-except' in acl :
31
- denied_channels = list (map (str .lower , acl ['allow-except' ]))
32
- if event .chan .lower () in denied_channels :
33
- return None
34
-
35
- # check disabled_commands
36
- if _hook .type == "command" :
37
- disabled_commands = conn .config .get ('disabled_commands' , [])
38
- if event .triggered_command in disabled_commands :
32
+ acl = conn .config .get ("acls" , {}).get (_hook .function_name , {})
33
+ allowlist = acl .get ("deny-except" )
34
+ denylist = acl .get ("allow-except" )
35
+ chan = event .chan .lower ()
36
+ if allowlist is not None :
37
+ allowed_channels = list (map (str .lower , allowlist ))
38
+ if chan not in allowed_channels :
39
+ return None
40
+
41
+ if denylist is not None :
42
+ denied_channels = list (map (str .lower , denylist ))
43
+ if chan in denied_channels :
39
44
return None
40
45
41
- # check permissions
46
+ return event
47
+
48
+
49
+ # noinspection PyUnusedLocal
50
+ @hook .sieve ()
51
+ async def perm_sieve (bot : CloudBot , event : Event , _hook : Hook ) -> Optional [Event ]:
52
+ """check permissions"""
42
53
allowed_permissions = _hook .permissions
43
54
if allowed_permissions :
44
55
allowed = False
@@ -51,33 +62,58 @@ async def sieve_suite(bot, event, _hook):
51
62
event .notice ("Sorry, you are not allowed to use this command." )
52
63
return None
53
64
54
- # check command spam tokens
65
+ return event
66
+
67
+
68
+ # noinspection PyUnusedLocal
69
+ @hook .sieve ()
70
+ def check_disabled (bot : CloudBot , event : CommandEvent , _hook : Hook ) -> Optional [Event ]:
71
+ """
72
+ check disabled_commands
73
+ """
74
+ conn = event .conn
55
75
if _hook .type == "command" :
76
+ disabled_commands = conn .config .get ("disabled_commands" , [])
77
+ if event .triggered_command in disabled_commands :
78
+ return None
79
+
80
+ return event
81
+
82
+
83
+ # noinspection PyUnusedLocal
84
+ @hook .sieve ()
85
+ def rate_limit (bot : CloudBot , event : Event , _hook : Hook ) -> Optional [Event ]:
86
+ """
87
+ Handle rate limiting certain hooks
88
+ """
89
+ conn = event .conn
90
+ # check command spam tokens
91
+ if _hook .type in ("command" , "regex" ):
56
92
uid = "!" .join ([conn .name , event .chan , event .nick ]).lower ()
57
93
58
- tokens = conn .config .get ('ratelimit' , {}).get ('tokens' , 17.5 )
59
- restore_rate = conn .config .get ('ratelimit' , {}).get ('restore_rate' , 2.5 )
60
- message_cost = conn .config .get ('ratelimit' , {}).get ('message_cost' , 5 )
61
- strict = conn .config .get ('ratelimit' , {}).get ('strict' , True )
62
-
63
- if uid not in buckets :
64
- bucket = TokenBucket (tokens , restore_rate )
65
- bucket .consume (message_cost )
66
- buckets [uid ] = bucket
67
- return event
68
-
69
- bucket = buckets [uid ]
70
- if bucket .consume (message_cost ):
71
- pass
72
- else :
94
+ config = conn .config .get ("ratelimit" , {})
95
+ tokens = config .get ("tokens" , 17.5 )
96
+ restore_rate = config .get ("restore_rate" , 2.5 )
97
+ message_cost = config .get ("message_cost" , 5 )
98
+ strict = config .get ("strict" , True )
99
+
100
+ try :
101
+ bucket = buckets [uid ]
102
+ except KeyError :
103
+ buckets [uid ] = bucket = TokenBucket (tokens , restore_rate )
104
+
105
+ if not bucket .consume (message_cost ):
73
106
logger .info (
74
- "[%s|sieve] Refused command from %s. "
75
- "Entity had %s tokens, needed %s." ,
76
- conn .name , uid , bucket .tokens , message_cost
107
+ "[%s|sieve] Refused command from %s. Entity had %s tokens, needed %s." ,
108
+ conn .name ,
109
+ uid ,
110
+ bucket .tokens ,
111
+ message_cost ,
77
112
)
78
113
if strict :
79
114
# bad person loses all tokens
80
115
bucket .empty ()
116
+
81
117
return None
82
118
83
119
return event
0 commit comments