Hey there, fellow JavaScript enthusiasts! Ready to dive into the world of Tumblr API integration? Let's get our hands dirty with some code and learn how to sync data for a user-facing integration. Buckle up!
First things first, let's get our API credentials sorted. Head over to the Tumblr API console and grab your OAuth keys. Once you've got those, we'll use the handy Tumblr.js library to make our lives easier.
npm install tumblr.js
Now, let's set up our client:
const Tumblr = require('tumblr.js'); const client = new Tumblr.Client({ consumer_key: 'YOUR_CONSUMER_KEY', consumer_secret: 'YOUR_CONSUMER_SECRET', token: 'USER_TOKEN', token_secret: 'USER_TOKEN_SECRET' });
Time to fetch some data! Let's grab the user's recent posts:
async function getRecentPosts(blogIdentifier, limit = 20) { try { const response = await client.blogPosts(blogIdentifier, { limit }); return response.posts; } catch (error) { console.error('Error fetching posts:', error); throw error; } }
Creating a new post is a breeze:
async function createTextPost(blogIdentifier, title, body, tags = []) { try { const response = await client.createTextPost(blogIdentifier, { title, body, tags }); return response; } catch (error) { console.error('Error creating post:', error); throw error; } }
Now for the fun part – let's create a basic sync function:
async function syncPosts(blogIdentifier, localPosts) { const remotePosts = await getRecentPosts(blogIdentifier); for (const localPost of localPosts) { const remotePost = remotePosts.find(p => p.id === localPost.id); if (!remotePost) { await createTextPost(blogIdentifier, localPost.title, localPost.body, localPost.tags); } else if (localPost.updated > remotePost.updated) { await client.editPost(blogIdentifier, localPost.id, { title: localPost.title, body: localPost.body, tags: localPost.tags }); } } }
Let's wrap our API calls with some error handling magic:
async function apiWrapper(apiCall) { try { return await apiCall(); } catch (error) { if (error.status === 429) { console.log('Rate limit hit. Retrying in 60 seconds...'); await new Promise(resolve => setTimeout(resolve, 60000)); return apiWrapper(apiCall); } throw error; } }
Caching can be a game-changer. Here's a simple in-memory cache:
const cache = new Map(); function getCachedData(key, ttl, fetchFunction) { if (cache.has(key) && Date.now() - cache.get(key).timestamp < ttl) { return cache.get(key).data; } const data = fetchFunction(); cache.set(key, { data, timestamp: Date.now() }); return data; }
Always keep those OAuth tokens safe! Store them securely and never expose them in client-side code:
const crypto = require('crypto'); function encryptToken(token, secretKey) { const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv('aes-256-cbc', secretKey, iv); let encrypted = cipher.update(token, 'utf8', 'hex'); encrypted += cipher.final('hex'); return iv.toString('hex') + ':' + encrypted; }
Don't forget to test! Here's a quick example using Jest:
jest.mock('tumblr.js'); test('syncPosts creates new posts', async () => { const mockCreate = jest.fn().mockResolvedValue({ id: 'new-post-id' }); Tumblr.Client.mockImplementation(() => ({ blogPosts: jest.fn().mockResolvedValue({ posts: [] }), createTextPost: mockCreate })); await syncPosts('blog.tumblr.com', [{ title: 'New Post', body: 'Content' }]); expect(mockCreate).toHaveBeenCalled(); });
And there you have it! We've covered the essentials of working with the Tumblr API for data syncing. Remember to always respect rate limits, handle errors gracefully, and keep your users' data secure.
Keep experimenting and building awesome integrations. The Tumblr community is waiting for your creative genius!
Happy coding, and may your API calls always return 200 OK! 🚀