/* * Copyright (C) 2008-2015 TrinityCore * Copyright (C) 2005-2009 MaNGOS * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "zlib.h" #include "Common.h" #include "Language.h" #include "ObjectMgr.h" #include "Opcodes.h" #include "Player.h" #include "SupportMgr.h" #include "TicketPackets.h" #include "Util.h" #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" void WorldSession::HandleGMTicketCreateOpcode(WorldPackets::Ticket::GMTicketCreate& packet) { // Don't accept tickets if the ticket queue is disabled. (Ticket UI is greyed out but not fully dependable) if (sSupportMgr->GetSupportSystemStatus() == GMTICKET_QUEUE_STATUS_DISABLED) return; if (GetPlayer()->getLevel() < sWorld->getIntConfig(CONFIG_TICKET_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_TICKET_REQ), sWorld->getIntConfig(CONFIG_TICKET_LEVEL_REQ)); return; } GMTicketResponse response = GMTICKET_RESPONSE_CREATE_ERROR; GmTicket* ticket = sSupportMgr->GetGmTicketByPlayerGuid(GetPlayer()->GetGUID()); if (ticket && ticket->IsCompleted()) sSupportMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID()); // Player must not have ticket if (!ticket || ticket->IsClosed()) { std::string chatLog; if (packet.DataLength > 0 && packet.ChatHistoryData.DecompressedSize < 0xFFFF) { ByteBuffer dest; dest.resize(size_t(packet.ChatHistoryData.DecompressedSize)); uLongf realSize = packet.ChatHistoryData.DecompressedSize; if (uncompress(dest.contents(), &realSize, packet.ChatHistoryData.Data.contents(), packet.ChatHistoryData.Data.size()) == Z_OK) dest >> chatLog; else { TC_LOG_ERROR("network", "CMSG_GM_TICKET_CREATE possibly corrupt. Uncompression failed."); return; } } ticket = new GmTicket(GetPlayer()); ticket->SetPosition(packet.Map, packet.Pos); ticket->SetDescription(packet.Description); ticket->SetGmAction(packet.NeedResponse, packet.NeedMoreHelp); //TODO: more reasearch needed //if (!chatLog.empty()) //ticket->SetChatLog(times, chatLog); sSupportMgr->AddTicket(ticket); sSupportMgr->UpdateLastChange(); sWorld->SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName().c_str(), ticket->GetId()); response = GMTICKET_RESPONSE_CREATE_SUCCESS; } sSupportMgr->SendGmTicketUpdate(this, response); } void WorldSession::HandleGMTicketUpdateTextOpcode(WorldPackets::Ticket::GMTicketUpdateText& packet) { GMTicketResponse response = GMTICKET_RESPONSE_UPDATE_ERROR; if (GmTicket* ticket = sSupportMgr->GetGmTicketByPlayerGuid(GetPlayer()->GetGUID())) { SQLTransaction trans = SQLTransaction(NULL); ticket->SetDescription(packet.Description); ticket->SaveToDB(trans); sWorld->SendGMText(LANG_COMMAND_TICKETUPDATED, GetPlayer()->GetName().c_str(), ticket->GetId()); response = GMTICKET_RESPONSE_UPDATE_SUCCESS; } sSupportMgr->SendGmTicketUpdate(this, response); } void WorldSession::HandleGMTicketDeleteOpcode(WorldPackets::Ticket::GMTicketDelete& /*packet*/) { if (GmTicket* ticket = sSupportMgr->GetGmTicketByPlayerGuid(GetPlayer()->GetGUID())) { sSupportMgr->SendGmTicketUpdate(this, GMTICKET_RESPONSE_TICKET_DELETED); sWorld->SendGMText(LANG_COMMAND_TICKETPLAYERABANDON, GetPlayer()->GetName().c_str(), ticket->GetId()); sSupportMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID()); sSupportMgr->SendGmTicket(this, NULL); } } void WorldSession::HandleGMTicketGetCaseStatusOpcode(WorldPackets::Ticket::GMTicketGetCaseStatus& /*packet*/) { // TODO: Implement GmCase and handle this packet properly WorldPackets::Ticket::GMTicketCaseStatus status; status.OldestTicketTime = time(nullptr); SendPacket(status.Write()); } void WorldSession::HandleGMTicketGetTicketOpcode(WorldPackets::Ticket::GMTicketGetTicket& /*packet*/) { SendQueryTimeResponse(); if (GmTicket* ticket = sSupportMgr->GetGmTicketByPlayerGuid(GetPlayer()->GetGUID())) { if (ticket->IsCompleted()) ticket->SendResponse(this); else sSupportMgr->SendGmTicket(this, ticket); } else sSupportMgr->SendGmTicket(this, NULL); } void WorldSession::HandleGMTicketSystemStatusOpcode(WorldPackets::Ticket::GMTicketGetSystemStatus& /*packet*/) { // Note: This only disables the ticket UI at client side and is not fully reliable // Note: This disables the whole customer support UI after trying to send a ticket in disabled state (MessageBox: "GM Help Tickets are currently unavaiable."). UI remains disabled until the character relogs. WorldPackets::Ticket::GMTicketSystemStatus response; response.Status = sSupportMgr->GetSupportSystemStatus() ? GMTICKET_QUEUE_STATUS_ENABLED : GMTICKET_QUEUE_STATUS_DISABLED; SendPacket(response.Write()); } void WorldSession::HandleGMSurveySubmit(WorldPackets::Ticket::GMSurveySubmit& /*packet*/) { /*uint32 nextSurveyID = sSupportMgr->GetNextSurveyID(); std::unordered_set surveyIds; SQLTransaction trans = CharacterDatabase.BeginTransaction(); for (auto const& q : packet.SurveyQuestion) { if (!q.QuestionID) break; // make sure the same sub survey is not added to DB twice if (!surveyIds.insert(q.QuestionID).second) continue; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GM_SUBSURVEY); stmt->setUInt32(0, nextSurveyID); stmt->setUInt32(1, q.QuestionID); // ref to i'th GMSurveySurveys.dbc field (all fields in that dbc point to fields in GMSurveyQuestions.dbc) stmt->setUInt32(2, q.Answer); // probably some sort of ref to GMSurveyAnswers.dbc stmt->setString(3, q.AnswerComment); // comment ("Usage: GMSurveyAnswerSubmit(question, rank, comment)") trans->Append(stmt); } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GM_SURVEY); stmt->setUInt64(0, GetPlayer()->GetGUID().GetCounter()); stmt->setUInt32(1, nextSurveyID); stmt->setUInt32(2, packet.SurveyID); // GMSurveyCurrentSurvey.dbc, column 1 (all 9) ref to GMSurveySurveys.dbc stmt->setString(3, packet.Comment); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans);*/ } void WorldSession::HandleGMResponseResolve(WorldPackets::Ticket::GMTicketResponseResolve& /*packet*/) { if (GmTicket* ticket = sSupportMgr->GetGmTicketByPlayerGuid(GetPlayer()->GetGUID())) { bool showSurvey = false; if (float(rand_chance()) < sWorld->getFloatConfig(CONFIG_CHANCE_OF_GM_SURVEY)) showSurvey = true; WorldPackets::Ticket::GMTicketResolveResponse response; response.ShowSurvey = showSurvey; SendPacket(response.Write()); sSupportMgr->SendGmTicketUpdate(this, GMTICKET_RESPONSE_TICKET_DELETED); sSupportMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID()); sSupportMgr->SendGmTicket(this, NULL); } } void WorldSession::HandleSupportTicketSubmitBug(WorldPackets::Ticket::SupportTicketSubmitBug& packet) { BugTicket* ticket = new BugTicket(GetPlayer()); ticket->SetPosition(packet.Header.MapID, packet.Header.Position); ticket->SetFacing(packet.Header.Facing); ticket->SetNote(packet.Note); sSupportMgr->AddTicket(ticket); } void WorldSession::HandleSupportTicketSubmitSuggestion(WorldPackets::Ticket::SupportTicketSubmitSuggestion& packet) { SuggestionTicket* ticket = new SuggestionTicket(GetPlayer()); ticket->SetPosition(packet.Header.MapID, packet.Header.Position); ticket->SetFacing(packet.Header.Facing); ticket->SetNote(packet.Note); sSupportMgr->AddTicket(ticket); } void WorldSession::HandleSupportTicketSubmitComplaint(WorldPackets::Ticket::SupportTicketSubmitComplaint& packet) { ComplaintTicket* comp = new ComplaintTicket(GetPlayer()); comp->SetPosition(packet.Header.MapID, packet.Header.Position); comp->SetFacing(packet.Header.Facing); comp->SetChatLog(packet.ChatLog); comp->SetTargetCharacterGuid(packet.TargetCharacterGUID); comp->SetComplaintType(GMSupportComplaintType(packet.ComplaintType)); comp->SetNote(packet.Note); sSupportMgr->AddTicket(comp); }