@followgate/js 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/dist/index.d.mts +30 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +132 -3
- package/dist/index.mjs +132 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -225,6 +225,47 @@ FollowGate.getUnlockStatus();
|
|
|
225
225
|
// }
|
|
226
226
|
```
|
|
227
227
|
|
|
228
|
+
### Server-Side Verification
|
|
229
|
+
|
|
230
|
+
When `userId` is set, completions are automatically saved to the server. You can verify users from your backend:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
// Check if user is verified (server-side)
|
|
234
|
+
const isVerified = await FollowGate.isVerified();
|
|
235
|
+
// Returns: true | false
|
|
236
|
+
|
|
237
|
+
// Get full verification status
|
|
238
|
+
const status = await FollowGate.getVerificationStatus();
|
|
239
|
+
// Returns: {
|
|
240
|
+
// verified: boolean,
|
|
241
|
+
// userId: string,
|
|
242
|
+
// completedAt?: string, // ISO date string
|
|
243
|
+
// actions?: [{ action: 'follow', target: 'lukasvanuden' }, ...]
|
|
244
|
+
// }
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Use Case: Conditional Features**
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// In your app (e.g., Chrome extension, Electron app)
|
|
251
|
+
FollowGate.init({
|
|
252
|
+
appId: 'your-app-id',
|
|
253
|
+
apiKey: 'fg_live_xxx',
|
|
254
|
+
userId: clerkUserId,
|
|
255
|
+
twitter: { handle: 'lukasvanuden' },
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const isVerified = await FollowGate.isVerified();
|
|
259
|
+
|
|
260
|
+
if (isVerified) {
|
|
261
|
+
// User completed FollowGate → Full access
|
|
262
|
+
enableAllFeatures();
|
|
263
|
+
} else {
|
|
264
|
+
// User hasn't completed → Limited access
|
|
265
|
+
enableTrialMode();
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
228
269
|
### Event Listeners
|
|
229
270
|
|
|
230
271
|
```typescript
|
|
@@ -339,6 +380,7 @@ import type {
|
|
|
339
380
|
CompleteOptions,
|
|
340
381
|
UserInfo,
|
|
341
382
|
UnlockStatus,
|
|
383
|
+
VerificationStatus,
|
|
342
384
|
} from '@followgate/js';
|
|
343
385
|
```
|
|
344
386
|
|
package/dist/index.d.mts
CHANGED
|
@@ -66,6 +66,18 @@ interface UnlockStatus {
|
|
|
66
66
|
username?: string;
|
|
67
67
|
completedActions?: CompleteOptions[];
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Server-side verification status
|
|
71
|
+
*/
|
|
72
|
+
interface VerificationStatus {
|
|
73
|
+
verified: boolean;
|
|
74
|
+
userId: string;
|
|
75
|
+
completedAt?: string;
|
|
76
|
+
actions?: Array<{
|
|
77
|
+
action: string;
|
|
78
|
+
target: string;
|
|
79
|
+
}>;
|
|
80
|
+
}
|
|
69
81
|
/**
|
|
70
82
|
* FollowGate SDK Client
|
|
71
83
|
*/
|
|
@@ -130,6 +142,18 @@ declare class FollowGateClient {
|
|
|
130
142
|
isUnlocked(): boolean;
|
|
131
143
|
getUnlockStatus(): UnlockStatus;
|
|
132
144
|
getCompletedActions(): CompleteOptions[];
|
|
145
|
+
/**
|
|
146
|
+
* Check if user is verified server-side
|
|
147
|
+
* Requires userId to be set in config
|
|
148
|
+
* @returns Promise<boolean> - true if verified, false otherwise
|
|
149
|
+
*/
|
|
150
|
+
isVerified(): Promise<boolean>;
|
|
151
|
+
/**
|
|
152
|
+
* Get full verification status from server
|
|
153
|
+
* Requires userId to be set in config
|
|
154
|
+
* @returns Promise<VerificationStatus> - full verification details
|
|
155
|
+
*/
|
|
156
|
+
getVerificationStatus(): Promise<VerificationStatus>;
|
|
133
157
|
on(event: EventType, callback: EventCallback): void;
|
|
134
158
|
off(event: EventType, callback: EventCallback): void;
|
|
135
159
|
/**
|
|
@@ -139,6 +163,11 @@ declare class FollowGateClient {
|
|
|
139
163
|
private getStorageKey;
|
|
140
164
|
private restoreSession;
|
|
141
165
|
private saveCompletedActions;
|
|
166
|
+
/**
|
|
167
|
+
* Save completion to server for verification
|
|
168
|
+
* Only works if userId is set in config
|
|
169
|
+
*/
|
|
170
|
+
private saveCompletion;
|
|
142
171
|
private buildIntentUrl;
|
|
143
172
|
private buildTwitterUrl;
|
|
144
173
|
private buildBlueskyUrl;
|
|
@@ -148,4 +177,4 @@ declare class FollowGateClient {
|
|
|
148
177
|
}
|
|
149
178
|
declare const FollowGate: FollowGateClient;
|
|
150
179
|
|
|
151
|
-
export { type CompleteOptions, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, FollowGateError, type Platform, type SocialAction, type TwitterConfig, type UnlockStatus, type UserInfo };
|
|
180
|
+
export { type CompleteOptions, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, FollowGateError, type Platform, type SocialAction, type TwitterConfig, type UnlockStatus, type UserInfo, type VerificationStatus };
|
package/dist/index.d.ts
CHANGED
|
@@ -66,6 +66,18 @@ interface UnlockStatus {
|
|
|
66
66
|
username?: string;
|
|
67
67
|
completedActions?: CompleteOptions[];
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Server-side verification status
|
|
71
|
+
*/
|
|
72
|
+
interface VerificationStatus {
|
|
73
|
+
verified: boolean;
|
|
74
|
+
userId: string;
|
|
75
|
+
completedAt?: string;
|
|
76
|
+
actions?: Array<{
|
|
77
|
+
action: string;
|
|
78
|
+
target: string;
|
|
79
|
+
}>;
|
|
80
|
+
}
|
|
69
81
|
/**
|
|
70
82
|
* FollowGate SDK Client
|
|
71
83
|
*/
|
|
@@ -130,6 +142,18 @@ declare class FollowGateClient {
|
|
|
130
142
|
isUnlocked(): boolean;
|
|
131
143
|
getUnlockStatus(): UnlockStatus;
|
|
132
144
|
getCompletedActions(): CompleteOptions[];
|
|
145
|
+
/**
|
|
146
|
+
* Check if user is verified server-side
|
|
147
|
+
* Requires userId to be set in config
|
|
148
|
+
* @returns Promise<boolean> - true if verified, false otherwise
|
|
149
|
+
*/
|
|
150
|
+
isVerified(): Promise<boolean>;
|
|
151
|
+
/**
|
|
152
|
+
* Get full verification status from server
|
|
153
|
+
* Requires userId to be set in config
|
|
154
|
+
* @returns Promise<VerificationStatus> - full verification details
|
|
155
|
+
*/
|
|
156
|
+
getVerificationStatus(): Promise<VerificationStatus>;
|
|
133
157
|
on(event: EventType, callback: EventCallback): void;
|
|
134
158
|
off(event: EventType, callback: EventCallback): void;
|
|
135
159
|
/**
|
|
@@ -139,6 +163,11 @@ declare class FollowGateClient {
|
|
|
139
163
|
private getStorageKey;
|
|
140
164
|
private restoreSession;
|
|
141
165
|
private saveCompletedActions;
|
|
166
|
+
/**
|
|
167
|
+
* Save completion to server for verification
|
|
168
|
+
* Only works if userId is set in config
|
|
169
|
+
*/
|
|
170
|
+
private saveCompletion;
|
|
142
171
|
private buildIntentUrl;
|
|
143
172
|
private buildTwitterUrl;
|
|
144
173
|
private buildBlueskyUrl;
|
|
@@ -148,4 +177,4 @@ declare class FollowGateClient {
|
|
|
148
177
|
}
|
|
149
178
|
declare const FollowGate: FollowGateClient;
|
|
150
179
|
|
|
151
|
-
export { type CompleteOptions, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, FollowGateError, type Platform, type SocialAction, type TwitterConfig, type UnlockStatus, type UserInfo };
|
|
180
|
+
export { type CompleteOptions, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, FollowGateError, type Platform, type SocialAction, type TwitterConfig, type UnlockStatus, type UserInfo, type VerificationStatus };
|
package/dist/index.js
CHANGED
|
@@ -865,7 +865,10 @@ var FollowGateClient = class {
|
|
|
865
865
|
platform
|
|
866
866
|
};
|
|
867
867
|
if (typeof localStorage !== "undefined") {
|
|
868
|
-
localStorage.setItem(
|
|
868
|
+
localStorage.setItem(
|
|
869
|
+
this.getStorageKey("followgate_user"),
|
|
870
|
+
JSON.stringify(this.currentUser)
|
|
871
|
+
);
|
|
869
872
|
}
|
|
870
873
|
if (this.config.debug) {
|
|
871
874
|
console.log("[FollowGate] Username set:", normalizedUsername);
|
|
@@ -959,6 +962,7 @@ var FollowGateClient = class {
|
|
|
959
962
|
if (typeof localStorage !== "undefined") {
|
|
960
963
|
localStorage.setItem(this.getStorageKey("followgate_unlocked"), "true");
|
|
961
964
|
}
|
|
965
|
+
await this.saveCompletion();
|
|
962
966
|
await this.trackEvent("gate_unlocked", {
|
|
963
967
|
username: this.currentUser?.username,
|
|
964
968
|
actions: this.completedActions
|
|
@@ -986,6 +990,90 @@ var FollowGateClient = class {
|
|
|
986
990
|
return [...this.completedActions];
|
|
987
991
|
}
|
|
988
992
|
// ============================================
|
|
993
|
+
// Server-Side Verification
|
|
994
|
+
// ============================================
|
|
995
|
+
/**
|
|
996
|
+
* Check if user is verified server-side
|
|
997
|
+
* Requires userId to be set in config
|
|
998
|
+
* @returns Promise<boolean> - true if verified, false otherwise
|
|
999
|
+
*/
|
|
1000
|
+
async isVerified() {
|
|
1001
|
+
if (!this.config) {
|
|
1002
|
+
throw new Error("[FollowGate] SDK not initialized. Call init() first.");
|
|
1003
|
+
}
|
|
1004
|
+
if (!this.config.userId) {
|
|
1005
|
+
if (this.config.debug) {
|
|
1006
|
+
console.warn("[FollowGate] isVerified() requires userId to be set");
|
|
1007
|
+
}
|
|
1008
|
+
return false;
|
|
1009
|
+
}
|
|
1010
|
+
try {
|
|
1011
|
+
const response = await fetch(
|
|
1012
|
+
`${this.config.apiUrl}/api/v1/completions/verify/${encodeURIComponent(this.config.userId)}`,
|
|
1013
|
+
{
|
|
1014
|
+
headers: {
|
|
1015
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
);
|
|
1019
|
+
if (!response.ok) {
|
|
1020
|
+
if (this.config.debug) {
|
|
1021
|
+
console.warn("[FollowGate] Verification check failed:", response.status);
|
|
1022
|
+
}
|
|
1023
|
+
return false;
|
|
1024
|
+
}
|
|
1025
|
+
const data = await response.json();
|
|
1026
|
+
return data.data?.verified === true;
|
|
1027
|
+
} catch (error) {
|
|
1028
|
+
if (this.config.debug) {
|
|
1029
|
+
console.warn("[FollowGate] Verification check error:", error);
|
|
1030
|
+
}
|
|
1031
|
+
return false;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Get full verification status from server
|
|
1036
|
+
* Requires userId to be set in config
|
|
1037
|
+
* @returns Promise<VerificationStatus> - full verification details
|
|
1038
|
+
*/
|
|
1039
|
+
async getVerificationStatus() {
|
|
1040
|
+
if (!this.config) {
|
|
1041
|
+
throw new Error("[FollowGate] SDK not initialized. Call init() first.");
|
|
1042
|
+
}
|
|
1043
|
+
if (!this.config.userId) {
|
|
1044
|
+
return {
|
|
1045
|
+
verified: false,
|
|
1046
|
+
userId: ""
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
try {
|
|
1050
|
+
const response = await fetch(
|
|
1051
|
+
`${this.config.apiUrl}/api/v1/completions/verify/${encodeURIComponent(this.config.userId)}`,
|
|
1052
|
+
{
|
|
1053
|
+
headers: {
|
|
1054
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
);
|
|
1058
|
+
if (!response.ok) {
|
|
1059
|
+
return {
|
|
1060
|
+
verified: false,
|
|
1061
|
+
userId: this.config.userId
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
const data = await response.json();
|
|
1065
|
+
return data.data;
|
|
1066
|
+
} catch (error) {
|
|
1067
|
+
if (this.config.debug) {
|
|
1068
|
+
console.warn("[FollowGate] getVerificationStatus error:", error);
|
|
1069
|
+
}
|
|
1070
|
+
return {
|
|
1071
|
+
verified: false,
|
|
1072
|
+
userId: this.config.userId
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
// ============================================
|
|
989
1077
|
// Event System
|
|
990
1078
|
// ============================================
|
|
991
1079
|
on(event, callback) {
|
|
@@ -1012,7 +1100,9 @@ var FollowGateClient = class {
|
|
|
1012
1100
|
}
|
|
1013
1101
|
restoreSession() {
|
|
1014
1102
|
if (typeof localStorage === "undefined") return;
|
|
1015
|
-
const userJson = localStorage.getItem(
|
|
1103
|
+
const userJson = localStorage.getItem(
|
|
1104
|
+
this.getStorageKey("followgate_user")
|
|
1105
|
+
);
|
|
1016
1106
|
if (userJson) {
|
|
1017
1107
|
try {
|
|
1018
1108
|
this.currentUser = JSON.parse(userJson);
|
|
@@ -1020,7 +1110,9 @@ var FollowGateClient = class {
|
|
|
1020
1110
|
localStorage.removeItem(this.getStorageKey("followgate_user"));
|
|
1021
1111
|
}
|
|
1022
1112
|
}
|
|
1023
|
-
const actionsJson = localStorage.getItem(
|
|
1113
|
+
const actionsJson = localStorage.getItem(
|
|
1114
|
+
this.getStorageKey("followgate_actions")
|
|
1115
|
+
);
|
|
1024
1116
|
if (actionsJson) {
|
|
1025
1117
|
try {
|
|
1026
1118
|
this.completedActions = JSON.parse(actionsJson);
|
|
@@ -1037,6 +1129,43 @@ var FollowGateClient = class {
|
|
|
1037
1129
|
);
|
|
1038
1130
|
}
|
|
1039
1131
|
}
|
|
1132
|
+
/**
|
|
1133
|
+
* Save completion to server for verification
|
|
1134
|
+
* Only works if userId is set in config
|
|
1135
|
+
*/
|
|
1136
|
+
async saveCompletion() {
|
|
1137
|
+
if (!this.config?.userId) {
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
try {
|
|
1141
|
+
const response = await fetch(`${this.config.apiUrl}/api/v1/completions`, {
|
|
1142
|
+
method: "POST",
|
|
1143
|
+
headers: {
|
|
1144
|
+
"Content-Type": "application/json",
|
|
1145
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
1146
|
+
},
|
|
1147
|
+
body: JSON.stringify({
|
|
1148
|
+
userId: this.config.userId,
|
|
1149
|
+
platform: this.currentUser?.platform || "twitter",
|
|
1150
|
+
actions: this.completedActions.map((a) => ({
|
|
1151
|
+
action: a.action,
|
|
1152
|
+
target: a.target
|
|
1153
|
+
}))
|
|
1154
|
+
})
|
|
1155
|
+
});
|
|
1156
|
+
if (this.config.debug) {
|
|
1157
|
+
if (response.ok) {
|
|
1158
|
+
console.log("[FollowGate] Completion saved to server");
|
|
1159
|
+
} else {
|
|
1160
|
+
console.warn("[FollowGate] Failed to save completion:", response.status);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
} catch (error) {
|
|
1164
|
+
if (this.config.debug) {
|
|
1165
|
+
console.warn("[FollowGate] Failed to save completion:", error);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1040
1169
|
buildIntentUrl(options) {
|
|
1041
1170
|
const { platform, action, target } = options;
|
|
1042
1171
|
switch (platform) {
|
package/dist/index.mjs
CHANGED
|
@@ -839,7 +839,10 @@ var FollowGateClient = class {
|
|
|
839
839
|
platform
|
|
840
840
|
};
|
|
841
841
|
if (typeof localStorage !== "undefined") {
|
|
842
|
-
localStorage.setItem(
|
|
842
|
+
localStorage.setItem(
|
|
843
|
+
this.getStorageKey("followgate_user"),
|
|
844
|
+
JSON.stringify(this.currentUser)
|
|
845
|
+
);
|
|
843
846
|
}
|
|
844
847
|
if (this.config.debug) {
|
|
845
848
|
console.log("[FollowGate] Username set:", normalizedUsername);
|
|
@@ -933,6 +936,7 @@ var FollowGateClient = class {
|
|
|
933
936
|
if (typeof localStorage !== "undefined") {
|
|
934
937
|
localStorage.setItem(this.getStorageKey("followgate_unlocked"), "true");
|
|
935
938
|
}
|
|
939
|
+
await this.saveCompletion();
|
|
936
940
|
await this.trackEvent("gate_unlocked", {
|
|
937
941
|
username: this.currentUser?.username,
|
|
938
942
|
actions: this.completedActions
|
|
@@ -960,6 +964,90 @@ var FollowGateClient = class {
|
|
|
960
964
|
return [...this.completedActions];
|
|
961
965
|
}
|
|
962
966
|
// ============================================
|
|
967
|
+
// Server-Side Verification
|
|
968
|
+
// ============================================
|
|
969
|
+
/**
|
|
970
|
+
* Check if user is verified server-side
|
|
971
|
+
* Requires userId to be set in config
|
|
972
|
+
* @returns Promise<boolean> - true if verified, false otherwise
|
|
973
|
+
*/
|
|
974
|
+
async isVerified() {
|
|
975
|
+
if (!this.config) {
|
|
976
|
+
throw new Error("[FollowGate] SDK not initialized. Call init() first.");
|
|
977
|
+
}
|
|
978
|
+
if (!this.config.userId) {
|
|
979
|
+
if (this.config.debug) {
|
|
980
|
+
console.warn("[FollowGate] isVerified() requires userId to be set");
|
|
981
|
+
}
|
|
982
|
+
return false;
|
|
983
|
+
}
|
|
984
|
+
try {
|
|
985
|
+
const response = await fetch(
|
|
986
|
+
`${this.config.apiUrl}/api/v1/completions/verify/${encodeURIComponent(this.config.userId)}`,
|
|
987
|
+
{
|
|
988
|
+
headers: {
|
|
989
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
);
|
|
993
|
+
if (!response.ok) {
|
|
994
|
+
if (this.config.debug) {
|
|
995
|
+
console.warn("[FollowGate] Verification check failed:", response.status);
|
|
996
|
+
}
|
|
997
|
+
return false;
|
|
998
|
+
}
|
|
999
|
+
const data = await response.json();
|
|
1000
|
+
return data.data?.verified === true;
|
|
1001
|
+
} catch (error) {
|
|
1002
|
+
if (this.config.debug) {
|
|
1003
|
+
console.warn("[FollowGate] Verification check error:", error);
|
|
1004
|
+
}
|
|
1005
|
+
return false;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Get full verification status from server
|
|
1010
|
+
* Requires userId to be set in config
|
|
1011
|
+
* @returns Promise<VerificationStatus> - full verification details
|
|
1012
|
+
*/
|
|
1013
|
+
async getVerificationStatus() {
|
|
1014
|
+
if (!this.config) {
|
|
1015
|
+
throw new Error("[FollowGate] SDK not initialized. Call init() first.");
|
|
1016
|
+
}
|
|
1017
|
+
if (!this.config.userId) {
|
|
1018
|
+
return {
|
|
1019
|
+
verified: false,
|
|
1020
|
+
userId: ""
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
try {
|
|
1024
|
+
const response = await fetch(
|
|
1025
|
+
`${this.config.apiUrl}/api/v1/completions/verify/${encodeURIComponent(this.config.userId)}`,
|
|
1026
|
+
{
|
|
1027
|
+
headers: {
|
|
1028
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
);
|
|
1032
|
+
if (!response.ok) {
|
|
1033
|
+
return {
|
|
1034
|
+
verified: false,
|
|
1035
|
+
userId: this.config.userId
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
const data = await response.json();
|
|
1039
|
+
return data.data;
|
|
1040
|
+
} catch (error) {
|
|
1041
|
+
if (this.config.debug) {
|
|
1042
|
+
console.warn("[FollowGate] getVerificationStatus error:", error);
|
|
1043
|
+
}
|
|
1044
|
+
return {
|
|
1045
|
+
verified: false,
|
|
1046
|
+
userId: this.config.userId
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
// ============================================
|
|
963
1051
|
// Event System
|
|
964
1052
|
// ============================================
|
|
965
1053
|
on(event, callback) {
|
|
@@ -986,7 +1074,9 @@ var FollowGateClient = class {
|
|
|
986
1074
|
}
|
|
987
1075
|
restoreSession() {
|
|
988
1076
|
if (typeof localStorage === "undefined") return;
|
|
989
|
-
const userJson = localStorage.getItem(
|
|
1077
|
+
const userJson = localStorage.getItem(
|
|
1078
|
+
this.getStorageKey("followgate_user")
|
|
1079
|
+
);
|
|
990
1080
|
if (userJson) {
|
|
991
1081
|
try {
|
|
992
1082
|
this.currentUser = JSON.parse(userJson);
|
|
@@ -994,7 +1084,9 @@ var FollowGateClient = class {
|
|
|
994
1084
|
localStorage.removeItem(this.getStorageKey("followgate_user"));
|
|
995
1085
|
}
|
|
996
1086
|
}
|
|
997
|
-
const actionsJson = localStorage.getItem(
|
|
1087
|
+
const actionsJson = localStorage.getItem(
|
|
1088
|
+
this.getStorageKey("followgate_actions")
|
|
1089
|
+
);
|
|
998
1090
|
if (actionsJson) {
|
|
999
1091
|
try {
|
|
1000
1092
|
this.completedActions = JSON.parse(actionsJson);
|
|
@@ -1011,6 +1103,43 @@ var FollowGateClient = class {
|
|
|
1011
1103
|
);
|
|
1012
1104
|
}
|
|
1013
1105
|
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Save completion to server for verification
|
|
1108
|
+
* Only works if userId is set in config
|
|
1109
|
+
*/
|
|
1110
|
+
async saveCompletion() {
|
|
1111
|
+
if (!this.config?.userId) {
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
try {
|
|
1115
|
+
const response = await fetch(`${this.config.apiUrl}/api/v1/completions`, {
|
|
1116
|
+
method: "POST",
|
|
1117
|
+
headers: {
|
|
1118
|
+
"Content-Type": "application/json",
|
|
1119
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
1120
|
+
},
|
|
1121
|
+
body: JSON.stringify({
|
|
1122
|
+
userId: this.config.userId,
|
|
1123
|
+
platform: this.currentUser?.platform || "twitter",
|
|
1124
|
+
actions: this.completedActions.map((a) => ({
|
|
1125
|
+
action: a.action,
|
|
1126
|
+
target: a.target
|
|
1127
|
+
}))
|
|
1128
|
+
})
|
|
1129
|
+
});
|
|
1130
|
+
if (this.config.debug) {
|
|
1131
|
+
if (response.ok) {
|
|
1132
|
+
console.log("[FollowGate] Completion saved to server");
|
|
1133
|
+
} else {
|
|
1134
|
+
console.warn("[FollowGate] Failed to save completion:", response.status);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
} catch (error) {
|
|
1138
|
+
if (this.config.debug) {
|
|
1139
|
+
console.warn("[FollowGate] Failed to save completion:", error);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1014
1143
|
buildIntentUrl(options) {
|
|
1015
1144
|
const { platform, action, target } = options;
|
|
1016
1145
|
switch (platform) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@followgate/js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "FollowGate SDK - Grow your audience with every download. Require social actions (follow, repost) before users can access your app.",
|
|
5
5
|
"author": "FollowGate <hello@followgate.app>",
|
|
6
6
|
"homepage": "https://followgate.app",
|