diff options
Diffstat (limited to 'Sluift/client.cpp')
| -rw-r--r-- | Sluift/client.cpp | 110 |
1 files changed, 35 insertions, 75 deletions
diff --git a/Sluift/client.cpp b/Sluift/client.cpp index db259cd..06df6a4 100644 --- a/Sluift/client.cpp +++ b/Sluift/client.cpp @@ -1,70 +1,77 @@ /* * Copyright (c) 2013 Remko Tronçon * Licensed under the GNU General Public License. * See the COPYING file for more information. */ #include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> #include <boost/assign/list_of.hpp> #include <iostream> #include <Sluift/SluiftClient.h> #include <Swiften/JID/JID.h> #include <Swiften/Elements/SoftwareVersion.h> #include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> #include <Swiften/Elements/RawXMLPayload.h> #include <Swiften/Elements/RosterItemPayload.h> #include <Swiften/Elements/RosterPayload.h> #include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Elements/MAMQuery.h> #include <Swiften/Disco/ClientDiscoManager.h> #include <Swiften/Queries/GenericRequest.h> #include <Swiften/Presence/PresenceSender.h> #include <Swiften/Roster/XMPPRoster.h> #include <Swiften/Roster/SetRosterRequest.h> #include <Swiften/Presence/SubscriptionManager.h> #include <Swiften/Roster/XMPPRosterItem.h> +#include <Swiften/Queries/IQRouter.h> #include <Swiften/Queries/Requests/GetSoftwareVersionRequest.h> #include <Sluift/Lua/FunctionRegistration.h> #include <Swiften/Base/foreach.h> +#include <Swiften/Base/IDGenerator.h> #include <Sluift/Lua/Check.h> #include <Sluift/Lua/Value.h> #include <Sluift/Lua/Exception.h> #include <Sluift/Lua/LuaUtils.h> #include <Sluift/globals.h> +#include <Sluift/ElementConvertors/StanzaConvertor.h> +#include <Sluift/ElementConvertors/IQConvertor.h> +#include <Sluift/ElementConvertors/PresenceConvertor.h> +#include <Sluift/ElementConvertors/MessageConvertor.h> using namespace Swift; namespace lambda = boost::lambda; static inline SluiftClient* getClient(lua_State* L) { return *Lua::checkUserData<SluiftClient>(L, 1); } static inline int getGlobalTimeout(lua_State* L) { lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.moduleLibIndex); lua_getfield(L, -1, "timeout"); int result = boost::numeric_cast<int>(lua_tointeger(L, -1)); lua_pop(L, 2); return result; } static void addPayloadsToTable(lua_State* L, const std::vector<boost::shared_ptr<Payload> >& payloads) { if (!payloads.empty()) { lua_createtable(L, boost::numeric_cast<int>(payloads.size()), 0); for (size_t i = 0; i < payloads.size(); ++i) { Sluift::globals.elementConvertor.convertToLua(L, payloads[i]); lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); } Lua::registerGetByTypeIndex(L, -1); lua_setfield(L, -2, "payloads"); } } static boost::shared_ptr<Payload> getPayload(lua_State* L, int index) { if (lua_type(L, index) == LUA_TTABLE) { return boost::dynamic_pointer_cast<Payload>(Sluift::globals.elementConvertor.convertFromLua(L, index)); } else if (lua_type(L, index) == LUA_TSTRING) { return boost::make_shared<RawXMLPayload>(Lua::checkString(L, index)); } @@ -204,231 +211,186 @@ SLUIFT_LUA_FUNCTION_WITH_HELP( "self\n" "to the JID to send the message to\n" "body the body of the message. Can alternatively be specified using the `body` option\n", "to the JID to send the message to\n" "body the body of the message\n" "subject the subject of the MUC room to set\n" "type the type of message to send (`normal`, `chat`, `error`, `groupchat`, `headline`)\n" "payloads payloads to add to the message\n" ) { Sluift::globals.eventLoop.runOnce(); JID to; boost::optional<std::string> body; boost::optional<std::string> subject; std::vector<boost::shared_ptr<Payload> > payloads; int index = 2; Message::Type type = Message::Chat; if (lua_isstring(L, index)) { to = std::string(lua_tostring(L, index)); ++index; if (lua_isstring(L, index)) { body = lua_tostring(L, index); ++index; } } if (lua_istable(L, index)) { if (boost::optional<std::string> value = Lua::getStringField(L, index, "to")) { to = *value; } if (boost::optional<std::string> value = Lua::getStringField(L, index, "body")) { body = value; } if (boost::optional<std::string> value = Lua::getStringField(L, index, "type")) { - if (*value == "normal") { - type = Message::Normal; - } - else if (*value == "chat") { - type = Message::Chat; - } - else if (*value == "error") { - type = Message::Error; - } - else if (*value == "groupchat") { - type = Message::Groupchat; - } - else if (*value == "headline") { - type = Message::Headline; - } + type = MessageConvertor::convertMessageTypeFromString(*value); } if (boost::optional<std::string> value = Lua::getStringField(L, index, "subject")) { subject = value; } payloads = getPayloadsFromTable(L, index); } if (!to.isValid()) { throw Lua::Exception("Missing 'to'"); } if ((!body || body->empty()) && !subject && payloads.empty()) { throw Lua::Exception("Missing any of 'body', 'subject' or 'payloads'"); } Message::ref message = boost::make_shared<Message>(); message->setTo(to); if (body && !body->empty()) { message->setBody(*body); } if (subject) { message->setSubject(*subject); } message->addPayloads(payloads.begin(), payloads.end()); message->setType(type); getClient(L)->getClient()->sendMessage(message); return 0; } SLUIFT_LUA_FUNCTION_WITH_HELP( Client, send_presence, "Send presence.", "self\n" "body the text of the presence. Can alternatively be specified using the `status` option\n", "to the JID to send the message to\n" "status the text of the presence\n" "priority the priority of the presence\n" "type the type of message to send (`available`, `error`, `probe`, `subscribe`, `subscribed`, `unavailable`, `unsubscribe`, `unsubscribed`)\n" "payloads payloads to add to the presence\n" ) { Sluift::globals.eventLoop.runOnce(); boost::shared_ptr<Presence> presence = boost::make_shared<Presence>(); int index = 2; if (lua_isstring(L, index)) { presence->setStatus(lua_tostring(L, index)); ++index; } if (lua_istable(L, index)) { if (boost::optional<std::string> value = Lua::getStringField(L, index, "to")) { presence->setTo(*value); } if (boost::optional<std::string> value = Lua::getStringField(L, index, "status")) { presence->setStatus(*value); } if (boost::optional<int> value = Lua::getIntField(L, index, "priority")) { presence->setPriority(*value); } if (boost::optional<std::string> value = Lua::getStringField(L, index, "type")) { - if (*value == "available") { - presence->setType(Presence::Available); - } - else if (*value == "error") { - presence->setType(Presence::Error); - } - else if (*value == "probe") { - presence->setType(Presence::Probe); - } - else if (*value == "subscribe") { - presence->setType(Presence::Subscribe); - } - else if (*value == "subscribed") { - presence->setType(Presence::Subscribed); - } - else if (*value == "unavailable") { - presence->setType(Presence::Unavailable); - } - else if (*value == "unsubscribe") { - presence->setType(Presence::Unsubscribe); - } - else if (*value == "unsubscribed") { - presence->setType(Presence::Unsubscribed); - } + presence->setType(PresenceConvertor::convertPresenceTypeFromString(*value)); } std::vector< boost::shared_ptr<Payload> > payloads = getPayloadsFromTable(L, index); presence->addPayloads(payloads.begin(), payloads.end()); } getClient(L)->getClient()->getPresenceSender()->sendPresence(presence); lua_pushvalue(L, 1); return 0; } static int sendQuery(lua_State* L, IQ::Type type) { SluiftClient* client = getClient(L); JID to; if (boost::optional<std::string> toString = Lua::getStringField(L, 2, "to")) { to = JID(*toString); } int timeout = getGlobalTimeout(L); if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { timeout = *timeoutInt; } boost::shared_ptr<Payload> payload; lua_getfield(L, 2, "query"); payload = getPayload(L, -1); lua_pop(L, 1); return client->sendRequest( boost::make_shared< GenericRequest<Payload> >(type, to, payload, client->getClient()->getIQRouter()), timeout).convertToLuaResult(L); } #define DISPATCH_PUBSUB_PAYLOAD(payloadType, container, response) \ else if (boost::shared_ptr<payloadType> p = boost::dynamic_pointer_cast<payloadType>(payload)) { \ return client->sendPubSubRequest(type, to, p, timeout).convertToLuaResult(L); \ } SLUIFT_LUA_FUNCTION(Client, query_pubsub) { SluiftClient* client = getClient(L); JID to; if (boost::optional<std::string> toString = Lua::getStringField(L, 2, "to")) { to = JID(*toString); } int timeout = getGlobalTimeout(L); if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { timeout = *timeoutInt; } IQ::Type type; if (boost::optional<std::string> queryType = Lua::getStringField(L, 2, "type")) { - if (*queryType == "get") { - type = IQ::Get; - } - else if (*queryType == "set") { - type = IQ::Set; - } - else { - throw Lua::Exception("Illegal query type: '" + *queryType + "'"); - } + type = IQConvertor::convertIQTypeFromString(*queryType); } else { throw Lua::Exception("Missing query type"); } lua_getfield(L, 2, "query"); if (!lua_istable(L, -1)) { throw Lua::Exception("Missing/incorrect query"); } boost::shared_ptr<Payload> payload = getPayload(L, -1); if (false) { } SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE(DISPATCH_PUBSUB_PAYLOAD) else { throw Lua::Exception("Incorrect PubSub payload"); } } SLUIFT_LUA_FUNCTION(Client, get) { return sendQuery(L, IQ::Get); } SLUIFT_LUA_FUNCTION(Client, set) { return sendQuery(L, IQ::Set); } SLUIFT_LUA_FUNCTION_WITH_HELP( Client, send, "Sends a raw string", "self\n" "data the string to send\n", "" @@ -458,122 +420,120 @@ SLUIFT_LUA_FUNCTION_WITH_HELP( SluiftClient* client = getClient(L); Lua::checkType(L, 2, LUA_TTABLE); lua_getfield(L, 2, "host"); if (!lua_isnil(L, -1)) { client->getOptions().manualHostname = lua_tostring(L, -1); } lua_getfield(L, 2, "port"); if (!lua_isnil(L, -1)) { client->getOptions().manualPort = boost::numeric_cast<int>(lua_tointeger(L, -1)); } lua_getfield(L, 2, "ack"); if (!lua_isnil(L, -1)) { client->getOptions().useAcks = lua_toboolean(L, -1); } lua_getfield(L, 2, "compress"); if (!lua_isnil(L, -1)) { client->getOptions().useStreamCompression = lua_toboolean(L, -1); } lua_getfield(L, 2, "tls"); if (!lua_isnil(L, -1)) { bool useTLS = lua_toboolean(L, -1); client->getOptions().useTLS = (useTLS ? ClientOptions::UseTLSWhenAvailable : ClientOptions::NeverUseTLS); } lua_getfield(L, 2, "bosh_url"); if (!lua_isnil(L, -1)) { client->getOptions().boshURL = URL::fromString(lua_tostring(L, -1)); } lua_getfield(L, 2, "allow_plain_without_tls"); if (!lua_isnil(L, -1)) { client->getOptions().allowPLAINWithoutTLS = lua_toboolean(L, -1); } lua_pushvalue(L, 1); return 0; } -static std::string convertPresenceTypeToString(Presence::Type type) { - std::string result; - - switch (type) { - case Presence::Available: result = "available"; break; - case Presence::Error: result = "error"; break; - case Presence::Probe: result = "probe"; break; - case Presence::Subscribe: result = "subscribe"; break; - case Presence::Subscribed: result = "subscribed"; break; - case Presence::Unavailable: result = "unavailable"; break; - case Presence::Unsubscribe: result = "unsubscribe"; break; - case Presence::Unsubscribed: result = "unsubscribed"; break; - } +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, send_mam_query, - return result; -} + "Builds and sends a MAM query.\n", -static std::string convertMessageTypeToString(Message::Type type) { - std::string result; + "self\n" + "mam_query parameters for the query\n" + "jid optional jid to set in the 'to' field of the IQ stanza", - switch (type) { - case Message::Normal: result = "normal"; break; - case Message::Chat: result = "chat"; break; - case Message::Error: result = "error"; break; - case Message::Groupchat: result = "groupchat"; break; - case Message::Headline: result = "headline"; break; + "See help('MAMQuery') for details." +) { + if (!lua_istable(L, 2)) { + throw Lua::Exception("Missing MAMQuery"); + } + if (boost::shared_ptr<MAMQuery> mamQuery = boost::dynamic_pointer_cast<MAMQuery>(Sluift::globals.elementConvertor.convertFromLuaUntyped(L, 2, "mam_query"))) { + IQRouter *router = getClient(L)->getClient()->getIQRouter(); + JID jid; + lua_getfield(L, 2, "jid"); + if (!lua_isnil(L, -1)) { + jid = JID(lua_tostring(L, -1)); + } + router->sendIQ(IQ::createRequest(IQ::Get, jid, IDGenerator().generateID(), mamQuery)); } - - return result; + else { + throw Lua::Exception("Illegal MAMQuery"); + } + return 0; } static void pushEvent(lua_State* L, const SluiftClient::Event& event) { switch (event.type) { case SluiftClient::Event::MessageType: { Message::ref message = boost::dynamic_pointer_cast<Message>(event.stanza); Lua::Table result = boost::assign::map_list_of ("type", boost::make_shared<Lua::Value>(std::string("message"))) ("from", boost::make_shared<Lua::Value>(message->getFrom().toString())) ("body", boost::make_shared<Lua::Value>(message->getBody())) - ("message_type", boost::make_shared<Lua::Value>(convertMessageTypeToString(message->getType()))); + ("message_type", boost::make_shared<Lua::Value>(MessageConvertor::convertMessageTypeToString(message->getType()))); Lua::pushValue(L, result); addPayloadsToTable(L, message->getPayloads()); Lua::registerTableToString(L, -1); break; } case SluiftClient::Event::PresenceType: { Presence::ref presence = boost::dynamic_pointer_cast<Presence>(event.stanza); Lua::Table result = boost::assign::map_list_of ("type", boost::make_shared<Lua::Value>(std::string("presence"))) ("from", boost::make_shared<Lua::Value>(presence->getFrom().toString())) ("status", boost::make_shared<Lua::Value>(presence->getStatus())) - ("presence_type", boost::make_shared<Lua::Value>(convertPresenceTypeToString(presence->getType()))); + ("presence_type", boost::make_shared<Lua::Value>(PresenceConvertor::convertPresenceTypeToString(presence->getType()))); Lua::pushValue(L, result); addPayloadsToTable(L, presence->getPayloads()); Lua::registerTableToString(L, -1); break; } case SluiftClient::Event::PubSubEventType: { Sluift::globals.elementConvertor.convertToLua(L, event.pubsubEvent); lua_pushstring(L, "pubsub"); lua_setfield(L, -2, "type"); lua_pushstring(L, event.from.toString().c_str()); lua_setfield(L, -2, "from"); lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); lua_getfield(L, -1, "process_pubsub_event"); lua_pushvalue(L, -3); lua_call(L, 1, 0); lua_pop(L, 1); } } } struct CallUnaryLuaPredicateOnEvent { CallUnaryLuaPredicateOnEvent(lua_State* L, int index) : L(L), index(index) { } bool operator()(const SluiftClient::Event& event) { lua_pushvalue(L, index); pushEvent(L, event); if (lua_pcall(L, 1, 1, 0) != 0) { throw Lua::Exception(lua_tostring(L, -1)); } bool result = lua_toboolean(L, -1); lua_pop(L, 1); return result; } |
Swift