Added a script to post to Reddit + doc.
This commit is contained in:
80
README.md
80
README.md
@@ -209,30 +209,47 @@ Open a **second terminal** in the same project directory. You can now run the `e
|
||||
After running a command, a new `.png` file (e.g., `wallstreetbets_daily_1690000000.png`) will be saved in the images-directory in the root directory of the project.
|
||||
|
||||
|
||||
|
||||
## 4. Full Automation: Posting to Reddit via Cron Job
|
||||
|
||||
The final piece of the project is a script that automates the entire process: scraping data, generating an image, and posting it to a target subreddit like `r/rstat`. This is designed to be run via a scheduled task or cron job.
|
||||
The final piece of the project is a script that automates the entire pipeline: scraping data, generating an image, and posting it to a target subreddit like `r/rstat`. This is designed to be run via a scheduled task or cron job.
|
||||
|
||||
### Prerequisites for Posting
|
||||
### Prerequisites: One-Time Account Authorization (OAuth2)
|
||||
|
||||
The posting script needs to log in to your Reddit account. You must add your Reddit username and password to your `.env` file.
|
||||
To post on your behalf, the script needs to be authorized with your Reddit account. This is done securely using OAuth2 and a `refresh_token`, which is compatible with 2-Factor Authentication (2FA). This is a **one-time setup process**.
|
||||
|
||||
**Add these two lines to your `.env` file:**
|
||||
```
|
||||
REDDIT_USERNAME=YourRedditUsername
|
||||
REDDIT_PASSWORD=YourRedditPassword
|
||||
```
|
||||
*(For security, it's recommended to use a dedicated bot account for this, not your personal account.)*
|
||||
**Step 1: Get Your Refresh Token**
|
||||
|
||||
1. First, ensure the "redirect uri" in your [Reddit App settings](https://www.reddit.com/prefs/apps) is set to **exactly** `http://localhost:8080`.
|
||||
2. Run the temporary helper script included in the project:
|
||||
```bash
|
||||
python get_refresh_token.py
|
||||
```
|
||||
3. The script will print a unique URL. Copy this URL and paste it into your web browser.
|
||||
4. Log in to the Reddit account you want to post from and click **"Allow"** when prompted.
|
||||
5. You'll be redirected to a `localhost:8080` page that says "This site can’t be reached". **This is normal and expected.**
|
||||
6. Copy the **full URL** from your browser's address bar. It will look something like `http://localhost:8080/?state=...&code=...`.
|
||||
7. Paste this full URL back into the terminal where the script is waiting and press Enter.
|
||||
8. The script will output your unique **refresh token**.
|
||||
|
||||
**Step 2: Update Your `.env` File**
|
||||
|
||||
1. Open your `.env` file.
|
||||
2. Add a new line and paste your refresh token into it.
|
||||
3. Ensure your file now contains the following (your username and password are no longer needed):
|
||||
```
|
||||
REDDIT_CLIENT_ID=your_client_id_from_reddit
|
||||
REDDIT_CLIENT_SECRET=your_client_secret_from_reddit
|
||||
REDDIT_USER_AGENT=A custom user agent string (e.g., python:rstat:v1.2)
|
||||
REDDIT_REFRESH_TOKEN=the_long_refresh_token_string_you_just_copied
|
||||
```
|
||||
You can now safely delete the `get_refresh_token.py` script. Your application is now authorized to post on your behalf indefinitely.
|
||||
|
||||
### The `post_to_reddit.py` Script
|
||||
|
||||
This is a standalone script located in the project's root directory that finds the most recently generated image and posts it to Reddit.
|
||||
This is the standalone script that finds the most recently generated image and posts it to Reddit using your new authorization.
|
||||
|
||||
**Manual Usage:**
|
||||
|
||||
You can run this script manually from your terminal. This is great for testing or one-off posts.
|
||||
|
||||
* **Post the latest OVERALL summary image to `r/rstat`:**
|
||||
```bash
|
||||
python post_to_reddit.py
|
||||
@@ -248,18 +265,13 @@ You can run this script manually from your terminal. This is great for testing o
|
||||
python post_to_reddit.py --subreddit wallstreetbets --weekly
|
||||
```
|
||||
|
||||
* **Post to a different target subreddit (e.g., a test subreddit):**
|
||||
```bash
|
||||
python post_to_reddit.py --target-subreddit MyTestSub
|
||||
```
|
||||
|
||||
### Setting Up the Cron Job for Full Automation
|
||||
### Setting Up the Cron Job
|
||||
|
||||
To run the entire pipeline automatically every day, you can use a simple shell script controlled by `cron`.
|
||||
|
||||
**Step 1: Create a Job Script**
|
||||
|
||||
Create a file named `run_daily_job.sh` in the root of your project directory. This script will run all the necessary commands in the correct order.
|
||||
Create a file named `run_daily_job.sh` in the root of your project directory.
|
||||
|
||||
**`run_daily_job.sh`:**
|
||||
```bash
|
||||
@@ -274,49 +286,43 @@ source /path/to/your/project/reddit_stock_analyzer/.venv/bin/activate
|
||||
|
||||
echo "--- Starting RSTAT Daily Job on $(date) ---"
|
||||
|
||||
# 1. Scrape data from the last 24 hours for all subreddits in the config.
|
||||
# 1. Scrape data from the last 24 hours.
|
||||
echo "Step 1: Scraping new data..."
|
||||
rstat --config subreddits.json --days 1
|
||||
rstat --days 1
|
||||
|
||||
# 2. Start the dashboard in the background so the exporter can access it.
|
||||
# 2. Start the dashboard in the background.
|
||||
echo "Step 2: Starting dashboard in background..."
|
||||
rstat-dashboard &
|
||||
DASHBOARD_PID=$!
|
||||
|
||||
# Give the server a moment to start up.
|
||||
sleep 10
|
||||
|
||||
# 3. Export the overall summary image.
|
||||
echo "Step 3: Exporting overall summary image..."
|
||||
python export_image.py --overall
|
||||
|
||||
# 4. Post the newly created overall summary image to r/rstat.
|
||||
# 4. Post the image to r/rstat.
|
||||
echo "Step 4: Posting image to Reddit..."
|
||||
python post_to_reddit.py --target-subreddit rstat
|
||||
|
||||
# 5. Clean up by stopping the background dashboard server.
|
||||
# 5. Clean up by stopping the dashboard server.
|
||||
echo "Step 5: Stopping dashboard server..."
|
||||
kill $DASHBOARD_PID
|
||||
|
||||
echo "--- RSTAT Daily Job Complete ---"
|
||||
```**Before proceeding, you must edit the two absolute paths at the top of this script to match your system.**
|
||||
```
|
||||
**Before proceeding, you must edit the two absolute paths at the top of this script to match your system.**
|
||||
|
||||
**Step 2: Make the Script Executable**
|
||||
|
||||
In your terminal, run the following command:
|
||||
```bash
|
||||
**Step 2: Make the Script Executable**```bash
|
||||
chmod +x run_daily_job.sh
|
||||
```
|
||||
|
||||
**Step 3: Schedule the Cron Job**
|
||||
|
||||
1. Open your crontab editor by running `crontab -e`.
|
||||
2. Add a new line to the file to schedule the job. For example, to run the script **every day at 10:00 PM**, add the following line:
|
||||
1. Run `crontab -e` to open your crontab editor.
|
||||
2. Add the following line to run the script every day at 10:00 PM and log its output:
|
||||
|
||||
```
|
||||
0 22 * * * /path/to/your/project/reddit_stock_analyzer/run_daily_job.sh >> /path/to/your/project/reddit_stock_analyzer/cron.log 2>&1
|
||||
```
|
||||
* `0 22 * * *` means at minute 0 of hour 22, every day, every month, every day of the week.
|
||||
* `>> /path/to/your/.../cron.log 2>&1` is highly recommended. It redirects all output (both standard and error) from the script into a log file, so you can check if the job ran successfully.
|
||||
|
||||
Your project is now fully automated to scrape, analyze, visualize, and post data every day.
|
||||
Your project is now fully and securely automated.
|
68
get_refresh_token.py
Normal file
68
get_refresh_token.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# get_refresh_token.py
|
||||
# A temporary, one-time-use script to get your OAuth2 refresh token.
|
||||
|
||||
import praw
|
||||
from dotenv import load_dotenv
|
||||
import os
|
||||
import random
|
||||
import socket
|
||||
|
||||
# --- IMPORTANT: Ensure this matches the "redirect uri" in your Reddit App settings ---
|
||||
REDIRECT_URI = "http://localhost:5000"
|
||||
|
||||
def main():
|
||||
print("--- RSTAT Refresh Token Generator ---")
|
||||
load_dotenv()
|
||||
client_id = os.getenv("REDDIT_CLIENT_ID")
|
||||
client_secret = os.getenv("REDDIT_CLIENT_SECRET")
|
||||
|
||||
if not all([client_id, client_secret]):
|
||||
print("Error: REDDIT_CLIENT_ID and REDDIT_CLIENT_SECRET must be set in your .env file.")
|
||||
return
|
||||
|
||||
# 1. Initialize PRAW
|
||||
reddit = praw.Reddit(
|
||||
client_id=client_id,
|
||||
client_secret=client_secret,
|
||||
redirect_uri=REDIRECT_URI,
|
||||
user_agent="rstat_token_fetcher (by u/YourUsername)" # Can be anything
|
||||
)
|
||||
|
||||
# 2. Generate the authorization URL
|
||||
# Scopes define what our script is allowed to do. 'identity' and 'submit' are needed.
|
||||
scopes = ["identity", "submit", "read"]
|
||||
state = str(random.randint(0, 65536))
|
||||
auth_url = reddit.auth.url(scopes, state, "permanent")
|
||||
|
||||
print("\nStep 1: Open this URL in your browser:\n")
|
||||
print(auth_url)
|
||||
|
||||
print("\nStep 2: Log in to Reddit, click 'Allow', and you'll be redirected to a 'page not found'.")
|
||||
print("Step 3: Copy the ENTIRE URL from your browser's address bar after the redirect.")
|
||||
|
||||
# 3. Get the redirected URL from the user
|
||||
redirected_url = input("\nStep 4: Paste the full redirected URL here and press Enter:\n> ")
|
||||
|
||||
# 4. Exchange the authorization code for a refresh token
|
||||
try:
|
||||
# The state is used to prevent CSRF attacks, we're just checking it matches
|
||||
assert state == redirected_url.split("state=")[1].split("&")[0]
|
||||
code = redirected_url.split("code=")[1].split("#_")[0]
|
||||
|
||||
print("\nAuthorization code received. Fetching refresh token...")
|
||||
|
||||
# This is the line that gets the key!
|
||||
refresh_token = reddit.auth.authorize(code)
|
||||
|
||||
print("\n--- SUCCESS! ---")
|
||||
print("Your Refresh Token is:\n")
|
||||
print(refresh_token)
|
||||
print("\nStep 5: Copy this token and add it to your .env file as REDDIT_REFRESH_TOKEN.")
|
||||
print("Step 6: You can now delete your REDDIT_USERNAME and REDDIT_PASSWORD from the .env file.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nAn error occurred: {e}")
|
||||
print("Please make sure you copied the full URL.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -16,19 +16,17 @@ def get_reddit_instance():
|
||||
client_id = os.getenv("REDDIT_CLIENT_ID")
|
||||
client_secret = os.getenv("REDDIT_CLIENT_SECRET")
|
||||
user_agent = os.getenv("REDDIT_USER_AGENT")
|
||||
username = os.getenv("REDDIT_USERNAME") # <-- Add your Reddit username to .env
|
||||
password = os.getenv("REDDIT_PASSWORD") # <-- Add your Reddit password to .env
|
||||
refresh_token = os.getenv("REDDIT_REFRESH_TOKEN")
|
||||
|
||||
if not all([client_id, client_secret, user_agent, username, password]):
|
||||
print("Error: Reddit API credentials (including username/password) not found in .env file.")
|
||||
if not all([client_id, client_secret, user_agent, refresh_token]):
|
||||
print("Error: Reddit API credentials (including REDDIT_REFRESH_TOKEN) must be set in .env file.")
|
||||
return None
|
||||
|
||||
return praw.Reddit(
|
||||
client_id=client_id,
|
||||
client_secret=client_secret,
|
||||
user_agent=user_agent,
|
||||
username=username,
|
||||
password=password
|
||||
refresh_token=refresh_token
|
||||
)
|
||||
|
||||
def find_latest_image(pattern):
|
||||
|
Reference in New Issue
Block a user