Initial commit of the generic reddit bot
This commit is contained in:
@@ -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
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules/
|
||||||
|
.env
|
||||||
|
*.log
|
||||||
@@ -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.
|
||||||
|
|||||||
Generated
+1029
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
var express = require('express');
|
||||||
|
|
||||||
|
var application = express();
|
||||||
|
|
||||||
|
module.exports = application;
|
||||||
@@ -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;
|
||||||
@@ -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};
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -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();
|
||||||
|
});
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
npm run debug
|
||||||
|
pause
|
||||||
Reference in New Issue
Block a user