0
# Social Interactions
1
2
Like, unlike, follow, and unfollow functionality for social engagement on the Tumblr platform.
3
4
## Capabilities
5
6
### Like Post
7
8
Like a specific post as the authenticated user.
9
10
```javascript { .api }
11
/**
12
* Like a post as the authenticating user
13
* @param postId - ID of the post to like
14
* @param reblogKey - Reblog key of the post to like
15
* @returns Promise resolving to like confirmation
16
*/
17
likePost(postId: string, reblogKey: string): Promise<any>;
18
```
19
20
**Usage Examples:**
21
22
```javascript
23
// Like a post (requires post ID and reblog key from post data)
24
await client.likePost('12345', 'abc123def456');
25
console.log('Post liked successfully');
26
27
// Get post data first, then like it
28
const posts = await client.blogPosts('some-blog');
29
const firstPost = posts.posts[0];
30
await client.likePost(firstPost.id, firstPost.reblog_key);
31
```
32
33
### Unlike Post
34
35
Remove a like from a post as the authenticated user.
36
37
```javascript { .api }
38
/**
39
* Unlike a post as the authenticating user
40
* @param postId - ID of the post to unlike
41
* @param reblogKey - Reblog key of the post to unlike
42
* @returns Promise resolving to unlike confirmation
43
*/
44
unlikePost(postId: string, reblogKey: string): Promise<any>;
45
```
46
47
**Usage Examples:**
48
49
```javascript
50
// Unlike a previously liked post
51
await client.unlikePost('12345', 'abc123def456');
52
console.log('Post unliked successfully');
53
54
// Unlike posts from your likes list
55
const likes = await client.userLikes({ limit: 5 });
56
for (const post of likes.liked_posts) {
57
await client.unlikePost(post.id, post.reblog_key);
58
console.log(`Unliked post ${post.id}`);
59
}
60
```
61
62
### Follow Blog
63
64
Follow a blog as the authenticated user.
65
66
```javascript { .api }
67
/**
68
* Follow a blog as the authenticating user
69
* @param params - Blog identification parameters
70
* @returns Promise resolving to follow confirmation
71
*/
72
followBlog(params: { url: string } | { email: string }): Promise<any>;
73
```
74
75
**Usage Examples:**
76
77
```javascript
78
// Follow a blog by URL
79
await client.followBlog({ url: 'cool-blog.tumblr.com' });
80
console.log('Blog followed successfully');
81
82
// Follow a blog by full URL
83
await client.followBlog({ url: 'https://cool-blog.tumblr.com/' });
84
85
// Follow a blog by email (if supported)
86
await client.followBlog({ email: 'blogger@example.com' });
87
88
// Follow multiple blogs
89
const blogsToFollow = [
90
'photography-blog.tumblr.com',
91
'art-blog.tumblr.com',
92
'music-blog.tumblr.com'
93
];
94
95
for (const blogUrl of blogsToFollow) {
96
try {
97
await client.followBlog({ url: blogUrl });
98
console.log(`Followed ${blogUrl}`);
99
} catch (error) {
100
console.error(`Failed to follow ${blogUrl}:`, error.message);
101
}
102
}
103
```
104
105
### Unfollow Blog
106
107
Unfollow a blog as the authenticated user.
108
109
```javascript { .api }
110
/**
111
* Unfollow a blog as the authenticating user
112
* @param params - Blog URL to unfollow
113
* @returns Promise resolving to unfollow confirmation
114
*/
115
unfollowBlog(params: { url: string }): Promise<any>;
116
```
117
118
**Usage Examples:**
119
120
```javascript
121
// Unfollow a blog by URL
122
await client.unfollowBlog({ url: 'some-blog.tumblr.com' });
123
console.log('Blog unfollowed successfully');
124
125
// Unfollow blogs from your following list
126
const following = await client.userFollowing({ limit: 10 });
127
for (const blog of following.blogs) {
128
if (blog.name.includes('spam')) {
129
await client.unfollowBlog({ url: blog.url });
130
console.log(`Unfollowed ${blog.name}`);
131
}
132
}
133
```
134
135
## Parameter Types
136
137
### Follow Blog Parameters
138
139
```javascript { .api }
140
type FollowBlogParams = { url: string } | { email: string };
141
142
interface FollowByUrl {
143
/** Blog URL to follow (can be short form or full URL) */
144
url: string;
145
}
146
147
interface FollowByEmail {
148
/** Email address associated with the blog */
149
email: string;
150
}
151
```
152
153
### Unfollow Blog Parameters
154
155
```javascript { .api }
156
interface UnfollowBlogParams {
157
/** Blog URL to unfollow */
158
url: string;
159
}
160
```
161
162
## Getting Required Information
163
164
### Obtaining Post ID and Reblog Key
165
166
```javascript
167
// Get post information from blog posts
168
const posts = await client.blogPosts('target-blog');
169
const targetPost = posts.posts[0];
170
171
console.log('Post ID:', targetPost.id);
172
console.log('Reblog Key:', targetPost.reblog_key);
173
174
// Now you can like/unlike the post
175
await client.likePost(targetPost.id, targetPost.reblog_key);
176
```
177
178
### Getting Post Information from Dashboard
179
180
```javascript
181
// Get posts from dashboard with like/reblog capabilities
182
const dashboard = await client.userDashboard({
183
reblog_info: true,
184
notes_info: true
185
});
186
187
dashboard.posts.forEach(async (post) => {
188
if (post.can_like && !post.liked) {
189
console.log(`Can like post ${post.id} by ${post.blog_name}`);
190
// await client.likePost(post.id, post.reblog_key);
191
}
192
});
193
```
194
195
### Finding Blogs to Follow
196
197
```javascript
198
// Discover blogs through tagged posts
199
const taggedPosts = await client.taggedPosts('photography');
200
const uniqueBlogs = [...new Set(taggedPosts.response.map(post => post.blog_name))];
201
202
console.log('Blogs posting about photography:');
203
uniqueBlogs.forEach(blogName => {
204
console.log(`- ${blogName}.tumblr.com`);
205
});
206
207
// Follow interesting blogs
208
for (const blogName of uniqueBlogs.slice(0, 5)) {
209
await client.followBlog({ url: `${blogName}.tumblr.com` });
210
}
211
```
212
213
## Bulk Operations
214
215
### Bulk Like Posts
216
217
```javascript
218
async function likeAllPostsFromBlog(blogName, maxPosts = 20) {
219
const posts = await client.blogPosts(blogName, { limit: maxPosts });
220
221
for (const post of posts.posts) {
222
try {
223
await client.likePost(post.id, post.reblog_key);
224
console.log(`Liked post ${post.id} from ${post.blog_name}`);
225
226
// Add delay to avoid rate limiting
227
await new Promise(resolve => setTimeout(resolve, 1000));
228
} catch (error) {
229
console.error(`Failed to like post ${post.id}:`, error.message);
230
}
231
}
232
}
233
```
234
235
### Clean Up Following List
236
237
```javascript
238
async function unfollowInactiveBlogs(daysSinceUpdate = 365) {
239
const cutoffTime = Date.now() / 1000 - (daysSinceUpdate * 24 * 60 * 60);
240
const following = await client.userFollowing();
241
242
for (const blog of following.blogs) {
243
if (blog.updated < cutoffTime) {
244
try {
245
await client.unfollowBlog({ url: blog.url });
246
console.log(`Unfollowed inactive blog: ${blog.name}`);
247
248
// Add delay to avoid rate limiting
249
await new Promise(resolve => setTimeout(resolve, 500));
250
} catch (error) {
251
console.error(`Failed to unfollow ${blog.name}:`, error.message);
252
}
253
}
254
}
255
}
256
```
257
258
### Like Posts from Dashboard
259
260
```javascript
261
async function likeInterestingDashboardPosts(keywords = []) {
262
const dashboard = await client.userDashboard({ limit: 20 });
263
264
for (const post of dashboard.posts) {
265
if (!post.liked && post.can_like) {
266
// Check if post contains interesting keywords
267
const postText = (post.title || '') + ' ' + (post.body || '') + ' ' + (post.tags || []).join(' ');
268
const hasKeyword = keywords.some(keyword =>
269
postText.toLowerCase().includes(keyword.toLowerCase())
270
);
271
272
if (hasKeyword) {
273
try {
274
await client.likePost(post.id, post.reblog_key);
275
console.log(`Liked post about "${keywords.find(k => postText.toLowerCase().includes(k.toLowerCase()))}"`);
276
} catch (error) {
277
console.error(`Failed to like post ${post.id}:`, error.message);
278
}
279
}
280
}
281
}
282
}
283
284
// Usage
285
await likeInterestingDashboardPosts(['photography', 'art', 'design']);
286
```
287
288
## Authentication Requirements
289
290
All social interaction methods require OAuth authentication:
291
292
```javascript
293
// Must have full OAuth credentials
294
const client = tumblr.createClient({
295
consumer_key: 'your-consumer-key',
296
consumer_secret: 'your-consumer-secret',
297
token: 'user-oauth-token',
298
token_secret: 'user-oauth-token-secret'
299
});
300
301
// These will fail without authentication
302
try {
303
await client.likePost('12345', 'abc123');
304
await client.followBlog({ url: 'some-blog.tumblr.com' });
305
} catch (error) {
306
if (error.message.includes('401')) {
307
console.error('OAuth authentication required');
308
}
309
}
310
```
311
312
## Rate Limiting and Best Practices
313
314
### Respect Rate Limits
315
316
```javascript
317
async function likePostsWithDelay(posts, delayMs = 1000) {
318
for (const post of posts) {
319
try {
320
await client.likePost(post.id, post.reblog_key);
321
console.log(`Liked post ${post.id}`);
322
323
// Wait between requests to avoid rate limiting
324
await new Promise(resolve => setTimeout(resolve, delayMs));
325
} catch (error) {
326
if (error.message.includes('429')) {
327
console.log('Rate limit hit, waiting 60 seconds...');
328
await new Promise(resolve => setTimeout(resolve, 60000));
329
// Retry the request
330
await client.likePost(post.id, post.reblog_key);
331
} else {
332
console.error(`Error liking post:`, error.message);
333
}
334
}
335
}
336
}
337
```
338
339
### Error Handling
340
341
```javascript
342
async function safelyFollowBlog(blogUrl) {
343
try {
344
await client.followBlog({ url: blogUrl });
345
return { success: true, message: `Followed ${blogUrl}` };
346
} catch (error) {
347
if (error.message.includes('403')) {
348
return { success: false, message: 'Blog does not allow follows or is private' };
349
} else if (error.message.includes('404')) {
350
return { success: false, message: 'Blog not found' };
351
} else if (error.message.includes('429')) {
352
return { success: false, message: 'Rate limit exceeded, try again later' };
353
} else {
354
return { success: false, message: `Unknown error: ${error.message}` };
355
}
356
}
357
}
358
359
// Usage
360
const result = await safelyFollowBlog('example-blog.tumblr.com');
361
console.log(result.message);
362
```
363
364
### Check Permissions Before Acting
365
366
```javascript
367
async function smartLikePosts(blogName) {
368
const posts = await client.blogPosts(blogName, {
369
reblog_info: true,
370
notes_info: true
371
});
372
373
for (const post of posts.posts) {
374
// Check if we can and should like this post
375
if (post.can_like && !post.liked) {
376
try {
377
await client.likePost(post.id, post.reblog_key);
378
console.log(`Liked ${post.type} post: ${post.summary || post.title || post.id}`);
379
} catch (error) {
380
console.error(`Cannot like post ${post.id}:`, error.message);
381
}
382
} else if (post.liked) {
383
console.log(`Already liked post ${post.id}`);
384
} else {
385
console.log(`Cannot like post ${post.id} (permissions)`);
386
}
387
}
388
}
389
```