Krita Source Code Documentation
Loading...
Searching...
No Matches
plugin_downloader.py
Go to the documentation of this file.
1# SPDX-FileCopyrightText: 2029 Rebecca Breu <rebecca@rbreu.de>
2
3# This file is part of Krita.
4
5# Krita is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9
10# Krita is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14
15# You should have received a copy of the GNU General Public License
16# along with Krita. If not, see <https://www.gnu.org/licenses/>.
17
18import mimetypes
19import os
20import urllib
21import urllib.request
22
23from builtins import i18n
24
25
26class PluginDownloadError(Exception):
27 """Base class for all exceptions of this module."""
28 pass
29
30
31def is_zip(url):
32 """Check if the given URL is a direct link to a zip file"""
33
34 MTYPE = 'application/zip'
35
36 # This just goes by the ending of the url string:
37 if mimetypes.guess_type(url)[0] == MTYPE:
38 return True
39
40 # Could still be a zip, so check the HTTP headers:
41 try:
42 request = urllib.request.Request(url, method='HEAD')
43 response = urllib.request.urlopen(request)
44 except Exception as e:
45 raise PluginDownloadError(str(e))
46
47 return response.getheader('Content-Type') == MTYPE
48
49
50def get_zipurl_github(base_path):
51 """Guess the zip location from a github url"""
52
53 url = None
54 split = base_path.split('/')
55 if len(split) > 2:
56 url = (f'https://api.github.com/repos/{split[1]}/{split[2]}/'
57 'zipball/master')
58 return (url, {'Accept': 'application/vnd.github.v3+json'})
59
60
61def get_zipurl(url):
62 """Guess the zip location from a given URL."""
63
64 if is_zip(url):
65 return (url, {})
66
67 parsed = urllib.parse.urlparse(url)
68 if parsed.netloc == 'github.com':
69 return get_zipurl_github(parsed.path)
70
72 i18n('Could not determine download link from URL'))
73
74
75def download_plugin(url, dest_dir):
76 """Download a plugin from a given URL into the given directory.
77
78 ``url`` may either point directly to a zip location (on any site),
79 or to a github repository.
80
81 Returns full path of the downloaded zip file.
82 """
83
84 dest_path = os.path.join(dest_dir, 'plugin.zip')
85 zip_url, headers = get_zipurl(url)
86 headers['User-Agent'] = 'krita-plugin-importer'
87
88 try:
89 request = urllib.request.Request(zip_url, headers=headers)
90 with urllib.request.urlopen(request) as source:
91 with open(dest_path, 'wb') as destination:
92 destination.write(source.read())
93 except Exception as e:
94 raise PluginDownloadError(str(e))
95 return dest_path