|
4 | 4 | Requires: |
5 | 5 | server_info.py |
6 | 6 | """ |
| 7 | +import gc |
7 | 8 | import weakref |
| 9 | +from collections import Mapping |
| 10 | +from contextlib import suppress |
8 | 11 | from operator import attrgetter |
9 | 12 | from weakref import WeakValueDictionary |
10 | 13 |
|
@@ -105,6 +108,34 @@ def get_chan_data(bot): |
105 | 108 | update_conn_data(conn) |
106 | 109 |
|
107 | 110 |
|
| 111 | +def clean_user_data(user): |
| 112 | + for memb in user.get("channels", {}).values(): |
| 113 | + status = list(set(memb.get("status", []))) |
| 114 | + status.sort(key=attrgetter("level"), reverse=True) |
| 115 | + memb["status"] = status |
| 116 | + |
| 117 | + |
| 118 | +def clean_chan_data(chan): |
| 119 | + with suppress(KeyError): |
| 120 | + del chan["new_users"] |
| 121 | + |
| 122 | + with suppress(KeyError): |
| 123 | + del chan["receiving_names"] |
| 124 | + |
| 125 | + |
| 126 | +def clean_conn_data(conn): |
| 127 | + for user in conn.memory.get("users", {}).values(): |
| 128 | + clean_user_data(user) |
| 129 | + |
| 130 | + for chan in conn.memory.get("chan_data", {}).values(): |
| 131 | + clean_chan_data(chan) |
| 132 | + |
| 133 | + |
| 134 | +def clean_data(bot): |
| 135 | + for conn in bot.connections.values(): |
| 136 | + clean_conn_data(conn) |
| 137 | + |
| 138 | + |
108 | 139 | @hook.connect |
109 | 140 | def init_chan_data(conn, _clear=True): |
110 | 141 | chan_data = conn.memory.setdefault("chan_data", ChanDict()) |
@@ -158,15 +189,16 @@ def replace_user_data(conn, chan_data): |
158 | 189 | nick = user_data["nick"] |
159 | 190 | new_users[nick] = memb_data |
160 | 191 | if nick in old_users: |
161 | | - old_data = old_users[nick] |
| 192 | + old_data = old_users[nick] # Old membership object |
162 | 193 | old_data.update(memb_data) # New data takes priority over old data |
163 | 194 | memb_data.update(old_data) |
164 | 195 |
|
165 | 196 | old_user_data = users.getuser(nick) |
| 197 | + user_data["channels"] = old_user_data["channels"] |
| 198 | + add_user_membership(user_data, chan_data["name"], memb_data) |
166 | 199 | old_user_data.update(user_data) |
167 | 200 | user_data = old_user_data |
168 | 201 | memb_data["user"] = user_data |
169 | | - add_user_membership(user_data, chan_data["name"], memb_data) |
170 | 202 |
|
171 | 203 | old_users.clear() |
172 | 204 | old_users.update(new_users) # Reassigning the dict would break other references to the data, so just update instead |
@@ -201,7 +233,7 @@ def dump_dict(data, indent=2, level=0, _objects=None): |
201 | 233 | yield ((" " * (indent * level)) + "{}:".format(key)) |
202 | 234 | if id(value) in _objects: |
203 | 235 | yield ((" " * (indent * (level + 1))) + "[...]") |
204 | | - elif isinstance(value, dict): |
| 236 | + elif isinstance(value, Mapping): |
205 | 237 | _objects.append(id(value)) |
206 | 238 | yield from dump_dict(value, indent=indent, level=level + 1, _objects=_objects) |
207 | 239 | else: |
@@ -257,6 +289,20 @@ def updateusers(bot): |
257 | 289 | return "Updating all channel data" |
258 | 290 |
|
259 | 291 |
|
| 292 | +@hook.command(permissions=["botcontrol"], autohelp=False) |
| 293 | +def cleanusers(bot): |
| 294 | + clean_data(bot) |
| 295 | + gc.collect() |
| 296 | + return "Data cleaned." |
| 297 | + |
| 298 | + |
| 299 | +@hook.command(permissions=["botcontrol"], autohelp=False) |
| 300 | +def clearusers(bot): |
| 301 | + init_chan_data(bot, True) |
| 302 | + gc.collect() |
| 303 | + return "Data cleared." |
| 304 | + |
| 305 | + |
260 | 306 | @hook.irc_raw('JOIN') |
261 | 307 | def on_join(nick, user, host, conn, irc_paramlist): |
262 | 308 | chan, *other_data = irc_paramlist |
|
0 commit comments