Added no2all

This commit is contained in:
Willem Cazander 2024-11-23 19:01:19 +01:00
parent 67185f479a
commit 4dabe2d905
153 changed files with 7022 additions and 3 deletions

34
nx01-no2all-nostr/pom.xml Normal file
View file

@ -0,0 +1,34 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>love.distributedrebirth.nx01</groupId>
<artifactId>nx01</artifactId>
<version>〇一。壬寅。一〄-SNAPSHOT</version>
</parent>
<artifactId>nx01-no2all-nostr</artifactId>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>love.distributedrebirth.nx01</groupId>
<artifactId>nx01-x4o-driver</artifactId>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>parsson</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,25 @@
package love.distributedrebirth.no2all.nostr;
import java.util.function.Consumer;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireWaterBoiler;
import love.distributedrebirth.no2all.nostr.fire.NoStrFirePipe;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentity;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToClient;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToRelay;
public enum NoStr {
FACTORY;
public NoStrFireWaterBoiler boiler(NoStrIdentity identity) {
return new NoStrFireWaterBoiler(identity);
}
public NoStrFirePipe pipeReaderClient(Consumer<String> errHandler, Consumer<NoStrMsgToClient> msgHandler) {
return new NoStrFirePipe(errHandler, null, msgHandler);
}
public NoStrFirePipe pipeReaderRelay(Consumer<String> errHandler, Consumer<NoStrMsgToRelay> msgHandler) {
return new NoStrFirePipe(errHandler, msgHandler, null);
}
}

View file

@ -0,0 +1,9 @@
package love.distributedrebirth.no2all.nostr;
import jakarta.json.JsonValue;
public interface NoStrGospel {
// slow version, add perf test, rewrite to streaming mode
JsonValue toBible();
}

View file

@ -0,0 +1,72 @@
package love.distributedrebirth.no2all.nostr.fire;
import java.io.StringReader;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonReader;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToClient;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToRelay;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrFirePipe {
private static final String ERROR_INVALID_JSON = "Invalid json; "; // on json parse
private static final String ERROR_INVALID_ROOT = "Invalid root; "; // on none array root
private static final String ERROR_TYPE_UNKNOWN = "Unknown type; "; // on not in values()
private static final String ERROR_TYPE_ILLEGAL = "Illegal type"; // on null mapper
private static final int MSG_TYPE_INDEX = 0;
private final Consumer<String> errHandler;
private final Consumer<NoStrMsgToRelay> msgHandlerToRelay;
private final Consumer<NoStrMsgToClient> msgHandlerToClient;
public NoStrFirePipe(Consumer<String> errHandler, Consumer<NoStrMsgToRelay> msgHandlerToRelay,
Consumer<NoStrMsgToClient> msgHandlerToClient) {
this.errHandler = Objects.requireNonNull(errHandler);
this.msgHandlerToRelay = msgHandlerToRelay;
this.msgHandlerToClient = msgHandlerToClient;
if (msgHandlerToRelay != null && msgHandlerToClient != null) {
throw new IllegalArgumentException("Only use one message handler");
}
if (msgHandlerToRelay == null && msgHandlerToClient == null) {
throw new NullPointerException("Need one message handler");
}
}
public void onFire(String msgStr) {
JsonValue msgJson = null;
try (JsonReader jsonReader = Json.createReader(new StringReader(msgStr))) {
msgJson = jsonReader.readValue();
} catch (Exception e) {
errHandler.accept(ERROR_INVALID_JSON + e.getMessage());
return;
}
if (!JsonValue.ValueType.ARRAY.equals(msgJson.getValueType())) {
errHandler.accept(ERROR_INVALID_ROOT + msgJson.getValueType().name());
return;
}
JsonArray msgPacket = msgJson.asJsonArray();
String msgTypeRaw = msgPacket.getString(MSG_TYPE_INDEX);
if (!NoStrImplMessageType.valueOfValid(msgTypeRaw)) {
errHandler.accept(ERROR_TYPE_UNKNOWN + msgTypeRaw);
return;
}
NoStrImplMessageType msgType = NoStrImplMessageType.valueOf(msgTypeRaw);
if (msgHandlerToClient != null) {
acceptType(msgType.getMapperToClient(), v -> msgHandlerToClient.accept(v.apply(msgPacket))); // on relay
} else {
acceptType(msgType.getMapperToRelay(), v -> msgHandlerToRelay.accept(v.apply(msgPacket))); // on client
}
}
private <T> void acceptType(Optional<T> mapper, Consumer<T> messageHandler) {
if (mapper.isEmpty()) {
errHandler.accept(ERROR_TYPE_ILLEGAL);
return;
}
messageHandler.accept(mapper.get());
}
}

View file

@ -0,0 +1,8 @@
package love.distributedrebirth.no2all.nostr.fire;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTag;
public interface NoStrFireStackFishWelder {
NoStrFireStackWelder tag(NoStrEventTag eventTag);
}

View file

@ -0,0 +1,76 @@
package love.distributedrebirth.no2all.nostr.fire;
import java.util.List;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTag;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagMeta;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagA;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagAlt;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagClient;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagContentWarning;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagD;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagDescription;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagE;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagI;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagImage;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagName;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagNonce;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagP;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagPublishedAt;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagR;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagSubject;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagSummary;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagT;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagThumb;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagTitle;
public class NoStrFireStackWelder implements NoStrFireStackFishWelder,
NoStrTagA.FishWelder,
NoStrTagAlt.FishWelder,
NoStrTagClient.FishWelder,
NoStrTagContentWarning.FishWelder,
NoStrTagD.FishWelder,
NoStrTagDescription.FishWelder,
NoStrTagE.FishWelder,
NoStrTagI.FishWelder,
NoStrTagImage.FishWelder,
NoStrTagName.FishWelder,
NoStrTagNonce.FishWelder,
NoStrTagP.FishWelder,
NoStrTagPublishedAt.FishWelder,
NoStrTagR.FishWelder,
NoStrTagSubject.FishWelder,
NoStrTagSummary.FishWelder,
NoStrTagT.FishWelder,
NoStrTagThumb.FishWelder,
NoStrTagTitle.FishWelder
{
private final NoStrFireWaterWelder welder;
protected NoStrFireStackWelder(NoStrFireWaterWelder welder) {
this.welder = welder;
}
public NoStrFireWaterWelder burn() {
return welder;
}
@Override
public NoStrFireStackWelder tag(NoStrEventTag eventTag) {
welder.smokeTag(eventTag);
return this;
}
public NoStrFireStackWelder tags(List<NoStrEventTag> eventTags) {
eventTags.forEach(v -> welder.smokeTag(v));
return this;
}
public NoStrFireStackWelder tag(NoStrEventTagMeta tag, String... args) {
return tag(NoStrEventTag.valueOf(tag, args));
}
public NoStrFireStackWelder tag(String tag, String... args) {
return tag(NoStrEventTagMeta.valueOf(tag), args);
}
}

View file

@ -0,0 +1,62 @@
package love.distributedrebirth.no2all.nostr.fire;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentity;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.model.NoStrProfileMetaData;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEvent;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagP;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventKind;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public final class NoStrFireWaterBoiler {
private final NoStrIdentity identity;
public NoStrFireWaterBoiler(NoStrIdentity identity) {
this.identity = Objects.requireNonNull(identity);
}
public NoStrFireWaterWelder burn() {
return new NoStrFireWaterWelder(identity);
}
public NoStrFireStackWelder smoker() {
return new NoStrFireStackWelder(burn());
}
public NoStrEvent boilProfileMetaData(NoStrProfileMetaData profileData) {
return burn().water(NoStrImplEventKind.METADATA, profileData.toBible().toString());
}
public NoStrEvent boilClientAuth(String relay, String challenge) {
return smoker()
.tag(NoStrImplEventTag.RELAY, relay)
.tag(NoStrImplEventTag.CHALLENGE, challenge)
.burn()
.water(NoStrImplEventKind.CLIENT_AUTH);
}
public NoStrEvent boilRecommendRelay(String relayUrl) {
return burn().water(NoStrImplEventKind.RECOMMEND_RELAY, relayUrl);
}
public NoStrEvent boilTextNote(String content, String subject, List<NoStrIdentityPublicKey> pubs) {
return smoker()
.tagSubject(subject)
.tags(pubs.stream().map(v -> new NoStrTagP(v, Optional.empty(), Optional.empty())).collect(Collectors.toList()))
.burn()
.water(NoStrImplEventKind.TEXT_NOTE, content);
}
// public NoStrEvent waterTextNote(String content, List<Object> eTags, List<NoStrIdentityPublicKey> pubs) {
// return smoker()
// .tag(NoStrImplEventTag.P, pubs.stream().map(v -> v.getHex()).collect(Collectors.toList()))
// .weld()
// .water(NoStrImplEventKind.TEXT_NOTE, content);
// }
}

View file

@ -0,0 +1,70 @@
package love.distributedrebirth.no2all.nostr.fire;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentity;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEvent;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventKind;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventPayload;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventSignature;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTag;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagMeta;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagClient;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventKind;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public class NoStrFireWaterWelder {
private final List<NoStrEventTag> smokeTags = new ArrayList<>();
private final NoStrIdentity identity;
public NoStrFireWaterWelder(NoStrIdentity identity) {
this.identity = Objects.requireNonNull(identity);
}
public NoStrFireWaterWelder smokeTag(NoStrEventTag tag) {
smokeTags.add(Objects.requireNonNull(tag));
return this;
}
private List<NoStrEventTag> findByMeta(NoStrEventTagMeta meta) {
List<NoStrEventTag> result = new ArrayList<>();
for (NoStrEventTag tag : smokeTags) {
if (tag.getMeta().getQName().equals(meta.getQName())) {
result.add(tag);
}
}
return result;
}
private void waterFishNet(NoStrEventKind kind) {
// TODO: here ? and on which kinds ALL ?
if (NoStrImplEventKind.TEXT_NOTE.equals(kind)) {
if (findByMeta(NoStrImplEventTag.CLIENT).isEmpty()) {
smokeTags.add(new NoStrTagClient("No2All", Optional.empty()));
}
}
// validate per kind minimal required tags here ?
}
public NoStrEvent water(NoStrEventKind kind, String content) {
waterFishNet(kind);
Instant wave = Instant.now();
NoStrEventPayload payload = new NoStrEventPayload(identity.getPublicKey(), wave, kind, smokeTags, content);
return NoStrEventSignature.sign(payload, identity.getPrivateKey());
}
public NoStrEvent water(NoStrEventKind kind) {
return water(kind, "");
}
public NoStrEvent water(NoStrEventKind kind, String content, List<NoStrEventTag> tags) {
this.smokeTags.addAll(tags);
return water(kind, content);
}
}

View file

@ -0,0 +1,22 @@
package love.distributedrebirth.no2all.nostr.model;
import java.util.Objects;
public final class NoStrIdentity {
private final NoStrIdentityPrivateKey privateKey;
private final NoStrIdentityPublicKey publicKey;
public NoStrIdentity(NoStrIdentityPrivateKey privateKey) {
this.privateKey = Objects.requireNonNull(privateKey);
this.publicKey = NoStrIdentityPublicKey.of(privateKey);
}
public NoStrIdentityPrivateKey getPrivateKey() {
return privateKey;
}
public NoStrIdentityPublicKey getPublicKey() {
return publicKey;
}
}

View file

@ -0,0 +1,25 @@
package love.distributedrebirth.no2all.nostr.model;
import org.x4o.xml.o4o.octo.OctoBitFormat;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplBinHexAdapter;
import love.distributedrebirth.no2all.nostr.trust.OctoTrust;
import love.distributedrebirth.no2all.nostr.trust.OctoTrustException;
public final class NoStrIdentityPrivateKey extends NoStrImplBinHexAdapter {
public NoStrIdentityPrivateKey(byte[] keyBytes) {
super(keyBytes);
if (keyBytes.length != OctoTrust.KEY_LENGTH) {
throw new OctoTrustException("Key length is not: " + OctoTrust.KEY_LENGTH);
}
}
public static NoStrIdentityPrivateKey ofRandom() {
return new NoStrIdentityPrivateKey(OctoTrust.generateSecretKey());
}
public static NoStrIdentityPrivateKey ofHex(String keyHex) {
return new NoStrIdentityPrivateKey(OctoBitFormat.HEX.toBytes(keyHex));
}
}

View file

@ -0,0 +1,26 @@
package love.distributedrebirth.no2all.nostr.model;
import org.x4o.xml.o4o.octo.OctoBitFormat;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplBinHexAdapter;
import love.distributedrebirth.no2all.nostr.trust.OctoTrust;
import love.distributedrebirth.no2all.nostr.trust.OctoTrustException;
import love.distributedrebirth.no2all.nostr.trust.OctoTrustSchnorr;
public final class NoStrIdentityPublicKey extends NoStrImplBinHexAdapter {
public NoStrIdentityPublicKey(byte[] keyBytes) {
super(keyBytes);
if (keyBytes.length != OctoTrust.KEY_LENGTH) {
throw new OctoTrustException("Key length is not: " + OctoTrust.KEY_LENGTH);
}
}
public static NoStrIdentityPublicKey ofHex(String keyHex) {
return new NoStrIdentityPublicKey(OctoBitFormat.HEX.toBytes(keyHex));
}
public static NoStrIdentityPublicKey of(NoStrIdentityPrivateKey privateKey) {
return new NoStrIdentityPublicKey(OctoTrustSchnorr.extractPublicKey(privateKey.getBytes()));
}
}

View file

@ -0,0 +1,77 @@
package love.distributedrebirth.no2all.nostr.model;
import java.util.List;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplChuch;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public final class NoStrKindValue {
private final int kind;
private final int kindStopRange;
public NoStrKindValue(int kind) {
this(kind, -1);
}
public NoStrKindValue(int kind, int kindStopRange) {
this.kind = kind;
this.kindStopRange = kindStopRange;
}
public int getKind() {
return kind;
}
public int getKindStopRange() {
return kindStopRange;
}
public boolean isRange() {
return kindStopRange != -1;
}
public static void readArrayKinds(JsonObject json, NoStrImplQName jsonName, List<NoStrKindValue> data) {
readArrayKinds(json, jsonName.getQName(), data);
}
public static void readArrayKinds(JsonObject json, String jsonName, List<NoStrKindValue> data) {
if (!json.containsKey(jsonName)) {
return;
}
JsonArray values = json.getJsonArray(jsonName);
for (int i = 0; i < values.size(); i++) {
JsonValue value = values.get(i);
if (JsonValue.ValueType.ARRAY.equals(value.getValueType())) {
JsonArray arr = value.asJsonArray();
int v1 = arr.getInt(0);
int v2 = arr.getInt(1);
data.add(new NoStrKindValue(v1, v2));
} else {
data.add(new NoStrKindValue(values.getInt(i)));
}
}
}
public static void writeArrayKinds(JsonObjectBuilder json, NoStrImplQName jsonName, List<NoStrKindValue> data) {
writeArrayKinds(json, jsonName.getQName(), data);
}
public static void writeArrayKinds(JsonObjectBuilder json, String jsonName, List<NoStrKindValue> data) {
NoStrImplChuch.writeArray(json, jsonName, data, (r, v) -> {
if (v.isRange()) {
r.add(Json.createArrayBuilder()
.add(v.getKind())
.add(v.getKindStopRange())
.build());
} else {
r.add(v.getKind());
}
});
}
}

View file

@ -0,0 +1,121 @@
package love.distributedrebirth.no2all.nostr.model;
import java.util.HashMap;
import java.util.Map;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public final class NoStrProfileMetaData implements NoStrGospel {
private final Map<String, String> fields = new HashMap<>();
public NoStrProfileMetaData() {
}
public NoStrProfileMetaData(JsonObject value) {
for (String fieldName : value.keySet()) {
JsonValue fieldValue = value.get(fieldName);
if (fieldValue instanceof JsonString) {
fields.put(fieldName, ((JsonString)fieldValue).getString());
}
}
}
@Override
public JsonValue toBible() {
return Json.createObjectBuilder(fields).build();
}
private enum QName implements NoStrImplQName {
NAME,
DISPLAY_NAME,
ABOUT,
WEBSITE,
PICTURE,
BANNER,
NIP05,
LUD16
;
private final String jsonQName;
private QName() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
}
public String getName() {
return fields.get(QName.NAME.getQName());
}
public void setName(String name) {
this.fields.put(QName.NAME.getQName(), name);
}
public String getDisplayName() {
return fields.get(QName.DISPLAY_NAME.getQName());
}
public void setDisplayName(String displayName) {
this.fields.put(QName.DISPLAY_NAME.getQName(), displayName);
}
public String getAbout() {
return fields.get(QName.ABOUT.getQName());
}
public void setAbout(String about) {
this.fields.put(QName.ABOUT.getQName(), about);
}
public String getWebsite() {
return fields.get(QName.WEBSITE.getQName());
}
public void setWebsite(String website) {
this.fields.put(QName.WEBSITE.getQName(), website);
}
public String getPicture() {
return fields.get(QName.PICTURE.getQName());
}
public void setPicture(String picture) {
this.fields.put(QName.PICTURE.getQName(), picture);
}
public String getBanner() {
return fields.get(QName.BANNER.getQName());
}
public void setBanner(String banner) {
this.fields.put(QName.BANNER.getQName(), banner);
}
public String getNip05() {
return fields.get(QName.NIP05.getQName());
}
public void setNip05(String nip05) {
this.fields.put(QName.NIP05.getQName(), nip05);
}
public String getLud16() {
return fields.get(QName.LUD16.getQName());
}
public void setLud16(String lud16) {
this.fields.put(QName.LUD16.getQName(), lud16);
}
}

View file

@ -0,0 +1,250 @@
package love.distributedrebirth.no2all.nostr.model;
import java.util.ArrayList;
import java.util.List;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplChuch;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public final class NoStrRelayInfo implements NoStrGospel {
private String id;
private String name;
private String description;
private String publicKey;
private String contact;
private final List<Integer> supportedNips = new ArrayList<>();
private String software;
private String version;
private NoStrRelayInfoLimitation limitation;
private final List<NoStrRelayInfoRetention> retentions = new ArrayList<>();
private final List<String> relayCountries = new ArrayList<>();
private final List<String> languageTags = new ArrayList<>();
private final List<String> tags = new ArrayList<>();
private String postingPolicy;
private String paymentUrl;
private final List<NoStrRelayInfoPayment> feesAdmission = new ArrayList<>();
private final List<NoStrRelayInfoPayment> feesSubscription = new ArrayList<>();
private final List<NoStrRelayInfoPayment> feesPublication = new ArrayList<>();
public NoStrRelayInfo() {
}
public NoStrRelayInfo(JsonObject json) {
id = NoStrImplChuch.readString(json, QName.ID);
name = NoStrImplChuch.readString(json, QName.NAME);
description = NoStrImplChuch.readString(json, QName.DESCRIPTION);
publicKey = NoStrImplChuch.readString(json, QName.PUBKEY);
contact = NoStrImplChuch.readString(json, QName.CONTACT);
if (json.containsKey(QName.SUPPORTED_NIPS.getQName())) {
JsonArray values = json.getJsonArray(QName.SUPPORTED_NIPS.getQName());
for (int i = 0; i < values.size(); i++) {
supportedNips.add(values.getInt(i));
}
}
software = NoStrImplChuch.readString(json, QName.SOFTWARE);
version = NoStrImplChuch.readString(json, QName.VERSION);
JsonValue limitationJson = json.get(QName.LIMITATION.getQName());
if (limitationJson != null && JsonValue.ValueType.OBJECT.equals(limitationJson.getValueType())) {
limitation = new NoStrRelayInfoLimitation(limitationJson.asJsonObject());
}
NoStrImplChuch.readArray(json, QName.RETENTION, v -> retentions.add(new NoStrRelayInfoRetention(v.asJsonObject())));
NoStrImplChuch.readArrayString(json, QName.RELAY_COUNTRIES, relayCountries);
NoStrImplChuch.readArrayString(json, QName.LANGUAGE_TAGS, languageTags);
NoStrImplChuch.readArrayString(json, QName.TAGS, tags);
postingPolicy = NoStrImplChuch.readString(json, QName.POSTING_POLICY);
paymentUrl = NoStrImplChuch.readString(json, QName.PAYMENT_URL);
JsonValue feesJson = json.get(QName.FEES.getQName());
if (feesJson != null && JsonValue.ValueType.OBJECT.equals(feesJson.getValueType())) {
JsonObject feesObject = feesJson.asJsonObject();
NoStrImplChuch.readArray(feesObject, QName.ADMISSION, v -> feesAdmission.add(new NoStrRelayInfoPayment(v.asJsonObject())));
NoStrImplChuch.readArray(feesObject, QName.SUBSCRIPTION, v -> feesSubscription.add(new NoStrRelayInfoPayment(v.asJsonObject())));
NoStrImplChuch.readArray(feesObject, QName.PUBLICATION, v -> feesPublication.add(new NoStrRelayInfoPayment(v.asJsonObject())));
}
}
@Override
public JsonValue toBible() {
JsonObjectBuilder result = Json.createObjectBuilder();
NoStrImplChuch.writeString(result, QName.ID, id);
NoStrImplChuch.writeString(result, QName.NAME, name);
NoStrImplChuch.writeString(result, QName.DESCRIPTION, description);
NoStrImplChuch.writeString(result, QName.PUBKEY, publicKey);
NoStrImplChuch.writeString(result, QName.CONTACT, contact);
NoStrImplChuch.writeArray(result, QName.SUPPORTED_NIPS, supportedNips, (r, v) -> r.add(v));
NoStrImplChuch.writeString(result, QName.SOFTWARE, software);
NoStrImplChuch.writeString(result, QName.VERSION, version);
if (limitation != null) {
result.add(QName.LIMITATION.getQName(), limitation.toBible());
}
NoStrImplChuch.writeArrayWriter(result, QName.RETENTION, retentions);
NoStrImplChuch.writeArrayString(result, QName.RELAY_COUNTRIES, relayCountries);
NoStrImplChuch.writeArrayString(result, QName.LANGUAGE_TAGS, languageTags);
NoStrImplChuch.writeArrayString(result, QName.TAGS, tags);
NoStrImplChuch.writeString(result, QName.POSTING_POLICY, postingPolicy);
NoStrImplChuch.writeString(result, QName.PAYMENT_URL, paymentUrl);
JsonObjectBuilder feesObject = Json.createObjectBuilder();
NoStrImplChuch.writeArrayWriter(feesObject, QName.ADMISSION, feesAdmission);
NoStrImplChuch.writeArrayWriter(feesObject, QName.SUBSCRIPTION, feesSubscription);
NoStrImplChuch.writeArrayWriter(feesObject, QName.PUBLICATION, feesPublication);
result.add(QName.FEES.getQName(), feesObject);
return result.build();
}
private enum QName implements NoStrImplQName {
ID,
NAME,
DESCRIPTION,
PUBKEY,
CONTACT,
SUPPORTED_NIPS,
SOFTWARE,
VERSION,
LIMITATION,
RETENTION,
RELAY_COUNTRIES,
LANGUAGE_TAGS,
TAGS,
POSTING_POLICY,
PAYMENT_URL,
ADMISSION,
SUBSCRIPTION,
PUBLICATION,
FEES,
;
private final String jsonQName;
private QName() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPublicKey() {
return publicKey;
}
public void setPublicKey(String publicKey) {
this.publicKey = publicKey;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public String getSoftware() {
return software;
}
public void setSoftware(String software) {
this.software = software;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public NoStrRelayInfoLimitation getLimitation() {
return limitation;
}
public void setLimitation(NoStrRelayInfoLimitation limitation) {
this.limitation = limitation;
}
public String getPostingPolicy() {
return postingPolicy;
}
public void setPostingPolicy(String postingPolicy) {
this.postingPolicy = postingPolicy;
}
public String getPaymentUrl() {
return paymentUrl;
}
public void setPaymentUrl(String paymentUrl) {
this.paymentUrl = paymentUrl;
}
public List<Integer> getSupportedNips() {
return supportedNips;
}
public List<NoStrRelayInfoRetention> getRetentions() {
return retentions;
}
public List<String> getRelayCountries() {
return relayCountries;
}
public List<String> getLanguageTags() {
return languageTags;
}
public List<String> getTags() {
return tags;
}
public List<NoStrRelayInfoPayment> getFeesAdmission() {
return feesAdmission;
}
public List<NoStrRelayInfoPayment> getFeesSubscription() {
return feesSubscription;
}
public List<NoStrRelayInfoPayment> getFeesPublication() {
return feesPublication;
}
}

View file

@ -0,0 +1,173 @@
package love.distributedrebirth.no2all.nostr.model;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplChuch;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public final class NoStrRelayInfoLimitation implements NoStrGospel {
private Integer maxMessageLength;
private Integer maxSubscriptions;
private Integer maxFilters;
private Integer maxLimit;
private Integer maxSubIdLength;
private Integer minPrefix;
private Integer maxEventTags;
private Integer maxContentLength;
private Integer minPowDifficulty;
private Boolean authRequired;
private Boolean paymentRequired;
public NoStrRelayInfoLimitation() {
}
public NoStrRelayInfoLimitation(JsonObject json) {
maxMessageLength = NoStrImplChuch.readInteger(json, QName.MAX_MESSAGE_LENGTH);
maxSubscriptions = NoStrImplChuch.readInteger(json, QName.MAX_SUBSCRIPTIONS);
maxFilters = NoStrImplChuch.readInteger(json, QName.MAX_FILTERS);
maxLimit = NoStrImplChuch.readInteger(json, QName.MAX_LIMIT);
maxSubIdLength = NoStrImplChuch.readInteger(json, QName.MAX_SUBID_LENGTH);
minPrefix = NoStrImplChuch.readInteger(json, QName.MIN_PREFIX);
maxEventTags = NoStrImplChuch.readInteger(json, QName.MAX_EVENT_TAGS);
maxContentLength = NoStrImplChuch.readInteger(json, QName.MAX_CONTENT_LENGTH);
minPowDifficulty = NoStrImplChuch.readInteger(json, QName.MIN_POW_DIFFICULTY);
authRequired = NoStrImplChuch.readBoolean(json, QName.AUTH_REQUIRED);
paymentRequired = NoStrImplChuch.readBoolean(json, QName.PAYMENT_REQUIRED);
}
@Override
public JsonValue toBible() {
JsonObjectBuilder result = Json.createObjectBuilder();
NoStrImplChuch.writeInteger(result, QName.MAX_MESSAGE_LENGTH, maxMessageLength);
NoStrImplChuch.writeInteger(result, QName.MAX_SUBSCRIPTIONS, maxSubscriptions);
NoStrImplChuch.writeInteger(result, QName.MAX_FILTERS, maxFilters);
NoStrImplChuch.writeInteger(result, QName.MAX_LIMIT, maxLimit);
NoStrImplChuch.writeInteger(result, QName.MAX_SUBID_LENGTH, maxSubIdLength);
NoStrImplChuch.writeInteger(result, QName.MIN_PREFIX, minPrefix);
NoStrImplChuch.writeInteger(result, QName.MAX_EVENT_TAGS, maxEventTags);
NoStrImplChuch.writeInteger(result, QName.MAX_CONTENT_LENGTH, maxContentLength);
NoStrImplChuch.writeInteger(result, QName.MIN_POW_DIFFICULTY, minPowDifficulty);
NoStrImplChuch.writeBoolean(result, QName.AUTH_REQUIRED, authRequired);
NoStrImplChuch.writeBoolean(result, QName.PAYMENT_REQUIRED, paymentRequired);
return result.build();
}
private enum QName implements NoStrImplQName {
MAX_MESSAGE_LENGTH,
MAX_SUBSCRIPTIONS,
MAX_FILTERS,
MAX_LIMIT,
MAX_SUBID_LENGTH,
MIN_PREFIX,
MAX_EVENT_TAGS,
MAX_CONTENT_LENGTH,
MIN_POW_DIFFICULTY,
AUTH_REQUIRED,
PAYMENT_REQUIRED,
;
private final String jsonQName;
private QName() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
}
public Integer getMaxMessageLength() {
return maxMessageLength;
}
public void setMaxMessageLength(Integer maxMessageLength) {
this.maxMessageLength = maxMessageLength;
}
public Integer getMaxSubscriptions() {
return maxSubscriptions;
}
public void setMaxSubscriptions(Integer maxSubscriptions) {
this.maxSubscriptions = maxSubscriptions;
}
public Integer getMaxFilters() {
return maxFilters;
}
public void setMaxFilters(Integer maxFilters) {
this.maxFilters = maxFilters;
}
public Integer getMaxLimit() {
return maxLimit;
}
public void setMaxLimit(Integer maxLimit) {
this.maxLimit = maxLimit;
}
public Integer getMaxSubIdLength() {
return maxSubIdLength;
}
public void setMaxSubIdLength(Integer maxSubIdLength) {
this.maxSubIdLength = maxSubIdLength;
}
public Integer getMinPrefix() {
return minPrefix;
}
public void setMinPrefix(Integer minPrefix) {
this.minPrefix = minPrefix;
}
public Integer getMaxEventTags() {
return maxEventTags;
}
public void setMaxEventTags(Integer maxEventTags) {
this.maxEventTags = maxEventTags;
}
public Integer getMaxContentLength() {
return maxContentLength;
}
public void setMaxContentLength(Integer maxContentLength) {
this.maxContentLength = maxContentLength;
}
public Integer getMinPowDifficulty() {
return minPowDifficulty;
}
public void setMinPowDifficulty(Integer minPowDifficulty) {
this.minPowDifficulty = minPowDifficulty;
}
public Boolean getAuthRequired() {
return authRequired;
}
public void setAuthRequired(Boolean authRequired) {
this.authRequired = authRequired;
}
public Boolean getPaymentRequired() {
return paymentRequired;
}
public void setPaymentRequired(Boolean paymentRequired) {
this.paymentRequired = paymentRequired;
}
}

View file

@ -0,0 +1,78 @@
package love.distributedrebirth.no2all.nostr.model;
import java.util.ArrayList;
import java.util.List;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplChuch;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public final class NoStrRelayInfoPayment implements NoStrGospel {
private final List<NoStrKindValue> kinds = new ArrayList<>();
private Integer amount;
private String unit;
public NoStrRelayInfoPayment(int amount, String unit) {
this.amount = amount;
this.unit = unit;
}
public NoStrRelayInfoPayment(JsonObject json) {
NoStrKindValue.readArrayKinds(json, QName.KINDS, kinds);
amount = NoStrImplChuch.readInteger(json, QName.AMOUNT);
unit = NoStrImplChuch.readString(json, QName.UNIT);
}
@Override
public JsonValue toBible() {
JsonObjectBuilder result = Json.createObjectBuilder();
NoStrKindValue.writeArrayKinds(result, QName.KINDS, kinds);
NoStrImplChuch.writeInteger(result, QName.AMOUNT, amount);
NoStrImplChuch.writeString(result, QName.UNIT, unit);
return result.build();
}
private enum QName implements NoStrImplQName {
KINDS,
AMOUNT,
UNIT,
;
private final String jsonQName;
private QName() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
}
public List<NoStrKindValue> getKinds() {
return kinds;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
}

View file

@ -0,0 +1,81 @@
package love.distributedrebirth.no2all.nostr.model;
import java.util.ArrayList;
import java.util.List;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplChuch;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public final class NoStrRelayInfoRetention implements NoStrGospel {
private final List<NoStrKindValue> kinds = new ArrayList<>();
private Integer time;
private Integer count;
public NoStrRelayInfoRetention() {
}
public NoStrRelayInfoRetention(Integer time, Integer count) {
this.time = time;
this.count = count;
}
public NoStrRelayInfoRetention(JsonObject json) {
NoStrKindValue.readArrayKinds(json, QName.KINDS, kinds);
time = NoStrImplChuch.readInteger(json, QName.TIME);
count = NoStrImplChuch.readInteger(json, QName.COUNT);
}
@Override
public JsonValue toBible() {
JsonObjectBuilder result = Json.createObjectBuilder();
NoStrKindValue.writeArrayKinds(result, QName.KINDS, kinds);
NoStrImplChuch.writeInteger(result, QName.TIME, time);
NoStrImplChuch.writeInteger(result, QName.COUNT, count);
return result.build();
}
private enum QName implements NoStrImplQName {
KINDS,
TIME,
COUNT,
;
private final String jsonQName;
private QName() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
}
public List<NoStrKindValue> getKinds() {
return kinds;
}
public Integer getTime() {
return time;
}
public void setTime(Integer time) {
this.time = time;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}

View file

@ -0,0 +1,133 @@
package love.distributedrebirth.no2all.nostr.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagMeta;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplChuch;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public class NoStrSubscriptionFilter implements NoStrGospel {
private final static String TAG_FILTER_PREFIX = "#";
private final List<String> ids = new ArrayList<>();
private final List<String> authors = new ArrayList<>();
private final List<NoStrKindValue> kinds = new ArrayList<>();
private final Map<String, NoStrSubscriptionFilterTag> tags = new HashMap<>();
private Integer since;
private Integer until;
private Integer limit;
private enum QName implements NoStrImplQName {
IDS, AUTHORS, KINDS, SINCE, UNTIL, LIMIT;
private final String jsonQName;
private QName() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
}
public NoStrSubscriptionFilter() {
}
public NoStrSubscriptionFilter(JsonObject json) {
NoStrImplChuch.readArrayString(json, QName.IDS, ids);
NoStrImplChuch.readArrayString(json, QName.AUTHORS, authors);
NoStrKindValue.readArrayKinds(json, QName.KINDS, kinds);
for (String jsonName : json.keySet()) {
if (!jsonName.startsWith(TAG_FILTER_PREFIX)) {
continue;
}
String jsonNameKey = jsonName.substring(0, 1);
if (tags.containsKey(jsonNameKey)) {
continue;
}
JsonValue arrayJson = json.get(jsonNameKey);
if (!JsonValue.ValueType.ARRAY.equals(arrayJson.getValueType())) {
continue;
}
Stream<JsonValue> tagFilterValues = arrayJson.asJsonArray().stream();
List<String> tagFilters = tagFilterValues.map(v -> ((JsonString)v).getString()).collect(Collectors.toList());
NoStrEventTagMeta eventTag = NoStrEventTagMeta.valueOf(jsonNameKey);
tags.put(jsonNameKey, new NoStrSubscriptionFilterTag(eventTag, tagFilters));
}
since = NoStrImplChuch.readInteger(json, QName.SINCE);
until = NoStrImplChuch.readInteger(json, QName.UNTIL);
limit = NoStrImplChuch.readInteger(json, QName.LIMIT);
}
@Override
public JsonValue toBible() {
JsonObjectBuilder result = Json.createObjectBuilder();
NoStrImplChuch.writeArrayString(result, QName.IDS, ids);
NoStrImplChuch.writeArrayString(result, QName.AUTHORS, authors);
NoStrKindValue.writeArrayKinds(result, QName.KINDS, kinds);
for (String tagKey : tags.keySet()) {
if (tagKey.length() != 1) {
continue;
}
NoStrSubscriptionFilterTag tag = tags.get(tagKey);
result.add(TAG_FILTER_PREFIX + tagKey, Json.createArrayBuilder(tag.getKeywords()));
}
NoStrImplChuch.writeInteger(result, QName.SINCE, since);
NoStrImplChuch.writeInteger(result, QName.UNTIL, until);
NoStrImplChuch.writeInteger(result, QName.LIMIT, limit);
return result.build();
}
public Integer getSince() {
return since;
}
public void setSince(Integer since) {
this.since = since;
}
public Integer getUntil() {
return until;
}
public void setUntil(Integer until) {
this.until = until;
}
public Integer getLimit() {
return limit;
}
public void setLimit(Integer limit) {
this.limit = limit;
}
public List<String> getIds() {
return ids;
}
public List<String> getAuthors() {
return authors;
}
public List<NoStrKindValue> getKinds() {
return kinds;
}
public Map<String, NoStrSubscriptionFilterTag> getTags() {
return tags;
}
}

View file

@ -0,0 +1,25 @@
package love.distributedrebirth.no2all.nostr.model;
import java.util.ArrayList;
import java.util.List;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagMeta;
public final class NoStrSubscriptionFilterTag {
private final NoStrEventTagMeta eventTag;
private final List<String> keywords = new ArrayList<>();
public NoStrSubscriptionFilterTag(NoStrEventTagMeta eventTag, List<String> keywords) {
this.eventTag = eventTag;
this.keywords.addAll(keywords);
}
public NoStrEventTagMeta getEventTag() {
return eventTag;
}
public List<String> getKeywords() {
return keywords;
}
}

View file

@ -0,0 +1,100 @@
package love.distributedrebirth.no2all.nostr.model.event;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public final class NoStrEvent implements NoStrGospel {
private final NoStrEventId id;
private final NoStrEventPayload payload;
private final NoStrEventSignature signature;
private enum QName implements NoStrImplQName {
ID, PUBKEY, CREATED_AT, KIND, TAGS, CONTENT, SIG;
private final String jsonQName;
private QName() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
}
public NoStrEvent(NoStrEventId id, NoStrEventPayload payload, NoStrEventSignature signature) {
this.id = Objects.requireNonNull(id);
this.payload = Objects.requireNonNull(payload);
this.signature = Objects.requireNonNull(signature);
}
public NoStrEvent(JsonObject event) {
List<NoStrEventTag> eventTags = new ArrayList<>();
JsonArray jsonTags = event.getJsonArray(QName.TAGS.getQName());
for (JsonValue jsonTag : jsonTags) {
Iterator<JsonValue> i = jsonTag.asJsonArray().iterator();
if (!i.hasNext()) {
throw new IllegalArgumentException("Empty tag");
}
String tagStr = ((JsonString)i.next()).getString();
NoStrEventTagMeta tagMeta = NoStrEventTagMeta.valueOf(tagStr);
List<String> args = new ArrayList<>();
while (i.hasNext()) {
args.add(((JsonString)i.next()).getString());
}
eventTags.add(NoStrEventTag.valueOf(tagMeta, args.toArray(new String[] {})));
}
long createdAtLong = event.getJsonNumber(QName.CREATED_AT.getQName()).longValue();
int kindNumber = event.getInt(QName.KIND.getQName());
String idStr = event.getString(QName.ID.getQName());
String signatureStr = event.getString(QName.SIG.getQName());
String pubkeyStr = event.getString(QName.PUBKEY.getQName());
String content = event.getString(QName.CONTENT.getQName());
NoStrIdentityPublicKey pubkey = NoStrIdentityPublicKey.ofHex(pubkeyStr);
Instant createdAt = Instant.ofEpochSecond(createdAtLong);
NoStrEventKind kind = NoStrEventKind.valueOf(kindNumber);
this.id = NoStrEventId.ofHex(idStr);
this.payload = new NoStrEventPayload(pubkey, createdAt, kind, eventTags, content);
this.signature = NoStrEventSignature.ofHex(signatureStr);
}
@Override
public JsonValue toBible() {
return Json.createObjectBuilder()
.add(QName.ID.getQName(), id.getHex())
.add(QName.PUBKEY.getQName(), payload.getPublicKey().getHex())
.add(QName.CREATED_AT.getQName(), payload.getCreatedAt().getEpochSecond())
.add(QName.KIND.getQName(), payload.getKind().getNumber())
.add(QName.TAGS.getQName(), NoStrEventTag.toJsonArray(payload.getTags()))
.add(QName.CONTENT.getQName(), payload.getContent())
.add(QName.SIG.getQName(), signature.getHex())
.build();
}
public NoStrEventId getId() {
return id;
}
public NoStrEventPayload getPayload() {
return payload;
}
public NoStrEventSignature getSignature() {
return signature;
}
}

View file

@ -0,0 +1,16 @@
package love.distributedrebirth.no2all.nostr.model.event;
import org.x4o.xml.o4o.octo.OctoBitFormat;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplBinHexAdapter;
public final class NoStrEventId extends NoStrImplBinHexAdapter {
public NoStrEventId(byte[] valueBytes) {
super(valueBytes);
}
public static NoStrEventId ofHex(String valueHex) {
return new NoStrEventId(OctoBitFormat.HEX.toBytes(valueHex));
}
}

View file

@ -0,0 +1,22 @@
package love.distributedrebirth.no2all.nostr.model.event;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventKind;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplPossibility;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQFlag;
public interface NoStrEventKind extends NoStrImplQFlag {
int getNumber();
NoStrImplPossibility getNip();
NoStrEventKindRange getRange();
static NoStrEventKind valueOf(int number) {
if (NoStrImplEventKind.valueOfKindValid(number)) {
return NoStrImplEventKind.valueOfKind(number);
} else {
return new NoStrEventKindCustom(number);
}
}
}

View file

@ -0,0 +1,37 @@
package love.distributedrebirth.no2all.nostr.model.event;
import love.distributedrebirth.no2all.nostr.nip.NoStrImpl;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventKindRange;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplPossibility;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQFlag;
public final class NoStrEventKindCustom implements NoStrEventKind {
private final int number;
private final NoStrEventKindRange range;
public NoStrEventKindCustom(int number) {
this.number = number;
this.range = NoStrImplEventKindRange.valueOfKind(number);
}
@Override
public int getNumber() {
return number;
}
@Override
public String getQFlag() {
return NoStrImplQFlag.CUSTOM_INDICATOR;
}
@Override
public NoStrImplPossibility getNip() {
return NoStrImpl.NIP_0_UNKNOWN;
}
@Override
public NoStrEventKindRange getRange() {
return range;
}
}

View file

@ -0,0 +1,12 @@
package love.distributedrebirth.no2all.nostr.model.event;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQFlag;
public interface NoStrEventKindRange extends NoStrImplQFlag {
int getNumberStart();
int getNumberstop();
boolean isReplaceable(int number);
}

View file

@ -0,0 +1,80 @@
package love.distributedrebirth.no2all.nostr.model.event;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
public final class NoStrEventPayload {
private final NoStrIdentityPublicKey publicKey;
private Instant createdAt;
private final NoStrEventKind kind;
private final List<NoStrEventTag> tags;
private final String content;
public NoStrEventPayload(NoStrIdentityPublicKey publicKey, Instant createdAt, NoStrEventKind kind, List<NoStrEventTag> tags,
String content) {
this.publicKey = Objects.requireNonNull(publicKey);
this.createdAt = Objects.requireNonNull(createdAt);
this.kind = Objects.requireNonNull(kind);
this.tags = Objects.requireNonNull(tags);
this.content = Objects.requireNonNull(content);
}
public NoStrIdentityPublicKey getPublicKey() {
return publicKey;
}
public Instant getCreatedAt() {
return createdAt;
}
public NoStrEventKind getKind() {
return kind;
}
public List<NoStrEventTag> getTags() {
return tags;
}
public String getContent() {
return content;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = Objects.requireNonNull(createdAt);
}
public List<NoStrEventTag> findByQName(String tagQName) {
List<NoStrEventTag> result = new ArrayList<>();
for (int i=0; i < tags.size(); i++) {
NoStrEventTag tag = tags.get(i);
if (tag.getMeta().getQName().equals(tagQName)) {
result.add(tag);
}
}
return result;
}
public List<NoStrEventTag> findByQName(NoStrEventTagMeta tagQName) {
return findByQName(tagQName.getQName());
}
public Optional<NoStrEventTag> findFirstByQName(String tagQName) {
for (int i=0; i < tags.size(); i++) {
NoStrEventTag tag = tags.get(i);
if (tag.getMeta().getQName().equals(tagQName)) {
return Optional.of(tag);
}
}
return Optional.empty();
}
public Optional<NoStrEventTag> findFirstByQName(NoStrEventTagMeta tagQName) {
return findFirstByQName(tagQName.getQName());
}
}

View file

@ -0,0 +1,69 @@
package love.distributedrebirth.no2all.nostr.model.event;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import org.x4o.xml.o4o.octo.OctoBitFormat;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonWriter;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPrivateKey;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplBinHexAdapter;
import love.distributedrebirth.no2all.nostr.trust.OctoTrust;
import love.distributedrebirth.no2all.nostr.trust.OctoTrustHash;
import love.distributedrebirth.no2all.nostr.trust.OctoTrustSchnorr;
public final class NoStrEventSignature extends NoStrImplBinHexAdapter {
public NoStrEventSignature(byte[] valueBytes) {
super(valueBytes);
}
public static NoStrEventSignature ofHex(String valueHex) {
return new NoStrEventSignature(OctoBitFormat.HEX.toBytes(valueHex));
}
public static NoStrEvent sign(NoStrEventPayload payload, NoStrIdentityPrivateKey privateKey, byte[] eventId) {
byte[] signRandom = OctoTrust.createRandomByteArray(OctoTrust.KEY_LENGTH);
byte[] signHash = OctoTrustSchnorr.sign(eventId, privateKey.getBytes(), signRandom);
NoStrEventSignature signature = new NoStrEventSignature(signHash);
return new NoStrEvent(new NoStrEventId(eventId), payload, signature);
}
public static NoStrEvent sign(NoStrEventPayload payload, NoStrIdentityPrivateKey privateKey) {
return sign(payload, privateKey, generateEventId(payload));
}
public static boolean verify(NoStrEvent event) {
byte[] eventId = generateEventId(event.getPayload());
byte[] pubkey = event.getPayload().getPublicKey().getBytes();
byte[] sig = event.getSignature().getBytes();
boolean result = OctoTrustSchnorr.verify(eventId, pubkey, sig);
return result;
}
public static String generateEventIdJsonString(NoStrEventPayload payload) {
JsonArray eventAsJson = Json.createArrayBuilder()
.add(0)
.add(payload.getPublicKey().getHex())
.add(payload.getCreatedAt().getEpochSecond())
.add(payload.getKind().getNumber())
.add(NoStrEventTag.toJsonArray(payload.getTags()))
.add(payload.getContent())
.build();
StringWriter eventAsString = new StringWriter();
try (JsonWriter writer = Json.createWriter(eventAsString)) {
writer.write(eventAsJson);
}
return eventAsString.getBuffer().toString();
}
public static byte[] generateEventIdHash(String eventIdJsonString) {
return OctoTrustHash.sha256(eventIdJsonString.getBytes(StandardCharsets.UTF_8));
}
public static byte[] generateEventId(NoStrEventPayload payload) {
return generateEventIdHash(generateEventIdJsonString(payload));
}
}

View file

@ -0,0 +1,81 @@
package love.distributedrebirth.no2all.nostr.model.event;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTagArgument;
public interface NoStrEventTag extends NoStrGospel {
NoStrEventTagMeta getMeta();
String[] getMetaArguments();
default Optional<String> getMetaArgument(int idx) {
if (idx >= getMetaArguments().length || idx < 0) {
return Optional.empty();
}
return Optional.ofNullable(getMetaArguments()[idx]);
}
default Optional<String> getMetaArgument(NoStrImplEventTagArgument idx) {
return getMetaArgument(idx.ordinal());
}
default List<String> getMetaSafeArguments() {
List<String> result = new ArrayList<>();
int idxLastValue = 0;
String[] values = getMetaArguments();
for (int i = 0; i < values.length; i++) {
String str = values[i];
if (str == null) {
result.add(""); // optional
} else {
result.add(str);
idxLastValue = i;
}
}
if (idxLastValue < result.size()) {
result = result.subList(0, idxLastValue + 1);
}
return result;
}
@Override
default JsonValue toBible() {
return Json.createArrayBuilder()
.add(getMeta().getQName())
.addAll(Json.createArrayBuilder(getMetaSafeArguments()))
.build();
}
static JsonArray toJsonArray(List<NoStrEventTag> tags) {
return Json.createArrayBuilder(
tags.stream().map(v -> v.toBible()).collect(Collectors.toList())
).build();
}
static NoStrEventTag valueOfArgs(NoStrEventTagMeta meta, String... args) {
return valueOf(meta, args);
}
static NoStrEventTag valueOf(NoStrEventTagMeta meta, String[] args) {
Objects.requireNonNull(meta);
Objects.requireNonNull(args);
if (meta instanceof NoStrImplEventTag) {
NoStrImplEventTag metaTag = NoStrImplEventTag.class.cast(meta);
if (metaTag.getMapperToEventTag().isPresent()) {
return metaTag.getMapperToEventTag().get().apply(args);
}
}
return new NoStrEventTagCustom(meta, args);
}
}

View file

@ -0,0 +1,65 @@
package love.distributedrebirth.no2all.nostr.model.event;
import java.util.Objects;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTagArgument;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public class NoStrEventTagBase<T extends NoStrImplEventTagArgument> implements NoStrEventTag {
private final NoStrEventTagMeta meta;
private String[] args;
public NoStrEventTagBase(NoStrEventTagMeta meta) {
this(meta, new String[4]); // limit autoGrow to zero in 99% of tags
}
public NoStrEventTagBase(NoStrEventTagMeta meta, String[] args) {
this.meta = Objects.requireNonNull(meta);
this.args = Objects.requireNonNull(args);
}
@Override
public NoStrEventTagMeta getMeta() {
return meta;
}
@Override
public String[] getMetaArguments() {
return args;
}
private int autoGrow(int index) {
if (index < args.length) {
return index;
}
String[] result = new String[index];
System.arraycopy(args, 0, result, 0, args.length);
args = result;
return index;
}
// public Optional<String> getMetaArgument(T arg) {
// return NoStrEventTag.super.getMetaArgument(arg.ordinal());
// }
protected void setMetaArgumentStr(T arg, String value) {
int index = autoGrow(arg.ordinal());
args[index] = value;
}
protected void setMetaArgumentOptStr(T arg, Optional<String> value) {
if (value.isEmpty()) {
return;
}
setMetaArgumentStr(arg, value.get());
}
protected void setMetaArgumentOptQName(T arg, Optional<? extends NoStrImplQName> value) {
if (value.isEmpty()) {
return;
}
setMetaArgumentStr(arg, value.get().getQName());
}
}

View file

@ -0,0 +1,53 @@
package love.distributedrebirth.no2all.nostr.model.event;
import java.util.Objects;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public class NoStrEventTagBaseMono implements NoStrEventTag {
private final NoStrEventTagMeta meta;
private String[] args;
public NoStrEventTagBaseMono(NoStrEventTagMeta meta) {
this(meta, new String[1]);
}
public NoStrEventTagBaseMono(NoStrEventTagMeta meta, String[] args) {
this.meta = Objects.requireNonNull(meta);
this.args = Objects.requireNonNull(args);
}
@Override
public NoStrEventTagMeta getMeta() {
return meta;
}
@Override
public String[] getMetaArguments() {
return args;
}
public Optional<String> getMetaArgument() {
return NoStrEventTag.super.getMetaArgument(0);
}
protected void setMetaArgumentStr(String value) {
args[0] = value;
}
protected void setMetaArgumentOptStr(Optional<String> value) {
if (value.isEmpty()) {
return;
}
setMetaArgumentStr(value.get());
}
protected void setMetaArgumentOptQName(Optional<? extends NoStrImplQName> value) {
if (value.isEmpty()) {
return;
}
setMetaArgumentStr(value.get().getQName());
}
}

View file

@ -0,0 +1,24 @@
package love.distributedrebirth.no2all.nostr.model.event;
import java.util.Objects;
public final class NoStrEventTagCustom implements NoStrEventTag {
private final NoStrEventTagMeta meta;
private final String[] args;
public NoStrEventTagCustom(NoStrEventTagMeta meta, String[] args) {
this.meta = Objects.requireNonNull(meta);
this.args = Objects.requireNonNull(args);
}
@Override
public NoStrEventTagMeta getMeta() {
return meta;
}
@Override
public String[] getMetaArguments() {
return args;
}
}

View file

@ -0,0 +1,23 @@
package love.distributedrebirth.no2all.nostr.model.event;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplPossibility;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQFlag;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public interface NoStrEventTagMeta extends NoStrImplQName, NoStrImplQFlag {
boolean isQuariable();
boolean isSinglton();
NoStrImplPossibility[] getNips();
static NoStrEventTagMeta valueOf(String qName) {
if (NoStrImplEventTag.valueOfWireValid(qName)) {
return NoStrImplEventTag.valueOfWire(qName);
} else {
return new NoStrEventTagMetaCustom(qName);
}
}
}

View file

@ -0,0 +1,45 @@
package love.distributedrebirth.no2all.nostr.model.event;
import java.util.Objects;
import love.distributedrebirth.no2all.nostr.nip.NoStrImpl;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplPossibility;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQFlag;
public class NoStrEventTagMetaCustom implements NoStrEventTagMeta {
private static final NoStrImplPossibility[] UNKNOWN_NIPS = new NoStrImplPossibility[] { NoStrImpl.NIP_0_UNKNOWN };
private final String qName;
private final boolean quariable;
public NoStrEventTagMetaCustom(String qName) {
this.qName = Objects.requireNonNull(qName);
this.quariable = NoStrImplEventTag.isQuariable(qName);
}
@Override
public String getQName() {
return qName;
}
@Override
public String getQFlag() {
return NoStrImplQFlag.CUSTOM_INDICATOR;
}
@Override
public NoStrImplPossibility[] getNips() {
return UNKNOWN_NIPS;
}
@Override
public boolean isQuariable() {
return quariable;
}
@Override
public boolean isSinglton() {
return false;
}
}

View file

@ -0,0 +1,7 @@
package love.distributedrebirth.no2all.nostr.model.message;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
public interface NoStrMsgToClient extends NoStrGospel {
// marker
}

View file

@ -0,0 +1,34 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToClientAuth implements NoStrMsgToClient {
private final String challenge;
public NoStrMsgToClientAuth(String challenge) {
this.challenge = Objects.requireNonNull(challenge);
}
public NoStrMsgToClientAuth(JsonArray json) {
this.challenge = ((JsonString)json.get(1)).getString();
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.AUTH.getQName())
.add(challenge)
.build();
}
public String getChallenge() {
return challenge;
}
}

View file

@ -0,0 +1,43 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToClientCount implements NoStrMsgToClient {
private final String QNAME_COUNT = "count";
private final String subscriptionId;
private final int count;
public NoStrMsgToClientCount(String subscriptionId, int count) {
this.subscriptionId = Objects.requireNonNull(subscriptionId);
this.count = count;
}
public NoStrMsgToClientCount(JsonArray json) {
this.subscriptionId = ((JsonString)json.get(1)).getString();
this.count = json.get(2).asJsonObject().getInt(QNAME_COUNT);
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.COUNT.getQName())
.add(subscriptionId)
.add(Json.createObjectBuilder().add(QNAME_COUNT, count))
.build();
}
public String getSubscriptionId() {
return subscriptionId;
}
public int getCount() {
return count;
}
}

View file

@ -0,0 +1,34 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToClientEose implements NoStrMsgToClient {
private final String subscriptionId;
public NoStrMsgToClientEose(String subscriptionId) {
this.subscriptionId = Objects.requireNonNull(subscriptionId);
}
public NoStrMsgToClientEose(JsonArray json) {
this.subscriptionId = ((JsonString)json.get(1)).getString();
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.EOSE.getQName())
.add(subscriptionId)
.build();
}
public String getSubscriptionId() {
return subscriptionId;
}
}

View file

@ -0,0 +1,43 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEvent;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToClientEvent implements NoStrMsgToClient {
private final String subscriptionId;
private final NoStrEvent event;
public NoStrMsgToClientEvent(String subscriptionId, NoStrEvent event) {
this.subscriptionId = Objects.requireNonNull(subscriptionId);
this.event = Objects.requireNonNull(event);
}
public NoStrMsgToClientEvent(JsonArray json) {
this.subscriptionId = ((JsonString)json.get(1)).getString();
this.event = new NoStrEvent(json.get(2).asJsonObject());
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.EVENT.getQName())
.add(subscriptionId)
.add(event.toBible())
.build();
}
public String getSubscriptionId() {
return subscriptionId;
}
public NoStrEvent getEvent() {
return event;
}
}

View file

@ -0,0 +1,34 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToClientNotice implements NoStrMsgToClient {
private final String message;
public NoStrMsgToClientNotice(String message) {
this.message = Objects.requireNonNull(message);
}
public NoStrMsgToClientNotice(JsonArray json) {
this.message = ((JsonString)json.get(1)).getString();
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.NOTICE.getQName())
.add(message)
.build();
}
public String getMessage() {
return message;
}
}

View file

@ -0,0 +1,66 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventId;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageOkReason;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToClientOk implements NoStrMsgToClient {
private final NoStrEventId eventId;
private final boolean saved;
private final String message;
private final NoStrImplMessageOkReason reason;
public NoStrMsgToClientOk(NoStrEventId eventId, boolean saved, NoStrImplMessageOkReason reason, String message) {
this.eventId = Objects.requireNonNull(eventId);
this.saved = saved;
this.reason = Objects.requireNonNull(reason);
this.message = reason.getPrefix() + " " + message;
}
public NoStrMsgToClientOk(NoStrEventId eventId, boolean saved, String message) {
this.eventId = Objects.requireNonNull(eventId);
this.saved = saved;
this.message = Objects.requireNonNull(message);
this.reason = NoStrImplMessageOkReason.valueOfPrefix(message);
}
public NoStrMsgToClientOk(JsonArray json) {
this.eventId = NoStrEventId.ofHex(((JsonString)json.get(1)).getString());
this.saved = JsonValue.TRUE.equals(json.get(2));
this.message = ((JsonString)json.get(3)).getString();
this.reason = NoStrImplMessageOkReason.valueOfPrefix(message);
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.OK.getQName())
.add(eventId.getHex())
.add(saved)
.add(message)
.build();
}
public NoStrEventId getEventId() {
return eventId;
}
public boolean isSaved() {
return saved;
}
public String getMessage() {
return message;
}
public NoStrImplMessageOkReason getReason() {
return reason;
}
}

View file

@ -0,0 +1,7 @@
package love.distributedrebirth.no2all.nostr.model.message;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
public interface NoStrMsgToRelay extends NoStrGospel {
// marker
}

View file

@ -0,0 +1,34 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEvent;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToRelayAuth implements NoStrMsgToRelay {
private final NoStrEvent event;
public NoStrMsgToRelayAuth(NoStrEvent event) {
this.event = Objects.requireNonNull(event);
}
public NoStrMsgToRelayAuth(JsonArray json) {
this.event = new NoStrEvent(json.get(1).asJsonObject());
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.AUTH.getQName())
.add(event.toBible())
.build();
}
public NoStrEvent getEvent() {
return event;
}
}

View file

@ -0,0 +1,34 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToRelayClose implements NoStrMsgToRelay {
private final String subscriptionId;
public NoStrMsgToRelayClose(String subscriptionId) {
this.subscriptionId = Objects.requireNonNull(subscriptionId);
}
public NoStrMsgToRelayClose(JsonArray json) {
this.subscriptionId = ((JsonString)json.get(1)).getString();
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.CLOSE.getQName())
.add(subscriptionId)
.build();
}
public String getSubscriptionId() {
return subscriptionId;
}
}

View file

@ -0,0 +1,49 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.model.NoStrSubscriptionFilter;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToRelayCount implements NoStrMsgToRelay {
private final String subscriptionId;
private final List<NoStrSubscriptionFilter> filters = new ArrayList<>();
public NoStrMsgToRelayCount(String subscriptionId, NoStrSubscriptionFilter... filters) {
this.subscriptionId = Objects.requireNonNull(subscriptionId);
this.filters.addAll(Arrays.asList(filters));
}
public NoStrMsgToRelayCount(JsonArray json) {
this.subscriptionId = ((JsonString)json.get(1)).getString();
for (int i = 2; i < json.size(); i++) {
filters.add(new NoStrSubscriptionFilter(json.get(i).asJsonObject()));
}
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.COUNT.getQName())
.add(subscriptionId)
.addAll(Json.createArrayBuilder(filters.stream().map(v -> v.toBible()).collect(Collectors.toList())))
.build();
}
public String getSubscriptionId() {
return subscriptionId;
}
public List<NoStrSubscriptionFilter> getFilters() {
return filters;
}
}

View file

@ -0,0 +1,34 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.Objects;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEvent;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToRelayEvent implements NoStrMsgToRelay {
private final NoStrEvent event;
public NoStrMsgToRelayEvent(NoStrEvent event) {
this.event = Objects.requireNonNull(event);
}
public NoStrMsgToRelayEvent(JsonArray json) {
this.event = new NoStrEvent(json.get(1).asJsonObject());
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.EVENT.getQName())
.add(event.toBible())
.build();
}
public NoStrEvent getEvent() {
return event;
}
}

View file

@ -0,0 +1,49 @@
package love.distributedrebirth.no2all.nostr.model.message;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.model.NoStrSubscriptionFilter;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplMessageType;
public final class NoStrMsgToRelayReq implements NoStrMsgToRelay {
private final String subscriptionId;
private final List<NoStrSubscriptionFilter> filters = new ArrayList<>();
public NoStrMsgToRelayReq(String subscriptionId, NoStrSubscriptionFilter... filters) {
this.subscriptionId = Objects.requireNonNull(subscriptionId);
this.filters.addAll(Arrays.asList(filters));
}
public NoStrMsgToRelayReq(JsonArray json) {
this.subscriptionId = ((JsonString)json.get(1)).getString();
for (int i = 2; i < json.size(); i++) {
filters.add(new NoStrSubscriptionFilter(json.get(i).asJsonObject()));
}
}
@Override
public JsonValue toBible() {
return Json.createArrayBuilder()
.add(NoStrImplMessageType.REQ.getQName())
.add(subscriptionId)
.addAll(Json.createArrayBuilder(filters.stream().map(v -> v.toBible()).collect(Collectors.toList())))
.build();
}
public String getSubscriptionId() {
return subscriptionId;
}
public List<NoStrSubscriptionFilter> getFilters() {
return filters;
}
}

View file

@ -0,0 +1,32 @@
package love.distributedrebirth.no2all.nostr.model.share;
import java.util.Objects;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public abstract class NoStrShareB32LinkBare implements NoStrShareLink {
private final String shareLink;
private final byte[] bareValue;
public NoStrShareB32LinkBare(NoStrImplShareLink linkType, OctoBech32String link) {
this(linkType, OctoBech32.fromBech32(linkType.validate(link)).getData());
}
public NoStrShareB32LinkBare(NoStrImplShareLink linkType, byte[] bareValue) {
Objects.requireNonNull(bareValue);
this.shareLink = OctoBech32.toBech32(linkType.getPrefix(), bareValue).getValue();
this.bareValue = bareValue;
}
@Override
public final String toShareLink() {
return shareLink;
}
protected byte[] getBareValue() {
return bareValue;
}
}

View file

@ -0,0 +1,52 @@
package love.distributedrebirth.no2all.nostr.model.share;
import java.util.Optional;
import java.util.function.Consumer;
import org.x4o.xml.o4o.io.tlv.TLVChainOctoBit;
import org.x4o.xml.o4o.octo.OctoBitFormat;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareTLV;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32Bucket;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public abstract class NoStrShareB32LinkTLV implements NoStrShareLink {
private final NoStrShareBitChainTapeDeck tapeDeck;
private final String shareLink;
public NoStrShareB32LinkTLV(NoStrImplShareLink linkType, OctoBech32String link) {
OctoBech32Bucket shareB32 = OctoBech32.fromBech32(linkType.validate(link));
TLVChainOctoBit chain = new TLVChainOctoBit();
chain.dataReadArray(shareB32.getData());
this.tapeDeck = new NoStrShareBitChainTapeDeck(chain);
this.shareLink = createShareLink(chain, linkType);
}
public NoStrShareB32LinkTLV(NoStrImplShareLink linkType, Consumer<NoStrShareBitChainTapeStudio> tapeStudio) {
TLVChainOctoBit chain = new TLVChainOctoBit();
tapeStudio.accept(new NoStrShareBitChainTapeStudio(chain));
this.tapeDeck = new NoStrShareBitChainTapeDeck(chain);
this.shareLink = createShareLink(chain, linkType);
}
private static String createShareLink(TLVChainOctoBit chain, NoStrImplShareLink linkType) {
return OctoBech32.toBech32(linkType.getPrefix(), chain.dataWriteArray()).getValue();
}
protected NoStrShareBitChainTapeDeck getTapeDeck() {
return tapeDeck;
}
public Optional<String> getClient() {
return getTapeDeck().playBitFormatOf(NoStrImplShareTLV.CLIENT, OctoBitFormat.UTF_8);
}
@Override
public final String toShareLink() {
return shareLink;
}
}

View file

@ -0,0 +1,92 @@
package love.distributedrebirth.no2all.nostr.model.share;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.x4o.xml.o4o.io.tlv.TLVChainOctoBit;
import org.x4o.xml.o4o.io.tlv.TLVChainOctoBitFrame;
import org.x4o.xml.o4o.octo.OctoBitConverter;
import org.x4o.xml.o4o.octo.OctoBitFormat;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventKind;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareTLV;
public class NoStrShareBitChainTapeDeck {
protected final TLVChainOctoBit chain;
public NoStrShareBitChainTapeDeck(TLVChainOctoBit chain) {
this.chain = Objects.requireNonNull(chain);
}
public int getFrameCount() {
return chain.getFrameCount();
}
public Optional<ByteBuffer> playByteBufferOf(NoStrImplShareTLV tlv) {
TLVChainOctoBitFrame frame = chain.getFirstFrameOfType(tlv);
if (frame == null) {
return Optional.empty();
}
return Optional.of(ByteBuffer.wrap(frame.getSegmentChainSmurfs()));
}
public Optional<ByteBuffer> playSpecial() {
return playByteBufferOf(NoStrImplShareTLV.SPECIAL);
}
public <T> Optional<T> playSpecial(OctoBitConverter<T> type) {
Optional<ByteBuffer> data = playSpecial();
if (data.isEmpty()) {
return Optional.empty();
}
return Optional.of(type.fromBytes(data.get().array()));
}
public List<String> playRelays() {
List<String> result = new ArrayList<>();
for (TLVChainOctoBitFrame frame : chain.getFramesByType(NoStrImplShareTLV.RELAY)) {
result.add(OctoBitFormat.IDN.fromBytes(frame.getSegmentChainSmurfs()));
}
return result;
}
public Optional<NoStrIdentityPublicKey> playAuthor() {
TLVChainOctoBitFrame frame = chain.getFirstFrameOfType(NoStrImplShareTLV.AUTHOR);
if (frame == null) {
return Optional.empty();
}
return Optional.of(new NoStrIdentityPublicKey(frame.getSegmentChainSmurfs()));
}
public Optional<NoStrEventKind> playKind() {
TLVChainOctoBitFrame frame = chain.getFirstFrameOfType(NoStrImplShareTLV.KIND);
if (frame == null) {
return Optional.empty();
}
return Optional.of(NoStrEventKind.valueOf(OctoBitFormat.UI32_BE.fromBytes(frame.getSegmentChainSmurfs()).intValue()));
}
public Optional<Byte> playByteOf(NoStrImplShareTLV tlv) {
Byte[] data = chain.getFirstDataOfType(tlv);
if (data == null) {
return Optional.empty();
}
if (data.length == 0) {
return Optional.empty();
}
return Optional.of(data[0]);
}
public <T> Optional<T> playBitFormatOf(NoStrImplShareTLV tlv, OctoBitConverter<T> type) {
TLVChainOctoBitFrame frame = chain.getFirstFrameOfType(tlv);
if (frame == null) {
return Optional.empty();
}
return Optional.of(type.fromBytes(frame.getSegmentChainSmurfs()));
}
}

View file

@ -0,0 +1,86 @@
package love.distributedrebirth.no2all.nostr.model.share;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.x4o.xml.o4o.io.tlv.TLVChainOctoBit;
import org.x4o.xml.o4o.octo.OctoBitConverter;
import org.x4o.xml.o4o.octo.OctoBitFormat;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventKind;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareTLV;
public class NoStrShareBitChainTapeStudio extends NoStrShareBitChainTapeDeck {
public NoStrShareBitChainTapeStudio(TLVChainOctoBit chain) {
super(chain);
}
public void clear() {
chain.clear();
}
public void recordClient(String client) {
if (client == null) {
return;
}
chain.addFrame(NoStrImplShareTLV.CLIENT, OctoBitFormat.UTF_8.toBytes(client));
}
public void recordByteArrayFor(byte[] value, NoStrImplShareTLV tlv) {
if (value == null) {
return;
}
chain.addFrame(tlv, value);
}
public void recordSpecial(byte[] value) {
recordByteArrayFor(Objects.requireNonNull(value), NoStrImplShareTLV.SPECIAL);
}
public <T> void recordSpecial(T value, OctoBitConverter<T> type) {
recordSpecial(type.toBytes(Objects.requireNonNull(value)));
}
public void recordRelays(List<String> relays) {
if (relays == null) {
return;
}
for (String relay : relays) {
chain.addFrame(NoStrImplShareTLV.RELAY, OctoBitFormat.IDN.toBytes(relay));
}
}
public void recordAuthor(Optional<NoStrIdentityPublicKey> value) {
if (value.isEmpty()) {
return;
}
recordAuthor(value.get());
}
public void recordAuthor(NoStrIdentityPublicKey value) {
recordByteArrayFor(value.getBytes(), NoStrImplShareTLV.AUTHOR);
}
public void recordKind(Optional<NoStrEventKind> value) {
if (value.isEmpty()) {
return;
}
recordKind(value.get());
}
public void recordKind(NoStrEventKind value) {
if (value == null) {
return;
}
chain.addFrame(NoStrImplShareTLV.KIND, OctoBitFormat.UI32_BE.toBytes((long)value.getNumber()));
}
public void recordByteFor(byte value, NoStrImplShareTLV tlv) {
byte[] data = new byte[1];
data[0] = value;
chain.addFrame(tlv, data);
}
}

View file

@ -0,0 +1,6 @@
package love.distributedrebirth.no2all.nostr.model.share;
public interface NoStrShareLink {
String toShareLink();
}

View file

@ -0,0 +1,50 @@
package love.distributedrebirth.no2all.nostr.model.share;
import java.util.List;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventId;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventKind;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public final class NoStrShareLinkEvent extends NoStrShareB32LinkTLV {
public NoStrShareLinkEvent(OctoBech32String link) {
super(NoStrImplShareLink.EVENT, link);
}
public NoStrShareLinkEvent(NoStrEventId eventId) {
this(eventId, List.of(), Optional.empty(), Optional.empty());
}
public NoStrShareLinkEvent(NoStrEventId eventId, List<String> relays, Optional<NoStrIdentityPublicKey> author, Optional<NoStrEventKind> kind) {
super(NoStrImplShareLink.EVENT, tapeStudio -> {
tapeStudio.recordSpecial(eventId.getBytes());
tapeStudio.recordRelays(relays);
tapeStudio.recordAuthor(author);
tapeStudio.recordKind(kind);
});
}
public NoStrEventId getEventId() {
return new NoStrEventId(getTapeDeck().playSpecial().get().array());
}
public List<String> getRelays() {
return getTapeDeck().playRelays();
}
public Optional<NoStrIdentityPublicKey> getAuthorId() {
return getTapeDeck().playAuthor();
}
public Optional<NoStrEventKind> getKind() {
return getTapeDeck().playKind();
}
public static NoStrShareLinkEvent ofB32(String linkB32) {
return new NoStrShareLinkEvent(OctoBech32String.of(linkB32));
}
}

View file

@ -0,0 +1,47 @@
package love.distributedrebirth.no2all.nostr.model.share;
import java.util.List;
import java.util.Objects;
import org.x4o.xml.o4o.octo.OctoBitFormat;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventKind;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public final class NoStrShareLinkEventReference extends NoStrShareB32LinkTLV {
public NoStrShareLinkEventReference(OctoBech32String link) {
super(NoStrImplShareLink.EVENT_REFERENCE, link);
}
public NoStrShareLinkEventReference(String refDValue, List<String> relays, NoStrIdentityPublicKey author, NoStrEventKind kind) {
super(NoStrImplShareLink.EVENT_REFERENCE, tapeStudio -> {
tapeStudio.recordSpecial(refDValue, OctoBitFormat.UTF_8);
tapeStudio.recordRelays(relays);
tapeStudio.recordAuthor(author);
tapeStudio.recordKind(Objects.requireNonNull(kind));
});
}
public String getReferenceDValue() {
return getTapeDeck().playSpecial(OctoBitFormat.UTF_8).get();
}
public List<String> getRelays() {
return getTapeDeck().playRelays();
}
public NoStrIdentityPublicKey getAuthorId() {
return getTapeDeck().playAuthor().get();
}
public NoStrEventKind getKind() {
return getTapeDeck().playKind().get();
}
public static NoStrShareLinkEventReference ofB32(String linkB32) {
return new NoStrShareLinkEventReference(OctoBech32String.of(linkB32));
}
}

View file

@ -0,0 +1,24 @@
package love.distributedrebirth.no2all.nostr.model.share;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventId;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public final class NoStrShareLinkNote extends NoStrShareB32LinkBare {
public NoStrShareLinkNote(OctoBech32String link) {
super(NoStrImplShareLink.NOTE, link);
}
public NoStrShareLinkNote(NoStrEventId eventId) {
super(NoStrImplShareLink.NOTE, eventId.getBytes());
}
public NoStrEventId getEventId() {
return new NoStrEventId(getBareValue());
}
public static NoStrShareLinkNote ofB32(String linkB32) {
return new NoStrShareLinkNote(OctoBech32String.of(linkB32));
}
}

View file

@ -0,0 +1,24 @@
package love.distributedrebirth.no2all.nostr.model.share;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPrivateKey;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public final class NoStrShareLinkPrivateKey extends NoStrShareB32LinkBare {
public NoStrShareLinkPrivateKey(OctoBech32String link) {
super(NoStrImplShareLink.PRIVATE_KEY, link);
}
public NoStrShareLinkPrivateKey(NoStrIdentityPrivateKey privateKey) {
super(NoStrImplShareLink.PRIVATE_KEY, privateKey.getBytes());
}
public NoStrIdentityPrivateKey getPrivateKey() {
return new NoStrIdentityPrivateKey(getBareValue());
}
public static NoStrShareLinkPrivateKey ofB32(String linkB32) {
return new NoStrShareLinkPrivateKey(OctoBech32String.of(linkB32));
}
}

View file

@ -0,0 +1,51 @@
package love.distributedrebirth.no2all.nostr.model.share;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareTLV;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public final class NoStrShareLinkPrivateKeySecure extends NoStrShareB32LinkTLV {
public NoStrShareLinkPrivateKeySecure(OctoBech32String link) {
super(NoStrImplShareLink.PRIVATE_KEY_SECURE, link);
}
public NoStrShareLinkPrivateKeySecure(byte[] cryptKey, byte version, byte logN, byte[] salt, byte[] nonce, byte level) {
super(NoStrImplShareLink.PRIVATE_KEY_SECURE, tapeStudio -> {
tapeStudio.recordSpecial(cryptKey);
tapeStudio.recordByteFor(version, NoStrImplShareTLV.VERSION);
tapeStudio.recordByteFor(logN, NoStrImplShareTLV.LOG_N);
tapeStudio.recordByteArrayFor(salt, NoStrImplShareTLV.SALT);
tapeStudio.recordByteArrayFor(nonce, NoStrImplShareTLV.NONCE);
tapeStudio.recordByteFor(level, NoStrImplShareTLV.LEVEL);
});
}
public byte[] getCryptKey() {
return getTapeDeck().playSpecial().get().array();
}
public byte getVersion() {
return getTapeDeck().playByteOf(NoStrImplShareTLV.VERSION).get();
}
public byte getLogN() {
return getTapeDeck().playByteOf(NoStrImplShareTLV.LOG_N).get();
}
public byte[] getSalt() {
return getTapeDeck().playByteBufferOf(NoStrImplShareTLV.SALT).get().array();
}
public byte[] getNonce() {
return getTapeDeck().playByteBufferOf(NoStrImplShareTLV.NONCE).get().array();
}
public byte getSecurityLevel() {
return getTapeDeck().playByteOf(NoStrImplShareTLV.LEVEL).get();
}
public static NoStrShareLinkPrivateKeySecure ofB32(String linkB32) {
return new NoStrShareLinkPrivateKeySecure(OctoBech32String.of(linkB32));
}
}

View file

@ -0,0 +1,33 @@
package love.distributedrebirth.no2all.nostr.model.share;
import java.util.List;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public final class NoStrShareLinkProfile extends NoStrShareB32LinkTLV {
public NoStrShareLinkProfile(OctoBech32String link) {
super(NoStrImplShareLink.PROFILE, link);
}
public NoStrShareLinkProfile(NoStrIdentityPublicKey publicKey, List<String> relays) {
super(NoStrImplShareLink.PROFILE, tapeStudio -> {
tapeStudio.recordSpecial(publicKey.getBytes());
tapeStudio.recordRelays(relays);
});
}
public NoStrIdentityPublicKey getPublicKey() {
return new NoStrIdentityPublicKey(getTapeDeck().playSpecial().get().array());
}
public List<String> getRelays() {
return getTapeDeck().playRelays();
}
public static NoStrShareLinkProfile ofB32(String linkB32) {
return new NoStrShareLinkProfile(OctoBech32String.of(linkB32));
}
}

View file

@ -0,0 +1,24 @@
package love.distributedrebirth.no2all.nostr.model.share;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public final class NoStrShareLinkPublicKey extends NoStrShareB32LinkBare {
public NoStrShareLinkPublicKey(OctoBech32String link) {
super(NoStrImplShareLink.PUBLIC_KEY, link);
}
public NoStrShareLinkPublicKey(NoStrIdentityPublicKey publicKey) {
super(NoStrImplShareLink.PUBLIC_KEY, publicKey.getBytes());
}
public NoStrIdentityPublicKey getPublicKey() {
return new NoStrIdentityPublicKey(getBareValue());
}
public static NoStrShareLinkPublicKey ofB32(String linkB32) {
return new NoStrShareLinkPublicKey(OctoBech32String.of(linkB32));
}
}

View file

@ -0,0 +1,27 @@
package love.distributedrebirth.no2all.nostr.model.share;
import org.x4o.xml.o4o.octo.OctoBitFormat;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplShareLink;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public final class NoStrShareLinkRelay extends NoStrShareB32LinkTLV {
public NoStrShareLinkRelay(OctoBech32String link) {
super(NoStrImplShareLink.RELAY, link);
}
public NoStrShareLinkRelay(String relayUrl) {
super(NoStrImplShareLink.RELAY, tapeStudio -> {
tapeStudio.recordSpecial(relayUrl, OctoBitFormat.UTF_8);
});
}
public String getRelayUrl() {
return getTapeDeck().playSpecial(OctoBitFormat.UTF_8).get();
}
public static NoStrShareLinkRelay ofB32(String linkB32) {
return new NoStrShareLinkRelay(OctoBech32String.of(linkB32));
}
}

View file

@ -0,0 +1,76 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventKind;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagA;
public final class NoStrTagA extends NoStrEventTagBase<NoStrImplTagA> {
public NoStrTagA(String address, String relayUrl, Optional<String> platform) {
super(NoStrImplEventTag.A);
setMetaArgumentStr(NoStrImplTagA.ADDRESS, address);
setMetaArgumentStr(NoStrImplTagA.RELAY_URL, relayUrl);
setMetaArgumentOptStr(NoStrImplTagA.PLATFORM, platform);
}
public NoStrTagA(String[] args) {
super(NoStrImplEventTag.A, args);
}
public String getAddress() {
return getMetaArgument(NoStrImplTagA.ADDRESS).get();
}
public String getRelayUrl() {
return getMetaArgument(NoStrImplTagA.RELAY_URL).get();
}
public Optional<String> getPlatform() {
return getMetaArgument(NoStrImplTagA.PLATFORM);
}
public NoStrEventKind getAddressKind() {
return NoStrEventKind.valueOf(NoStrImplTagA.splitToKind(getAddress()));
}
public NoStrIdentityPublicKey getAddressPublicKey() {
return NoStrIdentityPublicKey.ofHex(NoStrImplTagA.splitToPublicKey(getAddress()));
}
public String getAddressParameter() {
return NoStrImplTagA.splitToParameter(getAddress());
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagA(String address, String relayUrl, Optional<String> platform) {
return tag(new NoStrTagA(address, relayUrl, platform));
}
default NoStrFireStackWelder tagA(String address, String relayUrl, String platform) {
return tagA(address, relayUrl, Optional.of(platform));
}
default NoStrFireStackWelder tagA(String address, String relayUrl) {
return tagA(address, relayUrl, Optional.empty());
}
default NoStrFireStackWelder tagA(NoStrEventKind kind, NoStrIdentityPublicKey publicKey, String parameter, String relayUrl, Optional<String> platform) {
return tagA(kind.getNumber() + NoStrImplTagA.SEPERATOR + publicKey.getHex() + NoStrImplTagA.SEPERATOR + parameter, relayUrl, platform);
}
default NoStrFireStackWelder tagA(NoStrEventKind kind, NoStrIdentityPublicKey publicKey, String parameter, String relayUrl, String platform) {
return tagA(kind, publicKey, parameter, relayUrl, Optional.of(platform));
}
default NoStrFireStackWelder tagA(NoStrEventKind kind, NoStrIdentityPublicKey publicKey, String parameter, String relayUrl) {
return tagA(kind, publicKey, parameter, relayUrl, Optional.empty());
}
}
}

View file

@ -0,0 +1,29 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBaseMono;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public final class NoStrTagAlt extends NoStrEventTagBaseMono {
public NoStrTagAlt(String altDescription) {
super(NoStrImplEventTag.ALT);
setMetaArgumentStr(altDescription);
}
public NoStrTagAlt(String[] args) {
super(NoStrImplEventTag.ALT, args);
}
public String getAltDescription() {
return getMetaArgument().get();
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagAlt(String altDescription) {
return tag(new NoStrTagAlt(altDescription));
}
}
}

View file

@ -0,0 +1,45 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagClient;
public final class NoStrTagClient extends NoStrEventTagBase<NoStrImplTagClient> {
public NoStrTagClient(String userAgent, Optional<String> version) {
super(NoStrImplEventTag.CLIENT);
setMetaArgumentStr(NoStrImplTagClient.USER_AGENT, userAgent);
setMetaArgumentOptStr(NoStrImplTagClient.VERSION, version);
}
public NoStrTagClient(String[] args) {
super(NoStrImplEventTag.CLIENT, args);
}
public String getUserAgent() {
return getMetaArgument(NoStrImplTagClient.USER_AGENT).get();
}
public Optional<String> getVersion() {
return getMetaArgument(NoStrImplTagClient.VERSION);
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagClient(String userAgent, Optional<String> version) {
return tag(new NoStrTagClient(userAgent, version));
}
default NoStrFireStackWelder tagClient(String userAgent, String version) {
return tagClient(userAgent, Optional.of(version));
}
default NoStrFireStackWelder tagClient(String userAgent) {
return tagClient(userAgent, Optional.empty());
}
}
}

View file

@ -0,0 +1,50 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagContentWarning;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagContentWarningRGroup;
public final class NoStrTagContentWarning extends NoStrEventTagBase<NoStrImplTagContentWarning> {
public NoStrTagContentWarning(Optional<String> reason, Optional<NoStrImplTagContentWarningRGroup> rateGroup) {
super(NoStrImplEventTag.CONTENT_WARNING);
setMetaArgumentOptStr(NoStrImplTagContentWarning.REASON, reason);
setMetaArgumentOptQName(NoStrImplTagContentWarning.RATE_GROUP, rateGroup);
}
public NoStrTagContentWarning(String[] args) {
super(NoStrImplEventTag.CONTENT_WARNING, args);
}
public Optional<String> getReason() {
return getMetaArgument(NoStrImplTagContentWarning.REASON);
}
public Optional<NoStrImplTagContentWarningRGroup> getRateGroup() {
return getMetaArgument(NoStrImplTagContentWarning.RATE_GROUP).flatMap(v -> NoStrImplTagContentWarningRGroup.valueOfQName(v));
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagContentWarning(Optional<String> reason, Optional<NoStrImplTagContentWarningRGroup> rateGroup) {
return tag(new NoStrTagContentWarning(reason, rateGroup));
}
default NoStrFireStackWelder tagContentWarning(String reason, NoStrImplTagContentWarningRGroup rateGroup) {
return tagContentWarning(Optional.of(reason), Optional.of(rateGroup));
}
default NoStrFireStackWelder tagContentWarning(String reason) {
return tagContentWarning(Optional.of(reason), Optional.empty());
}
default NoStrFireStackWelder tagContentWarning() {
return tagContentWarning(Optional.empty(), Optional.empty());
}
}
}

View file

@ -0,0 +1,29 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBaseMono;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public final class NoStrTagD extends NoStrEventTagBaseMono {
public NoStrTagD(String parameter) {
super(NoStrImplEventTag.D);
setMetaArgumentStr(parameter);
}
public NoStrTagD(String[] args) {
super(NoStrImplEventTag.D, args);
}
public String getParameter() {
return getMetaArgument().get();
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagD(String parameter) {
return tag(new NoStrTagD(parameter));
}
}
}

View file

@ -0,0 +1,29 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBaseMono;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public final class NoStrTagDescription extends NoStrEventTagBaseMono {
public NoStrTagDescription(String description) {
super(NoStrImplEventTag.DESCRIPTION);
setMetaArgumentStr(description);
}
public NoStrTagDescription(String[] args) {
super(NoStrImplEventTag.DESCRIPTION, args);
}
public String getDescription() {
return getMetaArgument().get();
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagDescription(String description) {
return tag(new NoStrTagDescription(description));
}
}
}

View file

@ -0,0 +1,56 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventId;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagE;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagEMarker;
public final class NoStrTagE extends NoStrEventTagBase<NoStrImplTagE> {
public NoStrTagE(NoStrEventId eventId, Optional<String> relayUrl, Optional<NoStrImplTagEMarker> marker) {
super(NoStrImplEventTag.E);
setMetaArgumentStr(NoStrImplTagE.EVENT_ID, eventId.getHex());
setMetaArgumentOptStr(NoStrImplTagE.RELAY_URL, relayUrl);
setMetaArgumentOptQName(NoStrImplTagE.MARKER, marker);
}
public NoStrTagE(String[] args) {
super(NoStrImplEventTag.E, args);
}
public NoStrEventId getEventId() {
return NoStrEventId.ofHex(getMetaArgument(NoStrImplTagE.EVENT_ID).get());
}
public Optional<String> getRelayUrl() {
return getMetaArgument(NoStrImplTagE.RELAY_URL);
}
public Optional<NoStrImplTagEMarker> getMarker() {
return getMetaArgument(NoStrImplTagE.MARKER).flatMap(v -> NoStrImplTagEMarker.valueOfQName(v));
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagE(NoStrEventId eventId, Optional<String> relayUrl, Optional<NoStrImplTagEMarker> marker) {
return tag(new NoStrTagE(eventId, relayUrl, marker));
}
default NoStrFireStackWelder tagE(NoStrEventId eventId, String relayUrl, NoStrImplTagEMarker marker) {
return tagE(eventId, Optional.of(relayUrl), Optional.of(marker));
}
default NoStrFireStackWelder tagERelayUrl(NoStrEventId eventId, String relayUrl) {
return tagE(eventId, Optional.of(relayUrl), Optional.empty());
}
default NoStrFireStackWelder tagEMarker(NoStrEventId eventId, NoStrImplTagEMarker marker) {
return tagE(eventId, Optional.empty(), Optional.of(marker));
}
}
}

View file

@ -0,0 +1,50 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagI;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagIClaim;
public final class NoStrTagI extends NoStrEventTagBase<NoStrImplTagI> {
public NoStrTagI(String platformIdentity, String proof) {
super(NoStrImplEventTag.I);
setMetaArgumentStr(NoStrImplTagI.PLATFORM_IDENTITY, platformIdentity);
setMetaArgumentStr(NoStrImplTagI.PROOF, proof);
}
public NoStrTagI(String[] args) {
super(NoStrImplEventTag.I, args);
}
public String getPlatformIdentity() {
return getMetaArgument(NoStrImplTagI.PLATFORM_IDENTITY).get();
}
public String getProof() {
return getMetaArgument(NoStrImplTagI.PROOF).get();
}
public String getIdentityName() {
return NoStrImplTagIClaim.splitFromPlatformIdentity(getPlatformIdentity());
}
public Optional<NoStrImplTagIClaim> getIdentityClaim() {
return NoStrImplTagIClaim.valueOfPlatformIdentity(getPlatformIdentity());
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagI(String platformIdentity, String proof) {
return tag(new NoStrTagI(platformIdentity, proof));
}
default NoStrFireStackWelder tagI(NoStrImplTagIClaim claimPlatform, String claimIdentity, String proof) {
return tagI(claimPlatform.getQName() + NoStrImplTagIClaim.SEPERATOR + claimIdentity, proof);
}
}
}

View file

@ -0,0 +1,57 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagImage;
public final class NoStrTagImage extends NoStrEventTagBase<NoStrImplTagImage> {
public NoStrTagImage(String url, Optional<String> dimension) {
super(NoStrImplEventTag.IMAGE);
setMetaArgumentStr(NoStrImplTagImage.URL, url);
setMetaArgumentOptStr(NoStrImplTagImage.DIMENSION, dimension);
}
public NoStrTagImage(String[] args) {
super(NoStrImplEventTag.IMAGE, args);
}
public String getUrl() {
return getMetaArgument(NoStrImplTagImage.URL).get();
}
public Optional<String> getDimension() {
return getMetaArgument(NoStrImplTagImage.DIMENSION);
}
public Optional<Integer> getDimensionWidth() {
return getDimension().map(v -> NoStrImplTagImage.splitDimensionToWidth(v));
}
public Optional<Integer> getDimensionHeight() {
return getDimension().map(v -> NoStrImplTagImage.splitDimensionToHeight(v));
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagImage(String url, Optional<String> dimension) {
return tag(new NoStrTagImage(url, dimension));
}
default NoStrFireStackWelder tagImage(String url) {
return tagImage(url, Optional.empty());
}
default NoStrFireStackWelder tagImage(String url, String dimension) {
return tagImage(url, Optional.of(dimension));
}
default NoStrFireStackWelder tagImage(String url, int width, int height) {
return tagImage(url, Optional.of(NoStrImplTagImage.createDimension(width, height)));
}
}
}

View file

@ -0,0 +1,29 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBaseMono;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public final class NoStrTagName extends NoStrEventTagBaseMono {
public NoStrTagName(String name) {
super(NoStrImplEventTag.NAME);
setMetaArgumentStr(name);
}
public NoStrTagName(String[] args) {
super(NoStrImplEventTag.NAME, args);
}
public String getName() {
return getMetaArgument().get();
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagName(String name) {
return tag(new NoStrTagName(name));
}
}
}

View file

@ -0,0 +1,39 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagNonce;
public final class NoStrTagNonce extends NoStrEventTagBase<NoStrImplTagNonce> {
public NoStrTagNonce(int difficulty) {
super(NoStrImplEventTag.NONCE);
setMetaArgumentStr(NoStrImplTagNonce.BEARER_PROOF, Integer.toString(NoStrImplTagNonce.DEFAULT_BEARER_PROOF));
setMetaArgumentStr(NoStrImplTagNonce.DIFFICULTY, Integer.toString(difficulty));
}
public NoStrTagNonce(String[] args) {
super(NoStrImplEventTag.NONCE, args);
}
public void setBearerProof(int bearerProof) {
setMetaArgumentStr(NoStrImplTagNonce.BEARER_PROOF, Integer.toString(bearerProof));
}
public int getBearerProof() {
return Integer.valueOf(getMetaArgument(NoStrImplTagNonce.BEARER_PROOF).get());
}
public int getDifficulty() {
return Integer.valueOf(getMetaArgument(NoStrImplTagNonce.DIFFICULTY).get());
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagNonce(int difficulty) {
return tag(new NoStrTagNonce(difficulty));
}
}
}

View file

@ -0,0 +1,54 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.NoStrIdentityPublicKey;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagP;
public final class NoStrTagP extends NoStrEventTagBase<NoStrImplTagP> {
public NoStrTagP(NoStrIdentityPublicKey publicKey, Optional<String> relayUrl, Optional<String> petName) {
super(NoStrImplEventTag.P);
setMetaArgumentStr(NoStrImplTagP.PUBLIC_KEY, publicKey.getHex());
setMetaArgumentOptStr(NoStrImplTagP.PET_NAME, petName);
}
public NoStrTagP(String[] args) {
super(NoStrImplEventTag.P, args);
}
public NoStrIdentityPublicKey getPublicKey() {
return NoStrIdentityPublicKey.ofHex(getMetaArgument(NoStrImplTagP.PUBLIC_KEY).get());
}
public Optional<String> getPetName() {
return getMetaArgument(NoStrImplTagP.PET_NAME);
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagP(NoStrIdentityPublicKey publicKey, Optional<String> relayUrl, Optional<String> petName) {
return tag(new NoStrTagP(publicKey, relayUrl, petName));
}
default NoStrFireStackWelder tagP(NoStrIdentityPublicKey publicKey, String relayUrl, String petName) {
return tagP(publicKey, Optional.of(relayUrl), Optional.of(petName));
}
default NoStrFireStackWelder tagP(NoStrIdentityPublicKey publicKey) {
return tagP(publicKey, Optional.empty(), Optional.empty());
}
default NoStrFireStackWelder tagPRelayUrl(NoStrIdentityPublicKey publicKey, String relayUrl) {
return tagP(publicKey, Optional.of(relayUrl), Optional.empty());
}
default NoStrFireStackWelder tagPPetName(NoStrIdentityPublicKey publicKey, String petName) {
return tagP(publicKey, Optional.empty(), Optional.of(petName));
}
}
}

View file

@ -0,0 +1,35 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import java.time.Instant;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBaseMono;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public final class NoStrTagPublishedAt extends NoStrEventTagBaseMono {
public NoStrTagPublishedAt(Instant publishedAt) {
super(NoStrImplEventTag.PUBLISHED_AT);
setMetaArgumentStr(Long.toString(publishedAt.getEpochSecond()));
}
public NoStrTagPublishedAt(String[] args) {
super(NoStrImplEventTag.PUBLISHED_AT, args);
}
public Instant getPublishedAt() {
return Instant.ofEpochSecond(Long.valueOf(getMetaArgument().get()));
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagPublishedAt(Instant publishedAt) {
return tag(new NoStrTagPublishedAt(publishedAt));
}
default NoStrFireStackWelder tagPublishedAtNow() {
return tagPublishedAt(Instant.now());
}
}
}

View file

@ -0,0 +1,29 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBaseMono;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public final class NoStrTagR extends NoStrEventTagBaseMono {
public NoStrTagR(String reference) {
super(NoStrImplEventTag.R);
setMetaArgumentStr(reference);
}
public NoStrTagR(String[] args) {
super(NoStrImplEventTag.R, args);
}
public String getReference() {
return getMetaArgument().get();
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagR(String reference) {
return tag(new NoStrTagR(reference));
}
}
}

View file

@ -0,0 +1,45 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagSubject;
public final class NoStrTagSubject extends NoStrEventTagBase<NoStrImplTagSubject> {
public NoStrTagSubject(String subject) {
super(NoStrImplEventTag.SUBJECT);
setMetaArgumentStr(NoStrImplTagSubject.SUBJECT, subject);
}
public NoStrTagSubject(String[] args) {
super(NoStrImplEventTag.SUBJECT, args);
}
public String getSubject() {
return getMetaArgument(NoStrImplTagSubject.SUBJECT).get();
}
public boolean hasReplyPrefix() {
return NoStrImplTagSubject.hasReplyPrefix(getSubject());
}
public boolean hasChoppedPostfix() {
return NoStrImplTagSubject.hasChoppedPostfix(getSubject());
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagSubject(String subject) {
return tag(new NoStrTagSubject(NoStrImplTagSubject.limitLength(subject)));
}
default NoStrFireStackWelder tagSubjectReply(String subject) {
if (NoStrImplTagSubject.hasReplyPrefix(subject)) {
return tagSubject(subject);
}
return tagSubject(NoStrImplTagSubject.prefixSubject(subject));
}
}
}

View file

@ -0,0 +1,29 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBaseMono;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public final class NoStrTagSummary extends NoStrEventTagBaseMono {
public NoStrTagSummary(String summary) {
super(NoStrImplEventTag.SUMMARY);
setMetaArgumentStr(summary);
}
public NoStrTagSummary(String[] args) {
super(NoStrImplEventTag.SUMMARY, args);
}
public String getSummary() {
return getMetaArgument().get();
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagSummary(String summary) {
return tag(new NoStrTagSummary(summary));
}
}
}

View file

@ -0,0 +1,29 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBaseMono;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
public final class NoStrTagT extends NoStrEventTagBaseMono {
public NoStrTagT(String hashTag) {
super(NoStrImplEventTag.T);
setMetaArgumentStr(hashTag);
}
public NoStrTagT(String[] args) {
super(NoStrImplEventTag.T, args);
}
public String getHashTag() {
return getMetaArgument().get();
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagT(String hashTag) {
return tag(new NoStrTagT(hashTag));
}
}
}

View file

@ -0,0 +1,57 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagThumb;
public final class NoStrTagThumb extends NoStrEventTagBase<NoStrImplTagThumb> {
public NoStrTagThumb(String url, Optional<String> dimension) {
super(NoStrImplEventTag.THUMB);
setMetaArgumentStr(NoStrImplTagThumb.URL, url);
setMetaArgumentOptStr(NoStrImplTagThumb.DIMENSION, dimension);
}
public NoStrTagThumb(String[] args) {
super(NoStrImplEventTag.THUMB, args);
}
public String getUrl() {
return getMetaArgument(NoStrImplTagThumb.URL).get();
}
public Optional<String> getDimension() {
return getMetaArgument(NoStrImplTagThumb.DIMENSION);
}
public Optional<Integer> getDimensionWidth() {
return getDimension().map(v -> NoStrImplTagThumb.splitDimensionToWidth(v));
}
public Optional<Integer> getDimensionHeight() {
return getDimension().map(v -> NoStrImplTagThumb.splitDimensionToHeight(v));
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagThumb(String url, Optional<String> dimension) {
return tag(new NoStrTagThumb(url, dimension));
}
default NoStrFireStackWelder tagThumb(String url) {
return tagThumb(url, Optional.empty());
}
default NoStrFireStackWelder tagThumb(String url, String dimension) {
return tagThumb(url, Optional.of(dimension));
}
default NoStrFireStackWelder tagThumb(String url, int width, int height) {
return tagThumb(url, Optional.of(NoStrImplTagThumb.createDimension(width, height)));
}
}
}

View file

@ -0,0 +1,34 @@
package love.distributedrebirth.no2all.nostr.model.tag;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackFishWelder;
import love.distributedrebirth.no2all.nostr.fire.NoStrFireStackWelder;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagBase;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTag;
import love.distributedrebirth.no2all.nostr.nip.tag.NoStrImplTagTitle;
public final class NoStrTagTitle extends NoStrEventTagBase<NoStrImplTagTitle> {
public NoStrTagTitle(String title) {
super(NoStrImplEventTag.TITLE);
setMetaArgumentStr(NoStrImplTagTitle.TITLE, title);
}
public NoStrTagTitle(String[] args) {
super(NoStrImplEventTag.TITLE, args);
}
public String getTitle() {
return getMetaArgument(NoStrImplTagTitle.TITLE).get();
}
public boolean hasChoppedPostfix() {
return NoStrImplTagTitle.hasChoppedPostfix(getTitle());
}
public interface FishWelder extends NoStrFireStackFishWelder {
default NoStrFireStackWelder tagTitle(String title) {
return tag(new NoStrTagTitle(NoStrImplTagTitle.limitLength(title)));
}
}
}

View file

@ -0,0 +1,89 @@
package love.distributedrebirth.no2all.nostr.nip;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
public enum NoStrImpl implements NoStrImplPossibility {
NIP_0_UNKNOWN,
NIP_1_BASE_PROTOCOL,
NIP_2_CONTACTS,
NIP_3_OPEN_TIMESTAMPS,
NIP_4_CRYTE_DIRECT_MSG,
NIP_5_NOSTR_TO_DNS,
NIP_6_KEY_FROM_MNEMONIC_SEED,
NIP_7_BROWSER_WINDOW_NOSTR,
NIP_9_EVENT_DELETION,
NIP_10_CORRECT_BASE_TAGS,
NIP_11_RELAY_INFO_DOC,
NIP_12_GENERIC_TAG_QUERY,
NIP_13_PROOF_OF_WORK,
NIP_14_TEXT_SUBJECT,
NIP_15_MARKETPLACE,
NIP_16_EVENT_TREATMENT,
NIP_18_REPOSTS,
NIP_19_BECH32_ENCODED,
NIP_20_COMMAND_RESULT,
NIP_21_NOSTR_URL_SCHEMA,
NIP_22_EVENT_AT_LIMITS,
NIP_23_LONG_FORM_CONTENT,
NIP_25_REACTIONS,
NIP_26_DELEGATED_EVENT_SIGN,
NIP_27_TEXT_NOTE_REFERENCE,
NIP_28_PUBLIC_CHAT,
NIP_30_CUSTOM_EMOJI,
NIP_31_ALT_FOR_UNKNOWN,
NIP_33_PARA_REPLACEABLE_EVENTS,
NIP_36_SENSITIVE_CONTENT,
NIP_39_EXT_INDENTITIES_IN_PROFILE,
NIP_40_EXPIRATION_TIMESTAMP,
NIP_42_AUTH_RELAY,
NIP_45_COUNTING_RESULTS,
NIP_46_NOSTR_CONNECT,
NIP_47_WALLET_CONNECT,
NIP_50_KEYWORD_FILTER,
NIP_51_LISTS,
NIP_56_REPORTING,
NIP_57_LIGHTING_ZAPS,
NIP_58_BADGES,
NIP_65_RELAY_LIST_METADATA,
NIP_78_APP_CUSTOM_DATA,
@Deprecated
NIP_89_RECOMMENDED_APP_HANDLERS, // used dyna hash tags so client will a cancer disconnect if a mongool send this packet.
NIP_94_FILE_METADATA,
;
private static final char PREFIX_SPLIT = '_';
private static final int PREFIX_LENGTH = 4;
private static final Map<Integer, NoStrImpl> MAP_NUMBER = Collections.unmodifiableMap(
Arrays.asList(values()).stream().collect(Collectors.toMap(v -> v.getNumber(), v -> v)));
private final int number;
private final String qFlag;
private NoStrImpl() {
int secondSplitIdx = name().indexOf(PREFIX_SPLIT, PREFIX_LENGTH);
String numberStr = name().substring(PREFIX_LENGTH, secondSplitIdx);
this.number = Integer.valueOf(numberStr);
this.qFlag = name();
}
@Override
public int getNumber() {
return number;
}
@Override
public String getQFlag() {
return qFlag;
}
public static boolean valueOfNIPValid(int nip) {
return MAP_NUMBER.containsKey(nip);
}
public static NoStrImpl valueOfNIP(int nip) {
return MAP_NUMBER.get(nip);
}
}

View file

@ -0,0 +1,10 @@
package love.distributedrebirth.no2all.nostr.nip;
public interface NoStrImplBinHex {
byte[] getBytes();
String getHex();
String getHexDipavali();
}

View file

@ -0,0 +1,33 @@
package love.distributedrebirth.no2all.nostr.nip;
import java.util.Objects;
import org.x4o.xml.o4o.octo.OctoBitFormat;
public class NoStrImplBinHexAdapter implements NoStrImplBinHex {
private final byte[] valueBytes;
private final String valueHex;
private final String valueHexDipavali;
public NoStrImplBinHexAdapter(byte[] value) {
this.valueBytes = Objects.requireNonNull(value);
this.valueHex = OctoBitFormat.HEX.fromBytes(value);
this.valueHexDipavali = OctoBitFormat.HEX_DIPAVALI.fromBytes(value);
}
@Override
public final byte[] getBytes() {
return valueBytes;
}
@Override
public final String getHex() {
return valueHex;
}
@Override
public String getHexDipavali() {
return valueHexDipavali;
}
}

View file

@ -0,0 +1,133 @@
package love.distributedrebirth.no2all.nostr.nip;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import love.distributedrebirth.no2all.nostr.NoStrGospel;
public final class NoStrImplChuch {
public static void readArrayString(JsonObject json, NoStrImplQName jsonName, List<String> data) {
readArrayString(json, jsonName.getQName(), data);
}
public static void readArrayString(JsonObject json, String jsonName, List<String> data) {
readArray(json, jsonName, v -> data.add(((JsonString)v).getString()));
}
public static void readArray(JsonObject json, NoStrImplQName jsonName, Consumer<JsonValue> arrayValue) {
readArray(json, jsonName.getQName(), arrayValue);
}
public static void readArray(JsonObject json, String jsonName, Consumer<JsonValue> arrayValue) {
if (!json.containsKey(jsonName)) {
return;
}
JsonArray values = json.getJsonArray(jsonName);
for (JsonValue valueJson : values) {
arrayValue.accept(valueJson);
}
}
public static String readString(JsonObject json, NoStrImplQName jsonName) {
return readString(json, jsonName.getQName());
}
public static String readString(JsonObject json, String jsonName) {
return json.getString(jsonName, null);
}
public static Integer readInteger(JsonObject json, NoStrImplQName jsonName) {
return readInteger(json, jsonName.getQName());
}
public static Integer readInteger(JsonObject json, String jsonName) {
if (json.containsKey(jsonName)) {
return json.getInt(jsonName);
}
return null;
}
public static Boolean readBoolean(JsonObject json, NoStrImplQName jsonName) {
return readBoolean(json, jsonName.getQName());
}
public static Boolean readBoolean(JsonObject json, String jsonName) {
if (json.containsKey(jsonName)) {
return json.getBoolean(jsonName);
}
return null;
}
public static void writeArrayWriter(JsonObjectBuilder json, NoStrImplQName jsonName, List<? extends NoStrGospel> data) {
writeArrayWriter(json, jsonName.getQName(), data);
}
public static void writeArrayWriter(JsonObjectBuilder json, String jsonName, List<? extends NoStrGospel> data) {
writeArray(json, jsonName, data, (r, v) -> r.add(v.toBible()));
}
public static void writeArrayString(JsonObjectBuilder json, NoStrImplQName jsonName, List<String> data) {
writeArrayString(json, jsonName.getQName(), data);
}
public static void writeArrayString(JsonObjectBuilder json, String jsonName, List<String> data) {
writeArray(json, jsonName, data, (r, v) -> r.add(v));
}
public static <T> void writeArray(JsonObjectBuilder json, NoStrImplQName jsonName, List<T> data, BiConsumer<JsonArrayBuilder, T> addFn) {
writeArray(json, jsonName.getQName(), data, addFn);
}
public static <T> void writeArray(JsonObjectBuilder json, String jsonName, List<T> data, BiConsumer<JsonArrayBuilder, T> addFn) {
JsonArrayBuilder builder = Json.createArrayBuilder();
for (T value : data) {
addFn.accept(builder, value);
}
JsonArray result = builder.build();
if (!result.isEmpty()) {
json.add(jsonName, result);
}
}
public static void writeString(JsonObjectBuilder json, NoStrImplQName jsonName, String data) {
writeString(json, jsonName.getQName(), data);
}
public static void writeString(JsonObjectBuilder json, String jsonName, String data) {
if (data == null) {
return;
}
json.add(jsonName, data);
}
public static void writeInteger(JsonObjectBuilder json, NoStrImplQName jsonName, Integer data) {
writeInteger(json, jsonName.getQName(), data);
}
public static void writeInteger(JsonObjectBuilder json, String jsonName, Integer data) {
if (data == null) {
return;
}
json.add(jsonName, data);
}
public static void writeBoolean(JsonObjectBuilder json, NoStrImplQName jsonName, Boolean data) {
writeBoolean(json, jsonName.getQName(), data);
}
public static void writeBoolean(JsonObjectBuilder json, String jsonName, Boolean data) {
if (data == null) {
return;
}
json.add(jsonName, data);
}
}

View file

@ -0,0 +1,93 @@
package love.distributedrebirth.no2all.nostr.nip;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventKind;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventKindRange;
public enum NoStrImplEventKind implements NoStrEventKind {
METADATA (0, NoStrImpl.NIP_1_BASE_PROTOCOL),
TEXT_NOTE (1, NoStrImpl.NIP_1_BASE_PROTOCOL),
RECOMMEND_RELAY (2, NoStrImpl.NIP_1_BASE_PROTOCOL),
CONTACTS (3, NoStrImpl.NIP_2_CONTACTS),
CRYPT_DIRECT_MSG (4, NoStrImpl.NIP_4_CRYTE_DIRECT_MSG),
EVENT_DELETION (5, NoStrImpl.NIP_9_EVENT_DELETION),
REPOSTS (6, NoStrImpl.NIP_18_REPOSTS),
REACTION (7, NoStrImpl.NIP_25_REACTIONS),
BADGE_AWARD (8, NoStrImpl.NIP_58_BADGES),
CHANNEL_CREATION (40, NoStrImpl.NIP_28_PUBLIC_CHAT),
CHANNEL_METADATA (41, NoStrImpl.NIP_28_PUBLIC_CHAT),
CHANNEL_SEND_MSG (42, NoStrImpl.NIP_28_PUBLIC_CHAT),
CHANNEL_HIDE_MSG (43, NoStrImpl.NIP_28_PUBLIC_CHAT),
CHANNEL_MUTE_USER (44, NoStrImpl.NIP_28_PUBLIC_CHAT),
FILE_METADATA (1063, NoStrImpl.NIP_94_FILE_METADATA),
REPORTING (1984, NoStrImpl.NIP_56_REPORTING),
ZAP_REQUEST (9734, NoStrImpl.NIP_57_LIGHTING_ZAPS),
ZAP_TX (9735, NoStrImpl.NIP_57_LIGHTING_ZAPS),
MUTE_LIST (10000, NoStrImpl.NIP_51_LISTS),
PIN_LIST (10001, NoStrImpl.NIP_51_LISTS),
RELAY_LIST_METADATA (10002, NoStrImpl.NIP_65_RELAY_LIST_METADATA),
WALLET_INFO (13194, NoStrImpl.NIP_47_WALLET_CONNECT),
CLIENT_AUTH (22242, NoStrImpl.NIP_42_AUTH_RELAY),
WALLET_REQUEST (23194, NoStrImpl.NIP_47_WALLET_CONNECT),
WALLET_RESPONSE (23195, NoStrImpl.NIP_47_WALLET_CONNECT),
NOSTR_CONNECT (24133, NoStrImpl.NIP_46_NOSTR_CONNECT),
CAT_PEOPLE_LIST (30000, NoStrImpl.NIP_51_LISTS),
CAT_BOOKMARK_LIST (30001, NoStrImpl.NIP_51_LISTS),
PROFILE_BADGES (30008, NoStrImpl.NIP_58_BADGES),
BADGE_DEFINITION (30009, NoStrImpl.NIP_58_BADGES),
MARKET_STALL (30017, NoStrImpl.NIP_15_MARKETPLACE),
MARKET_PRODUCT (30018, NoStrImpl.NIP_15_MARKETPLACE),
LONG_FORM_CONTENT (30023, NoStrImpl.NIP_23_LONG_FORM_CONTENT),
APP_CUSTOM_DATA (30078, NoStrImpl.NIP_78_APP_CUSTOM_DATA),
;
private static final Map<Integer, NoStrImplEventKind> MAP_NUMBER = Collections.unmodifiableMap(
Arrays.asList(values()).stream().collect(Collectors.toMap(v -> v.getNumber(), v -> v)));
private final int number;
private final NoStrImplPossibility nip;
private final NoStrEventKindRange range;
private NoStrImplEventKind(int number, NoStrImpl nip) {
this.number = number;
this.nip = nip;
this.range = NoStrImplEventKindRange.valueOfKind(number);
}
@Override
public int getNumber() {
return number;
}
@Override
public String getQFlag() {
return name();
}
@Override
public NoStrImplPossibility getNip() {
return nip;
}
@Override
public NoStrEventKindRange getRange() {
return range;
}
public static boolean valueOfKindValid(int kind) {
return MAP_NUMBER.containsKey(kind);
}
public static NoStrImplEventKind valueOfKind(int kind) {
return MAP_NUMBER.get(kind);
}
}

View file

@ -0,0 +1,63 @@
package love.distributedrebirth.no2all.nostr.nip;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventKindRange;
public enum NoStrImplEventKindRange implements NoStrEventKindRange {
// Internal Nips
UNKNOWN ( -1, -1),
CHAT ( 0, 999),
REGULAR ( 1000, 9999),
REGULAR_REPL (10000, 19999),
EPHEMERAL (20000, 29999),
PARAM_REPL (30000, 39999),
// External Apps
NOSTROCKET (640000,649999),
;
private final int numberStart;
private final int numberstop;
private NoStrImplEventKindRange(int numberStart, int numberstop) {
this.numberStart = numberStart;
this.numberstop = numberstop;
}
@Override
public String getQFlag() {
return name();
}
@Override
public int getNumberStart() {
return numberStart;
}
@Override
public int getNumberstop() {
return numberstop;
}
@Override
public boolean isReplaceable(int number) {
if (number == 0 || number == 3 || number == 41) {
return true;
}
if (this == REGULAR_REPL) {
return true;
}
if (this == PARAM_REPL) {
return true;
}
return false;
}
public static NoStrImplEventKindRange valueOfKind(int number) {
for (NoStrImplEventKindRange range : values()) {
if (number >= range.getNumberStart() && number <= range.getNumberstop()) {
return range;
}
}
return NoStrImplEventKindRange.UNKNOWN;
}
}

View file

@ -0,0 +1,143 @@
package love.distributedrebirth.no2all.nostr.nip;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTag;
import love.distributedrebirth.no2all.nostr.model.event.NoStrEventTagMeta;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagA;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagClient;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagContentWarning;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagD;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagDescription;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagE;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagI;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagImage;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagName;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagNonce;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagP;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagPublishedAt;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagR;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagSubject;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagSummary;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagT;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagThumb;
import love.distributedrebirth.no2all.nostr.model.tag.NoStrTagTitle;
public enum NoStrImplEventTag implements NoStrEventTagMeta {
// the "p" tag is used for referencing public keys
P (v -> new NoStrTagP(v), NoStrImpl.NIP_1_BASE_PROTOCOL),
// the "e" tag for referencing event ids
E (v -> new NoStrTagE(v), NoStrImpl.NIP_1_BASE_PROTOCOL, NoStrImpl.NIP_10_CORRECT_BASE_TAGS),
// ["a", "<kind>:<pubkey>:<d-identifier>", "<relay url>"]
A (v -> new NoStrTagA(v), NoStrImpl.NIP_23_LONG_FORM_CONTENT, NoStrImpl.NIP_33_PARA_REPLACEABLE_EVENTS),
I (v -> new NoStrTagI(v), NoStrImpl.NIP_39_EXT_INDENTITIES_IN_PROFILE),
// the "d" tag is a delete slug key for "pubkey:kind:d" + time, empty is def key
D (v -> new NoStrTagD(v), NoStrImpl.NIP_33_PARA_REPLACEABLE_EVENTS), // TODO: add single tag info + check
T (v -> new NoStrTagT(v), NoStrImpl.NIP_12_GENERIC_TAG_QUERY),
R (v -> new NoStrTagR(v), NoStrImpl.NIP_12_GENERIC_TAG_QUERY),
G (NoStrImpl.NIP_12_GENERIC_TAG_QUERY),
CHALLENGE (NoStrImpl.NIP_42_AUTH_RELAY),
RELAY (NoStrImpl.NIP_42_AUTH_RELAY),
TITLE (v -> new NoStrTagTitle(v), NoStrImpl.NIP_23_LONG_FORM_CONTENT),
SUMMARY (v -> new NoStrTagSummary(v), NoStrImpl.NIP_23_LONG_FORM_CONTENT),
PUBLISHED_AT (v -> new NoStrTagPublishedAt(v), NoStrImpl.NIP_23_LONG_FORM_CONTENT),
IMAGE (v -> new NoStrTagImage(v), NoStrImpl.NIP_23_LONG_FORM_CONTENT, NoStrImpl.NIP_58_BADGES),
ZAP (NoStrImpl.NIP_57_LIGHTING_ZAPS),
LNURL (NoStrImpl.NIP_57_LIGHTING_ZAPS),
AMOUNT (NoStrImpl.NIP_57_LIGHTING_ZAPS),
BOLT11 (NoStrImpl.NIP_57_LIGHTING_ZAPS),
PREIMAGE (NoStrImpl.NIP_57_LIGHTING_ZAPS),
DESCRIPTION (v -> new NoStrTagDescription(v), NoStrImpl.NIP_57_LIGHTING_ZAPS, NoStrImpl.NIP_58_BADGES),
RELAYS (NoStrImpl.NIP_57_LIGHTING_ZAPS),
CLIENT (v -> new NoStrTagClient(v), true, NoStrImpl.NIP_0_UNKNOWN),
NONCE (v -> new NoStrTagNonce(v), true, NoStrImpl.NIP_13_PROOF_OF_WORK),
SUBJECT (v -> new NoStrTagSubject(v), NoStrImpl.NIP_14_TEXT_SUBJECT),
DELEGATION (NoStrImpl.NIP_26_DELEGATED_EVENT_SIGN),
EMOJI (NoStrImpl.NIP_30_CUSTOM_EMOJI),
CONTENT_WARNING (v -> new NoStrTagContentWarning(v), NoStrImpl.NIP_36_SENSITIVE_CONTENT),
EXPIRATION (NoStrImpl.NIP_40_EXPIRATION_TIMESTAMP),
ALT (NoStrImpl.NIP_31_ALT_FOR_UNKNOWN),
NAME (v -> new NoStrTagName(v), NoStrImpl.NIP_58_BADGES),
THUMB (v -> new NoStrTagThumb(v), NoStrImpl.NIP_58_BADGES),
// Dat Package extensions
DPFH (NoStrImpl.NIP_0_UNKNOWN), // "DAT Package File Hash" with event content = maven://ndaturl+versionhash
;
private static final Map<String, NoStrEventTagMeta> MAP_QNAME = Collections.unmodifiableMap(
Arrays.asList(values()).stream().collect(Collectors.toMap(v -> v.getQName(), v -> v)));
private final Optional<Function<String[], NoStrEventTag>> mapperToEventTag;
private final String jsonQName;
private final NoStrImplPossibility[] nips;
private final boolean quariable;
private final boolean singleton;
private NoStrImplEventTag(NoStrImpl... nips) {
this(null, nips);
}
private NoStrImplEventTag(Function<String[], NoStrEventTag> mapper, NoStrImpl... nips) {
this(mapper, false, nips); // TODO: add info on all needed tags
}
private NoStrImplEventTag(Function<String[], NoStrEventTag> mapper, boolean singleton, NoStrImpl... nips) {
this.mapperToEventTag = Optional.ofNullable(mapper);
this.jsonQName = name().toLowerCase().replaceAll("_", "-");
this.nips = nips;
this.quariable = isQuariable(name());
this.singleton = singleton;
}
public Optional<Function<String[], NoStrEventTag>> getMapperToEventTag() {
return mapperToEventTag;
}
@Override
public String getQName() {
return jsonQName;
}
@Override
public String getQFlag() {
return name();
}
@Override
public NoStrImplPossibility[] getNips() {
return nips;
}
@Override
public boolean isQuariable() {
return quariable;
}
@Override
public boolean isSinglton() {
return singleton;
}
public static boolean isQuariable(String qName) {
return qName != null && qName.length() == 1;
}
public static boolean valueOfWireValid(String tag) {
return MAP_QNAME.containsKey(Objects.requireNonNull(tag));
}
public static NoStrEventTagMeta valueOfWire(String tag) {
return MAP_QNAME.get(Objects.requireNonNull(tag));
}
}

View file

@ -0,0 +1,6 @@
package love.distributedrebirth.no2all.nostr.nip;
public interface NoStrImplEventTagArgument {
int ordinal();
}

View file

@ -0,0 +1,43 @@
package love.distributedrebirth.no2all.nostr.nip;
import java.util.Objects;
public enum NoStrImplMessageOkReason {
DEFAULT (""),
BLOCKED ("blocked:"),
INVALID ("invalid:"),
POW ("pow:"),
RATE_LIMITED ("rate-limited:"),
ERROR ("error:"),
;
private final String prefix;
private final String prefixFormat;
private NoStrImplMessageOkReason(String prefix) {
this.prefix = prefix;
this.prefixFormat = prefix + (prefix.isEmpty()?"":" ");
}
public String getPrefix() {
return prefix;
}
public String format(String message) {
return prefixFormat + Objects.requireNonNull(message);
}
public static NoStrImplMessageOkReason valueOfPrefix(String message) {
Objects.requireNonNull(message);
for (NoStrImplMessageOkReason reason : values()) {
if (reason == DEFAULT) {
continue;
}
if (message.startsWith(reason.getPrefix())) {
return reason;
}
}
return NoStrImplMessageOkReason.DEFAULT;
}
}

View file

@ -0,0 +1,70 @@
package love.distributedrebirth.no2all.nostr.nip;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import jakarta.json.JsonArray;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToClient;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToRelay;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToClientAuth;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToClientCount;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToClientEose;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToClientEvent;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToClientNotice;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToClientOk;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToRelayAuth;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToRelayClose;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToRelayCount;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToRelayEvent;
import love.distributedrebirth.no2all.nostr.model.message.NoStrMsgToRelayReq;
public enum NoStrImplMessageType implements NoStrImplQName {
EVENT (NoStrImpl.NIP_1_BASE_PROTOCOL, v -> new NoStrMsgToRelayEvent(v), v -> new NoStrMsgToClientEvent(v)),
REQ (NoStrImpl.NIP_1_BASE_PROTOCOL, v -> new NoStrMsgToRelayReq(v), null),
CLOSE (NoStrImpl.NIP_1_BASE_PROTOCOL, v -> new NoStrMsgToRelayClose(v), null),
EOSE (NoStrImpl.NIP_1_BASE_PROTOCOL, null, v -> new NoStrMsgToClientEose(v)),
NOTICE (NoStrImpl.NIP_1_BASE_PROTOCOL, null, v -> new NoStrMsgToClientNotice(v)),
OK (NoStrImpl.NIP_20_COMMAND_RESULT, null, v -> new NoStrMsgToClientOk(v)),
AUTH (NoStrImpl.NIP_42_AUTH_RELAY, v -> new NoStrMsgToRelayAuth(v), v -> new NoStrMsgToClientAuth(v)),
COUNT (NoStrImpl.NIP_45_COUNTING_RESULTS, v -> new NoStrMsgToRelayCount(v), v -> new NoStrMsgToClientCount(v)),
;
private static final Set<String> MAP_NAME = Arrays.asList(values()).stream().map(v -> v.name()).collect(Collectors.toSet());
private final NoStrImplPossibility requireNip;
private final Optional<Function<JsonArray, NoStrMsgToRelay>> mapperToRelay;
private final Optional<Function<JsonArray, NoStrMsgToClient>> mapperToClient;
private NoStrImplMessageType(NoStrImpl requireNip,
Function<JsonArray, NoStrMsgToRelay> mapperToRelay,
Function<JsonArray, NoStrMsgToClient> mapperToClient) {
this.requireNip = requireNip;
this.mapperToRelay = Optional.ofNullable(mapperToRelay);
this.mapperToClient = Optional.ofNullable(mapperToClient);
}
public NoStrImplPossibility getFeatureNip() {
return requireNip;
}
public String getQName() {
return name();
}
public Optional<Function<JsonArray, NoStrMsgToRelay>> getMapperToRelay() {
return mapperToRelay;
}
public Optional<Function<JsonArray, NoStrMsgToClient>> getMapperToClient() {
return mapperToClient;
}
public static boolean valueOfValid(String name) {
return MAP_NAME.contains(Objects.requireNonNull(name));
}
}

View file

@ -0,0 +1,6 @@
package love.distributedrebirth.no2all.nostr.nip;
public interface NoStrImplPossibility extends NoStrImplQFlag {
int getNumber();
}

View file

@ -0,0 +1,8 @@
package love.distributedrebirth.no2all.nostr.nip;
public interface NoStrImplQFlag {
String CUSTOM_INDICATOR = "CUSTOM";
String getQFlag(); // for part of i18n key slug
}

View file

@ -0,0 +1,17 @@
package love.distributedrebirth.no2all.nostr.nip;
import java.util.Optional;
public interface NoStrImplQName {
String getQName(); // for gospel church bible
static <T extends NoStrImplQName> Optional<T> valueOfQName(T[] values, String qName) {
for (T value : values) {
if (value.getQName().equals(qName)) {
return Optional.of(value);
}
}
return Optional.empty();
}
}

View file

@ -0,0 +1,52 @@
package love.distributedrebirth.no2all.nostr.nip;
import java.util.Objects;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32;
import love.distributedrebirth.no2all.nostr.trust.OctoBech32String;
public enum NoStrImplShareLink { // TODO: add NIP dep
// bare value bach32
PRIVATE_KEY("nsec"),
PUBLIC_KEY("npub"),
NOTE("note"),
// TLV values bach32
PROFILE("nprofile"),
EVENT("nevent"),
RELAY("nrelay"),
EVENT_REFERENCE("naddr"),
//CHANNEL("nchannel"), //todo find docs
PRIVATE_KEY_SECURE("ncryptsec"), // bip 49
// PRIVATE_KEY_SECURE("nsecpw"),
// SECURE_URL("nsurl"),
;
private final String prefix;
private NoStrImplShareLink(String prefix) {
this.prefix = prefix;
}
public String getPrefix() {
return prefix;
}
public OctoBech32String validate(OctoBech32String link) {
Objects.requireNonNull(link);
Objects.requireNonNull(link.getValue());
if (link.getValue().startsWith(getPrefix())) {
return link;
}
throw new IllegalArgumentException("Wrong prefix; wanted " + getPrefix() + " got " + link.getValue());
}
public byte[] fromBech32(OctoBech32String link) {
return OctoBech32.fromBech32(validate(link)).getData();
}
public String toBech32(byte[] data) {
return OctoBech32.toBech32(getPrefix(), data).getValue();
}
}

View file

@ -0,0 +1,41 @@
package love.distributedrebirth.no2all.nostr.nip;
import org.x4o.xml.o4o.io.tlv.TLVChainOctoBitFrameType;
public enum NoStrImplShareTLV implements TLVChainOctoBitFrameType {
SPECIAL(0), // pubkey/eventId/payload/etc
RELAY(1),
AUTHOR(2),
KIND(3),
// new
CLIENT(4), // for appId
// for "ncryptsec" ChaCha20-Poly1305 CIPHERTEXT is in SPECIAL
VERSION(5), // one byte
LOG_N(6), // one byte
SALT(7), // 16 bytes random
NONCE(8), // 24 bytes from ChaCha20-Poly1305
LEVEL(9), // 1 byte to indicate security level of private key
// for "nsecpw" (simple AES)
//SALT,
//IV
// for "nsurl"
//SURL,
//PKCS_8, // (full ASN.1 DER packet)
;
private final byte typeByte;
private NoStrImplShareTLV(int typeByte) {
this.typeByte = (byte)typeByte;
}
@Override
public byte ordinalFrameTypeSmurf() {
return typeByte;
}
}

View file

@ -0,0 +1,32 @@
package love.distributedrebirth.no2all.nostr.nip.tag;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTagArgument;
public enum NoStrImplTagA implements NoStrImplEventTagArgument {
ADDRESS,
RELAY_URL,
PLATFORM,
;
public static final String SEPERATOR = ":";
public static int splitToKind(String address) {
int idxSep = address.indexOf(SEPERATOR);
String result = address.substring(0, idxSep);
return Integer.valueOf(result);
}
public static String splitToPublicKey(String address) {
int idxSep = address.indexOf(SEPERATOR);
int idxSepEnd = address.indexOf(SEPERATOR, idxSep + 1);
String result = address.substring(idxSep + 1, idxSepEnd);
return result;
}
public static String splitToParameter(String address) {
int idxSep = address.indexOf(SEPERATOR);
int idxSepEnd = address.indexOf(SEPERATOR, idxSep + 1);
String result = address.substring(idxSepEnd + 1, address.length());
return result;
}
}

View file

@ -0,0 +1,9 @@
package love.distributedrebirth.no2all.nostr.nip.tag;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTagArgument;
public enum NoStrImplTagClient implements NoStrImplEventTagArgument {
USER_AGENT,
VERSION,
;
}

View file

@ -0,0 +1,9 @@
package love.distributedrebirth.no2all.nostr.nip.tag;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTagArgument;
public enum NoStrImplTagContentWarning implements NoStrImplEventTagArgument {
REASON,
RATE_GROUP
;
}

View file

@ -0,0 +1,30 @@
package love.distributedrebirth.no2all.nostr.nip.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public enum NoStrImplTagContentWarningRGroup implements NoStrImplQName {
// from: https://en.wikipedia.org/wiki/Motion_Picture_Association_film_rating_system#Rating_components
VIOLENCE,
LANGUAGE,
SUBSTANCE,
NUDITY,
SEX,
;
private final String jsonQName;
private NoStrImplTagContentWarningRGroup() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
public static Optional<NoStrImplTagContentWarningRGroup> valueOfQName(String qName) {
return NoStrImplQName.valueOfQName(values(), qName);
}
}

View file

@ -0,0 +1,10 @@
package love.distributedrebirth.no2all.nostr.nip.tag;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTagArgument;
public enum NoStrImplTagE implements NoStrImplEventTagArgument {
EVENT_ID,
RELAY_URL,
MARKER,
;
}

View file

@ -0,0 +1,25 @@
package love.distributedrebirth.no2all.nostr.nip.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public enum NoStrImplTagEMarker implements NoStrImplQName {
REPLAY, ROOT, MENTION;
private final String jsonQName;
private NoStrImplTagEMarker() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
public static Optional<NoStrImplTagEMarker> valueOfQName(String qName) {
return NoStrImplQName.valueOfQName(values(), qName);
}
}

View file

@ -0,0 +1,9 @@
package love.distributedrebirth.no2all.nostr.nip.tag;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplEventTagArgument;
public enum NoStrImplTagI implements NoStrImplEventTagArgument {
PLATFORM_IDENTITY,
PROOF,
;
}

View file

@ -0,0 +1,46 @@
package love.distributedrebirth.no2all.nostr.nip.tag;
import java.util.Optional;
import love.distributedrebirth.no2all.nostr.nip.NoStrImplQName;
public enum NoStrImplTagIClaim implements NoStrImplQName {
GITHUB,
TWITTER,
MASTODON,
TELEGRAM,
;
public static final String SEPERATOR = ":";
private final String jsonQName;
private NoStrImplTagIClaim() {
jsonQName = name().toLowerCase();
}
@Override
public String getQName() {
return jsonQName;
}
public static String splitFromPlatformIdentity(String claimUri) {
int sepIdx = claimUri.indexOf(SEPERATOR);
if (sepIdx == -1) {
return claimUri;
}
if (sepIdx == claimUri.length() - 1) {
return "";
}
return claimUri.substring(sepIdx + 1);
}
public static Optional<NoStrImplTagIClaim> valueOfPlatformIdentity(String claimUri) {
for (NoStrImplTagIClaim claim : values()) {
if (claimUri.startsWith(claim.getQName())) {
return Optional.of(claim);
}
}
return Optional.empty();
}
}

Some files were not shown because too many files have changed in this diff Show more