Showing posts with label icq. Show all posts
Showing posts with label icq. Show all posts

Wednesday, September 18, 2013

Написание бота для icq или как работать xmpp протоколом используя gateway openfire сервера.

Решил я сделать бота для работы с аськой, основной задачей которого было бы делать рассылки менеджерам, а также напоминание и возможно формирования дополнительных ""плюшек". Основной проблемой стало то, что в организации повально используется icq как основное средство общения. В начале было решил работать с с протоколом oscar, но само время icq уже подходит на нет - реализацию через прямой протокол я прекратил, тем более в памяти возникали воспоминания, про то как icq меняла свой протокол и возникавшими проблемами у других клиентов.
Сейчас пытаюсь понять какой веб портал было бы оптимально использовать для работы, перерывая куча документации по порталам и всяким плюшкам к ним, я заметил, что большая часть чатов порталов работает с xmpp серверами и по xmpp протоколу.
Итого после долгих изучений и разговоров был поднят Openfire как xmpp сервер под AD, спасибо habr-у.
Следующий шаг поиск библиотеки под c#. Честно была шальная мысля все прикрутить к самой 1С, но опять обратившись к самому how-to и погуглив в нете, понял что занятие бесперспективное и опасное, основная проблема заключается как раз в работе icq. Поднятие несколько раз соединения для отправки письма клиенту icq будет проблемно, так как сервер icq начнет блокировать соединения.
Поэтому начал смотреть список библиотек под c#, так как было реализовано много проектов на c#.
Первая из них agxmpp имеет 2 типа лицензий и в принципе подходит. На сайте производителя есть также библиотека matrix, но она полностью коммерческая.

итого краткая история формирования:
1. Часть это не сильно долгий по времени, но слабо описанный в нете процесс подключение к openfire, методом научного тыка и перебора удалось подключиться и начать отправлять сообщения внутри сервера.
2. Самая большая проблема это отправка сообщения через транспорт(или же gateway), вот тут пришлось очень сильно повозиться,четкого и грамотного описания как это сделать нет, на сайте разработчиков, в теме с вопросом есть только несколько невнятных ответов без примеров(Тема1, Тема2), и очень скудная документация, зародившая желания написать библиотеку самому.
В итоге после пару дней поиска решения и возникшего желания перейти на другой протокол, нормальных протоколов по c# не было, а вот java были SMACK, после небольшого гугления было найдено решение.


Ну а теперь код под c# с использование библиотеки agxmpp:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using agsXMPP;
using agsXMPP.protocol;
using agsXMPP.protocol.iq;
using agsXMPP.protocol.client;
using agsXMPP.sasl;


using System.Threading;

namespace ConsoleApplicationJabber
{
    class Program
    {
        static XmppClientConnection xmpp;
        static bool _wait;

        [STAThread]
        static void Main(string[] args)
        {
            
            string user = "user";
            string pass = "password";

            //Console.WriteLine("Press Key!");
            //Console.ReadLine();
            Jid jid = new Jid(user+"@domain");
            xmpp = new XmppClientConnection();
            xmpp.Server = jid.Server;
            xmpp.Username = jid.User;
            xmpp.ConnectServer = "NameServer.domain";
            xmpp.UseSSL = false;
            
            xmpp.AutoResolveConnectServer = false;
            xmpp.AutoPresence = false;
            xmpp.AutoRoster = false;
            xmpp.AutoAgents = false;


            xmpp.OnReadXml += new agsXMPP.XmlHandler(xmpp_OnReadXml);
            xmpp.OnWriteXml += new agsXMPP.XmlHandler(xmpp_OnWriteXml);
            xmpp.OnLogin += new ObjectHandler(xmpp_OnLogin);
            xmpp.OnError += new agsXMPP.ErrorHandler(xmpp_OnError);
            xmpp.OnSaslStart += new SaslEventHandler(XmppCon_OnSaslStart);
            xmpp.OnPresence += new PresenceHandler(xmpp_OnPresence);
            xmpp.OnMessage += new MessageHandler(xmpp_OnMessage);
            xmpp.OnAgentStart += new ObjectHandler(XmppCon_OnAgentStart);
            xmpp.OnAgentEnd += new ObjectHandler(XmppCon_OnAgentEnd);
            xmpp.OnAgentItem += new agsXMPP.XmppClientConnection.AgentHandler(XmppCon_OnAgentItem);
            xmpp.OnIq+= new IqHandler(xmpp_onIQ);

            try
            {
                xmpp.Open(user, pass, "ConsoleClient", 5);
             }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.Write("Wait for Login ");
            _wait = true;
            int i=0;
            do
            {
                Console.Write(".");
                i++;
                if (i == 10)
                    _wait = false;
                Thread.Sleep(500);
            } while (_wait); 


            Presence p = new Presence(ShowType.chat, "Online");
            p.Type = PresenceType.available;
            
            xmpp.Send(p);

        
            xmpp.AutoAgents = false;

            IQ iq = new IQ();
            iq.Type = IqType.set;
            iq.To = new Jid("icq.domain"); // тут название трансопрта
            
            iq.SetAttribute("username","NumberICQ"); // номер icq
            iq.SetAttribute("password", "PasswordICQ"); 
            xmpp.Send(iq);

            Thread.Sleep(5000);

            xmpp.Send(new Message(new Jid("UserToICQ@icq.domain"), MessageType.chat, "Hello, how are you?" + DateTime.Now.ToLongTimeString()));

            

            //while (true)
            //{
            //    System.Threading.Thread.Sleep(100);
            //};

            Console.WriteLine("End work. Press Key!");
            
            xmpp.Close();
            Console.ReadLine();
        }



        static void xmpp_onIQ(object sender, IQ iq)
        {
          
        }


        static void XmppCon_OnAgentStart(object sender)
        {

        }

        static void XmppCon_OnAgentEnd(object sender)
        {

        }

        static void XmppCon_OnAgentItem(object sender, agsXMPP.protocol.iq.agent.Agent agent)
        {

        }


        static void xmpp_OnMessage(object sender, agsXMPP.protocol.client.Message msg)
        {
            if (msg.Body != null)
            {
                Console.ForegroundColor = ConsoleColor.Blue;
                Console.WriteLine("{0}>> {1}", msg.From.User, msg.Body);                
                Console.ResetColor();                
            }
        }

        static void xmpp_OnPresence(object sender, Presence pres)
        {
            Console.WriteLine("Available Contacts: ");
            Console.WriteLine("{0}@{1}  {2}",        pres.From.User,pres.From.Server,pres.Type);
            Console.WriteLine();            
        }

        static void MessageCallBack(object sender, agsXMPP.protocol.client.Message msg, object data)
        {
            if (msg.Body != null)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("{0}>> {1}", msg.From.User, msg.Body);
                Console.ResetColor();
                
               
                //Console.ForegroundColor = ConsoleColor.Green;
            }
        } 


        private static void XmppCon_OnSaslStart(object sender, SaslEventArgs args)
        {
            args.Auto = false;
            args.Mechanism = agsXMPP.protocol.sasl.Mechanism.GetMechanismName(agsXMPP.protocol.sasl.MechanismType.PLAIN);
        }

        private static void xmpp_OnLogin(object sender)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("ok");
            Console.WriteLine("we are logged in to the server now");
            Console.ResetColor();
            xmpp.SendMyPresence();
            
            _wait = false;
        }

        private static void xmpp_OnError(object sender, Exception ex)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(ex.Message);
            Console.ResetColor();
        }

        private static void xmpp_OnReadXml(object sender, string xml)
        {
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.WriteLine("RECV XML: " + xml);
            Console.ResetColor();
        }

        private static void xmpp_OnWriteXml(object sender, string xml)
        {
            Console.ForegroundColor = ConsoleColor.DarkMagenta;
            Console.WriteLine("SEND XML: " + xml);
            Console.ResetColor();
        }
    }
}