Provide a more flexible way to label messages.
I'm not quite sure about chans yet
This commit is contained in:
parent
4f7f80c12a
commit
e8ddf90363
@ -6,7 +6,7 @@ subprojects {
|
||||
|
||||
sourceCompatibility = 1.7
|
||||
group = 'ch.dissem.jabit'
|
||||
version = '1.0.2-SNAPSHOT'
|
||||
version = '1.1.0-SNAPSHOT'
|
||||
|
||||
ext.isReleaseVersion = !version.endsWith("SNAPSHOT")
|
||||
|
||||
|
@ -17,7 +17,10 @@
|
||||
package ch.dissem.bitmessage;
|
||||
|
||||
import ch.dissem.bitmessage.entity.*;
|
||||
import ch.dissem.bitmessage.entity.payload.*;
|
||||
import ch.dissem.bitmessage.entity.payload.Broadcast;
|
||||
import ch.dissem.bitmessage.entity.payload.Msg;
|
||||
import ch.dissem.bitmessage.entity.payload.ObjectPayload;
|
||||
import ch.dissem.bitmessage.entity.payload.ObjectType;
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey.Feature;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
||||
@ -65,6 +68,7 @@ public class BitmessageContext {
|
||||
|
||||
private final InternalContext ctx;
|
||||
|
||||
private final Labeler labeler;
|
||||
private final Listener listener;
|
||||
private final NetworkHandler.MessageListener networkListener;
|
||||
|
||||
@ -72,8 +76,9 @@ public class BitmessageContext {
|
||||
|
||||
private BitmessageContext(Builder builder) {
|
||||
ctx = new InternalContext(builder);
|
||||
labeler = builder.labeler;
|
||||
listener = builder.listener;
|
||||
networkListener = new DefaultMessageListener(ctx, listener);
|
||||
networkListener = new DefaultMessageListener(ctx, labeler, listener);
|
||||
|
||||
// As this thread is used for parts that do POW, which itself uses parallel threads, only
|
||||
// one should be executed at any time.
|
||||
@ -97,6 +102,10 @@ public class BitmessageContext {
|
||||
return ctx.getMessageRepository();
|
||||
}
|
||||
|
||||
public Labeler labeler() {
|
||||
return labeler;
|
||||
}
|
||||
|
||||
public BitmessageAddress createIdentity(boolean shorter, Feature... features) {
|
||||
final BitmessageAddress identity = new BitmessageAddress(new PrivateKey(
|
||||
shorter,
|
||||
@ -280,7 +289,9 @@ public class BitmessageContext {
|
||||
try {
|
||||
Broadcast broadcast = (Broadcast) object.getPayload();
|
||||
broadcast.decrypt(address);
|
||||
listener.receive(broadcast.getPlaintext());
|
||||
// This decrypts it twice, but on the other hand it doesn't try to decrypt the objects with
|
||||
// other subscriptions and the interface stays as simple as possible.
|
||||
networkListener.receive(object);
|
||||
} catch (DecryptionFailedException ignore) {
|
||||
} catch (Exception e) {
|
||||
LOG.debug(e.getMessage(), e);
|
||||
@ -318,6 +329,7 @@ public class BitmessageContext {
|
||||
Cryptography cryptography;
|
||||
MessageCallback messageCallback;
|
||||
CustomCommandHandler customCommandHandler;
|
||||
Labeler labeler;
|
||||
Listener listener;
|
||||
int connectionLimit = 150;
|
||||
long connectionTTL = 30 * MINUTE;
|
||||
@ -378,6 +390,11 @@ public class BitmessageContext {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder labeler(Labeler labeler) {
|
||||
this.labeler = labeler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder listener(Listener listener) {
|
||||
this.listener = listener;
|
||||
return this;
|
||||
@ -430,6 +447,9 @@ public class BitmessageContext {
|
||||
if (messageCallback == null) {
|
||||
messageCallback = new BaseMessageCallback();
|
||||
}
|
||||
if (labeler == null) {
|
||||
labeler = new DefaultLabeler();
|
||||
}
|
||||
if (customCommandHandler == null) {
|
||||
customCommandHandler = new CustomCommandHandler() {
|
||||
@Override
|
||||
|
@ -20,8 +20,9 @@ import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.payload.*;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||
import ch.dissem.bitmessage.ports.Labeler;
|
||||
import ch.dissem.bitmessage.ports.NetworkHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -36,10 +37,12 @@ import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
||||
class DefaultMessageListener implements NetworkHandler.MessageListener {
|
||||
private final static Logger LOG = LoggerFactory.getLogger(DefaultMessageListener.class);
|
||||
private final InternalContext ctx;
|
||||
private final Labeler labeler;
|
||||
private final BitmessageContext.Listener listener;
|
||||
|
||||
public DefaultMessageListener(InternalContext context, BitmessageContext.Listener listener) {
|
||||
public DefaultMessageListener(InternalContext context, Labeler labeler, BitmessageContext.Listener listener) {
|
||||
this.ctx = context;
|
||||
this.labeler = labeler;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@ -127,12 +130,7 @@ class DefaultMessageListener implements NetworkHandler.MessageListener {
|
||||
if (!object.isSignatureValid(msg.getPlaintext().getFrom().getPubkey())) {
|
||||
LOG.warn("Msg with IV " + object.getInventoryVector() + " was successfully decrypted, but signature check failed. Ignoring.");
|
||||
} else {
|
||||
msg.getPlaintext().setStatus(RECEIVED);
|
||||
msg.getPlaintext().addLabels(ctx.getMessageRepository().getLabels(Label.Type.INBOX, Label.Type.UNREAD));
|
||||
msg.getPlaintext().setInventoryVector(object.getInventoryVector());
|
||||
ctx.getMessageRepository().save(msg.getPlaintext());
|
||||
listener.receive(msg.getPlaintext());
|
||||
updatePubkey(msg.getPlaintext().getFrom(), msg.getPlaintext().getFrom().getPubkey());
|
||||
receive(object.getInventoryVector(), msg.getPlaintext());
|
||||
}
|
||||
break;
|
||||
} catch (DecryptionFailedException ignore) {
|
||||
@ -151,15 +149,19 @@ class DefaultMessageListener implements NetworkHandler.MessageListener {
|
||||
if (!object.isSignatureValid(broadcast.getPlaintext().getFrom().getPubkey())) {
|
||||
LOG.warn("Broadcast with IV " + object.getInventoryVector() + " was successfully decrypted, but signature check failed. Ignoring.");
|
||||
} else {
|
||||
broadcast.getPlaintext().setStatus(RECEIVED);
|
||||
broadcast.getPlaintext().addLabels(ctx.getMessageRepository().getLabels(Label.Type.INBOX, Label.Type.BROADCAST, Label.Type.UNREAD));
|
||||
broadcast.getPlaintext().setInventoryVector(object.getInventoryVector());
|
||||
ctx.getMessageRepository().save(broadcast.getPlaintext());
|
||||
listener.receive(broadcast.getPlaintext());
|
||||
updatePubkey(broadcast.getPlaintext().getFrom(), broadcast.getPlaintext().getFrom().getPubkey());
|
||||
receive(object.getInventoryVector(), broadcast.getPlaintext());
|
||||
}
|
||||
} catch (DecryptionFailedException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void receive(InventoryVector iv, Plaintext msg) {
|
||||
msg.setStatus(RECEIVED);
|
||||
msg.setInventoryVector(iv);
|
||||
labeler.setLabels(msg);
|
||||
ctx.getMessageRepository().save(msg);
|
||||
listener.receive(msg);
|
||||
updatePubkey(msg.getFrom(), msg.getFrom().getPubkey());
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ public class InternalContext {
|
||||
|
||||
init(cryptography, inventory, nodeRegistry, networkHandler, addressRepository, messageRepository,
|
||||
proofOfWorkRepository, proofOfWorkService, proofOfWorkEngine,
|
||||
messageCallback, customCommandHandler);
|
||||
messageCallback, customCommandHandler, builder.labeler);
|
||||
for (BitmessageAddress identity : addressRepository.getIdentities()) {
|
||||
streams.add(identity.getStream());
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.ports;
|
||||
|
||||
import ch.dissem.bitmessage.InternalContext;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class DefaultLabeler implements Labeler, InternalContext.ContextHolder {
|
||||
private InternalContext ctx;
|
||||
|
||||
@Override
|
||||
public void setLabels(Plaintext msg) {
|
||||
if (msg.getType() == Plaintext.Type.BROADCAST) {
|
||||
msg.addLabels(ctx.getMessageRepository().getLabels(Label.Type.INBOX, Label.Type.BROADCAST, Label.Type.UNREAD));
|
||||
} else {
|
||||
msg.addLabels(ctx.getMessageRepository().getLabels(Label.Type.INBOX, Label.Type.UNREAD));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markAsRead(Plaintext msg) {
|
||||
Iterator<Label> iterator = msg.getLabels().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Label label = iterator.next();
|
||||
if (label.getType() == Label.Type.UNREAD) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markAsUnread(Plaintext msg) {
|
||||
msg.addLabels(ctx.getMessageRepository().getLabels(Label.Type.UNREAD));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Plaintext msg) {
|
||||
msg.getLabels().clear();
|
||||
msg.addLabels(ctx.getMessageRepository().getLabels(Label.Type.TRASH));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void archive(Plaintext msg) {
|
||||
msg.getLabels().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContext(InternalContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
}
|
39
core/src/main/java/ch/dissem/bitmessage/ports/Labeler.java
Normal file
39
core/src/main/java/ch/dissem/bitmessage/ports/Labeler.java
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.ports;
|
||||
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
|
||||
/**
|
||||
* Defines and sets labels
|
||||
*/
|
||||
public interface Labeler {
|
||||
/**
|
||||
* Sets the labels of a newly received message.
|
||||
*
|
||||
* @param msg an unlabeled message or broadcast
|
||||
*/
|
||||
void setLabels(Plaintext msg);
|
||||
|
||||
void markAsRead(Plaintext msg);
|
||||
|
||||
void markAsUnread(Plaintext msg);
|
||||
|
||||
void delete(Plaintext msg);
|
||||
|
||||
void archive(Plaintext msg);
|
||||
}
|
@ -143,10 +143,11 @@ public class BitmessageContextTest {
|
||||
objects.add(TestUtils.loadObjectMessage(5, "V5Broadcast.payload"));
|
||||
when(ctx.internals().getInventory().getObjects(eq(address.getStream()), anyLong(), any(ObjectType.class)))
|
||||
.thenReturn(objects);
|
||||
when(ctx.addresses().getSubscriptions(anyLong())).thenReturn(Collections.singletonList(address));
|
||||
|
||||
ctx.addSubscribtion(address);
|
||||
|
||||
verify(ctx.addresses(), times(1)).save(address);
|
||||
verify(ctx.addresses(), atLeastOnce()).save(address);
|
||||
assertThat(address.isSubscribed(), is(true));
|
||||
verify(ctx.internals().getInventory()).getObjects(eq(address.getStream()), anyLong(), any(ObjectType.class));
|
||||
verify(listener).receive(any(Plaintext.class));
|
||||
@ -232,6 +233,7 @@ public class BitmessageContextTest {
|
||||
expected.remove(a.getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureShortDeterministicAddressesAreCreated() {
|
||||
final int expected_size = 1;
|
||||
|
@ -25,6 +25,7 @@ import ch.dissem.bitmessage.entity.payload.GetPubkey;
|
||||
import ch.dissem.bitmessage.entity.payload.Msg;
|
||||
import ch.dissem.bitmessage.factory.Factory;
|
||||
import ch.dissem.bitmessage.ports.AddressRepository;
|
||||
import ch.dissem.bitmessage.ports.Labeler;
|
||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||
import ch.dissem.bitmessage.utils.Singleton;
|
||||
import ch.dissem.bitmessage.utils.TestBase;
|
||||
@ -62,7 +63,7 @@ public class DefaultMessageListenerTest extends TestBase {
|
||||
when(ctx.getAddressRepository()).thenReturn(addressRepo);
|
||||
when(ctx.getMessageRepository()).thenReturn(messageRepo);
|
||||
|
||||
listener = new DefaultMessageListener(ctx, mock(BitmessageContext.Listener.class));
|
||||
listener = new DefaultMessageListener(ctx, mock(Labeler.class), mock(BitmessageContext.Listener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -21,6 +21,7 @@ import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import ch.dissem.bitmessage.networking.DefaultNetworkHandler;
|
||||
import ch.dissem.bitmessage.ports.MemoryNodeRegistry;
|
||||
import ch.dissem.bitmessage.repository.*;
|
||||
@ -30,6 +31,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ch.dissem.bitmessage.demo.CommandLine.COMMAND_BACK;
|
||||
import static ch.dissem.bitmessage.demo.CommandLine.ERROR_UNKNOWN_COMMAND;
|
||||
@ -325,8 +327,10 @@ public class Application {
|
||||
System.out.println();
|
||||
System.out.println(message.getText());
|
||||
System.out.println();
|
||||
System.out.println("Labels: " + message.getLabels());
|
||||
System.out.println(message.getLabels().stream().map(Label::toString).collect(
|
||||
Collectors.joining("Labels: ", ", ", "")));
|
||||
System.out.println();
|
||||
ctx.labeler().markAsRead(message);
|
||||
String command;
|
||||
do {
|
||||
System.out.println("r) reply");
|
||||
|
Loading…
Reference in New Issue
Block a user