/* Plugin of miranda IM(ICQ) for Communicating with users of the baseProtocol. Copyright (C) 2004 Daniel Savi (dss@brturbo.com) -> Based on J. Lawler BaseProtocol <- Added: - plugin option window - make.bat (vc++) - tinyclib http://msdn.microsoft.com/msdnmag/issues/01/01/hood/default.aspx - C++ version Miranda ICQ: the free icq client for MS Windows Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede */ #include "Common.h" HINSTANCE hinstance; HANDLE hPreBuildHook = NULL, hAddEventHook = NULL, hOptHook = NULL, hCheckDefHook = NULL, hOnPreShutdown = NULL, hToggleEnable = NULL, hToggleAutoanswer = NULL; HANDLE hToggle = NULL, hEnableMenu = NULL; BOOL fEnabled, gbVarsServiceExist = FALSE; INT interval; int hLangpack; TCHAR* ptszDefaultMsg[]={ TranslateT("I am currently away. I will reply to you when I am back."), TranslateT("I am currently very busy and can't spare any time to talk with you. Sorry..."), TranslateT("I am not available right now."), TranslateT("I am now doing something, I will talk to you later."), TranslateT("I am on the phone right now. I will get back to you very soon."), TranslateT("I am having meal right now. I will get back to you very soon.") }; PLUGININFOEX pluginInfoEx = { sizeof(PLUGININFOEX), __PLUGIN_NAME, PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), __DESCRIPTION, __AUTHOR, __AUTHOREMAIL, __COPYRIGHT, __AUTHORWEB, UNICODE_AWARE, // {46BF191F-8DFB-4656-88B2-4C20BE4CFA44} {0x46bf191f, 0x8dfb, 0x4656, { 0x88, 0xb2, 0x4c, 0x20, 0xbe, 0x4c, 0xfa, 0x44}} }; extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) { return &pluginInfoEx; } BOOL WINAPI DllMain(HINSTANCE hinst,DWORD fdwReason,LPVOID lpvReserved) { hinstance=hinst; return TRUE; } INT_PTR ToggleEnable(WPARAM wParam, LPARAM lParam) { CLISTMENUITEM mi = { sizeof(mi) }; mi.flags = CMIM_NAME|CMIM_ICON|CMIF_TCHAR; fEnabled = !fEnabled; if (fEnabled) { mi.ptszName = LPGENT("Disable Auto&reply"); mi.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ON)); } else { mi.ptszName = LPGENT("Enable Auto&reply"); mi.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_OFF)); } CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hEnableMenu,(LPARAM)&mi); return 0; } INT_PTR Toggle(WPARAM w, LPARAM l) { HANDLE hContact = (HANDLE)w; BOOL on = 0; on = !DBGetContactSettingByte(hContact, protocolname, "TurnedOn", 0); DBWriteContactSettingByte(hContact, protocolname, "TurnedOn", on ? 1 : 0); on = on?0:1; CLISTMENUITEM mi = { sizeof(mi) }; mi.flags = CMIM_NAME |CMIM_ICON | CMIF_TCHAR; mi.ptszName = on ? LPGENT("Turn off Autoanswer") : LPGENT("Turn on Autoanswer"); mi.hIcon = on ? LoadIcon(hinstance, MAKEINTRESOURCE(IDI_OFF)) : LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ON)); CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hToggle, (LPARAM)&mi); return 0; } INT OnPreBuildContactMenu(WPARAM w, LPARAM l) { HANDLE hContact = (HANDLE)w; CLISTMENUITEM mi = { sizeof(mi) }; mi.flags = CMIM_NAME | CMIM_ICON | CMIF_TCHAR; BOOL on = !DBGetContactSettingByte(hContact, protocolname, "TurnedOn", 0); mi.ptszName = on ? LPGENT("Turn off Autoanswer") : LPGENT("Turn on Autoanswer"); mi.hIcon = on?LoadIcon(hinstance, MAKEINTRESOURCE(IDI_OFF)):LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ON)); CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hToggle, (LPARAM)&mi); return 0; } INT CheckDefaults(WPARAM, LPARAM) { DBVARIANT dbv; TCHAR* ptszDefault; char szStatus[6]={0}; UnhookEvent(hCheckDefHook); fEnabled=!DBGetContactSettingByte(NULL,protocolname,KEY_ENABLED,1)==1; interval=DBGetContactSettingWord(NULL,protocolname,KEY_REPEATINTERVAL,300); if (DBGetContactSettingTString(NULL,protocolname,KEY_HEADING,&dbv)) // Heading not set DBWriteContactSettingTString(NULL,protocolname,KEY_HEADING,TranslateT("Dear %user%, the owner left the following message:")); else DBFreeVariant(&dbv); for (int c=ID_STATUS_ONLINE; c 40078) ptszDefault=ptszDefaultMsg[c-ID_STATUS_ONLINE-3]; if (ptszDefault) DBWriteContactSettingTString(NULL,protocolname,szStatus,ptszDefault); } else DBFreeVariant(&dbv); } } hPreBuildHook = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, OnPreBuildContactMenu); if (ServiceExists(MS_VARS_FORMATSTRING)) gbVarsServiceExist = TRUE; ToggleEnable(0,0); return 0; } TCHAR* StrReplace (TCHAR* Search, TCHAR* Replace, TCHAR* Resource) { int i = 0; int SearchLen = (int)_tcslen(Search); TCHAR* Work = mir_tstrdup(Replace); int ReplaceLen = (int)_tcslen(Work); TCHAR* Pointer = _tcsstr(Resource, Search); while (Pointer != NULL) { int PointerLen = (int)_tcslen(Pointer); int ResourceLen = (int)_tcslen(Resource); TCHAR* NewText = (TCHAR*)mir_calloc((ResourceLen - SearchLen + ReplaceLen + 1)*sizeof(TCHAR)); _tcsncpy(NewText, Resource, ResourceLen - PointerLen); _tcscat(NewText, Work); _tcscat(NewText, Pointer + SearchLen); Resource = (TCHAR*)mir_realloc(Resource, (ResourceLen - SearchLen + ReplaceLen + 1)*sizeof(TCHAR)); for (i = 0; i < (ResourceLen - SearchLen + ReplaceLen); i++) Resource[i] = NewText[i]; Resource[i] = 0; mir_free(NewText); Pointer = _tcsstr(Resource + (ResourceLen - PointerLen + ReplaceLen), Search); } mir_free(Work); return Resource; } INT addEvent(WPARAM wParam, LPARAM lParam) { HANDLE hContact = (HANDLE)wParam; HANDLE hDBEvent = (HANDLE)lParam; DBEVENTINFO dbei = {sizeof(dbei)}; if (!fEnabled || !hContact || !hDBEvent) return FALSE; /// unspecifyed error char* pszProto = GetContactProto(hContact); int status = CallProtoService(pszProto, PS_GETSTATUS, 0, 0); if (status == 40072 || status == 40077 || status == 40078) return FALSE; CallService(MS_DB_EVENT_GET, (WPARAM)hDBEvent, (LPARAM)&dbei); /// detect size of msg if ((dbei.eventType != EVENTTYPE_MESSAGE) || (dbei.flags == DBEF_READ)) return FALSE; /// we need EVENTTYPE_MESSAGE event.. else { /// needed event has occured.. DBVARIANT dbv; if (!dbei.cbBlob) /// invalid size return FALSE; if (DBGetContactSettingTString(hContact,"Protocol","p",&dbv)) // Contact with no protocol ?!! return FALSE; else DBFreeVariant(&dbv); if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)) return FALSE; if(DBGetContactSettingByte(hContact, protocolname, "TurnedOn", 0)) return FALSE; if (!( dbei.flags & DBEF_SENT)) { int timeBetween=time(NULL)-DBGetContactSettingDword(hContact,protocolname,"LastReplyTS",0); if (timeBetween>interval || DBGetContactSettingWord(hContact,protocolname,"LastStatus",0)!=status) { char szStatus[6]={0}; int msgLen=1; int isQun=DBGetContactSettingByte(hContact,pszProto,"IsQun",0); if (isQun) return FALSE; mir_snprintf(szStatus,SIZEOF(szStatus),"%d",status); if (!DBGetContactSettingTString(NULL,protocolname,szStatus,&dbv)) { if (*dbv.ptszVal) { DBVARIANT dbvHead={0}, dbvNick={0}; TCHAR *ptszTemp, *ptszTemp2; DBGetContactSettingTString(hContact,pszProto,"Nick",&dbvNick); if (lstrcmp(dbvNick.ptszVal, NULL) == 0) { DBFreeVariant(&dbvNick); return FALSE; } msgLen += (int)_tcslen(dbv.ptszVal); if (!DBGetContactSettingTString(NULL,protocolname,KEY_HEADING,&dbvHead)) { ptszTemp = (TCHAR*)mir_alloc(sizeof(TCHAR) * (_tcslen(dbvHead.ptszVal)+1)); _tcscpy(ptszTemp, dbvHead.ptszVal); ptszTemp = StrReplace(_T("%user%"), dbvNick.ptszVal, ptszTemp); msgLen += (int)(_tcslen(ptszTemp)); } ptszTemp2 = (TCHAR*)mir_alloc(sizeof(TCHAR) * (msgLen+5)); mir_sntprintf(ptszTemp2, msgLen+5, _T("%s\r\n\r\n%s"), ptszTemp, dbv.ptszVal); if (ServiceExists(MS_VARS_FORMATSTRING)) { FORMATINFO fi; ZeroMemory(&fi, sizeof(fi)); fi.cbSize = sizeof(fi); fi.flags = FIF_TCHAR; fi.tszFormat = ptszTemp2; ptszTemp = (TCHAR*)CallService(MS_VARS_FORMATSTRING, (WPARAM)&fi, 0); }else ptszTemp = Utils_ReplaceVarsT(ptszTemp2); char* pszUtf = mir_utf8encodeT(ptszTemp); CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)pszUtf); dbei.cbSize = sizeof(dbei); dbei.eventType = EVENTTYPE_MESSAGE; dbei.flags = DBEF_UTF | DBEF_SENT; //DBEF_READ; dbei.szModule = pszProto; dbei.timestamp = time(NULL); dbei.cbBlob = lstrlenA(pszUtf) + 1; dbei.pBlob = (PBYTE)pszUtf; CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei); if (ServiceExists(MS_VARS_FORMATSTRING)) CallService(MS_VARS_FREEMEMORY, (WPARAM)ptszTemp, 0); else mir_free(ptszTemp); mir_free(ptszTemp2); mir_free(pszUtf); if (dbvNick.ptszVal) DBFreeVariant(&dbvNick); if (dbvHead.ptszVal) DBFreeVariant(&dbvHead); } DBFreeVariant(&dbv); } } } DBWriteContactSettingDword(hContact,protocolname,"LastReplyTS",time(NULL)); DBWriteContactSettingWord(hContact,protocolname,"LastStatus",status); } return 0; } INT OnPreShutdown(WPARAM wParam, LPARAM lParam) { UnhookEvent(hAddEventHook); UnhookEvent(hPreBuildHook); UnhookEvent(hOptHook); UnhookEvent(hOnPreShutdown); return 0; } extern "C" int __declspec(dllexport)Load(void) { mir_getLP(&pluginInfoEx); hToggleEnable = CreateServiceFunction(protocolname"/ToggleEnable", ToggleEnable); hToggleAutoanswer = CreateServiceFunction(protocolname"/ToggleAutoanswer",Toggle); CLISTMENUITEM mi = { sizeof(mi) }; mi.position = 500090000; mi.ptszName = _T(""); mi.pszService = protocolname"/ToggleEnable"; hEnableMenu = Menu_AddMainMenuItem(&mi); mi.position = -0x7FFFFFFF; mi.ptszName = _T(""); mi.pszService = protocolname"/ToggleAutoanswer"; hToggle = Menu_AddContactMenuItem(&mi); //add hook hOptHook = HookEvent(ME_OPT_INITIALISE, OptInit); hAddEventHook = HookEvent(ME_DB_EVENT_ADDED, addEvent); hCheckDefHook = HookEvent(ME_SYSTEM_MODULESLOADED, CheckDefaults); hOnPreShutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, OnPreShutdown); return 0; } extern "C" __declspec(dllexport)int Unload(void) { DestroyServiceFunction(hToggleEnable); DestroyServiceFunction(hToggleAutoanswer); return 0; }