/*
* 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);
}