Skip to content

Commit ed44b9b

Browse files
committed
i think this is ready (v2 update)
a lot of stuff, read up on the README.md to see how to setup the newer version...
1 parent ac8c371 commit ed44b9b

File tree

7 files changed

+1140
-861
lines changed

7 files changed

+1140
-861
lines changed

README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
# [adult swim] bump bot
22
A Twitter bot that posts random Adult Swim bumps.
33

4+
## V2 is out!!
5+
Since `twit.js` ain't workin' on my end, I gotta rewrite the bot usin' the `twitter-api-v2` npm module!!
6+
7+
Just download the latest version whenever you can `:)`
8+
9+
I've also made the bot do Twitter authentication in another file, `botAuth.js`, which is now how I authorize clients for my bots...
10+
411
## How to work.
512
1. Clone the repo - `git clone https://github.com/ktg5/asbumpbot`
613
2. Install required packages - `npm i`
7-
3. Open `config.json` and replace all the values with your own. (`botUsername` and all four keys listed)
14+
3. Open `auth.json` and replace all the listed keys (api & access) with your own.
15+
* ⚠⚠ Remember to **make sure your access keys are "`Created with Read, and Write permissions`" by enabling "`User authentication`" in your Twitter app's page!**
816
4. Start the bot - `npm start`

auth.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"api_key": "#",
3+
"api_key_secret": "##",
4+
"access_token": "#-#",
5+
"access_token_secret": "##"
6+
}

bot.js

+69-125
Original file line numberDiff line numberDiff line change
@@ -1,141 +1,85 @@
1-
const Twit = require('twit')
2-
var config = require('./config.json')
1+
const {config, client, logger} = require("./botAuth");
32
const http = require('http');
43
const fs = require('fs');
5-
var logger = require('winston');
6-
7-
8-
// Verify bot.
9-
var bot = new Twit({
10-
consumer_key: config.consumer_key,
11-
consumer_secret: config.consumer_key_secret,
12-
access_token: config.access_token,
13-
access_token_secret: config.access_token_secret,
14-
timeout_ms: 60*1000, // optional HTTP request timeout to apply to all requests.
15-
strictSSL: true, // optional - requires SSL certificates to be valid.
16-
})
17-
18-
19-
// Configure logger settings
20-
logger.remove(logger.transports.Console);
21-
logger.add(logger.transports.Console, {
22-
colorize: true
23-
});
24-
logger.level = 'debug';
25-
264

275
// getRandomArbitrary
286
function getRandomArbitrary(min, max) {
29-
return Math.floor(Math.random() * (max - min)) + min;
7+
return Math.floor(Math.random() * (max - min)) + min;
308
}
319

32-
// Make video file.
33-
var bumpNum = getRandomArbitrary(1, 8749);
34-
var url = `http://static.bumpworthy.com/bumps/${bumpNum}.d.mp4` // Get bump video file.
35-
var filepath = `media/${bumpNum}.mp4` // Set export locaiton.
36-
37-
// Check to see if the video already exists.
38-
var checkFile = fs.existsSync(filepath)
39-
console.log(checkFile)
40-
if (checkFile = false) {
41-
logger.error(`Media failed, a video file with the name is in the "media" folder. Restart to try again.`)
42-
return;
10+
// Get bot Username (can only be called when Twitter wakes up)
11+
async function getUsername() {
12+
return (await client.v2.me()).data.username;
4313
}
4414

45-
const file = fs.createWriteStream(filepath);
46-
const request = http.get(url, (response) => {
47-
response.pipe(file);
15+
console.log(`ーーーーーーーーーー✄ーーーーーーーーーー`);
16+
logger.info(`Starting process...`)
17+
// START
18+
// Time for how long until new clip is uploaded
19+
var time = config.time * 60000;
20+
// Start function
21+
function startProcess() {
22+
23+
// Make video file.
24+
var bumpNum = getRandomArbitrary(1, 8749);;
25+
var url = `http://static.bumpworthy.com/bumps/${bumpNum}.d.mp4` // Get bump video file.
26+
var filepath = `media/${bumpNum}.mp4` // Set export locaiton.
27+
28+
// Check to see if the video already exists.
29+
var checkFile = fs.existsSync(filepath)
30+
if (checkFile = false) {
31+
logger.error(`Media failed, a video file with the name is in the "media" folder. Restart to try again.`)
32+
return;
33+
}
4834

49-
file.on('finish',() => { // When file is done downloaded.
35+
// Download video.
36+
const file = fs.createWriteStream(filepath);
37+
const thing = http.get(url, (response) => {
38+
response.pipe(file);
5039

51-
file.close();
52-
console.log(`ーーーーーーーーーー✄ーーーーーーーーーー`);
53-
logger.info('Download Completed');
54-
55-
var filePath = `./${filepath}`
56-
bot.postMediaChunked({ file_path: filePath }, function (err, data, response) {
57-
console.log(`ーーーーーーーーーー✄ーーーーーーーーーー`);
58-
if (err) {
59-
logger.error("postMediaChunked error")
60-
console.log(err)
61-
return;
62-
}
63-
64-
// Log media chunk info. (FOR DEBUG)
65-
// logger.info("postMediaChunked data:")
66-
// console.log(data)
67-
68-
const mediaIdStr = data.media_id_string;
69-
const meta_params = { media_id: mediaIdStr };
70-
71-
pollStatus(bot, mediaIdStr, 0, function() {
72-
// Create media metadata.
73-
bot.post('media/metadata/create', meta_params, function (err, data, response) {
74-
console.log(`ーーーーーーーーーー✄ーーーーーーーーーー`);
75-
if (!err) {
76-
// Make the tweet params.
77-
var params = { media_ids: [mediaIdStr] }
78-
79-
bot.post('statuses/update', params, function (err, data, response) {
80-
logger.info(`Main tweet posted: https://twitter.com/${config.botUsername}/status/${data.id_str}`)
81-
82-
// Log tweet data (FOR DEBUG)
83-
// logger.info("statuses/update data:")
84-
// console.log(data)
85-
86-
var mainTweet = data.id_str;
87-
88-
bot.post('statuses/update', {status: `[source: https://bumpworthy.com/bumps/${bumpNum}]`, in_reply_to_status_id: mainTweet}, function (err, data, response) {
89-
logger.info(`Reply tweet posted: https://twitter.com/${config.botUsername}/status/${data.id_str}`)
90-
91-
// Log tweet data (FOR DEBUG)
92-
// logger.info("statuses/update data:")
93-
// console.log(data)
94-
});
95-
});
96-
} else {
97-
// If something happened.
98-
logger.error("media/metadata/create error:")
99-
console.log(err)
100-
}
101-
});
102-
});
103-
});
104-
});
105-
});
40+
file.on('finish', async () => { // When file is done downloaded.
41+
file.close();
10642

107-
console.log(`ーーーーーーーーーー✄ーーーーーーーーーー`);
43+
if (file.bytesWritten <= 500) {
44+
logger.error(`The bump received (ID: ${bumpNum}) might be not be an actual file.`)
45+
logger.error(`At the moment, the only way to solve this is to restart, sorry... :(`)
46+
return;
47+
}
10848

49+
console.log(`ーーーーーーーーーー✄ーーーーーーーーーー`);
50+
logger.info('Download Completed');
10951

110-
// Get media status from Twitter for uploading media.
111-
function pollStatus(bot, mediaIdStr, progressPercent, callback) {
112-
bot.get("media/upload", { command: "STATUS", media_id: mediaIdStr }, function(err, data, response) {
113-
// Log media data (FOR DEBUG)
114-
// console.log(data)
52+
console.log(`ーーーーーーーーーー✄ーーーーーーーーーー`);
53+
logger.info('Upload Started...');
11554

116-
if (progressPercent == 2) {
117-
logger.error(`Media failed, the video can not be uploaded. Restart to try again.`)
118-
return
119-
}
55+
var filePath = `./${filepath}`;
12056

121-
if (err) {
122-
// If something happened.
123-
logger.error("pollStatus error:")
124-
console.log(err)
125-
return
126-
} else {
127-
if (data && data.processing_info && data.processing_info.state === "succeeded") { // When the media is uploaded.
128-
logger.info("Media uploaded.")
129-
callback(); // Go back to main code.
130-
} else {
131-
logger.info(`Media is uploading. Progress: ${data.processing_info.progress_percent}, retrying...`)
132-
133-
if (data.processing_info.progress_percent == "100") {
134-
progressPercent++
135-
}
136-
137-
setTimeout(() => {pollStatus(bot, mediaIdStr, progressPercent, callback, err)}, 1000); // Retry after the secs provided by Twitter.
138-
}
139-
}
140-
})
141-
}
57+
// Upload media first...
58+
const mediaIds = await Promise.all([
59+
client.v1.uploadMedia(filePath),
60+
]);
61+
logger.info('Upload Completed');
62+
63+
// Then we can send in the tweet.
64+
var mainTweet = await client.v1.tweet('', { media_ids: mediaIds })
65+
console.log(`ーーーーーーーーーー✄ーーーーーーーーーー`);
66+
// get bot username for logs
67+
var botUsername = await getUsername();
68+
logger.info(`Sent main tweet; https://twitter.com/${botUsername}/status/${mainTweet.id_str}`);
69+
70+
// Oh! Don't forget the reply!
71+
var replyTweet = await client.v1.reply(`[source: https://bumpworthy.com/bumps/${bumpNum}]`, mainTweet.id_str);
72+
logger.info(`Sent reply tweet; https://twitter.com/${botUsername}/status/${replyTweet.id_str}`);
73+
});
74+
});
75+
};
76+
77+
// Start the bot when first loaded.
78+
startProcess();
79+
80+
// After a while, start again.
81+
setInterval(() => {
82+
console.log(`ーーーーーーーーーー✄ーーーーーーーーーー`);
83+
logger.info(`Time hit! Redoing process...`)
84+
startProcess();
85+
}, time);

botAuth.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const { TwitterApi } = require('twitter-api-v2');
2+
const auth = require(`./auth.json`)
3+
const config = require('./config.json');
4+
const logger = require('winston');
5+
6+
7+
// Configure logger settings
8+
logger.remove(logger.transports.Console);
9+
logger.add(logger.transports.Console, {
10+
colorize: true
11+
});
12+
logger.level = 'debug';
13+
14+
15+
// Verify bot.
16+
// V1 Read/Write access
17+
const authClient = new TwitterApi({
18+
appKey: auth.api_key,
19+
appSecret: auth.api_key_secret,
20+
accessToken: auth.access_token,
21+
accessSecret: auth.access_token_secret,
22+
});
23+
24+
// // App only
25+
// const bearer = new TwitterApi(auth.bearer_key);
26+
27+
// Set settings
28+
const client = authClient.readWrite;
29+
30+
logger.info(`Logged into Twitter!`)
31+
32+
module.exports = {config, client, logger}

config.json

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
{
2-
"botUsername": "(TWITTER USERNAME)",
3-
4-
"consumer_key": "#",
5-
"consumer_key_secret": "##",
6-
"access_token": "#-#",
7-
"access_token_secret": "###w"
2+
"time": "60" ,
3+
"_comment": "The above will upload a bump every hour (60 minutes)"
84
}

0 commit comments

Comments
 (0)