Source

chatrug / src / ape.cpp

Full commit
//-*- mode: c++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
#include <ape.h>
#include <jsonget.hpp>
#include <formvalue.h>
#include <stuff.h>

#include "channel_impl.h"

#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>

#include <iostream>

namespace chatru{
    Ape::Ape() 
	: chl_(1)
	, dlink_("http://1.data.chat.chat.ru") {}

    namespace{
	std::string get_error(const std::string& error, const Json::Value& value){
	    if (error.empty()){
		if (value.isArray() && value[0u].isObject() && value[0u]["raw"].asString() == "ERR")
		    return value[0u]["data"]["value"].asString();
		return "";
	    } else
		return error;
	}
	void onJoined(const Ape::OnConnectCallback& cb, Ape& ape, const std::string& json_error, const Json::Value& value){
	    std::string error(get_error(json_error, value));
	    if (error.empty()){
		cb(error);
		//std::cout << Json::
	    } else
		cb(error);
	}
	void onConnected(const Ape::OnConnectCallback& cb, Ape& ape, const std::string& datalink, const std::string& json_error, const Json::Value& resp){
	    std::string error(get_error(json_error, resp));
	    if (error.empty()){
		ape.sessid() = resp[0u]["data"]["sessid"].asString();
		Json::Value value;
		value["cmd"] = "JOIN";
		value["chl"] = ape.chl();
		Json::Value params;
		params["channels"] = datalink;
		value["params"] = params;
		value["sessid"] = ape.sessid();
		Json::Value d;
		d[0u] = value;
                FormValue fv(Json::FastWriter().write(d), false);
		jsonPost(ape.dlink(), "/0/", fv, boost::bind(&onJoined, cb, boost::ref(ape), _1, _2));
	    } else
		cb(error);
	}
    }

    void Ape::connect(const std::string& datalink, const OnConnectCallback& cb){
	datalink_ = datalink;

	Json::Value value;
	value["cmd"] = "CONNECT";
	value["chl"] = chl();
	Json::Value d;
	d[0u] = value;
        FormValue fv(Json::FastWriter().write(d), false);
	jsonPost(dlink_, "/0/", fv, boost::bind(&onConnected, cb, boost::ref(*this), datalink, _1, _2));
    }

    namespace{
	void onMessage(const OnMessageCallback& cb, Ape& ape, const std::string& json_error, Avatar& avatar, const Json::Value& root){
	    std::string error(get_error(json_error, root));
	    if (error.empty() || root.isNull()){
		//messages received, or timeout reached
		//std::cout << Json::StyledWriter().write(root) << std::endl;
		if (root.isArray()){
		    for (size_t i = 0; i < root.size(); ++i){
			Json::Value content;// = root[i]["data"]["content"];
			Json::Reader reader;
			//XXX
			bool parsingSuccessful = reader.parse(root[i]["data"]["content"].asString(), content);
			if (parsingSuccessful){
			    if (content["type"] == "message"){
				//std::cout << Json::StyledWriter().write(content) << std::endl;
				Message msg(asInt(content["channel"]),
					    asLongLong(content["time"]),
					    content["msgtype"].asString(), 
					    content["sender"].asString(),
					    content["recipient"].asString(),
					    content["msgtext"].asString(),
					    root[i]["data"]["content"].asString()
					    );
				cb(avatar, msg, "");
			    } else if (content["type"] == "channelupdate"){
				channelUpdate(avatar, content);
			    } else if (content["type"] == "login"){
				channelLogin(avatar, content);
			    } else if (content["type"] == "logout"){
				channelLogout(avatar, content);
			    } else if (content["type"] == "userupdate"){
				//channelLogout(avatar, content);
			    } else{
				std::cout << Json::StyledWriter().write(content) << std::endl;
			    }
			}
		    }
		}
		receiveMessages(boost::ref(ape), boost::ref(avatar), cb);
	    } else{
		std::cerr << "PANIC: " << error << std::endl;
		//try to reconnect APE
		//TODO rejoin channels?
		//ape.connect(ape.datalink(), boost::bind(&receiveMessages, boost::ref(ape), boost::ref(avatar), cb));
		cb(avatar, Message(error), error);
	    }
	}
    }
    void receiveMessages(Ape& ape, Avatar& avatar, const OnMessageCallback& cb){
	Json::Value value;
	value["cmd"] = "CHECK";
	value["chl"] = ape.chl();
	value["sessid"] = ape.sessid();
	Json::Value d;
	d[0u] = value;
        FormValue fv(Json::FastWriter().write(d), false);
	jsonPost(ape.dlink(), "/0/", fv, boost::bind(&onMessage, cb, boost::ref(ape), _1, boost::ref(avatar), _2));
    }

}