forked from retoor/devplacepy
feat: add plug-and-play devRant API client examples with Python and JavaScript
Add complete set of example scripts for the devRant REST protocol under examples/devrant/, including reusable client libraries, a rant poster, a live feed watcher with keyword-based auto-upvote, and an end-to-end smoke test that exercises every endpoint. Both Python (stdlib-only) and JavaScript (Node 18+ global fetch) implementations are provided.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import time
|
||||
import urllib.request
|
||||
import xml.etree.ElementTree as ET
|
||||
from pathlib import Path
|
||||
|
||||
from client import DevPlace
|
||||
|
||||
URL = os.environ.get("DEVPLACE_URL", "https://devplace.net")
|
||||
API_KEY = os.environ.get("DEVPLACE_API_KEY", "YOUR_API_KEY")
|
||||
FEED_URL = os.environ.get("DEVPLACE_RSS_URL", "https://news.ycombinator.com/rss")
|
||||
TOPIC = os.environ.get("DEVPLACE_RSS_TOPIC", "devlog")
|
||||
POLL_SECONDS = int(os.environ.get("DEVPLACE_POLL_SECONDS", "900"))
|
||||
SEEN_FILE = Path(os.environ.get("DEVPLACE_RSS_SEEN", "rss_seen.txt"))
|
||||
|
||||
ATOM = "{http://www.w3.org/2005/Atom}"
|
||||
|
||||
|
||||
def fetch_items():
|
||||
with urllib.request.urlopen(FEED_URL, timeout=20) as response:
|
||||
root = ET.fromstring(response.read())
|
||||
items = []
|
||||
for node in root.iter():
|
||||
tag = node.tag.split("}")[-1]
|
||||
if tag in ("item", "entry"):
|
||||
title = node.findtext("title") or node.findtext(f"{ATOM}title") or ""
|
||||
link = node.findtext("link") or ""
|
||||
if not link:
|
||||
link_node = node.find(f"{ATOM}link")
|
||||
link = link_node.get("href") if link_node is not None else ""
|
||||
if title and link:
|
||||
items.append((title.strip(), link.strip()))
|
||||
return items
|
||||
|
||||
|
||||
def load_seen() -> set[str]:
|
||||
if SEEN_FILE.exists():
|
||||
return set(SEEN_FILE.read_text(encoding="utf-8").splitlines())
|
||||
return set()
|
||||
|
||||
|
||||
def remember(link: str) -> None:
|
||||
with SEEN_FILE.open("a", encoding="utf-8") as handle:
|
||||
handle.write(link + "\n")
|
||||
|
||||
|
||||
def run() -> None:
|
||||
dp = DevPlace(URL, api_key=API_KEY)
|
||||
print(f"RSS poster started for {FEED_URL}; polling every {POLL_SECONDS}s.")
|
||||
while True:
|
||||
seen = load_seen()
|
||||
try:
|
||||
for title, link in fetch_items():
|
||||
if link in seen:
|
||||
continue
|
||||
content = f"{title}\n\n{link}"
|
||||
dp.call("posts.create", content=content, title=title[:120], topic=TOPIC)
|
||||
remember(link)
|
||||
print("posted:", title)
|
||||
except Exception as error:
|
||||
print("error:", error)
|
||||
time.sleep(POLL_SECONDS)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
Reference in New Issue
Block a user