/*
* Copyright (C) 2008-2012 TrinityCore
*
* 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 .
*/
/*
DROP TABLE IF EXISTS `calendar_events`;
CREATE TABLE IF NOT EXISTS `calendar_events` (
`id` int(11) unsigned NOT NULL DEFAULT '0',
`creator` int(11) unsigned NOT NULL DEFAULT '0',
`title` varchar(255) NOT NULL DEFAULT '',
`description` varchar(255) NOT NULL DEFAULT '',
`type` tinyint(1) unsigned NOT NULL DEFAULT '4',
`dungeon` tinyint(3) NOT NULL DEFAULT '-1',
`eventtime` int(10) unsigned NOT NULL DEFAULT '0',
`flags` int(10) unsigned NOT NULL DEFAULT '0',
`repeatable` tinyint(1) unsigned NOT NULL DEFAULT '0',
`time2` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
);
DROP TABLE IF EXISTS `calendar_invites`;
CREATE TABLE IF NOT EXISTS `calendar_invites` (
`id` int(11) unsigned NOT NULL DEFAULT '0',
`event` int(11) unsigned NOT NULL DEFAULT '0',
`invitee` int(11) unsigned NOT NULL DEFAULT '0',
`sender` int(11) unsigned NOT NULL DEFAULT '0',
`status` tinyint(1) unsigned NOT NULL DEFAULT '0',
`statustime` int(10) unsigned NOT NULL DEFAULT '0',
`rank` tinyint(1) unsigned NOT NULL DEFAULT '0',
`text` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
);
*/
#include "CalendarMgr.h"
#include "QueryResult.h"
#include "DatabaseEnv.h"
#include "Log.h"
#include "Player.h"
#include "ObjectAccessor.h"
CalendarMgr::CalendarMgr() :
_eventNum(0), _inviteNum(0)
{
}
CalendarMgr::~CalendarMgr()
{
}
uint32 CalendarMgr::GetPlayerNumPending(uint64 guid)
{
if (!guid)
return 0;
CalendarPlayerInviteIdMap::const_iterator itr = _playerInvites.find(guid);
if (itr == _playerInvites.end())
return 0;
uint32 pendingNum = 0;
for (CalendarInviteIdList::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
if (CalendarInvite* invite = GetInvite(*it))
if (invite->GetRank() != CALENDAR_RANK_OWNER
&& invite->GetStatus() != CALENDAR_STATUS_CONFIRMED
&& invite->GetStatus() != CALENDAR_STATUS_8
&& invite->GetStatus() != CALENDAR_STATUS_9) // FIXME Check the proper value
++pendingNum;
return pendingNum;
}
CalendarInviteIdList const& CalendarMgr::GetPlayerInvites(uint64 guid)
{
return _playerInvites[guid];
}
CalendarEventIdList const& CalendarMgr::GetPlayerEvents(uint64 guid)
{
return _playerEvents[guid];
}
CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId)
{
CalendarInviteMap::iterator itr = _invites.find(inviteId);
if (itr != _invites.end())
return &(itr->second);
sLog->outError(LOG_FILTER_CALENDAR, "CalendarMgr::GetInvite: [" UI64FMTD "] not found!", inviteId);
return NULL;
}
CalendarEvent* CalendarMgr::GetEvent(uint64 eventId)
{
CalendarEventMap::iterator itr = _events.find(eventId);
if (itr != _events.end())
return &(itr->second);
sLog->outError(LOG_FILTER_CALENDAR, "CalendarMgr::GetEvent: [" UI64FMTD "] not found!", eventId);
return NULL;
}
uint64 CalendarMgr::GetFreeEventId()
{
return ++_eventNum;
}
uint64 CalendarMgr::GetFreeInviteId()
{
return ++_inviteNum;
}
void CalendarMgr::LoadFromDB()
{
/*
uint32 count = 0;
// 0 1 2 3 4 5 6 7 8 9
if (QueryResult result = CharacterDatabase.Query("SELECT id, creator, title, description, type, dungeon, eventtime, flags, repeatable, time2 FROM calendar_events"))
do
{
Field * fields = result->Fetch();
uint64 eventId = fields[0].GetUInt64();
CalendarEvent& calendarEvent = _events[eventId];
calendarEvent.SetEventId(eventId);
calendarEvent.SetCreatorGUID(fields[1].GetUInt64());
calendarEvent.SetTitle(fields[2].GetString());
calendarEvent.SetDescription(fields[3].GetString());
calendarEvent.SetType(fields[4].GetUInt8());
calendarEvent.SetDungeonId(fields[5].GetInt32());
calendarEvent.SetTime(fields[6].GetUInt32());
calendarEvent.SetFlags(fields[7].GetUInt32());
calendarEvent.SetRepeatable(fields[8].GetBool());
calendarEvent.SetTimeZoneTime(fields[9].GetUInt32());
++count;
}
while (result->NextRow());
sLog->outInfo(LOG_FILTER_CALENDAR, ">> Loaded %u calendar events", count);
count = 0;
// 0 1 2 3 4 5 6 7
if (QueryResult result = CharacterDatabase.Query("SELECT id, event, invitee, sender, status, statustime, rank, text FROM calendar_invites"))
do
{
Field * fields = result->Fetch();
uint64 inviteId = fields[0].GetUInt64();
uint64 eventId = fields[1].GetUInt64();
CalendarInvite& invite = _invites[inviteId];
invite.SetEventId(eventId);
invite.SetInvitee(fields[2].GetUInt64());
invite.SetSenderGUID(fields[3].GetUInt64());
invite.SetStatus(fields[4].GetUInt8());
invite.SetStatusTime(fields[5].GetUInt32());
invite.SetRank(fields[6].GetUInt8());
invite.SetText(fields[7].GetString());
CalendarEvent& calendarEvent = _events[eventId];
calendarEvent.AddInvite(inviteId);
}
while (result->NextRow());
sLog->outInfo(LOG_FILTER_CALENDAR, ">> Loaded %u calendar Invites", count);
*/
}
CalendarEvent* CalendarMgr::CheckPermisions(uint64 eventId, Player* player, uint64 inviteId, CalendarModerationRank minRank)
{
if (!player)
return NULL; // CALENDAR_ERROR_INTERNAL
CalendarEvent* calendarEvent = GetEvent(eventId);
if (!calendarEvent)
{
player->GetSession()->SendCalendarCommandResult(CALENDAR_ERROR_EVENT_INVALID);
return NULL;
}
CalendarInvite* invite = GetInvite(inviteId);
if (!invite)
{
player->GetSession()->SendCalendarCommandResult(CALENDAR_ERROR_NO_INVITE);
return NULL;
}
if (!calendarEvent->HasInvite(inviteId))
{
player->GetSession()->SendCalendarCommandResult(CALENDAR_ERROR_NOT_INVITED);
return NULL;
}
if (invite->GetEventId() != calendarEvent->GetEventId() || invite->GetInvitee() != player->GetGUID())
{
player->GetSession()->SendCalendarCommandResult(CALENDAR_ERROR_INTERNAL);
return NULL;
}
if (invite->GetRank() < minRank)
{
player->GetSession()->SendCalendarCommandResult(CALENDAR_ERROR_PERMISSIONS);
return NULL;
}
return calendarEvent;
}
void CalendarMgr::AddAction(CalendarAction const& action)
{
switch (action.GetAction())
{
case CALENDAR_ACTION_ADD_EVENT:
{
if (AddEvent(action.Event) && AddInvite(action.Invite))
{
SendCalendarEventInviteAlert(action.Event, action.Invite);
SendCalendarEvent(action.Event, CALENDAR_SENDTYPE_ADD);
}
break;
}
case CALENDAR_ACTION_MODIFY_EVENT:
{
uint64 eventId = action.Event.GetEventId();
CalendarEvent* calendarEvent = CheckPermisions(eventId, action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_MODERATOR);
if (!calendarEvent)
return;
calendarEvent->SetEventId(action.Event.GetEventId());
calendarEvent->SetType(action.Event.GetType());
calendarEvent->SetFlags(action.Event.GetFlags());
calendarEvent->SetTime(action.Event.GetTime());
calendarEvent->SetTimeZoneTime(action.Event.GetTimeZoneTime());
calendarEvent->SetRepeatable(action.Event.GetRepeatable());
calendarEvent->SetDungeonId(action.Event.GetDungeonId());
calendarEvent->SetTitle(action.Event.GetTitle());
calendarEvent->SetDescription(action.Event.GetDescription());
calendarEvent->SetMaxInvites(action.Event.GetMaxInvites());
CalendarInviteIdList const& invites = calendarEvent->GetInviteIdList();
for (CalendarInviteIdList::const_iterator itr = invites.begin(); itr != invites.end(); ++itr)
if (CalendarInvite* invite = GetInvite(*itr))
SendCalendarEventUpdateAlert(invite->GetInvitee(), *calendarEvent, CALENDAR_SENDTYPE_ADD);
break;
}
case CALENDAR_ACTION_COPY_EVENT:
{
CalendarEvent* calendarEvent = CheckPermisions(action.Event.GetEventId(), action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_OWNER);
if (!calendarEvent)
return;
uint64 eventId = GetFreeEventId();
CalendarEvent newEvent(eventId);
newEvent.SetType(calendarEvent->GetType());
newEvent.SetFlags(calendarEvent->GetFlags());
newEvent.SetTime(action.Event.GetTime());
newEvent.SetTimeZoneTime(calendarEvent->GetTimeZoneTime());
newEvent.SetRepeatable(calendarEvent->GetRepeatable());
newEvent.SetDungeonId(calendarEvent->GetDungeonId());
newEvent.SetTitle(calendarEvent->GetTitle());
newEvent.SetDescription(calendarEvent->GetDescription());
newEvent.SetMaxInvites(calendarEvent->GetMaxInvites());
newEvent.SetCreatorGUID(calendarEvent->GetCreatorGUID());
newEvent.SetGuildId(calendarEvent->GetGuildId());
CalendarInviteIdList const invites = calendarEvent->GetInviteIdList();
for (CalendarInviteIdList::const_iterator itr = invites.begin(); itr != invites.end(); ++itr)
{
if (CalendarInvite* invite = GetInvite(*itr))
{
uint64 inviteId = GetFreeInviteId();
CalendarInvite newInvite(inviteId);
newInvite.SetEventId(eventId);
newInvite.SetSenderGUID(action.GetPlayer()->GetGUID());
newInvite.SetInvitee(invite->GetInvitee());
newInvite.SetStatus(invite->GetStatus());
newInvite.SetStatusTime(invite->GetStatusTime());
newInvite.SetText(invite->GetText());
newInvite.SetRank(invite->GetRank());
if (AddInvite(newInvite))
{
SendCalendarEventInviteAlert(newEvent, newInvite);
newEvent.AddInvite(inviteId);
}
}
}
if (AddEvent(newEvent))
SendCalendarEvent(newEvent, CALENDAR_SENDTYPE_COPY);
break;
}
case CALENDAR_ACTION_REMOVE_EVENT:
{
uint64 eventId = action.Event.GetEventId();
//uint32 flags = action.Event.GetFlags();
// FIXME - Use of Flags here!
CalendarEvent* calendarEvent = CheckPermisions(eventId, action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_OWNER);
if (!calendarEvent)
return;
RemoveEvent(eventId);
break;
}
case CALENDAR_ACTION_ADD_EVENT_INVITE:
{
uint64 eventId = action.Invite.GetEventId();
CalendarEvent* calendarEvent = CheckPermisions(eventId, action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_MODERATOR);
if (!calendarEvent)
return;
if (AddInvite(action.Invite))
{
calendarEvent->AddInvite(action.Invite.GetInviteId());
SendCalendarEventInvite(action.Invite, (!(calendarEvent->GetFlags() & CALENDAR_FLAG_INVITES_LOCKED) &&
!action.Invite.GetStatusTime()));
SendCalendarEventInviteAlert(*calendarEvent, action.Invite);
}
break;
}
case CALENDAR_ACTION_SIGNUP_TO_EVENT:
{
uint64 eventId = action.Event.GetEventId();
CalendarEvent* calendarEvent = GetEvent(eventId);
CheckPermisions(eventId, action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_MODERATOR);
if (!calendarEvent || !(calendarEvent->GetFlags() & CALENDAR_FLAG_GUILD_ONLY)
|| !calendarEvent->GetGuildId() || calendarEvent->GetGuildId() != action.GetExtraData())
return;
CalendarInviteStatus status = action.Invite.GetStatus();
if (status == CALENDAR_STATUS_INVITED)
status = CALENDAR_STATUS_CONFIRMED;
else if (status == CALENDAR_STATUS_ACCEPTED)
status = CALENDAR_STATUS_8;
CalendarInvite newInvite(GetFreeInviteId());
newInvite.SetStatus(status);
newInvite.SetStatusTime(uint32(time(NULL)));
newInvite.SetEventId(eventId);
newInvite.SetInvitee(action.GetPlayer()->GetGUID());
newInvite.SetSenderGUID(action.GetPlayer()->GetGUID());
if (AddInvite(newInvite))
SendCalendarEventInvite(newInvite, false);
break;
}
case CALENDAR_ACTION_MODIFY_EVENT_INVITE:
{
uint64 eventId = action.Invite.GetEventId();
uint64 inviteId = action.Invite.GetInviteId();
CalendarEvent* calendarEvent = NULL;
if (action.GetInviteId() != action.Invite.GetInviteId())
calendarEvent = CheckPermisions(eventId, action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_MODERATOR);
else
calendarEvent = GetEvent(eventId);
CalendarInvite* invite = GetInvite(inviteId);
if (!calendarEvent || !invite || !calendarEvent->HasInvite(inviteId))
return;
invite->SetStatus(action.Invite.GetStatus());
SendCalendarEventStatus(invite->GetSenderGUID(), *calendarEvent, *invite);
break;
}
case CALENDAR_ACTION_MODIFY_MODERATOR_EVENT_INVITE:
{
uint64 eventId = action.Invite.GetEventId();
uint64 inviteId = action.Invite.GetInviteId();
CalendarEvent* calendarEvent = NULL;
if (action.GetInviteId() != action.Invite.GetInviteId())
calendarEvent = CheckPermisions(eventId, action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_OWNER);
else
calendarEvent = GetEvent(eventId);
CalendarInvite* invite = GetInvite(inviteId);
if (!calendarEvent || !invite || !calendarEvent->HasInvite(inviteId))
return;
invite->SetStatus(action.Invite.GetStatus());
SendCalendarEventModeratorStatusAlert(*invite);
break;
}
case CALENDAR_ACTION_REMOVE_EVENT_INVITE:
{
uint64 eventId = action.Invite.GetEventId();
uint64 inviteId = action.Invite.GetInviteId();
CalendarEvent* calendarEvent = CheckPermisions(eventId, action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_MODERATOR);
if (!calendarEvent)
return;
// already checked in CheckPermisions
CalendarInvite* invite = GetInvite(inviteId);
if (!invite)
return;
if (calendarEvent->GetCreatorGUID() == invite->GetInvitee())
{
action.GetPlayer()->GetSession()->SendCalendarCommandResult(CALENDAR_ERROR_DELETE_CREATOR_FAILED);
return;
}
if (uint64 invitee = RemoveInvite(inviteId))
{
SendCalendarEventInviteRemoveAlert(invitee, *calendarEvent, CALENDAR_STATUS_9);
SendCalendarEventInviteRemove(action.GetPlayer()->GetGUID(), action.Invite, calendarEvent->GetFlags());
}
break;
}
default:
break;
}
}
bool CalendarMgr::AddEvent(CalendarEvent const& newEvent)
{
uint64 eventId = newEvent.GetEventId();
if (_events.find(eventId) != _events.end())
{
sLog->outError(LOG_FILTER_CALENDAR, "CalendarMgr::AddEvent: Event [" UI64FMTD "] exists", eventId);
return false;
}
_events[eventId] = newEvent;
return true;
}
bool CalendarMgr::RemoveEvent(uint64 eventId)
{
CalendarEventMap::iterator itr = _events.find(eventId);
if (itr == _events.end())
{
sLog->outError(LOG_FILTER_CALENDAR, "CalendarMgr::RemoveEvent: Event [" UI64FMTD "] does not exist", eventId);
return false;
}
bool val = true;
CalendarInviteIdList const& invites = itr->second.GetInviteIdList();
for (CalendarInviteIdList::const_iterator itrInvites = invites.begin(); itrInvites != invites.end(); ++itrInvites)
{
CalendarInvite* invite = GetInvite(*itrInvites);
if (!invite || !RemovePlayerEvent(invite->GetInvitee(), eventId))
val = false;
if (uint64 invitee = RemoveInvite(*itrInvites))
SendCalendarEventRemovedAlert(invitee, itr->second);
}
_events.erase(itr);
return val;
}
bool CalendarMgr::AddPlayerEvent(uint64 guid, uint64 eventId)
{
_playerEvents[guid].insert(eventId);
return true;
}
bool CalendarMgr::RemovePlayerEvent(uint64 guid, uint64 eventId)
{
_playerEvents[guid].erase(eventId);
return true;
}
bool CalendarMgr::AddInvite(CalendarInvite const& newInvite)
{
uint64 inviteId = newInvite.GetInviteId();
if (!inviteId)
{
sLog->outError(LOG_FILTER_CALENDAR, "CalendarMgr::AddInvite: Cant add Invite 0");
return false;
}
if (_invites.find(inviteId) != _invites.end())
{
sLog->outError(LOG_FILTER_CALENDAR, "CalendarMgr::AddInvite: Invite [" UI64FMTD "] exists", inviteId);
return false;
}
_invites[inviteId] = newInvite;
uint64 guid = newInvite.GetInvitee();
bool inviteAdded = AddPlayerInvite(guid, inviteId);
bool eventAdded = AddPlayerEvent(guid, newInvite.GetEventId());
return eventAdded && inviteAdded;
}
uint64 CalendarMgr::RemoveInvite(uint64 inviteId)
{
CalendarInviteMap::iterator itr = _invites.find(inviteId);
if (itr == _invites.end())
{
sLog->outError(LOG_FILTER_CALENDAR, "CalendarMgr::RemoveInvite: Invite [" UI64FMTD "] does not exist", inviteId);
return 0;
}
uint64 invitee = itr->second.GetInvitee();
_invites.erase(itr);
return RemovePlayerInvite(invitee, inviteId) ? invitee : 0;
}
bool CalendarMgr::AddPlayerInvite(uint64 guid, uint64 inviteId)
{
_playerInvites[guid].insert(inviteId);
return true;
}
bool CalendarMgr::RemovePlayerInvite(uint64 guid, uint64 inviteId)
{
_playerInvites[guid].erase(inviteId);
return true;
}
void CalendarMgr::SendCalendarEvent(CalendarEvent const& calendarEvent, CalendarSendEventType type)
{
if (Player* player = ObjectAccessor::FindPlayer(calendarEvent.GetCreatorGUID()))
player->GetSession()->SendCalendarEvent(calendarEvent, type);
}
void CalendarMgr::SendCalendarEventInvite(CalendarInvite const& invite, bool pending)
{
if (Player* player = ObjectAccessor::FindPlayer(invite.GetSenderGUID()))
player->GetSession()->SendCalendarEventInvite(invite, pending);
}
void CalendarMgr::SendCalendarEventInviteAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite)
{
if (Player* player = ObjectAccessor::FindPlayer(invite.GetInvitee()))
player->GetSession()->SendCalendarEventInviteAlert(calendarEvent, invite);
}
void CalendarMgr::SendCalendarEventUpdateAlert(uint64 guid, CalendarEvent const& calendarEvent, CalendarSendEventType type)
{
if (Player* player = ObjectAccessor::FindPlayer(guid))
player->GetSession()->SendCalendarEventUpdateAlert(calendarEvent, type);
}
void CalendarMgr::SendCalendarEventStatus(uint64 guid, CalendarEvent const& calendarEvent, CalendarInvite const& invite)
{
if (Player* player = ObjectAccessor::FindPlayer(guid))
player->GetSession()->SendCalendarEventStatus(calendarEvent, invite);
}
void CalendarMgr::SendCalendarEventRemovedAlert(uint64 guid, CalendarEvent const& calendarEvent)
{
if (Player* player = ObjectAccessor::FindPlayer(guid))
player->GetSession()->SendCalendarEventRemovedAlert(calendarEvent);
}
void CalendarMgr::SendCalendarEventInviteRemoveAlert(uint64 guid, CalendarEvent const& calendarEvent, CalendarInviteStatus status)
{
if (Player* player = ObjectAccessor::FindPlayer(guid))
player->GetSession()->SendCalendarEventInviteRemoveAlert(calendarEvent, status);
}
void CalendarMgr::SendCalendarEventInviteRemove(uint64 guid, CalendarInvite const& invite, uint32 flags)
{
if (Player* player = ObjectAccessor::FindPlayer(guid))
player->GetSession()->SendCalendarEventInviteRemove(invite, flags);
}
void CalendarMgr::SendCalendarEventModeratorStatusAlert(CalendarInvite const& invite)
{
if (Player* player = ObjectAccessor::FindPlayer(invite.GetInvitee()))
player->GetSession()->SendCalendarEventModeratorStatusAlert(invite);
}