summaryrefslogblamecommitdiff
path: root/src/map/mail.c
blob: 6e6dc0a9192e7eec88787586d180cc94fe54e6ab (plain) (tree)
1
2
3
4
5



                                                          
 













                              




                   

                             
 




                                                                          
 
                                                      



                            



                                                                                                                                                                                                                                        


                         





                                                                                     
 





















                                                                                                                                                  

                 











                                                                                                                  
                                 



                                                                                                       
                                 

                         





                                                                                 
 



                                                  
                                                     





                                                                                                        
         


                                                                                            




                 

                                                     
 


                                         
                         

                                                  
 
                           
 





                                                                                                                                                                                                                                                       
 



                                                                                  
                         
         
 





                                                   
 





                                                                                                            
 
                                    
 





                                                                                                                                          
 


                                                                         
 



                                                                                                                                 



                 

                                                       
 



                                                  

                            




                                                                                                                                                                                                                            
 



                                                                                  
                         







                                                   
 



                                                                                   
 
                                    
 




                                                                                                  
 



                                                                                                                         

         







                                                                                                                  


                 

                                                                               
 

                      

                            








                                                                                                                      


                         




                                                                                                                                                                                    

                                 

            





                                                                                                                              

                                 
         
 





                                                                                        
 













                                                                                                                                                                                                                         
         

                                    
 



                                                                          



                 

                                                                         
 
                                
                                   


                 

                                                                  



                             
                                                                                    
 



                                                                                                                                                      
                         
         
 







                                                                                          
 
                                    
 

                                                 
 




                                                                                                                     
 




                      


                                                                                    



                 
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder

#ifndef TXT_ONLY

#include "../common/strlib.h"
#include "../common/socket.h"
#include "../common/timer.h"
#include "../common/nullpo.h"
#include "../common/showmsg.h"

#include "map.h"
#include "clif.h"
#include "chrif.h"
#include "intif.h"
#include "atcommand.h"
#include "pc.h"
#include "mail.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int MAIL_CHECK_TIME = 120000;
int mail_timer;

/// type: 0 - mail check at login, silent if there aren't any new messages
///       1 - @checkmail, just print the number of messages
///       2 - @listmail, shows both read and unread messages
///       3 - @listnewmail, shows only unread messages
int mail_check(struct map_session_data* sd, int type)
{
	int i = 0, new_ = 0, priority = 0; // counters
	char message[80];

	nullpo_retr (0, sd);

	// retrieve all existing messages for this player
	if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`to_account_id`,`from_char_name`,`read_flag`,`priority`,`check_flag` FROM `%s` WHERE `to_account_id` = %d ORDER by `message_id`", mail_db, sd->status.account_id) )
	{
		Sql_ShowDebug(mail_handle);
		return 0;
	}

	if( Sql_NumRows(mail_handle) == 0)
	{
		clif_displaymessage(sd->fd, msg_txt(516)); // "You have no messages."
		Sql_FreeResult(mail_handle);
		return 0;
	}

	while( SQL_SUCCESS == Sql_NextRow(mail_handle) )
	{
		char* data;
		int message_id;
		int to_account_id;
		char from_char_name[NAME_LENGTH];
		bool read_flag, priority_flag, check_flag;

		Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data);
		Sql_GetData(mail_handle, 1, &data, NULL); to_account_id = atoi(data);
		Sql_GetData(mail_handle, 2, &data, NULL); safestrncpy(from_char_name, data, sizeof(from_char_name));
		Sql_GetData(mail_handle, 3, &data, NULL); read_flag = (bool) atoi(data);
		Sql_GetData(mail_handle, 4, &data, NULL); priority_flag = (bool) atoi(data);
		Sql_GetData(mail_handle, 5, &data, NULL); check_flag = (bool) atoi(data);

		i++;

		if( !check_flag )
		{
			// mark this message as checked
			if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) )
				Sql_ShowDebug(mail_handle);
		}

		if( !read_flag )
		{
			new_++;
			if(priority_flag)
				priority++;

			if( type == 2 || type == 3 )
			{
				if( priority_flag )
				{
					snprintf(message, 80, msg_txt(511), i, from_char_name);
					clif_displaymessage(sd->fd, message); // "%d - From : %s (New - Priority)"
				}
				else
				{
					snprintf(message, 80, msg_txt(512), i, from_char_name);
					clif_displaymessage(sd->fd, message); // "%d - From : %s (New)"
				}
			}
		}
		else if( type == 2 )
		{
			snprintf(message, 80, msg_txt(513), i, from_char_name);
			clif_displaymessage(sd->fd, message); // "%d - From : %s"
		}
	}

	Sql_FreeResult(mail_handle);
	
	if( new_ > 0 && (type == 0 || type == 1) )
	{
		sprintf(message, msg_txt(514), new_);
		clif_displaymessage(sd->fd, message); // "You have %d unread messages."
		if (priority > 0)
		{
			sprintf(message, msg_txt(515), priority);
			clif_displaymessage(sd->fd, message); // "You have %d unread priority messages."
		}
	}
	if( new_ == 0 && type != 0 )
	{
		clif_displaymessage(sd->fd, msg_txt(516)); // "You have no unread messages."
	}

	return 0;
}

/// displays the selected message
int mail_read(struct map_session_data* sd, int index)
{
	char* data;
	int message_id;
	char from_char_name[NAME_LENGTH];
	char message[80];
	bool read_flag, priority_flag, check_flag;
	char output[100];

	nullpo_retr(0, sd);

	// retrieve the 'index'-th message 
	if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`from_char_name`,`message`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = %d ORDER by `message_id` LIMIT %d, 1", mail_db, sd->status.account_id, index-1) )
	{
		Sql_ShowDebug(mail_handle);
		return 0;
	}

	if( 0 == Sql_NumRows(mail_handle) )
	{
		clif_displaymessage(sd->fd, msg_txt(517)); // "Message not found."
		Sql_FreeResult(mail_handle);
		return 0;
	}

	if( SQL_ERROR == Sql_NextRow(mail_handle) )
	{
		Sql_ShowDebug(mail_handle);
		Sql_FreeResult(mail_handle);
		return 0;
	}

	Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data);
	Sql_GetData(mail_handle, 1, &data, NULL); safestrncpy(from_char_name, data, sizeof(from_char_name));
	Sql_GetData(mail_handle, 2, &data, NULL); safestrncpy(message, data, sizeof(message));
	Sql_GetData(mail_handle, 3, &data, NULL); read_flag = (bool) atoi(data);
	Sql_GetData(mail_handle, 4, &data, NULL); priority_flag = (bool) atoi(data);
	Sql_GetData(mail_handle, 5, &data, NULL); check_flag = (bool) atoi(data);

	Sql_FreeResult(mail_handle);

	// mark mail as checked
	if( !check_flag )
	{
		if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) )
		Sql_ShowDebug(mail_handle);
	}

	sprintf(output, msg_txt(518), from_char_name);
	clif_displaymessage(sd->fd, output); // "Reading message from %s"
	clif_displaymessage(sd->fd, message);

	if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `read_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) )
	{
		Sql_ShowDebug(mail_handle);
	}

	return 0;
}

/// message deletion
int mail_delete(struct map_session_data* sd, int index)
{
	char* data;
	int message_id;
	bool read_flag, priority_flag, check_flag;

	nullpo_retr (0, sd);

	if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = %d ORDER by `message_id` LIMIT %d, 1", mail_db, sd->status.account_id, index-1) )
	{
		Sql_ShowDebug(mail_handle);
		return 0;
	}

	if( 0 == Sql_NumRows(mail_handle) )
	{
		clif_displaymessage(sd->fd, msg_txt(517)); // "Message not found."
		Sql_FreeResult(mail_handle);
		return 0;
	}

	if( SQL_ERROR == Sql_NextRow(mail_handle) )
	{
		Sql_ShowDebug(mail_handle);
		Sql_FreeResult(mail_handle);
		return 0;
	}

	Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data);
	Sql_GetData(mail_handle, 1, &data, NULL); read_flag = (bool)atoi(data);
	Sql_GetData(mail_handle, 2, &data, NULL); priority_flag = (bool)atoi(data);
	Sql_GetData(mail_handle, 3, &data, NULL); check_flag = (bool)atoi(data);

	Sql_FreeResult(mail_handle);

	if( !read_flag && priority_flag )
	{
		clif_displaymessage(sd->fd,msg_txt(519)); // "Cannot delete unread priority mail."
		return 0;
	}

	if( !check_flag )
	{
		clif_displaymessage(sd->fd,msg_txt(520)); // "You have received new mail, use @listmail before deleting."
		return 0;
	}

	if( SQL_ERROR == Sql_Query(mail_handle, "DELETE FROM `%s` WHERE `message_id` = %d", mail_db, message_id) )
	{
		Sql_ShowDebug(mail_handle);
		return 0;
	}

	clif_displaymessage(sd->fd,msg_txt(521)); // "Message deleted."

	return 0;
}

/// for sending normal and priority messages
int mail_send(struct map_session_data* sd, char* name, char* message, int flag)
{
	SqlStmt* stmt;

	nullpo_retr (0, sd);

	if( pc_isGM(sd) < 80 && sd->mail_counter > 0 )
	{
		clif_displaymessage(sd->fd,msg_txt(522)); // "You must wait 10 minutes before sending another message"
		return 0;
	}

	if( strcmp(name,"*") == 0 && pc_isGM(sd) < 80 )
	{
		clif_displaymessage(sd->fd, msg_txt(523)); // "Access Denied."
		return 0;
	}

	if( strcmp(name,"*") == 0 )
	{
		if( SQL_ERROR == Sql_Query(mail_handle, "SELECT DISTINCT `account_id` FROM `%s` WHERE `account_id` != '%d' ORDER BY `account_id`", char_db, sd->status.account_id) )
		{
			Sql_ShowDebug(mail_handle);
			return 0;
		}
	}
	else
	{
		char name_[2*NAME_LENGTH];
		Sql_EscapeString(mail_handle, name_, name);
		if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `account_id` FROM `%s` WHERE `name` = '%s'", char_db, name_) )
		{
			Sql_ShowDebug(mail_handle);
			return 0;
		}
	}

	if( 0 == Sql_NumRows(mail_handle) )
	{
		clif_displaymessage(sd->fd,msg_txt(524)); // "Character does not exist."
		Sql_FreeResult(mail_handle);
		return 0;
	}

	stmt = SqlStmt_Malloc(mail_handle);
	SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`to_account_id`,`to_char_name`,`from_account_id`,`from_char_name`,`message`,`priority`) VALUES (?, ?, '%d', ?, ?, '%d')", mail_db, sd->status.account_id, flag);
	SqlStmt_BindParam(stmt, 1, SQLDT_STRING, name, strnlen(name, NAME_LENGTH));
	SqlStmt_BindParam(stmt, 2, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH));
	SqlStmt_BindParam(stmt, 3, SQLDT_STRING, message, strnlen(message, 80));

	while( SQL_SUCCESS == Sql_NextRow(mail_handle) )
	{
		int id;
		char* data;
		Sql_GetData(mail_handle, 0, &data, NULL); id = atoi(data);
		SqlStmt_BindParam(stmt, 0, SQLDT_INT, &id, sizeof(id));
		if( SQL_ERROR == SqlStmt_Execute(stmt) )
			SqlStmt_ShowDebug(stmt);
	}
	Sql_FreeResult(mail_handle);
	SqlStmt_Free(stmt);

	if(pc_isGM(sd) < 80)
		sd->mail_counter = 5;

	clif_displaymessage(sd->fd,msg_txt(525)); // "Mail has been sent."

	return 0;
}

/// invoked every MAIL_CHECK_TIME ms, decreases the send blocking counter
static int mail_check_timer_sub(struct map_session_data* sd, va_list va)
{
	if(sd->mail_counter > 0)
		sd->mail_counter--;
	return 0;
}

/// periodically checks for new messages and notifies about them
int mail_check_timer(int tid, unsigned int tick, int id, int data)
{
	if(mail_timer != tid)
		return 0;

	mail_timer = add_timer(gettick() + MAIL_CHECK_TIME, mail_check_timer, 0, 0);

	// fetch account ids of people who received new mail since the last iteration
	if( SQL_ERROR == Sql_Query(mail_handle, "SELECT DISTINCT `to_account_id` FROM `%s` WHERE `read_flag` = '0' AND `check_flag` = '0'", mail_db) )
	{
		Sql_ShowDebug(mail_handle);
		return 0;
	}

	while( SQL_SUCCESS == Sql_NextRow(mail_handle) )
	{
		char* id;
		struct map_session_data* sd;
		Sql_GetData(mail_handle, 0, &id, NULL);
		if( (sd = map_id2sd(atoi(id))) != NULL )
			clif_displaymessage(sd->fd, msg_txt(526)); // "You have new mail."
	}

	Sql_FreeResult(mail_handle);

	// decrease the send-blocking counter
	clif_foreachclient(mail_check_timer_sub);

	// The 'check_flag' indicates whether the player was informed about the message.
	// All online players were notified by the above code, and offline players will get the notice at next login.
	// Therefore it is safe to simply set the flag to '1' for all existing mails.
	if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `check_flag` = 0", mail_db) )
		Sql_ShowDebug(mail_handle);

	return 0;
}

int do_init_mail(void)
{
	add_timer_func_list(mail_check_timer, "mail_check_timer");
	mail_timer = add_timer(gettick() + MAIL_CHECK_TIME, mail_check_timer, 0, 0);

	return 0;
}

#endif