From fb3e86f42932a7f2fa4762e1c73a27db9dbb2947 Mon Sep 17 00:00:00 2001 From: Houmgaor Date: Tue, 17 Feb 2026 17:44:35 +0100 Subject: [PATCH] fix: handle Query/QueryRow/transaction errors in channel server handlers Add error checking and logging for ~25 database call sites that were silently dropping errors, preventing resource leaks (unclosed rows), nil pointer panics, and silent data corruption in festa transactions. --- server/channelserver/handlers_cast_binary.go | 12 +- server/channelserver/handlers_diva.go | 12 +- server/channelserver/handlers_festa.go | 140 ++++++++++++------- server/channelserver/handlers_guild.go | 12 +- server/channelserver/handlers_house.go | 14 +- server/channelserver/handlers_mercenary.go | 26 ++-- server/channelserver/handlers_rengoku.go | 23 +-- server/channelserver/handlers_tower.go | 15 +- server/channelserver/sys_channel_server.go | 13 +- 9 files changed, 174 insertions(+), 93 deletions(-) diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index 752dca48b..d6d35cf26 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -147,7 +147,9 @@ func parseChatCommand(s *Session, command string) { case commands["Timer"].Prefix: if commands["Timer"].Enabled || s.isOp() { var state bool - s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&state) + if err := s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&state); err != nil { + s.logger.Error("Failed to get timer state", zap.Error(err)) + } s.server.db.Exec(`UPDATE users u SET timer=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, !state, s.charID) if state { sendServerChatMessage(s, s.server.i18n.commands.timer.disabled) @@ -161,7 +163,9 @@ func parseChatCommand(s *Session, command string) { 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) + if err := s.server.db.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, args[1]).Scan(&exists); err != nil { + s.logger.Error("Failed to check PSN ID existence", zap.Error(err)) + } if exists == 0 { _, err := s.server.db.Exec(`UPDATE users u SET psn_id=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, args[1], s.charID) if err == nil { @@ -435,7 +439,9 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { if pkt.BroadcastType == 0x03 && pkt.MessageType == 0x03 && len(pkt.RawDataPayload) == 0x10 { if tmp.ReadUint16() == 0x0002 && tmp.ReadUint8() == 0x18 { var timer bool - s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&timer) + if err := s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&timer); err != nil { + s.logger.Error("Failed to get timer setting", zap.Error(err)) + } if timer { _ = tmp.ReadBytes(9) tmp.SetLE() diff --git a/server/channelserver/handlers_diva.go b/server/channelserver/handlers_diva.go index 7f5b33992..8a96fb143 100644 --- a/server/channelserver/handlers_diva.go +++ b/server/channelserver/handlers_diva.go @@ -8,6 +8,7 @@ import ( "erupe-ce/common/byteframe" "erupe-ce/network/mhfpacket" + "go.uber.org/zap" ) func cleanupDiva(s *Session) { @@ -64,9 +65,14 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() id, start := uint32(0xCAFEBEEF), uint32(0) - rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='diva'") - for rows.Next() { - rows.Scan(&id, &start) + rows, err := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='diva'") + if err != nil { + s.logger.Error("Failed to query diva schedule", zap.Error(err)) + } else { + defer rows.Close() + for rows.Next() { + rows.Scan(&id, &start) + } } var timestamps []uint32 diff --git a/server/channelserver/handlers_festa.go b/server/channelserver/handlers_festa.go index d5cba4d90..7139d2b9f 100644 --- a/server/channelserver/handlers_festa.go +++ b/server/channelserver/handlers_festa.go @@ -6,6 +6,7 @@ import ( "erupe-ce/common/token" _config "erupe-ce/config" "erupe-ce/network/mhfpacket" + "go.uber.org/zap" "sort" "time" ) @@ -19,7 +20,9 @@ func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadMezfesData) var data []byte - s.server.db.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.charID).Scan(&data) + if err := s.server.db.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.charID).Scan(&data); err != nil { + s.logger.Error("Failed to load mezfes data", zap.Error(err)) + } bf := byteframe.NewByteFrame() if len(data) > 0 { bf.WriteBytes(data) @@ -168,9 +171,14 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() id, start := uint32(0xDEADBEEF), uint32(0) - rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='festa'") - for rows.Next() { - rows.Scan(&id, &start) + rows, err := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='festa'") + if err != nil { + s.logger.Error("Failed to query festa schedule", zap.Error(err)) + } else { + defer rows.Close() + for rows.Next() { + rows.Scan(&id, &start) + } } var timestamps []uint32 @@ -190,8 +198,12 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { } var blueSouls, redSouls uint32 - s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'blue'`).Scan(&blueSouls) - s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'red'`).Scan(&redSouls) + if err := s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'blue'`).Scan(&blueSouls); err != nil { + s.logger.Error("Failed to get blue souls", zap.Error(err)) + } + if err := s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'red'`).Scan(&redSouls); err != nil { + s.logger.Error("Failed to get red souls", zap.Error(err)) + } bf.WriteUint32(id) for _, timestamp := range timestamps { @@ -206,7 +218,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { var trials []FestaTrial var trial FestaTrial - rows, _ = s.server.db.Queryx(`SELECT ft.*, + rows, err = s.server.db.Queryx(`SELECT ft.*, COALESCE(CASE WHEN COUNT(gc.id) FILTER (WHERE fr.team = 'blue' AND gc.trial_vote = ft.id) > COUNT(gc.id) FILTER (WHERE fr.team = 'red' AND gc.trial_vote = ft.id) @@ -219,12 +231,16 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { LEFT JOIN public.guild_characters gc ON ft.id = gc.trial_vote LEFT JOIN public.festa_registrations fr ON gc.guild_id = fr.guild_id GROUP BY ft.id`) - for rows.Next() { - err := rows.StructScan(&trial) - if err != nil { - continue + if err != nil { + s.logger.Error("Failed to query festa trials", zap.Error(err)) + } else { + defer rows.Close() + for rows.Next() { + if err := rows.StructScan(&trial); err != nil { + continue + } + trials = append(trials, trial) } - trials = append(trials, trial) } bf.WriteUint16(uint16(len(trials))) for _, trial := range trials { @@ -300,7 +316,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { var guildID uint32 var guildName string var guildTeam = FestivalColorNone - s.server.db.QueryRow(` + if err := s.server.db.QueryRow(` SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _ FROM festa_submissions fs LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id @@ -308,7 +324,9 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { WHERE fs.trial_type = $1 GROUP BY fs.guild_id, g.name, fr.team ORDER BY _ DESC LIMIT 1 - `, i+1).Scan(&guildID, &guildName, &guildTeam, &temp) + `, i+1).Scan(&guildID, &guildName, &guildTeam, &temp); err != nil { + s.logger.Error("Failed to get festa trial ranking", zap.Error(err)) + } bf.WriteUint32(guildID) bf.WriteUint16(i + 1) bf.WriteInt16(FestivalColorCodes[guildTeam]) @@ -320,7 +338,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { var guildName string var guildTeam = FestivalColorNone offset := 86400 * uint32(i) - s.server.db.QueryRow(` + if err := s.server.db.QueryRow(` SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _ FROM festa_submissions fs LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id @@ -328,7 +346,9 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { WHERE EXTRACT(EPOCH FROM fs.timestamp)::int > $1 AND EXTRACT(EPOCH FROM fs.timestamp)::int < $2 GROUP BY fs.guild_id, g.name, fr.team ORDER BY _ DESC LIMIT 1 - `, timestamps[1]+offset, timestamps[1]+offset+86400).Scan(&guildID, &guildName, &guildTeam, &temp) + `, timestamps[1]+offset, timestamps[1]+offset+86400).Scan(&guildID, &guildName, &guildTeam, &temp); err != nil { + s.logger.Error("Failed to get festa daily ranking", zap.Error(err)) + } bf.WriteUint32(guildID) bf.WriteUint16(i + 1) bf.WriteInt16(FestivalColorCodes[guildTeam]) @@ -366,7 +386,9 @@ func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) { return } var souls, exists uint32 - s.server.db.QueryRow(`SELECT COALESCE((SELECT SUM(souls) FROM festa_submissions WHERE character_id=$1), 0)`, s.charID).Scan(&souls) + if err := s.server.db.QueryRow(`SELECT COALESCE((SELECT SUM(souls) FROM festa_submissions WHERE character_id=$1), 0)`, s.charID).Scan(&souls); err != nil { + s.logger.Error("Failed to get festa user souls", zap.Error(err)) + } err = s.server.db.QueryRow("SELECT prize_id FROM festa_prizes_accepted WHERE prize_id=0 AND character_id=$1", s.charID).Scan(&exists) bf := byteframe.NewByteFrame() bf.WriteUint32(souls) @@ -469,14 +491,22 @@ func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfChargeFesta) - tx, _ := s.server.db.Begin() - for i := range pkt.Souls { - if pkt.Souls[i] == 0 { - continue + tx, err := s.server.db.Begin() + if err != nil { + s.logger.Error("Failed to begin festa submission transaction", zap.Error(err)) + } else { + for i := range pkt.Souls { + if pkt.Souls[i] == 0 { + continue + } + if _, err := tx.Exec(`INSERT INTO festa_submissions VALUES ($1, $2, $3, $4, now())`, s.charID, pkt.GuildID, i, pkt.Souls[i]); err != nil { + s.logger.Error("Failed to insert festa submission", zap.Error(err)) + } + } + if err := tx.Commit(); err != nil { + s.logger.Error("Failed to commit festa submissions", zap.Error(err)) } - _, _ = tx.Exec(`INSERT INTO festa_submissions VALUES ($1, $2, $3, $4, now())`, s.charID, pkt.GuildID, i, pkt.Souls[i]) } - _ = tx.Commit() doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } @@ -509,23 +539,27 @@ type Prize struct { func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateFestaPersonalPrize) - rows, _ := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='personal'`, s.charID) + rows, err := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='personal'`, s.charID) var count uint32 prizeData := byteframe.NewByteFrame() - for rows.Next() { - prize := &Prize{} - err := rows.StructScan(&prize) - if err != nil { - continue + if err != nil { + s.logger.Error("Failed to query festa personal prizes", zap.Error(err)) + } else { + defer rows.Close() + for rows.Next() { + prize := &Prize{} + if err := rows.StructScan(&prize); err != nil { + continue + } + count++ + prizeData.WriteUint32(prize.ID) + prizeData.WriteUint32(prize.Tier) + prizeData.WriteUint32(prize.SoulsReq) + prizeData.WriteUint32(7) // Unk + prizeData.WriteUint32(prize.ItemID) + prizeData.WriteUint32(prize.NumItem) + prizeData.WriteBool(prize.Claimed > 0) } - count++ - prizeData.WriteUint32(prize.ID) - prizeData.WriteUint32(prize.Tier) - prizeData.WriteUint32(prize.SoulsReq) - prizeData.WriteUint32(7) // Unk - prizeData.WriteUint32(prize.ItemID) - prizeData.WriteUint32(prize.NumItem) - prizeData.WriteBool(prize.Claimed > 0) } bf := byteframe.NewByteFrame() bf.WriteUint32(count) @@ -535,23 +569,27 @@ func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) func handleMsgMhfEnumerateFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateFestaIntermediatePrize) - rows, _ := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='guild'`, s.charID) + rows, err := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='guild'`, s.charID) var count uint32 prizeData := byteframe.NewByteFrame() - for rows.Next() { - prize := &Prize{} - err := rows.StructScan(&prize) - if err != nil { - continue + if err != nil { + s.logger.Error("Failed to query festa intermediate prizes", zap.Error(err)) + } else { + defer rows.Close() + for rows.Next() { + prize := &Prize{} + if err := rows.StructScan(&prize); err != nil { + continue + } + count++ + prizeData.WriteUint32(prize.ID) + prizeData.WriteUint32(prize.Tier) + prizeData.WriteUint32(prize.SoulsReq) + prizeData.WriteUint32(7) // Unk + prizeData.WriteUint32(prize.ItemID) + prizeData.WriteUint32(prize.NumItem) + prizeData.WriteBool(prize.Claimed > 0) } - count++ - prizeData.WriteUint32(prize.ID) - prizeData.WriteUint32(prize.Tier) - prizeData.WriteUint32(prize.SoulsReq) - prizeData.WriteUint32(7) // Unk - prizeData.WriteUint32(prize.ItemID) - prizeData.WriteUint32(prize.NumItem) - prizeData.WriteBool(prize.Claimed > 0) } bf := byteframe.NewByteFrame() bf.WriteUint32(count) diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index 2e04b70b2..31cc2d060 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -763,7 +763,9 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { case mhfpacket.OperateGuildEventExchange: rp := uint16(pkt.Data1.ReadUint32()) var balance uint32 - s.server.db.QueryRow(`UPDATE guilds SET event_rp=event_rp-$1 WHERE id=$2 RETURNING event_rp`, rp, guild.ID).Scan(&balance) + if err := s.server.db.QueryRow(`UPDATE guilds SET event_rp=event_rp-$1 WHERE id=$2 RETURNING event_rp`, rp, guild.ID).Scan(&balance); err != nil { + s.logger.Error("Failed to exchange guild event RP", zap.Error(err)) + } bf.WriteUint32(balance) default: panic(fmt.Sprintf("unhandled operate guild action '%d'", pkt.Action)) @@ -811,7 +813,9 @@ func handleDonateRP(s *Session, amount uint16, guild *Guild, _type int) []byte { var resetRoom bool if _type == 2 { var currentRP uint16 - s.server.db.QueryRow(`SELECT room_rp FROM guilds WHERE id = $1`, guild.ID).Scan(¤tRP) + if err := s.server.db.QueryRow(`SELECT room_rp FROM guilds WHERE id = $1`, guild.ID).Scan(¤tRP); err != nil { + s.logger.Error("Failed to get guild room RP", zap.Error(err)) + } if currentRP+amount >= 30 { amount = 30 - currentRP resetRoom = true @@ -1593,7 +1597,9 @@ func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) { func guildGetItems(s *Session, guildID uint32) []mhfitem.MHFItemStack { var data []byte var items []mhfitem.MHFItemStack - s.server.db.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data) + if err := s.server.db.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data); err != nil { + s.logger.Error("Failed to get guild item box", zap.Error(err)) + } if len(data) > 0 { box := byteframe.NewByteFrameFromBytes(data) numStacks := box.ReadUint16() diff --git a/server/channelserver/handlers_house.go b/server/channelserver/handlers_house.go index 7261194e0..e366ffecc 100644 --- a/server/channelserver/handlers_house.go +++ b/server/channelserver/handlers_house.go @@ -95,11 +95,15 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) { houseQuery = `SELECT c.id, hr, gr, name, COALESCE(ub.house_state, 2) as house_state, COALESCE(ub.house_password, '') as house_password FROM characters c LEFT JOIN user_binary ub ON ub.id = c.id WHERE name ILIKE $1` house := HouseData{} - rows, _ := s.server.db.Queryx(houseQuery, fmt.Sprintf(`%%%s%%`, pkt.Name)) - for rows.Next() { - err := rows.StructScan(&house) - if err == nil { - houses = append(houses, house) + rows, err := s.server.db.Queryx(houseQuery, fmt.Sprintf(`%%%s%%`, pkt.Name)) + if err != nil { + s.logger.Error("Failed to query houses by name", zap.Error(err)) + } else { + defer rows.Close() + for rows.Next() { + if err := rows.StructScan(&house); err == nil { + houses = append(houses, house) + } } } case 4: diff --git a/server/channelserver/handlers_mercenary.go b/server/channelserver/handlers_mercenary.go index d0312f464..e54a29eb1 100644 --- a/server/channelserver/handlers_mercenary.go +++ b/server/channelserver/handlers_mercenary.go @@ -217,18 +217,22 @@ func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) { if pkt.Op != 2 && pkt.Op != 5 { var loans uint8 temp := byteframe.NewByteFrame() - rows, _ := s.server.db.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.charID) - for rows.Next() { - err := rows.Scan(&name, &cid, &pactID) - if err != nil { - continue + rows, err := s.server.db.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.charID) + if err != nil { + s.logger.Error("Failed to query mercenary loans", zap.Error(err)) + } else { + defer rows.Close() + for rows.Next() { + if err := rows.Scan(&name, &cid, &pactID); err != nil { + continue + } + loans++ + temp.WriteUint32(pactID) + temp.WriteUint32(cid) + temp.WriteUint32(uint32(TimeAdjusted().Unix())) + temp.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * 7).Unix())) + temp.WriteBytes(stringsupport.PaddedString(name, 18, true)) } - loans++ - temp.WriteUint32(pactID) - temp.WriteUint32(cid) - temp.WriteUint32(uint32(TimeAdjusted().Unix())) - temp.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * 7).Unix())) - temp.WriteBytes(stringsupport.PaddedString(name, 18, true)) } bf.WriteUint8(loans) bf.WriteBytes(temp.Data()) diff --git a/server/channelserver/handlers_rengoku.go b/server/channelserver/handlers_rengoku.go index 63a591fd2..48e68c16c 100644 --- a/server/channelserver/handlers_rengoku.go +++ b/server/channelserver/handlers_rengoku.go @@ -131,24 +131,31 @@ func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) { scoreData := byteframe.NewByteFrame() var rows *sqlx.Rows + var err error switch pkt.Leaderboard { case 0: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s ORDER BY max_stages_mp DESC", rengokuScoreQuery)) + rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s ORDER BY max_stages_mp DESC", rengokuScoreQuery)) case 1: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s ORDER BY max_points_mp DESC", rengokuScoreQuery)) + rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s ORDER BY max_points_mp DESC", rengokuScoreQuery)) case 2: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s WHERE guild_id=$1 ORDER BY max_stages_mp DESC", rengokuScoreQuery), guild.ID) + rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s WHERE guild_id=$1 ORDER BY max_stages_mp DESC", rengokuScoreQuery), guild.ID) case 3: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s WHERE guild_id=$1 ORDER BY max_points_mp DESC", rengokuScoreQuery), guild.ID) + rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s WHERE guild_id=$1 ORDER BY max_points_mp DESC", rengokuScoreQuery), guild.ID) case 4: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s ORDER BY max_stages_sp DESC", rengokuScoreQuery)) + rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s ORDER BY max_stages_sp DESC", rengokuScoreQuery)) case 5: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s ORDER BY max_points_sp DESC", rengokuScoreQuery)) + rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s ORDER BY max_points_sp DESC", rengokuScoreQuery)) case 6: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s WHERE guild_id=$1 ORDER BY max_stages_sp DESC", rengokuScoreQuery), guild.ID) + rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s WHERE guild_id=$1 ORDER BY max_stages_sp DESC", rengokuScoreQuery), guild.ID) case 7: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s WHERE guild_id=$1 ORDER BY max_points_sp DESC", rengokuScoreQuery), guild.ID) + rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s WHERE guild_id=$1 ORDER BY max_points_sp DESC", rengokuScoreQuery), guild.ID) } + if err != nil { + s.logger.Error("Failed to query rengoku ranking", zap.Error(err)) + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 11)) + return + } + defer rows.Close() for rows.Next() { rows.StructScan(&score) diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 0e2e87ab4..c223e69bf 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -317,11 +317,16 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { pkt.Unk3 = 3 } } - rows, _ := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c ON gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL ORDER BY tower_mission_%d DESC`, pkt.Unk3, pkt.Unk3, pkt.Unk3), pkt.GuildID) - for rows.Next() { - temp := TenrouiraiCharScore{} - rows.Scan(&temp.Name, &temp.Score) - tenrouirai.CharScore = append(tenrouirai.CharScore, temp) + rows, err := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c ON gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL ORDER BY tower_mission_%d DESC`, pkt.Unk3, pkt.Unk3, pkt.Unk3), pkt.GuildID) + if err != nil { + s.logger.Error("Failed to query tower mission scores", zap.Error(err)) + } else { + defer rows.Close() + for rows.Next() { + temp := TenrouiraiCharScore{} + rows.Scan(&temp.Name, &temp.Score) + tenrouirai.CharScore = append(tenrouirai.CharScore, temp) + } } for _, charScore := range tenrouirai.CharScore { bf := byteframe.NewByteFrame() diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index 62ed7b08e..0cbd0b838 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -416,10 +416,15 @@ func (s *Server) FindSessionByCharID(charID uint32) *Session { 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) + rows, err := s.db.Query(`SELECT id FROM characters WHERE user_id=$1`, uid) + if err != nil { + s.logger.Error("Failed to query characters for disconnect", zap.Error(err)) + } else { + defer rows.Close() + for rows.Next() { + rows.Scan(&cid) + cids = append(cids, cid) + } } for _, c := range s.Channels { for _, session := range c.sessions {