Package: redditquotebot
Reddit Quote BotReads all comments in selected subreddits and compares their comments to famous quotes. On a close match, replies with the full quote, crediting the original author.I'm live! Check out what I've been up to onReddit.OverviewThe bot periodically requests comments from selected subreddits, sorted by newest submissions. Each comment, is compared for similarity to a dataset ofquotesusingspacy. If a high similarity is detected, a reply is generated and posted as a response to the original comment.Running a bot instanceUsing PythonThe package is available onpypi, it can be installed with:pipinstallredditquotebotA Spacy language model is also needed for natural language processing. Testing is conducted withen-core-web-md:pipinstallhttps://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.4.1/en_core_web_md-3.4.1-py3-none-any.whlGenerate the configuration and credential templates in the current directory (see reference below):reddit_quote_bot.py-gStart up the bot:reddit_quote_bot.pyUsing DockerCurrently, the only option is to build the container from source. Eventually, this will be pushed toDocker Hub.Clone this repository:gitclonehttps://github.com/etdds/redditQuoteBot.gitcdredditQuoteBotBuild the docker container:make build-image
# or
docker build -t etdds/reddit-quote-bot:latest .Start up the bot. The configuration and credential templates are generated on the first run. Populate these files then restart the container.# Initial run to generate configuration
docker run -v $(pwd):/home/app_user/run etdds/reddit-quote-bot

# Run the container, detached, restarting unless stopped.
docker run --restart unless-stopped -d -v $(pwd):/home/app_user/run etdds/reddit-quote-botThe mounted directory is used to store the configuration files, credentials, comment and reply records and state.Runtime file descriptionsThe bot uses four files during runtime, these are created and stored in the directory from where the bot is started.ConfigurationThe configuration fileconfiguration.jsonis created the first time is run, and read once on startup.{"reddit":{"subreddits":["test"],"new_submissions_per_request":10,"max_comments_per_request":100,"minimum_comment_length":15},"bot":{"reply_to_comments":true,"reply_threshold":0.99,"matched_quotes_to_log":3,"remove_own_comments":true,"remove_comment_threshold":-1},"nlp":{"match_store_threshold":0.97,"quote_comment_length_delta":0.7,"minimum_comment_sentence_word_length":5,"quote_length_bonus_coefficient":0.0008,"quote_length_bonus_start":6,"quote_length_bonus_end":10,"matched_sentence_coefficient":0.5,"discard_comments_with_author":true},"records":{"maximum_comment_count":0,"maximum_match_count":100,"maximum_reply_count":null}}SectionSubsectionDescriptionredditsubredditList of subreddits from which comments are takennew_submissions_per_requestThe maximum number of submissions (posts) which are takenmax_comments_per_requestThe maximum number comments which are queried per request.minimum_comment_lengthThe minimum length of a comment which is stored. Shorter comments are discarded.botreply_to_commentsIf set to true, replies are posted to reddit. If false, they are only logged inrecords.jsonreply_thresholdThe NLP score needed in order for a reply to be sent. Ranging between 0-1matched_quotes_to_logThe number of matches abovematch_store_thresholdto log.remove_own_commentsToggle the bot's ability to remove it's own commentsremove_comment_thresholdToggle the comment score at which a comment is removed. Comments which score equal or below this value are removed.nlpmatch_store_thresholdThe NLP score threshold for comments which are stored, undermatchesinrecords.jsonquote_comment_length_deltaThe maximum difference ratio between the length of a comments sentence and quote sentence to be compared. Quote / comment sentence ratios outside this range are discarded.minimum_comment_sentence_word_lengthThe minimum word length a comment needs to be in order to be compared with a quote.quote_length_bonus_coefficientThe coefficient applied per word to the NLP score for comment quote sentences matches when they longer thanquote_length_bonus_startquote_length_bonus_startThe starting quote sentence length needed for the NLP score bonus to be applied.quote_length_bonus_endThe maximum quote sentence length to which a bonus NLP score is applied.discard_comments_with_authorDefine if comments should be matched to quotes when the body of the comment contains the author of the quoterecordsmaximum_comment_countSpecify the maximum number of comments to be logged inrecords.json. 0 = None, null = No limitmaximum_match_countSpecify the maximum number of matches to be logged inrecords.json. 0 = None, null = No limitmaximum_reply_countSpecify the maximum number of replies to be logged inrecords.json. 0 = None, null = No limitmaximum_removed_comment_countSpecify the maximum number of removed comments to be logged inrecords.json. 0 = None, null = No limitCredentialsThe credentials filecredentials.jsonis created the first time is run, and read once on startup. Currently, this means the credentials are stored in plain text. This should be changed.The fields for theredditobject are identically named, and passed directly toPraw. See Praw's documentationhere.{"reddit":{"user_agent":"","client_id":"","client_secret":"","username":"","password":""}}RecordsThe record file,records.jsonis automatically generated and updated during the bots runtime. A minimum example would look like:Comments SectionContains a log of all comments fetched which meet the minimum length criteria, have not been edited, and are not part of the author blacklist.Matches SectionContains a log of all comments and quotes which matched with a score above thematch_store_thresholdscore.Replies SectionContains a log of all replies which have been sent (or just logged ifreply_to_commentsis set to false). These are generally matches with a score abovereply_threshold.Removed SectionContains a log of all self-posted comments that the bot has removed.Banned Subreddit SectionContains a list of subreddits which the bot thinks it is banned from. This is determined by receiving a forbidden exception when trying to post a reply.{"records":{"comments":[{"body":"Eight billion people, it is a momentous milestone for humanity\n\nYet, I realise this moment might not be celebrated by all.\n\nInstead of the fear of overpopulation, we should focus on the overconsumption of the planet\u2019s resources by the wealthiest among us.","utc":1667800195.0,"author":"cop3213","url":"https://reddit.com/r/worldnews/comments/yodyyg/planet_earth_8_billion_people_and_dwindling/ivdteb8/","subreddit":"r/worldnews","edited":false,"uid":"ivdteb8"},],"matches":[{"comment":{"body":"The question feels very cryptic. What are you trying to do?","utc":1667805202.0,"author":"dbug89","url":"https://reddit.com/r/AusFinance/comments/yofkj7/salary_sacrificing_super/ivdzyjj/","subreddit":"r/AusFinance","edited":false,"uid":"ivdzyjj"},"quote":{"body":"Always do what you are afraid to do.","author":"Ralph Waldo Emerson","category":["'inspirational'"]},"score":0.9728559309059505}],"replies":[{"quote":{"body":"Just because you're paranoid doesn't mean they aren't after you.","author":"Joseph Heller,","category":["'misattributed-kurt-cobain'"]},"comment":{"body":"*just because you're not paranoid doesn't mean they're not after you*","utc":1667874409.0,"author":"peter-doubt","url":"https://reddit.com/r/worldnews/comments/yp7yux/afp_says_it_does_not_believe_china_has_an_active/ivhyeqv/","subreddit":"r/worldnews","edited":false,"uid":"ivhyeqv"},"body":"Hi peter-doubt,\n\nIt looks like your comment closely matches the famous quote:\n\n\"Just because you're paranoid doesn't mean they aren't after you.\"\n\nJoseph Heller,\n\nI'm a bot and this action was automatic. [project source](https://www.google.com)\n        "}],"removed":[{"body":"Hi Mikey2bz,\n\nIt looks like your comment closely matches the famous quote:\n\n\"It hurts to let go. Sometimes it seems the harder you try to hold on to something or someone the more it wants to get away. You feel like some kind of criminal for having felt, for having wanted. For having wanted to be wanted. It confuses you, because you think that your feelings were wrong and it makes you feel so small because it's so hard to keep it inside when you let it out and it doesn't coma back. You're left so alone that you can't explain. Damn, there's nothing like that, is there? I've been there and you have too. You're nodding your head.\" - Henry Rollins,\n\n*I'm a bot and this action was automatic [Project source](https://github.com/etdds/redditQuoteBot).*","utc":1669551675.0,"author":"redditQuoteBot","url":"https://reddit.com/r/Futurology/comments/z5mtb3/we_tasted_the_worlds_first_cultivated_steak_no/ixyo0nc/","subreddit":"r/Futurology","edited":false,"uid":"ixyo0nc","score":-2},],"banned_subreddits":["test"]}}Bot StateThe current state of the bot is stored in an autogenerated filescrape_state.json. Currently, this only keeps a log of the latest comment timestamp in UTC for each subreddit queried.{"latest_comments":{"worldnews":1667877818.0,"science":1667877772.0,"AusFinance":1667877814.0,"news":1667877770.0,"ShowerThoughts":1667877860.0,"askscience":1667875135.0,"nottheonion":1667877792.0,"space":1667877875.0,"books":1667877515.0,"UpliftingNews":1667877390.0,"test":1667856381.0}}DevelopmentThe repository is setup to use VSCode with the remote development plugin. Everything should be self-contained within this environment.Contributions and suggestions welcome. Open and an issue or formulate a pull request.