46ad8ee25abcc7c81cd3005972b9069f2f14b5c5
gperez2
  Thu Apr 23 12:09:16 2026 -0700
Updating hubPublicMail and hubPublicAutoUpdate crons to correctly detect
and contact authors of broken public hubs. hubPublicMail now uses curl
instead of python-requests (handles Cloudflare bot-blocks and 4xx/5xx
responses that requests silently treats as successful), falls back to
hubPublic.email as a secondary source so newly-added broken hubs still
accumulate failCount, and strips the mailto: prefix in parseEmail.
hubPublicAutoUpdate now escapes double quotes on email values. No RM

diff --git src/utils/qa/hubPublicAutoUpdate src/utils/qa/hubPublicAutoUpdate
index 6781e56f88b..326a25c7418 100755
--- src/utils/qa/hubPublicAutoUpdate
+++ src/utils/qa/hubPublicAutoUpdate
@@ -157,31 +157,31 @@
         
     if hubPublicDic[hub]['longLabel'] != currentHub['longLabel'].rstrip().lstrip():     
         printHgsql(hub,'longLabel',escapeDoubleQuotesOnLabels(currentHub['longLabel'].rstrip().lstrip()),hgsqlInput,testMode)
 
     if int(hubPublicDic[hub]['dbCount']) != int(currentHub['dbCount']):
         printHgsql(hub,'dbCount',currentHub['dbCount'],hgsqlInput,testMode)
         
     if set(hubPublicDic[hub]['dbList'][:-1].split(',')) != set(currentHub['dbList']):
         printHgsql(hub,'dbList',",".join(currentHub['dbList'])+",",hgsqlInput,testMode)
 
     if hubPublicDic[hub]['descriptionUrl'] != currentHub['descriptionUrl'].rstrip().lstrip():
         printHgsql(hub,'descriptionUrl',currentHub['descriptionUrl'].rstrip().lstrip(),hgsqlInput,testMode)
 
     if 'email' in currentHub and currentHub['email'].strip():
         if hubPublicDic[hub]['email'] != currentHub['email'].strip():
-            printHgsql(hub,'email',currentHub['email'].strip(),hgsqlInput,testMode)
+            printHgsql(hub,'email',escapeDoubleQuotesOnLabels(currentHub['email'].strip()),hgsqlInput,testMode)
     
 def hubPublicCompare(hubPublicDic,hgsqlInput,testMode,silent):
     """Query hub.txt files and compare values to hubPublic values"""
     for hub in hubPublicDic.keys():
         try: #Try for timeout connections
             currentHub = buildCurrentHubTxtDic(hub)
             currentHub = queryHubTxt(currentHub,hub)
             compareResults(hubPublicDic,currentHub,hub,hgsqlInput,testMode)
         except:
             if not silent:
                 print("The following hub has an error or is not responsive: "+str(hub))
             
 def main():
     """Initialize options and call other functions"""
     options = parseArgs()