Author: rbowen
Date: Wed Jul  2 15:06:45 2025
New Revision: 1926916

URL: http://svn.apache.org/viewvc?rev=1926916&view=rev
Log:
Convert birthday script to python

Added:
    comdev/tools/birthday.py   (with props)

Added: comdev/tools/birthday.py
URL: http://svn.apache.org/viewvc/comdev/tools/birthday.py?rev=1926916&view=auto
==============================================================================
--- comdev/tools/birthday.py (added)
+++ comdev/tools/birthday.py Wed Jul  2 15:06:45 2025
@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+
+"""
+Generates the CSV file that I import into Hootsuite each month to do
+the #ApacheBirthday tweets.
+
+Caveats:
+
+The "n years" bit probably doesn't work if you're running it
+for a month in the following year. eg, if you run it for January while
+it's still December.
+
+This script takes a long time to run because it verifies that projects
+actually exist, by loading their website. This is so that we're not
+reporting on Attic'ed projects, and subprojects, and so on.
+"""
+
+import sys
+import json
+import re
+from datetime import datetime
+from urllib.request import urlopen, Request
+from urllib.error import URLError, HTTPError
+
+# Set to True to make it noisy
+VERBOSE = False
+
+def usage():
+    print("Usage: ./birthday.py MONTH - eg, ./birthday.py 07")
+    sys.exit(1)
+
+def fetch_url(url, timeout=5):
+    """Fetch URL content with timeout and user agent"""
+    try:
+        req = Request(url, headers={'User-Agent': 'Twitter4Ponies/0.1'})
+        with urlopen(req, timeout=timeout) as response:
+            return response.read().decode('utf-8'), response.getcode()
+    except (URLError, HTTPError) as e:
+        return None, None
+
+def main():
+    if len(sys.argv) != 2 or not sys.argv[1].isdigit():
+        usage()
+    
+    month = f"{int(sys.argv[1]):02d}"
+    if not month:
+        usage()
+    
+    thisyear = datetime.now().year
+    
+    where = 'https://projects.apache.org/json/foundation/committees.json'
+    
+    # Fetch the json
+    content, status_code = fetch_url(where)
+    if not content or status_code != 200:
+        print("Error fetching project data")
+        sys.exit(1)
+    
+    try:
+        projects = json.loads(content)
+    except json.JSONDecodeError as e:
+        print(f"Error parsing JSON: {e}")
+        sys.exit(1)
+    
+    day = 1
+    hour = 9
+    
+    for project in projects:
+        proj = project.get('id')
+        established_date = project.get('established')
+        
+        if not established_date:
+            continue
+            
+        if not established_date.endswith(f'-{month}'):
+            continue
+        
+        # Skip projects that aren't actually there. (Attic? Subprojects?)
+        if VERBOSE:
+            print(f"Checking the validity of {proj}", file=sys.stderr)
+        
+        _, status_code = fetch_url(f"http://{proj}.apache.org/";)
+        if status_code != 200:
+            continue
+        
+        # Extract year from date
+        year_match = re.search(r'(\d{4})', established_date)
+        if not year_match:
+            continue
+            
+        year = int(year_match.group(1))
+        age = thisyear - year
+        
+        # Format the CSV output
+        date_time = f"{day:02d}/{month}/{thisyear} {hour:02d}:00:00"
+        
+        years_text = "years" if age > 1 else "year"
+        tweet_text = (f"Happy birthday to {project['name']}! {age} 
{years_text} "
+                     f"as an ASF top level project! #ApacheBirthday")
+        
+        url = f"http://{proj}.apache.org/";
+        
+        print(f'"{date_time}","{tweet_text}","{url}"')
+        
+        day += 1
+        if day > 28:
+            day = 1
+            hour += 6
+
+if __name__ == "__main__":
+    main()

Propchange: comdev/tools/birthday.py
------------------------------------------------------------------------------
    svn:executable = *


Reply via email to