Reformat all files with prettier

This commit is contained in:
Pieter Vander Vennet 2022-09-08 21:40:48 +02:00
parent e22d189376
commit b541d3eab4
382 changed files with 50893 additions and 35566 deletions

View file

@ -1,45 +1,52 @@
import {Mapillary} from "./Mapillary";
import {WikimediaImageProvider} from "./WikimediaImageProvider";
import {Imgur} from "./Imgur";
import GenericImageProvider from "./GenericImageProvider";
import {Store, UIEventSource} from "../UIEventSource";
import ImageProvider, {ProvidedImage} from "./ImageProvider";
import {WikidataImageProvider} from "./WikidataImageProvider";
import { Mapillary } from "./Mapillary"
import { WikimediaImageProvider } from "./WikimediaImageProvider"
import { Imgur } from "./Imgur"
import GenericImageProvider from "./GenericImageProvider"
import { Store, UIEventSource } from "../UIEventSource"
import ImageProvider, { ProvidedImage } from "./ImageProvider"
import { WikidataImageProvider } from "./WikidataImageProvider"
/**
* A generic 'from the interwebz' image picker, without attribution
*/
export default class AllImageProviders {
public static ImageAttributionSource: ImageProvider[] = [
Imgur.singleton,
Mapillary.singleton,
WikidataImageProvider.singleton,
WikimediaImageProvider.singleton,
new GenericImageProvider(
[].concat(...Imgur.defaultValuePrefix, ...WikimediaImageProvider.commonsPrefixes, ...Mapillary.valuePrefixes)
)
[].concat(
...Imgur.defaultValuePrefix,
...WikimediaImageProvider.commonsPrefixes,
...Mapillary.valuePrefixes
)
),
]
private static providersByName= {
"imgur": Imgur.singleton,
"mapillary": Mapillary.singleton,
"wikidata": WikidataImageProvider.singleton,
"wikimedia": WikimediaImageProvider.singleton
private static providersByName = {
imgur: Imgur.singleton,
mapillary: Mapillary.singleton,
wikidata: WikidataImageProvider.singleton,
wikimedia: WikimediaImageProvider.singleton,
}
public static byName(name: string){
public static byName(name: string) {
return AllImageProviders.providersByName[name.toLowerCase()]
}
public static defaultKeys = [].concat(AllImageProviders.ImageAttributionSource.map(provider => provider.defaultKeyPrefixes))
public static defaultKeys = [].concat(
AllImageProviders.ImageAttributionSource.map((provider) => provider.defaultKeyPrefixes)
)
private static _cache: Map<string, UIEventSource<ProvidedImage[]>> = new Map<string, UIEventSource<ProvidedImage[]>>()
private static _cache: Map<string, UIEventSource<ProvidedImage[]>> = new Map<
string,
UIEventSource<ProvidedImage[]>
>()
public static LoadImagesFor(tags: Store<any>, tagKey?: string[]): Store<ProvidedImage[]> {
if (tags.data.id === undefined) {
return undefined;
return undefined
}
const cacheKey = tags.data.id + tagKey
@ -48,23 +55,21 @@ export default class AllImageProviders {
return cached
}
const source = new UIEventSource([])
this._cache.set(cacheKey, source)
const allSources = []
for (const imageProvider of AllImageProviders.ImageAttributionSource) {
let prefixes = imageProvider.defaultKeyPrefixes
if (tagKey !== undefined) {
prefixes = tagKey
}
const singleSource = imageProvider.GetRelevantUrls(tags, {
prefixes: prefixes
prefixes: prefixes,
})
allSources.push(singleSource)
singleSource.addCallbackAndRunD(_ => {
const all: ProvidedImage[] = [].concat(...allSources.map(source => source.data))
singleSource.addCallbackAndRunD((_) => {
const all: ProvidedImage[] = [].concat(...allSources.map((source) => source.data))
const uniq = []
const seen = new Set<string>()
for (const img of all) {
@ -77,7 +82,6 @@ export default class AllImageProviders {
source.setData(uniq)
})
}
return source;
return source
}
}
}

View file

@ -1,18 +1,17 @@
import ImageProvider, {ProvidedImage} from "./ImageProvider";
import ImageProvider, { ProvidedImage } from "./ImageProvider"
export default class GenericImageProvider extends ImageProvider {
public defaultKeyPrefixes: string[] = ["image"];
public defaultKeyPrefixes: string[] = ["image"]
private readonly _valuePrefixBlacklist: string[];
private readonly _valuePrefixBlacklist: string[]
public constructor(valuePrefixBlacklist: string[]) {
super();
this._valuePrefixBlacklist = valuePrefixBlacklist;
super()
this._valuePrefixBlacklist = valuePrefixBlacklist
}
async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> {
if (this._valuePrefixBlacklist.some(prefix => value.startsWith(prefix))) {
if (this._valuePrefixBlacklist.some((prefix) => value.startsWith(prefix))) {
return []
}
@ -23,20 +22,20 @@ export default class GenericImageProvider extends ImageProvider {
return []
}
return [Promise.resolve({
key: key,
url: value,
provider: this
})]
return [
Promise.resolve({
key: key,
url: value,
provider: this,
}),
]
}
SourceIcon(backlinkSource?: string) {
return undefined;
return undefined
}
public DownloadAttribution(url: string) {
return undefined
}
}
}

View file

@ -1,50 +1,53 @@
import {Store, UIEventSource} from "../UIEventSource";
import BaseUIElement from "../../UI/BaseUIElement";
import {LicenseInfo} from "./LicenseInfo";
import {Utils} from "../../Utils";
import { Store, UIEventSource } from "../UIEventSource"
import BaseUIElement from "../../UI/BaseUIElement"
import { LicenseInfo } from "./LicenseInfo"
import { Utils } from "../../Utils"
export interface ProvidedImage {
url: string,
key: string,
url: string
key: string
provider: ImageProvider
}
export default abstract class ImageProvider {
public abstract readonly defaultKeyPrefixes: string[]
public abstract SourceIcon(backlinkSource?: string): BaseUIElement;
public abstract SourceIcon(backlinkSource?: string): BaseUIElement
/**
* Given a properies object, maps it onto _all_ the available pictures for this imageProvider
*/
public GetRelevantUrls(allTags: Store<any>, options?: {
prefixes?: string[]
}): UIEventSource<ProvidedImage[]> {
public GetRelevantUrls(
allTags: Store<any>,
options?: {
prefixes?: string[]
}
): UIEventSource<ProvidedImage[]> {
const prefixes = options?.prefixes ?? this.defaultKeyPrefixes
if (prefixes === undefined) {
throw "No `defaultKeyPrefixes` defined by this image provider"
}
const relevantUrls = new UIEventSource<{ url: string; key: string; provider: ImageProvider }[]>([])
const relevantUrls = new UIEventSource<
{ url: string; key: string; provider: ImageProvider }[]
>([])
const seenValues = new Set<string>()
allTags.addCallbackAndRunD(tags => {
allTags.addCallbackAndRunD((tags) => {
for (const key in tags) {
if (!prefixes.some(prefix => key.startsWith(prefix))) {
if (!prefixes.some((prefix) => key.startsWith(prefix))) {
continue
}
const values = Utils.NoEmpty(tags[key]?.split(";")?.map(v => v.trim()) ?? [])
const values = Utils.NoEmpty(tags[key]?.split(";")?.map((v) => v.trim()) ?? [])
for (const value of values) {
if (seenValues.has(value)) {
continue
}
seenValues.add(value)
this.ExtractUrls(key, value).then(promises => {
this.ExtractUrls(key, value).then((promises) => {
for (const promise of promises ?? []) {
if (promise === undefined) {
continue
}
promise.then(providedImage => {
promise.then((providedImage) => {
if (providedImage === undefined) {
return
}
@ -54,15 +57,12 @@ export default abstract class ImageProvider {
}
})
}
}
})
return relevantUrls
}
public abstract ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]>;
public abstract ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]>
public abstract DownloadAttribution(url: string): Promise<LicenseInfo>;
}
public abstract DownloadAttribution(url: string): Promise<LicenseInfo>
}

View file

@ -1,93 +1,105 @@
import ImageProvider, { ProvidedImage } from "./ImageProvider";
import BaseUIElement from "../../UI/BaseUIElement";
import {Utils} from "../../Utils";
import Constants from "../../Models/Constants";
import {LicenseInfo} from "./LicenseInfo";
import ImageProvider, { ProvidedImage } from "./ImageProvider"
import BaseUIElement from "../../UI/BaseUIElement"
import { Utils } from "../../Utils"
import Constants from "../../Models/Constants"
import { LicenseInfo } from "./LicenseInfo"
export class Imgur extends ImageProvider {
public static readonly defaultValuePrefix = ["https://i.imgur.com"]
public static readonly singleton = new Imgur();
public readonly defaultKeyPrefixes: string[] = ["image"];
public static readonly singleton = new Imgur()
public readonly defaultKeyPrefixes: string[] = ["image"]
private constructor() {
super();
super()
}
static uploadMultiple(
title: string, description: string, blobs: FileList,
handleSuccessfullUpload: ((imageURL: string) => Promise<void>),
allDone: (() => void),
onFail: ((reason: string) => void),
offset: number = 0) {
title: string,
description: string,
blobs: FileList,
handleSuccessfullUpload: (imageURL: string) => Promise<void>,
allDone: () => void,
onFail: (reason: string) => void,
offset: number = 0
) {
if (blobs.length == offset) {
allDone();
return;
allDone()
return
}
const blob = blobs.item(offset);
const self = this;
this.uploadImage(title, description, blob,
const blob = blobs.item(offset)
const self = this
this.uploadImage(
title,
description,
blob,
async (imageUrl) => {
await handleSuccessfullUpload(imageUrl);
await handleSuccessfullUpload(imageUrl)
self.uploadMultiple(
title, description, blobs,
title,
description,
blobs,
handleSuccessfullUpload,
allDone,
onFail,
offset + 1);
offset + 1
)
},
onFail
);
)
}
static uploadImage(title: string, description: string, blob: File,
handleSuccessfullUpload: ((imageURL: string) => Promise<void>),
onFail: (reason: string) => void) {
static uploadImage(
title: string,
description: string,
blob: File,
handleSuccessfullUpload: (imageURL: string) => Promise<void>,
onFail: (reason: string) => void
) {
const apiUrl = "https://api.imgur.com/3/image"
const apiKey = Constants.ImgurApiKey
const apiUrl = 'https://api.imgur.com/3/image';
const apiKey = Constants.ImgurApiKey;
const formData = new FormData();
formData.append('image', blob);
formData.append("title", title);
const formData = new FormData()
formData.append("image", blob)
formData.append("title", title)
formData.append("description", description)
const settings: RequestInit = {
method: 'POST',
method: "POST",
body: formData,
redirect: 'follow',
redirect: "follow",
headers: new Headers({
Authorization: `Client-ID ${apiKey}`,
Accept: 'application/json',
Accept: "application/json",
}),
};
}
// Response contains stringified JSON
// Image URL available at response.data.link
fetch(apiUrl, settings).then(async function (response) {
const content = await response.json()
await handleSuccessfullUpload(content.data.link);
}).catch((reason) => {
console.log("Uploading to IMGUR failed", reason);
// @ts-ignore
onFail(reason);
});
fetch(apiUrl, settings)
.then(async function (response) {
const content = await response.json()
await handleSuccessfullUpload(content.data.link)
})
.catch((reason) => {
console.log("Uploading to IMGUR failed", reason)
// @ts-ignore
onFail(reason)
})
}
SourceIcon(): BaseUIElement {
return undefined;
return undefined
}
public async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> {
if (Imgur.defaultValuePrefix.some(prefix => value.startsWith(prefix))) {
return [Promise.resolve({
url: value,
key: key,
provider: this
})]
if (Imgur.defaultValuePrefix.some((prefix) => value.startsWith(prefix))) {
return [
Promise.resolve({
url: value,
key: key,
provider: this,
}),
]
}
return []
}
@ -103,29 +115,27 @@ export class Imgur extends ImageProvider {
* expected.artist = "Pieter Vander Vennet"
* licenseInfo // => expected
*/
public async DownloadAttribution (url: string) : Promise<LicenseInfo> {
const hash = url.substr("https://i.imgur.com/".length).split(".jpg")[0];
public async DownloadAttribution(url: string): Promise<LicenseInfo> {
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.downloadJsonCached(apiUrl, 365*24*60*60,
{Authorization: 'Client-ID ' + Constants.ImgurApiKey})
const apiUrl = "https://api.imgur.com/3/image/" + hash
const response = await Utils.downloadJsonCached(apiUrl, 365 * 24 * 60 * 60, {
Authorization: "Client-ID " + Constants.ImgurApiKey,
})
const descr: string = response.data.description ?? "";
const data: any = {};
const descr: string = response.data.description ?? ""
const data: any = {}
for (const tag of descr.split("\n")) {
const kv = tag.split(":");
const k = kv[0];
data[k] = kv[1]?.replace(/\r/g, "");
const kv = tag.split(":")
const k = kv[0]
data[k] = kv[1]?.replace(/\r/g, "")
}
const licenseInfo = new LicenseInfo()
const licenseInfo = new LicenseInfo();
licenseInfo.licenseShortName = data.license;
licenseInfo.artist = data.author;
licenseInfo.licenseShortName = data.license
licenseInfo.artist = data.author
return licenseInfo
}
}
}

View file

@ -1,16 +1,15 @@
import {UIEventSource} from "../UIEventSource";
import {Imgur} from "./Imgur";
import { UIEventSource } from "../UIEventSource"
import { Imgur } from "./Imgur"
export default class ImgurUploader {
public readonly queue: UIEventSource<string[]> = new UIEventSource<string[]>([]);
public readonly failed: UIEventSource<string[]> = new UIEventSource<string[]>([]);
public readonly success: UIEventSource<string[]> = new UIEventSource<string[]>([]);
public maxFileSizeInMegabytes = 10;
private readonly _handleSuccessUrl: (string) => Promise<void>;
public readonly queue: UIEventSource<string[]> = new UIEventSource<string[]>([])
public readonly failed: UIEventSource<string[]> = new UIEventSource<string[]>([])
public readonly success: UIEventSource<string[]> = new UIEventSource<string[]>([])
public maxFileSizeInMegabytes = 10
private readonly _handleSuccessUrl: (string) => Promise<void>
constructor(handleSuccessUrl: (string) => Promise<void>) {
this._handleSuccessUrl = handleSuccessUrl;
this._handleSuccessUrl = handleSuccessUrl
}
public uploadMany(title: string, description: string, files: FileList): void {
@ -19,25 +18,26 @@ export default class ImgurUploader {
}
this.queue.ping()
const self = this;
const self = this
this.queue.setData([...self.queue.data])
Imgur.uploadMultiple(title,
Imgur.uploadMultiple(
title,
description,
files,
async function (url) {
console.log("File saved at", url);
console.log("File saved at", url)
self.success.data.push(url)
self.success.ping();
await self._handleSuccessUrl(url);
self.success.ping()
await self._handleSuccessUrl(url)
},
function () {
console.log("All uploads completed");
console.log("All uploads completed")
},
function (failReason) {
console.log("Upload failed due to ", failReason)
self.failed.setData([...self.failed.data, failReason])
}
);
)
}
}
}

View file

@ -1,12 +1,12 @@
export class LicenseInfo {
title: string = ""
artist: string = "";
license: string = undefined;
licenseShortName: string = "";
usageTerms: string = "";
attributionRequired: boolean = false;
copyrighted: boolean = false;
credit: string = "";
description: string = "";
artist: string = ""
license: string = undefined
licenseShortName: string = ""
usageTerms: string = ""
attributionRequired: boolean = false
copyrighted: boolean = false
credit: string = ""
description: string = ""
informationLocation: URL = undefined
}
}

View file

@ -1,21 +1,26 @@
import ImageProvider, {ProvidedImage} from "./ImageProvider";
import BaseUIElement from "../../UI/BaseUIElement";
import Svg from "../../Svg";
import {Utils} from "../../Utils";
import {LicenseInfo} from "./LicenseInfo";
import Constants from "../../Models/Constants";
import ImageProvider, { ProvidedImage } from "./ImageProvider"
import BaseUIElement from "../../UI/BaseUIElement"
import Svg from "../../Svg"
import { Utils } from "../../Utils"
import { LicenseInfo } from "./LicenseInfo"
import Constants from "../../Models/Constants"
export class Mapillary extends ImageProvider {
public static readonly singleton = new Mapillary();
public static readonly singleton = new Mapillary()
private static readonly valuePrefix = "https://a.mapillary.com"
public static readonly valuePrefixes = [Mapillary.valuePrefix, "http://mapillary.com", "https://mapillary.com", "http://www.mapillary.com", "https://www.mapillary.com"]
public static readonly valuePrefixes = [
Mapillary.valuePrefix,
"http://mapillary.com",
"https://mapillary.com",
"http://www.mapillary.com",
"https://www.mapillary.com",
]
defaultKeyPrefixes = ["mapillary", "image"]
/**
* Indicates that this is the same URL
* Ignores 'stp' parameter
*
*
* const a = "https://scontent-bru2-1.xx.fbcdn.net/m1/v/t6/An8xm5SGLt20ETziNqzhhBd8b8S5GHLiIu8N6BbyqHFohFAQoaJJPG8i5yQiSwjYmEqXSfVeoCmpiyBJICEkQK98JOB21kkJoBS8VdhYa-Ty93lBnznQyesJBtKcb32foGut2Hgt10hEMWJbE3dDgA?stp=s1024x768&ccb=10-5&oh=00_AT-ZGTXHzihoaQYBILmEiAEKR64z_IWiTlcAYq_D7Ka0-Q&oe=6278C456&_nc_sid=122ab1"
* const b = "https://scontent-bru2-1.xx.fbcdn.net/m1/v/t6/An8xm5SGLt20ETziNqzhhBd8b8S5GHLiIu8N6BbyqHFohFAQoaJJPG8i5yQiSwjYmEqXSfVeoCmpiyBJICEkQK98JOB21kkJoBS8VdhYa-Ty93lBnznQyesJBtKcb32foGut2Hgt10hEMWJbE3dDgA?stp=s256x192&ccb=10-5&oh=00_AT9BZ1Rpc9zbY_uNu92A_4gj1joiy1b6VtgtLIu_7wh9Bg&oe=6278C456&_nc_sid=122ab1"
* Mapillary.sameUrl(a, b) => true
@ -28,9 +33,9 @@ export class Mapillary extends ImageProvider {
const aUrl = new URL(a)
const bUrl = new URL(b)
if (aUrl.host !== bUrl.host || aUrl.pathname !== bUrl.pathname) {
return false;
return false
}
let allSame = true;
let allSame = true
aUrl.searchParams.forEach((value, key) => {
if (key === "stp") {
// This is the key indicating the image size on mapillary; we ignore it
@ -41,20 +46,18 @@ export class Mapillary extends ImageProvider {
return
}
})
return allSame;
return allSame
} catch (e) {
console.debug("Could not compare ", a, "and", b, "due to", e)
}
return false;
return false
}
/**
* Returns the correct key for API v4.0
*/
private static ExtractKeyFromURL(value: string): number {
let key: string;
let key: string
const newApiFormat = value.match(/https?:\/\/www.mapillary.com\/app\/\?pKey=([0-9]*)/)
if (newApiFormat !== null) {
@ -62,7 +65,7 @@ export class Mapillary extends ImageProvider {
} else if (value.startsWith(Mapillary.valuePrefix)) {
key = value.substring(0, value.lastIndexOf("?")).substring(value.lastIndexOf("/") + 1)
} else if (value.match("[0-9]*")) {
key = value;
key = value
}
const keyAsNumber = Number(key)
@ -74,7 +77,7 @@ export class Mapillary extends ImageProvider {
}
SourceIcon(backlinkSource?: string): BaseUIElement {
return Svg.mapillary_svg();
return Svg.mapillary_svg()
}
async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> {
@ -83,26 +86,30 @@ export class Mapillary extends ImageProvider {
public async DownloadAttribution(url: string): Promise<LicenseInfo> {
const license = new LicenseInfo()
license.artist = "Contributor name unavailable";
license.license = "CC BY-SA 4.0";
license.artist = "Contributor name unavailable"
license.license = "CC BY-SA 4.0"
// license.license = "Creative Commons Attribution-ShareAlike 4.0 International License";
license.attributionRequired = true;
license.attributionRequired = true
return license
}
private async PrepareUrlAsync(key: string, value: string): Promise<ProvidedImage> {
const mapillaryId = Mapillary.ExtractKeyFromURL(value)
if (mapillaryId === undefined) {
return undefined;
return undefined
}
const metadataUrl = 'https://graph.mapillary.com/' + mapillaryId + '?fields=thumb_1024_url&&access_token=' + Constants.mapillary_client_token_v4;
const response = await Utils.downloadJsonCached(metadataUrl,60*60)
const url = <string>response["thumb_1024_url"];
const metadataUrl =
"https://graph.mapillary.com/" +
mapillaryId +
"?fields=thumb_1024_url&&access_token=" +
Constants.mapillary_client_token_v4
const response = await Utils.downloadJsonCached(metadataUrl, 60 * 60)
const url = <string>response["thumb_1024_url"]
return {
url: url,
provider: this,
key: key
key: key,
}
}
}
}

View file

@ -1,11 +1,10 @@
import ImageProvider, {ProvidedImage} from "./ImageProvider";
import BaseUIElement from "../../UI/BaseUIElement";
import Svg from "../../Svg";
import {WikimediaImageProvider} from "./WikimediaImageProvider";
import Wikidata from "../Web/Wikidata";
import ImageProvider, { ProvidedImage } from "./ImageProvider"
import BaseUIElement from "../../UI/BaseUIElement"
import Svg from "../../Svg"
import { WikimediaImageProvider } from "./WikimediaImageProvider"
import Wikidata from "../Web/Wikidata"
export class WikidataImageProvider extends ImageProvider {
public static readonly singleton = new WikidataImageProvider()
public readonly defaultKeyPrefixes = ["wikidata"]
@ -14,7 +13,7 @@ export class WikidataImageProvider extends ImageProvider {
}
public SourceIcon(backlinkSource?: string): BaseUIElement {
throw Svg.wikidata_svg();
throw Svg.wikidata_svg()
}
public async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> {
@ -39,7 +38,10 @@ export class WikidataImageProvider extends ImageProvider {
}
const commons = entity.commons
if (commons !== undefined && (commons.startsWith("Category:") || commons.startsWith("File:"))) {
if (
commons !== undefined &&
(commons.startsWith("Category:") || commons.startsWith("File:"))
) {
const promises = await WikimediaImageProvider.singleton.ExtractUrls(undefined, commons)
allImages.push(...promises)
}
@ -47,7 +49,6 @@ export class WikidataImageProvider extends ImageProvider {
}
public DownloadAttribution(url: string): Promise<any> {
throw new Error("Method not implemented; shouldn't be needed!");
throw new Error("Method not implemented; shouldn't be needed!")
}
}
}

View file

@ -1,45 +1,47 @@
import ImageProvider, {ProvidedImage} from "./ImageProvider";
import BaseUIElement from "../../UI/BaseUIElement";
import Svg from "../../Svg";
import Link from "../../UI/Base/Link";
import {Utils} from "../../Utils";
import {LicenseInfo} from "./LicenseInfo";
import Wikimedia from "../Web/Wikimedia";
import ImageProvider, { ProvidedImage } from "./ImageProvider"
import BaseUIElement from "../../UI/BaseUIElement"
import Svg from "../../Svg"
import Link from "../../UI/Base/Link"
import { Utils } from "../../Utils"
import { LicenseInfo } from "./LicenseInfo"
import Wikimedia from "../Web/Wikimedia"
/**
* This module provides endpoints for wikimedia and others
*/
export class WikimediaImageProvider extends ImageProvider {
public static readonly singleton = new WikimediaImageProvider();
public static readonly commonsPrefixes = ["https://commons.wikimedia.org/wiki/", "https://upload.wikimedia.org", "File:"]
public static readonly singleton = new WikimediaImageProvider()
public static readonly commonsPrefixes = [
"https://commons.wikimedia.org/wiki/",
"https://upload.wikimedia.org",
"File:",
]
private readonly commons_key = "wikimedia_commons"
public readonly defaultKeyPrefixes = [this.commons_key, "image"]
private constructor() {
super();
super()
}
private static ExtractFileName(url: string) {
if (!url.startsWith("http")) {
return url;
return url
}
const path = new URL(url).pathname
return path.substring(path.lastIndexOf("/") + 1);
return path.substring(path.lastIndexOf("/") + 1)
}
private static PrepareUrl(value: string): string {
if (value.toLowerCase().startsWith("https://commons.wikimedia.org/wiki/")) {
return value;
return value
}
return (`https://commons.wikimedia.org/wiki/Special:FilePath/${encodeURIComponent(value)}?width=500&height=400`)
return `https://commons.wikimedia.org/wiki/Special:FilePath/${encodeURIComponent(
value
)}?width=500&height=400`
}
private static startsWithCommonsPrefix(value: string): boolean {
return WikimediaImageProvider.commonsPrefixes.some(prefix => value.startsWith(prefix))
return WikimediaImageProvider.commonsPrefixes.some((prefix) => value.startsWith(prefix))
}
private static removeCommonsPrefix(value: string): string {
@ -49,7 +51,7 @@ export class WikimediaImageProvider extends ImageProvider {
if (!value.startsWith("File:")) {
value = "File:" + value
}
return value;
return value
}
for (const prefix of WikimediaImageProvider.commonsPrefixes) {
@ -61,21 +63,20 @@ export class WikimediaImageProvider extends ImageProvider {
return part
}
}
return value;
return value
}
SourceIcon(backlink: string): BaseUIElement {
const img = Svg.wikimedia_commons_white_svg()
.SetStyle("width:2em;height: 2em");
const img = Svg.wikimedia_commons_white_svg().SetStyle("width:2em;height: 2em")
if (backlink === undefined) {
return img
}
return new Link(Svg.wikimedia_commons_white_img,
`https://commons.wikimedia.org/wiki/${backlink}`, true)
return new Link(
Svg.wikimedia_commons_white_img,
`https://commons.wikimedia.org/wiki/${backlink}`,
true
)
}
public PrepUrl(value: string): ProvidedImage {
@ -99,7 +100,9 @@ export class WikimediaImageProvider extends ImageProvider {
value = WikimediaImageProvider.removeCommonsPrefix(value)
if (value.startsWith("Category:")) {
const urls = await Wikimedia.GetCategoryContents(value)
return urls.filter(url => url.startsWith("File:")).map(image => Promise.resolve(this.UrlForImage(image)))
return urls
.filter((url) => url.startsWith("File:"))
.map((image) => Promise.resolve(this.UrlForImage(image)))
}
if (value.startsWith("File:")) {
return [Promise.resolve(this.UrlForImage(value))]
@ -116,24 +119,30 @@ export class WikimediaImageProvider extends ImageProvider {
filename = WikimediaImageProvider.ExtractFileName(filename)
if (filename === "") {
return undefined;
return undefined
}
const url = "https://en.wikipedia.org/w/" +
const url =
"https://en.wikipedia.org/w/" +
"api.php?action=query&prop=imageinfo&iiprop=extmetadata&" +
"titles=" + filename +
"&format=json&origin=*";
const data = await Utils.downloadJsonCached(url,365*24*60*60)
const licenseInfo = new LicenseInfo();
"titles=" +
filename +
"&format=json&origin=*"
const data = await Utils.downloadJsonCached(url, 365 * 24 * 60 * 60)
const licenseInfo = new LicenseInfo()
const pageInfo = data.query.pages[-1]
if (pageInfo === undefined) {
return undefined;
return undefined
}
const license = (pageInfo.imageinfo ?? [])[0]?.extmetadata;
const license = (pageInfo.imageinfo ?? [])[0]?.extmetadata
if (license === undefined) {
console.warn("The file", filename, "has no usable metedata or license attached... Please fix the license info file yourself!")
return undefined;
console.warn(
"The file",
filename,
"has no usable metedata or license attached... Please fix the license info file yourself!"
)
return undefined
}
let title = pageInfo.title
@ -145,26 +154,22 @@ export class WikimediaImageProvider extends ImageProvider {
}
licenseInfo.title = title
licenseInfo.artist = license.Artist?.value;
licenseInfo.license = license.License?.value;
licenseInfo.copyrighted = license.Copyrighted?.value;
licenseInfo.attributionRequired = license.AttributionRequired?.value;
licenseInfo.usageTerms = license.UsageTerms?.value;
licenseInfo.licenseShortName = license.LicenseShortName?.value;
licenseInfo.credit = license.Credit?.value;
licenseInfo.description = license.ImageDescription?.value;
licenseInfo.informationLocation = new URL("https://en.wikipedia.org/wiki/"+pageInfo.title)
return licenseInfo;
licenseInfo.artist = license.Artist?.value
licenseInfo.license = license.License?.value
licenseInfo.copyrighted = license.Copyrighted?.value
licenseInfo.attributionRequired = license.AttributionRequired?.value
licenseInfo.usageTerms = license.UsageTerms?.value
licenseInfo.licenseShortName = license.LicenseShortName?.value
licenseInfo.credit = license.Credit?.value
licenseInfo.description = license.ImageDescription?.value
licenseInfo.informationLocation = new URL("https://en.wikipedia.org/wiki/" + pageInfo.title)
return licenseInfo
}
private UrlForImage(image: string): ProvidedImage {
if (!image.startsWith("File:")) {
image = "File:" + image
}
return {url: WikimediaImageProvider.PrepareUrl(image), key: undefined, provider: this}
return { url: WikimediaImageProvider.PrepareUrl(image), key: undefined, provider: this }
}
}