@prmichaelsen/reddit-mcp 0.1.0 → 0.1.1

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.
Files changed (58) hide show
  1. package/.claude/settings.local.json +4 -1
  2. package/README.md +253 -27
  3. package/agent/progress.yaml +29 -30
  4. package/dist/factory.js +1206 -0
  5. package/dist/factory.js.map +4 -4
  6. package/dist/index.js +1206 -0
  7. package/dist/index.js.map +4 -4
  8. package/dist/server.d.ts.map +1 -1
  9. package/dist/server.js +1206 -0
  10. package/dist/server.js.map +4 -4
  11. package/dist/tools/account.d.ts +4 -0
  12. package/dist/tools/account.d.ts.map +1 -0
  13. package/dist/tools/comments.d.ts +4 -0
  14. package/dist/tools/comments.d.ts.map +1 -0
  15. package/dist/tools/flair.d.ts +4 -0
  16. package/dist/tools/flair.d.ts.map +1 -0
  17. package/dist/tools/messages.d.ts +4 -0
  18. package/dist/tools/messages.d.ts.map +1 -0
  19. package/dist/tools/moderation.d.ts +4 -0
  20. package/dist/tools/moderation.d.ts.map +1 -0
  21. package/dist/tools/multireddits.d.ts +4 -0
  22. package/dist/tools/multireddits.d.ts.map +1 -0
  23. package/dist/tools/posts.d.ts +4 -0
  24. package/dist/tools/posts.d.ts.map +1 -0
  25. package/dist/tools/subreddits.d.ts +4 -0
  26. package/dist/tools/subreddits.d.ts.map +1 -0
  27. package/dist/tools/users.d.ts +4 -0
  28. package/dist/tools/users.d.ts.map +1 -0
  29. package/dist/tools/voting.d.ts +4 -0
  30. package/dist/tools/voting.d.ts.map +1 -0
  31. package/dist/tools/wiki.d.ts +4 -0
  32. package/dist/tools/wiki.d.ts.map +1 -0
  33. package/package.json +1 -1
  34. package/src/server.ts +22 -0
  35. package/src/tools/account.ts +84 -0
  36. package/src/tools/comments.ts +73 -0
  37. package/src/tools/flair.ts +79 -0
  38. package/src/tools/messages.ts +126 -0
  39. package/src/tools/moderation.ts +292 -0
  40. package/src/tools/multireddits.ts +152 -0
  41. package/src/tools/posts.ts +177 -0
  42. package/src/tools/subreddits.ts +137 -0
  43. package/src/tools/users.ts +181 -0
  44. package/src/tools/voting.ts +90 -0
  45. package/src/tools/wiki.ts +118 -0
  46. package/tests/fixtures/reddit-responses.ts +159 -0
  47. package/tests/unit/account.test.ts +95 -0
  48. package/tests/unit/comments.test.ts +92 -0
  49. package/tests/unit/flair.test.ts +101 -0
  50. package/tests/unit/messages.test.ts +106 -0
  51. package/tests/unit/moderation.test.ts +243 -0
  52. package/tests/unit/multireddits.test.ts +136 -0
  53. package/tests/unit/posts.test.ts +155 -0
  54. package/tests/unit/subreddits.test.ts +125 -0
  55. package/tests/unit/transport.test.ts +13 -0
  56. package/tests/unit/users.test.ts +124 -0
  57. package/tests/unit/voting.test.ts +110 -0
  58. package/tests/unit/wiki.test.ts +116 -0
@@ -0,0 +1,137 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import type { RedditClient } from "../client/reddit.js";
4
+
5
+ const paginationParams = {
6
+ limit: z
7
+ .number()
8
+ .min(1)
9
+ .max(100)
10
+ .optional()
11
+ .describe("Number of items to return (1-100, default 25)"),
12
+ after: z.string().optional().describe("Fullname to paginate after"),
13
+ before: z.string().optional().describe("Fullname to paginate before"),
14
+ };
15
+
16
+ function buildParams(
17
+ input: Record<string, unknown>,
18
+ ): Record<string, string | undefined> {
19
+ const params: Record<string, string | undefined> = {};
20
+ for (const [key, value] of Object.entries(input)) {
21
+ if (value !== undefined && value !== null) {
22
+ params[key] = String(value);
23
+ }
24
+ }
25
+ return params;
26
+ }
27
+
28
+ export function registerSubredditTools(
29
+ server: McpServer,
30
+ client: RedditClient,
31
+ ): void {
32
+ server.tool(
33
+ "reddit_subreddit_about",
34
+ "Get a subreddit's metadata (description, subscribers, rules summary, etc). Requires 'read' scope.",
35
+ {
36
+ subreddit: z.string().describe("Subreddit name (without r/ prefix)"),
37
+ },
38
+ async (input) => {
39
+ const data = await client.get(`/r/${input.subreddit}/about`);
40
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
41
+ },
42
+ );
43
+
44
+ server.tool(
45
+ "reddit_subreddit_rules",
46
+ "Get a subreddit's rules list. Requires 'read' scope.",
47
+ {
48
+ subreddit: z.string().describe("Subreddit name (without r/ prefix)"),
49
+ },
50
+ async (input) => {
51
+ const data = await client.get(`/r/${input.subreddit}/about/rules`);
52
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
53
+ },
54
+ );
55
+
56
+ server.tool(
57
+ "reddit_subscribe",
58
+ "Subscribe to a subreddit. Requires 'subscribe' scope.",
59
+ {
60
+ sr_name: z.string().describe("Subreddit name to subscribe to (without r/ prefix)"),
61
+ },
62
+ async (input) => {
63
+ const data = await client.post("/api/subscribe", {
64
+ sr_name: input.sr_name,
65
+ action: "sub",
66
+ });
67
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
68
+ },
69
+ );
70
+
71
+ server.tool(
72
+ "reddit_unsubscribe",
73
+ "Unsubscribe from a subreddit. Requires 'subscribe' scope.",
74
+ {
75
+ sr_name: z.string().describe("Subreddit name to unsubscribe from (without r/ prefix)"),
76
+ },
77
+ async (input) => {
78
+ const data = await client.post("/api/subscribe", {
79
+ sr_name: input.sr_name,
80
+ action: "unsub",
81
+ });
82
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
83
+ },
84
+ );
85
+
86
+ server.tool(
87
+ "reddit_subreddits_mine",
88
+ "List subreddits the authenticated user is subscribed to. Requires 'mysubreddits' scope.",
89
+ { ...paginationParams },
90
+ async (input) => {
91
+ const data = await client.get(
92
+ "/subreddits/mine/subscriber",
93
+ buildParams(input),
94
+ );
95
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
96
+ },
97
+ );
98
+
99
+ server.tool(
100
+ "reddit_subreddits_popular",
101
+ "List popular subreddits. Requires 'read' scope.",
102
+ { ...paginationParams },
103
+ async (input) => {
104
+ const data = await client.get(
105
+ "/subreddits/popular",
106
+ buildParams(input),
107
+ );
108
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
109
+ },
110
+ );
111
+
112
+ server.tool(
113
+ "reddit_subreddits_new",
114
+ "List newest subreddits. Requires 'read' scope.",
115
+ { ...paginationParams },
116
+ async (input) => {
117
+ const data = await client.get("/subreddits/new", buildParams(input));
118
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
119
+ },
120
+ );
121
+
122
+ server.tool(
123
+ "reddit_subreddits_search",
124
+ "Search for subreddits by name or topic. Requires 'read' scope.",
125
+ {
126
+ q: z.string().describe("Search query"),
127
+ ...paginationParams,
128
+ },
129
+ async (input) => {
130
+ const data = await client.get(
131
+ "/subreddits/search",
132
+ buildParams(input),
133
+ );
134
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
135
+ },
136
+ );
137
+ }
@@ -0,0 +1,181 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import type { RedditClient } from "../client/reddit.js";
4
+
5
+ const userListingParams = {
6
+ sort: z
7
+ .enum(["hot", "new", "top", "controversial"])
8
+ .optional()
9
+ .describe("Sort order"),
10
+ t: z
11
+ .enum(["hour", "day", "week", "month", "year", "all"])
12
+ .optional()
13
+ .describe("Time filter (for top/controversial)"),
14
+ limit: z
15
+ .number()
16
+ .min(1)
17
+ .max(100)
18
+ .optional()
19
+ .describe("Number of items to return (1-100, default 25)"),
20
+ after: z.string().optional().describe("Fullname to paginate after"),
21
+ before: z.string().optional().describe("Fullname to paginate before"),
22
+ };
23
+
24
+ function buildParams(
25
+ input: Record<string, unknown>,
26
+ ): Record<string, string | undefined> {
27
+ const params: Record<string, string | undefined> = {};
28
+ for (const [key, value] of Object.entries(input)) {
29
+ if (value !== undefined && value !== null) {
30
+ params[key] = String(value);
31
+ }
32
+ }
33
+ return params;
34
+ }
35
+
36
+ export function registerUserTools(
37
+ server: McpServer,
38
+ client: RedditClient,
39
+ ): void {
40
+ server.tool(
41
+ "reddit_user_about",
42
+ "Get a user's public profile info. Requires 'read' scope.",
43
+ {
44
+ username: z.string().describe("Username (without /u/ prefix)"),
45
+ },
46
+ async (input) => {
47
+ const data = await client.get(`/user/${input.username}/about`);
48
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
49
+ },
50
+ );
51
+
52
+ server.tool(
53
+ "reddit_user_overview",
54
+ "Get a user's recent posts and comments. Requires 'history' scope.",
55
+ {
56
+ username: z.string().describe("Username (without /u/ prefix)"),
57
+ ...userListingParams,
58
+ },
59
+ async (input) => {
60
+ const { username, ...rest } = input;
61
+ const data = await client.get(
62
+ `/user/${username}/overview`,
63
+ buildParams(rest),
64
+ );
65
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
66
+ },
67
+ );
68
+
69
+ server.tool(
70
+ "reddit_user_submitted",
71
+ "Get a user's submitted posts. Requires 'history' scope.",
72
+ {
73
+ username: z.string().describe("Username (without /u/ prefix)"),
74
+ ...userListingParams,
75
+ },
76
+ async (input) => {
77
+ const { username, ...rest } = input;
78
+ const data = await client.get(
79
+ `/user/${username}/submitted`,
80
+ buildParams(rest),
81
+ );
82
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
83
+ },
84
+ );
85
+
86
+ server.tool(
87
+ "reddit_user_comments",
88
+ "Get a user's comments. Requires 'history' scope.",
89
+ {
90
+ username: z.string().describe("Username (without /u/ prefix)"),
91
+ ...userListingParams,
92
+ },
93
+ async (input) => {
94
+ const { username, ...rest } = input;
95
+ const data = await client.get(
96
+ `/user/${username}/comments`,
97
+ buildParams(rest),
98
+ );
99
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
100
+ },
101
+ );
102
+
103
+ server.tool(
104
+ "reddit_user_saved",
105
+ "Get a user's saved posts and comments. Only works for the authenticated user. Requires 'history' scope.",
106
+ {
107
+ username: z.string().describe("Username (without /u/ prefix)"),
108
+ ...userListingParams,
109
+ },
110
+ async (input) => {
111
+ const { username, ...rest } = input;
112
+ const data = await client.get(
113
+ `/user/${username}/saved`,
114
+ buildParams(rest),
115
+ );
116
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
117
+ },
118
+ );
119
+
120
+ server.tool(
121
+ "reddit_user_upvoted",
122
+ "Get a user's upvoted posts. Only works for the authenticated user. Requires 'history' scope.",
123
+ {
124
+ username: z.string().describe("Username (without /u/ prefix)"),
125
+ ...userListingParams,
126
+ },
127
+ async (input) => {
128
+ const { username, ...rest } = input;
129
+ const data = await client.get(
130
+ `/user/${username}/upvoted`,
131
+ buildParams(rest),
132
+ );
133
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
134
+ },
135
+ );
136
+
137
+ server.tool(
138
+ "reddit_user_downvoted",
139
+ "Get a user's downvoted posts. Only works for the authenticated user. Requires 'history' scope.",
140
+ {
141
+ username: z.string().describe("Username (without /u/ prefix)"),
142
+ ...userListingParams,
143
+ },
144
+ async (input) => {
145
+ const { username, ...rest } = input;
146
+ const data = await client.get(
147
+ `/user/${username}/downvoted`,
148
+ buildParams(rest),
149
+ );
150
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
151
+ },
152
+ );
153
+
154
+ server.tool(
155
+ "reddit_user_trophies",
156
+ "Get a user's trophies. Requires 'read' scope.",
157
+ {
158
+ username: z.string().describe("Username (without /u/ prefix)"),
159
+ },
160
+ async (input) => {
161
+ const data = await client.get(
162
+ `/api/v1/user/${input.username}/trophies`,
163
+ );
164
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
165
+ },
166
+ );
167
+
168
+ server.tool(
169
+ "reddit_block_user",
170
+ "Block a user. Requires 'account' scope.",
171
+ {
172
+ name: z.string().describe("Username to block (without /u/ prefix)"),
173
+ },
174
+ async (input) => {
175
+ const data = await client.post("/api/block_user", {
176
+ name: input.name,
177
+ });
178
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
179
+ },
180
+ );
181
+ }
@@ -0,0 +1,90 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import type { RedditClient } from "../client/reddit.js";
4
+
5
+ export function registerVotingTools(
6
+ server: McpServer,
7
+ client: RedditClient,
8
+ ): void {
9
+ server.tool(
10
+ "reddit_vote",
11
+ "Upvote, downvote, or remove vote on a post or comment. Requires 'vote' scope.",
12
+ {
13
+ id: z
14
+ .string()
15
+ .describe("Fullname of the post (t3_) or comment (t1_) to vote on"),
16
+ dir: z
17
+ .enum(["1", "0", "-1"])
18
+ .describe("Vote direction: '1' = upvote, '0' = unvote, '-1' = downvote"),
19
+ },
20
+ async (input) => {
21
+ const data = await client.post("/api/vote", {
22
+ id: input.id,
23
+ dir: input.dir,
24
+ });
25
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
26
+ },
27
+ );
28
+
29
+ server.tool(
30
+ "reddit_save",
31
+ "Save a post or comment to your saved list. Requires 'save' scope.",
32
+ {
33
+ id: z
34
+ .string()
35
+ .describe("Fullname of the post (t3_) or comment (t1_) to save"),
36
+ category: z
37
+ .string()
38
+ .optional()
39
+ .describe("Save category name (Reddit Gold feature)"),
40
+ },
41
+ async (input) => {
42
+ const params: Record<string, string | undefined> = {
43
+ id: input.id,
44
+ category: input.category,
45
+ };
46
+ const data = await client.post("/api/save", params);
47
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
48
+ },
49
+ );
50
+
51
+ server.tool(
52
+ "reddit_unsave",
53
+ "Remove a post or comment from your saved list. Requires 'save' scope.",
54
+ {
55
+ id: z
56
+ .string()
57
+ .describe("Fullname of the post (t3_) or comment (t1_) to unsave"),
58
+ },
59
+ async (input) => {
60
+ const data = await client.post("/api/unsave", { id: input.id });
61
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
62
+ },
63
+ );
64
+
65
+ server.tool(
66
+ "reddit_report",
67
+ "Report a post or comment to subreddit moderators. Requires 'report' scope.",
68
+ {
69
+ thing_id: z
70
+ .string()
71
+ .describe("Fullname of the post (t3_) or comment (t1_) to report"),
72
+ reason: z
73
+ .string()
74
+ .describe("Subreddit rule violated (from subreddit rules list)"),
75
+ other_reason: z
76
+ .string()
77
+ .optional()
78
+ .describe("Additional explanation (for 'other' reason)"),
79
+ },
80
+ async (input) => {
81
+ const params: Record<string, string | undefined> = {
82
+ thing_id: input.thing_id,
83
+ reason: input.reason,
84
+ other_reason: input.other_reason,
85
+ };
86
+ const data = await client.post("/api/report", params);
87
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
88
+ },
89
+ );
90
+ }
@@ -0,0 +1,118 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import type { RedditClient } from "../client/reddit.js";
4
+
5
+ const paginationParams = {
6
+ limit: z
7
+ .number()
8
+ .min(1)
9
+ .max(100)
10
+ .optional()
11
+ .describe("Number of items to return (1-100, default 25)"),
12
+ after: z.string().optional().describe("Fullname to paginate after"),
13
+ before: z.string().optional().describe("Fullname to paginate before"),
14
+ };
15
+
16
+ function buildParams(
17
+ input: Record<string, unknown>,
18
+ ): Record<string, string | undefined> {
19
+ const params: Record<string, string | undefined> = {};
20
+ for (const [key, value] of Object.entries(input)) {
21
+ if (value !== undefined && value !== null) {
22
+ params[key] = String(value);
23
+ }
24
+ }
25
+ return params;
26
+ }
27
+
28
+ export function registerWikiTools(
29
+ server: McpServer,
30
+ client: RedditClient,
31
+ ): void {
32
+ server.tool(
33
+ "reddit_wiki_page",
34
+ "Get the content of a wiki page. Requires 'wikiread' scope.",
35
+ {
36
+ subreddit: z.string().describe("Subreddit name (without r/ prefix)"),
37
+ page: z.string().describe("Wiki page name (e.g. 'index', 'faq')"),
38
+ },
39
+ async (input) => {
40
+ const data = await client.get(
41
+ `/r/${input.subreddit}/wiki/${input.page}`,
42
+ );
43
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
44
+ },
45
+ );
46
+
47
+ server.tool(
48
+ "reddit_wiki_edit",
49
+ "Edit a wiki page. Requires 'wikiedit' scope.",
50
+ {
51
+ subreddit: z.string().describe("Subreddit name (without r/ prefix)"),
52
+ page: z.string().describe("Wiki page name"),
53
+ content: z.string().describe("Full wiki page content (markdown)"),
54
+ reason: z
55
+ .string()
56
+ .optional()
57
+ .describe("Edit reason (like a commit message)"),
58
+ },
59
+ async (input) => {
60
+ const data = await client.post(
61
+ `/r/${input.subreddit}/api/wiki/edit`,
62
+ {
63
+ page: input.page,
64
+ content: input.content,
65
+ reason: input.reason,
66
+ },
67
+ );
68
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
69
+ },
70
+ );
71
+
72
+ server.tool(
73
+ "reddit_wiki_pages",
74
+ "List all wiki pages in a subreddit. Requires 'wikiread' scope.",
75
+ {
76
+ subreddit: z.string().describe("Subreddit name (without r/ prefix)"),
77
+ },
78
+ async (input) => {
79
+ const data = await client.get(`/r/${input.subreddit}/wiki/pages`);
80
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
81
+ },
82
+ );
83
+
84
+ server.tool(
85
+ "reddit_wiki_revisions",
86
+ "Get revision history for all wiki pages in a subreddit. Requires 'wikiread' scope.",
87
+ {
88
+ subreddit: z.string().describe("Subreddit name (without r/ prefix)"),
89
+ ...paginationParams,
90
+ },
91
+ async (input) => {
92
+ const { subreddit, ...rest } = input;
93
+ const data = await client.get(
94
+ `/r/${subreddit}/wiki/revisions`,
95
+ buildParams(rest),
96
+ );
97
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
98
+ },
99
+ );
100
+
101
+ server.tool(
102
+ "reddit_wiki_page_revisions",
103
+ "Get revision history for a specific wiki page. Requires 'wikiread' scope.",
104
+ {
105
+ subreddit: z.string().describe("Subreddit name (without r/ prefix)"),
106
+ page: z.string().describe("Wiki page name"),
107
+ ...paginationParams,
108
+ },
109
+ async (input) => {
110
+ const { subreddit, page, ...rest } = input;
111
+ const data = await client.get(
112
+ `/r/${subreddit}/wiki/revisions/${page}`,
113
+ buildParams(rest),
114
+ );
115
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
116
+ },
117
+ );
118
+ }
@@ -125,6 +125,165 @@ export const mockSubredditAbout = {
125
125
  },
126
126
  };
127
127
 
128
+ export const mockSubmitResponse = {
129
+ json: {
130
+ errors: [],
131
+ data: {
132
+ url: "https://www.reddit.com/r/test/comments/newpost/my_new_post/",
133
+ drafts_count: 0,
134
+ id: "t3_newpost",
135
+ name: "t3_newpost",
136
+ },
137
+ },
138
+ };
139
+
140
+ export const mockEditResponse = {
141
+ json: {
142
+ errors: [],
143
+ data: {
144
+ things: [
145
+ {
146
+ kind: "t3",
147
+ data: {
148
+ id: "abc123",
149
+ name: "t3_abc123",
150
+ selftext: "Updated text",
151
+ },
152
+ },
153
+ ],
154
+ },
155
+ },
156
+ };
157
+
158
+ export const mockCommentResponse = {
159
+ json: {
160
+ errors: [],
161
+ data: {
162
+ things: [
163
+ {
164
+ kind: "t1",
165
+ data: {
166
+ id: "comment1",
167
+ name: "t1_comment1",
168
+ body: "This is my comment",
169
+ author: "testuser",
170
+ parent_id: "t3_abc123",
171
+ },
172
+ },
173
+ ],
174
+ },
175
+ },
176
+ };
177
+
178
+ export const mockMoreChildrenResponse = {
179
+ json: {
180
+ errors: [],
181
+ data: {
182
+ things: [
183
+ {
184
+ kind: "t1",
185
+ data: {
186
+ id: "more1",
187
+ name: "t1_more1",
188
+ body: "Expanded comment",
189
+ author: "otheruser",
190
+ parent_id: "t1_xyz789",
191
+ },
192
+ },
193
+ ],
194
+ },
195
+ },
196
+ };
197
+
198
+ export const mockMeResponse = {
199
+ name: "testuser",
200
+ id: "user123",
201
+ created_utc: 1600000000,
202
+ link_karma: 1000,
203
+ comment_karma: 5000,
204
+ is_gold: false,
205
+ is_mod: true,
206
+ has_verified_email: true,
207
+ subreddit: { display_name: "u_testuser", subscribers: 10 },
208
+ };
209
+
210
+ export const mockKarmaResponse = {
211
+ kind: "KarmaList",
212
+ data: [
213
+ { sr: "programming", comment_karma: 500, link_karma: 200 },
214
+ { sr: "typescript", comment_karma: 300, link_karma: 100 },
215
+ ],
216
+ };
217
+
218
+ export const mockPrefsResponse = {
219
+ over_18: false,
220
+ hide_downs: false,
221
+ default_comment_sort: "confidence",
222
+ lang: "en",
223
+ num_comments: 200,
224
+ };
225
+
226
+ export const mockTrophiesResponse = {
227
+ kind: "TrophyList",
228
+ data: {
229
+ trophies: [
230
+ { kind: "t6", data: { name: "Verified Email", icon_70: "icon.png" } },
231
+ ],
232
+ },
233
+ };
234
+
235
+ export const mockFriendsResponse = {
236
+ kind: "UserList",
237
+ data: {
238
+ children: [
239
+ { name: "friend1", date: 1700000000, id: "t2_friend1" },
240
+ ],
241
+ },
242
+ };
243
+
244
+ export const mockBlockedResponse = {
245
+ kind: "UserList",
246
+ data: {
247
+ children: [
248
+ { name: "blocked1", date: 1700000000, id: "t2_blocked1" },
249
+ ],
250
+ },
251
+ };
252
+
253
+ export const mockMessageListing = {
254
+ kind: "Listing",
255
+ data: {
256
+ after: null,
257
+ before: null,
258
+ children: [
259
+ {
260
+ kind: "t4",
261
+ data: {
262
+ id: "msg1",
263
+ name: "t4_msg1",
264
+ subject: "Hello",
265
+ body: "Hi there!",
266
+ author: "sender",
267
+ dest: "testuser",
268
+ created_utc: 1710000000,
269
+ new: true,
270
+ },
271
+ },
272
+ ],
273
+ dist: 1,
274
+ modhash: "",
275
+ },
276
+ };
277
+
278
+ export const mockComposeResponse = {
279
+ json: {
280
+ errors: [],
281
+ data: {},
282
+ },
283
+ };
284
+
285
+ export const mockEmptyResponse = {};
286
+
128
287
  export const mockErrorResponse = {
129
288
  error: 403,
130
289
  message: "Forbidden",