Improvements to moderation handlers

This commit is contained in:
Ben 2019-12-02 23:33:38 +00:00
parent 9bc18b5b34
commit 576f79c8b7
3 changed files with 100 additions and 61 deletions

View File

@ -707,6 +707,7 @@ CREATE TABLE ban (
moderator_id INT DEFAULT NULL, moderator_id INT DEFAULT NULL,
reason SMALLINT NOT NULL, reason SMALLINT NOT NULL,
comment TEXT DEFAULT NULL, comment TEXT DEFAULT NULL,
message TEXT DEFAULT NULL,
PRIMARY KEY (penguin_id, issued, expires), PRIMARY KEY (penguin_id, issued, expires),
CONSTRAINT ban_ibfk_1 FOREIGN KEY (penguin_id) REFERENCES penguin (id) ON DELETE RESTRICT ON UPDATE CASCADE, CONSTRAINT ban_ibfk_1 FOREIGN KEY (penguin_id) REFERENCES penguin (id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT ban_ibfk_2 FOREIGN KEY (moderator_id) REFERENCES penguin (id) ON DELETE RESTRICT ON UPDATE CASCADE CONSTRAINT ban_ibfk_2 FOREIGN KEY (moderator_id) REFERENCES penguin (id) ON DELETE RESTRICT ON UPDATE CASCADE
@ -725,6 +726,7 @@ COMMENT ON COLUMN ban.expires IS 'Expiry date';
COMMENT ON COLUMN ban.moderator_id IS 'Moderator penguin ID'; COMMENT ON COLUMN ban.moderator_id IS 'Moderator penguin ID';
COMMENT ON COLUMN ban.reason IS 'Ban reason'; COMMENT ON COLUMN ban.reason IS 'Ban reason';
COMMENT ON COLUMN ban.comment IS 'Ban comment'; COMMENT ON COLUMN ban.comment IS 'Ban comment';
COMMENT ON COLUMN ban.message IS 'Banned for message';
DROP TABLE IF EXISTS warning; DROP TABLE IF EXISTS warning;
CREATE TABLE warning ( CREATE TABLE warning (

View File

@ -11,6 +11,7 @@ class Ban(db.Model):
moderator_id = db.Column(db.ForeignKey('penguin.id', ondelete='CASCADE', onupdate='CASCADE'), index=True) moderator_id = db.Column(db.ForeignKey('penguin.id', ondelete='CASCADE', onupdate='CASCADE'), index=True)
reason = db.Column(db.SmallInteger, nullable=False) reason = db.Column(db.SmallInteger, nullable=False)
comment = db.Column(db.Text) comment = db.Column(db.Text)
message = db.Column(db.Text)
class Warning(db.Model): class Warning(db.Model):
@ -19,6 +20,7 @@ class Warning(db.Model):
penguin_id = db.Column(db.ForeignKey('penguin.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True, penguin_id = db.Column(db.ForeignKey('penguin.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
nullable=False) nullable=False)
expires = db.Column(db.DateTime, primary_key=True, nullable=False) expires = db.Column(db.DateTime, primary_key=True, nullable=False)
issued = db.Column(db.DateTime, primary_key=True, nullable=False)
class Report(db.Model): class Report(db.Model):

View File

@ -2,59 +2,66 @@ from houdini import handlers
from houdini.data import db from houdini.data import db
from houdini.handlers import XTPacket from houdini.handlers import XTPacket
from houdini.data.moderator import Ban, Warning, Report from houdini.data.moderator import Ban, Warning, Report
from houdini.data.penguin import Penguin
from houdini.constants import ClientType
import datetime import datetime
@handlers.handler(XTPacket('o', 'k')) @handlers.handler(XTPacket('o', 'k'))
async def handle_kick_player(p, penguin_id: int): async def handle_kick_player(p, penguin_id: int):
if p.data.moderator: if p.moderator:
await moderator_kick(p, penguin_id) await moderator_kick(p, penguin_id)
@handlers.handler(XTPacket('o', 'b')) @handlers.handler(XTPacket('o', 'b'), client=ClientType.Legacy)
async def handle_ban_player(p, penguin_id: int, message: str): async def handle_ban_player(p, penguin_id: int, message: str):
if p.data.moderator: if p.moderator:
await moderator_ban(p, penguin_id, comment=message) await moderator_ban(p, penguin_id, comment=message)
@handlers.handler(XTPacket('o', 'm')) @handlers.handler(XTPacket('o', 'm'))
async def handle_mute_player(p, penguin_id: int): async def handle_mute_player(p, penguin_id: int):
if p.data.moderator: if p.moderator:
if penguin_id in p.server.penguins_by_id: if penguin_id in p.server.penguins_by_id:
player = p.server.penguins_by_id[penguin_id] player = p.server.penguins_by_id[penguin_id]
if not player.data.moderator: if not player.moderator:
player.muted = True player.muted = True
@handlers.handler(XTPacket('o', 'initban')) @handlers.handler(XTPacket('o', 'initban'), client=ClientType.Vanilla)
@handlers.player_attribute(moderator=True)
async def handle_init_ban(p, penguin_id: int, message: str): async def handle_init_ban(p, penguin_id: int, message: str):
if penguin_id in p.server.penguins_by_id and p.data.moderator: player = p.server.penguins_by_id[penguin_id] if penguin_id in p.server.penguins_by_id \
player = p.server.penguins_by_id[penguin_id] else await Penguin.get(penguin_id)
if not player.moderator:
number_bans = await db.select([db.func.count(Ban.penguin_id)]).where(
Ban.penguin_id == player.id).gino.scalar()
if not player.data.moderator: await p.send_xt('initban', penguin_id, 0, number_bans, message, player.username)
number_bans = await db.select([db.func.count(Ban.penguin_id)]).where(
Ban.penguin_id == player.data.id).gino.scalar()
await p.send_xt('initban', penguin_id, 0, number_bans, message, player.data.username)
@handlers.handler(XTPacket('o', 'ban')) @handlers.handler(XTPacket('o', 'ban'), client=ClientType.Vanilla)
@handlers.player_attribute(moderator=True)
async def handle_moderator_ban(p, penguin_id: int, ban_type: int, reason: int, duration: int, message: str, notes: str): async def handle_moderator_ban(p, penguin_id: int, ban_type: int, reason: int, duration: int, message: str, notes: str):
if p.data.moderator: player = p.server.penguins_by_id[penguin_id] if penguin_id in p.server.penguins_by_id \
else await Penguin.get(penguin_id)
if not player.moderator:
date_issued = datetime.datetime.now()
date_expires = date_issued + datetime.timedelta(hours=duration)
if duration == 0:
await player.update(permaban=True).apply()
await Ban.create(penguin_id=player.id, issued=date_issued, expires=date_expires,
moderator_id=p.id, reason=reason, comment=notes, message=message)
if penguin_id in p.server.penguins_by_id: if penguin_id in p.server.penguins_by_id:
player = p.server.penguins_by_id[penguin_id] if player.is_vanilla_client:
if not player.data.moderator:
date_issued = datetime.datetime.now()
date_expires = date_issued + datetime.timedelta(hours=duration)
if duration == 0:
await player.data.update(permaban=True).apply()
await Ban.create(penguin_id=player.data.id, issued=date_issued, expires=date_expires,
moderator_id=p.data.id, reason=reason, comment=notes)
await player.send_xt('ban', ban_type, reason, duration, notes) await player.send_xt('ban', ban_type, reason, duration, notes)
await player.close() else:
await player.send_error(610, message)
await player.close()
@handlers.handler(XTPacket('m', 'r')) @handlers.handler(XTPacket('m', 'r'))
@ -64,52 +71,80 @@ async def handle_report(p, penguin_id: int, reason: int = 0):
date=date_now, server_id=p.server.config.id, room_id=p.room.id) date=date_now, server_id=p.server.config.id, room_id=p.room.id)
@handlers.handler(XTPacket('o', 'moderatormessage')) @handlers.handler(XTPacket('o', 'moderatormessage'), client=ClientType.Vanilla)
async def handle_moderator_message(p, type: int, penguin_id: int): @handlers.player_attribute(moderator=True)
if p.data.moderator: async def handle_moderator_message(p, warning_type: int, penguin_id: int):
player = p.server.penguins_by_id[penguin_id] if penguin_id in p.server.penguins_by_id \
else await Penguin.get(penguin_id)
date_issued = datetime.datetime.now()
date_expires = date_issued + datetime.timedelta(hours=48)
warning_count = await db.select([db.func.count(Warning.expires)]).where(
(Warning.penguin_id == player.id) & (Warning.expires >= date_issued)).gino.scalar()
if warning_count >= 3:
return await moderator_ban(p, player.id, message='Exceeded warning limit')
await player.send_xt('moderatormessage', warning_type)
await Warning.create(penguin_id=player.id, issued=date_issued, expires=date_expires)
async def cheat_kick(p, penguin_id):
if penguin_id in p.server.penguins_by_id:
await p.server.penguins_by_id[penguin_id].send_error_and_disconnect(800)
async def cheat_ban(p, penguin_id, hours=24, comment=''):
if penguin_id in p.server.penguins_by_id:
player = p.server.penguins_by_id[penguin_id]
number_bans = await db.select([db.func.count(Ban.penguin_id)]).where(
Ban.penguin_id == player.id).gino.scalar()
date_issued = datetime.datetime.now()
date_expires = date_issued + datetime.timedelta(hours=hours)
if number_bans >= 3:
await player.update(permaban=True).apply()
await Ban.create(penguin_id=player.id, issued=date_issued, expires=date_expires,
moderator_id=p.id, reason=1, comment=comment, message='Cheat ban')
if penguin_id in p.server.penguins_by_id: if penguin_id in p.server.penguins_by_id:
player = p.server.penguins_by_id[penguin_id] await player.send_error_and_disconnect(611, comment)
date_issued = datetime.datetime.now()
date_expires = date_issued + datetime.timedelta(hours=48)
warning_count = await db.select([db.func.count(Warning.expires)]).where(
(Warning.penguin_id == player.data.id) & (Warning.expires >= date_issued)).gino.scalar()
if warning_count >= 3:
return await moderator_ban(p, player.data.id, comment='Exceeded warning limit')
await player.send_xt('moderatormessage', type)
await Warning.create(penguin_id=player.data.id, expires=date_expires)
async def moderator_kick(p, penguin_id): async def moderator_kick(p, penguin_id):
if penguin_id in p.server.penguins_by_id and p.data.moderator: if penguin_id in p.server.penguins_by_id:
player = p.server.penguins_by_id[penguin_id] player = p.server.penguins_by_id[penguin_id]
if not player.data.moderator: if not player.moderator:
for penguin in p.server.penguins_by_id.values(): for penguin in p.server.penguins_by_id.values():
if penguin.data.moderator: if penguin.moderator:
await penguin.send_xt('ma', 'k', penguin_id, player.data.username) await penguin.send_xt('ma', 'k', penguin_id, player.username)
await player.send_error_and_disconnect(5) await player.send_error_and_disconnect(5)
async def moderator_ban(p, penguin_id, hours=24, comment=''): async def moderator_ban(p, penguin_id, hours=24, comment='', message=''):
if penguin_id in p.server.penguins_by_id and p.data.moderator: player = p.server.penguins_by_id[penguin_id] if penguin_id in p.server.penguins_by_id \
player = p.server.penguins_by_id[penguin_id] else await Penguin.get(penguin_id)
if not player.data.moderator: if not player.moderator:
for penguin in p.server.penguins_by_id.values(): for penguin in p.server.penguins_by_id.values():
if penguin.data.moderator: if penguin.moderator:
await penguin.send_xt('ma', 'b', penguin_id, player.data.username) await penguin.send_xt('ma', 'b', penguin_id, player.username)
number_bans = await db.select([db.func.count(Ban.penguin_id)]).where( number_bans = await db.select([db.func.count(Ban.penguin_id)]).where(
Ban.penguin_id == player.data.id).gino.scalar() Ban.penguin_id == player.id).gino.scalar()
date_issued = datetime.datetime.now() date_issued = datetime.datetime.now()
date_expires = date_issued + datetime.timedelta(hours=hours) date_expires = date_issued + datetime.timedelta(hours=hours)
if number_bans >= 3: if number_bans >= 3:
await player.data.update(permaban=True).apply() await player.update(permaban=True).apply()
await Ban.create(penguin_id=player.data.id, issued=date_issued, expires=date_expires, await Ban.create(penguin_id=player.id, issued=date_issued, expires=date_expires,
moderator_id=p.data.id, reason=1, comment=comment) moderator_id=p.id, reason=2, comment=comment, message=message)
await player.send_error_and_disconnect(610, comment) if penguin_id in p.server.penguins_by_id:
await player.close() if player.is_vanilla_client:
await player.send_xt('ban', 612, 2, hours, comment)
else:
await player.send_error_and_disconnect(610, comment)