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
houdini.sql
houdini
data
handlers/play

@ -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 (

@ -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):

@ -2,58 +2,65 @@ 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:
if not player.data.moderator:
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()
await p.send_xt('initban', penguin_id, 0, number_bans, message, player.data.username) await p.send_xt('initban', penguin_id, 0, number_bans, message, player.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 \
if penguin_id in p.server.penguins_by_id: else await Penguin.get(penguin_id)
player = p.server.penguins_by_id[penguin_id] if not player.moderator:
if not player.data.moderator:
date_issued = datetime.datetime.now() date_issued = datetime.datetime.now()
date_expires = date_issued + datetime.timedelta(hours=duration) date_expires = date_issued + datetime.timedelta(hours=duration)
if duration == 0: if duration == 0:
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=reason, comment=notes) moderator_id=p.id, reason=reason, comment=notes, message=message)
if penguin_id in p.server.penguins_by_id:
if player.is_vanilla_client:
await player.send_xt('ban', ban_type, reason, duration, notes) await player.send_xt('ban', ban_type, reason, duration, notes)
else:
await player.send_error(610, message)
await player.close() await player.close()
@ -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):
if penguin_id in p.server.penguins_by_id: 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)
date_issued = datetime.datetime.now() date_issued = datetime.datetime.now()
date_expires = date_issued + datetime.timedelta(hours=48) date_expires = date_issued + datetime.timedelta(hours=48)
warning_count = await db.select([db.func.count(Warning.expires)]).where( warning_count = await db.select([db.func.count(Warning.expires)]).where(
(Warning.penguin_id == player.data.id) & (Warning.expires >= date_issued)).gino.scalar() (Warning.penguin_id == player.id) & (Warning.expires >= date_issued)).gino.scalar()
if warning_count >= 3: if warning_count >= 3:
return await moderator_ban(p, player.data.id, comment='Exceeded warning limit') return await moderator_ban(p, player.id, message='Exceeded warning limit')
await player.send_xt('moderatormessage', type) await player.send_xt('moderatormessage', warning_type)
await Warning.create(penguin_id=player.data.id, expires=date_expires) await Warning.create(penguin_id=player.id, issued=date_issued, expires=date_expires)
async def moderator_kick(p, penguin_id): async def cheat_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:
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] player = p.server.penguins_by_id[penguin_id]
if not player.data.moderator:
for penguin in p.server.penguins_by_id.values():
if penguin.data.moderator:
await penguin.send_xt('ma', 'k', penguin_id, player.data.username)
await player.send_error_and_disconnect(5)
async def moderator_ban(p, penguin_id, hours=24, comment=''):
if penguin_id in p.server.penguins_by_id and p.data.moderator:
player = p.server.penguins_by_id[penguin_id]
if not player.data.moderator:
for penguin in p.server.penguins_by_id.values():
if penguin.data.moderator:
await penguin.send_xt('ma', 'b', penguin_id, player.data.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=1, comment=comment, message='Cheat ban')
if penguin_id in p.server.penguins_by_id:
await player.send_error_and_disconnect(611, comment)
async def moderator_kick(p, penguin_id):
if penguin_id in p.server.penguins_by_id:
player = p.server.penguins_by_id[penguin_id]
if not player.moderator:
for penguin in p.server.penguins_by_id.values():
if penguin.moderator:
await penguin.send_xt('ma', 'k', penguin_id, player.username)
await player.send_error_and_disconnect(5)
async def moderator_ban(p, penguin_id, hours=24, comment='', message=''):
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:
for penguin in p.server.penguins_by_id.values():
if penguin.moderator:
await penguin.send_xt('ma', 'b', penguin_id, player.username)
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=2, comment=comment, message=message)
if penguin_id in p.server.penguins_by_id:
if player.is_vanilla_client:
await player.send_xt('ban', 612, 2, hours, comment)
else:
await player.send_error_and_disconnect(610, comment) await player.send_error_and_disconnect(610, comment)
await player.close()