Skip to content

Commit ecd3130

Browse files
committed
feat(reddit): add 5 new tools, fix bugs, and audit all endpoints against API docs
1 parent 4f45f70 commit ecd3130

File tree

18 files changed

+1385
-374
lines changed

18 files changed

+1385
-374
lines changed

apps/sim/blocks/blocks/reddit.ts

Lines changed: 430 additions & 236 deletions
Large diffs are not rendered by default.

apps/sim/lib/workflows/migrations/subblock-migrations.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ describe('migrateSubblockIds', () => {
3737
const { blocks, migrated } = migrateSubblockIds(input)
3838

3939
expect(migrated).toBe(true)
40-
expect(blocks['b1'].subBlocks['knowledgeBaseSelector']).toEqual({
40+
expect(blocks.b1.subBlocks.knowledgeBaseSelector).toEqual({
4141
id: 'knowledgeBaseSelector',
4242
type: 'knowledge-base-selector',
4343
value: 'kb-uuid-123',
4444
})
45-
expect(blocks['b1'].subBlocks['knowledgeBaseId']).toBeUndefined()
46-
expect(blocks['b1'].subBlocks['operation'].value).toBe('search')
45+
expect(blocks.b1.subBlocks.knowledgeBaseId).toBeUndefined()
46+
expect(blocks.b1.subBlocks.operation.value).toBe('search')
4747
})
4848

4949
it('should prefer new key when both old and new exist', () => {
@@ -68,8 +68,8 @@ describe('migrateSubblockIds', () => {
6868
const { blocks, migrated } = migrateSubblockIds(input)
6969

7070
expect(migrated).toBe(true)
71-
expect(blocks['b1'].subBlocks['knowledgeBaseSelector'].value).toBe('fresh-kb')
72-
expect(blocks['b1'].subBlocks['knowledgeBaseId']).toBeUndefined()
71+
expect(blocks.b1.subBlocks.knowledgeBaseSelector.value).toBe('fresh-kb')
72+
expect(blocks.b1.subBlocks.knowledgeBaseId).toBeUndefined()
7373
})
7474

7575
it('should not touch blocks that already use the new key', () => {
@@ -89,7 +89,7 @@ describe('migrateSubblockIds', () => {
8989
const { blocks, migrated } = migrateSubblockIds(input)
9090

9191
expect(migrated).toBe(false)
92-
expect(blocks['b1'].subBlocks['knowledgeBaseSelector'].value).toBe('kb-uuid')
92+
expect(blocks.b1.subBlocks.knowledgeBaseSelector.value).toBe('kb-uuid')
9393
})
9494
})
9595

@@ -109,8 +109,8 @@ describe('migrateSubblockIds', () => {
109109

110110
const { blocks } = migrateSubblockIds(input)
111111

112-
expect(input['b1'].subBlocks['knowledgeBaseId']).toBeDefined()
113-
expect(blocks['b1'].subBlocks['knowledgeBaseSelector']).toBeDefined()
112+
expect(input.b1.subBlocks.knowledgeBaseId).toBeDefined()
113+
expect(blocks.b1.subBlocks.knowledgeBaseSelector).toBeDefined()
114114
expect(blocks).not.toBe(input)
115115
})
116116

@@ -127,7 +127,7 @@ describe('migrateSubblockIds', () => {
127127
const { blocks, migrated } = migrateSubblockIds(input)
128128

129129
expect(migrated).toBe(false)
130-
expect(blocks['b1'].subBlocks['code'].value).toBe('console.log("hi")')
130+
expect(blocks.b1.subBlocks.code.value).toBe('console.log("hi")')
131131
})
132132

133133
it('should migrate multiple blocks in one pass', () => {
@@ -166,9 +166,9 @@ describe('migrateSubblockIds', () => {
166166
const { blocks, migrated } = migrateSubblockIds(input)
167167

168168
expect(migrated).toBe(true)
169-
expect(blocks['b1'].subBlocks['knowledgeBaseSelector'].value).toBe('kb-1')
170-
expect(blocks['b2'].subBlocks['knowledgeBaseSelector'].value).toBe('kb-2')
171-
expect(blocks['b3'].subBlocks['code']).toBeDefined()
169+
expect(blocks.b1.subBlocks.knowledgeBaseSelector.value).toBe('kb-1')
170+
expect(blocks.b2.subBlocks.knowledgeBaseSelector.value).toBe('kb-2')
171+
expect(blocks.b3.subBlocks.code).toBeDefined()
172172
})
173173

174174
it('should handle blocks with empty subBlocks', () => {

apps/sim/tools/reddit/delete.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ export const deleteTool: ToolConfig<RedditDeleteParams, RedditWriteResponse> = {
4646
id: params.id,
4747
})
4848

49-
return {
50-
body: formData.toString(),
51-
}
49+
return formData.toString() as unknown as Record<string, any>
5250
},
5351
},
5452

apps/sim/tools/reddit/get_comments.ts

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,6 @@ export const getCommentsTool: ToolConfig<RedditCommentsParams, RedditCommentsRes
6969
visibility: 'user-or-llm',
7070
description: 'Include "load more comments" elements in the response',
7171
},
72-
showtitle: {
73-
type: 'boolean',
74-
required: false,
75-
visibility: 'user-or-llm',
76-
description: 'Include submission title in the response',
77-
},
7872
threaded: {
7973
type: 'boolean',
8074
required: false,
@@ -87,23 +81,11 @@ export const getCommentsTool: ToolConfig<RedditCommentsParams, RedditCommentsRes
8781
visibility: 'user-or-llm',
8882
description: 'Integer to truncate comment depth',
8983
},
90-
after: {
91-
type: 'string',
92-
required: false,
93-
visibility: 'user-or-llm',
94-
description: 'Fullname of a thing to fetch items after (for pagination)',
95-
},
96-
before: {
84+
comment: {
9785
type: 'string',
9886
required: false,
9987
visibility: 'user-or-llm',
100-
description: 'Fullname of a thing to fetch items before (for pagination)',
101-
},
102-
count: {
103-
type: 'number',
104-
required: false,
105-
visibility: 'user-or-llm',
106-
description: 'A count of items already seen in the listing (used for numbering)',
88+
description: 'ID36 of a comment to focus on (returns that comment thread)',
10789
},
10890
},
10991

@@ -126,15 +108,11 @@ export const getCommentsTool: ToolConfig<RedditCommentsParams, RedditCommentsRes
126108
urlParams.append('context', Number(params.context).toString())
127109
if (params.showedits !== undefined) urlParams.append('showedits', params.showedits.toString())
128110
if (params.showmore !== undefined) urlParams.append('showmore', params.showmore.toString())
129-
if (params.showtitle !== undefined) urlParams.append('showtitle', params.showtitle.toString())
130111
if (params.threaded !== undefined) urlParams.append('threaded', params.threaded.toString())
131112
if (params.truncate !== undefined)
132113
urlParams.append('truncate', Number(params.truncate).toString())
133114

134-
// Add pagination parameters if provided
135-
if (params.after) urlParams.append('after', params.after)
136-
if (params.before) urlParams.append('before', params.before)
137-
if (params.count !== undefined) urlParams.append('count', Number(params.count).toString())
115+
if (params.comment) urlParams.append('comment', params.comment)
138116

139117
// Build URL using OAuth endpoint
140118
return `https://oauth.reddit.com/r/${subreddit}/comments/${params.postId}?${urlParams.toString()}`
@@ -179,11 +157,12 @@ export const getCommentsTool: ToolConfig<RedditCommentsParams, RedditCommentsRes
179157
: []
180158

181159
return {
182-
id: commentData.id || '',
160+
id: commentData.id ?? '',
161+
name: commentData.name ?? '',
183162
author: commentData.author || '[deleted]',
184-
body: commentData.body || '',
185-
created_utc: commentData.created_utc || 0,
186-
score: commentData.score || 0,
163+
body: commentData.body ?? '',
164+
created_utc: commentData.created_utc ?? 0,
165+
score: commentData.score ?? 0,
187166
permalink: commentData.permalink
188167
? `https://www.reddit.com${commentData.permalink}`
189168
: '',
@@ -199,12 +178,13 @@ export const getCommentsTool: ToolConfig<RedditCommentsParams, RedditCommentsRes
199178
success: true,
200179
output: {
201180
post: {
202-
id: postData.id || '',
203-
title: postData.title || '',
181+
id: postData.id ?? '',
182+
name: postData.name ?? '',
183+
title: postData.title ?? '',
204184
author: postData.author || '[deleted]',
205-
selftext: postData.selftext || '',
206-
created_utc: postData.created_utc || 0,
207-
score: postData.score || 0,
185+
selftext: postData.selftext ?? '',
186+
created_utc: postData.created_utc ?? 0,
187+
score: postData.score ?? 0,
208188
permalink: postData.permalink ? `https://www.reddit.com${postData.permalink}` : '',
209189
},
210190
comments: comments,
@@ -218,6 +198,7 @@ export const getCommentsTool: ToolConfig<RedditCommentsParams, RedditCommentsRes
218198
description: 'Post information including ID, title, author, content, and metadata',
219199
properties: {
220200
id: { type: 'string', description: 'Post ID' },
201+
name: { type: 'string', description: 'Thing fullname (t3_xxxxx)' },
221202
title: { type: 'string', description: 'Post title' },
222203
author: { type: 'string', description: 'Post author' },
223204
selftext: { type: 'string', description: 'Post text content' },
@@ -233,6 +214,7 @@ export const getCommentsTool: ToolConfig<RedditCommentsParams, RedditCommentsRes
233214
type: 'object',
234215
properties: {
235216
id: { type: 'string', description: 'Comment ID' },
217+
name: { type: 'string', description: 'Thing fullname (t1_xxxxx)' },
236218
author: { type: 'string', description: 'Comment author' },
237219
body: { type: 'string', description: 'Comment text' },
238220
score: { type: 'number', description: 'Comment score' },

apps/sim/tools/reddit/get_controversial.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export const getControversialTool: ToolConfig<RedditControversialParams, RedditP
7474
request: {
7575
url: (params: RedditControversialParams) => {
7676
const subreddit = normalizeSubreddit(params.subreddit)
77-
const limit = Math.min(Math.max(1, params.limit || 10), 100)
77+
const limit = Math.min(Math.max(1, params.limit ?? 10), 100)
7878

7979
// Build URL with appropriate parameters using OAuth endpoint
8080
const urlParams = new URLSearchParams({
@@ -122,18 +122,19 @@ export const getControversialTool: ToolConfig<RedditControversialParams, RedditP
122122
data.data?.children?.map((child: any) => {
123123
const post = child.data || {}
124124
return {
125-
id: post.id || '',
126-
title: post.title || '',
125+
id: post.id ?? '',
126+
name: post.name ?? '',
127+
title: post.title ?? '',
127128
author: post.author || '[deleted]',
128-
url: post.url || '',
129+
url: post.url ?? '',
129130
permalink: post.permalink ? `https://www.reddit.com${post.permalink}` : '',
130-
created_utc: post.created_utc || 0,
131-
score: post.score || 0,
132-
num_comments: post.num_comments || 0,
131+
created_utc: post.created_utc ?? 0,
132+
score: post.score ?? 0,
133+
num_comments: post.num_comments ?? 0,
133134
is_self: !!post.is_self,
134-
selftext: post.selftext || '',
135-
thumbnail: post.thumbnail || '',
136-
subreddit: post.subreddit || subredditName,
135+
selftext: post.selftext ?? '',
136+
thumbnail: post.thumbnail ?? '',
137+
subreddit: post.subreddit ?? subredditName,
137138
}
138139
}) || []
139140

@@ -142,6 +143,8 @@ export const getControversialTool: ToolConfig<RedditControversialParams, RedditP
142143
output: {
143144
subreddit: subredditName,
144145
posts,
146+
after: data.data?.after ?? null,
147+
before: data.data?.before ?? null,
145148
},
146149
}
147150
},
@@ -159,6 +162,7 @@ export const getControversialTool: ToolConfig<RedditControversialParams, RedditP
159162
type: 'object',
160163
properties: {
161164
id: { type: 'string', description: 'Post ID' },
165+
name: { type: 'string', description: 'Thing fullname (t3_xxxxx)' },
162166
title: { type: 'string', description: 'Post title' },
163167
author: { type: 'string', description: 'Author username' },
164168
url: { type: 'string', description: 'Post URL' },
@@ -173,5 +177,15 @@ export const getControversialTool: ToolConfig<RedditControversialParams, RedditP
173177
},
174178
},
175179
},
180+
after: {
181+
type: 'string',
182+
description: 'Fullname of the last item for forward pagination',
183+
optional: true,
184+
},
185+
before: {
186+
type: 'string',
187+
description: 'Fullname of the first item for backward pagination',
188+
optional: true,
189+
},
176190
},
177191
}

apps/sim/tools/reddit/get_me.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import type { RedditGetMeParams, RedditUserResponse } from '@/tools/reddit/types'
2+
import type { ToolConfig } from '@/tools/types'
3+
4+
export const getMeTool: ToolConfig<RedditGetMeParams, RedditUserResponse> = {
5+
id: 'reddit_get_me',
6+
name: 'Get Reddit User Identity',
7+
description: 'Get information about the authenticated Reddit user',
8+
version: '1.0.0',
9+
10+
oauth: {
11+
required: true,
12+
provider: 'reddit',
13+
},
14+
15+
params: {
16+
accessToken: {
17+
type: 'string',
18+
required: true,
19+
visibility: 'hidden',
20+
description: 'Access token for Reddit API',
21+
},
22+
},
23+
24+
request: {
25+
url: () => 'https://oauth.reddit.com/api/v1/me?raw_json=1',
26+
method: 'GET',
27+
headers: (params: RedditGetMeParams) => {
28+
if (!params.accessToken) {
29+
throw new Error('Access token is required for Reddit API')
30+
}
31+
32+
return {
33+
Authorization: `Bearer ${params.accessToken}`,
34+
'User-Agent': 'sim-studio/1.0 (https://github.com/simstudioai/sim)',
35+
Accept: 'application/json',
36+
}
37+
},
38+
},
39+
40+
transformResponse: async (response: Response) => {
41+
const data = await response.json()
42+
43+
return {
44+
success: true,
45+
output: {
46+
id: data.id ?? '',
47+
name: data.name ?? '',
48+
created_utc: data.created_utc ?? 0,
49+
link_karma: data.link_karma ?? 0,
50+
comment_karma: data.comment_karma ?? 0,
51+
total_karma: data.total_karma ?? 0,
52+
is_gold: data.is_gold ?? false,
53+
is_mod: data.is_mod ?? false,
54+
has_verified_email: data.has_verified_email ?? false,
55+
icon_img: data.icon_img ?? '',
56+
},
57+
}
58+
},
59+
60+
outputs: {
61+
id: { type: 'string', description: 'User ID' },
62+
name: { type: 'string', description: 'Username' },
63+
created_utc: { type: 'number', description: 'Account creation time in UTC epoch seconds' },
64+
link_karma: { type: 'number', description: 'Total link karma' },
65+
comment_karma: { type: 'number', description: 'Total comment karma' },
66+
total_karma: { type: 'number', description: 'Combined total karma' },
67+
is_gold: { type: 'boolean', description: 'Whether user has Reddit Premium' },
68+
is_mod: { type: 'boolean', description: 'Whether user is a moderator' },
69+
has_verified_email: { type: 'boolean', description: 'Whether email is verified' },
70+
icon_img: { type: 'string', description: 'User avatar/icon URL' },
71+
},
72+
}

0 commit comments

Comments
 (0)