| 
									
										
										
										
											2025-04-06 00:18:25 +02:00
										 |  |  | import Script from "./Script" | 
					
						
							|  |  |  | import { Overpass } from "../src/Logic/Osm/Overpass" | 
					
						
							|  |  |  | import { Or } from "../src/Logic/Tags/Or" | 
					
						
							|  |  |  | import { RegexTag } from "../src/Logic/Tags/RegexTag" | 
					
						
							|  |  |  | import { Utils } from "../src/Utils" | 
					
						
							|  |  |  | import Constants from "../src/Models/Constants" | 
					
						
							|  |  |  | import { ImmutableStore } from "../src/Logic/UIEventSource" | 
					
						
							|  |  |  | import { BBox } from "../src/Logic/BBox" | 
					
						
							|  |  |  | import ChangeTagAction from "../src/Logic/Osm/Actions/ChangeTagAction" | 
					
						
							|  |  |  | import { Tag } from "../src/Logic/Tags/Tag" | 
					
						
							|  |  |  | import { Panoramax } from "panoramax-js/dist" | 
					
						
							|  |  |  | import { Changes } from "../src/Logic/Osm/Changes" | 
					
						
							|  |  |  | import OsmChangeAction from "../src/Logic/Osm/Actions/OsmChangeAction" | 
					
						
							|  |  |  | import { writeFileSync } from "fs" | 
					
						
							|  |  |  | import { Feature } from "geojson" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RepairPanoramax extends Script { | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |     private static readonly europe: Feature = { | 
					
						
							|  |  |  |         type: "Feature", | 
					
						
							|  |  |  |         properties: {}, | 
					
						
							|  |  |  |         geometry: { | 
					
						
							|  |  |  |             coordinates: [ | 
					
						
							| 
									
										
										
										
											2025-04-06 00:18:25 +02:00
										 |  |  |                 [ | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |                     [-20.091159690050006, 25.773375277790038], | 
					
						
							|  |  |  |                     [46.12276429398841, 25.773375277790038], | 
					
						
							|  |  |  |                     [46.12276429398841, 65.41389761819318], | 
					
						
							|  |  |  |                     [-20.091159690050006, 65.41389761819318], | 
					
						
							|  |  |  |                     [-20.091159690050006, 25.773375277790038], | 
					
						
							|  |  |  |                 ], | 
					
						
							| 
									
										
										
										
											2025-04-06 00:18:25 +02:00
										 |  |  |             ], | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |             type: "Polygon", | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2025-04-06 00:18:25 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor() { | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |         super( | 
					
						
							|  |  |  |             "See https://source.mapcomplete.org/MapComplete/MapComplete/issues/2372\n" + | 
					
						
							|  |  |  |                 "We accidentally added the full image URL instead of the hash due to a bug. This scripts rewrites all" | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2025-04-06 00:18:25 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async main(args: string[]): Promise<void> { | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |         const keys = ["panoramax", ...Utils.TimesT(10, (i) => "panoramax:" + i)] | 
					
						
							| 
									
										
										
										
											2025-04-06 00:18:25 +02:00
										 |  |  |         const overpass = new Overpass( | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |             new Or(keys.map((k) => new RegexTag(k, /^https:\/\/panoramax.mapcomplete.org\/.*/))), | 
					
						
							| 
									
										
										
										
											2025-04-06 00:18:25 +02:00
										 |  |  |             [], | 
					
						
							|  |  |  |             Constants.defaultOverpassUrls[0], | 
					
						
							|  |  |  |             new ImmutableStore(500) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const [wrongFeatures] = await overpass.queryGeoJson(BBox.global) | 
					
						
							|  |  |  |         const allChanges: OsmChangeAction[] = [] | 
					
						
							|  |  |  |         for (const f of wrongFeatures.features) { | 
					
						
							|  |  |  |             for (const key of keys) { | 
					
						
							|  |  |  |                 const v = f.properties[key] | 
					
						
							|  |  |  |                 if (!v) { | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const pre = "https://panoramax.mapcomplete.org/api/pictures/" | 
					
						
							|  |  |  |                 const pre1 = "https://panoramax.mapcomplete.org/permanent/" | 
					
						
							|  |  |  |                 let correct: string | 
					
						
							|  |  |  |                 if (v.startsWith(pre)) { | 
					
						
							|  |  |  |                     correct = v.substring(pre.length) | 
					
						
							|  |  |  |                     correct = correct.substring(0, correct.indexOf("/")) | 
					
						
							|  |  |  |                 } else if (v.startsWith(pre1)) { | 
					
						
							|  |  |  |                     const stripped = v.substring(pre1.length) | 
					
						
							|  |  |  |                     correct = stripped.replace(/\//g, "").replace(/\.jpg$/, "") | 
					
						
							|  |  |  |                     correct = correct.substring(0, 8) + "-" + correct.substring(8) | 
					
						
							|  |  |  |                 } else if (Panoramax.isId(v)) { | 
					
						
							|  |  |  |                     // This is a valid ID that came on an object also having an _invalid_ id
 | 
					
						
							|  |  |  |                     // We can safely skip this
 | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     throw "Unknown url " + v | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 console.log(key, correct, "    old: ", v) | 
					
						
							|  |  |  |                 if (!Panoramax.isId(correct)) { | 
					
						
							|  |  |  |                     throw "Constructed an invalid id:" + correct | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const change = new ChangeTagAction( | 
					
						
							|  |  |  |                     f.properties.id, | 
					
						
							|  |  |  |                     new Tag(key, correct), | 
					
						
							|  |  |  |                     f.properties, | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         theme: "fix", | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |                         changeType: "fix", | 
					
						
							| 
									
										
										
										
											2025-04-06 00:18:25 +02:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |                 allChanges.push(change) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const xml = await Changes.createChangesetXMLForJosm(allChanges) | 
					
						
							|  |  |  |         console.log(xml) | 
					
						
							|  |  |  |         const path = "repairPanoramax.osc" | 
					
						
							|  |  |  |         writeFileSync(path, xml) | 
					
						
							|  |  |  |         console.log("Written XML to", path) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | new RepairPanoramax().run() |