/* Copyright © 2009 Jim Porter 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 "common.h" #include "proto.h" #include #include void TwitterProto::UpdateChat(const twitter_user &update) { GCDEST gcd = { m_szModuleName }; gcd.ptszID = const_cast(m_tszUserName); gcd.iType = GC_EVENT_MESSAGE; GCEVENT gce = {sizeof(gce)}; gce.pDest = &gcd; gce.dwFlags = GC_TCHAR|GCEF_ADDTOLOG; gce.pDest = &gcd; gce.ptszUID = mir_a2t( update.username.c_str()); gce.bIsMe = (update.username == twit_.get_username()); gce.ptszText = ( TCHAR* )update.status.text.c_str(); gce.time = static_cast(update.status.time); DBVARIANT nick; HANDLE hContact = UsernameToHContact( _A2T(update.username.c_str())); if (hContact && !DBGetContactSettingTString(hContact, "CList", "MyHandle", &nick)) { gce.ptszNick = mir_tstrdup( nick.ptszVal ); DBFreeVariant(&nick); } else gce.ptszNick = mir_a2t( update.username.c_str()); CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast(&gce)); mir_free(const_cast(gce.ptszNick)); mir_free(const_cast(gce.ptszUID)); mir_free(const_cast(gce.ptszText)); } int TwitterProto::OnChatOutgoing(WPARAM wParam, LPARAM lParam) { GCHOOK *hook = reinterpret_cast(lParam); if (strcmp(hook->pDest->pszModule, m_szModuleName)) return 0; TCHAR *text; switch(hook->pDest->iType) { case GC_USER_MESSAGE: text = mir_tstrdup(hook->ptszText); ForkThread(&TwitterProto::SendTweetWorker, this, text); break; case GC_USER_PRIVMESS: text = mir_tstrdup(hook->ptszUID); CallService(MS_MSG_SENDMESSAGE, reinterpret_cast( UsernameToHContact(text)), 0); mir_free(text); break; } return 0; } // TODO: remove nick? void TwitterProto::AddChatContact(const TCHAR *name, const TCHAR *nick) { GCDEST gcd = { m_szModuleName }; gcd.ptszID = const_cast(m_tszUserName); gcd.iType = GC_EVENT_JOIN; GCEVENT gce = {sizeof(gce)}; gce.pDest = &gcd; gce.dwFlags = GC_TCHAR; gce.ptszNick = nick ? nick:name; gce.ptszUID = name; gce.bIsMe = false; gce.ptszStatus = _T("Normal"); gce.time = static_cast(time(0)); CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast(&gce)); } void TwitterProto::DeleteChatContact(const TCHAR *name) { GCDEST gcd = { m_szModuleName }; gcd.ptszID = const_cast(m_tszUserName); gcd.iType = GC_EVENT_PART; GCEVENT gce = {sizeof(gce)}; gce.pDest = &gcd; gce.dwFlags = GC_TCHAR; gce.ptszNick = name; gce.ptszUID = gce.ptszNick; gce.time = static_cast(time(0)); CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast(&gce)); mir_free(const_cast(gce.ptszNick)); } int TwitterProto::OnJoinChat(WPARAM, LPARAM suppress) { GCSESSION gcw = {sizeof(gcw)}; // ***** Create the group chat session gcw.dwFlags = GC_TCHAR; gcw.iType = GCW_CHATROOM; gcw.pszModule = m_szModuleName; gcw.ptszName = m_tszUserName; gcw.ptszID = m_tszUserName; CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw); if (m_iStatus != ID_STATUS_ONLINE) return 0; // ***** Create a group GCDEST gcd = { m_szModuleName }; gcd.ptszID = const_cast(m_tszUserName); GCEVENT gce = {sizeof(gce)}; gce.pDest = &gcd; gce.dwFlags = GC_TCHAR; gcd.iType = GC_EVENT_ADDGROUP; gce.ptszStatus = _T("Normal"); CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast(&gce)); // ***** Hook events HookProtoEvent(ME_GC_EVENT, &TwitterProto::OnChatOutgoing, this); // Note: Initialization will finish up in SetChatStatus, called separately if (!suppress) SetChatStatus(m_iStatus); in_chat_ = true; return 0; } int TwitterProto::OnLeaveChat(WPARAM, LPARAM) { in_chat_ = false; GCDEST gcd = { m_szModuleName }; gcd.ptszID = const_cast(m_tszUserName); gcd.iType = GC_EVENT_CONTROL; GCEVENT gce = {sizeof(gce)}; gce.dwFlags = GC_TCHAR; gce.pDest = &gcd; CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, reinterpret_cast(&gce)); CallServiceSync(MS_GC_EVENT, SESSION_TERMINATE, reinterpret_cast(&gce)); return 0; } void TwitterProto::SetChatStatus(int status) { GCDEST gcd = { m_szModuleName }; gcd.ptszID = const_cast(m_tszUserName); gcd.iType = GC_EVENT_CONTROL; GCEVENT gce = {sizeof(gce)}; gce.dwFlags = GC_TCHAR; gce.pDest = &gcd; if (status == ID_STATUS_ONLINE) { // Add all friends to contact list for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) { if (!IsMyContact(hContact)) continue; DBVARIANT uid, nick; if ( DBGetContactSettingTString(hContact, m_szModuleName, TWITTER_KEY_UN, &uid)) continue; if ( !DBGetContactSettingTString(hContact, "CList", "MyHandle", &nick)) AddChatContact(uid.ptszVal, nick.ptszVal); else AddChatContact(uid.ptszVal); DBFreeVariant(&nick); DBFreeVariant(&uid); } // For some reason, I have to send an INITDONE message, even if I'm not actually // initializing the room... CallServiceSync(MS_GC_EVENT, SESSION_INITDONE, reinterpret_cast(&gce)); CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast(&gce)); } else CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, reinterpret_cast(&gce)); }