Skip to content

Instantly share code, notes, and snippets.

@stefanbohacek
Last active December 3, 2023 12:57
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save stefanbohacek/b307d5d94d6f38efbf0a1be8e2ebd19b to your computer and use it in GitHub Desktop.
Save stefanbohacek/b307d5d94d6f38efbf0a1be8e2ebd19b to your computer and use it in GitHub Desktop.
/*
A simple Twitter bot that posts random images.
Tutorial: https://botwiki.org/resource/tutorial/random-image-tweet/
*/
const fs = require('fs'),
path = require('path'),
Twit = require('twit'),
config = require(path.join(__dirname, 'config.js'));
/*
Your config.js file should have the following format:
const config = {
consumer_key: 'XXXXX',
consumer_secret: 'XXXXX',
access_token: 'XXXXX',
access_token_secret: 'XXXXX'
}
module.exports = config;
Here's a tutorial on how to get the API keys: https://botwiki.org/resource/tutorial/how-to-create-a-twitter-app/
*/
const T = new Twit(config);
const randomFromArray = (arr) => {
/* Helper function for picking a random item from an array. */
return arr[Math.floor(Math.random() * arr.length)];
}
const tweetRandomImage = () => {
/* First, read the content of the images folder. */
fs.readdir(__dirname + '/images', (err, files) => {
if (err){
console.log('error:', err);
return;
} else {
let images = [];
files.forEach((f) => {
images.push(f);
});
/* Then pick a random image. */
console.log('opening an image...');
const imagePath = path.join(__dirname, '/images/' + randomFromArray(images)),
imageData = fs.readFileSync(imagePath, { encoding: 'base64' });
/* Upload the image to Twitter. */
console.log('uploading an image...', imagePath);
T.post('media/upload', { media_data: imageData }, (err, data, response) => {
if (err){
console.log('error:', err);
} else {
/* Add image description. */
const image = data;
console.log('image uploaded, adding description...');
T.post('media/metadata/create', {
media_id: image.media_id_string,
alt_text: {
text: 'Describe the image'
}
}, (err, data, response) => {
/* And finally, post a tweet with the image. */
T.post('statuses/update', {
// status: 'Optional tweet text.',
media_ids: [image.media_id_string]
},
(err, data, response) => {
if (err){
console.log('error:', err);
} else {
console.log('posted an image!');
/*
After successfully tweeting, we can delete the image.
Keep this part commented out if you want to keep the image and reuse it later.
*/
// fs.unlink(imagePath, (err) => {
// if (err){
// console.log('error: unable to delete image ' + imagePath);
// } else {
// console.log('image ' + imagePath + ' was deleted');
// }
// });
}
});
});
}
});
}
});
}
setInterval(() => {
tweetRandomImage();
}, 10000);
@jsobczak-um
Copy link

This is awesome - thank you so much for sharing! Is there any way to modify this to post two random images within the same tweet? I understood most of what was going on until it hit media_ids: new Array( data.media_id_string ). Have a great day!

@stefanbohacek
Copy link
Author

Yes, you can absolutely post multiple images in a tweet, notice how media_ids is an array of the media IDs you uploaded.

The tricky part will be uploading all the images and waiting for that to finish so that you can pass the list of media IDs to the tweet.

I can try to put together an example code when I have a bit more time, but I think this should give you an idea how to approach this:

https://stackoverflow.com/a/32833133

@jsobczak-um
Copy link

Thank you very much for the clarification and link! I will keep playing around with this to see if I can get something to work.

@ayamkv
Copy link

ayamkv commented Jun 27, 2021

what if i want to post images in order. 'image1.png , image2.png...' ?

@stefanbohacek
Copy link
Author

@ayamkv There's a few ways you can achieve that.

  • name and sort your images in the order in which you want them tweeted out, and delete each image that gets posted
  • keep a track of which images have been posted in another file

If you need help with the code, or would like to get more ideas, you can join botmakers.org on Slack.

@LuxStatera
Copy link

just to confirm so I dont mess up the bot. how do I add the same hashtags to every picture?

@stefanbohacek
Copy link
Author

@LuxStatera: See the optional status parameter, like this:

T.post( 'statuses/update', {
    status: '#hashtag',
    media_ids: [image.media_id_string]
}

@LuxStatera
Copy link

@fourtonfish thank you!

@stefanbohacek
Copy link
Author

No problem!

@LuxStatera
Copy link

i am also very interested in the code to tweet pictures in order and delete them after they have been tweeted. i feel like this will solve my problem of too many duplicates and also after a few days of posting it will stop and i get an error saying JS stacktrace FATAL ERROR: Ineffective mark-compacts near heap limit allocation failed - javascript heap of of memory. i tried to give it more space with the command export NODE_OPTIONS=--max-old-space-size=14000 but it still gives me that fatal error after a few days. is there a way to allow it to run nonstop?

@stefanbohacek
Copy link
Author

As for the memory issue, hard to tell without seeing the full code, but if your bot only runs on a schedule, would it be an option for you to use cron?

To delete an image after it's tweeted see the fs.unlink section that's commented out above. You could name your files alphabetically (image-001.png, image-002.png, etc) to ensure the correct order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment