Commit ea26e098 authored by Krzysztof Misztal's avatar Krzysztof Misztal Committed by daryl herzmann

Improved CallbackOnOffline plugin (#981)

* Sending message body inside of callback

* Updated version and readme.html

* Updated changelog

* Sending POST request. Better logs. sendBody property.

* Updated readme and changelog. v1.2

* Fixed small bug
parent 3f0091c6
...@@ -44,6 +44,21 @@ ...@@ -44,6 +44,21 @@
Callback on offline Plugin Changelog Callback on offline Plugin Changelog
</h1> </h1>
<p><b>1.2</b> -- December 15, 2017</p>
<ul>
<li>Sending POST request instead of GET</li>
<li>Parameters are send as JSON body instead of query params.</li>
<li>Added "plugin.callback_on_offline.send_body" to enable/disable sending message body. True by default.</li>
<li>Slightly improved logging.</li>
</ul>
<p><b>1.1</b> -- December 14, 2017</p>
<ul>
<li>Added message body to the request. </li>
</ul>
<p><b>1.0</b> -- August 16, 2015</p> <p><b>1.0</b> -- August 16, 2015</p>
<ul> <ul>
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
<name>CallbackOnOffline</name> <name>CallbackOnOffline</name>
<description>Url is called when recipient is offline</description> <description>Url is called when recipient is offline</description>
<author>Pavel Goski</author> <author>Pavel Goski / Krzysztof Misztal</author>
<version>1.0</version> <version>1.2</version>
<date>08/16/2015</date> <date>12/15/2017</date>
<minServerVersion>2.3.0</minServerVersion> <minServerVersion>2.3.0</minServerVersion>
</plugin> </plugin>
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
</parent> </parent>
<groupId>org.igniterealtime.openfire.plugins</groupId> <groupId>org.igniterealtime.openfire.plugins</groupId>
<artifactId>callbackOnOffline</artifactId> <artifactId>callbackOnOffline</artifactId>
<version>1.0</version> <version>1.2</version>
<name>Callback on Offline Plugin</name> <name>Callback on Offline Plugin</name>
<description>Url is called when recipient is offline</description> <description>Url is called when recipient is offline</description>
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
<developer> <developer>
<name>Pavel Goski</name> <name>Pavel Goski</name>
</developer> </developer>
<developer>
<name>Krzysztof Misztal</name>
</developer>
</developers> </developers>
<build> <build>
...@@ -33,5 +36,12 @@ ...@@ -33,5 +36,12 @@
<artifactId>jersey-client</artifactId> <artifactId>jersey-client</artifactId>
<version>2.21</version> <version>2.21</version>
</dependency> </dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<scope>runtime</scope>
<version>2.26</version>
</dependency>
</dependencies> </dependencies>
</project> </project>
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#datatable .name { #datatable .name {
background-color : #DCE2F5; background-color : #DCE2F5;
} }
</style> </style>
</head> </head>
<body> <body>
...@@ -57,13 +59,35 @@ ...@@ -57,13 +59,35 @@
<h2>Overview</h2> <h2>Overview</h2>
<p> <p>
The plugin loads url from 'plugin.callback_on_offline.url' property, adds 'to' & 'from' parameters and executes GET request. The request is async. Plugin intercepts messages and checks if recipient is available. If not, plugin sends async POST request with JSON
Sample link: http://localhost:8080/user/offline/callback/url?from=1%40fotsum.com&to=2%40fotsum.com body to defined url.
</p> </p>
<p> <p>
If something don't work, set "plugin.callback_on_offline.debug" property to true and check the debug log. Example JSON body:
<pre>
<code>
{
"token":"21uh9d1h91d",
"from":"user@mychatapp.com",
"to":"user123@mychatapp.com",
"body":"Message body, so what user's typed"
}
</code>
</pre>
</p> </p>
<h2>
Callback properties
</h2>
There are few properties that can be defined to change plugin behaviour:
<ul>
<li><code>plugin.callback_on_offline.debug</code> - enable debug logs. If something doesn't work set property to true</li>
<li><code>plugin.callback_on_offline.url</code> - url that will be called</li>
<li><code>plugin.callback_on_offline.token</code> - token to be send with request</li>
<li><code>plugin.callback_on_offline.send_body</code> - boolean value to determine if message's body will be send. True by default.</li>
</ul>
</body> </body>
</html> </html>
...@@ -20,6 +20,7 @@ import org.xmpp.packet.Packet; ...@@ -20,6 +20,7 @@ import org.xmpp.packet.Packet;
import javax.ws.rs.client.Client; import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget; import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.File; import java.io.File;
...@@ -30,7 +31,14 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor { ...@@ -30,7 +31,14 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor {
private static final Logger Log = LoggerFactory.getLogger(CallbackOnOffline.class); private static final Logger Log = LoggerFactory.getLogger(CallbackOnOffline.class);
private static final String PROPERTY_DEBUG = "plugin.callback_on_offline.debug";
private static final String PROPERTY_URL = "plugin.callback_on_offline.url";
private static final String PROPERTY_TOKEN = "plugin.callback_on_offline.token";
private static final String PROPERTY_SEND_BODY = "plugin.callback_on_offline.send_body";
private boolean debug; private boolean debug;
private boolean sendBody;
private String url; private String url;
private String token; private String token;
private InterceptorManager interceptorManager; private InterceptorManager interceptorManager;
...@@ -39,9 +47,15 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor { ...@@ -39,9 +47,15 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor {
private Client client; private Client client;
public void initializePlugin(PluginManager pManager, File pluginDirectory) { public void initializePlugin(PluginManager pManager, File pluginDirectory) {
debug = JiveGlobals.getBooleanProperty("plugin.callback_on_offline.debug", false); debug = JiveGlobals.getBooleanProperty(PROPERTY_DEBUG, false);
sendBody = JiveGlobals.getBooleanProperty(PROPERTY_SEND_BODY, true);
url = getProperty(PROPERTY_URL, "http://localhost:8080/user/offline/callback/url");
token = getProperty(PROPERTY_TOKEN, UUID.randomUUID().toString());
if (debug) { if (debug) {
Log.debug("initialize CallbackOnOffline plugin. Start."); Log.debug("initialize CallbackOnOffline plugin. Start.");
Log.debug("Loaded properties: \nurl={}, \ntoken={}, \nsendBody={}", new Object[]{url, token, sendBody});
} }
interceptorManager = InterceptorManager.getInstance(); interceptorManager = InterceptorManager.getInstance();
...@@ -49,9 +63,6 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor { ...@@ -49,9 +63,6 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor {
userManager = XMPPServer.getInstance().getUserManager(); userManager = XMPPServer.getInstance().getUserManager();
client = ClientBuilder.newClient(); client = ClientBuilder.newClient();
url = getProperty("plugin.callback_on_offline.url", "http://localhost:8080/user/offline/callback/url");
token = getProperty("plugin.callback_on_offline.token", UUID.randomUUID().toString());
// register with interceptor manager // register with interceptor manager
interceptorManager.addInterceptor(this); interceptorManager.addInterceptor(this);
...@@ -87,33 +98,37 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor { ...@@ -87,33 +98,37 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor {
&& packet.getTo() != null) { && packet.getTo() != null) {
Message msg = (Message) packet; Message msg = (Message) packet;
JID to = packet.getTo();
if (msg.getType() != Message.Type.chat) { if (msg.getType() != Message.Type.chat) {
return; return;
} }
try { try {
JID to = packet.getTo();
User userTo = userManager.getUser(to.getNode()); User userTo = userManager.getUser(to.getNode());
boolean available = presenceManager.isAvailable(userTo); boolean available = presenceManager.isAvailable(userTo);
if (debug) { if (debug) {
Log.debug("intercepted message from {} to {}, recipient is available {}", new Object[] { packet.getFrom().toBareJID(), to.toBareJID(), available }); Log.debug("intercepted message from {} to {}, recipient is available {}", new Object[]{packet.getFrom().toBareJID(), to.toBareJID(), available});
} }
if (!available) { if (!available) {
JID from = packet.getFrom(); JID from = packet.getFrom();
String body = sendBody ? msg.getBody() : null;
WebTarget target = client.target(url) WebTarget target = client.target(url);
.queryParam("token", token)
.queryParam("from", from.toBareJID())
.queryParam("to", to.toBareJID());
if (debug) { if (debug) {
Log.debug("sending request to url='{}'", target); Log.debug("sending request to url='{}'", target);
} }
Future<Response> responseFuture = target.request().async().get(); MessageData data = new MessageData(token, from.toBareJID(), to.toBareJID(), body);
Future<Response> responseFuture = target
.request()
.async()
.post(Entity.json(data));
if (debug) { if (debug) {
try { try {
Response response = responseFuture.get(); Response response = responseFuture.get();
...@@ -124,6 +139,9 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor { ...@@ -124,6 +139,9 @@ public class CallbackOnOffline implements Plugin, PacketInterceptor {
} }
} }
} catch (UserNotFoundException e) { } catch (UserNotFoundException e) {
if (debug) {
Log.debug("can't find user with name: " + to.getNode());
}
} }
} }
} }
......
package com.fotsum;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public final class MessageData {
private String token;
private String from;
private String to;
private String body;
MessageData(String token, String from, String to, String body) {
this.token = token;
this.from = from;
this.to = to;
this.body = body;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MessageData that = (MessageData) o;
if (!token.equals(that.token)) return false;
if (!from.equals(that.from)) return false;
if (!to.equals(that.to)) return false;
return body.equals(that.body);
}
@Override
public int hashCode() {
int result = token.hashCode();
result = 31 * result + from.hashCode();
result = 31 * result + to.hashCode();
result = 31 * result + body.hashCode();
return result;
}
@Override
public String toString() {
return "MessageData{" +
"token='" + token + '\'' +
", from='" + from + '\'' +
", to='" + to + '\'' +
", body='" + body + '\'' +
'}';
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment