Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.
Keywords: Messenger Chat Type Client
NOTE: It does not have much in the way of comments, error handling, it's very limited and may not be that stable.
But it works. It allows you to send and receive messages. I've only tested it with one chat at a time but it might work with more :)
It you want more information about the protocol that MSM uses have a look at http://www.hypothetic.org/docs/msn/
; Basic MS Messenger client in Winbatch ; Protocol details from http://www.hypothetic.org/docs/msn/ ; By Iain Dickason (iain@caverock.net) 7/11/02 ; Go setup the subroutines and dialog gosub functions ; Needed extender! AddExtender("WWWSK34i.DLL") ; Get .Net e-mail address and password account = AskLine("wbMSM","E-mail address for .Net account to connect with:","") password = AskPassword("wbMSM","Password:") ;set defaults state = -1 ; Used for working out where in the connect system we are retry = 0 reconect = 0 ConnectServer = "messenger.hotmail.com" ; Messenger start server ConnectPort = "1863" ; List of commands and mime types we know about ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 CommandList = "ACK,ADD,ANS,BLP,BYE,CAL,CHG,CHL,FLN,GTC,INF,ILN,IRO,JOI,LST,MSG,NAK,NLN,OUT,QRY,REM,RNG,SYN,USR,VAR,XFR" MSgTypeList = "x-msmsgsprofile,x-msmsgsinitialemailnotification,x-msmsgsemailnotification,x-msmsgsactivemailnotification,x-msmsgscontrol,plain" Contacts = ArrDimension(3) ; 0 = passport, 1 = screen name, 2 = status ContactListChange = @True ArrInitialize(Contacts, "") Chats = ArrDimension(3) ; 0 = socket handle, 1 = index to Contact, 2 = transaction # ArrInitialize(Chats, "") MyStatus = "" LogData = "" OldLogData = "" ChatData = "" OldChatData = "" Text = "" reply = "" sendline = "" ButtonPushed=Dialog("wbMSM") :exit sClose(socket_handle) For c = 1 to ItemCount(Chats[0],@tab) sClose(Chats[0]) Next exit :Functions ; This subroutine is for the inital connection could do with a major re-write. ; each loop round it should do a new section, till it gets moved to a new server and re does the start. #DefineSubroutine Connect() Switch state Case 0 ; Open Socket transaction = 0 socket_handle = sOpen () If !(socket_handle) then retry = retry + 1 Else state = state + 1 EndIf break Case 1 ; Connect If !(sConnect (socket_handle, ConnectServer, ConnectPort)) then state = -1 Else retry = 0 state = state + 1 transaction = 0 EndIf break Case 2 ; Version sendline = StrCat("VER ",transaction," MSNP7 MSNP6 MSNP5 MSNP4 CVR0") If !(sSendLine (socket_handle, sendline)) then state = -1 Else retry = 0 state = state + 1 transaction = transaction + 1 EndIf break Case 3 ; Version reply reply = sRecvLine (socket_handle, 256) If ItemExtract(3,reply," ") == "0" Then sClose(socket_handle) state = -1 Else state = state + 1 EndIf break Case 4 ; Auth request sendline = StrCat("INF ",transaction) If !(sSendLine (socket_handle, sendline)) then state = -1 Else retry = 0 state = state + 1 transaction = transaction + 1 EndIf break Case 5 ; Auth reply reply = sRecvLine (socket_handle, 256) If ItemExtract(3,reply," ") <> "MD5" Then sClose(socket_handle) state = -1 Else retry = 0 state = state + 1 EndIf break Case 6 ; Server request sendline = StrCat("USR ",transaction," MD5 I ",account) If !(sSendLine (socket_handle, sendline)) then state = -1 Else retry = 0 state = state + 1 transaction = transaction + 1 EndIf break Case 7 ; server reply - reply = sRecvLine (socket_handle, 256) If ItemExtract(1,reply," ") == "XFR" Then ; We get told to move to a new server now. retry = 0 state = 0 ; Thats why the state is set back to 0 ConnectServer = ItemExtract(1,ItemExtract(4,reply," "),":") ConnectPort = ItemExtract(2,ItemExtract(4,reply," "),":") sClose(socket_handle) Else If ItemExtract(1,reply," ") == "USR" Then retry = 0 hash = ItemExtract(5,reply," ") state = 8 Else state = -1 EndIf EndIf break Case 8 ; Send hashed password sendline = StrCat("USR ",transaction," MD5 S ",Md5(password,hash)) If !(sSendLine (socket_handle, sendline)) then state = -1 Else retry = 0 state = state + 1 transaction = transaction + 1 EndIf break Case 9 ; Login reply reply = sRecvLine (socket_handle, 256) If ItemExtract(3,reply," ") == "OK" Then retry = 0 state = state + 1 transaction = transaction + 1 Else state = -1 EndIf break EndSwitch If reply <> "" then LogData = StrCat(LogData,">> ",reply,@CRLF) If sendline <> "" then LogData = StrCat(LogData,"<< ",sendline,@CRLF) reply = "" sendline = "" Return state #EndSubroutine ; This gets called once for the main connection and once each for any chats that are open. #DefineSubroutine sysMessages(socket,trans) ; check to see if there is anything waiting to be looked at If !sOK2Recv (socket, 1) then If state == 10 Then ; if this is the first time after we've connected we have to tell the system we are available for chatting sendline = StrCat("CHG ",trans," NLN") sSendLine (socket, sendline) trans = trans + 1 LogData = StrCat(LogData,"<< ",sendline,@CRLF) state = state + 1 EndIf ;If AskYesNo("Exit","Exit?") == @Yes then goto exit return trans EndIf recvLine = sRecvLine (socket, 256) LogData = StrCat(LogData,">> ",recvline,@CRLF) command = ItemExtract(1,recvLine," ") ; All lines should have a 3 letter at the start of them Switch ItemLocate(command,CommandList,",") ; find out which command we are looking at by compareing it with our list Case 5 ; BYE - Someone has left a chat we are in, for the moment we will pretend that the chat only had us and them so we close it ChatName = ItemExtract(2,recvLine," ") chat = ItemLocate(ItemLocate(ChatName,Contacts[0],@tab),Chats[1],@tab) sClose(ItemExtract(chat,Chats[0],@tab)) Chats[0] = ItemRemove(Chat,Chats[0],@tab) Chats[1] = ItemRemove(Chat,Chats[1],@tab) Chats[2] = ItemRemove(Chat,Chats[2],@tab) ChatData = StrCat(ChatData,ChatName," has left chat.",@CRLF) break Case 7 ; CHG - Have been told by the server to change our state (busy, away etc). Dont do anything about it realy. reply_trans = ItemExtract(2,recvLine," ") If reply_trans == 0 Then ; being told to change state by server MyStatus = ItemExtract(3,recvLine," ") Else MyStatus = ItemExtract(3,recvLine," ") EndIf break Case 8 ; CHL - We've been chalenged by MSM we must reply! hash = ItemExtract(3,recvLine," ") sendline = StrCat("QRY ",trans," msmsgs@msnmsgr.com 32",@CRLF,Md5("Q1P7W2E4J9R8U3S5",hash)) sSendString(socket,sendline) LogData = StrCat(LogData,"<< ",sendline,@CRLF) trans = trans + 1 break Case 9 ; FLN - a friend has gone ofline, so we remove them from the list of contacts ContactListChange = @True ContactPassport = ItemExtract(2,recvLine," ") ContactScreenName = ItemExtract(3,recvLine," ") loc = ItemLocate(ContactPassport,Contacts[0],@tab) If loc then Contacts[0] = ItemRemove(loc, Contacts[0], @Tab) Contacts[1] = ItemRemove(loc, Contacts[1], @Tab) Contacts[2] = ItemRemove(loc, Contacts[2], @Tab) EndIf break Case 12 ; ILN - once we connect we will be told if our friends are on, and what state they are in ContactListChange = @True ContactPassport = ItemExtract(4,recvLine," ") ContactScreenName = ItemExtract(5,recvLine," ") ContactStatus = ItemExtract(3,recvLine," ") loc = ItemLocate(ContactPassport,Contacts[0],@tab) If !loc then Contacts[0] = ItemInsert(ContactPassport, -1, Contacts[0], @Tab) Contacts[1] = ItemInsert(ContactScreenName, -1, Contacts[1], @Tab) Contacts[2] = ItemInsert(ContactStatus, -1, Contacts[2], @Tab) Else Contacts[0] = ItemReplace(ContactPassport, loc, Contacts[0], @Tab) Contacts[1] = ItemReplace(ContactScreenName, loc, Contacts[1], @Tab) Contacts[2] = ItemReplace(ContactStatus, loc, Contacts[2], @Tab) EndIf break Case 14 ; JOI - someone has joined a chat we invited them to If ChatPending <> "" then ChatName = ItemExtract(1,ChatPending,@tab) Chat = ItemLocate(ChatName,Contacts[0],@tab) SendText = ItemRemove(1,ChatPending,@tab) msgbody = StrCat("MIME-Version: 1.0",@CRLF,"Content-Type: text/plain; charset=UTF-8",@CRLF) msgbody = StrCat(msgbody,"X-MMS-IM-Format: FN=MS%%20Shell%%20Dlg; EF=; CO=0; CS=0; PF=0",@CRLF,@CRLF) msgbody = StrCat(msgbody,SendText,@CRLF) cmdline = StrCat("MSG ", trans," U ",StrLen(msgbody), @CRLF) sendline = StrCat(cmdline,msgbody) LogData = StrCat(LogData,"<< ",sendline,@CRLF) ChatData = StrCat(ChatData,"To ",ChatName,": ",SendText,@CRLF) sSendString(socket,sendline) trans = trans + 1 ChatPending = "" EndIf break Case 16 ; MSG - we have received a mime type message UserHandle = ItemExtract(2,recvLine," ") MessageSize = ItemExtract(4,recvLine," ") Msg = ReceiveMessage(socket,MessageSize) LogData = StrCat(LogData,Msg,@CRLF) MsgTypeLine = ItemExtract(2,Msg,@CR) MsgType = StrTrim(ItemExtract(2,ItemExtract(2,ItemExtract(1,MsgTypeLine,";"),":"),"/")) If UserHandle == "Hotmail" Then ; is the message a MSM system message? Select ItemLocate(MsgType,MsgTypeList,",") Case 2; inital mail UnreadEmail = StrTrim(ItemExtract(2,ItemExtract(4,Msg,@CR),":")) If UnreadEmail > 0 then ChatData = StrCat(ChatData,"Unread e-mail Inbox: ",UnreadEmail,@CRLF) EndIf break Case 3; New Mail MailFrom = ItemExtract(2,ItemExtract(4,Msg,@CR),":") ChatData = StrCat(ChatData,"New mail received from '",MailFrom,"'",@CRLF) break EndSelect Else ; nope.. mostlikly a chat message from a friend. (have to deal with typeing message) ChatMsg = Msg For line = 1 to 4 ChatMsg = ItemRemove(1,ChatMsg,@CR) Next line ChatMsg = StrTrim(StrReplace(ChatMsg,@lf,"")) ChatData = StrCat(ChatData,UserHandle,":",ChatMsg,@CRLF) EndIf break Case 18 ; NLN - a friend is now online so we add them to the list of contacts ContactListChange = @True ContactPassport = ItemExtract(3,recvLine," ") ContactScreenName = ItemExtract(4,recvLine," ") ContactStatus = ItemExtract(2,recvLine," ") loc = ItemLocate(ContactPassport,Contacts[0],@tab) If !loc then Contacts[0] = ItemInsert(ContactPassport, -1, Contacts[0], @Tab) Contacts[1] = ItemInsert(ContactScreenName, -1, Contacts[1], @Tab) Contacts[2] = ItemInsert(ContactStatus, -1, Contacts[2], @Tab) Else Contacts[0] = ItemReplace(ContactPassport, loc, Contacts[0], @Tab) Contacts[1] = ItemReplace(ContactScreenName, loc, Contacts[1], @Tab) Contacts[2] = ItemReplace(ContactStatus, loc, Contacts[2], @Tab) EndIf break Case 20 ; QRY break Case 22 ; RNG - Ohh.. we're being invited to a chat.... SessionID = ItemExtract(2, recvLine, " ") sbServer = ItemExtract(3, recvLine, " ") ChatHash = ItemExtract(5, recvLine, " ") ChatName = ItemExtract(6, recvLine, " ") loc = ItemLocate(ChatName, Contacts[0], @tab) If loc then Chats[0] = ItemInsert(sOpen (), -1, Chats[0],@tab) Chats[1] = ItemInsert(loc, -1,Chats[1], @tab) Chats[2] = ItemInsert(2,-1,Chats[2],@Tab) Chat = ItemLocate(loc,Chats[1],@tab) If !sConnect (ItemExtract(Chat,Chats[0],@tab), ItemExtract(1,sbServer,":"), ItemExtract(2,sbServer,":")) Chats[0] = ItemRemove(Chat,Chats[0],@tab) Chats[1] = ItemRemove(Chat,Chats[1],@tab) Chats[2] = ItemRemove(Chat,Chats[2],@tab) LogData = StrCat(LogData,"Chat failed",@CRLF) break EndIf sendline = StrCat("ANS 1 ",account," ",ChatHash," ",SessionID,@CRLF) sSendString(ItemExtract(Chat,Chats[0],@tab),sendline) LogData = StrCat(LogData,"<< ",sendline,@CRLF) EndIf Break Case 24 ; USR - starting off the new chat session, telling the server who we want to chat to. ChatName = ItemExtract(ItemExtract(c,Chats[1],@tab),Contacts[0],@tab) sendline = StrCat("CAL ",trans," ",ChatName,@CRLF) sSendString(ItemExtract(Chat,Chats[0],@tab),sendline) LogData = StrCat(LogData,"<< ",sendline,@CRLF) break Case 26 ; XFR - asking for a switchboard server to start a new chat on. sbServer = ItemExtract(4, recvLine, " ") ChatHash = ItemExtract(6, recvLine, " ") loc = ItemLocate(ItemExtract(1,ChatPending,@tab),Contacts[0],@tab) Chats[0] = ItemInsert(sOpen (), -1, Chats[0],@tab) Chats[1] = ItemInsert(loc, -1,Chats[1], @tab) Chats[2] = ItemInsert(2,-1,Chats[2],@Tab) Chat = ItemLocate(loc,Chats[1],@tab) If !sConnect (ItemExtract(Chat,Chats[0],@tab), ItemExtract(1,sbServer,":"), ItemExtract(2,sbServer,":")) Chats[0] = ItemRemove(Chat,Chats[0],@tab) Chats[1] = ItemRemove(Chat,Chats[1],@tab) Chats[2] = ItemRemove(Chat,Chats[2],@tab) LogData = StrCat(LogData,"Chat failed",@CRLF) break EndIf sendline = StrCat("USR 1 ",account," ",ChatHash,@CRLF) sSendString(ItemExtract(Chat,Chats[0],@tab),sendline) LogData = StrCat(LogData,"<< ",sendline,@CRLF) Break EndSwitch Return trans #EndSubroutine ; to make the MD5 hash we have to send to the server from time to time #DefineFunction Md5(text,hash) handle = BinaryAlloc(StrLen(text)+StrLen(hash)) BinaryPokeStr(handle, 0,StrCat(hash,text)) return StrReplace (BinaryCheckSum(handle,0),"-","") #EndFunction ;receive the rest of a message, we get told how big the message is so its quite easy #DefineFunction ReceiveMessage(socket,size) ret = "" binbuf = BinaryAlloc(1000) BinaryEODSet(binbuf,1000) binaddr=IntControl(42,binbuf,0,0,0) stuff=sRecvBinary(socket, binaddr, size) data=BinaryPeekStr(binbuf,0,size) return data #EndFunction ;Standard dialog control subroutine. We are intrested in a timer and button presses. PROCOPT_INIT = 0 ; Dialog created . PROCOPT_TIMER = 1 ; Timer event PROCOPT_PUSH = 2 ; Pass push/picture button presses. PROCOPT_ITEM = 7 ; ItemList selected #DEFINESUBROUTINE dlg_control(DialogHandle, EventCode, ControlNum, Res4, Res5) switch( EventCode) case PROCOPT_INIT DialogProcOptions(DialogHandle, PROCOPT_TIMER, 100) ; have a go every seccond... could drop this down once connected? DialogProcOptions(DialogHandle, PROCOPT_PUSH, 1) break case PROCOPT_TIMER If (state <> -1) then If (state >= 0 & state < 10) then Connect() Else transaction = sysMessages(socket_handle,transaction) For c = 1 to ItemCount(Chats[0],@tab) new_trans = sysMessages(Chats[0],ItemExtract(c,Chats[2],@tab)) Chats[2] = ItemReplace(new_trans,c,Chats[2],@tab) Next EndIf EndIf If ContactListChange Then ; If the Contact list has changed then update it. DialogControlSet(dialoghandle, 1, 5, Contacts[0]) ContactListChange = @False EndIf LogData = StrReplace(LogData, @CRLF, @CR) If ItemCount(LogData,@CR) > 200 Then LogData = ItemRemove(1,LogData,@CR) LogData = StrReplace(LogData, @CRLF, @CR) If LogData <> OldLogData Then ; If we've changed the log data then we need to update it. DialogControlSet(dialoghandle, 7, 3, LogData) EndIf ChatData = StrReplace(ChatData, @CRLF, @CR) If ItemCount(ChatData,@CR) > 200 Then ChatData = ItemRemove(1,ChatData,@CR) ChatData = StrReplace(ChatData, @CR, @CRLF) If ChatData <> OldChatData Then ; If we've changed the Chat data then we need to update it. DialogControlSet(dialoghandle, 3, 3, ChatData) EndIf OldLogData = LogData OldChatData = ChatData break case PROCOPT_PUSH if ControlNum == 6 ; Send SendText = DialogControlGet(DialogHandle, 5, 3) CurrentContact = DialogControlGet(DialogHandle, 1, 6) chat = ItemLocate(CurrentContact,Contacts[0],@tab) loc = ItemLocate(chat ,Chats[1],@tab) If loc == 0 Then sendline = StrCat("XFR ",transaction," SB",@CRLF) sSendString(socket_handle,sendline) ChatPending = StrCat(CurrentContact,@tab,SendText) Else msgbody = StrCat("MIME-Version: 1.0",@CRLF,"Content-Type: text/plain; charset=UTF-8",@CRLF) msgbody = StrCat(msgbody,"X-MMS-IM-Format: FN=MS%%20Shell%%20Dlg; EF=; CO=0; CS=0; PF=0",@CRLF,@CRLF) msgbody = StrCat(msgbody,SendText,@CRLF) cmdline = StrCat("MSG ", ItemExtract(loc,Chats[2],@tab)," U ",StrLen(msgbody), @CRLF) sendline = StrCat(cmdline,msgbody) LogData = StrCat(LogData,loc,"<< ",sendline,@CRLF) ChatData = StrCat(ChatData,"To ",CurrentContact,": ",SendText,@CRLF) sSendString(ItemExtract(loc,Chats[0],@tab),sendline) trans = ItemExtract(loc,Chats[2],@tab) + 1 Chats[2] = ItemReplace(trans,loc,Chats[2],@tab) EndIf return -2 ; Don't termnate the dialog endif if ControlNum == 8 ; Exit return -1 ; Don't termnate the dialog endif if ControlNum == 9 ; Settings return -2 ; Don't termnate the dialog endif if ControlNum == 10 ; Connect state = 0 return -2 ; Don't termnate the dialog endif break case PROCOPT_ITEM ; dont use this . CurrentContact = DialogControlGet(DialogHandle, 1, 5) break endswitch return -1 #ENDSUBROUTINE wbMSMFormat=`WWWDLGED,6.1` wbMSMCaption=`wbMSM` wbMSMX=-17 wbMSMY=127 wbMSMWidth=274 wbMSMHeight=226 wbMSMNumControls=010 wbMSMProcedure=`dlg_control` wbMSMFont=`DEFAULT` wbMSMTextColor=`DEFAULT` wbMSMBackground=`DEFAULT,DEFAULT` wbMSM001=`211,009,056,092,ITEMBOX,dlg_contactlist,DEFAULT,DEFAULT,1,DEFAULT,DEFAULT,DEFAULT,DEFAULT` wbMSM002=`213,001,024,008,STATICTEXT,DEFAULT,"Contacts",DEFAULT,2,DEFAULT,DEFAULT,DEFAULT,DEFAULT` wbMSM003=`003,011,204,090,MULTILINEBOX,dlg_messages,DEFAULT,DEFAULT,3,8,DEFAULT,DEFAULT,DEFAULT` wbMSM004=`005,001,044,008,STATICTEXT,DEFAULT,"Messages",DEFAULT,4,DEFAULT,DEFAULT,DEFAULT,DEFAULT` wbMSM005=`003,103,204,012,EDITBOX,dlg_editline,DEFAULT,DEFAULT,5,DEFAULT,DEFAULT,DEFAULT,DEFAULT` wbMSM006=`211,105,028,010,PUSHBUTTON,DEFAULT,"Send",1,6,DEFAULT,DEFAULT,DEFAULT,DEFAULT` wbMSM007=`003,119,264,102,MULTILINEBOX,dlg_log,DEFAULT,DEFAULT,7,8,DEFAULT,DEFAULT,DEFAULT` wbMSM008=`179,001,028,010,PUSHBUTTON,DEFAULT,"Exit",2,8,DEFAULT,DEFAULT,DEFAULT,DEFAULT` wbMSM009=`149,001,028,010,PUSHBUTTON,DEFAULT,"Settings",3,8,DEFAULT,DEFAULT,DEFAULT,DEFAULT` wbMSM010=`119,001,028,010,PUSHBUTTON,DEFAULT,"Connect",4,8,DEFAULT,DEFAULT,DEFAULT,DEFAULT` ;ButtonPushed=Dialog("wbMSM") return
Article ID: W15690
File Created: 2003:05:13:11:29:34
Last Updated: 2003:05:13:11:29:34