1
0
Fork 0
mirror of synced 2024-07-05 06:20:29 +12:00
bulk-downloader-for-reddit/src/reddit.py

92 lines
3.6 KiB
Python
Raw Normal View History

import random
import socket
import webbrowser
import praw
from prawcore.exceptions import ResponseException
from src.errors import RedditLoginFailed
from src.jsonHelper import JsonFile
from src.utils import GLOBAL
class Reddit:
2021-02-07 01:29:13 +13:00
def __init__(self, refresh_token: str = None):
self.SCOPES = ['identity', 'history', 'read', 'save']
self.PORT = 7634
self.refresh_token = refresh_token
self.redditInstance = None
self.arguments = {
"client_id": GLOBAL.reddit_client_id,
"client_secret": GLOBAL.reddit_client_secret,
"user_agent": str(socket.gethostname())
}
2021-02-07 01:29:13 +13:00
def begin(self) -> praw.Reddit:
if self.refresh_token:
self.arguments["refresh_token"] = self.refresh_token
self.redditInstance = praw.Reddit(**self.arguments)
try:
self.redditInstance.auth.scopes()
return self.redditInstance
except ResponseException:
self.arguments["redirect_uri"] = "http://localhost:" + \
str(self.PORT)
self.redditInstance = praw.Reddit(**self.arguments)
reddit, refresh_token = self.getRefreshToken(*self.SCOPES)
else:
self.arguments["redirect_uri"] = "http://localhost:" + \
str(self.PORT)
self.redditInstance = praw.Reddit(**self.arguments)
reddit, refresh_token = self.getRefreshToken(*self.SCOPES)
JsonFile(GLOBAL.configDirectory).add({"reddit_username": str(
reddit.user.me()), "reddit": refresh_token}, "credentials")
return self.redditInstance
2021-02-07 01:29:13 +13:00
def recieve_connection(self) -> socket:
"""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)
2020-06-06 02:23:45 +12:00
server.bind(('0.0.0.0', self.PORT))
server.listen(1)
client = server.accept()[0]
server.close()
return client
2021-02-07 01:29:13 +13:00
def send_message(self, client: socket, message: str):
"""Send message to client and close the connection."""
client.send('HTTP/1.1 200 OK\r\n\r\n{}'.format(message).encode('utf-8'))
client.close()
2021-02-07 01:29:13 +13:00
def getRefreshToken(self, scopes: list[str]) -> tuple[praw.Reddit, str]:
state = str(random.randint(0, 65000))
url = self.redditInstance.auth.url(scopes, state, 'permanent')
print("---Setting up the Reddit API---\n")
print("Go to this URL and login to reddit:\n", url, sep="\n", end="\n\n")
webbrowser.open(url, new=2)
client = self.recieve_connection()
data = client.recv(1024).decode('utf-8')
str(data)
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']:
self.send_message(client, 'State mismatch. Expected: {} Received: {}'.format(state, params['state']))
raise RedditLoginFailed
if 'error' in params:
self.send_message(client, params['error'])
raise RedditLoginFailed
refresh_token = self.redditInstance.auth.authorize(params['code'])
self.send_message(client,
"<script>"
"alert(\"You can go back to terminal window now.\");"
"</script>"
)
return self.redditInstance, refresh_token