@devvit/reddit 0.11.17-next-2025-05-28-417d95f5a.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/LICENSE +26 -0
- package/README.md +5 -0
- package/RedditClient.d.ts +1155 -0
- package/RedditClient.d.ts.map +1 -0
- package/RedditClient.js +1417 -0
- package/common.d.ts +10 -0
- package/common.d.ts.map +1 -0
- package/common.js +5 -0
- package/getReddit.d.ts +3 -0
- package/getReddit.d.ts.map +1 -0
- package/getReddit.js +8 -0
- package/getRedditApiPlugins.d.ts +23 -0
- package/getRedditApiPlugins.d.ts.map +1 -0
- package/getRedditApiPlugins.js +25 -0
- package/getUserActionsPlugin.d.ts +6 -0
- package/getUserActionsPlugin.d.ts.map +1 -0
- package/getUserActionsPlugin.js +12 -0
- package/graphql/GraphQL.d.ts +10 -0
- package/graphql/GraphQL.d.ts.map +1 -0
- package/graphql/GraphQL.js +27 -0
- package/helpers/makeGettersEnumerable.d.ts +2 -0
- package/helpers/makeGettersEnumerable.d.ts.map +1 -0
- package/helpers/makeGettersEnumerable.js +19 -0
- package/helpers/permissions.d.ts +6 -0
- package/helpers/permissions.d.ts.map +1 -0
- package/helpers/permissions.js +24 -0
- package/helpers/richtextToString.d.ts +3 -0
- package/helpers/richtextToString.d.ts.map +1 -0
- package/helpers/richtextToString.js +14 -0
- package/helpers/textFallbackToRichtext.d.ts +4 -0
- package/helpers/textFallbackToRichtext.d.ts.map +1 -0
- package/helpers/textFallbackToRichtext.js +14 -0
- package/index.d.ts +3 -0
- package/index.d.ts.map +1 -0
- package/index.js +1 -0
- package/models/Comment.d.ts +138 -0
- package/models/Comment.d.ts.map +1 -0
- package/models/Comment.js +597 -0
- package/models/Flair.d.ts +171 -0
- package/models/Flair.d.ts.map +1 -0
- package/models/Flair.js +293 -0
- package/models/Listing.d.ts +53 -0
- package/models/Listing.d.ts.map +1 -0
- package/models/Listing.js +101 -0
- package/models/ModAction.d.ts +32 -0
- package/models/ModAction.d.ts.map +1 -0
- package/models/ModAction.js +70 -0
- package/models/ModMail.d.ts +655 -0
- package/models/ModMail.d.ts.map +1 -0
- package/models/ModMail.js +723 -0
- package/models/ModNote.d.ts +57 -0
- package/models/ModNote.d.ts.map +1 -0
- package/models/ModNote.js +103 -0
- package/models/Post.d.ts +491 -0
- package/models/Post.d.ts.map +1 -0
- package/models/Post.js +1022 -0
- package/models/PrivateMessage.d.ts +52 -0
- package/models/PrivateMessage.d.ts.map +1 -0
- package/models/PrivateMessage.js +126 -0
- package/models/Subreddit.d.ts +606 -0
- package/models/Subreddit.d.ts.map +1 -0
- package/models/Subreddit.js +750 -0
- package/models/User.d.ts +238 -0
- package/models/User.d.ts.map +1 -0
- package/models/User.js +458 -0
- package/models/Vault.d.ts +32 -0
- package/models/Vault.d.ts.map +1 -0
- package/models/Vault.js +25 -0
- package/models/Widget.d.ts +133 -0
- package/models/Widget.d.ts.map +1 -0
- package/models/Widget.js +467 -0
- package/models/WikiPage.d.ts +137 -0
- package/models/WikiPage.d.ts.map +1 -0
- package/models/WikiPage.js +329 -0
- package/models/index.d.ts +14 -0
- package/models/index.d.ts.map +1 -0
- package/models/index.js +13 -0
- package/package.json +46 -0
- package/tests/comment.api.test.d.ts.map +1 -0
- package/tests/flair.api.test.d.ts.map +1 -0
- package/tests/modmail.api.test.d.ts.map +1 -0
- package/tests/modnote.api.test.d.ts.map +1 -0
- package/tests/post.api.test.d.ts.map +1 -0
- package/tests/subreddit.api.test.d.ts.map +1 -0
- package/tests/user.api.test.d.ts.map +1 -0
- package/tests/utils/createTestPreview.d.ts +2 -0
- package/tests/utils/createTestPreview.d.ts.map +1 -0
- package/tests/utils/createTestPreview.js +5 -0
- package/tests/utils/redditApiPluginsMock.d.ts +203 -0
- package/tests/utils/redditApiPluginsMock.d.ts.map +1 -0
- package/tests/utils/redditApiPluginsMock.js +202 -0
- package/tests/utils/runWithTestContext.d.ts +4 -0
- package/tests/utils/runWithTestContext.d.ts.map +1 -0
- package/tests/utils/runWithTestContext.js +12 -0
- package/tests/utils/userActionsPluginMock.d.ts +6 -0
- package/tests/utils/userActionsPluginMock.d.ts.map +1 -0
- package/tests/utils/userActionsPluginMock.js +5 -0
package/models/User.js
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _a, _User_id, _User_username, _User_createdAt, _User_linkKarma, _User_commentKarma, _User_nsfw, _User_isAdmin, _User_modPermissionsBySubreddit, _User_url, _User_permalink, _User_hasVerifiedEmail, _User_metadata_get;
|
|
13
|
+
import { getContext } from '@devvit/server';
|
|
14
|
+
import { assertNonNull } from '@devvit/shared-types/NonNull.js';
|
|
15
|
+
import { asT2ID, isT2ID } from '@devvit/shared-types/tid.js';
|
|
16
|
+
import { getRedditApiPlugins } from '../getRedditApiPlugins.js';
|
|
17
|
+
import { GraphQL } from '../graphql/GraphQL.js';
|
|
18
|
+
import { makeGettersEnumerable } from '../helpers/makeGettersEnumerable.js';
|
|
19
|
+
import { formatModeratorPermissions, validModPermissions } from '../helpers/permissions.js';
|
|
20
|
+
import { Comment } from './Comment.js';
|
|
21
|
+
import { convertUserFlairProtoToAPI, Flair } from './Flair.js';
|
|
22
|
+
import { Listing } from './Listing.js';
|
|
23
|
+
import { Post } from './Post.js';
|
|
24
|
+
export var SocialLinkType;
|
|
25
|
+
(function (SocialLinkType) {
|
|
26
|
+
SocialLinkType["Custom"] = "CUSTOM";
|
|
27
|
+
SocialLinkType["Reddit"] = "REDDIT";
|
|
28
|
+
SocialLinkType["Instagram"] = "INSTAGRAM";
|
|
29
|
+
SocialLinkType["Twitter"] = "TWITTER";
|
|
30
|
+
SocialLinkType["Tiktok"] = "TIKTOK";
|
|
31
|
+
SocialLinkType["Twitch"] = "TWITCH";
|
|
32
|
+
SocialLinkType["Facebook"] = "FACEBOOK";
|
|
33
|
+
SocialLinkType["Youtube"] = "YOUTUBE";
|
|
34
|
+
SocialLinkType["Tumblr"] = "TUMBLR";
|
|
35
|
+
SocialLinkType["Spotify"] = "SPOTIFY";
|
|
36
|
+
SocialLinkType["Soundcloud"] = "SOUNDCLOUD";
|
|
37
|
+
SocialLinkType["Beacons"] = "BEACONS";
|
|
38
|
+
SocialLinkType["Linktree"] = "LINKTREE";
|
|
39
|
+
SocialLinkType["Discord"] = "DISCORD";
|
|
40
|
+
SocialLinkType["Venmo"] = "VENMO";
|
|
41
|
+
SocialLinkType["CashApp"] = "CASH_APP";
|
|
42
|
+
SocialLinkType["Patreon"] = "PATREON";
|
|
43
|
+
SocialLinkType["Kofi"] = "KOFI";
|
|
44
|
+
SocialLinkType["Paypal"] = "PAYPAL";
|
|
45
|
+
SocialLinkType["Cameo"] = "CAMEO";
|
|
46
|
+
SocialLinkType["Onlyfans"] = "ONLYFANS";
|
|
47
|
+
SocialLinkType["Substack"] = "SUBSTACK";
|
|
48
|
+
SocialLinkType["Kickstarter"] = "KICKSTARTER";
|
|
49
|
+
SocialLinkType["Indiegogo"] = "INDIEGOGO";
|
|
50
|
+
SocialLinkType["BuyMeACoffee"] = "BUY_ME_A_COFFEE";
|
|
51
|
+
SocialLinkType["Shopify"] = "SHOPIFY";
|
|
52
|
+
})(SocialLinkType || (SocialLinkType = {}));
|
|
53
|
+
/**
|
|
54
|
+
* A class representing a user.
|
|
55
|
+
*/
|
|
56
|
+
export class User {
|
|
57
|
+
/**
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
constructor(data) {
|
|
61
|
+
_User_id.set(this, void 0);
|
|
62
|
+
_User_username.set(this, void 0);
|
|
63
|
+
_User_createdAt.set(this, void 0);
|
|
64
|
+
_User_linkKarma.set(this, void 0);
|
|
65
|
+
_User_commentKarma.set(this, void 0);
|
|
66
|
+
_User_nsfw.set(this, void 0);
|
|
67
|
+
_User_isAdmin.set(this, void 0);
|
|
68
|
+
_User_modPermissionsBySubreddit.set(this, new Map());
|
|
69
|
+
// R2 bug: user.url is a permalink path
|
|
70
|
+
_User_url.set(this, void 0);
|
|
71
|
+
// R2 bug: user object does not contain a permalink field
|
|
72
|
+
_User_permalink.set(this, void 0);
|
|
73
|
+
_User_hasVerifiedEmail.set(this, void 0);
|
|
74
|
+
makeGettersEnumerable(this);
|
|
75
|
+
assertNonNull(data.id, 'User ID is missing or undefined');
|
|
76
|
+
assertNonNull(data.name, 'Username is missing or undefined');
|
|
77
|
+
assertNonNull(data.createdUtc, 'User is missing created date');
|
|
78
|
+
// UserDataByAccountIds returns the ID without the t2_ prefix
|
|
79
|
+
__classPrivateFieldSet(this, _User_id, asT2ID(isT2ID(data.id) ? data.id : `t2_${data.id}`), "f");
|
|
80
|
+
__classPrivateFieldSet(this, _User_username, data.name, "f");
|
|
81
|
+
__classPrivateFieldSet(this, _User_nsfw, data.over18 ?? false, "f");
|
|
82
|
+
__classPrivateFieldSet(this, _User_isAdmin, data.isEmployee ?? false, "f");
|
|
83
|
+
const createdAt = new Date(0);
|
|
84
|
+
createdAt.setUTCSeconds(data.createdUtc);
|
|
85
|
+
__classPrivateFieldSet(this, _User_createdAt, createdAt, "f");
|
|
86
|
+
__classPrivateFieldSet(this, _User_linkKarma, data.linkKarma ?? 0, "f");
|
|
87
|
+
__classPrivateFieldSet(this, _User_commentKarma, data.commentKarma ?? 0, "f");
|
|
88
|
+
if (data.modPermissions) {
|
|
89
|
+
for (const [subredditName, permissions] of Object.entries(data.modPermissions)) {
|
|
90
|
+
__classPrivateFieldGet(this, _User_modPermissionsBySubreddit, "f").set(subredditName, validModPermissions(permissions));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
__classPrivateFieldSet(this, _User_url, new URL(data.subreddit?.url ?? '', 'https://www.reddit.com').toString(), "f");
|
|
94
|
+
__classPrivateFieldSet(this, _User_permalink, data.subreddit?.url ?? '', "f");
|
|
95
|
+
__classPrivateFieldSet(this, _User_hasVerifiedEmail, data.hasVerifiedEmail ?? false, "f");
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The ID (starting with t2_) of the user to retrieve.
|
|
99
|
+
* @example 't2_1w72'
|
|
100
|
+
*/
|
|
101
|
+
get id() {
|
|
102
|
+
return __classPrivateFieldGet(this, _User_id, "f");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The username of the user omitting the u/.
|
|
106
|
+
* @example 'spez'
|
|
107
|
+
*/
|
|
108
|
+
get username() {
|
|
109
|
+
return __classPrivateFieldGet(this, _User_username, "f");
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The date the user was created.
|
|
113
|
+
*/
|
|
114
|
+
get createdAt() {
|
|
115
|
+
return __classPrivateFieldGet(this, _User_createdAt, "f");
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The amount of link karma the user has.
|
|
119
|
+
*/
|
|
120
|
+
get linkKarma() {
|
|
121
|
+
return __classPrivateFieldGet(this, _User_linkKarma, "f");
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The amount of comment karma the user has.
|
|
125
|
+
*/
|
|
126
|
+
get commentKarma() {
|
|
127
|
+
return __classPrivateFieldGet(this, _User_commentKarma, "f");
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Whether the user's profile is marked as NSFW (Not Safe For Work).
|
|
131
|
+
*/
|
|
132
|
+
get nsfw() {
|
|
133
|
+
return __classPrivateFieldGet(this, _User_nsfw, "f");
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Whether the user is admin.
|
|
137
|
+
*/
|
|
138
|
+
get isAdmin() {
|
|
139
|
+
return __classPrivateFieldGet(this, _User_isAdmin, "f");
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The permissions the user has on the subreddit.
|
|
143
|
+
*/
|
|
144
|
+
get modPermissions() {
|
|
145
|
+
return __classPrivateFieldGet(this, _User_modPermissionsBySubreddit, "f");
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Returns the HTTP URL for the user
|
|
149
|
+
*/
|
|
150
|
+
get url() {
|
|
151
|
+
return __classPrivateFieldGet(this, _User_url, "f");
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Returns a permalink path relative to https://www.reddit.com
|
|
155
|
+
*/
|
|
156
|
+
get permalink() {
|
|
157
|
+
return __classPrivateFieldGet(this, _User_permalink, "f");
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Indicates whether or not the user has verified their email address.
|
|
161
|
+
*/
|
|
162
|
+
get hasVerifiedEmail() {
|
|
163
|
+
return __classPrivateFieldGet(this, _User_hasVerifiedEmail, "f");
|
|
164
|
+
}
|
|
165
|
+
toJSON() {
|
|
166
|
+
return {
|
|
167
|
+
id: this.id,
|
|
168
|
+
username: this.username,
|
|
169
|
+
createdAt: this.createdAt,
|
|
170
|
+
linkKarma: this.linkKarma,
|
|
171
|
+
commentKarma: this.commentKarma,
|
|
172
|
+
nsfw: this.nsfw,
|
|
173
|
+
modPermissionsBySubreddit: Object.fromEntries(this.modPermissions),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get the mod permissions the user has on the subreddit if they are a moderator.
|
|
178
|
+
*
|
|
179
|
+
* @param subredditName - name of the subreddit
|
|
180
|
+
* @returns the moderator permissions the user has on the subreddit
|
|
181
|
+
*/
|
|
182
|
+
async getModPermissionsForSubreddit(subredditName) {
|
|
183
|
+
if (__classPrivateFieldGet(this, _User_modPermissionsBySubreddit, "f").has(subredditName)) {
|
|
184
|
+
return __classPrivateFieldGet(this, _User_modPermissionsBySubreddit, "f").get(subredditName);
|
|
185
|
+
}
|
|
186
|
+
const mods = await _a.getSubredditUsersByType({
|
|
187
|
+
subredditName,
|
|
188
|
+
type: 'moderators',
|
|
189
|
+
username: this.username,
|
|
190
|
+
}).all();
|
|
191
|
+
if (mods.length === 0) {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
const permissions = mods[0].modPermissions.get(subredditName) ?? [];
|
|
195
|
+
if (permissions.length > 0) {
|
|
196
|
+
__classPrivateFieldGet(this, _User_modPermissionsBySubreddit, "f").set(subredditName, permissions);
|
|
197
|
+
}
|
|
198
|
+
return permissions;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get the user's comments.
|
|
202
|
+
*
|
|
203
|
+
* @param options - Options for the request
|
|
204
|
+
* @param options.sort - The sort order of the comments. e.g. 'new'
|
|
205
|
+
* @param options.timeframe - The timeframe of the comments. e.g. 'all'
|
|
206
|
+
* @param options.limit - The maximum number of comments to return. e.g. 1000
|
|
207
|
+
* @param options.pageSize - The number of comments to return per request. e.g. 100
|
|
208
|
+
* @returns A Listing of Comment objects.
|
|
209
|
+
*/
|
|
210
|
+
getComments(options) {
|
|
211
|
+
return Comment.getCommentsByUser({
|
|
212
|
+
username: this.username,
|
|
213
|
+
...options,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get the user's posts.
|
|
218
|
+
*
|
|
219
|
+
* @param options - Options for the request
|
|
220
|
+
* @param options.sort - The sort order of the posts. e.g. 'new'
|
|
221
|
+
* @param options.timeframe - The timeframe of the posts. e.g. 'all'
|
|
222
|
+
* @param options.limit - The maximum number of posts to return. e.g. 1000
|
|
223
|
+
* @param options.pageSize - The number of posts to return per request. e.g. 100
|
|
224
|
+
* @returns A Listing of Post objects.
|
|
225
|
+
*/
|
|
226
|
+
getPosts(options) {
|
|
227
|
+
return Post.getPostsByUser({
|
|
228
|
+
username: this.username,
|
|
229
|
+
...options,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Retrieve the user's flair for the subreddit.
|
|
234
|
+
*
|
|
235
|
+
* @param subreddit - The name of the subreddit associated with the user's flair.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```ts
|
|
239
|
+
* const username = "badapple"
|
|
240
|
+
* const subredditName = "mysubreddit"
|
|
241
|
+
* const user = await reddit.getUserByUsername(username);
|
|
242
|
+
* const userFlair = await user.getUserFlairBySubreddit(subredditName);
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
async getUserFlairBySubreddit(subreddit) {
|
|
246
|
+
const userFlairs = await Flair.getUserFlairBySubreddit({
|
|
247
|
+
subreddit,
|
|
248
|
+
name: __classPrivateFieldGet(this, _User_username, "f"),
|
|
249
|
+
});
|
|
250
|
+
return userFlairs.users[0] ? convertUserFlairProtoToAPI(userFlairs.users[0]) : undefined;
|
|
251
|
+
}
|
|
252
|
+
getSnoovatarUrl() {
|
|
253
|
+
return _a.getSnoovatarUrl(this.username);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Gets social links of the user
|
|
257
|
+
*
|
|
258
|
+
* @returns A Promise that resolves an Array of UserSocialLink objects
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* const socialLinks = await user.getSocialLinks();
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
async getSocialLinks() {
|
|
265
|
+
const operationName = 'GetUserSocialLinks';
|
|
266
|
+
const persistedQueryHash = '2aca18ef5f4fc75fb91cdaace3e9aeeae2cb3843b5c26ad511e6f01b8521593a';
|
|
267
|
+
const response = await GraphQL.query(operationName, persistedQueryHash, {
|
|
268
|
+
name: this.username,
|
|
269
|
+
});
|
|
270
|
+
if (!response.data?.user?.profile?.socialLinks) {
|
|
271
|
+
return [];
|
|
272
|
+
}
|
|
273
|
+
return response.data.user.profile.socialLinks.map((link) => ({
|
|
274
|
+
...link,
|
|
275
|
+
handle: link.handle ?? undefined,
|
|
276
|
+
}));
|
|
277
|
+
}
|
|
278
|
+
/** @internal */
|
|
279
|
+
static async getById(id) {
|
|
280
|
+
const username = await getUsernameById(id);
|
|
281
|
+
return username == null ? undefined : _a.getByUsername(username);
|
|
282
|
+
}
|
|
283
|
+
/** @internal */
|
|
284
|
+
static async getByUsername(username) {
|
|
285
|
+
const client = getRedditApiPlugins().Users;
|
|
286
|
+
try {
|
|
287
|
+
const response = await client.UserAbout({ username }, __classPrivateFieldGet(this, _a, "a", _User_metadata_get));
|
|
288
|
+
// suspended accounts 404.
|
|
289
|
+
if (response.data?.id)
|
|
290
|
+
return new _a(response.data);
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
if (error instanceof Error && error.message.includes('404 Not Found')) {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/** @internal */
|
|
300
|
+
static getSubredditUsersByType(options) {
|
|
301
|
+
const client = getRedditApiPlugins().Subreddits;
|
|
302
|
+
return new Listing({
|
|
303
|
+
hasMore: true,
|
|
304
|
+
pageSize: options.pageSize,
|
|
305
|
+
limit: options.limit,
|
|
306
|
+
after: options.after,
|
|
307
|
+
before: options.before,
|
|
308
|
+
fetch: async (fetchOptions) => {
|
|
309
|
+
const response = await client.AboutWhere({
|
|
310
|
+
where: options.type,
|
|
311
|
+
user: options.username,
|
|
312
|
+
subreddit: options.subredditName,
|
|
313
|
+
show: 'all',
|
|
314
|
+
...fetchOptions,
|
|
315
|
+
});
|
|
316
|
+
return listingProtosToUsers(response, options.subredditName);
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
/** @internal */
|
|
321
|
+
static async createRelationship(options) {
|
|
322
|
+
const client = getRedditApiPlugins().Users;
|
|
323
|
+
const { type, subredditName, username, permissions, ...optionalFields } = options;
|
|
324
|
+
const response = await client.Friend({
|
|
325
|
+
type,
|
|
326
|
+
subreddit: subredditName,
|
|
327
|
+
name: username,
|
|
328
|
+
permissions: permissions ? formatModeratorPermissions(permissions) : undefined,
|
|
329
|
+
...optionalFields,
|
|
330
|
+
}, __classPrivateFieldGet(this, _a, "a", _User_metadata_get));
|
|
331
|
+
if (response.json?.errors?.length) {
|
|
332
|
+
throw new Error(response.json.errors.join('\n'));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/** @internal */
|
|
336
|
+
static async removeRelationship(options) {
|
|
337
|
+
const client = getRedditApiPlugins().Users;
|
|
338
|
+
await client.Unfriend({
|
|
339
|
+
type: options.type,
|
|
340
|
+
subreddit: options.subredditName,
|
|
341
|
+
name: options.username,
|
|
342
|
+
}, __classPrivateFieldGet(this, _a, "a", _User_metadata_get));
|
|
343
|
+
}
|
|
344
|
+
/** @internal */
|
|
345
|
+
static async setModeratorPermissions(username, subredditName, permissions) {
|
|
346
|
+
const client = getRedditApiPlugins().Users;
|
|
347
|
+
const response = await client.SetPermissions({
|
|
348
|
+
subreddit: subredditName,
|
|
349
|
+
name: username,
|
|
350
|
+
type: 'moderator',
|
|
351
|
+
permissions: formatModeratorPermissions(permissions),
|
|
352
|
+
}, __classPrivateFieldGet(this, _a, "a", _User_metadata_get));
|
|
353
|
+
if (response.json?.errors?.length) {
|
|
354
|
+
throw new Error(response.json.errors.join('\n'));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/** @internal */
|
|
358
|
+
static async getSnoovatarUrl(username) {
|
|
359
|
+
const operationName = 'GetSnoovatarUrlByName';
|
|
360
|
+
const persistedQueryHash = 'c47fd42345af268616d2d8904b56856acdc05cf61d3650380f539ad7d596ac0c';
|
|
361
|
+
const response = await GraphQL.query(operationName, persistedQueryHash, { username });
|
|
362
|
+
return response.data?.redditorInfoByName?.snoovatarIcon?.url;
|
|
363
|
+
}
|
|
364
|
+
/** @internal */
|
|
365
|
+
static getOverview(options) {
|
|
366
|
+
const client = getRedditApiPlugins().Users;
|
|
367
|
+
return new Listing({
|
|
368
|
+
hasMore: true,
|
|
369
|
+
before: options.before,
|
|
370
|
+
after: options.after,
|
|
371
|
+
pageSize: options.pageSize,
|
|
372
|
+
limit: options.limit,
|
|
373
|
+
fetch: async (fetchOptions) => {
|
|
374
|
+
const response = await client.UserWhere({
|
|
375
|
+
username: options.username,
|
|
376
|
+
where: 'overview',
|
|
377
|
+
...fetchOptions,
|
|
378
|
+
}, __classPrivateFieldGet(this, _a, "a", _User_metadata_get));
|
|
379
|
+
return listingProtosToPostsOrComments(response);
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
_a = User, _User_id = new WeakMap(), _User_username = new WeakMap(), _User_createdAt = new WeakMap(), _User_linkKarma = new WeakMap(), _User_commentKarma = new WeakMap(), _User_nsfw = new WeakMap(), _User_isAdmin = new WeakMap(), _User_modPermissionsBySubreddit = new WeakMap(), _User_url = new WeakMap(), _User_permalink = new WeakMap(), _User_hasVerifiedEmail = new WeakMap(), _User_metadata_get = function _User_metadata_get() {
|
|
385
|
+
return getContext().debug.metadata;
|
|
386
|
+
};
|
|
387
|
+
function listingProtosToPostsOrComments(listingProto) {
|
|
388
|
+
if (!listingProto.data?.children) {
|
|
389
|
+
throw new Error('Listing response is missing children');
|
|
390
|
+
}
|
|
391
|
+
const children = listingProto.data.children.map((child) => {
|
|
392
|
+
if (child.kind === 't3') {
|
|
393
|
+
return new Post(child.data);
|
|
394
|
+
}
|
|
395
|
+
else if (child.kind === 't1') {
|
|
396
|
+
return new Comment(child.data);
|
|
397
|
+
}
|
|
398
|
+
throw new Error(`Type ${child.kind} is not supported`);
|
|
399
|
+
});
|
|
400
|
+
return {
|
|
401
|
+
children: children,
|
|
402
|
+
before: listingProto.data.before,
|
|
403
|
+
after: listingProto.data.after,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
async function listingProtosToUsers(listingProto, subredditName) {
|
|
407
|
+
const client = getRedditApiPlugins().Users;
|
|
408
|
+
if (!listingProto.data?.children) {
|
|
409
|
+
throw new Error('Listing response is missing children');
|
|
410
|
+
}
|
|
411
|
+
const userIds = listingProto.data.children.map((child) => {
|
|
412
|
+
assertNonNull(child.data?.id, 'User id is still from listing data');
|
|
413
|
+
return child.data.id;
|
|
414
|
+
});
|
|
415
|
+
// break the ids into chunks since they're passed over a query parameter
|
|
416
|
+
const chunkSize = 100;
|
|
417
|
+
const userIdChunks = [];
|
|
418
|
+
for (let i = 0; i < userIds.length; i += chunkSize) {
|
|
419
|
+
userIdChunks.push(userIds.slice(i, i + chunkSize));
|
|
420
|
+
}
|
|
421
|
+
// perform the requests
|
|
422
|
+
const usersMapResponses = await Promise.all(userIdChunks.map((userIds) => client.UserDataByAccountIds({
|
|
423
|
+
ids: userIds.join(','),
|
|
424
|
+
}, getContext().debug.metadata)));
|
|
425
|
+
// join the responses back into a single map of user data
|
|
426
|
+
const userDataById = usersMapResponses.reduce((allUsers, response) => ({ ...allUsers, ...response.users }), {});
|
|
427
|
+
const children = listingProto.data.children.map((child) => {
|
|
428
|
+
const id = child.data?.id;
|
|
429
|
+
assertNonNull(id, 'User id is missing from listing');
|
|
430
|
+
const userData = userDataById[id];
|
|
431
|
+
// Casting to unknown because Typescript assumes that userData is always defined
|
|
432
|
+
// because of how we defined the UserDataByAccountIdsResponse_UserAccountData protobuf.
|
|
433
|
+
assertNonNull(userData, 'User data is missing from response');
|
|
434
|
+
return new User({
|
|
435
|
+
id,
|
|
436
|
+
name: userData.name,
|
|
437
|
+
linkKarma: userData.linkKarma,
|
|
438
|
+
commentKarma: userData.commentKarma,
|
|
439
|
+
createdUtc: userData.createdUtc,
|
|
440
|
+
over18: userData.profileOver18,
|
|
441
|
+
snoovatarSize: [],
|
|
442
|
+
modPermissions: {
|
|
443
|
+
[subredditName]: child.data?.modPermissions ?? [],
|
|
444
|
+
},
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
return {
|
|
448
|
+
children,
|
|
449
|
+
before: listingProto.data.before,
|
|
450
|
+
after: listingProto.data.after,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
/** @internal */
|
|
454
|
+
async function getUsernameById(id) {
|
|
455
|
+
const client = getRedditApiPlugins().Users;
|
|
456
|
+
const response = await client.UserDataByAccountIds({ ids: id }, getContext().debug.metadata);
|
|
457
|
+
return response?.users?.[id]?.name;
|
|
458
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { T2ID } from '@devvit/shared-types/tid.js';
|
|
2
|
+
/**
|
|
3
|
+
* A type representing a Vault (crypto wallet).
|
|
4
|
+
*/
|
|
5
|
+
export type Vault = {
|
|
6
|
+
/**
|
|
7
|
+
* The provider of the Vault address.
|
|
8
|
+
* @example 'ethereum'
|
|
9
|
+
*/
|
|
10
|
+
provider: string;
|
|
11
|
+
/**
|
|
12
|
+
* The ID (starting with t2_) of the user owning the Vault.
|
|
13
|
+
* @example 't2_1w72'
|
|
14
|
+
*/
|
|
15
|
+
userId: T2ID;
|
|
16
|
+
/**
|
|
17
|
+
* The address of the Vault.
|
|
18
|
+
* @example '0x205ee28744456bDBf180A0Fa7De51e0F116d54Ed'
|
|
19
|
+
*/
|
|
20
|
+
address: string;
|
|
21
|
+
/**
|
|
22
|
+
* The date the Vault was created.
|
|
23
|
+
*/
|
|
24
|
+
createdAt: string;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the Vault is active.
|
|
27
|
+
*/
|
|
28
|
+
isActive: boolean;
|
|
29
|
+
};
|
|
30
|
+
export declare function getVaultByAddress(address: string): Promise<Vault>;
|
|
31
|
+
export declare function getVaultByUserId(userId: T2ID): Promise<Vault>;
|
|
32
|
+
//# sourceMappingURL=Vault.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Vault.d.ts","sourceRoot":"","sources":["../../src/models/Vault.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAKxD;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,MAAM,EAAE,IAAI,CAAC;IAEb;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CASvE;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CASnE"}
|
package/models/Vault.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { asT2ID } from '@devvit/shared-types/tid.js';
|
|
2
|
+
import { GraphQL } from '../graphql/GraphQL.js';
|
|
3
|
+
export async function getVaultByAddress(address) {
|
|
4
|
+
return getVaultByParams('GetVaultContactByAddress', '3e2f7966a5c120e64fd2795d06a46595c52d988185be98d3ed71c3f81ae80d2e', {
|
|
5
|
+
provider: 'ethereum', // Only one supported at the moment
|
|
6
|
+
address,
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
export async function getVaultByUserId(userId) {
|
|
10
|
+
return getVaultByParams('GetVaultContactByUserId', 'a854ddc19d0e22c4f36ed917fdbd568f299f3571427e393aee5e2972080fffe9', {
|
|
11
|
+
provider: 'ethereum', // Only one supported at the moment
|
|
12
|
+
userId,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
async function getVaultByParams(operationName, queryHash, params) {
|
|
16
|
+
const response = await GraphQL.query(operationName, queryHash, params);
|
|
17
|
+
const contact = response?.data?.vault?.contact;
|
|
18
|
+
return {
|
|
19
|
+
provider: contact?.provider,
|
|
20
|
+
userId: asT2ID(contact?.userId),
|
|
21
|
+
address: contact?.address,
|
|
22
|
+
createdAt: contact?.createdAt,
|
|
23
|
+
isActive: contact?.isActive,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { AddButtonWidgetRequest, AddCalendarWidgetRequest, AddCommunityListWidgetRequest, AddCustomWidgetRequest, AddImageWidgetRequest, AddPostFlairWidgetRequest, AddTextAreaWidgetRequest, CalendarWidgetConfiguration, GetWidgetsResponse_WidgetItem_PostFlairTemplate as PostFlairTemplateData, SubredditAboutRulesResponse, UpdateButtonWidgetRequest, UpdateCalendarWidgetRequest, UpdateCommunityListWidgetRequest, UpdateCustomWidgetRequest, UpdateImageWidgetRequest, UpdatePostFlairWidgetRequest, UpdateTextAreaWidgetRequest, WidgetButton, WidgetImage, WidgetStyles } from '@devvit/protos';
|
|
2
|
+
import { CommunityListWidget_CommunityData as CommunityData, GetWidgetsResponse_WidgetItem as WidgetItem } from '@devvit/protos';
|
|
3
|
+
export type AddWidgetData = (AddImageWidgetRequest & {
|
|
4
|
+
type: 'image';
|
|
5
|
+
}) | (AddCalendarWidgetRequest & {
|
|
6
|
+
type: 'calendar';
|
|
7
|
+
}) | (AddTextAreaWidgetRequest & {
|
|
8
|
+
type: 'textarea';
|
|
9
|
+
}) | (AddButtonWidgetRequest & {
|
|
10
|
+
type: 'button';
|
|
11
|
+
}) | (AddCommunityListWidgetRequest & {
|
|
12
|
+
type: 'community-list';
|
|
13
|
+
}) | (AddPostFlairWidgetRequest & {
|
|
14
|
+
type: 'post-flair';
|
|
15
|
+
}) | (AddCustomWidgetRequest & {
|
|
16
|
+
type: 'custom';
|
|
17
|
+
});
|
|
18
|
+
export declare class Widget {
|
|
19
|
+
#private;
|
|
20
|
+
constructor(widgetData: WidgetItem, subredditName: string);
|
|
21
|
+
get id(): string;
|
|
22
|
+
get name(): string;
|
|
23
|
+
get subredditName(): string;
|
|
24
|
+
toJSON(): Pick<Widget, 'id' | 'name' | 'subredditName'>;
|
|
25
|
+
delete(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* @internal
|
|
28
|
+
* @note - This method only returns the widgets listed on the sidebar.
|
|
29
|
+
*/
|
|
30
|
+
static getWidgets(subredditName: string): Promise<Widget[]>;
|
|
31
|
+
/** @internal */
|
|
32
|
+
static delete(subredditName: string, id: string): Promise<void>;
|
|
33
|
+
/** @internal */
|
|
34
|
+
static reorder(subredditName: string, orderByIds: string[]): Promise<void>;
|
|
35
|
+
/** @internal */
|
|
36
|
+
static add(widgetData: AddWidgetData): Promise<Widget>;
|
|
37
|
+
}
|
|
38
|
+
export declare class ImageWidget extends Widget {
|
|
39
|
+
#private;
|
|
40
|
+
constructor(widgetData: WidgetItem, subredditName: string);
|
|
41
|
+
get images(): WidgetImage[];
|
|
42
|
+
toJSON(): ReturnType<Widget['toJSON']> & Pick<ImageWidget, 'images'>;
|
|
43
|
+
/** @internal */
|
|
44
|
+
static create(options: AddImageWidgetRequest): Promise<ImageWidget>;
|
|
45
|
+
/** @internal */
|
|
46
|
+
static update(options: UpdateImageWidgetRequest): Promise<ImageWidget>;
|
|
47
|
+
}
|
|
48
|
+
export declare class CalendarWidget extends Widget {
|
|
49
|
+
#private;
|
|
50
|
+
constructor(widgetData: WidgetItem, subredditName: string);
|
|
51
|
+
get googleCalendarId(): string;
|
|
52
|
+
get configuration(): CalendarWidgetConfiguration;
|
|
53
|
+
get styles(): WidgetStyles;
|
|
54
|
+
toJSON(): ReturnType<Widget['toJSON']> & Pick<CalendarWidget, 'googleCalendarId' | 'configuration' | 'styles'>;
|
|
55
|
+
/** @internal */
|
|
56
|
+
static create(options: AddCalendarWidgetRequest): Promise<CalendarWidget>;
|
|
57
|
+
/** @internal */
|
|
58
|
+
static update(options: UpdateCalendarWidgetRequest): Promise<CalendarWidget>;
|
|
59
|
+
}
|
|
60
|
+
export declare class TextAreaWidget extends Widget {
|
|
61
|
+
#private;
|
|
62
|
+
constructor(widgetData: WidgetItem, subredditName: string);
|
|
63
|
+
get text(): string;
|
|
64
|
+
get styles(): WidgetStyles;
|
|
65
|
+
toJSON(): ReturnType<Widget['toJSON']> & Pick<TextAreaWidget, 'text' | 'styles'>;
|
|
66
|
+
/** @internal */
|
|
67
|
+
static create(options: AddTextAreaWidgetRequest): Promise<TextAreaWidget>;
|
|
68
|
+
/** @internal */
|
|
69
|
+
static update(options: UpdateTextAreaWidgetRequest): Promise<TextAreaWidget>;
|
|
70
|
+
}
|
|
71
|
+
export declare class ButtonWidget extends Widget {
|
|
72
|
+
#private;
|
|
73
|
+
constructor(widgetData: WidgetItem, subredditName: string);
|
|
74
|
+
get buttons(): WidgetButton[];
|
|
75
|
+
get description(): string;
|
|
76
|
+
get styles(): WidgetStyles;
|
|
77
|
+
toJSON(): ReturnType<Widget['toJSON']> & Pick<ButtonWidget, 'buttons' | 'description' | 'styles'>;
|
|
78
|
+
/** @internal */
|
|
79
|
+
static create(options: AddButtonWidgetRequest): Promise<ButtonWidget>;
|
|
80
|
+
/** @internal */
|
|
81
|
+
static update(options: UpdateButtonWidgetRequest): Promise<ButtonWidget>;
|
|
82
|
+
}
|
|
83
|
+
export declare class CommunityListWidget extends Widget {
|
|
84
|
+
#private;
|
|
85
|
+
constructor(widgetData: WidgetItem, subredditName: string);
|
|
86
|
+
get communities(): CommunityData[];
|
|
87
|
+
get styles(): WidgetStyles;
|
|
88
|
+
toJSON(): ReturnType<Widget['toJSON']> & Pick<CommunityListWidget, 'communities' | 'styles'>;
|
|
89
|
+
/** @internal */
|
|
90
|
+
static create(options: AddCommunityListWidgetRequest): Promise<CommunityListWidget>;
|
|
91
|
+
/** @internal */
|
|
92
|
+
static update(options: UpdateCommunityListWidgetRequest): Promise<CommunityListWidget>;
|
|
93
|
+
}
|
|
94
|
+
export declare class PostFlairWidget extends Widget {
|
|
95
|
+
#private;
|
|
96
|
+
constructor(widgetData: WidgetItem, subredditName: string);
|
|
97
|
+
get styles(): WidgetStyles;
|
|
98
|
+
get templates(): PostFlairTemplateData[];
|
|
99
|
+
get display(): 'list' | 'cloud';
|
|
100
|
+
toJSON(): ReturnType<Widget['toJSON']> & Pick<PostFlairWidget, 'templates' | 'display' | 'styles'>;
|
|
101
|
+
/** @internal */
|
|
102
|
+
static create(options: AddPostFlairWidgetRequest): Promise<PostFlairWidget>;
|
|
103
|
+
/** @internal */
|
|
104
|
+
static update(options: UpdatePostFlairWidgetRequest): Promise<PostFlairWidget>;
|
|
105
|
+
}
|
|
106
|
+
export declare class CustomWidget extends Widget {
|
|
107
|
+
#private;
|
|
108
|
+
constructor(widgetData: WidgetItem, subredditName: string);
|
|
109
|
+
get images(): WidgetImage[];
|
|
110
|
+
get text(): string;
|
|
111
|
+
get stylesheetUrl(): string;
|
|
112
|
+
get height(): number;
|
|
113
|
+
get css(): string;
|
|
114
|
+
toJSON(): ReturnType<Widget['toJSON']> & Pick<CustomWidget, 'images' | 'text' | 'stylesheetUrl' | 'height' | 'css'>;
|
|
115
|
+
/** @internal */
|
|
116
|
+
static create(options: AddCustomWidgetRequest): Promise<CustomWidget>;
|
|
117
|
+
/** @internal */
|
|
118
|
+
static update(options: UpdateCustomWidgetRequest): Promise<CustomWidget>;
|
|
119
|
+
}
|
|
120
|
+
type SubredditRule = {
|
|
121
|
+
description: string;
|
|
122
|
+
priority: number;
|
|
123
|
+
shortName: string;
|
|
124
|
+
violationReason: string;
|
|
125
|
+
};
|
|
126
|
+
export declare class SubredditRulesWidget extends Widget {
|
|
127
|
+
#private;
|
|
128
|
+
constructor(subredditAboutRulesRsp: SubredditAboutRulesResponse, widgetData: WidgetItem, subredditName: string);
|
|
129
|
+
get rules(): SubredditRule[];
|
|
130
|
+
toJSON(): ReturnType<Widget['toJSON']> & Pick<SubredditRulesWidget, 'rules'>;
|
|
131
|
+
}
|
|
132
|
+
export {};
|
|
133
|
+
//# sourceMappingURL=Widget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Widget.d.ts","sourceRoot":"","sources":["../../src/models/Widget.ts"],"names":[],"mappings":"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"}
|