Example #1
0
void ChangeProtoMessages(char* szProto, int iMode, TCString &Msg)
{
	TCString CurMsg(Msg);
	if (szProto)
	{
		if (Msg == NULL)
		{
			CurMsg = GetDynamicStatMsg(INVALID_HANDLE_VALUE, szProto);
		}
		CallAllowedPS_SETAWAYMSG(szProto, iMode, (char*)TCHAR2ANSI(CurMsg));
		g_ProtoStates[szProto].CurStatusMsg = CurMsg;
	} else // change message of all protocols
	{
		int ProtoCount;
		PROTOCOLDESCRIPTOR **proto;
		CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&ProtoCount, (LPARAM)&proto);
		int I;
		for (I = 0; I < ProtoCount; I++)
		{
			if (proto[I]->type == PROTOTYPE_PROTOCOL && !DBGetContactSettingByte(NULL, proto[I]->szName, "LockMainStatus", 0))
			{
				if (Msg == NULL)
				{
					CurMsg = GetDynamicStatMsg(INVALID_HANDLE_VALUE, proto[I]->szName);
				}
				CallAllowedPS_SETAWAYMSG(proto[I]->szName, iMode, (char*)TCHAR2ANSI(CurMsg));
				g_ProtoStates[proto[I]->szName].CurStatusMsg = CurMsg;
			}
		}
	}
	static struct
	{
		int Status;
		char *Setting;
	} StatusSettings[] = {
		ID_STATUS_OFFLINE, "Off",
		ID_STATUS_ONLINE, "On",
		ID_STATUS_AWAY, "Away",
		ID_STATUS_NA, "Na",
		ID_STATUS_DND, "Dnd",
		ID_STATUS_OCCUPIED, "Occupied",
		ID_STATUS_FREECHAT, "FreeChat",
		ID_STATUS_INVISIBLE, "Inv",
		ID_STATUS_ONTHEPHONE, "Otp",
		ID_STATUS_OUTTOLUNCH, "Otl",
		ID_STATUS_IDLE, "Idl"
	};
	int I;
	for (I = 0; I < lengthof(StatusSettings); I++)
	{
		if (iMode == StatusSettings[I].Status)
		{
			DBWriteContactSettingTString(NULL, "SRAway", CString(StatusSettings[I].Setting) + "Msg", CurMsg);
			DBWriteContactSettingTString(NULL, "SRAway", CString(StatusSettings[I].Setting) + "Default", CurMsg); // TODO: make it more accurate, and change not only here, but when changing status messages through UpdateMsgsTimerFunc too; and when changing messages through AutoAway() ?
			break;
		}
	}
//	InitUpdateMsgs();
}
Example #2
0
void ChangeProtoMessages(char* szProto, int iMode, TCString &Msg)
{
	TCString CurMsg(Msg);
	if (szProto) {
		if (Msg == NULL)
			CurMsg = GetDynamicStatMsg(INVALID_CONTACT_ID, szProto);

		CallAllowedPS_SETAWAYMSG(szProto, iMode, (char*)_T2A(CurMsg));
		g_ProtoStates[szProto].CurStatusMsg = CurMsg;
	}
	else { // change message of all protocols
		int numAccs;
		PROTOACCOUNT **accs;
		ProtoEnumAccounts(&numAccs, &accs);
		for (int i = 0; i < numAccs; i++) {
			PROTOACCOUNT *p = accs[i];
			if (!db_get_b(NULL, p->szModuleName, "LockMainStatus", 0)) {
				if (Msg == NULL)
					CurMsg = GetDynamicStatMsg(INVALID_CONTACT_ID, p->szModuleName);

				CallAllowedPS_SETAWAYMSG(p->szModuleName, iMode, (char*)_T2A(CurMsg));
				g_ProtoStates[p->szModuleName].CurStatusMsg = CurMsg;
			}
		}
	}

	static struct
	{
		int Status;
		char *Setting;
	} StatusSettings[] = {
		ID_STATUS_OFFLINE, "Off",
		ID_STATUS_ONLINE, "On",
		ID_STATUS_AWAY, "Away",
		ID_STATUS_NA, "Na",
		ID_STATUS_DND, "Dnd",
		ID_STATUS_OCCUPIED, "Occupied",
		ID_STATUS_FREECHAT, "FreeChat",
		ID_STATUS_INVISIBLE, "Inv",
		ID_STATUS_ONTHEPHONE, "Otp",
		ID_STATUS_OUTTOLUNCH, "Otl",
		ID_STATUS_IDLE, "Idl"
	};

	for (int i = 0; i < SIZEOF(StatusSettings); i++) {
		if (iMode == StatusSettings[i].Status) {
			db_set_ts(NULL, "SRAway", CString(StatusSettings[i].Setting) + "Msg", CurMsg);
			db_set_ts(NULL, "SRAway", CString(StatusSettings[i].Setting) + "Default", CurMsg); // TODO: make it more accurate, and change not only here, but when changing status messages through UpdateMsgsTimerFunc too; and when changing messages through AutoAway() ?
			break;
		}
	}
	//	InitUpdateMsgs();
}
Example #3
0
void __cdecl UpdateMsgsThreadProc(void *)
{
	int ProtoCount;
	PROTOCOLDESCRIPTOR **proto;
	CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&ProtoCount, (LPARAM)&proto);
	int I;
	while (WaitForSingleObject(g_hTerminateUpdateMsgsThread, 0) == WAIT_TIMEOUT && !Miranda_Terminated())
	{
		DWORD MinUpdateTimeDifference = g_MoreOptPage.GetDBValueCopy(IDC_MOREOPTDLG_UPDATEMSGSPERIOD) * 1000; // in milliseconds
		for (I = 0; I < ProtoCount; I++)
		{
			if (proto[I]->type == PROTOTYPE_PROTOCOL && CallProtoService(proto[I]->szName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND && !IsAnICQProto(proto[I]->szName))
			{
				int Status = CallProtoService(proto[I]->szName, PS_GETSTATUS, 0, 0);
				if (Status < ID_STATUS_OFFLINE || Status > ID_STATUS_OUTTOLUNCH)
				{
					Status = g_ProtoStates[proto[I]->szName].Status;
				}
				if (CallProtoService(proto[I]->szName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(Status) && g_ProtoStates[proto[I]->szName].CurStatusMsg.GetUpdateTimeDifference() >= MinUpdateTimeDifference)
				{
					TCString CurMsg(GetDynamicStatMsg(INVALID_HANDLE_VALUE, proto[I]->szName));
					if ((TCString)g_ProtoStates[proto[I]->szName].CurStatusMsg != (const TCHAR*)CurMsg) // if the message has changed
					{
						g_ProtoStates[proto[I]->szName].CurStatusMsg = CurMsg;
						CallAllowedPS_SETAWAYMSG(proto[I]->szName, Status, (char*)TCHAR2ANSI(CurMsg));
					}
				}
			}
		}
		SleepEx(PARSE_INTERVAL, true);
	}
}
Example #4
0
void __cdecl UpdateMsgsThreadProc(void *)
{
	int numAccs;
	PROTOACCOUNT **accs;
	ProtoEnumAccounts(&numAccs, &accs);

	while (WaitForSingleObject(g_hTerminateUpdateMsgsThread, 0) == WAIT_TIMEOUT && !Miranda_Terminated()) {
		DWORD MinUpdateTimeDifference = g_MoreOptPage.GetDBValueCopy(IDC_MOREOPTDLG_UPDATEMSGSPERIOD) * 1000; // in milliseconds
		for (int i = 0; i < numAccs; i++) {
			PROTOACCOUNT *p = accs[i];
			if (CallProtoService(p->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND && !IsAnICQProto(p->szModuleName)) {
				int Status = CallProtoService(p->szModuleName, PS_GETSTATUS, 0, 0);
				if (Status < ID_STATUS_OFFLINE || Status > ID_STATUS_OUTTOLUNCH) {
					Status = g_ProtoStates[p->szModuleName].Status;
				}
				if (CallProtoService(p->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(Status) && g_ProtoStates[p->szModuleName].CurStatusMsg.GetUpdateTimeDifference() >= MinUpdateTimeDifference) {
					TCString CurMsg(GetDynamicStatMsg(INVALID_CONTACT_ID, p->szModuleName));
					if ((TCString)g_ProtoStates[p->szModuleName].CurStatusMsg != (const TCHAR*)CurMsg) { // if the message has changed
						g_ProtoStates[p->szModuleName].CurStatusMsg = CurMsg;
						CallAllowedPS_SETAWAYMSG(p->szModuleName, Status, (char*)_T2A(CurMsg));
					}
				}
			}
		}
		SleepEx(PARSE_INTERVAL, true);
	}
}
Example #5
0
int StatusMsgReq(WPARAM wParam, LPARAM lParam, CString &szProto)
{
    _ASSERT(szProto != NULL);
    LogMessage("ME_ICQ_STATUSMSGREQ called. szProto=%s, Status=%d, UIN=%d", (char*)szProto, wParam, lParam);
    // find the contact
    char *szFoundProto;
    MCONTACT hFoundContact = NULL; // if we'll find the contact only on some other protocol, but not on szProto, then we'll use that hContact.
    for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) {
        char *szCurProto = GetContactProto(hContact);
        if (db_get_dw(hContact, szCurProto, "UIN", 0) == lParam) {
            szFoundProto = szCurProto;
            hFoundContact = hContact;
            if (!mir_strcmp(szCurProto, szProto))
                break;
        }
    }

    int iMode = ICQStatusToGeneralStatus(wParam);
    if (!hFoundContact)
        hFoundContact = INVALID_CONTACT_ID;
    else if (iMode >= ID_STATUS_ONLINE && iMode <= ID_STATUS_OUTTOLUNCH)
        // don't count xstatus requests
        db_set_w(hFoundContact, MOD_NAME, DB_REQUESTCOUNT, db_get_w(hFoundContact, MOD_NAME, DB_REQUESTCOUNT, 0) + 1);

    MCONTACT hContactForSettings = hFoundContact; // used to take into account not-on-list contacts when getting contact settings, but at the same time allows to get correct contact info for contacts that are in the DB
    if (hContactForSettings != INVALID_CONTACT_ID && db_get_b(hContactForSettings, "CList", "NotOnList", 0))
        hContactForSettings = INVALID_CONTACT_ID; // INVALID_HANDLE_VALUE means the contact is not-on-list

    if (g_SetAwayMsgPage.GetWnd()) {
        CallAllowedPS_SETAWAYMSG(szProto, iMode, NULL); // we can set status messages to NULL here, as they'll be changed again when the SAM dialog closes.
        return 0;
    }
    if (CContactSettings(iMode, hContactForSettings).Ignore) {
        CallAllowedPS_SETAWAYMSG(szProto, iMode, _T("")); // currently NULL makes ICQ to ignore _any_ further status message requests until the next PS_SETAWAYMSG, so i can't use it here..
        return 0; // move along, sir
    }

    if (iMode) // if it's not an xstatus message request
        CallAllowedPS_SETAWAYMSG(szProto, iMode, GetDynamicStatMsg(hFoundContact, szProto, lParam));

    //	COptPage PopupNotifyData(g_PopupOptPage);
    //	PopupNotifyData.DBToMem();
    VarParseData.szProto = szProto;
    VarParseData.UIN = lParam;
    VarParseData.Flags = 0;
    if (!iMode)
        VarParseData.Flags |= VPF_XSTATUS;

    return 0;
}
int MsgEventAdded(WPARAM wParam, LPARAM lParam)
{
	HANDLE hContact = (HANDLE)wParam;
	DBEVENTINFO *dbei = (DBEVENTINFO*)lParam;
	if (!hContact)
	{
		return 0;
	}
	if (dbei->flags & DBEF_SENT || (dbei->eventType != EVENTTYPE_MESSAGE && dbei->eventType != EVENTTYPE_URL && dbei->eventType != EVENTTYPE_FILE))
	{
		return 0;
	}
	if (time(NULL) - dbei->timestamp > MAX_REPLY_TIMEDIFF)
	{ // don't reply to offline messages
		return 0;
	}
	char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
	if (!szProto)
	{
		return 0;
	}
	DWORD Flags1 = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0);
	if (!(Flags1 & PF1_IMSEND))
	{ // don't reply to protocols that don't support outgoing messages
		return 0;
	}
	int bMsgWindowIsOpen = MSGWNDOPEN_UNDEFINED;
	if (dbei->flags & DBEF_READ)
	{
		HANDLE hMetaContact;
		if (ServiceExists(MS_MC_GETMETACONTACT) && (hMetaContact = (HANDLE)CallService(MS_MC_GETMETACONTACT, (WPARAM)hContact, 0))) // if it's a subcontact of a metacontact
		{ // ugly workaround for metacontacts, part II
		// remove outdated events first
			DWORD CurTime = time(NULL);
			int I;
			for (I = MetacontactEvents.GetSize() - 1; I >= 0; I--)
			{
				if (CurTime - MetacontactEvents[I].timestamp > MAX_REPLY_TIMEDIFF)
				{
					MetacontactEvents.RemoveElem(I);
				}
			}
		// we compare only event timestamps, and do not look at the message itself. it's unlikely that there'll be two events from a contact at the same second, so it's a trade-off between speed and reliability
			for (I = MetacontactEvents.GetSize() - 1; I >= 0; I--)
			{
				if (MetacontactEvents[I].timestamp == dbei->timestamp && MetacontactEvents[I].hMetaContact == hMetaContact)
				{
					bMsgWindowIsOpen = MetacontactEvents[I].bMsgWindowIsOpen;
					break;
				}
			}
			if (I < 0)
			{
				_ASSERT(0);
				return 0;
			}
		} else
		{
			return 0;
		}
	}
	if (ServiceExists(MS_MC_GETPROTOCOLNAME) && !lstrcmpA(szProto, (char*)CallService(MS_MC_GETPROTOCOLNAME, 0, 0)))
	{ // ugly workaround for metacontacts, part I; store all metacontacts' events to a temporary array, so we'll be able to get the 'source' protocol when subcontact event happens later. we need the protocol to get its status and per-status settings properly
	// remove outdated events first
		DWORD CurTime = time(NULL);
		int I;
		for (I = MetacontactEvents.GetSize() - 1; I >= 0; I--)
		{
			if (CurTime - MetacontactEvents[I].timestamp > MAX_REPLY_TIMEDIFF)
			{
				MetacontactEvents.RemoveElem(I);
			}
		}
	// add the new event and wait for a subcontact's event
		MetacontactEvents.AddElem(CMetacontactEvent(hContact, dbei->timestamp, IsSRMsgWindowOpen(hContact, false)));
		return 0;
	}
	unsigned int iMode = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
	int I;
	for (I = lengthof(StatusModeList) - 1; I >= 0; I--)
	{
		if (iMode == StatusModeList[I].Status)
		{
			break;
		}
	}
	if (I < 0)
	{
		return 0;
	}
	COptPage AutoreplyOptData(g_AutoreplyOptPage);
	AutoreplyOptData.DBToMem();
	if (dbei->eventType == EVENTTYPE_MESSAGE)
	{
		DBWriteContactSettingWord(hContact, MOD_NAME, DB_MESSAGECOUNT, DBGetContactSettingWord(hContact, MOD_NAME, DB_MESSAGECOUNT, 0) + 1); // increment message counter
	}
	if (AutoreplyOptData.GetValue(StatusModeList[I].DisableReplyCtlID))
	{
		return 0;
	}
	HANDLE hContactForSettings = hContact; // used to take into account not-on-list contacts when getting contact settings, but at the same time allows to get correct contact info for contacts that are in the DB
	if (hContactForSettings != INVALID_HANDLE_VALUE && DBGetContactSettingByte(hContactForSettings, "CList", "NotOnList", 0))
	{
		hContactForSettings = INVALID_HANDLE_VALUE; // INVALID_HANDLE_VALUE means the contact is not-on-list
	}
	if (!CContactSettings(iMode, hContactForSettings).Autoreply.IncludingParents(szProto) || CContactSettings(iMode, hContactForSettings).Ignore)
	{
		return 0;
	}
	if (AutoreplyOptData.GetValue(IDC_REPLYDLG_DONTREPLYINVISIBLE))
	{
		WORD ApparentMode = DBGetContactSettingWord(hContact, szProto, "ApparentMode", 0);
		if ((iMode == ID_STATUS_INVISIBLE && (!(Flags1 & PF1_INVISLIST) || ApparentMode != ID_STATUS_ONLINE)) ||
			(Flags1 & PF1_VISLIST && ApparentMode == ID_STATUS_OFFLINE))
		{
			return 0;
		}
	}
	if (AutoreplyOptData.GetValue(IDC_REPLYDLG_ONLYCLOSEDDLGREPLY))
	{
		if (bMsgWindowIsOpen && bMsgWindowIsOpen != MSGWNDOPEN_UNDEFINED)
		{
			return 0;
		}
	// we never get here for a metacontact; we did check for metacontact's window earlier, and here we need to check only for subcontact's window
		if (IsSRMsgWindowOpen(hContact, false))
		{
			return 0;
		}
	}
	if (AutoreplyOptData.GetValue(IDC_REPLYDLG_ONLYIDLEREPLY) && !g_bIsIdle)
	{
		return 0;
	}
	int UIN = 0;
	if (IsAnICQProto(szProto))
	{
		UIN = DBGetContactSettingDword(hContact, szProto, "UIN", 0);
	}
	int SendCount = AutoreplyOptData.GetValue(IDC_REPLYDLG_SENDCOUNT);
	if ((AutoreplyOptData.GetValue(IDC_REPLYDLG_DONTSENDTOICQ) && UIN) || // an icq contact
		(SendCount != -1 && DBGetContactSettingByte(hContact, MOD_NAME, DB_SENDCOUNT, 0) >= SendCount))
	{
		return 0;
	}
	if ((dbei->eventType == EVENTTYPE_MESSAGE && !AutoreplyOptData.GetValue(IDC_REPLYDLG_EVENTMSG)) || (dbei->eventType == EVENTTYPE_URL && !AutoreplyOptData.GetValue(IDC_REPLYDLG_EVENTURL)) || (dbei->eventType == EVENTTYPE_FILE && !AutoreplyOptData.GetValue(IDC_REPLYDLG_EVENTFILE)))
	{
		return 0;
	}
	DBWriteContactSettingByte(hContact, MOD_NAME, DB_SENDCOUNT, DBGetContactSettingByte(hContact, MOD_NAME, DB_SENDCOUNT, 0) + 1);
	GetDynamicStatMsg(hContact); // it updates VarParseData.Message needed for %extratext% in the format
	TCString Reply(*(TCString*)AutoreplyOptData.GetValue(IDC_REPLYDLG_PREFIX));
	if (Reply != NULL && ServiceExists(MS_VARS_FORMATSTRING) && !g_SetAwayMsgPage.GetDBValueCopy(IDS_SAWAYMSG_DISABLEVARIABLES))
	{
		FORMATINFO fi = {0};
		fi.cbSize = sizeof(FORMATINFO);
		fi.tszFormat = Reply;
		fi.hContact = hContact;
		fi.flags = FIF_TCHAR;
		fi.tszExtraText = VarParseData.Message;
		TCHAR *szResult = (TCHAR *)CallService(MS_VARS_FORMATSTRING, (WPARAM)&fi, 0);
		if (szResult != NULL)
		{
			Reply = szResult;
			mir_free(szResult);
		}
	}
	if (Reply.GetLen())
	{
		CAutoreplyData *ad = new CAutoreplyData(hContact, Reply);
		mir_forkthread(AutoreplyDelayThread, ad);
	}
	return 0;
}