<commit_before>const ROOM_NAME = "Shadow Ban Room";
var room = Rooms.get(toId(ROOM_NAME));
if (!room) {
	Rooms.global.addChatRoom(ROOM_NAME);
	room = Rooms.get(toId(ROOM_NAME));

	room.isPrivate = true;
	room.staffRoom = true;
	room.staffAutojoin = true;
	room.addedUsers = {};

	if (room.chatRoomData) {
		room.chatRoomData.isPrivate = true;
		room.chatRoomData.staffRoom = true;
		room.chatRoomData.staffAutojoin = true;
		room.chatRoomData.addedUsers = room.addedUsers;

		Rooms.global.writeChatRoomData();
	}
}
if (Object.size(room.addedUsers) > 0) {
	setImmediate(function () {
		room.add("||Loaded user list: " + Object.keys(room.addedUsers).sort().join(", "));
		room.update();
	});
}
exports.room = room;

function getAllAlts(user) {
	var targets = {};
	if (typeof user === 'string') {
		targets[toId(user)] = 1;
	} else {
		user.getAlts().concat(user.name).forEach(function (altName) {
			var alt = Users.get(altName);
			if (!alt.named) return;

			targets[toId(alt)] = 1;
			Object.keys(alt.prevNames).forEach(function (name) {
				targets[toId(name)] = 1;
			});
		});
	}
	return targets;
}

function intersectAndExclude(a, b) {
	var intersection = [];
	var exclusionA = [];
	var exclusionB = [];

	var ai = 0;
	var bi = 0;
	while (ai < a.length && bi < b.length) {
		var difference = a[ai].localeCompare(b[bi]);
		if (difference < 0) {
			exclusionA.push(a[ai]);
			++ai;
		} else if (difference > 0) {
			exclusionB.push(b[bi]);
			++bi;
		} else {
			intersection.push(a[ai]);
			++ai;
			++bi;
		}
	}

	Array.prototype.push.apply(exclusionA, a.slice(ai));
	Array.prototype.push.apply(exclusionB, b.slice(bi));
	return {intersection: intersection, exclusionA: exclusionA, exclusionB: exclusionB};
}

var checkBannedCache = {};
var checkBanned = exports.checkBanned = function (user) {
	var userId = toId(user);
	if (userId in checkBannedCache) return checkBannedCache[userId];
	console.log("Shadow ban cache miss:", userId);

	var targets = Object.keys(getAllAlts(user)).sort();
	var bannedUsers = Object.keys(room.addedUsers).sort();

	var matches = intersectAndExclude(targets, bannedUsers);
	var isBanned = matches.intersection.length !== 0;
	for (var t = 0; t < targets.length; ++t) {
		if (isBanned) room.addedUsers[targets[t]] = 1;
		checkBannedCache[targets[t]] = isBanned;
	}
	if (!isBanned) return false;

	if (matches.exclusionA.length > 0) {
		Rooms.global.writeChatRoomData();
		room.add("||Alts of " + matches.intersection[0] + " automatically added: " + matches.exclusionA.join(", "));
	}

	return true;
};

var addUser = exports.addUser = function (user) {
	var targets = getAllAlts(user);
	for (var u in targets) {
		if (room.addedUsers[u]) {
			delete targets[u];
		} else {
			room.addedUsers[u] = 1;<commit_msg>Fix alt checking in shadow ban<commit_after>const ROOM_NAME = "Shadow Ban Room";
var room = Rooms.get(toId(ROOM_NAME));
if (!room) {
	Rooms.global.addChatRoom(ROOM_NAME);
	room = Rooms.get(toId(ROOM_NAME));

	room.isPrivate = true;
	room.staffRoom = true;
	room.staffAutojoin = true;
	room.addedUsers = {};

	if (room.chatRoomData) {
		room.chatRoomData.isPrivate = true;
		room.chatRoomData.staffRoom = true;
		room.chatRoomData.staffAutojoin = true;
		room.chatRoomData.addedUsers = room.addedUsers;

		Rooms.global.writeChatRoomData();
	}
}
if (Object.size(room.addedUsers) > 0) {
	setImmediate(function () {
		room.add("||Loaded user list: " + Object.keys(room.addedUsers).sort().join(", "));
		room.update();
	});
}
exports.room = room;

function getAllAlts(user) {
	var targets = {};
	if (typeof user === 'string') {
		targets[toId(user)] = 1;
	} else {
		user.getAlts().concat(user.name).forEach(function (altName) {
			var alt = Users.get(altName);

			var id = toId(alt);
			if (id.slice(0, 5) !== 'guest') targets[toId(alt)] = 1;
			Object.keys(alt.prevNames).forEach(function (name) {
				var id = toId(name);
				if (id.slice(0, 5) !== 'guest') targets[toId(name)] = 1;
			});
		});
	}
	return targets;
}

function intersectAndExclude(a, b) {
	var intersection = [];
	var exclusionA = [];
	var exclusionB = [];

	var ai = 0;
	var bi = 0;
	while (ai < a.length && bi < b.length) {
		var difference = a[ai].localeCompare(b[bi]);
		if (difference < 0) {
			exclusionA.push(a[ai]);
			++ai;
		} else if (difference > 0) {
			exclusionB.push(b[bi]);
			++bi;
		} else {
			intersection.push(a[ai]);
			++ai;
			++bi;
		}
	}

	Array.prototype.push.apply(exclusionA, a.slice(ai));
	Array.prototype.push.apply(exclusionB, b.slice(bi));
	return {intersection: intersection, exclusionA: exclusionA, exclusionB: exclusionB};
}

var checkBannedCache = {};
var checkBanned = exports.checkBanned = function (user) {
	var userId = toId(user);
	if (userId in checkBannedCache) return checkBannedCache[userId];

	var targets = Object.keys(getAllAlts(user)).sort();
	var bannedUsers = Object.keys(room.addedUsers).sort();

	var matches = intersectAndExclude(targets, bannedUsers);
	var isBanned = matches.intersection.length !== 0;
	for (var t = 0; t < targets.length; ++t) {
		if (isBanned) room.addedUsers[targets[t]] = 1;
		checkBannedCache[targets[t]] = isBanned;
	}
	if (!isBanned) return false;

	if (matches.exclusionA.length > 0) {
		Rooms.global.writeChatRoomData();
		room.add("||Alts of " + matches.intersection[0] + " automatically added: " + matches.exclusionA.join(", "));
	}

	return true;
};

var addUser = exports.addUser = function (user) {
	var targets = getAllAlts(user);
	for (var u in targets) {
		if (room.addedUsers[u]) {
			delete targets[u];
		} else {
			room.addedUsers[u] = 1;
{'fraction_non_alphanumeric': 0.16865079365079366, 'fraction_numerical': 0.005772005772005772, 'mean_word_length': 4.226201696512724, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4594744', 'n_tokens_mistral': 2202, 'n_tokens_neox': 2026, 'n_words': 414}