Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions PostCleaner.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import praw
import prawcore
import time
from datetime import datetime

from drive_upload import maybe_upload_logs

_RETRY_WAIT = (5, 15, 45)


def _with_retry(fn, label="operation"):
"""Call fn(), retrying up to 3 times on rate-limit errors."""
for attempt, wait in enumerate(_RETRY_WAIT, start=1):
try:
return fn()
except prawcore.exceptions.TooManyRequests as exc:
retry_after = getattr(exc, "retry_after", None) or wait
print(f" Rate limited on {label}. Waiting {retry_after}s (attempt {attempt}/3)…")
time.sleep(retry_after)
except praw.exceptions.APIException:
raise
return fn()


def get_reddit_credentials(credentials_file="Credentials.txt"):
"""
Expand Down Expand Up @@ -68,7 +85,7 @@ def initialize_reddit(client_id, client_secret, username, password):
reddit.user.me()
print("Authenticated successfully.")
return reddit
except praw.exceptions.APIException as e:
except praw.exceptions.APIException:
print("Error: Could not authenticate with the provided credentials.")
exit()

Expand Down Expand Up @@ -105,11 +122,11 @@ def delete_old_posts(reddit, username, days_old, posts_deleted):
with open("deleted_posts.txt", "a", encoding="utf-8") as f:
f.write(f"{submission.title}, {datetime.utcfromtimestamp(submission.created_utc)}, {submission.score}, {submission.subreddit.display_name}\n")
try:
submission.edit(".")
submission.delete()
_with_retry(lambda: submission.edit("."), "post edit")
_with_retry(submission.delete, "post delete")
posts_deleted += 1
print(f"Deleted post: {submission.title}")
except praw.exceptions.APIException as e:
except (praw.exceptions.APIException, prawcore.exceptions.TooManyRequests) as e:
print(f"Error removing post: {e}")

print(f"Deleted {posts_deleted} posts.")
Expand Down
43 changes: 31 additions & 12 deletions commentCleaner.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import praw
import prawcore
import time
from datetime import datetime, timedelta

from drive_upload import maybe_upload_logs

_RETRY_WAIT = (5, 15, 45)


def _with_retry(fn, label="operation"):
"""Call fn(), retrying up to 3 times on rate-limit errors."""
for attempt, wait in enumerate(_RETRY_WAIT, start=1):
try:
return fn()
except prawcore.exceptions.TooManyRequests as exc:
retry_after = getattr(exc, "retry_after", None) or wait
print(f" Rate limited on {label}. Waiting {retry_after}s (attempt {attempt}/3)…")
time.sleep(retry_after)
except praw.exceptions.APIException:
raise
return fn()


def get_reddit_credentials(credentials_file="Credentials.txt"):
"""
Prompt the user to input Reddit client credentials.
Expand Down Expand Up @@ -83,7 +101,7 @@ def initialize_reddit(client_id, client_secret, username, password):
reddit.user.me()
print("Authenticated successfully.")
return reddit
except praw.exceptions.APIException as e:
except praw.exceptions.APIException:
print("Error: Could not authenticate with the provided credentials.")
exit()

Expand All @@ -107,10 +125,10 @@ def delete_old_comments(reddit, username, days_old, comments_deleted):
# Write the date, karma score, and comment body to the file
f.write(f"{comment_date} | {comment.score} | {comment.body}\n")
try:
comment.edit(".")
comment.delete()
_with_retry(lambda: comment.edit("."), "comment edit")
_with_retry(comment.delete, "comment delete")
comments_deleted.append(comment)
except praw.exceptions.APIException as e:
except (praw.exceptions.APIException, prawcore.exceptions.TooManyRequests) as e:
print(f"Error deleting comment: {e}")


Expand All @@ -133,13 +151,13 @@ def remove_comments_with_negative_karma(reddit, username, comments_deleted):
# Write the date, karma score, and comment body to the file
f.write(f"{comment_date} | {comment.score} | {comment.body}\n")
try:
comment.edit(".")
comment.delete()
_with_retry(lambda: comment.edit("."), "comment edit")
_with_retry(comment.delete, "comment delete")
comments_deleted.append(comment)
except praw.exceptions.APIException as e:
except (praw.exceptions.APIException, prawcore.exceptions.TooManyRequests) as e:
print(f"Error removing comment: {e}")


def remove_comments_with_one_karma_and_no_replies(reddit, username, comments_deleted):
"""
Remove comments with one karma, no replies, and are at least a week old.
Expand Down Expand Up @@ -168,12 +186,13 @@ def remove_comments_with_one_karma_and_no_replies(reddit, username, comments_del
# Write the date, karma score, and comment to the file
f.write(f"{comment_date} | {comment.score} | {comment.body}\n")
try:
comment.edit(".")
comment.delete()
_with_retry(lambda: comment.edit("."), "comment edit")
_with_retry(comment.delete, "comment delete")
comments_deleted.append(comment)
except praw.exceptions.APIException as e:
except (praw.exceptions.APIException, prawcore.exceptions.TooManyRequests) as e:
print(f"Error removing comment: {e}")


def main():
client_id, client_secret, username, password = get_reddit_credentials()

Expand Down
37 changes: 30 additions & 7 deletions weekly_cleanup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,35 @@
"""

import os
import time
from datetime import datetime, timezone

import praw
import prawcore

from drive_upload import maybe_upload_logs

_RETRY_WAIT = (5, 15, 45) # seconds between successive retries


def _with_retry(fn, label="operation"):
"""Call fn(), retrying up to 3 times on rate-limit errors.

Args:
fn: Zero-argument callable to invoke.
label: Human-readable description for log messages.
"""
for attempt, wait in enumerate(_RETRY_WAIT, start=1):
try:
return fn()
except prawcore.exceptions.TooManyRequests as exc:
retry_after = getattr(exc, "retry_after", None) or wait
print(f" Rate limited on {label}. Waiting {retry_after}s (attempt {attempt}/3)…")
time.sleep(retry_after)
except praw.exceptions.APIException:
raise
return fn() # final attempt — let exceptions propagate

AGE_THRESHOLD_DAYS = 14


Expand All @@ -42,7 +65,7 @@ def _load_credentials():
cred_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Credentials.txt")
if os.path.exists(cred_path):
with open(cred_path, encoding="utf-8") as f:
lines = [l.strip() for l in f.readlines()]
lines = [line.strip() for line in f.readlines()]
if len(lines) >= 4:
return lines[0], lines[1], lines[2], lines[3]

Expand Down Expand Up @@ -83,11 +106,11 @@ def main():
with open("deleted_comments.txt", "a", encoding="utf-8") as f:
f.write(f"{date_str} | {comment.score} | {comment.body}\n")
try:
comment.edit(".")
comment.delete()
_with_retry(lambda: comment.edit("."), "comment edit")
_with_retry(comment.delete, "comment delete")
comments_deleted += 1
print(f" Deleted comment (score={comment.score}) in r/{comment.subreddit}")
except praw.exceptions.APIException as e:
except (praw.exceptions.APIException, prawcore.exceptions.TooManyRequests) as e:
print(f" Error deleting comment {comment.id}: {e}")

# ── Posts ─────────────────────────────────────────────────────────────
Expand All @@ -103,11 +126,11 @@ def main():
f"{submission.subreddit.display_name}\n"
)
try:
submission.edit(".")
submission.delete()
_with_retry(lambda: submission.edit("."), "post edit")
_with_retry(submission.delete, "post delete")
posts_deleted += 1
print(f" Deleted post '{submission.title}' (score={submission.score}) in r/{submission.subreddit}")
except praw.exceptions.APIException as e:
except (praw.exceptions.APIException, prawcore.exceptions.TooManyRequests) as e:
print(f" Error deleting post {submission.id}: {e}")

print(f"\nDone. Deleted {comments_deleted} comment(s) and {posts_deleted} post(s).")
Expand Down