diff --git a/Logic/ImageProviders/ImageProvider.ts b/Logic/ImageProviders/ImageProvider.ts index dded72a0b..d2cb93710 100644 --- a/Logic/ImageProviders/ImageProvider.ts +++ b/Logic/ImageProviders/ImageProvider.ts @@ -13,18 +13,6 @@ export default abstract class ImageProvider { public abstract readonly defaultKeyPrefixes: string[] - private _cache = new Map>() - - GetAttributionFor(url: string): UIEventSource { - const cached = this._cache.get(url); - if (cached !== undefined) { - return cached; - } - const src = UIEventSource.FromPromise(this.DownloadAttribution(url)) - this._cache.set(url, src) - return src; - } - public abstract SourceIcon(backlinkSource?: string): BaseUIElement; /** @@ -75,6 +63,6 @@ export default abstract class ImageProvider { public abstract ExtractUrls(key: string, value: string): Promise[]>; - protected abstract DownloadAttribution(url: string): Promise; + public abstract DownloadAttribution(url: string): Promise; } \ No newline at end of file diff --git a/Logic/ImageProviders/Imgur.ts b/Logic/ImageProviders/Imgur.ts index d7de993c0..27689a32e 100644 --- a/Logic/ImageProviders/Imgur.ts +++ b/Logic/ImageProviders/Imgur.ts @@ -99,11 +99,23 @@ export class Imgur extends ImageProvider { return [] } - protected DownloadAttribution: (url: string) => Promise = async (url: string) => { + /** + * Download the attribution from attribution + * + * const data = {"data":{"id":"I9t6B7B","title":"Station Knokke","description":"author:Pieter Vander Vennet\r\nlicense:CC-BY 4.0\r\nosmid:node\/9812712386","datetime":1655052078,"type":"image\/jpeg","animated":false,"width":2400,"height":1795,"size":910872,"views":2,"bandwidth":1821744,"vote":null,"favorite":false,"nsfw":false,"section":null,"account_url":null,"account_id":null,"is_ad":false,"in_most_viral":false,"has_sound":false,"tags":[],"ad_type":0,"ad_url":"","edited":"0","in_gallery":false,"link":"https:\/\/i.imgur.com\/I9t6B7B.jpg","ad_config":{"safeFlags":["not_in_gallery","share"],"highRiskFlags":[],"unsafeFlags":["sixth_mod_unsafe"],"wallUnsafeFlags":[],"showsAds":false,"showAdLevel":1}},"success":true,"status":200} + * Utils.injectJsonDownloadForTests("https://api.imgur.com/3/image/E0RuAK3", data) + * const licenseInfo = await Imgur.singleton.DownloadAttribution("https://i.imgur.com/E0RuAK3.jpg") + * const expected = new LicenseInfo() + * expected.licenseShortName = "CC-BY 4.0" + * expected.artist = "Pieter Vander Vennet" + * licenseInfo // => expected + */ + public async DownloadAttribution (url: string) : Promise { const hash = url.substr("https://i.imgur.com/".length).split(".jpg")[0]; const apiUrl = 'https://api.imgur.com/3/image/' + hash; - const response = await Utils.downloadJson(apiUrl, {Authorization: 'Client-ID ' + Constants.ImgurApiKey}) + const response = await Utils.downloadJsonCached(apiUrl, 365*24*60*60, + {Authorization: 'Client-ID ' + Constants.ImgurApiKey}) const descr: string = response.data.description ?? ""; const data: any = {}; diff --git a/Logic/ImageProviders/LicenseInfo.ts b/Logic/ImageProviders/LicenseInfo.ts index b295af1d4..d6353c5b6 100644 --- a/Logic/ImageProviders/LicenseInfo.ts +++ b/Logic/ImageProviders/LicenseInfo.ts @@ -1,7 +1,7 @@ export class LicenseInfo { title: string = "" artist: string = ""; - license: string = ""; + license: string = undefined; licenseShortName: string = ""; usageTerms: string = ""; attributionRequired: boolean = false; diff --git a/Logic/ImageProviders/Mapillary.ts b/Logic/ImageProviders/Mapillary.ts index 1bd655583..ffbf14945 100644 --- a/Logic/ImageProviders/Mapillary.ts +++ b/Logic/ImageProviders/Mapillary.ts @@ -4,7 +4,6 @@ import Svg from "../../Svg"; import {Utils} from "../../Utils"; import {LicenseInfo} from "./LicenseInfo"; import Constants from "../../Models/Constants"; -import * as Console from "console"; export class Mapillary extends ImageProvider { @@ -82,7 +81,7 @@ export class Mapillary extends ImageProvider { return [this.PrepareUrlAsync(key, value)] } - protected async DownloadAttribution(url: string): Promise { + public async DownloadAttribution(url: string): Promise { const license = new LicenseInfo() license.artist = "Contributor name unavailable"; license.license = "CC BY-SA 4.0"; @@ -98,7 +97,7 @@ export class Mapillary extends ImageProvider { } const metadataUrl = 'https://graph.mapillary.com/' + mapillaryId + '?fields=thumb_1024_url&&access_token=' + Constants.mapillary_client_token_v4; - const response = await Utils.downloadJson(metadataUrl) + const response = await Utils.downloadJsonCached(metadataUrl,60*60) const url = response["thumb_1024_url"]; return { url: url, diff --git a/Logic/ImageProviders/WikidataImageProvider.ts b/Logic/ImageProviders/WikidataImageProvider.ts index c3d72d064..4bcb7c2fe 100644 --- a/Logic/ImageProviders/WikidataImageProvider.ts +++ b/Logic/ImageProviders/WikidataImageProvider.ts @@ -46,7 +46,7 @@ export class WikidataImageProvider extends ImageProvider { return allImages } - protected DownloadAttribution(url: string): Promise { + public DownloadAttribution(url: string): Promise { throw new Error("Method not implemented; shouldn't be needed!"); } diff --git a/Logic/ImageProviders/WikimediaImageProvider.ts b/Logic/ImageProviders/WikimediaImageProvider.ts index ec9920640..352900f04 100644 --- a/Logic/ImageProviders/WikimediaImageProvider.ts +++ b/Logic/ImageProviders/WikimediaImageProvider.ts @@ -112,7 +112,7 @@ export class WikimediaImageProvider extends ImageProvider { return [Promise.resolve(this.UrlForImage("File:" + value))] } - protected async DownloadAttribution(filename: string): Promise { + public async DownloadAttribution(filename: string): Promise { filename = WikimediaImageProvider.ExtractFileName(filename) if (filename === "") { @@ -123,7 +123,7 @@ export class WikimediaImageProvider extends ImageProvider { "api.php?action=query&prop=imageinfo&iiprop=extmetadata&" + "titles=" + filename + "&format=json&origin=*"; - const data = await Utils.downloadJson(url) + const data = await Utils.downloadJsonCached(url,365*24*60*60) const licenseInfo = new LicenseInfo(); const pageInfo = data.query.pages[-1] if (pageInfo === undefined) { diff --git a/Models/ThemeConfig/Json/RewritableConfigJson.ts b/Models/ThemeConfig/Json/RewritableConfigJson.ts index eb15c40a7..b50771724 100644 --- a/Models/ThemeConfig/Json/RewritableConfigJson.ts +++ b/Models/ThemeConfig/Json/RewritableConfigJson.ts @@ -23,7 +23,7 @@ * * [ * { - * // The first pair: key --> X, a|b|c --> 0 + * # The first pair: key --> X, a|b|c --> 0 * "X": 0 * }, * { diff --git a/UI/Image/AttributedImage.ts b/UI/Image/AttributedImage.ts index b4485cc26..bb6ab806d 100644 --- a/UI/Image/AttributedImage.ts +++ b/UI/Image/AttributedImage.ts @@ -1,9 +1,10 @@ import Combine from "../Base/Combine"; import Attribution from "./Attribution"; import Img from "../Base/Img"; -import ImageProvider, {ProvidedImage} from "../../Logic/ImageProviders/ImageProvider"; +import ImageProvider from "../../Logic/ImageProviders/ImageProvider"; import BaseUIElement from "../BaseUIElement"; import {Mapillary} from "../../Logic/ImageProviders/Mapillary"; +import {UIEventSource} from "../../Logic/UIEventSource"; export class AttributedImage extends Combine { @@ -21,7 +22,7 @@ export class AttributedImage extends Combine { let attr: BaseUIElement = undefined if(imageInfo.provider !== undefined){ - attr = new Attribution(imageInfo.provider?.GetAttributionFor(imageInfo.url), + attr = new Attribution(UIEventSource.FromPromise( imageInfo.provider?.DownloadAttribution(imageInfo.url)), imageInfo.provider?.SourceIcon(), imageInfo.date ) diff --git a/UI/Image/Attribution.ts b/UI/Image/Attribution.ts index 98f72950f..917e9316f 100644 --- a/UI/Image/Attribution.ts +++ b/UI/Image/Attribution.ts @@ -24,7 +24,7 @@ export default class Attribution extends VariableUiElement { new Combine([ Translations.W(license?.title).SetClass("block"), Translations.W(license?.artist ?? "").SetClass("block font-bold"), - Translations.W((license?.license ?? "") === "" ? "CC0" : (license?.license ?? "")), + Translations.W(license?.license ?? license?.licenseShortName), date === undefined ? undefined : new FixedUiElement(date.toLocaleDateString()) ]).SetClass("flex flex-col") ]).SetClass("flex flex-row bg-black text-white text-sm absolute bottom-0 left-0 p-0.5 pl-5 pr-3 rounded-lg no-images") diff --git a/package-lock.json b/package-lock.json index c39cdda16..2df8f425f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,9 +26,8 @@ "@types/prompt-sync": "^4.1.0", "@types/wikidata-sdk": "^6.1.0", "@types/xml2js": "^0.4.9", - "core-js": "^3.22.8", "country-language": "^0.1.7", - "doctest-ts-improved": "^0.8.6", + "doctest-ts-improved": "^0.8.8", "email-validator": "^2.0.4", "escape-html": "^1.0.3", "geojson2svg": "^1.3.1", @@ -4899,6 +4898,7 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz", "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==", "hasInstallScript": true, + "optional": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" @@ -6057,9 +6057,9 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "node_modules/doctest-ts-improved": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/doctest-ts-improved/-/doctest-ts-improved-0.8.6.tgz", - "integrity": "sha512-J7fXMJ29ve6DUsUHKEO5bOwGmYjhNZd88L7NMVDKIiLIiUCJ9zkR2k7IZOGjMC0RXw/q788REawcMUgIj+7Muw==", + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/doctest-ts-improved/-/doctest-ts-improved-0.8.8.tgz", + "integrity": "sha512-aEkS6go+DBz8atfQSAUoCXc0N+nI2YKFXOhS9j/Jrxv0rG0J+6e6xDxiZq0rP6sKybRF/zHSWqC2jjR9qzx2ZA==", "dependencies": { "@types/chai": "^4.3.0", "chai": "^4.3.6", @@ -20572,7 +20572,8 @@ "core-js": { "version": "3.22.8", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz", - "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==" + "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==", + "optional": true }, "core-js-compat": { "version": "3.12.0", @@ -21466,9 +21467,9 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "doctest-ts-improved": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/doctest-ts-improved/-/doctest-ts-improved-0.8.6.tgz", - "integrity": "sha512-J7fXMJ29ve6DUsUHKEO5bOwGmYjhNZd88L7NMVDKIiLIiUCJ9zkR2k7IZOGjMC0RXw/q788REawcMUgIj+7Muw==", + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/doctest-ts-improved/-/doctest-ts-improved-0.8.8.tgz", + "integrity": "sha512-aEkS6go+DBz8atfQSAUoCXc0N+nI2YKFXOhS9j/Jrxv0rG0J+6e6xDxiZq0rP6sKybRF/zHSWqC2jjR9qzx2ZA==", "requires": { "@types/chai": "^4.3.0", "chai": "^4.3.6", diff --git a/package.json b/package.json index 1a7cb8523..266b05722 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "@types/wikidata-sdk": "^6.1.0", "@types/xml2js": "^0.4.9", "country-language": "^0.1.7", - "doctest-ts-improved": "^0.8.6", + "doctest-ts-improved": "^0.8.8", "email-validator": "^2.0.4", "escape-html": "^1.0.3", "geojson2svg": "^1.3.1",