145 lines
3.7 KiB
Python
145 lines
3.7 KiB
Python
import requests
|
|
import sys
|
|
import os
|
|
import math
|
|
import time
|
|
import shelve
|
|
|
|
from requests.adapters import HTTPAdapter, Retry
|
|
|
|
from data import config, db
|
|
|
|
|
|
class DramaClient:
|
|
BASE_URL = "https://rdrama.net"
|
|
|
|
def __init__(self):
|
|
self.session = requests.Session()
|
|
retries = Retry(
|
|
total=5, backoff_factor=5, status_forcelist=[500, 502, 503, 504, 521]
|
|
)
|
|
self.session.mount("https://", HTTPAdapter(max_retries=retries))
|
|
|
|
self.chud_phrase = self.get("/@me").get("chud_phrase", "")
|
|
|
|
def get(self, endpoint):
|
|
print("GET", endpoint)
|
|
time.sleep(5)
|
|
|
|
while True:
|
|
r = self.session.get(
|
|
f"{self.BASE_URL}{endpoint}",
|
|
headers={"Authorization": config["api_token"]},
|
|
)
|
|
|
|
if "502 Bad Gateway" in r.text:
|
|
print("Received 502")
|
|
time.sleep(10)
|
|
continue
|
|
|
|
break
|
|
|
|
# Return None for country club and chudrama posts.
|
|
if r.status_code == 403:
|
|
return None
|
|
|
|
if r.status_code != 200:
|
|
print("Error!", r, r.status_code, r.content)
|
|
sys.exit(1)
|
|
|
|
return r.json()
|
|
|
|
def post(self, endpoint, payload=None, files=[]):
|
|
print("POST", endpoint, f"Payload:\n{payload}")
|
|
time.sleep(5)
|
|
|
|
while True:
|
|
r = self.session.post(
|
|
f"{self.BASE_URL}{endpoint}",
|
|
payload,
|
|
headers={"Authorization": config["api_token"]},
|
|
files=files,
|
|
)
|
|
|
|
if "502 Bad Gateway" in r.text:
|
|
print("Received 502")
|
|
time.sleep(10)
|
|
continue
|
|
|
|
break
|
|
|
|
if r.status_code != 200:
|
|
print("Error!", r, r.status_code, r.content)
|
|
sys.exit(1)
|
|
|
|
return r.json()
|
|
|
|
def fetch_new_comments(self, limit=config["num_replies"] * 25):
|
|
comments = []
|
|
|
|
earliest_id = math.inf
|
|
page = 1
|
|
|
|
# Fetch comments until we find the last one processed.
|
|
while earliest_id > db["last_processed_id"]:
|
|
page_comments = self.fetch_page(page)
|
|
|
|
if len(page_comments) == 0:
|
|
break
|
|
|
|
earliest_id = min([c["id"] for c in page_comments])
|
|
comments += [c for c in page_comments if c["id"] > db["last_processed_id"]]
|
|
|
|
if limit > 0 and len(comments) >= limit:
|
|
break
|
|
|
|
page += 1
|
|
|
|
if not comments:
|
|
return []
|
|
|
|
db["last_processed_id"] = max(c["id"] for c in comments)
|
|
db.commit()
|
|
|
|
# New comments may have pushed others to page n+1 while fetching.
|
|
deduped_comments = {c["id"]: c for c in comments}.values()
|
|
|
|
# Oldest first.
|
|
comments.reverse()
|
|
|
|
return comments
|
|
|
|
def fetch_new_replies(self):
|
|
notifs = self.get("/unread")["data"]
|
|
notifs = [n for n in notifs if n["body"]]
|
|
return notifs
|
|
|
|
def fetch_page(self, page):
|
|
return self.get(f"/comments?page={page}")["data"]
|
|
|
|
def fetch_context(self, comment):
|
|
post = self.get(f"/post/{comment['post_id']}")
|
|
|
|
if not post:
|
|
return None, None
|
|
|
|
comments = [comment]
|
|
while parent_id := comments[-1].get("parent_comment_id", None):
|
|
parent = self.get(f"/comment/{parent_id}")
|
|
comments.append(parent)
|
|
|
|
comments.reverse()
|
|
|
|
return post, comments
|
|
|
|
def reply(self, body, comment):
|
|
if self.chud_phrase and self.chud_phrase not in body:
|
|
body += f"\n{self.chud_phrase}"
|
|
|
|
payload = {
|
|
"parent_fullname": f"c_{comment['id']}",
|
|
"body": body,
|
|
}
|
|
|
|
return self.post("/comment", payload)
|