Initial commit of the generic reddit bot

This commit is contained in:
StarAppeal
2021-01-30 23:06:21 +01:00
parent 43f7d887d6
commit 76923fcbea
11 changed files with 1247 additions and 2 deletions
+10
View File
@@ -0,0 +1,10 @@
CLIENT_ID=Your Client ID
CLIENT_SECRET=Your Client Secret
REFRESH_TOKEN=The refresh Token
BOT_NAME=Name of your Bot.
SUBREDDIT=The subreddit, where the bots operates on
POLL_LIMIT=Limit of posts it polls
POLL_TIME=The time the bot looks for new posts (in ms)
AUTOMOD_ID=The ID of the automod (of the user the bot will reply to)
REST_URL=URL of the rest interface, where the post text gets sent to
DEVELOPER=Your reddit user account name
+3
View File
@@ -0,0 +1,3 @@
node_modules/
.env
*.log
+3 -2
View File
@@ -1,3 +1,4 @@
# generic-reddit-bot # generic-reddit-bot
Generic reddit bot, which replies to a comment from each post in a subreddit. Generic reddit bot, which replies to a comment from each post in a subreddit.
The text from the post will be send to a rest url (which can be configured in an .env file), which handles the text manipulation if needed.
The text from the post will be send to a rest url (which can be configured in an .env file), which handles the text manipulation if needed.
+1029
View File
File diff suppressed because it is too large Load Diff
+26
View File
@@ -0,0 +1,26 @@
{
"name": "generic-reddit-bot",
"version": "1.0.0",
"description": "Generic reddit bot",
"main": "server.js",
"scripts": {
"start": "start src/server.js",
"debug": "node src/server.js DEBUG",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "\u0016https://github.com/StarAppeal/generic-reddit-bot"
},
"author": "starappeal, tsomic",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
"dateformat": "^3.0.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"snoostorm": "^1.3.0",
"snoowrap": "^1.21.0",
"winston": "^3.2.1"
}
}
+5
View File
@@ -0,0 +1,5 @@
var express = require('express');
var application = express();
module.exports = application;
+54
View File
@@ -0,0 +1,54 @@
const {
createLogger,
format,
transports
} = require('winston');
const logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp({
format: 'DD.MM.YYYY HH:mm:ss'
}),
format.errors({
stack: true
}),
format.splat(),
format.json()
),
defaultMeta: {
service: process.env.BOT_NAME
},
transports: [
//
// - Write to all logs with level `info` and below to `quick-start-combined.log`.
// - Write all logs error (and below) to `quick-start-error.log`.
//
new transports.File({
filename: 'error.log',
level: 'error'
}),
new transports.File({
filename: 'info.log',
level: 'info'
}),
new transports.File({
filename: 'combined.log'
})
]
});
//
// If we're not in production then **ALSO** log to the `console`
// with the colorized simple format.
//
if (process.env.NODE_ENV !== 'production') {
logger.add(new transports.Console({
format: format.combine(
format.colorize(),
format.simple()
)
}));
}
module.exports = logger;
+21
View File
@@ -0,0 +1,21 @@
const {
SubmissionStream
} = require("snoostorm");
const Snoowrap = require('snoowrap');
const Snoostorm = require('snoostorm');
const r = new Snoowrap({
userAgent: 'linux:'+process.env.BOT_NAME+':1.0 (by ' + process.env.DEVELOPER + ')',
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
refreshToken: process.env.REFRESH_TOKEN
});
const submissionstream = new SubmissionStream(r, {
subreddit: process.env.SUBREDDIT,
limit: process.env.POLL_LIMIT * 1, // small hack to change it from string to a number
pollTime: process.env.POLL_TIME * 1 // same as above
});
module.exports = {stream: submissionstream, wrap: r};
+82
View File
@@ -0,0 +1,82 @@
const dateFormat = require('dateformat');
const streamConfig = require("../config/streamConfig")
const logger = require("../config/logger");
const axios = require('axios');
const alreadyReplied = postId =>
streamConfig.wrap.getMe().getComments({
limit: process.env.POLL_LIMIT * 2 // removed posts won't get streamed, but the comments to these removed posts still show up.
}).then(comments => {
for (comment of comments) {
if (comment.link_id.includes(postId)) return true;
}
return false;
});
function startStream() {
streamConfig.stream.on("item", post => {
logger.info("found post with id: " + post.id + " posted at: " + dateFormat(new Date(post.created_utc * 1000), "dd.mm.yyyy hh:MM:ss"));
streamConfig.wrap.getSubmission(post.id).comments.then(async (comments) => {
if (await alreadyReplied(post.id)) {
logger.info("Already replied to this post, gonna skip.");
return;
}
try {
checkForAutomodComment(comments, 5000).then(c => replyToComment(post, c)).catch(e => logger.error(e));
} catch (e) {
logger.error(e);
}
});
});
}
async function checkForAutomodComment(comments, wait, i = 1) {
logger.info('Searching for Automod comment...');
var c;
for (comment of comments) {
if (comment.author_fullname === process.env.AUTOMOD_ID) {
c = comment;
}
}
if (!c) {
logger.info('No Automod Comment found, checking again soon...');
logger.info('This was try #' + i);
if (i === 20) {
logger.info('Not found after 20 tries, doubling wait time');
wait *= 2;
}
await new Promise(r => setTimeout(r, wait));
return checkForAutomodComment(post, wait, i + 1)
} else {
logger.info('Automod comment found!');
return c;
}
}
function replyToComment(post, comment) {
if (process.argv[2] === 'DEBUG') {
console.log("I would reply but im locally started so I do not. Sorry mate");
return;
}
let url = process.env.REST_URL;
let objectToSend = {
text: post.selftext
};
logger.info("post requesting to url " + url);
logger.info(JSON.stringify(objectToSend));
axios.post(url, objectToSend).then(response => {
let result = response.data;
logger.info("Didn't reply to post with ID: " + post.id + "... reply to it now!");
comment.reply(result.result);
logger.info('Text of reply was: ' + result.result);
logger.info("post request took " + result.timeNeeded + "ms!");
}).catch(error => {
logger.error(error);
});
}
module.exports = {
startStream: startStream
};
+12
View File
@@ -0,0 +1,12 @@
require('dotenv').config();
const app = require('./app');
const http = require('http');
const roboter = require("./roboter/genericBoter");
var port = process.argv[2] === 'DEBUG' ? 81 : process.env.PORT;
http.createServer(app).listen(port, function() {
console.log("App listens on port: " + this.address().port);
roboter.startStream();
});
+2
View File
@@ -0,0 +1,2 @@
npm run debug
pause