55server_info.py
66"""
77import gc
8+ import json
89import weakref
9- from collections import Mapping
10+ from collections import Mapping , Iterable
1011from contextlib import suppress
12+ from numbers import Number
1113from operator import attrgetter
1214from weakref import WeakValueDictionary
1315
1416import cloudbot .bot
1517from cloudbot import hook
18+ from cloudbot .util import web
1619from cloudbot .util .parsers .irc import Prefix
1720
1821logger = cloudbot .bot .logger
@@ -312,26 +315,38 @@ def on_names(conn, irc_paramlist, irc_command):
312315 users .extend (names .split ())
313316
314317
315- def dump_dict (data , indent = 2 , level = 0 , _objects = None ):
316- """
317- :type data: Mapping
318- :type indent: int
319- :type level: int
320- :type _objects: list
321- """
322- if _objects is None :
323- _objects = [id (data )]
318+ class MappingSerializer :
319+ def __init__ (self ):
320+ self ._seen_objects = []
321+
322+ def _serialize (self , obj ):
323+ if isinstance (obj , (str , Number , bool )) or obj is None :
324+ return obj
325+ elif isinstance (obj , Mapping ):
326+ if id (obj ) in self ._seen_objects :
327+ return '<{} with id {}>' .format (type (obj ).__name__ , id (obj ))
328+
329+ self ._seen_objects .append (id (obj ))
330+
331+ return {
332+ self ._serialize (k ): self ._serialize (v )
333+ for k , v in obj .items ()
334+ }
335+ elif isinstance (obj , Iterable ):
336+ if id (obj ) in self ._seen_objects :
337+ return '<{} with id {}>' .format (type (obj ).__name__ , id (obj ))
338+
339+ self ._seen_objects .append (id (obj ))
324340
325- for key , value in data .items ():
326- yield ((" " * (indent * level )) + "{}:" .format (key ))
327- if id (value ) in _objects :
328- yield ((" " * (indent * (level + 1 ))) + "[...]" )
329- elif isinstance (value , Mapping ):
330- _objects .append (id (value ))
331- yield from dump_dict (value , indent = indent , level = level + 1 , _objects = _objects )
341+ return [
342+ self ._serialize (item )
343+ for item in obj
344+ ]
332345 else :
333- _objects .append (id (value ))
334- yield ((" " * (indent * (level + 1 ))) + "{}" .format (value ))
346+ return repr (obj )
347+
348+ def serialize (self , mapping , ** kwargs ):
349+ return json .dumps (self ._serialize (mapping ), ** kwargs )
335350
336351
337352@hook .permission ("chanop" )
@@ -368,9 +383,7 @@ def dumpchans(conn):
368383 :type conn: cloudbot.client.Client
369384 """
370385 data = get_chans (conn )
371- lines = list (dump_dict (data ))
372- print ('\n ' .join (lines ))
373- return "Printed {} channel records totalling {} lines of data to the console." .format (len (data ), len (lines ))
386+ return web .paste (MappingSerializer ().serialize (data , indent = 2 ))
374387
375388
376389@hook .command (permissions = ["botcontrol" ], autohelp = False )
@@ -379,9 +392,7 @@ def dumpusers(conn):
379392 :type conn: cloudbot.client.Client
380393 """
381394 data = get_users (conn )
382- lines = list (dump_dict (data ))
383- print ('\n ' .join (lines ))
384- return "Printed {} user records totalling {} lines of data to the console." .format (len (data ), len (lines ))
395+ return web .paste (MappingSerializer ().serialize (data , indent = 2 ))
385396
386397
387398@hook .command (permissions = ["botcontrol" ], autohelp = False )
@@ -415,6 +426,14 @@ def clearusers(bot):
415426 return "Data cleared."
416427
417428
429+ @hook .command ("getdata" , permissions = ["botcontrol" ], autohelp = False )
430+ def getdata_cmd (conn , chan , text , nick ):
431+ chan_data = get_chans (conn ).getchan (chan )
432+ user_data = get_users (conn ).getuser (nick )
433+ memb = get_channel_member (chan_data , user_data )
434+ return web .paste (MappingSerializer ().serialize (memb , indent = 2 ))
435+
436+
418437@hook .irc_raw ('JOIN' )
419438def on_join (nick , user , host , conn , irc_paramlist ):
420439 """
@@ -457,6 +476,10 @@ def on_mode(chan, irc_paramlist, conn):
457476 if chan .startswith (':' ):
458477 chan = chan [1 :]
459478
479+ if chan .casefold () == conn .nick .casefold ():
480+ # this is a user mode line
481+ return
482+
460483 serv_info = conn .memory ["server_info" ]
461484 statuses = serv_info ["statuses" ]
462485 status_modes = {status .mode for status in statuses .values ()}
0 commit comments