Skip to content

Commit fa808f1

Browse files
committed
feat: add pro utf stuff and move it to its own wrapper
1 parent d603683 commit fa808f1

File tree

5 files changed

+132
-1
lines changed

5 files changed

+132
-1
lines changed

include/pro/pro.hpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#pragma once
2+
3+
#include <napi.h>
4+
#include <oxenc/base64.h>
5+
#include <oxenc/hex.h>
6+
7+
#include <algorithm>
8+
#include <span>
9+
#include <vector>
10+
11+
#include "../utilities.hpp"
12+
#include "oxen/log.hpp"
13+
#include "pro/types.hpp"
14+
#include "session/attachments.hpp"
15+
#include "session/config/user_profile.hpp"
16+
#include "session/random.hpp"
17+
#include "session/session_protocol.hpp"
18+
19+
namespace session::nodeapi {
20+
21+
class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
22+
public:
23+
ProWrapper(const Napi::CallbackInfo& info) : Napi::ObjectWrap<ProWrapper>{info} {
24+
throw std::invalid_argument("ProWrapper is static and doesn't need to be constructed");
25+
}
26+
27+
static void Init(Napi::Env env, Napi::Object exports) {
28+
MetaBaseWrapper::NoBaseClassInitHelper<ProWrapper>(
29+
env,
30+
exports,
31+
"ProWrapperNode",
32+
{
33+
// Pro features
34+
StaticMethod<&ProWrapper::proFeaturesForMessage>(
35+
"proFeaturesForMessage",
36+
static_cast<napi_property_attributes>(
37+
napi_writable | napi_configurable)),
38+
});
39+
}
40+
41+
private:
42+
static Napi::Value proFeaturesForMessage(const Napi::CallbackInfo& info) {
43+
return wrapResult(info, [&] {
44+
// we expect two arguments that match:
45+
// first: {
46+
// "utf16": string,
47+
// "proFeatures": Array<ProFeature>,
48+
// }
49+
50+
assertInfoLength(info, 1);
51+
assertIsObject(info[0]);
52+
53+
auto first = info[0].As<Napi::Object>();
54+
55+
if (first.IsEmpty())
56+
throw std::invalid_argument("proFeaturesForMessage first received empty");
57+
58+
assertIsArray(first.Get("proFeatures"), "proFeaturesForMessage.proFeatures");
59+
auto proFeaturesJS = first.Get("proFeatures").As<Napi::Array>();
60+
std::vector<std::string> proFeatures;
61+
proFeatures.reserve(proFeaturesJS.Length());
62+
for (uint32_t i = 0; i < proFeaturesJS.Length(); i++) {
63+
auto itemValue = proFeaturesJS.Get(i);
64+
assertIsString(itemValue, "proFeaturesForMessage.proFeatures.itemValue");
65+
std::string item =
66+
toCppString(itemValue, "proFeaturesForMessage.proFeatures.itemValue");
67+
proFeatures.push_back(item);
68+
}
69+
70+
SESSION_PROTOCOL_PRO_EXTRA_FEATURES flags;
71+
for (std::string& feature : proFeatures) {
72+
if (feature == "10K_CHARACTER_LIMIT") {
73+
flags |= SESSION_PROTOCOL_PRO_FEATURES_10K_CHARACTER_LIMIT;
74+
} else if (feature == "PRO_BADGE") {
75+
flags |= SESSION_PROTOCOL_PRO_FEATURES_PRO_BADGE;
76+
} else if (feature == "ANIMATED_AVATAR") {
77+
flags |= SESSION_PROTOCOL_PRO_FEATURES_ANIMATED_AVATAR;
78+
}
79+
}
80+
assertIsString(first.Get("utf16"), "proFeaturesForMessage.utf16");
81+
std::u16string utf16 = first.Get("utf16").As<Napi::String>().Utf16Value();
82+
return session::pro_features_for_utf16((utf16.data()), utf16.length(), flags);
83+
});
84+
};
85+
};
86+
}; // namespace session::nodeapi

include/pro/types.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,19 @@ struct toJs_impl<session::DecodedPro> {
116116
}
117117
};
118118

119+
template <>
120+
struct toJs_impl<session::ProFeaturesForMsg> {
121+
Napi::Object operator()(
122+
const Napi::Env& env, const session::ProFeaturesForMsg pro_features_msg) {
123+
auto obj = Napi::Object::New(env);
124+
125+
obj["success"] = toJs(env, pro_features_msg.success);
126+
obj["error"] = toJs(env, pro_features_msg.error);
127+
obj["codepointCount"] = toJs(env, pro_features_msg.codepoint_count);
128+
obj["proFeatures"] = toJs(env, pro_features_msg.features);
129+
130+
return obj;
131+
}
132+
};
133+
119134
}; // namespace session::nodeapi

src/addon.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "convo_info_volatile_config.hpp"
99
#include "groups/meta_group_wrapper.hpp"
1010
#include "multi_encrypt/multi_encrypt.hpp"
11+
#include "pro/pro.hpp"
1112
#include "user_config.hpp"
1213
#include "user_groups_config.hpp"
1314

@@ -52,6 +53,7 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
5253

5354
// Fully static wrappers init
5455
session::nodeapi::MultiEncryptWrapper::Init(env, exports);
56+
session::nodeapi::ProWrapper::Init(env, exports);
5557
session::nodeapi::BlindingWrapper::Init(env, exports);
5658

5759
return exports;

types/pro/pro.d.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,32 @@ declare module 'libsession_util_nodejs' {
6464
pro_access_not_found: string;
6565
support_url: string;
6666
};
67+
68+
type ProWrapper = {
69+
proFeaturesForMessage: (args: {
70+
utf16: string;
71+
/**
72+
* If the utf16 requires 10K_CHARACTER_LIMIT to be set, it will be set in the return.
73+
* If provided (here) as an input, it will be ignored.
74+
*/
75+
proFeatures: ProFeatures;
76+
}) => WithProFeatures & { success: boolean; error: string | null; codePointCount: number };
77+
};
78+
79+
export type ProActionsCalls = MakeWrapperActionCalls<ProWrapper>;
80+
81+
82+
/**
83+
* To be used inside the web worker only (calls are synchronous and won't work asynchronously)
84+
*/
85+
export class ProWrapperNode {
86+
public static proFeaturesForMessage: ProWrapper['proFeaturesForMessage'];
87+
}
88+
89+
/**
90+
* Those actions are used internally for the web worker communication.
91+
* You should never need to import them in Session directly
92+
* You will need to add an entry here if you add a new function
93+
*/
94+
export type ProActionsType = MakeActionCall<ProWrapper, 'proFeaturesForMessage'>;
6795
}

0 commit comments

Comments
 (0)