Commits

Kirill Morarenko  committed 4b2be7b

working python bindings

  • Participants
  • Parent commits 5f48cc9

Comments (0)

Files changed (5)

File CMakeLists.txt

 cmake_minimum_required (VERSION 2.6)
 project (CRG)
 
-add_definitions(-Wall -Werror -DHAVE_BOOST)
+add_definitions(-Wall -Werror -DHAVE_BOOST -ggdb -O0)
 
 add_subdirectory(src)
 add_subdirectory(tests)

File include/channel.h

     public:
 	Channel() : private_(false), id_(0) {}
 	Channel(int id, const std::string& name, const std::string& flags, const std::string& topic) : private_(false), id_(id), name_(name), topic_(topic), flags_(flags) {}
+	~Channel();
+
 	static Channel Private(){
 	    Channel ret;
 	    ret.private_ = true;
     typedef boost::function<void (Avatar&, ChannelList&, const std::string&)> ListChannelsCallback;
     void listChannels(Avatar& avatar, const ListChannelsCallback& cb);
 
-    typedef boost::function<void(Avatar&, const Channel&, const std::string&)> JoinChannelCallback;
+    typedef boost::function<void(Avatar&, Channel&, const std::string&)> JoinChannelCallback;
     void joinChannel(Avatar& avatar, Channel& channel, const JoinChannelCallback& cb);
 }
 

File interfaces/crg.i

 #include "avatar.h"
 #include "datalink.h"
 #include "channel.h"
+#include "message.h"
 #include <boost/bind.hpp>
+#include <iostream>
 %}
 
 #if defined(SWIGPYTHON)
 #endif
 
 %{
-static double PythonCallBack(double a, void *clientdata)
-{
-   PyObject *func, *arglist;
-   PyObject *result;
-   double    dres = 0;
-   
-   func = (PyObject *) clientdata;               // Get Python function
-   arglist = Py_BuildValue("(d)",a);             // Build argument list
-   result = PyEval_CallObject(func,arglist);     // Call Python
-   Py_DECREF(arglist);                           // Trash arglist
-   if (result) {                                 // If no errors, return double
-     dres = PyFloat_AsDouble(result);
-   }
-   Py_XDECREF(result);
-   return dres;
-}
-
  void do_onIdle(PyObject* function){
      PyObject* result = PyEval_CallObject(function, NULL);
      Py_XDECREF(result);
      Py_DECREF(function);
  }
  void do_onList(PyObject* function, chatru::Avatar& avatar, chatru::ChannelList& cl, const std::string& error);
+ void do_onJoin(PyObject* function, chatru::Avatar& avatar, chatru::Channel& cl, const std::string& error){
+     PyObject *obj = SWIG_NewPointerObj(&avatar, SWIGTYPE_p_chatru__Avatar, 0);
+     PyObject *chl = SWIG_NewPointerObj(&cl, SWIGTYPE_p_chatru__Channel, 0);
+     PyObject* arglist = Py_BuildValue("(OOs)", obj, chl, error.c_str());
+     PyObject* result = PyEval_CallObject(function, arglist);
+     Py_DECREF(arglist);
+     Py_XDECREF(result);
+     Py_DECREF(function);
+}
+ void do_onSent(PyObject* function, chatru::Avatar& avatar, const chatru::Channel& cl, const chatru::Message& mg, const std::string& error){
+     PyObject *obj = SWIG_NewPointerObj(&avatar, SWIGTYPE_p_chatru__Avatar, 0);
+     PyObject *chl = SWIG_NewPointerObj(const_cast<void*>((const void*)&cl), SWIGTYPE_p_chatru__Channel, 0);
+     PyObject *msg = SWIG_NewPointerObj(const_cast<void*>((const void*)&mg), SWIGTYPE_p_chatru__Message, 0);
+     PyObject* arglist = Py_BuildValue("(OOOs)", obj, chl, msg, error.c_str());
+     PyObject* result = PyEval_CallObject(function, arglist);
+     Py_DECREF(arglist);
+     Py_XDECREF(result);
+     Py_DECREF(function);
+}
+ void do_onMessage(PyObject* function, chatru::Avatar& avatar, chatru::Message& mg){
+     PyObject *obj = SWIG_NewPointerObj(&avatar, SWIGTYPE_p_chatru__Avatar, 0);
+     PyObject *msg = SWIG_NewPointerObj(const_cast<void*>((const void*)&mg), SWIGTYPE_p_chatru__Message, 0);
+     PyObject* arglist = Py_BuildValue("(OO)", obj, msg);
+     PyObject* result = PyEval_CallObject(function, arglist);
+     Py_DECREF(arglist);
+     Py_XDECREF(result);
+     //Py_DECREF(function);
+}
+
 %}
 
 namespace chatru{
 	}
     };
 
+    %nodefaultctor Channel;
     class Channel{
     public:
 	Channel(int id, const std::string& name, const std::string& flags, const std::string& topic);
 	const int id() const;
 	const std::string& name() const;
     };
+
+    class Message{
+    public:
+	Message(const std::string& text, const std::string& recipient = std::string());
+	Message(int channel_id, long long time, const std::string& type, const std::string& sender, const std::string& recipient, const std::string& text, const std::string& raw);
+	int channel_id() const;
+	const std::string& sender() const;
+	const std::string& recipient() const;
+	const std::string& text() const;
+    };
+
     typedef std::map<int, Channel> ChannelList;
     %template (ChannelList) ::std::map<int, Channel>;
-    //ChannelList a();
-    /*    
-    typedef boost::function<void (Avatar&, ChannelList&, const std::string&)> ListChannelsCallback;
-    void listChannels(Avatar& avatar, const ListChannelsCallback& cb);
 
-    typedef boost::function<void(Avatar&, const Channel&, const std::string&)> JoinChannelCallback;
-    void joinChannel(Avatar& avatar, Channel& channel, const JoinChannelCallback& cb);
-    */
+    chatru::Channel& getChannel(chatru::Avatar& avatar, const chatru::Message& msg);
 };
+
 %inline %{
     void listChannels(PyObject* avatar_ptr, PyObject* onList){
 	chatru::Avatar* avatar;
 	Py_INCREF(onList);
 	chatru::listChannels(*avatar, boost::bind(&do_onList, onList, _1, _2, _3));
     }
+    void joinChannel(PyObject* avatar_ptr, PyObject* channel_ptr, PyObject* onJoin){
+	chatru::Avatar* avatar;
+	if (SWIG_ConvertPtr(avatar_ptr, (void **) &avatar, SWIGTYPE_p_chatru__Avatar, SWIG_POINTER_EXCEPTION) == -1)
+	    return;
+	chatru::Channel* channel;
+	if (SWIG_ConvertPtr(channel_ptr, (void **) &channel, SWIGTYPE_p_chatru__Channel, SWIG_POINTER_EXCEPTION) == -1)
+	    return;
+	Py_INCREF(onJoin);
+	chatru::joinChannel(*avatar, *channel, boost::bind(&do_onJoin, onJoin, _1, _2, _3));
+    }
+    void sendMessage(PyObject* avatar_ptr, PyObject* channel_ptr, PyObject* message_ptr, PyObject* onSent){
+	chatru::Avatar* avatar;
+	if (SWIG_ConvertPtr(avatar_ptr, (void **) &avatar, SWIGTYPE_p_chatru__Avatar, SWIG_POINTER_EXCEPTION) == -1)
+	    return;
+	chatru::Channel* channel;
+	if (SWIG_ConvertPtr(channel_ptr, (void **) &channel, SWIGTYPE_p_chatru__Channel, SWIG_POINTER_EXCEPTION) == -1)
+	    return;
+	chatru::Message* message;
+	if (SWIG_ConvertPtr(message_ptr, (void **) &message, SWIGTYPE_p_chatru__Message, SWIG_POINTER_EXCEPTION) == -1)
+	    return;
+	Py_INCREF(onSent);
+	chatru::sendMessage(*avatar, *channel, *message, boost::bind(&do_onSent, onSent, _1, _2, _3, _4));
+    }
+    void receiveMessages(PyObject* avatar_ptr, PyObject* onMessage){
+	chatru::Avatar* avatar;
+	if (SWIG_ConvertPtr(avatar_ptr, (void **) &avatar, SWIGTYPE_p_chatru__Avatar, SWIG_POINTER_EXCEPTION) == -1)
+	    return;
+	Py_INCREF(onMessage);
+	chatru::receiveMessages(*avatar, boost::bind(&do_onMessage, onMessage, _1, _2));
+    }
 %}    
 
 %{
 void do_onList(PyObject* function, chatru::Avatar& avatar, chatru::ChannelList& cl, const std::string& error){
     PyObject *obj = SWIG_NewPointerObj(&avatar, SWIGTYPE_p_chatru__Avatar, 0);
-    //OMG WTF
-    //PyObject *cl_obj = SWIG_NewPointerObj(&cl, SWIGTYPE_p_std__mapT_int_chatru__Channel_std__lessT_int_t_std__allocatorT_std__pairT_int_const_chatru__Channel_t_t_t, 0);
     PyObject *cl_obj = swig::traits_from<chatru::ChannelList>::from(cl);
     PyObject* arglist = Py_BuildValue("(OOs)", obj, cl_obj, error.c_str());
     PyObject* result = PyEval_CallObject(function, arglist);

File src/channel.cpp

 	    }
 	}
     }
+    
+    Channel::~Channel(){
+    }
+
     void listChannels(Avatar& avatar, const ListChannelsCallback& cb){
 	jsonGet(avatar, std::string("/channels?uticket=") + avatar.data()->uticket, boost::bind(&onListImpl, cb, _1, _2, _3));
 	//jsonGet(avatar.dlink(), std::string("/channels?uticket=") + avatar.data()->uticket, boost::bind(&onList, cb, _1, boost::ref(avatar), _2));
     void joinChannel(Avatar& avatar, Channel& channel, const JoinChannelCallback& cb){
 	jsonGet(avatar, 
 		std::string("/chl?uticket=") + avatar.data()->uticket + "&channel=" + boost::lexical_cast<std::string>(channel.id()),
-		boost::bind(&onJoin, cb, boost::ref(channel), _1, _2, _3)
+		boost::bind(&onJoin, cb, boost::ref(avatar.data()->channels[channel.id()]), _1, _2, _3)
 		);
     }
 

File tests/test.py

 #!/usr/bin/python
+#coding=utf-8
 
 import crg
 import traceback
-print "imported"
 
 a = crg.Avatar('moriarty_test', 'testtesttest')
 print "avatar created"
     crg.listChannels(avatar, onList)
 
 def onList(avatar, channels, error):
+    print "onList error: '%s' on avatar %s. Channels: %s" % (error, avatar.name(), ", ".join("%s (%d)" % (v.name(), k) for k, v in channels.items()))
+    crg.joinChannel(avatar, channels[6], onJoin)
+    crg.receiveMessages(avatar, onMessage)
+
+def onJoin(avatar, channel, error):
+    print "on Join error: '%s', channel: %s, avatar: %s" % (error, channel.name(), avatar.name())
+    #crg.sendMessage(avatar, channel, crg.Message("тест"), onSent)
+
+def onSent(avatar, channel, message, error):
+    print "onSent error: '%s', message: %s, channel: %s, avatar: %s" % (error, message.text(), channel.name(), avatar.name())
+
+def cmdPing(avatar, channel, msg, **kwargs):
+    crg.sendMessage(avatar, channel, crg.Message("pong", msg.sender() if channel.isPrivate() else ""), onSent)
+
+def cmdHelp(avatar, channel, msg, **kwargs):
+    crg.sendMessage(avatar, channel, crg.Message("Команды: ping, погода [город]", msg.sender() if channel.isPrivate() else ""), onSent)
+
+def cmdWeather(avatar, channel, msg, text, **kwargs):
+    def getWeather(city):
+        def s(c):
+            return u"Температура: %s, %s, %s, %s" % (c["temp_c"], c["condition"], c["humidity"], c["wind_condition"])
+        def s2(c):
+            return u"%s: %s" % (c["day_of_week"], c["condition"])
+
+        import pywapi
+        w = pywapi.get_weather_from_google(city, hl="ru")
+        return (u"%s. %s" % (s(w["current_conditions"]), u". ".join(s2(x) for x in w["forecasts"]))).encode("utf-8")
+        
+    parts = text.strip().split(' ')
+    if len(parts) == 1:
+        city = "Москва"
+    else:
+        city = parts[1].strip()
+    print "weather for %s (%s)" % (city, text)
+    crg.sendMessage(avatar, channel, crg.Message(getWeather(city), msg.sender() if channel.isPrivate() else ""), onSent)
+
+def get_cmd(avatar, chl, msg):
+    def nop(*args, **kwargs): pass
+    cmds = {"ping": cmdPing, "погода": cmdWeather}
+
+    text = None
+    if chl.isPrivate():
+        text = msg.text()
+    elif msg.text().startswith(avatar.name() + ": "):
+        text = msg.text()[len(avatar.name() + ": "):]
+    else:
+        return nop, text
+
+    for k, v in cmds.iteritems():
+        if text.lower().startswith(k):
+            return v, text
+    return cmdHelp, text
+    #return cmds.get(text, cmdHelp)
+
+def onMessage(avatar, msg):
     try:
-        print "onList error: '%s' on avatar %s. Channels: %s" % (error, avatar.name(), ", ".join("%s (%d)" % (v.name(), k) for k, v in channels.items()))
+        print "%s: %s" % (msg.sender(), msg.text())
+        if msg.sender() != "-SYS" and msg.sender() != avatar.name():
+            chl = crg.getChannel(avatar, msg)
+            c, t = get_cmd(avatar, chl, msg)
+            c(avatar = avatar, channel = chl, msg = msg, text = t)
+
     except:
         print traceback.format_exc()
 
 def onIdle():
-    print "onIdle"
+    pass
+    #print "onIdle"
 
 a.auth(onAuth)
 print "auth registered"