Commits

Kirill Morarenko  committed b34ac9d

+ logging
+ new 'thanks' command
* new chat server address
* small fixes to compile on newest gcc

  • Participants
  • Parent commits 4b2be7b

Comments (0)

Files changed (7)

File include/formvalue.h

 
 #include <sstream>
 #include <boost/lexical_cast.hpp>
+#include <boost/noncopyable.hpp>
 
 namespace chatru{
-    class FormValue{
+    class FormValue : private boost::noncopyable{
     public:
 	template <class T>
 	FormValue(const std::string& k, const T& value, bool do_escape = true) : do_escape_(do_escape){

File include/message.h

 	const std::string& sender() const {return sender_;}
 	const std::string& recipient() const {return recipient_;}
 	const std::string& text() const {return text_;}
+	const std::string& raw() const {return raw_;}
+
+	time_t time() const {return time_;}
 
     private:
 	int channel_id_;

File interfaces/build.sh

+#!/bin/sh
+swig -c++ -python crg.i
+gcc -fPIC -o _crg.so -shared -I /usr/include/python2.6/ -I ../include/ -L ../src -lcrg -lcurlpp -ljson -lpython2.6 ../interfaces/crg_wrap.cxx

File interfaces/crg.i

 	const std::string& sender() const;
 	const std::string& recipient() const;
 	const std::string& text() const;
+	const std::string& raw() const;
+	long long time() const;
     };
 
     typedef std::map<int, Channel> ChannelList;
 namespace chatru{
     Ape::Ape() 
 	: chl_(1)
-	, dlink_("http://0.data.chat4.chat.ru") {}
+	, dlink_("http://1.data.chat.chat.ru") {}
 
     namespace{
 	std::string get_error(const std::string& error, const Json::Value& value){
 		value["sessid"] = ape.sessid();
 		Json::Value d;
 		d[0u] = value;
-		jsonPost(ape.dlink(), "/0/", FormValue(Json::FastWriter().write(d), false), boost::bind(&onJoined, cb, boost::ref(ape), _1, _2));
+                FormValue fv(Json::FastWriter().write(d), false);
+		jsonPost(ape.dlink(), "/0/", fv, boost::bind(&onJoined, cb, boost::ref(ape), _1, _2));
 	    } else
 		cb(error);
 	}
 	value["chl"] = chl();
 	Json::Value d;
 	d[0u] = value;
-	jsonPost(dlink_, "/0/", FormValue(Json::FastWriter().write(d), false), boost::bind(&onConnected, cb, boost::ref(*this), datalink, _1, _2));
+        FormValue fv(Json::FastWriter().write(d), false);
+	jsonPost(dlink_, "/0/", fv, boost::bind(&onConnected, cb, boost::ref(*this), datalink, _1, _2));
     }
 
     namespace{
 	value["sessid"] = ape.sessid();
 	Json::Value d;
 	d[0u] = value;
-	jsonPost(ape.dlink(), "/0/", FormValue(Json::FastWriter().write(d), false), boost::bind(&onMessage, cb, boost::ref(ape), _1, boost::ref(avatar), _2));
+        FormValue fv(Json::FastWriter().write(d), false);
+	jsonPost(ape.dlink(), "/0/", fv, boost::bind(&onMessage, cb, boost::ref(ape), _1, boost::ref(avatar), _2));
     }
 
 }

File src/avatar.cpp

 
 namespace chatru{
     Avatar::Avatar(const std::string& name, const std::string& passwd)
-        : dlink_("http://chat4.chat.ru")
+        : dlink_("http://chat.chat.ru")
         , name_(name)
 	, passwd_(passwd)
         , data_(NULL){

File tests/test.py

 #coding=utf-8
 
 import crg
+
 import traceback
+import sqlite3
+import random
+
+def u(string):
+    return unicode(string, "utf-8")
+
+class Log(object):
+    def __init__(self, file):
+        self.file = file
+        self.connection = sqlite3.connect(file)
+        self.cursor = self.connection.cursor()
+        self.cursor.execute("""CREATE TABLE IF NOT EXISTS messages(time int not null, channel varchar(255) not null, sender varchar(255) NOT NULL, recipient varchar(255), body text)""")
+        self.cursor.execute("""CREATE INDEX IF NOT EXISTS messages_ts_chl ON messages(time, channel)""")
+    def notSeen(self, avatar, channel, message):
+        return len(self.cursor.execute("SELECT 1 FROM messages WHERE time = ? AND channel = ? AND sender = ? and body = ?", (message.time(), u(channel.name()), u(message.sender()), u(message.text()))).fetchall()) == 0
+    def register(self, avatar, channel, message):
+        self.cursor.execute("INSERT INTO messages(time, channel, sender, body) VALUES (?, ?, ?, ?)", (message.time(), u(channel.name()), u(message.sender()), u(message.text())))
+        self.connection.commit()
+
+log = Log("messages.db")
+
+def chatify(msg):
+    return msg.replace(u"\n", u" *n").replace(u" ", u"&nbsp;")
 
 a = crg.Avatar('moriarty_test', 'testtesttest')
 print "avatar created"
 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.joinChannel(avatar, channels[1], onJoin)
     crg.receiveMessages(avatar, onMessage)
 
 def onJoin(avatar, channel, error):
         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")
+        result = ""
+        try:
+            import pywapi
+            w = pywapi.get_weather_from_google(city, hl="ru")
+            result = u"%s. %s" % (s(w["current_conditions"]), u". ".join(s2(x) for x in w["forecasts"]))
+        except:
+            result = chatify(u"\n" + unicode(traceback.format_exc(), "utf-8"))
+        print type(result)
+        return (u"%s: %s" % (unicode(city, "utf-8"), result)).encode("utf-8")
         
     parts = text.strip().split(' ')
     if len(parts) == 1:
     print "weather for %s (%s)" % (city, text)
     crg.sendMessage(avatar, channel, crg.Message(getWeather(city), msg.sender() if channel.isPrivate() else ""), onSent)
 
+def cmdThanks(avatar, channel, msg, text, **kwargs):
+    parts = text.strip().split(' ')
+    answer = "Пожалуйста!"
+    if len(parts) > 1 and random.randint(0, 1) == 1:
+        answer = "Пожалуйста, а вот это тебе: %s" % (" ".join(parts[1:]))
+    crg.sendMessage(avatar, channel, crg.Message(answer, msg.sender() if channel.isPrivate() else ""), onSent)
+
+
 def get_cmd(avatar, chl, msg):
     def nop(*args, **kwargs): pass
-    cmds = {"ping": cmdPing, "погода": cmdWeather}
+    cmds = {"ping": cmdPing, "погода": cmdWeather, "спасибо": cmdThanks}
 
     text = None
     if chl.isPrivate():
 
 def onMessage(avatar, msg):
     try:
-        print "%s: %s" % (msg.sender(), msg.text())
+        chl = crg.getChannel(avatar, msg)
+        flag = "-"
+        seen = True
+        if log.notSeen(avatar, chl, msg):
+            seen = False
+            flag = "*"
+            log.register(avatar, chl, msg)
+
         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)
+            if not seen:
+                c, t = get_cmd(avatar, chl, msg)
+                c(avatar = avatar, channel = chl, msg = msg, text = t)
+        else:
+            flag = "#"
+        print "%s [%d/%s] %s: %s" % (flag, msg.time(), chl.name(), msg.sender(), msg.text())
+
 
     except:
         print traceback.format_exc()