Skip to content

Commit 2c548d4

Browse files
SessionHero01SessionHero01
authored andcommitted
Message pro features
1 parent 49bee28 commit 2c548d4

File tree

6 files changed

+133
-0
lines changed

6 files changed

+133
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package network.loki.messenger.libsession_util.protocol
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import org.junit.Assert.assertEquals
5+
import org.junit.Test
6+
import org.junit.runner.RunWith
7+
8+
@RunWith(AndroidJUnit4::class)
9+
class SessionProtocolTest {
10+
11+
@Test
12+
fun proFeaturesForMessageWorks() {
13+
val proposedFeatures = ProFeatures.from(listOf(ProFeature.PRO_BADGE))
14+
val result = SessionProtocol.proFeaturesForMessage(
15+
messageBody = "Hello, Session Pro!",
16+
proposedFeatures
17+
)
18+
19+
assertEquals(ProFeaturesForMsg.Status.Success, result.status)
20+
assertEquals(19, result.codepointCount)
21+
assertEquals(proposedFeatures, result.features)
22+
}
23+
}

library/src/main/cpp/jni_utils.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,37 @@ namespace jni_utils {
200200
}
201201
};
202202

203+
class JavaCharsRef {
204+
JNIEnv *env;
205+
jstring s;
206+
std::span<jchar> data;
207+
208+
public:
209+
JavaCharsRef(JNIEnv *env, jstring s) : env(env), s(s) {
210+
const jchar *c_str = env->GetStringChars(s, nullptr);
211+
data = std::span<jchar>(const_cast<jchar *>(c_str), env->GetStringLength(s));
212+
}
213+
214+
JavaCharsRef(const JavaCharsRef &) = delete;
215+
216+
~JavaCharsRef() {
217+
env->ReleaseStringChars(s, data.data());
218+
}
219+
220+
const jchar* chars() const {
221+
return data.data();
222+
}
223+
224+
size_t size() const {
225+
return data.size();
226+
}
227+
228+
// Get the data as a span. Only valid during the lifetime of this object.
229+
std::span<jchar> get() const {
230+
return data;
231+
}
232+
};
233+
203234
/**
204235
* A RAII wrapper for a Java byte array. This will automatically release the byte array when it goes out of scope.
205236
*/

library/src/main/cpp/protocol.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,4 +262,29 @@ Java_network_loki_messenger_libsession_1util_protocol_SessionProtocol_decodeForG
262262
*java_to_cpp_array<32>(env, pro_backend_pub_key)
263263
));
264264
});
265+
}
266+
267+
extern "C"
268+
JNIEXPORT jobject JNICALL
269+
Java_network_loki_messenger_libsession_1util_protocol_SessionProtocol_proFeaturesForMessage(
270+
JNIEnv *env, jobject thiz, jstring message_body, jlong proposed_features) {
271+
return run_catching_cxx_exception_or_throws<jobject>(env, [=] {
272+
JavaCharsRef message_ref(env, message_body);
273+
274+
auto features = session::pro_features_for_utf16(
275+
reinterpret_cast<const char16_t *>(message_ref.chars()),
276+
message_ref.size(),
277+
static_cast<SESSION_PROTOCOL_PRO_FEATURES>(proposed_features)
278+
);
279+
280+
auto clazz = env->FindClass("network/loki/messenger/libsession_util/protocol/ProFeaturesForMsg");
281+
return env->NewObject(
282+
clazz,
283+
env->GetMethodID(clazz, "<init>", "(ILjava/lang/String;JI)V"),
284+
static_cast<jint>(features.status),
285+
features.error.empty() ? nullptr : env->NewStringUTF(std::string(features.error).c_str()),
286+
static_cast<jlong>(features.features),
287+
static_cast<jint>(features.codepoint_count)
288+
);
289+
});
265290
}

library/src/main/java/network/loki/messenger/libsession_util/protocol/ProFeatures.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ enum class ProFeature(internal val bitIndex: Int) {
1414
value class ProFeatures(val rawValue: Long) {
1515
companion object {
1616
val NONE = ProFeatures(0L)
17+
18+
fun from(features: Collection<ProFeature>): ProFeatures {
19+
return ProFeatures(features.toLong())
20+
}
1721
}
1822

1923
fun contains(feature: ProFeature): Boolean {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package network.loki.messenger.libsession_util.protocol
2+
3+
import androidx.annotation.Keep
4+
5+
/**
6+
* Represents the result of trying to augment a message with Pro features.
7+
*
8+
* @param status The status of the augmentation attempt.
9+
* @param error An optional error message if the augmentation failed.
10+
* @param features The Pro features that were successfully applied.
11+
* @param codepointCount The number of codepoints in the message
12+
*/
13+
data class ProFeaturesForMsg(
14+
val status: Status,
15+
val error: String?,
16+
val features: ProFeatures,
17+
val codepointCount: Int,
18+
) {
19+
@Keep
20+
constructor(
21+
statusNativeValue: Int,
22+
error: String?,
23+
featuresNativeValue: Long,
24+
codepointCount: Int,
25+
) : this(
26+
status = Status.entries.first { it.nativeValue == statusNativeValue },
27+
error = error,
28+
features = ProFeatures(featuresNativeValue),
29+
codepointCount = codepointCount,
30+
)
31+
32+
enum class Status(internal val nativeValue: Int) {
33+
Success(0),
34+
UTFDecodingError(1),
35+
ExceedsCharacterLimit(2),
36+
}
37+
}

library/src/main/java/network/loki/messenger/libsession_util/protocol/SessionProtocol.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,17 @@ object SessionProtocol : LibSessionUtilCApi() {
5555
groupEd25519PrivateKeys: Array<ByteArray>, // all available group private keys
5656
proBackendPubKey: ByteArray, // 32 bytes backend key
5757
): DecodedEnvelope
58+
59+
private external fun proFeaturesForMessage(
60+
messageBody: String,
61+
proposedFeatures: Long
62+
): ProFeaturesForMsg
63+
64+
/**
65+
* Determines which Pro features shall be applied to a message based on its content and the proposed features.
66+
*/
67+
fun proFeaturesForMessage(
68+
messageBody: String,
69+
proposedFeatures: ProFeatures
70+
): ProFeaturesForMsg = proFeaturesForMessage(messageBody, proposedFeatures.rawValue)
5871
}

0 commit comments

Comments
 (0)