mirror of
https://github.com/driftywinds/rssrise.git
synced 2025-12-19 11:33:32 +00:00
138 lines
4.0 KiB
Python
138 lines
4.0 KiB
Python
import os
|
|
import time
|
|
import requests
|
|
from dotenv import load_dotenv
|
|
import subprocess
|
|
import re
|
|
import datetime
|
|
|
|
load_dotenv()
|
|
|
|
FRESHRSS_URL = os.getenv("FRESHRSS_URL") # e.g. https://freshrss.example.net/api/greader.php
|
|
USERNAME = os.getenv("FRESHRSS_USERNAME")
|
|
PASSWORD = os.getenv("FRESHRSS_PASSWORD")
|
|
POLL_INTERVAL = int(os.getenv("POLL_INTERVAL", "60")) # seconds
|
|
|
|
APPRISE_CONFIG = os.getenv("APPRISE_CONFIG") # apprise URLs or config file, optional
|
|
|
|
session = requests.Session()
|
|
auth_token = None
|
|
|
|
def login():
|
|
global auth_token
|
|
login_url = f"{FRESHRSS_URL}/accounts/ClientLogin"
|
|
params = {
|
|
"Email": USERNAME,
|
|
"Passwd": PASSWORD
|
|
}
|
|
resp = session.get(login_url, params=params)
|
|
if resp.status_code != 200:
|
|
print(f"Login failed: {resp.status_code} {resp.text}")
|
|
return False
|
|
|
|
# Response is like:
|
|
# SID=alice/8e6845e089457af25303abc6f53356eb60bdb5f8
|
|
# Auth=alice/8e6845e089457af25303abc6f53356eb60bdb5f8
|
|
# We need the Auth line
|
|
for line in resp.text.splitlines():
|
|
if line.startswith("Auth="):
|
|
auth_token = line[len("Auth="):].strip()
|
|
break
|
|
if not auth_token:
|
|
print("Auth token not found in login response")
|
|
return False
|
|
|
|
print(f"Logged in, got auth token")
|
|
return True
|
|
|
|
def get_headers():
|
|
return {
|
|
"Authorization": f"GoogleLogin auth={auth_token}"
|
|
}
|
|
|
|
def fetch_unread_items():
|
|
url = f"{FRESHRSS_URL}/reader/api/0/stream/contents/reading-list?output=json&n=20"
|
|
resp = session.get(url, headers=get_headers())
|
|
if resp.status_code != 200:
|
|
print(f"Failed to fetch unread items: {resp.status_code} {resp.text}")
|
|
return []
|
|
|
|
data = resp.json()
|
|
items = data.get("items", [])
|
|
unread_items = []
|
|
for item in items:
|
|
categories = item.get("categories", [])
|
|
# Skip items marked as read
|
|
if "user/-/state/com.google/read" not in categories:
|
|
unread_items.append(item)
|
|
return unread_items
|
|
|
|
def clean_html(raw_html):
|
|
cleanr = re.compile('<.*?>')
|
|
cleantext = re.sub(cleanr, '', raw_html)
|
|
return cleantext.strip()
|
|
|
|
def format_message(item):
|
|
title = item.get("title", "No title").strip()
|
|
url = item.get("alternate", [{}])[0].get("href", "").strip()
|
|
categories = item.get("categories", [])
|
|
fresh_categories = [c for c in categories if not c.startswith("user/-/state/com.google")]
|
|
category = fresh_categories[0] if fresh_categories else "Uncategorized"
|
|
|
|
message_body = (
|
|
f"---------\n"
|
|
f"URL: {url}\n\n"
|
|
f"Category: {category}\n"
|
|
f"---------"
|
|
)
|
|
|
|
return title, message_body
|
|
|
|
|
|
def send_notification(title, body):
|
|
# Compose apprise command
|
|
cmd = ["apprise"]
|
|
if APPRISE_CONFIG:
|
|
cmd += ["-q", "-c", APPRISE_CONFIG] # quiet mode, config file
|
|
cmd += ["-t", title, "-b", body]
|
|
print(f"Sending notification: {title}")
|
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
print(f"Failed to send notification: {result.stderr}")
|
|
else:
|
|
print("Notification sent.")
|
|
|
|
def main():
|
|
if not login():
|
|
return
|
|
|
|
sent_ids = set()
|
|
|
|
# On first run, send all unread items
|
|
unread_items = fetch_unread_items()
|
|
print(f"[{datetime.datetime.now().isoformat()}] Fetched {len(unread_items)} unread items on startup")
|
|
for item in unread_items:
|
|
item_id = item.get("id")
|
|
if item_id in sent_ids:
|
|
continue
|
|
title, body = format_message(item)
|
|
send_notification(title, body)
|
|
sent_ids.add(item_id)
|
|
|
|
while True:
|
|
time.sleep(POLL_INTERVAL)
|
|
now = datetime.datetime.now().isoformat()
|
|
unread_items = fetch_unread_items()
|
|
print(f"[{now}] Polled and found {len(unread_items)} unread items")
|
|
|
|
for item in unread_items:
|
|
item_id = item.get("id")
|
|
if item_id in sent_ids:
|
|
continue
|
|
title, body = format_message(item)
|
|
send_notification(title, body)
|
|
sent_ids.add(item_id)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|