Introduction
Some days ago, I was involved in a discussion about ex (ex boyfriend or girlfriend). Well throughout the discussion (it was going fast and colourful seeing what the argument was) between a resentment, a nostalgia and an excessive optimism, a girl says this thing: "My escape ends tomorrow, tomorrow I’ll return to my silence, to my messages first written and then erased in my absence, etc."
Apart from words that could be interpreted more or less sweet, in bold type I’ve highlighted something: a girl was suggesting me a little utility that everyone can develop to try to understand if someone is thinking about us (on Facebook) or not. That girl was talking of a XMPP "composing..." packet that moves on Facebook millions of times!
How to Define Who’s Thinking about You?
Well, Facebook (and the chat in general) allows us to think too much: I could write an entire romance to a beautiful girl, repent and erase it. But I thought about that girl and maybe I was writing the message on the chat.
We all know that while someone writes, Facebook notices that someone is writing. Perhaps an “I’m thinking about you” can be defined as an “I’m writing to you” that stands. If for every "composing..." packet received, I insert an item in a hashtable and let it there since the message arrives on the chat, I can suppose that it was a thought for me! The idea is simple: for every "composing..." received I add an item(Jid, #composing) in a hashtable: if I receive a message from that Jid, I erase the item from the hashtable because the thought was transformed in an action.
Background
Transforming this night romance in a code is pretty simple: another way we use agsXMPP
to comunicate with the Facebook chat and C# to write the logic of the application. The code is extremely simple and it explains itself.
PAY ATTENTION: Before you read the code, remember that your Facebook username isn’t the email you use to register BUT THE NAME THAT COMES AFTER WWW.FACEBOOK.COM/… after login.
The Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using agsXMPP;
using agsXMPP.protocol.client;
using agsXMPP.protocol.iq.roster;
using agsXMPP.Collections;
using agsXMPP.protocol.iq.vcard;
namespace WindowsFormsApplication1
{
class Program
{
static private bool isConn = false;
static XmppClientConnection xmpp = new
XmppClientConnection("chat.facebook.com");
static Dictionary hmt = new Dictionary();
static Dictionary users = new Dictionary();
public static void start()
{
if (isConn)
return;
xmpp.Username = "YOUR_USERNAME";
xmpp.Password = "YOUR_PASSWORD";
xmpp.OnLogin += new ObjectHandler(OnLogin);
xmpp.OnError += new ErrorHandler(xmpp_OnError);
xmpp.OnRosterItem += new
XmppClientConnection.RosterHandler(XmppCon_OnRosterItem);
xmpp.OnAuthError += new XmppElementHandler(xmpp_OnAuthError);
xmpp.OnMessage += new MessageHandler(xmpp_OnMessage);
xmpp.AutoResolveConnectServer = false;
xmpp.Open();
}
static private void VcardResult(object sender, IQ iq, object data)
{
if (iq.Type == IqType.result)
{
Vcard vcard = iq.Vcard;
if (vcard != null)
{
string fullname = vcard.Fullname;
string nickname = vcard.Nickname;
string description = vcard.Description;
Photo photo = vcard.Photo;
if (!users.ContainsKey(iq.GetAttribute("from").ToString()))
{
users.Add(iq.GetAttribute("from").ToString(), vcard);
Console.WriteLine("Ricevuta informazione : " +
vcard.Fullname);
}
}
}
}
static private void XmppCon_OnRosterItem(object sender,agsXMPP.protocol.iq.roster.RosterItem item)
{
if (item.Subscription != SubscriptionType.remove)
{
VcardIq viq = new VcardIq(IqType.get,item.Jid);
xmpp.IqGrabber.SendIq(viq, new IqCB(VcardResult), null);
}
else
users.Remove(item.Jid.ToString());
}
static void xmpp_OnMessage(object sender,agsXMPP.protocol.client.Message msg)
{
if (!isConn)
return;
if (msg.Chatstate.ToString() == "composing")
{
if (!hmt.ContainsKey(msg.From.Bare.ToString()))
{
hmt.Add(msg.From.Bare.ToString(),0);
}
hmt[msg.From.Bare.ToString()]+=1;
return;
}
String a = msg.FirstChild.InnerXml;
if (a == "")
return;
if (hmt.ContainsKey(msg.From.Bare.ToString()))
{
hmt.Remove(msg.From.Bare.ToString());
}
Jid to = msg.From;
string s;
agsXMPP.protocol.client.Message nmsg = new
agsXMPP.protocol.client.Message();
nmsg.Type = agsXMPP.protocol.client.MessageType.chat;
nmsg.To = to;
nmsg.Body = s;
xmpp.Send(nmsg);
}
static void xmpp_OnAuthError(object sender, agsXMPP.Xml.Dom.Element e)
{
isConn = false;
MessageBox.Show("Username / password not valid.\nRiprova!
", "Cilentiamoci.it");
}
static void xmpp_OnError(object sender, Exception ex)
{
isConn = false;
MessageBox.Show("Error:" +ex.Message, "test.it");
}
static private void OnLogin(object sender)
{
Presence p = new Presence(ShowType.chat, "Online");
p.Type = PresenceType.available;
xmpp.Send(p);
isConn = true;
Console.WriteLine("Connected...\n\nauditing...");
xmpp.RequestRoster();
}
static private void stop()
{
if (!isConn)
return;
xmpp.Close();
isConn = false;
}
[STAThread]
static void Main()
{
start();
DateTime d1 = DateTime.Now;
while (true)
{
TimeSpan x = DateTime.Now - d1;
if (x.Seconds>5)
{
Console.WriteLine("\n\nwho think you?...\n");
d1 = DateTime.Now;
if (hmt.Count == 0)
{
Console.WriteLine("\nI'm sorry... no one think you :D");
}
foreach (KeyValuePair entry in hmt)
{
string uname = entry.Key;
if (users.ContainsKey(uname))
uname = users[uname].Fullname;
Console.WriteLine("\t" + uname + "\t" + entry.Value);
}
}
}
}
}
}