From f477d48c7c715defdb565c24df525b710e70e200 Mon Sep 17 00:00:00 2001
From: Virgil Grigoras <v.grigoras@vg-dev.de>
Date: Sun, 9 Sep 2018 11:46:00 +0200
Subject: [PATCH] More robust handling while checking for new updates

---
 cps/static/js/main.js    |  6 ++++
 cps/templates/admin.html |  1 +
 cps/web.py               | 61 +++++++++++++++++++++++++++++++---------
 3 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/cps/static/js/main.js b/cps/static/js/main.js
index 524abdb0..3fdd42ae 100644
--- a/cps/static/js/main.js
+++ b/cps/static/js/main.js
@@ -104,6 +104,7 @@ $(function() {
         var $this = $(this);
         var buttonText = $this.html();
         $this.html("...");
+        $("#update_error").addClass("hidden")
         $.ajax({
             dataType: "json",
             url: window.location.pathname + "/../../get_update_status",
@@ -116,6 +117,11 @@ $(function() {
                         .removeClass("hidden")
                         .find("span").html(data.commit);
                 }
+                if (data.error.length != 0) {
+                    $("#update_error")
+                        .removeClass("hidden")
+                        .find("span").html(data.error);
+                }
             }
         });
     });
diff --git a/cps/templates/admin.html b/cps/templates/admin.html
index 81ff05c5..78773cac 100644
--- a/cps/templates/admin.html
+++ b/cps/templates/admin.html
@@ -93,6 +93,7 @@
   <h2>{{_('Administration')}}</h2>
     <div>{{_('Current commit timestamp')}}: <span>{{commit}} </span></div>
     <div class="hidden" id="update_info">{{_('Newest commit timestamp')}}: <span></span></div>
+    <div class="hidden" id="update_error"> <span>{{update_error}}</span></div>
     <p></p>
     <div class="btn btn-default" id="restart_database">{{_('Reconnect to Calibre DB')}}</div>
     <div class="btn btn-default" data-toggle="modal" data-target="#RestartDialog">{{_('Restart Calibre-Web')}}</div>
diff --git a/cps/web.py b/cps/web.py
index 4ba2c35b..05fd8835 100644
--- a/cps/web.py
+++ b/cps/web.py
@@ -1082,23 +1082,58 @@ def get_matching_tags():
 @app.route("/get_update_status", methods=['GET'])
 @login_required_if_no_ano
 def get_update_status():
-    status = {}
+    status = {
+        'status': False
+    }
+    repository_url = 'https://api.github.com/repos/janeczku/calibre-web'
     tz = datetime.timedelta(seconds=time.timezone if (time.localtime().tm_isdst == 0) else time.altzone)
+
     if request.method == "GET":
         # should be automatically replaced by git with current commit hash
-        commit_id = '$Format:%H$'
-        # ToDo: Handle server not reachable -> ValueError:
-        commit = requests.get('https://api.github.com/repos/janeczku/calibre-web/git/refs/heads/master').json()
-        if "object" in commit and commit['object']['sha'] != commit_id:
-            status['status'] = True
-            commitdate = requests.get('https://api.github.com/repos/janeczku/calibre-web/git/commits/'+commit['object']['sha']).json()
-            if "committer" in commitdate:
-                form_date=datetime.datetime.strptime(commitdate['committer']['date'],"%Y-%m-%dT%H:%M:%SZ") - tz
-                status['commit'] = format_datetime(form_date, format='short', locale=get_locale())
+        current_commit_id = '$Format:%H$'
+
+        try:
+            r = requests.get(repository_url + '/git/refs/heads/master')
+            r.raise_for_status()
+            commit = r.json()
+        except requests.exceptions.HTTPError as ex:
+            status['error'] = _(u'HTTP Error') + ' ' + str(ex)
+        except requests.exceptions.ConnectionError:
+            status['error'] = _(u'Connection error')
+        except requests.exceptions.Timeout:
+            status['error'] = _(u'Timeout while establishing connection')
+        except requests.exceptions.RequestException:
+            status['error'] = _(u'General error')
+
+        if 'error' in status:
+            return json.dumps(status)
+
+        if 'object' in commit and commit['object']['sha'] != current_commit_id:
+            # a new update is available
+            try:
+                r = requests.get(repository_url + '/git/commits/' + commit['object']['sha'])
+                r.raise_for_status()
+                update_data = r.json()
+            except requests.exceptions.HTTPError as ex:
+                status['error'] = _(u'HTTP Error') + ' ' + str(ex)
+            except requests.exceptions.ConnectionError:
+                status['error'] = _(u'Connection error')
+            except requests.exceptions.Timeout:
+                status['error'] = _(u'Timeout while establishing connection')
+            except requests.exceptions.RequestException:
+                status['error'] = _(u'General error')
+
+            if 'error' in status:
+                return json.dumps(status)
+
+            if 'committer' in update_data:
+                status['status'] = True
+                new_commit_date = datetime.datetime.strptime(
+                    update_data['committer']['date'], '%Y-%m-%dT%H:%M:%SZ') - tz
+                status['commit'] = format_datetime(new_commit_date, format='short', locale=get_locale())
             else:
-                status['commit'] = u'Unknown'
-        else:
-            status['status'] = False
+                status['error'] = _(u'Could not fetch update information')
+
     return json.dumps(status)
 
 
-- 
2.18.1