mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-26 18:22:09 +02:00
Automatically check for new releases and notify when an update is available, via the system notification facilities. Can be controlled by :opt:update_check_interval
Fixes #1342
This commit is contained in:
109
kitty/update_check.py
Normal file
109
kitty/update_check.py
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPLv3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
from collections import namedtuple
|
||||
from urllib.request import urlopen
|
||||
|
||||
from .config import atomic_save
|
||||
from .constants import cache_dir, get_boss, version
|
||||
from .fast_data_types import add_timer, monitor_pid
|
||||
from .notify import notify
|
||||
from .utils import open_url
|
||||
|
||||
CHANGELOG_URL = 'https://sw.kovidgoyal.net/kitty/changelog.html'
|
||||
RELEASED_VERSION_URL = 'https://sw.kovidgoyal.net/kitty/current-version.txt'
|
||||
CHECK_INTERVAL = 24 * 60 * 60
|
||||
Notification = namedtuple('Notification', 'version time_of_last_notification count')
|
||||
|
||||
|
||||
def notification_activated():
|
||||
open_url(CHANGELOG_URL)
|
||||
|
||||
|
||||
def version_notification_log():
|
||||
override = getattr(version_notification_log, 'override', None)
|
||||
if override:
|
||||
return override
|
||||
return os.path.join(cache_dir(), 'new-version-notifications-1.txt')
|
||||
|
||||
|
||||
def notify_new_version(release_version):
|
||||
notify(
|
||||
'kitty update available!',
|
||||
'kitty version {} released'.format('.'.join(map(str, release_version))),
|
||||
identifier='new-version',
|
||||
)
|
||||
|
||||
|
||||
def get_released_version():
|
||||
try:
|
||||
raw = urlopen(RELEASED_VERSION_URL).read().decode('utf-8').strip()
|
||||
except Exception:
|
||||
raw = '0.0.0'
|
||||
return raw
|
||||
|
||||
|
||||
def parse_line(line):
|
||||
parts = line.split(',')
|
||||
version, timestamp, count = parts
|
||||
version = tuple(map(int, version.split('.')))
|
||||
return Notification(version, float(timestamp), int(count))
|
||||
|
||||
|
||||
def read_cache():
|
||||
notified_versions = {}
|
||||
try:
|
||||
with open(version_notification_log()) as f:
|
||||
for line in f:
|
||||
try:
|
||||
n = parse_line(line)
|
||||
except Exception:
|
||||
continue
|
||||
notified_versions[n.version] = n
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return notified_versions
|
||||
|
||||
|
||||
def already_notified(version):
|
||||
notified_versions = read_cache()
|
||||
return version in notified_versions
|
||||
|
||||
|
||||
def save_notification(version):
|
||||
notified_versions = read_cache()
|
||||
if version in notified_versions:
|
||||
v = notified_versions[version]
|
||||
notified_versions[version] = v._replace(time_of_last_notification=time.time(), count=v.count + 1)
|
||||
else:
|
||||
notified_versions[version] = Notification(version, time.time(), 1)
|
||||
lines = []
|
||||
for version in sorted(notified_versions):
|
||||
n = notified_versions[version]
|
||||
lines.append('{},{},{}'.format(
|
||||
'.'.join(map(str, n.version)), n.time_of_last_notification, n.count))
|
||||
atomic_save('\n'.join(lines).encode('utf-8'), version_notification_log())
|
||||
|
||||
|
||||
def process_current_release(raw):
|
||||
release_version = tuple(map(int, raw.split('.')))
|
||||
if release_version > version and not already_notified(release_version):
|
||||
save_notification(release_version)
|
||||
notify_new_version(release_version)
|
||||
|
||||
|
||||
def update_check(timer_id=None):
|
||||
p = subprocess.Popen([
|
||||
'kitty', '+runpy', 'from kitty.update_check import *; import time; time.sleep(2); print(get_released_version())'
|
||||
], stdout=subprocess.PIPE)
|
||||
monitor_pid(p.pid)
|
||||
get_boss().set_update_check_process(p)
|
||||
|
||||
|
||||
def run_update_check(interval=24 * 60 * 60):
|
||||
update_check()
|
||||
add_timer('update_check', update_check, interval)
|
||||
Reference in New Issue
Block a user