11import asyncio
2+ import time
3+ from functools import partial
24
35from cloudbot import hook
4- from cloudbot .util import colors
6+ from cloudbot .util import colors , async_util
57
68
79@hook .command (autohelp = False , permissions = ["botcontrol" ])
@@ -48,12 +50,19 @@ def reconnect(conn, text, bot):
4850
4951
5052def format_conn (conn ):
53+ act_time = time .time () - conn .memory .get ("last_activity" , 0 )
54+ ping_interval = conn .config .get ("ping_interval" , 60 )
5155 if conn .connected :
52- out = "$(green){name}$(clear)"
56+ if act_time > ping_interval :
57+ out = "$(yellow){name}$(clear) (last activity: {activity} secs)"
58+ else :
59+ out = "$(green){name}$(clear)"
5360 else :
5461 out = "$(red){name}$(clear)"
5562
56- return colors .parse (out .format (name = conn .name ))
63+ return colors .parse (out .format (
64+ name = conn .name , activity = round (act_time , 3 )
65+ ))
5766
5867
5968@hook .command ("connlist" , "listconns" , autohelp = False , permissions = ["botcontrol" ])
@@ -63,3 +72,31 @@ def list_conns(bot):
6372 map (format_conn , bot .connections .values ())
6473 )
6574 return "Current connections: {}" .format (conns )
75+
76+
77+ @hook .periodic (5 )
78+ def pinger (bot ):
79+ for conn in bot .connections .values ():
80+ if conn .connected :
81+ ping_interval = conn .config .get ("ping_interval" , 60 )
82+ # This is updated by a catch-all hook, so any activity from the server will indicate a live connection
83+ # This mimics most modern clients, as they will only send a ping if they have not received any data recently
84+ last_act = conn .memory .get ("last_activity" )
85+ # If the activity time isn't set, default to the current time.
86+ # This avoids an issue where the bot would reconnect just after loading this plugin
87+ if last_act is None :
88+ conn .memory ["last_activity" ] = time .time ()
89+ continue
90+
91+ diff = time .time () - last_act
92+ if diff >= (ping_interval * 2 ):
93+ conn .loop .call_soon_threadsafe (
94+ partial (async_util .wrap_future , conn .connect (), loop = conn .loop )
95+ )
96+ elif diff >= ping_interval :
97+ conn .send ("PING :LAGCHECK{}" .format (time .time ()))
98+
99+
100+ @hook .irc_raw ('*' )
101+ def on_activity (conn ):
102+ conn .memory ["last_activity" ] = time .time ()
0 commit comments