forked from MapComplete/MapComplete
		
	Graciously handle multiple entries in wikidata for fetching images and showing articles, verious bug fixes
This commit is contained in:
		
							parent
							
								
									8d52ef1106
								
							
						
					
					
						commit
						a996ba2a7c
					
				
					 14 changed files with 231 additions and 90 deletions
				
			
		|  | @ -1,17 +1,20 @@ | |||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import BaseUIElement from "../../UI/BaseUIElement"; | ||||
| import {LicenseInfo} from "./LicenseInfo"; | ||||
| import {Utils} from "../../Utils"; | ||||
| 
 | ||||
| export interface ProvidedImage { | ||||
|     url: string, key: string, provider: ImageProvider | ||||
|     url: string, | ||||
|     key: string, | ||||
|     provider: ImageProvider | ||||
| } | ||||
| 
 | ||||
| export default abstract class ImageProvider { | ||||
|      | ||||
|     public abstract readonly defaultKeyPrefixes : string[] = ["mapillary", "image"] | ||||
|      | ||||
| 
 | ||||
|     public abstract readonly defaultKeyPrefixes: string[] = ["mapillary", "image"] | ||||
| 
 | ||||
|     private _cache = new Map<string, UIEventSource<LicenseInfo>>() | ||||
|      | ||||
| 
 | ||||
|     GetAttributionFor(url: string): UIEventSource<LicenseInfo> { | ||||
|         const cached = this._cache.get(url); | ||||
|         if (cached !== undefined) { | ||||
|  | @ -31,43 +34,49 @@ export default abstract class ImageProvider { | |||
|      */ | ||||
|     public GetRelevantUrls(allTags: UIEventSource<any>, options?: { | ||||
|         prefixes?: string[] | ||||
|     }):UIEventSource<ProvidedImage[]> { | ||||
|     }): UIEventSource<ProvidedImage[]> { | ||||
|         const prefixes = options?.prefixes ?? this.defaultKeyPrefixes | ||||
|         if(prefixes === undefined){ | ||||
|             throw "The image provider"+this.constructor.name+" doesn't define `defaultKeyPrefixes`" | ||||
|         if (prefixes === undefined) { | ||||
|             throw "The image provider" + this.constructor.name + " doesn't define `defaultKeyPrefixes`" | ||||
|         } | ||||
|         const relevantUrls = new UIEventSource<{ url: string; key: string; provider: ImageProvider }[]>([]) | ||||
|         const seenValues = new Set<string>() | ||||
|         const self = this | ||||
|         const self =this | ||||
|         allTags.addCallbackAndRunD(tags => { | ||||
|             for (const key in tags) { | ||||
|                 if(!prefixes.some(prefix => key.startsWith(prefix))){ | ||||
|                 if (!prefixes.some(prefix => key.startsWith(prefix))) { | ||||
|                     continue | ||||
|                 } | ||||
|                 const value = tags[key] | ||||
|                 if(seenValues.has(value)){ | ||||
|                     continue | ||||
|                 } | ||||
|                 seenValues.add(value) | ||||
|                 this.ExtractUrls(key, value).then(promises => { | ||||
|                     for (const promise of promises ?? []) { | ||||
|                         if(promise === undefined){ | ||||
|                             continue | ||||
|                         } | ||||
|                         promise.then(providedImage => { | ||||
|                             if(providedImage === undefined){ | ||||
|                                 return | ||||
|                             } | ||||
|                             relevantUrls.data.push(providedImage) | ||||
|                             relevantUrls.ping() | ||||
|                         }) | ||||
|                 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 => { | ||||
|                         console.log("Got ", promises.length, "promises for", value,"by",self.constructor.name) | ||||
|                         for (const promise of promises ?? []) { | ||||
|                             if (promise === undefined) { | ||||
|                                 continue | ||||
|                             } | ||||
|                             promise.then(providedImage => { | ||||
|                                 if (providedImage === undefined) { | ||||
|                                     return | ||||
|                                 } | ||||
|                                 relevantUrls.data.push(providedImage) | ||||
|                                 relevantUrls.ping() | ||||
|                             }) | ||||
|                         } | ||||
|                     }) | ||||
|                 } | ||||
| 
 | ||||
| 
 | ||||
|             } | ||||
|         }) | ||||
|         return relevantUrls | ||||
|     } | ||||
| 
 | ||||
|     public abstract ExtractUrls(key: string, value: string) : Promise<Promise<ProvidedImage>[]>; | ||||
|      | ||||
|     public abstract ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]>; | ||||
| 
 | ||||
| } | ||||
|  | @ -1,4 +1,5 @@ | |||
| export class LicenseInfo { | ||||
|     title: string = "" | ||||
|     artist: string = ""; | ||||
|     license: string = ""; | ||||
|     licenseShortName: string = ""; | ||||
|  |  | |||
|  | @ -65,12 +65,26 @@ export class WikimediaImageProvider extends ImageProvider { | |||
|             "&format=json&origin=*"; | ||||
|         const data = await Utils.downloadJson(url) | ||||
|         const licenseInfo = new LicenseInfo(); | ||||
|         const license = (data.query.pages[-1].imageinfo ?? [])[0]?.extmetadata; | ||||
|         const pageInfo = data.query.pages[-1] | ||||
|         if(pageInfo === undefined){ | ||||
|             return undefined; | ||||
|         } | ||||
|          | ||||
|         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; | ||||
|         } | ||||
| 
 | ||||
|         let title = pageInfo.title | ||||
|         if(title.startsWith("File:")){ | ||||
|             title=  title.substr("File:".length) | ||||
|         } | ||||
|         if(title.endsWith(".jpg") || title.endsWith(".png")){ | ||||
|             title = title.substring(0, title.length - 4) | ||||
|         } | ||||
|          | ||||
|         licenseInfo.title = title | ||||
|         licenseInfo.artist = license.Artist?.value; | ||||
|         licenseInfo.license = license.License?.value; | ||||
|         licenseInfo.copyrighted = license.Copyrighted?.value; | ||||
|  |  | |||
|  | @ -47,7 +47,7 @@ export default class Wikidata { | |||
|             const claimsList: any[] = entity.claims[claimId] | ||||
|             const values = new Set<string>() | ||||
|             for (const claim of claimsList) { | ||||
|                 const value = claim.mainsnak?.datavalueq?.value; | ||||
|                 const value = claim.mainsnak?.datavalue?.value; | ||||
|                 if(value !== undefined){ | ||||
|                     values.add(value) | ||||
|                 } | ||||
|  |  | |||
|  | @ -22,6 +22,10 @@ export default class Wikipedia { | |||
|         "mw-selflink", | ||||
|         "hatnote" // Often redirects
 | ||||
|     ] | ||||
|      | ||||
|     private static readonly idsToRemove = [ | ||||
|         "sjabloon_zie" | ||||
|     ] | ||||
| 
 | ||||
|     private static readonly _cache = new Map<string, UIEventSource<{ success: string } | { error: any }>>() | ||||
|      | ||||
|  | @ -59,6 +63,13 @@ export default class Wikipedia { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         for (const forbiddenId of Wikipedia.idsToRemove) { | ||||
|             const toRemove = content.querySelector("#"+forbiddenId) | ||||
|             toRemove?.parentElement?.removeChild(toRemove) | ||||
|         } | ||||
|          | ||||
|          | ||||
| 
 | ||||
|         const links = Array.from(content.getElementsByTagName("a")) | ||||
| 
 | ||||
|         // Rewrite relative links to absolute links + open them in a new tab
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue