From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- share/extensions/other/clipart/sources/bioicons.py | 97 ++++ .../extensions/other/clipart/sources/bioicons.svg | 145 ++++++ .../other/clipart/sources/inkscape-web.py | 74 +++ .../other/clipart/sources/inkscape-web.svg | 569 +++++++++++++++++++++ share/extensions/other/clipart/sources/ocal.py | 97 ++++ share/extensions/other/clipart/sources/ocal.svg | 132 +++++ share/extensions/other/clipart/sources/reactome.py | 64 +++ .../extensions/other/clipart/sources/reactome.svg | 111 ++++ .../extensions/other/clipart/sources/wikimedia.py | 76 +++ .../extensions/other/clipart/sources/wikimedia.svg | 92 ++++ 10 files changed, 1457 insertions(+) create mode 100644 share/extensions/other/clipart/sources/bioicons.py create mode 100644 share/extensions/other/clipart/sources/bioicons.svg create mode 100644 share/extensions/other/clipart/sources/inkscape-web.py create mode 100644 share/extensions/other/clipart/sources/inkscape-web.svg create mode 100644 share/extensions/other/clipart/sources/ocal.py create mode 100644 share/extensions/other/clipart/sources/ocal.svg create mode 100644 share/extensions/other/clipart/sources/reactome.py create mode 100644 share/extensions/other/clipart/sources/reactome.svg create mode 100644 share/extensions/other/clipart/sources/wikimedia.py create mode 100644 share/extensions/other/clipart/sources/wikimedia.svg (limited to 'share/extensions/other/clipart/sources') diff --git a/share/extensions/other/clipart/sources/bioicons.py b/share/extensions/other/clipart/sources/bioicons.py new file mode 100644 index 0000000..232f024 --- /dev/null +++ b/share/extensions/other/clipart/sources/bioicons.py @@ -0,0 +1,97 @@ +# +# Copyright 2022 Simon Duerr dev@simonduerr.eu +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# +""" +Access Bioicons. + +Downloads the database to cache and uses it locally for searching. +""" + +import json +import requests +from datetime import datetime +import os + + +from cachecontrol import CacheControl, CacheControlAdapter +from cachecontrol.caches.file_cache import FileCache +from cachecontrol.heuristics import ExpiresAfter + +from import_sources import RemoteSource + + +def local_search(query, db): + for item in db: + if query.lower() in item["name"].lower(): + yield item + return + + +class Bioicons(RemoteSource): + name = "Bioicons" + icon = "sources/bioicons.svg" + db_url = "https://bioicons.com/icons/icons.json" + icon_url = "https://bioicons.com/icons/" + + def __init__(self, cache_dir): + self.session = requests.session() + self.cache_dir = cache_dir + self.session.mount( + "https://", + CacheControlAdapter( + cache=FileCache(cache_dir), + heuristic=ExpiresAfter(days=5), + ), + ) + # check if local db is up to date with Last Modified header + try: + response = requests.head(self.db_url) + except Exception: + response = None + + self._json = os.path.join(self.cache_dir, "icons.json") + if not os.path.isfile(self._json): + last_modified = 0 + else: + last_modified = os.path.getmtime(self._json) + + if response is not None: + last_update = datetime.strptime( + response.headers["Last-Modified"], "%a, %d %b %Y %H:%M:%S GMT" + ).timestamp() + # if icon db was modified download new database + if last_modified < last_update: + self.to_local_file(self.db_url) + + def search(self, query): + results = [] + if os.path.isfile(self._json): + with open(self._json, "r") as f: + db = json.load(f) + results = local_search(query, db) + + for item in results: + yield { + "id": item["name"], + "name": item["name"], + "summary": item["category"], + "created": None, + "popularity": 0, + "author": item["author"], + "thumbnail": f"{self.icon_url}{item['license']}/{item['category']}/{item['author']}/{item['name']}.svg", + "file": f"{self.icon_url}{item['license']}/{item['category']}/{item['author']}/{item['name']}.svg", + "license": item["license"], + } diff --git a/share/extensions/other/clipart/sources/bioicons.svg b/share/extensions/other/clipart/sources/bioicons.svg new file mode 100644 index 0000000..ad9c98c --- /dev/null +++ b/share/extensions/other/clipart/sources/bioicons.svg @@ -0,0 +1,145 @@ + + + + + + image/svg+xml + + Reactome_Imagotype_Positive + + + + + + + + + Reactome_Imagotype_Positive + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/sources/inkscape-web.py b/share/extensions/other/clipart/sources/inkscape-web.py new file mode 100644 index 0000000..5960c3e --- /dev/null +++ b/share/extensions/other/clipart/sources/inkscape-web.py @@ -0,0 +1,74 @@ +# +# Copyright 2021 Martin Owens +# Copyright 2022 Simon Duerr +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# + +from import_sources import RemoteSource + + +license_mapping = { + "PD": "cc-0", + "CC-0": "cc-0", + "CC-BY 3.0": "cc-by-3.0", + "CC-BY 4.0": "cc-by-4.0", + "CC-BY-SA 4.0": "cc-by-sa-4.0", + "CC-BY-NC 3.0": "cc-by-nc-3.0", + "CC-BY-NC-SA 3.0": "cc-by-nc-sa-3.0", + "CC-BY-NC-SA 4.0": "cc-by-nc-sa-4.0", + "CC-BY-SA 3.0": "cc-by-sa-3.0", + "CC-BY-ND 3.0": "cc-by-nd-3.0", + "ASL": "asl", + "nbsd": "bsd", + "GPLv2": "gpl-2", + "GPLv3": "gpl-3", + "AGPLv3": "agpl-3", + "MIT": "mit", +} + + +class InkscapeWebsite(RemoteSource): + name = "Inkscape Community" + icon = "sources/inkscape-web.svg" + is_default = True + + base_url = "https://inkscape.org/gallery/=artwork/json/" + + def search(self, query): + """Ask the inkscape website for some artwork""" + items = [] + try: + response = self.session.get(self.base_url, params={"q": query}) + items = response.json()["items"] + except Exception: + pass + + for item in items: + if "svg" not in item["type"]: + continue + if ( + item["license"] == "(C)" + ): # ignore copyrighted items because they cannot be reused + continue + yield { + "id": item["id"], + "name": item["name"], + "author": item["author"], + "license": license_mapping.get(item["license"], item["license"].lower()), + "summary": item["summary"], + "thumbnail": item["icon"] or item["links"]["file"], + "created": item["dates"]["created"], + "popularity": item["stats"]["liked"], + "file": item["links"]["file"], + } diff --git a/share/extensions/other/clipart/sources/inkscape-web.svg b/share/extensions/other/clipart/sources/inkscape-web.svg new file mode 100644 index 0000000..8e2ec3b --- /dev/null +++ b/share/extensions/other/clipart/sources/inkscape-web.svg @@ -0,0 +1,569 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/sources/ocal.py b/share/extensions/other/clipart/sources/ocal.py new file mode 100644 index 0000000..2fe06db --- /dev/null +++ b/share/extensions/other/clipart/sources/ocal.py @@ -0,0 +1,97 @@ +# +# Copyright 2021 Martin Owens +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# + +import sys +import json +import logging + +from import_sources import RemoteSource, RemoteFile +from urllib.parse import urljoin, parse_qs + +try: + from bs4 import BeautifulSoup +except ImportError: + BeautifulSoup = None + + +class OpenClipartFile(RemoteFile): + def get_file(self): + """Extract search result from html""" + response = self.remote.session.get(self.info["file"]) + soup = BeautifulSoup(response.text, features="lxml") + for script in soup.find_all("script"): + content = script.contents + if content and "image" in content[0]: + try: + data = json.loads(content[0]) + return self.remote.to_local_file(data["image"]["url"]) + except Exception: + continue + logging.error("Couldn't load svg from %s", self.info["file"]) + + +class OpenClipart(RemoteSource): + name = "Open Clipart Library" + icon = "sources/ocal.svg" + base_url = "https://openclipart.org/search/" + is_enabled = BeautifulSoup is not None + file_cls = OpenClipartFile + + def html_search(self, response): + """Extract search results from html""" + soup = BeautifulSoup(response.text, features="lxml") + for div in soup.find_all("div", {"class": "artwork"}): + if div.a and div.a.img: + link = urljoin(self.base_url, div.a.get("href")) + img = urljoin(self.base_url, div.a.img.get("src")) + + yield { + "file": link, # Not the actual file yet (see above) + "name": div.a.img.get("alt"), + "thumbnail": img, + "author": "OpenClipart", + "license": "cc-0", + } + + for page in soup.find_all("a", {"class": "page-link", "aria-label": "Next"}): + if "=" in page.get("href", ""): + yield lambda: self._search(**parse_qs(page.get("href").split("?")[-1])) + + def search(self, query): + """HTML searching for now""" + return self._search(query=query) + + def _search(self, **params): + try: + response = self.session.get(self.base_url, params=params) + except Exception: + return [] + + items = [] + next_page = None + for item in self.html_search(response): + if callable(item): + next_page = item + else: + items.append(item) + # Often ocal will have empty pages, weirdly. + if not items and next_page: + return next_page() + # None empty page, return all + if next_page: + items.append(next_page) + return items diff --git a/share/extensions/other/clipart/sources/ocal.svg b/share/extensions/other/clipart/sources/ocal.svg new file mode 100644 index 0000000..44eba39 --- /dev/null +++ b/share/extensions/other/clipart/sources/ocal.svg @@ -0,0 +1,132 @@ + + + + + + image/svg+xml + + Reactome_Imagotype_Positive + + + + + + + + Reactome_Imagotype_Positive + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/sources/reactome.py b/share/extensions/other/clipart/sources/reactome.py new file mode 100644 index 0000000..1a1c8b3 --- /dev/null +++ b/share/extensions/other/clipart/sources/reactome.py @@ -0,0 +1,64 @@ +# +# Copyright 2021 Martin Owens +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# +""" +Access Reactome Content Services. +""" + +import re + +from import_sources import RemoteSource + +TAG_REX = re.compile(r'<[^<]+?>') + +class Reactome(RemoteSource): + name = 'Reactome (Bio)' + icon = 'sources/reactome.svg' + search_url = "https://reactome.org/ContentService/search/query" + file_url = "https://reactome.org/icon/{stId}.svg" + icon_url = "https://reactome.org/icon/{stId}.png" + all_licence = "cc-by-sa-4.0" + + def search(self, query): + params = { + "query": query, + "types": "Icon", + "cluster": "true", + "Start row": 0, + "rows": 100, + } + response = {} + try: + response = self.session.get(self.search_url, params=params).json() + except Exception: + pass + + if 'messages' in response and 'No entries' in response['messages'][0]: + return + for cats in response.get('results', []): + for entry in cats['entries']: + yield { + 'id': entry['dbId'], + 'name': TAG_REX.sub('', entry['name']), + 'author': 'Reactome/'+entry.get('iconDesignerName', "Unknown"), + 'summary': TAG_REX.sub('', entry.get('summation', '')), + 'created': None, # No data + 'popularity': 0, # No data + 'thumbnail': self.icon_url.format(**entry), + 'file': self.file_url.format(**entry), + 'license': self.all_licence, + } + diff --git a/share/extensions/other/clipart/sources/reactome.svg b/share/extensions/other/clipart/sources/reactome.svg new file mode 100644 index 0000000..3c6562c --- /dev/null +++ b/share/extensions/other/clipart/sources/reactome.svg @@ -0,0 +1,111 @@ + + + + + + image/svg+xml + + Reactome_Imagotype_Positive + + + + + + + + Reactome_Imagotype_Positive + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/sources/wikimedia.py b/share/extensions/other/clipart/sources/wikimedia.py new file mode 100644 index 0000000..f260bc8 --- /dev/null +++ b/share/extensions/other/clipart/sources/wikimedia.py @@ -0,0 +1,76 @@ +# +# Copyright 2021 Martin Owens +# Copyright 2022 Simon Duerr +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# + +import hashlib +from import_sources import RemoteSource + + +class Wikimedia(RemoteSource): + name = "Wikimedia" + icon = "sources/wikimedia.svg" + base_url = "https://commons.wikimedia.org/w/api.php" + + def search(self, query): + params = { + "action": "query", + "format": "json", + "uselang": "en", + "generator": "search", + "gsrsearch": "filetype:bitmap|drawing filemime:svg " + query, + "gsrlimit": 40, + "gsroffset": 0, + "gsrinfo": "totalhits|suggestion", + "gsrprop": "size|wordcount", + "gsrnamespace": 6, + "prop": "info|imageinfo|entityterms", + "inprop": "url", + "iiprop": "url|size|mime|user|extmetadata", + "iiurlheight": 180, + "wbetterms": "label", + } + pages = [] + try: + response = self.session.get(self.base_url, params=params).json() + if "error" in response: + raise IOError(response["error"]["info"]) + pages = response["query"]["pages"].values() + except: + pass + + for item in pages: + img = item["imageinfo"][0] + # get standard licenses + # for non standard licenses we have to get the ShortName and provide the url to the resource + try: + license = img["extmetadata"]["License"]["value"] + if license in ["cc0", "pd"]: + license = "cc-0" + except KeyError: + license = img["extmetadata"]["LicenseShortName"]["value"] + yield { + "id": item.get("pageid", None), + "name": item["title"].split(":", 1)[-1], + "author": img["user"], + "license": license, + "summary": "", # No data + "thumbnail": img["thumburl"], + "created": item["touched"], + "descriptionurl": item["canonicalurl"], + "popularity": 0, # No data + "file": img["url"], + } diff --git a/share/extensions/other/clipart/sources/wikimedia.svg b/share/extensions/other/clipart/sources/wikimedia.svg new file mode 100644 index 0000000..23387ab --- /dev/null +++ b/share/extensions/other/clipart/sources/wikimedia.svg @@ -0,0 +1,92 @@ + + + + + + image/svg+xml + + Reactome_Imagotype_Positive + + + + + + + + + + + Reactome_Imagotype_Positive + + + + + + + + -- cgit v1.2.3