diff options
author | Richard Maudsley <richard.maudsley@isode.com> | 2014-02-28 14:38:04 (GMT) |
---|---|---|
committer | Richard Maudsley <richard.maudsley@isode.com> | 2014-05-02 08:47:32 (GMT) |
commit | 47ba7eb4a5d3a48f4aa554ff07d20cc7c8682bae (patch) | |
tree | e6a6d69e187e75fbf34ffa89370476a9a3bc9752 /Sluift | |
parent | 481f33cdee8a907c98f1b87dd1b65418b096c4f6 (diff) | |
download | swift-contrib-47ba7eb4a5d3a48f4aa554ff07d20cc7c8682bae.zip swift-contrib-47ba7eb4a5d3a48f4aa554ff07d20cc7c8682bae.tar.bz2 |
Added Sluift MAM convertors.
Change-Id: I472023726e84fbdd14af1fd9f57de411a20eb584
Diffstat (limited to 'Sluift')
20 files changed, 1011 insertions, 76 deletions
diff --git a/Sluift/ElementConvertors/ForwardedConvertor.cpp b/Sluift/ElementConvertors/ForwardedConvertor.cpp new file mode 100644 index 0000000..a6f78d0 --- /dev/null +++ b/Sluift/ElementConvertors/ForwardedConvertor.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/numeric/conversion/cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <lua.hpp> +#include <Swiften/Base/foreach.h> +#include <Sluift/ElementConvertors/ForwardedConvertor.h> +#include <Sluift/LuaElementConvertors.h> +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/Message.h> + +#pragma clang diagnostic ignored "-Wunused-private-field" + +using namespace Swift; + +ForwardedConvertor::ForwardedConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<Forwarded>("forwarded"), + convertors(convertors) { +} + +ForwardedConvertor::~ForwardedConvertor() { +} + +boost::shared_ptr<Forwarded> ForwardedConvertor::doConvertFromLua(lua_State* L) { + boost::shared_ptr<Forwarded> result = boost::make_shared<Forwarded>(); + lua_getfield(L, -1, "delay"); + if (!lua_isnil(L, -1)) { + boost::shared_ptr<Delay> delay = boost::dynamic_pointer_cast<Delay>(convertors->convertFromLuaUntyped(L, -1, "delay")); + if (!!delay) { + result->setDelay(delay); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "stanza"); + if (!lua_isnil(L, -1)) { + boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(convertors->convertFromLua(L, -1)); + if (!!stanza) { + result->setStanza(stanza); + } + lua_pop(L, 1); + return result; + } + return result; +} + +void ForwardedConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<Forwarded> payload) { + lua_createtable(L, 0, 0); + if (convertors->convertToLuaUntyped(L, payload->getDelay()) > 0) { + lua_setfield(L, -2, "delay"); + } + boost::shared_ptr<Stanza> stanza = payload->getStanza(); + if (!!stanza) { + if (convertors->convertToLua(L, stanza) > 0) { + lua_setfield(L, -2, "stanza"); + } + } +} + +boost::optional<LuaElementConvertor::Documentation> ForwardedConvertor::getDocumentation() const { + return Documentation( + "Forwarded", + "This table has the following fields:\n\n" + "- `delay`: @{Delay} (Optional)\n" + "- `stanza`: @{Stanza} (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/ForwardedConvertor.h b/Sluift/ElementConvertors/ForwardedConvertor.h new file mode 100644 index 0000000..3ee4498 --- /dev/null +++ b/Sluift/ElementConvertors/ForwardedConvertor.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Sluift/GenericLuaElementConvertor.h> +#include <Swiften/Base/Override.h> +#include <Swiften/Elements/Forwarded.h> + +namespace Swift { + class LuaElementConvertors; + + class ForwardedConvertor : public GenericLuaElementConvertor<Forwarded> { + public: + ForwardedConvertor(LuaElementConvertors* convertors); + virtual ~ForwardedConvertor(); + + virtual boost::shared_ptr<Forwarded> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; + virtual void doConvertToLua(lua_State*, boost::shared_ptr<Forwarded>) SWIFTEN_OVERRIDE; + virtual boost::optional<Documentation> getDocumentation() const SWIFTEN_OVERRIDE; + + private: + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/IQConvertor.cpp b/Sluift/ElementConvertors/IQConvertor.cpp new file mode 100644 index 0000000..8a8e463 --- /dev/null +++ b/Sluift/ElementConvertors/IQConvertor.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/smart_ptr/make_shared.hpp> +#include <lua.hpp> +#include <Sluift/ElementConvertors/IQConvertor.h> +#include <Sluift/LuaElementConvertors.h> + +#pragma clang diagnostic ignored "-Wunused-private-field" + +using namespace Swift; + +IQConvertor::IQConvertor(LuaElementConvertors* convertors) : + StanzaConvertor("iq"), + convertors(convertors) { +} + +IQConvertor::~IQConvertor() { +} + +boost::shared_ptr<IQ> IQConvertor::doConvertFromLua(lua_State* L) { + boost::shared_ptr<IQ> result = getStanza(L, convertors); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + result->setType(IQConvertor::convertIQTypeFromString(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void IQConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<IQ> stanza) { + pushStanza(L, stanza, convertors); + const std::string type = IQConvertor::convertIQTypeToString(stanza->getType()); + lua_pushstring(L, type.c_str()); + lua_setfield(L, -2, "type"); +} + +boost::optional<LuaElementConvertor::Documentation> IQConvertor::getDocumentation() const { + return Documentation( + "IQ", + "This table has the following fields:\n\n" + "- `type`: string\n" + "- `id`: string\n" + "- `from`: string\n" + "- `to`: string\n" + "- `payloads`: array<@{Payload}>\n" + ); +} + +std::string IQConvertor::convertIQTypeToString(IQ::Type type) { + switch (type) { + case IQ::Get: return "get"; + case IQ::Set: return "set"; + case IQ::Result: return "result"; + case IQ::Error: return "error"; + } +} + +IQ::Type IQConvertor::convertIQTypeFromString(const std::string& type) { + if (type == "get") { + return IQ::Get; + } + else if (type == "set") { + return IQ::Set; + } + else { + throw Lua::Exception("Illegal query type: '" + type + "'"); + } +} diff --git a/Sluift/ElementConvertors/IQConvertor.h b/Sluift/ElementConvertors/IQConvertor.h new file mode 100644 index 0000000..d22df08 --- /dev/null +++ b/Sluift/ElementConvertors/IQConvertor.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Sluift/ElementConvertors/StanzaConvertor.h> +#include <Swiften/Base/Override.h> +#include <Swiften/Elements/IQ.h> + +namespace Swift { + class LuaElementConvertors; + + class IQConvertor : public StanzaConvertor<IQ> { + public: + IQConvertor(LuaElementConvertors* convertors); + virtual ~IQConvertor(); + + virtual boost::shared_ptr<IQ> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; + virtual void doConvertToLua(lua_State*, boost::shared_ptr<IQ>) SWIFTEN_OVERRIDE; + + virtual boost::optional<Documentation> getDocumentation() const SWIFTEN_OVERRIDE; + + static std::string convertIQTypeToString(IQ::Type type); + static IQ::Type convertIQTypeFromString(const std::string& type); + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/MAMArchivedConvertor.cpp b/Sluift/ElementConvertors/MAMArchivedConvertor.cpp new file mode 100644 index 0000000..39ac7df --- /dev/null +++ b/Sluift/ElementConvertors/MAMArchivedConvertor.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/numeric/conversion/cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <lua.hpp> +#include <Sluift/ElementConvertors/MAMArchivedConvertor.h> + +#pragma clang diagnostic ignored "-Wunused-private-field" + +using namespace Swift; + +MAMArchivedConvertor::MAMArchivedConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<MAMArchived>("mam_archived"), + convertors(convertors) { +} + +MAMArchivedConvertor::~MAMArchivedConvertor() { +} + +boost::shared_ptr<MAMArchived> MAMArchivedConvertor::doConvertFromLua(lua_State* L) { + boost::shared_ptr<MAMArchived> result = boost::make_shared<MAMArchived>(); + lua_getfield(L, -1, "by"); + if (lua_isstring(L, -1)) { + result->setBy(JID(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "id"); + if (lua_isstring(L, -1)) { + result->setID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void MAMArchivedConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<MAMArchived> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getBy().toString().c_str()); + lua_setfield(L, -2, "by"); + lua_pushstring(L, payload->getID().c_str()); + lua_setfield(L, -2, "id"); +} + +boost::optional<LuaElementConvertor::Documentation> MAMArchivedConvertor::getDocumentation() const { + return Documentation( + "MAMArchived", + "This table has the following fields:\n\n" + "- `by`: string\n" + "- `id`: string\n" + ); +} diff --git a/Sluift/ElementConvertors/MAMArchivedConvertor.h b/Sluift/ElementConvertors/MAMArchivedConvertor.h new file mode 100644 index 0000000..9d95e4a --- /dev/null +++ b/Sluift/ElementConvertors/MAMArchivedConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Sluift/GenericLuaElementConvertor.h> +#include <Swiften/Base/Override.h> +#include <Swiften/Elements/MAMArchived.h> + +namespace Swift { + class LuaElementConvertors; + + class MAMArchivedConvertor : public GenericLuaElementConvertor<MAMArchived> { + public: + MAMArchivedConvertor(LuaElementConvertors* convertors); + virtual ~MAMArchivedConvertor(); + + virtual boost::shared_ptr<MAMArchived> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; + virtual void doConvertToLua(lua_State*, boost::shared_ptr<MAMArchived>) SWIFTEN_OVERRIDE; + virtual boost::optional<Documentation> getDocumentation() const SWIFTEN_OVERRIDE; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/MAMQueryConvertor.cpp b/Sluift/ElementConvertors/MAMQueryConvertor.cpp new file mode 100644 index 0000000..7d7224e --- /dev/null +++ b/Sluift/ElementConvertors/MAMQueryConvertor.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/numeric/conversion/cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <lua.hpp> +#include <Sluift/ElementConvertors/MAMQueryConvertor.h> +#include <Sluift/LuaElementConvertors.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/ResultSet.h> + +#pragma clang diagnostic ignored "-Wunused-private-field" + +using namespace Swift; + +MAMQueryConvertor::MAMQueryConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<MAMQuery>("mam_query"), + convertors(convertors) { +} + +MAMQueryConvertor::~MAMQueryConvertor() { +} + +boost::shared_ptr<MAMQuery> MAMQueryConvertor::doConvertFromLua(lua_State* L) { + boost::shared_ptr<MAMQuery> result = boost::make_shared<MAMQuery>(); + lua_getfield(L, -1, "query_id"); + if (lua_isstring(L, -1)) { + result->setQueryID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "form"); + if (!lua_isnil(L, -1)) { + boost::shared_ptr<Form> form = boost::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form")); + if (!!form) { + result->setForm(form); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "result_set"); + if (!lua_isnil(L, -1)) { + boost::shared_ptr<ResultSet> resultSet = boost::dynamic_pointer_cast<ResultSet>(convertors->convertFromLuaUntyped(L, -1, "result_set")); + if (!!resultSet) { + result->setResultSet(resultSet); + } + } + lua_pop(L, 1); + return result; +} + +void MAMQueryConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<MAMQuery> payload) { + lua_createtable(L, 0, 0); + if (payload->getQueryID()) { + lua_pushstring(L, (*payload->getQueryID()).c_str()); + lua_setfield(L, -2, "query_id"); + } + if (convertors->convertToLuaUntyped(L, payload->getForm()) > 0) { + lua_setfield(L, -2, "form"); + } + if (convertors->convertToLuaUntyped(L, payload->getResultSet()) > 0) { + lua_setfield(L, -2, "result_set"); + } +} + +boost::optional<LuaElementConvertor::Documentation> MAMQueryConvertor::getDocumentation() const { + return Documentation( + "MAMQuery", + "This table has the following fields:\n\n" + "- `query_id`: string (Optional)\n" + "- `form`: string @{Form} (Optional)\n" + "- `result_set`: @{ResultSet} (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/MAMQueryConvertor.h b/Sluift/ElementConvertors/MAMQueryConvertor.h new file mode 100644 index 0000000..92392e5 --- /dev/null +++ b/Sluift/ElementConvertors/MAMQueryConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Sluift/GenericLuaElementConvertor.h> +#include <Swiften/Base/Override.h> +#include <Swiften/Elements/MAMQuery.h> + +namespace Swift { + class LuaElementConvertors; + + class MAMQueryConvertor : public GenericLuaElementConvertor<MAMQuery> { + public: + MAMQueryConvertor(LuaElementConvertors* convertors); + virtual ~MAMQueryConvertor(); + + virtual boost::shared_ptr<MAMQuery> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; + virtual void doConvertToLua(lua_State*, boost::shared_ptr<MAMQuery>) SWIFTEN_OVERRIDE; + virtual boost::optional<Documentation> getDocumentation() const SWIFTEN_OVERRIDE; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/MAMResultConvertor.cpp b/Sluift/ElementConvertors/MAMResultConvertor.cpp new file mode 100644 index 0000000..8ba4de7 --- /dev/null +++ b/Sluift/ElementConvertors/MAMResultConvertor.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/numeric/conversion/cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <lua.hpp> +#include <Sluift/ElementConvertors/MAMResultConvertor.h> +#include <Sluift/LuaElementConvertors.h> +#include <Swiften/Elements/Forwarded.h> + + +#pragma clang diagnostic ignored "-Wunused-private-field" + +using namespace Swift; + +MAMResultConvertor::MAMResultConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<MAMResult>("mam_result"), + convertors(convertors) { +} + +MAMResultConvertor::~MAMResultConvertor() { +} + +boost::shared_ptr<MAMResult> MAMResultConvertor::doConvertFromLua(lua_State* L) { + boost::shared_ptr<MAMResult> result = boost::make_shared<MAMResult>(); + lua_getfield(L, -1, "payload"); + if (!lua_isnil(L, -1)) { + boost::shared_ptr<Forwarded> payload = boost::dynamic_pointer_cast<Forwarded>(convertors->convertFromLuaUntyped(L, -1, "payload")); + if (!!payload) { + result->setPayload(payload); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "id"); + if (lua_isstring(L, -1)) { + result->setID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "query_id"); + if (lua_isstring(L, -1)) { + result->setQueryID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void MAMResultConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<MAMResult> payload) { + lua_createtable(L, 0, 0); + if (convertors->convertToLuaUntyped(L, payload->getPayload()) > 0) { + lua_setfield(L, -2, "payload"); + } + lua_pushstring(L, payload->getID().c_str()); + lua_setfield(L, -2, "id"); + if (payload->getQueryID()) { + lua_pushstring(L, (*payload->getQueryID()).c_str()); + lua_setfield(L, -2, "query_id"); + } +} + +boost::optional<LuaElementConvertor::Documentation> MAMResultConvertor::getDocumentation() const { + return Documentation( + "MAMResult", + "This table has the following fields:\n\n" + "- `payload`: @{Forwarded}\n" + "- `id`: string\n" + "- `query_id`: string (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/MAMResultConvertor.h b/Sluift/ElementConvertors/MAMResultConvertor.h new file mode 100644 index 0000000..153ffd8 --- /dev/null +++ b/Sluift/ElementConvertors/MAMResultConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Sluift/GenericLuaElementConvertor.h> +#include <Swiften/Base/Override.h> +#include <Swiften/Elements/MAMResult.h> + +namespace Swift { + class LuaElementConvertors; + + class MAMResultConvertor : public GenericLuaElementConvertor<MAMResult> { + public: + MAMResultConvertor(LuaElementConvertors* convertors); + virtual ~MAMResultConvertor(); + + virtual boost::shared_ptr<MAMResult> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; + virtual void doConvertToLua(lua_State*, boost::shared_ptr<MAMResult>) SWIFTEN_OVERRIDE; + virtual boost::optional<Documentation> getDocumentation() const SWIFTEN_OVERRIDE; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/MessageConvertor.cpp b/Sluift/ElementConvertors/MessageConvertor.cpp new file mode 100644 index 0000000..9994bd0 --- /dev/null +++ b/Sluift/ElementConvertors/MessageConvertor.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/smart_ptr/make_shared.hpp> +#include <lua.hpp> +#include <Sluift/ElementConvertors/MessageConvertor.h> +#include <Sluift/LuaElementConvertors.h> + +#pragma clang diagnostic ignored "-Wunused-private-field" + +using namespace Swift; + +MessageConvertor::MessageConvertor(LuaElementConvertors* convertors) : + StanzaConvertor("message"), + convertors(convertors) { +} + +MessageConvertor::~MessageConvertor() { +} + +boost::shared_ptr<Message> MessageConvertor::doConvertFromLua(lua_State* L) { + boost::shared_ptr<Message> result = getStanza(L, convertors); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + result->setType(convertMessageTypeFromString(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void MessageConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<Message> stanza) { + pushStanza(L, stanza, convertors); + const std::string type = convertMessageTypeToString(stanza->getType()); + lua_pushstring(L, type.c_str()); + lua_setfield(L, -2, "type"); +} + +boost::optional<LuaElementConvertor::Documentation> MessageConvertor::getDocumentation() const { + return Documentation( + "Message", + "This table has the following fields:\n\n" + "- `type`: string\n" + "- `id`: string\n" + "- `from`: string\n" + "- `to`: string\n" + "- `payloads`: array<@{Payload}>\n" + ); +} + +std::string MessageConvertor::convertMessageTypeToString(Message::Type type) { + switch (type) { + case Message::Normal: return "normal"; + case Message::Chat: return "chat"; + case Message::Error: return "error"; + case Message::Groupchat: return "groupchat"; + case Message::Headline: return "headline"; + } +} + +Message::Type MessageConvertor::convertMessageTypeFromString(const std::string& type) { + if (type == "normal") { + return Message::Normal; + } + else if (type == "chat") { + return Message::Chat; + } + else if (type == "error") { + return Message::Error; + } + else if (type == "groupchat") { + return Message::Groupchat; + } + else if (type == "headline") { + return Message::Headline; + } + else { + throw Lua::Exception("Illegal message type: '" + type + "'"); + } +} diff --git a/Sluift/ElementConvertors/MessageConvertor.h b/Sluift/ElementConvertors/MessageConvertor.h new file mode 100644 index 0000000..b2167be --- /dev/null +++ b/Sluift/ElementConvertors/MessageConvertor.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Sluift/ElementConvertors/StanzaConvertor.h> +#include <Swiften/Base/Override.h> +#include <Swiften/Elements/Message.h> + +namespace Swift { + class LuaElementConvertors; + + class MessageConvertor : public StanzaConvertor<Message> { + public: + MessageConvertor(LuaElementConvertors* convertors); + virtual ~MessageConvertor(); + + virtual boost::shared_ptr<Message> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; + virtual void doConvertToLua(lua_State*, boost::shared_ptr<Message>) SWIFTEN_OVERRIDE; + + virtual boost::optional<Documentation> getDocumentation() const SWIFTEN_OVERRIDE; + + static std::string convertMessageTypeToString(Message::Type type); + static Message::Type convertMessageTypeFromString(const std::string& type); + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/PresenceConvertor.cpp b/Sluift/ElementConvertors/PresenceConvertor.cpp new file mode 100644 index 0000000..ea6bbb8 --- /dev/null +++ b/Sluift/ElementConvertors/PresenceConvertor.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/smart_ptr/make_shared.hpp> +#include <lua.hpp> +#include <Sluift/ElementConvertors/PresenceConvertor.h> +#include <Sluift/LuaElementConvertors.h> + +#pragma clang diagnostic ignored "-Wunused-private-field" + +using namespace Swift; + +PresenceConvertor::PresenceConvertor(LuaElementConvertors* convertors) : + StanzaConvertor("presence"), + convertors(convertors) { +} + +PresenceConvertor::~PresenceConvertor() { +} + +boost::shared_ptr<Presence> PresenceConvertor::doConvertFromLua(lua_State* L) { + boost::shared_ptr<Presence> result = getStanza(L, convertors); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + result->setType(convertPresenceTypeFromString(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PresenceConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<Presence> stanza) { + pushStanza(L, stanza, convertors); + const std::string type = convertPresenceTypeToString(stanza->getType()); + lua_pushstring(L, type.c_str()); + lua_setfield(L, -2, "type"); +} + +boost::optional<LuaElementConvertor::Documentation> PresenceConvertor::getDocumentation() const { + return Documentation( + "Presence", + "This table has the following fields:\n\n" + "- `type`: string\n" + "- `id`: string\n" + "- `from`: string\n" + "- `to`: string\n" + "- `payloads`: array<@{Payload}>\n" + ); +} + +std::string PresenceConvertor::convertPresenceTypeToString(Presence::Type type) { + switch (type) { + case Presence::Available: return "available"; + case Presence::Error: return "error"; + case Presence::Probe: return "probe"; + case Presence::Subscribe: return "subscribe"; + case Presence::Subscribed: return "subscribed"; + case Presence::Unavailable: return "unavailable"; + case Presence::Unsubscribe: return "unsubscribe"; + case Presence::Unsubscribed: return "unsubscribed"; + } +} + +Presence::Type PresenceConvertor::convertPresenceTypeFromString(const std::string& type) { + if (type == "available") { + return Presence::Available; + } + else if (type == "error") { + return Presence::Error; + } + else if (type == "probe") { + return Presence::Probe; + } + else if (type == "subscribe") { + return Presence::Subscribe; + } + else if (type == "subscribed") { + return Presence::Subscribed; + } + else if (type == "unavailable") { + return Presence::Unavailable; + } + else if (type == "unsubscribe") { + return Presence::Unsubscribe; + } + else if (type == "unsubscribed") { + return Presence::Unsubscribed; + } + else { + throw Lua::Exception("Illegal presence type: '" + type + "'"); + } +} diff --git a/Sluift/ElementConvertors/PresenceConvertor.h b/Sluift/ElementConvertors/PresenceConvertor.h new file mode 100644 index 0000000..d25d3a6 --- /dev/null +++ b/Sluift/ElementConvertors/PresenceConvertor.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Sluift/ElementConvertors/StanzaConvertor.h> +#include <Swiften/Base/Override.h> +#include <Swiften/Elements/Presence.h> + +namespace Swift { + class LuaElementConvertors; + + class PresenceConvertor : public StanzaConvertor<Presence> { + public: + PresenceConvertor(LuaElementConvertors* convertors); + virtual ~PresenceConvertor(); + + virtual boost::shared_ptr<Presence> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; + virtual void doConvertToLua(lua_State*, boost::shared_ptr<Presence>) SWIFTEN_OVERRIDE; + + virtual boost::optional<Documentation> getDocumentation() const SWIFTEN_OVERRIDE; + + static std::string convertPresenceTypeToString(Presence::Type type); + static Presence::Type convertPresenceTypeFromString(const std::string& type); + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/ResultSetConvertor.cpp b/Sluift/ElementConvertors/ResultSetConvertor.cpp new file mode 100644 index 0000000..a4ebbf1 --- /dev/null +++ b/Sluift/ElementConvertors/ResultSetConvertor.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/numeric/conversion/cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <lua.hpp> +#include <Sluift/ElementConvertors/ResultSetConvertor.h> + +#pragma clang diagnostic ignored "-Wunused-private-field" + +using namespace Swift; + +ResultSetConvertor::ResultSetConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<ResultSet>("result_set"), + convertors(convertors) { +} + +ResultSetConvertor::~ResultSetConvertor() { +} + +boost::shared_ptr<ResultSet> ResultSetConvertor::doConvertFromLua(lua_State* L) { + boost::shared_ptr<ResultSet> result = boost::make_shared<ResultSet>(); + lua_getfield(L, -1, "max_items"); + if (lua_isstring(L, -1)) { + result->setMaxItems(boost::numeric_cast<int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "count"); + if (lua_isnumber(L, -1)) { + result->setCount(boost::numeric_cast<int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "first_id_index"); + if (lua_isstring(L, -1)) { + result->setFirstIDIndex(boost::numeric_cast<int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "first_id"); + if (lua_isstring(L, -1)) { + result->setFirstID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "last_id"); + if (lua_isstring(L, -1)) { + result->setLastID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "after"); + if (lua_isstring(L, -1)) { + result->setAfter(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void ResultSetConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<ResultSet> payload) { + lua_createtable(L, 0, 0); + if (payload->getMaxItems()) { + lua_pushnumber(L, *payload->getMaxItems()); + lua_setfield(L, -2, "max_items"); + } + if (payload->getCount()) { + lua_pushnumber(L, *payload->getCount()); + lua_setfield(L, -2, "count"); + } + if (payload->getFirstIDIndex()) { + lua_pushnumber(L, *payload->getFirstIDIndex()); + lua_setfield(L, -2, "first_id_index"); + } + if (payload->getFirstID()) { + lua_pushstring(L, (*payload->getFirstID()).c_str()); + lua_setfield(L, -2, "first_id"); + } + if (payload->getLastID()) { + lua_pushstring(L, (*payload->getLastID()).c_str()); + lua_setfield(L, -2, "last_id"); + } + if (payload->getAfter()) { + lua_pushstring(L, (*payload->getAfter()).c_str()); + lua_setfield(L, -2, "after"); + } +} + +boost::optional<LuaElementConvertor::Documentation> ResultSetConvertor::getDocumentation() const { + return Documentation( + "ResultSet", + "This table has the following fields:\n\n" + "- `max_items`: number (Optional)\n" + "- `count`: number (Optional)\n" + "- `first_id_index`: number (Optional)\n" + "- `first_id`: string (Optional)\n" + "- `last_id`: string (Optional)\n" + "- `after`: string (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/ResultSetConvertor.h b/Sluift/ElementConvertors/ResultSetConvertor.h new file mode 100644 index 0000000..a8f4f85 --- /dev/null +++ b/Sluift/ElementConvertors/ResultSetConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Sluift/GenericLuaElementConvertor.h> +#include <Swiften/Base/Override.h> +#include <Swiften/Elements/ResultSet.h> + +namespace Swift { + class LuaElementConvertors; + + class ResultSetConvertor : public GenericLuaElementConvertor<ResultSet> { + public: + ResultSetConvertor(LuaElementConvertors* convertors); + virtual ~ResultSetConvertor(); + + virtual boost::shared_ptr<ResultSet> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; + virtual void doConvertToLua(lua_State*, boost::shared_ptr<ResultSet>) SWIFTEN_OVERRIDE; + virtual boost::optional<Documentation> getDocumentation() const SWIFTEN_OVERRIDE; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/SConscript b/Sluift/ElementConvertors/SConscript index a2de5a0..7317ac7 100644 --- a/Sluift/ElementConvertors/SConscript +++ b/Sluift/ElementConvertors/SConscript @@ -39,6 +39,14 @@ convertors = [ env.File("PubSubEventAssociateConvertor.cpp"), env.File("PubSubSubscriptionConvertor.cpp"), env.File("SecurityLabelConvertor.cpp"), - env.File("PubSubEventConfigurationConvertor.cpp") + env.File("PubSubEventConfigurationConvertor.cpp"), + env.File("IQConvertor.cpp"), + env.File("PresenceConvertor.cpp"), + env.File("MessageConvertor.cpp"), + env.File("ResultSetConvertor.cpp"), + env.File("ForwardedConvertor.cpp"), + env.File("MAMResultConvertor.cpp"), + env.File("MAMQueryConvertor.cpp"), + env.File("MAMArchivedConvertor.cpp") ] Return('convertors') diff --git a/Sluift/ElementConvertors/StanzaConvertor.h b/Sluift/ElementConvertors/StanzaConvertor.h new file mode 100644 index 0000000..405371b --- /dev/null +++ b/Sluift/ElementConvertors/StanzaConvertor.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/numeric/conversion/cast.hpp> + +#include <Sluift/GenericLuaElementConvertor.h> +#include <Sluift/LuaElementConvertors.h> +#include <Sluift/Lua/Exception.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/Message.h> + +namespace Swift { + template <typename T> class StanzaConvertor : public GenericLuaElementConvertor<T> { + public: + StanzaConvertor(const std::string& tag) + : GenericLuaElementConvertor<T>(tag) { + } + + virtual ~StanzaConvertor() { + } + + boost::shared_ptr<T> getStanza(lua_State* L, LuaElementConvertors* convertors) { + boost::shared_ptr<T> result = boost::make_shared<T>(); + lua_getfield(L, -1, "id"); + if (lua_isstring(L, -1)) { + result->setID(lua_tostring(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "from"); + if (lua_isstring(L, -1)) { + result->setFrom(lua_tostring(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "to"); + if (lua_isstring(L, -1)) { + result->setTo(lua_tostring(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "payloads"); + if (lua_type(L, -1) == LUA_TTABLE) { + for(size_t i = 0; i < lua_objlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + boost::shared_ptr<Payload> payload = boost::dynamic_pointer_cast<Payload>(convertors->convertFromLua(L, -1)); + if (!!payload) { + result->addPayload(payload); + } + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + return result; + } + + void pushStanza(lua_State* L, const boost::shared_ptr<T> stanza, LuaElementConvertors* convertors) { + lua_createtable(L, 0, 0); + lua_pushstring(L, stanza->getID().c_str()); + lua_setfield(L, -2, "id"); + lua_pushstring(L, stanza->getFrom().toString().c_str()); + lua_setfield(L, -2, "from"); + lua_pushstring(L, stanza->getTo().toString().c_str()); + lua_setfield(L, -2, "to"); + if (!stanza->getPayloads().empty()) { + lua_createtable(L, boost::numeric_cast<int>(stanza->getPayloads().size()), 0); + { + int i = 0; + foreach(const boost::shared_ptr<Payload> &item, stanza->getPayloads()) { + if (convertors->convertToLua(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + lua_setfield(L, -2, "payloads"); + } + } + }; +} diff --git a/Sluift/LuaElementConvertors.cpp b/Sluift/LuaElementConvertors.cpp index a79b578..a5d0b0a 100644 --- a/Sluift/LuaElementConvertors.cpp +++ b/Sluift/LuaElementConvertors.cpp @@ -25,6 +25,14 @@ #include <Sluift/ElementConvertors/StatusShowConvertor.h> #include <Sluift/ElementConvertors/StatusConvertor.h> #include <Sluift/ElementConvertors/DelayConvertor.h> +#include <Sluift/ElementConvertors/IQConvertor.h> +#include <Sluift/ElementConvertors/PresenceConvertor.h> +#include <Sluift/ElementConvertors/MessageConvertor.h> +#include <Sluift/ElementConvertors/ResultSetConvertor.h> +#include <Sluift/ElementConvertors/ForwardedConvertor.h> +#include <Sluift/ElementConvertors/MAMResultConvertor.h> +#include <Sluift/ElementConvertors/MAMQueryConvertor.h> +#include <Sluift/ElementConvertors/MAMArchivedConvertor.h> #include <Sluift/Lua/LuaUtils.h> #include <Sluift/Lua/Exception.h> @@ -47,6 +55,14 @@ LuaElementConvertors::LuaElementConvertors() { convertors.push_back(boost::make_shared<DOMElementConvertor>()); convertors.push_back(boost::make_shared<RawXMLElementConvertor>()); convertors.push_back(boost::make_shared<DefaultElementConvertor>()); + convertors.push_back(boost::make_shared<IQConvertor>(this)); + convertors.push_back(boost::make_shared<PresenceConvertor>(this)); + convertors.push_back(boost::make_shared<MessageConvertor>(this)); + convertors.push_back(boost::make_shared<ResultSetConvertor>(this)); + convertors.push_back(boost::make_shared<ForwardedConvertor>(this)); + convertors.push_back(boost::make_shared<MAMResultConvertor>(this)); + convertors.push_back(boost::make_shared<MAMQueryConvertor>(this)); + convertors.push_back(boost::make_shared<MAMArchivedConvertor>(this)); } LuaElementConvertors::~LuaElementConvertors() { diff --git a/Sluift/client.cpp b/Sluift/client.cpp index db259cd..06df6a4 100644 --- a/Sluift/client.cpp +++ b/Sluift/client.cpp @@ -18,6 +18,7 @@ #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> @@ -25,14 +26,20 @@ #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; @@ -236,21 +243,7 @@ SLUIFT_LUA_FUNCTION_WITH_HELP( } 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")) { @@ -312,30 +305,7 @@ SLUIFT_LUA_FUNCTION_WITH_HELP( 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()); @@ -388,15 +358,7 @@ SLUIFT_LUA_FUNCTION(Client, query_pubsub) { 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"); @@ -490,35 +452,33 @@ SLUIFT_LUA_FUNCTION_WITH_HELP( 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) { @@ -529,7 +489,7 @@ static void pushEvent(lua_State* L, const SluiftClient::Event& event) { ("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); @@ -541,7 +501,7 @@ static void pushEvent(lua_State* L, const SluiftClient::Event& event) { ("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); |