Like, unlike, follow, and unfollow functionality for social engagement on the Tumblr platform.
Like a specific post as the authenticated user.
/**
* Like a post as the authenticating user
* @param postId - ID of the post to like
* @param reblogKey - Reblog key of the post to like
* @returns Promise resolving to like confirmation
*/
likePost(postId: string, reblogKey: string): Promise<any>;Usage Examples:
// Like a post (requires post ID and reblog key from post data)
await client.likePost('12345', 'abc123def456');
console.log('Post liked successfully');
// Get post data first, then like it
const posts = await client.blogPosts('some-blog');
const firstPost = posts.posts[0];
await client.likePost(firstPost.id, firstPost.reblog_key);Remove a like from a post as the authenticated user.
/**
* Unlike a post as the authenticating user
* @param postId - ID of the post to unlike
* @param reblogKey - Reblog key of the post to unlike
* @returns Promise resolving to unlike confirmation
*/
unlikePost(postId: string, reblogKey: string): Promise<any>;Usage Examples:
// Unlike a previously liked post
await client.unlikePost('12345', 'abc123def456');
console.log('Post unliked successfully');
// Unlike posts from your likes list
const likes = await client.userLikes({ limit: 5 });
for (const post of likes.liked_posts) {
await client.unlikePost(post.id, post.reblog_key);
console.log(`Unliked post ${post.id}`);
}Follow a blog as the authenticated user.
/**
* Follow a blog as the authenticating user
* @param params - Blog identification parameters
* @returns Promise resolving to follow confirmation
*/
followBlog(params: { url: string } | { email: string }): Promise<any>;Usage Examples:
// Follow a blog by URL
await client.followBlog({ url: 'cool-blog.tumblr.com' });
console.log('Blog followed successfully');
// Follow a blog by full URL
await client.followBlog({ url: 'https://cool-blog.tumblr.com/' });
// Follow a blog by email (if supported)
await client.followBlog({ email: 'blogger@example.com' });
// Follow multiple blogs
const blogsToFollow = [
'photography-blog.tumblr.com',
'art-blog.tumblr.com',
'music-blog.tumblr.com'
];
for (const blogUrl of blogsToFollow) {
try {
await client.followBlog({ url: blogUrl });
console.log(`Followed ${blogUrl}`);
} catch (error) {
console.error(`Failed to follow ${blogUrl}:`, error.message);
}
}Unfollow a blog as the authenticated user.
/**
* Unfollow a blog as the authenticating user
* @param params - Blog URL to unfollow
* @returns Promise resolving to unfollow confirmation
*/
unfollowBlog(params: { url: string }): Promise<any>;Usage Examples:
// Unfollow a blog by URL
await client.unfollowBlog({ url: 'some-blog.tumblr.com' });
console.log('Blog unfollowed successfully');
// Unfollow blogs from your following list
const following = await client.userFollowing({ limit: 10 });
for (const blog of following.blogs) {
if (blog.name.includes('spam')) {
await client.unfollowBlog({ url: blog.url });
console.log(`Unfollowed ${blog.name}`);
}
}type FollowBlogParams = { url: string } | { email: string };
interface FollowByUrl {
/** Blog URL to follow (can be short form or full URL) */
url: string;
}
interface FollowByEmail {
/** Email address associated with the blog */
email: string;
}interface UnfollowBlogParams {
/** Blog URL to unfollow */
url: string;
}// Get post information from blog posts
const posts = await client.blogPosts('target-blog');
const targetPost = posts.posts[0];
console.log('Post ID:', targetPost.id);
console.log('Reblog Key:', targetPost.reblog_key);
// Now you can like/unlike the post
await client.likePost(targetPost.id, targetPost.reblog_key);// Get posts from dashboard with like/reblog capabilities
const dashboard = await client.userDashboard({
reblog_info: true,
notes_info: true
});
dashboard.posts.forEach(async (post) => {
if (post.can_like && !post.liked) {
console.log(`Can like post ${post.id} by ${post.blog_name}`);
// await client.likePost(post.id, post.reblog_key);
}
});// Discover blogs through tagged posts
const taggedPosts = await client.taggedPosts('photography');
const uniqueBlogs = [...new Set(taggedPosts.response.map(post => post.blog_name))];
console.log('Blogs posting about photography:');
uniqueBlogs.forEach(blogName => {
console.log(`- ${blogName}.tumblr.com`);
});
// Follow interesting blogs
for (const blogName of uniqueBlogs.slice(0, 5)) {
await client.followBlog({ url: `${blogName}.tumblr.com` });
}async function likeAllPostsFromBlog(blogName, maxPosts = 20) {
const posts = await client.blogPosts(blogName, { limit: maxPosts });
for (const post of posts.posts) {
try {
await client.likePost(post.id, post.reblog_key);
console.log(`Liked post ${post.id} from ${post.blog_name}`);
// Add delay to avoid rate limiting
await new Promise(resolve => setTimeout(resolve, 1000));
} catch (error) {
console.error(`Failed to like post ${post.id}:`, error.message);
}
}
}async function unfollowInactiveBlogs(daysSinceUpdate = 365) {
const cutoffTime = Date.now() / 1000 - (daysSinceUpdate * 24 * 60 * 60);
const following = await client.userFollowing();
for (const blog of following.blogs) {
if (blog.updated < cutoffTime) {
try {
await client.unfollowBlog({ url: blog.url });
console.log(`Unfollowed inactive blog: ${blog.name}`);
// Add delay to avoid rate limiting
await new Promise(resolve => setTimeout(resolve, 500));
} catch (error) {
console.error(`Failed to unfollow ${blog.name}:`, error.message);
}
}
}
}async function likeInterestingDashboardPosts(keywords = []) {
const dashboard = await client.userDashboard({ limit: 20 });
for (const post of dashboard.posts) {
if (!post.liked && post.can_like) {
// Check if post contains interesting keywords
const postText = (post.title || '') + ' ' + (post.body || '') + ' ' + (post.tags || []).join(' ');
const hasKeyword = keywords.some(keyword =>
postText.toLowerCase().includes(keyword.toLowerCase())
);
if (hasKeyword) {
try {
await client.likePost(post.id, post.reblog_key);
console.log(`Liked post about "${keywords.find(k => postText.toLowerCase().includes(k.toLowerCase()))}"`);
} catch (error) {
console.error(`Failed to like post ${post.id}:`, error.message);
}
}
}
}
}
// Usage
await likeInterestingDashboardPosts(['photography', 'art', 'design']);All social interaction methods require OAuth authentication:
// Must have full OAuth credentials
const client = tumblr.createClient({
consumer_key: 'your-consumer-key',
consumer_secret: 'your-consumer-secret',
token: 'user-oauth-token',
token_secret: 'user-oauth-token-secret'
});
// These will fail without authentication
try {
await client.likePost('12345', 'abc123');
await client.followBlog({ url: 'some-blog.tumblr.com' });
} catch (error) {
if (error.message.includes('401')) {
console.error('OAuth authentication required');
}
}async function likePostsWithDelay(posts, delayMs = 1000) {
for (const post of posts) {
try {
await client.likePost(post.id, post.reblog_key);
console.log(`Liked post ${post.id}`);
// Wait between requests to avoid rate limiting
await new Promise(resolve => setTimeout(resolve, delayMs));
} catch (error) {
if (error.message.includes('429')) {
console.log('Rate limit hit, waiting 60 seconds...');
await new Promise(resolve => setTimeout(resolve, 60000));
// Retry the request
await client.likePost(post.id, post.reblog_key);
} else {
console.error(`Error liking post:`, error.message);
}
}
}
}async function safelyFollowBlog(blogUrl) {
try {
await client.followBlog({ url: blogUrl });
return { success: true, message: `Followed ${blogUrl}` };
} catch (error) {
if (error.message.includes('403')) {
return { success: false, message: 'Blog does not allow follows or is private' };
} else if (error.message.includes('404')) {
return { success: false, message: 'Blog not found' };
} else if (error.message.includes('429')) {
return { success: false, message: 'Rate limit exceeded, try again later' };
} else {
return { success: false, message: `Unknown error: ${error.message}` };
}
}
}
// Usage
const result = await safelyFollowBlog('example-blog.tumblr.com');
console.log(result.message);async function smartLikePosts(blogName) {
const posts = await client.blogPosts(blogName, {
reblog_info: true,
notes_info: true
});
for (const post of posts.posts) {
// Check if we can and should like this post
if (post.can_like && !post.liked) {
try {
await client.likePost(post.id, post.reblog_key);
console.log(`Liked ${post.type} post: ${post.summary || post.title || post.id}`);
} catch (error) {
console.error(`Cannot like post ${post.id}:`, error.message);
}
} else if (post.liked) {
console.log(`Already liked post ${post.id}`);
} else {
console.log(`Cannot like post ${post.id} (permissions)`);
}
}
}