From 1a6586343f39442040b3e37a3a1f55482a3aae13 Mon Sep 17 00:00:00 2001 From: Neshura Date: Mon, 6 Feb 2023 00:10:20 +0100 Subject: [PATCH] Initial Bot Test, no advanced Features, only manual posting --- .gitignore | 2 + README.md | 1 + bot.py | 80 +++++++++++++++++++++++++++++++++++++++ refreshtoken.py | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 .gitignore create mode 100644 bot.py create mode 100644 refreshtoken.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1a5895 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/venv/ +/config.json \ No newline at end of file diff --git a/README.md b/README.md index 4c467d8..828f3aa 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ # ascendance-of-a-bookworm-bot +`python -m venv venv` \ No newline at end of file diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..c8eadfe --- /dev/null +++ b/bot.py @@ -0,0 +1,80 @@ +from enum import Enum +import praw +import json +import requests + +class PostFlair(str, Enum): + debug = "b9626520-a55b-11ed-8a89-de8567ca69ac" + light_novel = "4c6c8e7c-2f96-11ed-b4e8-8ad3482a4000" + manga = "48e0f284-2f96-11ed-8035-9e12ed32b10a" + anime = "4671b6fa-2f96-11ed-8f94-324864767feb" + pre_pub = "dc2829a2-a14e-11ed-962a-ee45985252e2" + + +class PostData(): + title: str + link: str + image: str + flair: PostFlair + + def __init__(self): + pass + +def main(): + data = loadConfig("config.json") + postConfigs = data['PostConfigs'] + botConfig = data['BotConfig'] + + reddit = praw.Reddit( + client_id = botConfig['appId'], + client_secret = botConfig['appSecret'], + refresh_token = botConfig['refreshToken'], + redirect_uri = botConfig['redirectUri'], + user_agent = botConfig['userAgent'] + ) + + sub = reddit.subreddit(botConfig['subReddit']) + + #submissionList = reddit.redditor("MestionorasAvatar").submissions.new() + + # Timer Logic will be implemented here + # Move into class to improve performance (less value copying) + if True: + feedUri = postConfigs[0]['feed'] + postData = getFeedData(feedUri) + postData.flair = PostFlair[postConfigs[0]['flair']] + + exists = True + #for submission in submissionList: + exists = False + if not exists: + createPost(sub, postData) + pass + +def createPost(sub, postConfig): + sub.submit(title=postConfig.title, url=postConfig.link, flair_id=postConfig.flair.value, spoiler=True) + pass + +def getFeedData(uri) -> PostData: + res = requests.get(uri) + + newPost = PostData() + + if res.ok: + data = res.json() + # return most recent entry + recentEntry = data['items'][0] + newPost.title = recentEntry['title'] + newPost.link = recentEntry['url'] + newPost.image = recentEntry['image'] + + return newPost + + +def loadConfig(filePath): + configFile = open(filePath) + data = json.load(configFile) + return data + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/refreshtoken.py b/refreshtoken.py new file mode 100644 index 0000000..3e9d069 --- /dev/null +++ b/refreshtoken.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python + +"""This example demonstrates the flow for retrieving a refresh token. + +In order for this example to work your application's redirect URI must be set to +http://localhost:8080. + +This tool can be used to conveniently create refresh tokens for later use with your web +application OAuth2 credentials. + +""" +import random +import socket +import sys + +import praw + + +def receive_connection(): + """Wait for and then return a connected socket.. + + Opens a TCP connection on port 8080, and waits for a single client. + + """ + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server.bind(("localhost", 8080)) + server.listen(1) + client = server.accept()[0] + server.close() + return client + + +def send_message(client, message): + """Send message to client and close the connection.""" + print(message) + client.send(f"HTTP/1.1 200 OK\r\n\r\n{message}".encode("utf-8")) + client.close() + + +def main(): + """Provide the program's entry point when directly executed.""" + print( + "Go here while logged into the account you want to create a token for: " + "https://www.reddit.com/prefs/apps/" + ) + print( + "Click the create an app button. Put something in the name field and select the" + " script radio button." + ) + print("Put http://localhost:8080 in the redirect uri field and click create app") + client_id = input( + "Enter the client ID, it's the line just under Personal use script at the top: " + ) + client_secret = input("Enter the client secret, it's the line next to secret: ") + commaScopes = input( + "Now enter a comma separated list of scopes, or all for all tokens: " + ) + + if commaScopes.lower() == "all": + scopes = ["*"] + else: + scopes = commaScopes.strip().split(",") + + reddit = praw.Reddit( + client_id=client_id.strip(), + client_secret=client_secret.strip(), + redirect_uri="http://localhost:8080", + user_agent="praw_refresh_token_example", + ) + state = str(random.randint(0, 65000)) + url = reddit.auth.url(scopes, state, "permanent") + print(f"Now open this url in your browser: {url}") + sys.stdout.flush() + + client = receive_connection() + data = client.recv(1024).decode("utf-8") + param_tokens = data.split(" ", 2)[1].split("?", 1)[1].split("&") + params = { + key: value for (key, value) in [token.split("=") for token in param_tokens] + } + + if state != params["state"]: + send_message( + client, + f"State mismatch. Expected: {state} Received: {params['state']}", + ) + return 1 + elif "error" in params: + send_message(client, params["error"]) + return 1 + + refresh_token = reddit.auth.authorize(params["code"]) + send_message(client, f"Refresh token: {refresh_token}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file