| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | import * as $ from "jquery" | 
					
						
							| 
									
										
										
										
											2021-06-18 01:25:13 +02:00
										 |  |  | import ImageAttributionSource from "./ImageAttributionSource"; | 
					
						
							|  |  |  | import BaseUIElement from "../../UI/BaseUIElement"; | 
					
						
							|  |  |  | import Svg from "../../Svg"; | 
					
						
							|  |  |  | import {UIEventSource} from "../UIEventSource"; | 
					
						
							|  |  |  | import Link from "../../UI/Base/Link"; | 
					
						
							| 
									
										
										
										
											2021-06-22 14:21:32 +02:00
										 |  |  | import {Utils} from "../../Utils"; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * This module provides endpoints for wikipedia/wikimedia and others | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-06-18 01:25:13 +02:00
										 |  |  | export class Wikimedia extends ImageAttributionSource { | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-26 03:24:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-18 01:25:13 +02:00
										 |  |  |     public static readonly singleton = new Wikimedia(); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-18 01:25:13 +02:00
										 |  |  |     private constructor() { | 
					
						
							|  |  |  |         super(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-18 01:25:13 +02:00
										 |  |  |     static ImageNameToUrl(filename: string, width: number = 500, height: number = 200): string { | 
					
						
							|  |  |  |         filename = encodeURIComponent(filename); | 
					
						
							|  |  |  |         return "https://commons.wikimedia.org/wiki/Special:FilePath/" + filename + "?width=" + width + "&height=" + height; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-26 03:24:58 +01:00
										 |  |  |     static GetCategoryFiles(categoryName: string, handleCategory: ((ImagesInCategory: ImagesInCategory) => void), | 
					
						
							|  |  |  |                             alreadyLoaded = 0, | 
					
						
							|  |  |  |                             continueParameter: { k: string, param: string } = undefined) { | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         if (categoryName === undefined || categoryName === null || categoryName === "") { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // @ts-ignore
 | 
					
						
							|  |  |  |         if (!categoryName.startsWith("Category:")) { | 
					
						
							|  |  |  |             categoryName = "Category:" + categoryName; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         let url = "https://commons.wikimedia.org/w/api.php?" + | 
					
						
							|  |  |  |             "action=query&list=categorymembers&format=json&" + | 
					
						
							|  |  |  |             "&origin=*" + | 
					
						
							|  |  |  |             "&cmtitle=" + encodeURIComponent(categoryName); | 
					
						
							|  |  |  |         if (continueParameter !== undefined) { | 
					
						
							|  |  |  |             url = url + "&" + continueParameter.k + "=" + continueParameter.param; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-26 03:24:58 +01:00
										 |  |  |         const self = this; | 
					
						
							|  |  |  |         console.log("Loading a wikimedia category: ", url) | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         $.getJSON(url, (response) => { | 
					
						
							|  |  |  |             let imageOverview = new ImagesInCategory(); | 
					
						
							|  |  |  |             let members = response.query?.categorymembers; | 
					
						
							|  |  |  |             if (members === undefined) { | 
					
						
							|  |  |  |                 members = []; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (const member of members) { | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |                 imageOverview.images.push(member.title); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-03-26 03:24:58 +01:00
										 |  |  |             console.log("Got images! ", imageOverview) | 
					
						
							|  |  |  |             if (response.continue === undefined) { | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |                 handleCategory(imageOverview); | 
					
						
							| 
									
										
										
										
											2021-03-26 03:24:58 +01:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (alreadyLoaded > 10) { | 
					
						
							|  |  |  |                 console.log(`Recursive wikimedia category load stopped for ${categoryName} - got already enough images now (${alreadyLoaded})`) | 
					
						
							|  |  |  |                 handleCategory(imageOverview) | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.GetCategoryFiles(categoryName, | 
					
						
							|  |  |  |                 (recursiveImages) => { | 
					
						
							|  |  |  |                     recursiveImages.images.push(...imageOverview.images); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |                     handleCategory(recursiveImages); | 
					
						
							|  |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2021-03-26 03:24:58 +01:00
										 |  |  |                 alreadyLoaded + 10, | 
					
						
							|  |  |  |                 {k: "cmcontinue", param: response.continue.cmcontinue}) | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static GetWikiData(id: number, handleWikidata: ((Wikidata) => void)) { | 
					
						
							|  |  |  |         const url = "https://www.wikidata.org/wiki/Special:EntityData/Q" + id + ".json"; | 
					
						
							|  |  |  |         $.getJSON(url, (response) => { | 
					
						
							|  |  |  |             const entity = response.entities["Q" + id]; | 
					
						
							|  |  |  |             const commons = entity.sitelinks.commonswiki; | 
					
						
							|  |  |  |             const wd = new Wikidata(); | 
					
						
							|  |  |  |             wd.commonsWiki = commons?.title; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // P18 is the claim 'depicted in this image'
 | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |             const image = entity.claims.P18?.[0]?.mainsnak?.datavalue?.value; | 
					
						
							|  |  |  |             if (image) { | 
					
						
							|  |  |  |                 wd.image = "File:" + image; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |             handleWikidata(wd); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-26 03:24:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-18 01:25:13 +02:00
										 |  |  |     private static ExtractFileName(url: string) { | 
					
						
							|  |  |  |         if (!url.startsWith("http")) { | 
					
						
							|  |  |  |             return url; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const path = new URL(url).pathname | 
					
						
							|  |  |  |         return path.substring(path.lastIndexOf("/") + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SourceIcon(backlink: string): BaseUIElement { | 
					
						
							|  |  |  |         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) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PrepareUrl(value: string): string { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (value.toLowerCase().startsWith("https://commons.wikimedia.org/wiki/")) { | 
					
						
							|  |  |  |             return value; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return Wikimedia.ImageNameToUrl(value, 500, 400) | 
					
						
							|  |  |  |             .replace(/'/g, '%27'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected DownloadAttribution(filename: string): UIEventSource<LicenseInfo> { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const source = new UIEventSource<LicenseInfo>(undefined); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         filename = Wikimedia.ExtractFileName(filename) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (filename === "") { | 
					
						
							|  |  |  |             return source; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const url = "https://en.wikipedia.org/w/" + | 
					
						
							|  |  |  |             "api.php?action=query&prop=imageinfo&iiprop=extmetadata&" + | 
					
						
							|  |  |  |             "titles=" + filename + | 
					
						
							|  |  |  |             "&format=json&origin=*"; | 
					
						
							| 
									
										
										
										
											2021-06-22 14:21:32 +02:00
										 |  |  |         Utils.downloadJson(url).then( | 
					
						
							|  |  |  |             data =>{ | 
					
						
							|  |  |  |                 const licenseInfo = new LicenseInfo(); | 
					
						
							|  |  |  |                 const license = (data.query.pages[-1].imageinfo ?? [])[0]?.extmetadata; | 
					
						
							|  |  |  |                 if(license === undefined){ | 
					
						
							|  |  |  |                     console.error("This file has no usable metedata or license attached... Please fix the license info file yourself!") | 
					
						
							|  |  |  |                     source.setData(null) | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 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; | 
					
						
							|  |  |  |                 source.setData(licenseInfo);       | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2021-06-18 01:25:13 +02:00
										 |  |  |         return source; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class Wikidata { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     commonsWiki: string; | 
					
						
							|  |  |  |     image: string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class ImagesInCategory { | 
					
						
							|  |  |  |     // Filenames of relevant images
 | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |     images: string[] = []; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class LicenseInfo { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     artist: string = ""; | 
					
						
							|  |  |  |     license: string = ""; | 
					
						
							|  |  |  |     licenseShortName: string = ""; | 
					
						
							|  |  |  |     usageTerms: string = ""; | 
					
						
							|  |  |  |     attributionRequired: boolean = false; | 
					
						
							|  |  |  |     copyrighted: boolean = false; | 
					
						
							|  |  |  |     credit: string = ""; | 
					
						
							|  |  |  |     description: string = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |