Add back reddit inbox listening mode; now configurable using the 'mode' config parameter.
Add support for notifying reddit users of generation in 'immediately' mode.
This commit is contained in:
parent
abb36769fe
commit
809ffd05ec
3 changed files with 73 additions and 22 deletions
|
@ -11,7 +11,7 @@ pip3 install --upgrade https://git.caspervk.net/caspervk/dailyreleases/archive/m
|
|||
**It requires Python 3.6 or later.**
|
||||
|
||||
### Usage
|
||||
The program can be started by running `dailyreleases` or `python3 -m dailyreleases` depending on system configuration.
|
||||
The bot can be started by running `dailyreleases` or `python3 -m dailyreleases` depending on system configuration.
|
||||
|
||||
### Configuration
|
||||
The default configuration file will be copied to `~/.dailyreleases/config.ini` on the first run. All fields under the
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
[main]
|
||||
# true : Listen for reddit PMs; on receipt, generate and submit post to own subreddit. Reply with link to post.
|
||||
# false : Immediately generate and print post to log and console. Nothing is posted to reddit.
|
||||
production = false
|
||||
|
||||
# mode =
|
||||
# immediately : Immediately generate and submit post to own subreddit. PM reddit notify_users with link to post.
|
||||
# reply : Listen for reddit PMs; on receipt, generate and submit post to own subreddit. Reply with link to post.
|
||||
# test : Generate and print to log and console. Nothing is posted to reddit.
|
||||
mode = test
|
||||
|
||||
|
||||
[logging]
|
||||
|
@ -19,10 +22,15 @@ user_agent = <platform>:<app ID>:<version string> (by /u/<reddit username>)
|
|||
username = xxxxxxxxxxxxx
|
||||
password = xxxxxxx
|
||||
|
||||
# List of users who are allowed to PM the bot.
|
||||
# List of users who are authorized to start the generation by PM'ing the bot. Only applies to 'reply' mode.
|
||||
authorized_users = spez,Deimorz,kn0thing
|
||||
|
||||
# Reddit perceives PMs with many links as spam, so the bot posts the code for the generated post in its own subreddit.
|
||||
# List of users who should receive a PM on generation. Only applies to 'immediately' mode, since the sender will receive
|
||||
# the PM in 'reply' mode.
|
||||
notify_users = chooter,GallowBoob
|
||||
|
||||
# Reddit perceives PMs with many links as spam, so the bot posts the code for the generated post in its own subreddit
|
||||
# instead of sending it directly in the PM.
|
||||
bot_subreddit = dailyreleases
|
||||
|
||||
# It also needs to know of the subreddit where the daily releases threads are posted so it can link to the previous one.
|
||||
|
@ -42,5 +50,5 @@ key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|||
|
||||
[web]
|
||||
# Number of seconds to cache web requests (google, steam etc.). May help reduce the number of requests if the same game
|
||||
# has multiple scene releases on the same day.
|
||||
# has multiple releases on the same day.
|
||||
cache_time = 600
|
|
@ -1,3 +1,4 @@
|
|||
import inspect
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
|
@ -7,6 +8,7 @@ import time
|
|||
from collections import defaultdict
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import prawcore
|
||||
import requests_cache
|
||||
|
||||
from dailyreleases import config, __version__, util
|
||||
|
@ -41,12 +43,38 @@ class DailyReleasesBot(object):
|
|||
self.reddit = Reddit(self.config)
|
||||
|
||||
def run(self):
|
||||
# If not production, generate now (without posting to reddit) and then exit
|
||||
if not self.config["main"].getboolean("production"):
|
||||
self.generate()
|
||||
return
|
||||
mode = self.config["main"]["mode"]
|
||||
|
||||
self.generate(do_post=True)
|
||||
if mode == "test":
|
||||
self.generate(post=False)
|
||||
|
||||
if mode == "immediately":
|
||||
self.generate(post=True, pm_recipients=self.config["reddit"]["notify_users"].split(","))
|
||||
|
||||
if mode == "reply":
|
||||
self.listen_inbox()
|
||||
|
||||
def listen_inbox(self):
|
||||
logger.info("Listening on reddit inbox stream")
|
||||
authorized_users = self.config["reddit"]["authorized_users"].split(",")
|
||||
|
||||
while True:
|
||||
try:
|
||||
for message in self.reddit.praw.inbox.stream():
|
||||
if message.author in authorized_users:
|
||||
self.generate(post=True, pm_recipients=(message.author.name,))
|
||||
else:
|
||||
logger.info("Discarding PM from %s: not authorized user", message.author)
|
||||
|
||||
message.mark_read() # mark message read last so we can retry after potential fatal errors
|
||||
|
||||
except prawcore.PrawcoreException as e:
|
||||
logger.warning("PrawcoreException: %s", e)
|
||||
logger.info("Restarting inbox listener..")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("Exiting (KeyboardInterrupt)")
|
||||
break
|
||||
|
||||
def find_store_links(self, game_name) -> dict:
|
||||
links = {}
|
||||
|
@ -349,7 +377,7 @@ class DailyReleasesBot(object):
|
|||
logger.debug("Generated post:\n%s", post_str)
|
||||
return post_str
|
||||
|
||||
def generate(self, do_post=False):
|
||||
def generate(self, post=False, pm_recipients=None):
|
||||
logger.info("-------------------------------------------------------------------------------------------------")
|
||||
start_time = time.time()
|
||||
|
||||
|
@ -358,26 +386,41 @@ class DailyReleasesBot(object):
|
|||
releases = self.predb.get_releases()
|
||||
parsed_releases, failed_dirnames = self.parse_releases(releases, already_posted)
|
||||
|
||||
post = self.generate_post(parsed_releases)
|
||||
source = textwrap.indent(post, " ")
|
||||
|
||||
# The date of the post changes at midday instead of midnight to allow calling script after 00:00
|
||||
title = "Daily Releases ({})".format((datetime.today() - timedelta(hours=12)).strftime("%B %-d, %Y"))
|
||||
|
||||
if do_post:
|
||||
# Post to bot's subreddit
|
||||
source_post = self.reddit.submit_post(f"{title} - Source", source, self.config["reddit"]["bot_subreddit"])
|
||||
preview_post = self.reddit.submit_post(title, post, self.config["reddit"]["bot_subreddit"])
|
||||
generated_post = self.generate_post(parsed_releases)
|
||||
generated_post_src = textwrap.indent(generated_post, " ")
|
||||
|
||||
if post:
|
||||
# Post to bot's own subreddit
|
||||
bot_subreddit = self.config["reddit"]["bot_subreddit"]
|
||||
reddit_src_post = self.reddit.submit_post(f"{title} - Source", generated_post_src, bot_subreddit)
|
||||
reddit_post = self.reddit.submit_post(title, generated_post, bot_subreddit)
|
||||
|
||||
# Manually approve posts since reddit seem to think posts with many links are spam
|
||||
source_post.mod.approve()
|
||||
preview_post.mod.approve()
|
||||
reddit_src_post.mod.approve()
|
||||
reddit_post.mod.approve()
|
||||
|
||||
self.save_already_posted(already_posted)
|
||||
|
||||
if pm_recipients is not None:
|
||||
msg = inspect.cleandoc(
|
||||
f"""
|
||||
[Preview]({reddit_post.url})
|
||||
[Source]({reddit_src_post.url})
|
||||
Failed: {", ".join(failed_dirnames)}
|
||||
"""
|
||||
)
|
||||
for recipient in pm_recipients:
|
||||
self.reddit.send_pm(recipient, title, msg)
|
||||
|
||||
logger.info("Execution took %s seconds", int(time.time() - start_time))
|
||||
logger.info("-------------------------------------------------------------------------------------------------")
|
||||
|
||||
# Clean requests cache after each successful generation so it doesn't grow indefinitely
|
||||
self.cache.remove_expired_responses()
|
||||
|
||||
def load_already_posted(self):
|
||||
try:
|
||||
with config.DATA_DIR.joinpath("already_posted").open() as file:
|
||||
|
|
Reference in a new issue