Add files via upload

This commit is contained in:
drifty
2025-08-08 17:26:25 +05:30
committed by GitHub
parent 1c16dbc6ed
commit 84eeff3da3
5 changed files with 165 additions and 0 deletions

5
.env Normal file
View File

@@ -0,0 +1,5 @@
FRESHRSS_URL=https://frss.example.com/api/greader.php
FRESHRSS_USERNAME=YourUsername
FRESHRSS_PASSWORD=YourPassword
POLL_INTERVAL=60
APPRISE_URLS=discord://webhook_id/webhook_token,gotifys://gotify.example.com/token,tgram://bot_token/chat_id1/chat_id2/chat_idN

12
Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM python:3.11-slim
WORKDIR /app
ENV PYTHONUNBUFFERED=1
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY main.py .
CMD ["python3", "main.py"]

8
compose.yml Normal file
View File

@@ -0,0 +1,8 @@
version: "3.9"
services:
rssrise:
image: ghcr.io/driftywinds/rssrise:latest
container_name: rssrise
restart: unless-stopped
volumes:
- ./.env:/app/.env

137
main.py Normal file
View File

@@ -0,0 +1,137 @@
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()

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
requests
apprise
python-dotenv