mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-21 22:02:06 +01:00
Improve ChatMarkersManager
* Created filters to be used with incoming and outgoing message stanzas * Added a list of ChatMarkersListener and its add and remove methods. * Added a stanza listener for outgoing messages. * Added a stanza listener for incoming messages. * Added discover feature for XEP-0333. * Added methods to inform a message was: received, displayed or ack * Added javadoc autor tag.
This commit is contained in:
parent
33d01bff34
commit
547138b325
8 changed files with 381 additions and 10 deletions
|
@ -35,6 +35,7 @@ public final class MessageTypeFilter extends FlexibleStanzaTypeFilter<Message> {
|
|||
public static final StanzaFilter HEADLINE = new MessageTypeFilter(Type.headline);
|
||||
public static final StanzaFilter ERROR = new MessageTypeFilter(Type.error);
|
||||
public static final StanzaFilter NORMAL_OR_CHAT = new OrFilter(NORMAL, CHAT);
|
||||
public static final StanzaFilter NORMAL_OR_CHAT_OR_GROUPCHAT = new OrFilter(NORMAL_OR_CHAT, GROUPCHAT);
|
||||
public static final StanzaFilter NORMAL_OR_CHAT_OR_HEADLINE = new OrFilter(NORMAL_OR_CHAT,
|
||||
HEADLINE);
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018 Miguel Hincapie.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.chat_markers;
|
||||
|
||||
import org.jivesoftware.smack.chat2.Chat;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
|
||||
/**
|
||||
* Chat Markers Manager class (XEP-0333).
|
||||
*
|
||||
* @author Miguel Hincapie
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0333.html">XEP-0333: Chat
|
||||
* Markers</a>
|
||||
*/
|
||||
public interface ChatMarkersListener {
|
||||
/**
|
||||
* Called in ChatMarkersManager when a new message with a markable tag arrives.
|
||||
*
|
||||
* @param chatMarkersState the current state of the message.
|
||||
* @param message the new incoming message with a markable XML tag.
|
||||
* @param chat associated to the message. This element can be <tt>NULL</tt>.
|
||||
*/
|
||||
void newChatMarkerMessage(ChatMarkersState chatMarkersState, Message message, Chat chat);
|
||||
}
|
|
@ -17,24 +17,45 @@
|
|||
package org.jivesoftware.smackx.chat_markers;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.jivesoftware.smack.AsyncButOrdered;
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.StanzaListener;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
|
||||
import org.jivesoftware.smack.chat2.Chat;
|
||||
import org.jivesoftware.smack.chat2.ChatManager;
|
||||
import org.jivesoftware.smack.filter.AndFilter;
|
||||
import org.jivesoftware.smack.filter.MessageTypeFilter;
|
||||
import org.jivesoftware.smack.filter.MessageWithBodiesFilter;
|
||||
import org.jivesoftware.smack.filter.NotFilter;
|
||||
import org.jivesoftware.smack.filter.PossibleFromTypeFilter;
|
||||
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
||||
import org.jivesoftware.smack.filter.StanzaFilter;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Stanza;
|
||||
import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements;
|
||||
import org.jivesoftware.smackx.chat_markers.filter.ChatMarkersFilter;
|
||||
import org.jivesoftware.smackx.chat_markers.filter.EligibleForChatMarker;
|
||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.jxmpp.jid.EntityFullJid;
|
||||
|
||||
/**
|
||||
* Chat Markers Manager class (XEP-0333).
|
||||
*
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0333.html">XEP-0333: Chat
|
||||
* Markers</a>
|
||||
* @author Miguel Hincapie
|
||||
* @author Fernando Ramirez
|
||||
*
|
||||
*/
|
||||
|
@ -51,10 +72,30 @@ public final class ChatMarkersManager extends Manager {
|
|||
|
||||
private static final Map<XMPPConnection, ChatMarkersManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
// @FORMATTER:OFF
|
||||
private static final StanzaFilter INCOMING_MESSAGE_FILTER = new AndFilter(
|
||||
MessageTypeFilter.NORMAL_OR_CHAT_OR_GROUPCHAT,
|
||||
new StanzaExtensionFilter(ChatMarkersElements.NAMESPACE),
|
||||
PossibleFromTypeFilter.ENTITY_BARE_JID,
|
||||
EligibleForChatMarker.INSTANCE
|
||||
);
|
||||
|
||||
private static final StanzaFilter OUTGOING_MESSAGE_FILTER = new AndFilter(
|
||||
MessageTypeFilter.NORMAL_OR_CHAT_OR_GROUPCHAT,
|
||||
MessageWithBodiesFilter.INSTANCE,
|
||||
new NotFilter(ChatMarkersFilter.INSTANCE),
|
||||
EligibleForChatMarker.INSTANCE
|
||||
);
|
||||
// @FORMATTER:ON
|
||||
|
||||
private final Set<ChatMarkersListener> incomingListeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
private final AsyncButOrdered<Chat> asyncButOrdered = new AsyncButOrdered<>();
|
||||
|
||||
/**
|
||||
* Get the singleton instance of ChatMarkersManager.
|
||||
*
|
||||
* @param connection
|
||||
* @param connection the connection used to get the ChatMarkersManager instance.
|
||||
* @return the instance of ChatMarkersManager
|
||||
*/
|
||||
public static synchronized ChatMarkersManager getInstanceFor(XMPPConnection connection) {
|
||||
|
@ -70,16 +111,66 @@ public final class ChatMarkersManager extends Manager {
|
|||
|
||||
private ChatMarkersManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
connection.addStanzaInterceptor(new StanzaListener() {
|
||||
@Override
|
||||
public void processStanza(Stanza packet)
|
||||
throws
|
||||
NotConnectedException,
|
||||
InterruptedException,
|
||||
SmackException.NotLoggedInException {
|
||||
Message message = (Message) packet;
|
||||
// add a markable extension
|
||||
message.addExtension(new ChatMarkersElements.MarkableExtension());
|
||||
}
|
||||
}, OUTGOING_MESSAGE_FILTER);
|
||||
|
||||
connection.addSyncStanzaListener(new StanzaListener() {
|
||||
@Override
|
||||
public void processStanza(Stanza packet)
|
||||
throws
|
||||
NotConnectedException,
|
||||
InterruptedException,
|
||||
SmackException.NotLoggedInException {
|
||||
final Message message = (Message) packet;
|
||||
|
||||
EntityFullJid fullFrom = message.getFrom().asEntityFullJidIfPossible();
|
||||
EntityBareJid bareFrom = fullFrom.asEntityBareJid();
|
||||
final Chat chat = ChatManager.getInstanceFor(connection()).chatWith(bareFrom);
|
||||
|
||||
asyncButOrdered.performAsyncButOrdered(chat, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (ChatMarkersListener listener : incomingListeners) {
|
||||
if (ChatMarkersElements.MarkableExtension.from(message) != null) {
|
||||
listener.newChatMarkerMessage(ChatMarkersState.markable, message, chat);
|
||||
}
|
||||
else if (ChatMarkersElements.ReceivedExtension.from(message) != null) {
|
||||
listener.newChatMarkerMessage(ChatMarkersState.received, message, chat);
|
||||
}
|
||||
else if (ChatMarkersElements.DisplayedExtension.from(message) != null) {
|
||||
listener.newChatMarkerMessage(ChatMarkersState.displayed, message, chat);
|
||||
}
|
||||
else if (ChatMarkersElements.AcknowledgedExtension.from(message) != null) {
|
||||
listener.newChatMarkerMessage(ChatMarkersState.acknowledged, message, chat);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}, INCOMING_MESSAGE_FILTER);
|
||||
|
||||
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(ChatMarkersElements.NAMESPACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if Chat Markers is supported by the server.
|
||||
*
|
||||
* @return true if Chat Markers is supported by the server.
|
||||
* @throws NotConnectedException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NoResponseException
|
||||
* @throws InterruptedException
|
||||
* @throws NotConnectedException if the connection is not connected.
|
||||
* @throws XMPPErrorException in case an error response was received.
|
||||
* @throws NoResponseException if no response was received.
|
||||
* @throws InterruptedException if the connection is interrupted.
|
||||
*/
|
||||
public boolean isSupportedByServer()
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
|
@ -87,4 +178,64 @@ public final class ChatMarkersManager extends Manager {
|
|||
.serverSupportsFeature(ChatMarkersElements.NAMESPACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a ChatMarkersListener. That listener will be informed about new
|
||||
* incoming markable messages.
|
||||
*
|
||||
* @param listener ChatMarkersListener
|
||||
* @return true, if the listener was not registered before
|
||||
*/
|
||||
public boolean addIncomingChatMarkerMessageListener(ChatMarkersListener listener) {
|
||||
return incomingListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a ChatMarkersListener.
|
||||
*
|
||||
* @param listener ChatMarkersListener
|
||||
* @return true, if the listener was registered before
|
||||
*/
|
||||
public boolean removeIncomingChatMarkerMessageListener(ChatMarkersListener listener) {
|
||||
return incomingListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void markMessageAsReceived(Message message)
|
||||
throws
|
||||
NotConnectedException,
|
||||
InterruptedException,
|
||||
IllegalArgumentException {
|
||||
if (message == null) {
|
||||
throw new IllegalArgumentException("To and From needed");
|
||||
}
|
||||
message.addExtension(new ChatMarkersElements.ReceivedExtension(message.getStanzaId()));
|
||||
sendChatMarkerMessage(message);
|
||||
}
|
||||
|
||||
public void markMessageAsDisplayed(Message message)
|
||||
throws
|
||||
NotConnectedException,
|
||||
InterruptedException,
|
||||
IllegalArgumentException {
|
||||
if (message == null) {
|
||||
throw new IllegalArgumentException("To and From needed");
|
||||
}
|
||||
message.addExtension(new ChatMarkersElements.DisplayedExtension(message.getStanzaId()));
|
||||
sendChatMarkerMessage(message);
|
||||
}
|
||||
|
||||
public void markMessageAsAcknowledged(Message message)
|
||||
throws
|
||||
NotConnectedException,
|
||||
InterruptedException,
|
||||
IllegalArgumentException {
|
||||
if (message == null) {
|
||||
throw new IllegalArgumentException("To and From needed");
|
||||
}
|
||||
message.addExtension(new ChatMarkersElements.AcknowledgedExtension(message.getStanzaId()));
|
||||
sendChatMarkerMessage(message);
|
||||
}
|
||||
|
||||
private void sendChatMarkerMessage(Message message) throws NotConnectedException, InterruptedException {
|
||||
connection().sendStanza(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
*
|
||||
* Copyright © 2018 Miguel Hincapie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.chat_markers;
|
||||
|
||||
/**
|
||||
* Chat Markers elements (XEP-0333).
|
||||
*
|
||||
* @author Miguel Hincapie
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0333.html">XEP-0333: Chat
|
||||
* Markers</a>
|
||||
*/
|
||||
public enum ChatMarkersState {
|
||||
/**
|
||||
* Indicates that a message can be marked with a Chat Marker and is therefore
|
||||
* a "markable message".
|
||||
*/
|
||||
markable,
|
||||
/**
|
||||
* The message has been received by a client.
|
||||
*/
|
||||
received,
|
||||
/**
|
||||
* The message has been displayed to a user in a active chat and not in a system notification.
|
||||
*/
|
||||
displayed,
|
||||
/**
|
||||
* The message has been acknowledged by some user interaction e.g. pressing an
|
||||
* acknowledgement button.
|
||||
*/
|
||||
acknowledged
|
||||
}
|
|
@ -19,6 +19,7 @@ package org.jivesoftware.smackx.chat_markers.element;
|
|||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smackx.chat_markers.ChatMarkersState;
|
||||
|
||||
/**
|
||||
* Chat Markers elements (XEP-0333).
|
||||
|
@ -45,7 +46,7 @@ public class ChatMarkersElements {
|
|||
/**
|
||||
* markable element.
|
||||
*/
|
||||
public static final String ELEMENT = "markable";
|
||||
public static final String ELEMENT = ChatMarkersState.markable.toString();
|
||||
|
||||
public MarkableExtension() {
|
||||
}
|
||||
|
@ -85,7 +86,7 @@ public class ChatMarkersElements {
|
|||
/**
|
||||
* received element.
|
||||
*/
|
||||
public static final String ELEMENT = "received";
|
||||
public static final String ELEMENT = ChatMarkersState.received.toString();
|
||||
|
||||
private final String id;
|
||||
|
||||
|
@ -138,7 +139,7 @@ public class ChatMarkersElements {
|
|||
/**
|
||||
* displayed element.
|
||||
*/
|
||||
public static final String ELEMENT = "displayed";
|
||||
public static final String ELEMENT = ChatMarkersState.displayed.toString();
|
||||
|
||||
private final String id;
|
||||
|
||||
|
@ -191,7 +192,7 @@ public class ChatMarkersElements {
|
|||
/**
|
||||
* acknowledged element.
|
||||
*/
|
||||
public static final String ELEMENT = "acknowledged";
|
||||
public static final String ELEMENT = ChatMarkersState.acknowledged.toString();
|
||||
|
||||
private final String id;
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018 Miguel Hincapie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.chat_markers.filter;
|
||||
|
||||
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
||||
import org.jivesoftware.smack.filter.StanzaFilter;
|
||||
import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements;
|
||||
|
||||
/**
|
||||
* Chat Markers Manager class (XEP-0333).
|
||||
*
|
||||
* @author HINCM008 6/08/2018.
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0333.html">XEP-0333: Chat
|
||||
* Markers</a>
|
||||
*/
|
||||
public final class ChatMarkersFilter extends StanzaExtensionFilter {
|
||||
|
||||
public static final StanzaFilter INSTANCE = new ChatMarkersFilter(ChatMarkersElements.NAMESPACE);
|
||||
|
||||
private ChatMarkersFilter(String namespace) {
|
||||
super(namespace);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018 Miguel Hincapie.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.chat_markers.filter;
|
||||
|
||||
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.Stanza;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smackx.chatstates.ChatState;
|
||||
import org.jivesoftware.smackx.chatstates.ChatStateManager;
|
||||
|
||||
/**
|
||||
* Chat Markers Manager class (XEP-0333).
|
||||
*
|
||||
* @author Miguel Hincapie
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0333.html">XEP-0333: Chat
|
||||
* Markers</a>
|
||||
*/
|
||||
public final class EligibleForChatMarker extends StanzaExtensionFilter {
|
||||
|
||||
public static final EligibleForChatMarker INSTANCE = new EligibleForChatMarker(ChatStateManager.NAMESPACE);
|
||||
|
||||
private EligibleForChatMarker(String namespace) {
|
||||
super(namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* From XEP-0333, Protocol Format: The Chat Marker MUST have an 'id' which is the 'id' of the
|
||||
* message being marked.<br>
|
||||
* In order to make Chat Markers works together with XEP-0085 as it said in
|
||||
* 8.5 Interaction with Chat States, only messages with <tt>active</tt> chat
|
||||
* state are accepted.
|
||||
*
|
||||
* @param message to be analyzed.
|
||||
* @return true if the message contains a stanza Id.
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0333.html">XEP-0333: Chat Markers</a>
|
||||
*/
|
||||
@Override
|
||||
public boolean accept(Stanza message) {
|
||||
if (StringUtils.isNullOrEmpty(message.getStanzaId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (super.accept(message)) {
|
||||
ExtensionElement extension = message.getExtension(ChatStateManager.NAMESPACE);
|
||||
String chatStateElementName = extension.getElementName();
|
||||
|
||||
ChatState state;
|
||||
try {
|
||||
state = ChatState.valueOf(chatStateElementName);
|
||||
return (state == ChatState.active);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018 Miguel Hincapie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Chat Markers elements (XEP-0333).
|
||||
*
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0333.html">XEP-0333: Chat
|
||||
* Markers</a>
|
||||
*
|
||||
*/
|
||||
package org.jivesoftware.smackx.chat_markers.filter;
|
Loading…
Reference in a new issue