#!/usr/bin/env python3 import json, os, re, time from datetime import datetime,timezone from pathlib import Path from urllib.parse import urlencode, quote from common import request,store,state_file ROOT=Path(__file__).resolve().parents[1] API=os.getenv('ROCKY_API','https://apollo.build.resf.org/v2/advisories').rstrip('/') PAGE_SIZE=int(os.getenv('ROCKY_PAGE_SIZE','100')) MAX_PAGES=int(os.getenv('ROCKY_MAX_PAGES','20')) DELAY=float(os.getenv('ROCKY_DELAY','0.15')) STATE=ROOT/'state/sync.json' def get_advisories(body): obj=json.loads(body) if not isinstance(obj,dict) or not isinstance(obj.get('advisories'),list): raise ValueError('Unexpected Apollo list response') total=int(obj['total']) if 'total' in obj else None if total is None: raise ValueError('Apollo response lacks total count') return obj['advisories'],total def identity(doc): name=doc.get('name') or doc.get('id') if not isinstance(name,str) or not re.fullmatch(r'[A-Za-z0-9:._-]+',name): raise ValueError(f'Invalid advisory identity {name!r}') return name def date_filter(doc): return identity(doc).startswith(('RLSA','RXSA')) def main(): old=json.loads(STATE.read_text()) if STATE.exists() else {} page=max(1,int(old.get('next_page',1))) pages=0 while pages(total+PAGE_SIZE-1)//PAGE_SIZE: page=1 state_file(STATE,{'next_page':page,'last_success_utc':datetime.now(timezone.utc).isoformat(),'last_total':total}) if page==1: break if __name__=='__main__': main()