| 
									
										
										
										
											2024-11-09 09:01:34 -05:00
										 |  |  | #!/usr/bin/env python3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import argparse | 
					
						
							|  |  |  | import feedparser | 
					
						
							|  |  |  | import json | 
					
						
							| 
									
										
										
										
											2024-11-18 22:58:51 -05:00
										 |  |  | import re | 
					
						
							| 
									
										
										
										
											2024-11-09 09:24:13 -05:00
										 |  |  | import subprocess | 
					
						
							| 
									
										
										
										
											2024-11-09 09:01:34 -05:00
										 |  |  | import time | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | parser = argparse.ArgumentParser() | 
					
						
							|  |  |  | parser.add_argument('--state_file', help = 'Path to a file in which to store state.') | 
					
						
							|  |  |  | args = parser.parse_args() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | k_feeds = { | 
					
						
							|  |  |  |     'tildefriends': 'https://dev.tildefriends.net/cory/tildefriends.rss', | 
					
						
							|  |  |  |     'erlbutt': 'https://github.com/cmoid/erlbutt/commits/main.atom', | 
					
						
							| 
									
										
										
										
											2024-11-10 19:30:36 -05:00
										 |  |  |     'habitat': 'https://tildegit.org/jeremylist/habitat.rss', | 
					
						
							| 
									
										
										
										
											2024-11-09 09:01:34 -05:00
										 |  |  |     'manyverse': 'https://gitlab.com/staltz/manyverse/-/commits/master?format=atom', | 
					
						
							|  |  |  |     'ahau': 'https://gitlab.com/ahau/ahau/-/commits/master.atom', | 
					
						
							| 
									
										
										
										
											2025-04-01 08:13:54 -04:00
										 |  |  |     'patchfox': 'https://github.com/soapdog/patchfox/commits.atom', | 
					
						
							| 
									
										
										
										
											2024-11-09 09:01:34 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def fix_title(entry): | 
					
						
							|  |  |  |     if entry.summary.startswith('<a href=') and '\n' in entry.summary and entry.summary and '\n' in entry.summary: | 
					
						
							|  |  |  |         return entry.summary.split('\n')[1] | 
					
						
							|  |  |  |     return entry.title.split('\n')[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_entries(): | 
					
						
							| 
									
										
										
										
											2025-02-24 12:16:31 -05:00
										 |  |  |     seen = set() | 
					
						
							| 
									
										
										
										
											2024-11-09 09:01:34 -05:00
										 |  |  |     results = [] | 
					
						
							|  |  |  |     for name, url in k_feeds.items(): | 
					
						
							|  |  |  |         feed = feedparser.parse(url) | 
					
						
							|  |  |  |         for entry in feed.entries: | 
					
						
							| 
									
										
										
										
											2024-11-23 13:50:23 -05:00
										 |  |  |             if '/issues/' in entry.link: | 
					
						
							|  |  |  |                 m = re.match(r'^(\d+)#(.*)#$', entry.description) | 
					
						
							|  |  |  |                 if m: | 
					
						
							|  |  |  |                     results.append((time.mktime(entry.get('updated_parsed')), name, entry.link, f'new issue #{m.group(1)}: {m.group(2)}')) | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2024-11-28 11:11:25 -05:00
										 |  |  |             elif '/releases/' in entry.link: | 
					
						
							|  |  |  |                 m = re.match(r'(.*) released <a href=".*?">(.*?)</a>', entry.title) | 
					
						
							|  |  |  |                 if m: | 
					
						
							|  |  |  |                     results.append((time.mktime(entry.get('updated_parsed')), name, entry.link, f'{m.group(1)} released {m.group(2)}')) | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2024-11-18 22:58:51 -05:00
										 |  |  |             if entry.summary.startswith('<a href='): | 
					
						
							|  |  |  |                 for m in re.findall(r'<a href="(.*?)">.*?</a>$\s*^([^\n]+)$', entry.summary, re.S | re.M): | 
					
						
							| 
									
										
										
										
											2025-02-24 12:16:31 -05:00
										 |  |  |                     if not m[0] in seen: | 
					
						
							|  |  |  |                         seen.add(m[0]) | 
					
						
							|  |  |  |                         results.append((time.mktime(entry.get('updated_parsed')), name, m[0], m[1])) | 
					
						
							| 
									
										
										
										
											2024-11-18 22:58:51 -05:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2025-02-24 12:16:31 -05:00
										 |  |  |                 if not entry.link in seen: | 
					
						
							|  |  |  |                     seen.add(entry.link) | 
					
						
							|  |  |  |                     results.append((time.mktime(entry.get('updated_parsed')), name, entry.link, entry.title.split('\n')[0])) | 
					
						
							| 
									
										
										
										
											2024-11-09 09:01:34 -05:00
										 |  |  |     results.sort() | 
					
						
							|  |  |  |     results.reverse() | 
					
						
							|  |  |  |     return results | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | state = {} | 
					
						
							|  |  |  | if args.state_file: | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         with open(args.state_file, 'r') as f: | 
					
						
							|  |  |  |             state = json.load(f) | 
					
						
							|  |  |  |     except: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | cutoff = state.get('last_update') or (time.time() - 2 * 7 * 24 * 60 * 60) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-10 19:30:36 -05:00
										 |  |  | entries = [entry for entry in get_entries() if entry[0] > cutoff] | 
					
						
							| 
									
										
										
										
											2024-11-09 09:01:34 -05:00
										 |  |  | if entries: | 
					
						
							| 
									
										
										
										
											2025-01-25 08:08:02 -05:00
										 |  |  |     text = '\n'.join([f' * **{entry[1]}** [{entry[3]}]({entry[2]})' for entry in entries]) | 
					
						
							| 
									
										
										
										
											2024-11-09 09:01:34 -05:00
										 |  |  |     state['last_update'] = entries[0][0] | 
					
						
							|  |  |  |     if args.state_file: | 
					
						
							| 
									
										
										
										
											2024-11-09 09:24:13 -05:00
										 |  |  |         content = json.dumps({'type': 'post', 'text': text, 'mentions': []}) | 
					
						
							|  |  |  |         subprocess.check_call(['out/debug/tildefriends', 'publish', '--user', 'cory', '--id', '@DnYDqFfmxdNkYQlpflF9Wkltk2HIhJ5u1MW5njKPLzM=.ed25519', '--content', content]) | 
					
						
							| 
									
										
										
										
											2024-11-09 09:01:34 -05:00
										 |  |  |         with open(args.state_file, 'w') as f: | 
					
						
							|  |  |  |             json.dump(state, f) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         print(text) |