Skip to content

Commit

Permalink
Merge pull request #111 from ZeruLight/feature/moderation
Browse files Browse the repository at this point in the history
feature/moderation
  • Loading branch information
sekaiwish authored Jan 11, 2024
2 parents af29ee6 + 2135c44 commit 4fbfd56
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 10 deletions.
54 changes: 54 additions & 0 deletions common/mhfcid/mhfcid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package mhfcid

import (
"math"
)

// ConvertCID converts a MHF Character ID String to integer
//
// Banned characters: 0, I, O, S
func ConvertCID(ID string) (r uint32) {
if len(ID) != 6 {
return
}

m := map[rune]uint32{
'1': 0,
'2': 1,
'3': 2,
'4': 3,
'5': 4,
'6': 5,
'7': 6,
'8': 7,
'9': 8,
'A': 9,
'B': 10,
'C': 11,
'D': 12,
'E': 13,
'F': 14,
'G': 15,
'H': 16,
'J': 17,
'K': 18,
'L': 19,
'M': 20,
'N': 21,
'P': 22,
'Q': 23,
'R': 24,
'T': 25,
'U': 26,
'V': 27,
'W': 28,
'X': 29,
'Y': 30,
'Z': 31,
}

for i, c := range ID {
r += m[c] * uint32(math.Pow(32, float64(i)))
}
return
}
5 changes: 5 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@
"Enabled": true,
"Description": "Generate a token to link your Discord account",
"Prefix": "discord"
}, {
"Name": "Ban",
"Enabled": false,
"Description": "Ban/Temp Ban a user",
"Prefix": "ban"
}
],
"Courses": [
Expand Down
12 changes: 12 additions & 0 deletions patch-schema/op-accounts.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
BEGIN;

ALTER TABLE IF EXISTS public.users ADD COLUMN op boolean;

CREATE TABLE public.bans
(
user_id integer NOT NULL,
expires timestamp with time zone,
PRIMARY KEY (user_id)
);

END;
77 changes: 67 additions & 10 deletions server/channelserver/handlers_cast_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/rand"
"encoding/hex"
"erupe-ce/common/byteframe"
"erupe-ce/common/mhfcid"
"erupe-ce/common/mhfcourse"
"erupe-ce/common/token"
"erupe-ce/config"
Expand Down Expand Up @@ -87,8 +88,64 @@ func sendServerChatMessage(s *Session, message string) {
func parseChatCommand(s *Session, command string) {
args := strings.Split(command[len(s.server.erupeConfig.CommandPrefix):], " ")
switch args[0] {
case commands["Ban"].Prefix:
if s.isOp() {
if len(args) > 1 {
var expiry time.Time
if len(args) > 2 {
var length int
var unit string
n, err := fmt.Sscanf(args[2], `%d%s`, &length, &unit)
if err == nil && n == 2 {
switch unit {
case "s", "second", "seconds":
expiry = time.Now().Add(time.Duration(length) * time.Second)
case "m", "mi", "minute", "minutes":
expiry = time.Now().Add(time.Duration(length) * time.Minute)
case "h", "hour", "hours":
expiry = time.Now().Add(time.Duration(length) * time.Hour)
case "d", "day", "days":
expiry = time.Now().Add(time.Duration(length) * time.Hour * 24)
case "mo", "month", "months":
expiry = time.Now().Add(time.Duration(length) * time.Hour * 24 * 30)
case "y", "year", "years":
expiry = time.Now().Add(time.Duration(length) * time.Hour * 24 * 365)
}
} else {
sendServerChatMessage(s, s.server.i18n.commands.ban.error)
return
}
}
cid := mhfcid.ConvertCID(args[1])
if cid > 0 {
var uid uint32
var uname string
err := s.server.db.QueryRow(`SELECT id, username FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, cid).Scan(&uid, &uname)
if err == nil {
if expiry.IsZero() {
s.server.db.Exec(`INSERT INTO bans VALUES ($1)
ON CONFLICT (user_id) DO UPDATE SET expires=NULL`, uid)
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname))
} else {
s.server.db.Exec(`INSERT INTO bans VALUES ($1, $2)
ON CONFLICT (user_id) DO UPDATE SET expires=$2`, uid, expiry)
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname)+fmt.Sprintf(s.server.i18n.commands.ban.length, expiry.Format(time.DateTime)))
}
s.server.DisconnectUser(uid)
} else {
sendServerChatMessage(s, s.server.i18n.commands.ban.noUser)
}
} else {
sendServerChatMessage(s, s.server.i18n.commands.ban.invalid)
}
} else {
sendServerChatMessage(s, s.server.i18n.commands.ban.error)
}
} else {
sendServerChatMessage(s, s.server.i18n.commands.noOp)
}
case commands["PSN"].Prefix:
if commands["PSN"].Enabled {
if commands["PSN"].Enabled || s.isOp() {
if len(args) > 1 {
var exists int
s.server.db.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, args[1]).Scan(&exists)
Expand All @@ -107,7 +164,7 @@ func parseChatCommand(s *Session, command string) {
sendDisabledCommandMessage(s, commands["PSN"])
}
case commands["Reload"].Prefix:
if commands["Reload"].Enabled {
if commands["Reload"].Enabled || s.isOp() {
sendServerChatMessage(s, s.server.i18n.commands.reload)
var temp mhfpacket.MHFPacket
deleteNotif := byteframe.NewByteFrame()
Expand Down Expand Up @@ -168,7 +225,7 @@ func parseChatCommand(s *Session, command string) {
sendDisabledCommandMessage(s, commands["Reload"])
}
case commands["KeyQuest"].Prefix:
if commands["KeyQuest"].Enabled {
if commands["KeyQuest"].Enabled || s.isOp() {
if s.server.erupeConfig.RealClientMode < _config.G10 {
sendServerChatMessage(s, s.server.i18n.commands.kqf.version)
} else {
Expand All @@ -191,7 +248,7 @@ func parseChatCommand(s *Session, command string) {
sendDisabledCommandMessage(s, commands["KeyQuest"])
}
case commands["Rights"].Prefix:
if commands["Rights"].Enabled {
if commands["Rights"].Enabled || s.isOp() {
if len(args) > 1 {
v, _ := strconv.Atoi(args[1])
_, err := s.server.db.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", v, s.charID)
Expand All @@ -207,7 +264,7 @@ func parseChatCommand(s *Session, command string) {
sendDisabledCommandMessage(s, commands["Rights"])
}
case commands["Course"].Prefix:
if commands["Course"].Enabled {
if commands["Course"].Enabled || s.isOp() {
if len(args) > 1 {
for _, course := range mhfcourse.Courses() {
for _, alias := range course.Aliases() {
Expand Down Expand Up @@ -250,7 +307,7 @@ func parseChatCommand(s *Session, command string) {
sendDisabledCommandMessage(s, commands["Course"])
}
case commands["Raviente"].Prefix:
if commands["Raviente"].Enabled {
if commands["Raviente"].Enabled || s.isOp() {
if len(args) > 1 {
if s.server.getRaviSemaphore() != nil {
switch args[1] {
Expand Down Expand Up @@ -301,7 +358,7 @@ func parseChatCommand(s *Session, command string) {
sendDisabledCommandMessage(s, commands["Raviente"])
}
case commands["Teleport"].Prefix:
if commands["Teleport"].Enabled {
if commands["Teleport"].Enabled || s.isOp() {
if len(args) > 2 {
x, _ := strconv.ParseInt(args[1], 10, 16)
y, _ := strconv.ParseInt(args[2], 10, 16)
Expand All @@ -324,7 +381,7 @@ func parseChatCommand(s *Session, command string) {
sendDisabledCommandMessage(s, commands["Teleport"])
}
case commands["Discord"].Prefix:
if commands["Discord"].Enabled {
if commands["Discord"].Enabled || s.isOp() {
var _token string
err := s.server.db.QueryRow(`SELECT discord_token FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&_token)
if err != nil {
Expand All @@ -338,9 +395,9 @@ func parseChatCommand(s *Session, command string) {
sendDisabledCommandMessage(s, commands["Discord"])
}
case commands["Help"].Prefix:
if commands["Help"].Enabled {
if commands["Help"].Enabled || s.isOp() {
for _, command := range commands {
if command.Enabled {
if command.Enabled || s.isOp() {
sendServerChatMessage(s, fmt.Sprintf("%s%s: %s", s.server.erupeConfig.CommandPrefix, command.Prefix, command.Description))
}
}
Expand Down
20 changes: 20 additions & 0 deletions server/channelserver/sys_channel_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,26 @@ func (s *Server) FindSessionByCharID(charID uint32) *Session {
return nil
}

func (s *Server) DisconnectUser(uid uint32) {
var cid uint32
var cids []uint32
rows, _ := s.db.Query(`SELECT id FROM characters WHERE user_id=$1`, uid)
for rows.Next() {
rows.Scan(&cid)
cids = append(cids, cid)
}
for _, c := range s.Channels {
for _, session := range c.sessions {
for _, cid := range cids {
if session.charID == cid {
session.rawConn.Close()
break
}
}
}
}
}

func (s *Server) FindObjectByChar(charID uint32) *Object {
s.stagesLock.RLock()
defer s.stagesLock.RUnlock()
Expand Down
22 changes: 22 additions & 0 deletions server/channelserver/sys_language.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type i18n struct {
reset string
}
commands struct {
noOp string
disabled string
reload string
kqf struct {
Expand Down Expand Up @@ -38,6 +39,13 @@ type i18n struct {
discord struct {
success string
}
ban struct {
success string
noUser string
invalid string
error string
length string
}
ravi struct {
noCommand string
start struct {
Expand Down Expand Up @@ -95,6 +103,7 @@ func getLangStrings(s *Server) i18n {
i.language = "日本語"
i.cafe.reset = "%d/%dにリセット"

i.commands.noOp = "You don't have permission to use this command"
i.commands.disabled = "%sのコマンドは無効です"
i.commands.reload = "リロードします"
i.commands.kqf.get = "現在のキークエストフラグ:%x"
Expand All @@ -115,6 +124,12 @@ func getLangStrings(s *Server) i18n {

i.commands.discord.success = "あなたのDiscordトークン:%s"

i.commands.ban.noUser = "Could not find user"
i.commands.ban.success = "Successfully banned %s"
i.commands.ban.invalid = "Invalid Character ID"
i.commands.ban.error = "Error in command. Format: %s <id> [length]"
i.commands.ban.length = " until %s"

i.commands.ravi.noCommand = "ラヴィコマンドが指定されていません"
i.commands.ravi.start.success = "大討伐を開始します"
i.commands.ravi.start.error = "大討伐は既に開催されています"
Expand Down Expand Up @@ -150,6 +165,7 @@ func getLangStrings(s *Server) i18n {
i.language = "English"
i.cafe.reset = "Resets on %d/%d"

i.commands.noOp = "You don't have permission to use this command"
i.commands.disabled = "%s command is disabled"
i.commands.reload = "Reloading players..."
i.commands.kqf.get = "KQF: %x"
Expand All @@ -170,6 +186,12 @@ func getLangStrings(s *Server) i18n {

i.commands.discord.success = "Your Discord token: %s"

i.commands.ban.noUser = "Could not find user"
i.commands.ban.success = "Successfully banned %s"
i.commands.ban.invalid = "Invalid Character ID"
i.commands.ban.error = "Error in command. Format: %s <id> [length]"
i.commands.ban.length = " until %s"

i.commands.ravi.noCommand = "No Raviente command specified!"
i.commands.ravi.start.success = "The Great Slaying will begin in a moment"
i.commands.ravi.start.error = "The Great Slaying has already begun!"
Expand Down
9 changes: 9 additions & 0 deletions server/channelserver/sys_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,12 @@ func (s *Session) NextObjectID() uint32 {
bf.Seek(0, 0)
return bf.ReadUint32()
}

func (s *Session) isOp() bool {
var op bool
err := s.server.db.QueryRow(`SELECT op FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&op)
if err == nil && op {
return true
}
return false
}
9 changes: 9 additions & 0 deletions server/signserver/dbutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,15 @@ func (s *Server) validateLogin(user string, pass string) (uint32, RespID) {
return 0, SIGN_EABORT
} else {
if bcrypt.CompareHashAndPassword([]byte(passDB), []byte(pass)) == nil {
var bans int
err = s.db.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires IS NULL`, uid).Scan(&bans)
if err == nil && bans > 0 {
return uid, SIGN_EELIMINATE
}
err = s.db.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires > now()`, uid).Scan(&bans)
if err == nil && bans > 0 {
return uid, SIGN_ESUSPEND
}
return uid, SIGN_SUCCESS
}
return 0, SIGN_EPASS
Expand Down

0 comments on commit 4fbfd56

Please sign in to comment.