All events, such as live sessions, voicemails, SMS messages, file transfers, etc. are reflected in the SkypeKit API as Message objects. In order to retrieve a historic list of certain type of events, you will need to obtain a list of corresponding messages.
As of SDK version 4.0, the SkypeKit API includes a much better way of doing this - Skype::GetMessageListByType
This method enables you to retrieve messages of certain Message::TYPE accross all conversations. For example, to retrieve a "global" list of file transfers, you could use skype->GetMessageListByType(Message::POSTED_FILES, false, history, fromTime, toTime) and you would end up with all the file transfer related messages in the given time period, neatly in the history argument.
The only problem then is that most of the relevant info you might want to display in your UI, for each of those Message objects, is encoded in the type-specific Message::P_BODY_XML property.
In this exercise, we will look into how this can be done for:
/**************************************************************************** Getting Started With SkypeKit. Tutorial Application, Step 12. In this exercise, we will assemble an event history, of: 1. Incoming calls 2. Outgoing calls 3. Authorization request 4. Authorizations granted **/ #include "time.h" #include "skype-embedded_2.h" #include "keypair.h" #include "tutorial_common.h" using namespace Sid; SEString myAccountName; SEString myAccountPsw; //---------------------------------------------------------------------------- // Subclassing Contact class MyContact : public Contact { public: typedef DRef<MyContact, Contact> Ref; typedef DRefs<MyContact, Contact> Refs; MyContact(unsigned int oid, SERootObject* root) : Contact(oid, root) {}; }; //---------------------------------------------------------------------------- // Subclassing Skype class MySkype : public Skype { public: MySkype() : Skype() {}; Account* newAccount(int oid) { return new MyAccount(oid, this); }; Contact* newContact(int oid) { return new MyContact(oid, this); }; }; //---------------------------------------------------------------------------- // Main MySkype* skype; int main(int argc, char * argv[]) { printf("*****************************************************************\n"); printf(" SkypeKit Tutorial, Step 12 - Event History.\n"); printf("*****************************************************************\n"); if (argc < 3) { printf("usage: tutorial <skypename> <password>\n"); return 0; }; myAccountName = argv[1]; myAccountPsw = argv[2]; printf("Creating skype ..\n"); skype = new MySkype(); printf("Submitting application token..\n"); getKeyPair (); skype->init(keyBuf, inetAddr, portNum, "streamlog.txt"); skype->start(); printf("Retrieving account ..\n"); MyAccount::Ref account; if (skype->GetAccount(myAccountName, account)) { printf("Logging in..\n"); account->LoginWithPassword(myAccountPsw, false, true); account->BlockWhileLoggingIn(); printf("Loggin complete.\n"); Conversation::Refs conversationList; skype->GetConversationList(conversationList); for (uint i = 0; i < conversationList.size(); i++) { Message::Refs contextMessages; Message::Refs unconsumedMessages; // Replace '0' with real timestamp to get more. conversationList[i]->GetLastMessages(contextMessages, unconsumedMessages, 0); for (int k = 0; k < 2; k++) { Message::Refs loopref; loopref = (k)?contextMessages:unconsumedMessages; int messageRefsCount=loopref.size(); for (int j = 0; j < messageRefsCount; j++) { Message::TYPE msgType=(Message::TYPE)atoi((const char*)(loopref[j]->GetProp(Message::P_TYPE))); switch (msgType) { case Message::STARTED_LIVESESSION: { // Message::P_AUTHOR tells who initiated the call. SEString author=loopref[j]->GetProp(Message::P_AUTHOR); // For duration we unfortunately have to parse the XML // the duration that interests me is in // <part identity="&me">\n<duration>x</duration>... // // Real implementation should use a proper xml-parser here SEString body=loopref[j]->GetProp(Message::P_BODY_XML); const char *body_str=(const char*)body; char partname[256]; snprintf(partname,256,"<part identity=\"%s\">",(const char*)myAccountName); const char *my_part=strstr(body_str,partname); int duration=-1; if (my_part) { const char *my_part_end=strstr(my_part,"</part>"); if (my_part_end) { const char *duration_str=strstr(my_part,"<duration>"); if (duration_str && duration_str<my_part_end) { duration_str+=strlen("<duration>"); duration=atoi(duration_str); } } } // ditto for counting how many parts the body has. int num_parts=0; char *tmp=(char*)body_str; while ((tmp=strstr(tmp,"<part"))) { tmp++; num_parts++; } // get identities SEString identities=loopref[j]->GetProp(Message::P_IDENTITIES); // timestamp time_t timestamp=loopref[j]->GetUintProp(Message::P_TIMESTAMP); char *time_str=ctime(×tamp); time_str[24]=0; // remove newline // last part is to fetch message reason SEString reason=loopref[j]->GetProp(Message::P_REASON); printf("[%s] ",time_str); if (!strcmp((const char*)author,(const char*)myAccountName)) { // I was the initiator printf("outgoing call to %s: ",(const char*)identities); } else { // somebody else called printf("incoming call from %s: ",(const char*)identities); } if (duration>=0) { printf("duration %d seconds\n",duration); } else { if (num_parts>1) { if (!strcmp((const char*)reason,"manual")) { printf("refused\n"); } else { printf("failed (%s)\n",(const char*)reason); } } else { printf("missed\n"); } } } break; case Message::POSTED_VOICE_MESSAGE: { SEString author=loopref[j]->GetProp(Message::P_AUTHOR); // XML parsing again... SEString body=loopref[j]->GetProp(Message::P_BODY_XML); const char *body_str=(const char*)body; int length=0; const char *len_str=strstr(body_str,"<length>"); if (len_str) { len_str+=strlen("<length>"); length=atoi(len_str); } // get identities SEString identities=loopref[j]->GetProp(Message::P_IDENTITIES); // timestamp time_t timestamp=loopref[j]->GetUintProp(Message::P_TIMESTAMP); char *time_str=ctime(×tamp); time_str[24]=0; // remove newline printf("[%s] ",time_str); if (!strcmp((const char*)author,(const char*)myAccountName)) { // I was the initiator printf("Sent voicemail to %s: ",(const char*)identities); } else { // somebody else called printf("Got voicemail from %s: ",(const char*)identities); } printf("duration %d\n",length); } break; case Message::REQUESTED_AUTH: // Please note that REQUESTED_AUTH is not used to request authorization // ALERT is used for that. REQUESTED_AUTH is used only for history { SEString author=loopref[j]->GetProp(Message::P_AUTHOR); // get identities SEString identities=loopref[j]->GetProp(Message::P_IDENTITIES); // timestamp time_t timestamp=loopref[j]->GetUintProp(Message::P_TIMESTAMP); char *time_str=ctime(×tamp); time_str[24]=0; // remove newline printf("[%s] ",time_str); printf("Authorization request from %s to %s\n",(const char*)author,(const char*)identities); } break; case Message::GRANTED_AUTH: { SEString author=loopref[j]->GetProp(Message::P_AUTHOR); // get identities SEString identities=loopref[j]->GetProp(Message::P_IDENTITIES); // timestamp time_t timestamp=loopref[j]->GetUintProp(Message::P_TIMESTAMP); char *time_str=ctime(×tamp); time_str[24]=0; // remove newline printf("[%s] ",time_str); printf("%s granted authorization to %s\n",(const char*)author,(const char*)identities); } break; default: break; } } } } printf("Press ENTER to quit.\n"); getchar(); printf("Logging out..\n"); account->Logout(false); account->BlockWhileLoggingOut(); printf("Logout complete.\n"); } else { printf("Account does not exist\n"); }; printf("Cleaning up.\n"); skype->stop(); delete skype; printf("Done.\n"); return 0; };
(c) Skype Technologies S.A. Confidential/Proprietary
Last updated: Fri Mar 16 2012