User:Rudolphous/inat2commons.js

Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
// source https://commons.wikimedia.org/w/index.php?title=User:Kaldari/inat2commons.js
// This script adds a new "iNaturalist Import" button to taxon categories or gallery
// pages (whichever one is associated with the Wikidata item for the taxon).

//<nowiki>

console.log(mw.config.get( 'wgNamespaceNumber'));
console.log(mw.config.get( 'wgAction'));
console.log(mw.config.get( 'wgWikibaseItemId'));
debugger;

// Make sure we are on a Category page and in view mode.
if ( ( mw.config.get( 'wgNamespaceNumber' ) === 0 || mw.config.get( 'wgNamespaceNumber' ) === 14 ) && mw.config.get( 'wgAction' ) === 'view' ) {

	// Move this out when converting to gadget
	mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=User:Kaldari/inat2commons.css&action=raw&ctype=text/css', 'text/css' );

	// Initialize global iNaturalist ID variable
	iNatId = null;

	// Script depends on jQuery UI dialog and jQuery UI selectable modules
	mw.loader.using( ['mediawiki.user', 'mediawiki.api', 'mediawiki.ForeignApi', 'jquery.ui'], function() {

       /*
       new mw.Api() ).postWithToken( 'options', {
			action: "options",
			change: "compact-language-links=0"
		} ).done( function(param) {
		})*/

    	//console.log(mw.api.postWithToken())
	    //console.log(mw.user.tokens.get( 'csrfToken' ))

		// Construct object (to prevent namespace conflicts)
		inat2commons = {
			cleanCountry: function(country) {
				if (country === 'B&H') return 'Bosnia and Herzegovina';
				if (country === 'Czechia') return 'Czech Republic';
				if (country === 'D.R.') return 'Dominican Republic';
				if (country === 'DR Congo') return 'Democratic Republic of the Congo';
				if (country === 'Macedonia') return 'Republic of Macedonia';
				if (country === 'PRC') return 'China';
				if (country === 'ROC') return 'Taiwan';
				if (country === 'The Bahamas') return 'Bahamas';
				if (country === 'The Netherlands') return 'Netherlands';
				if (country === 'TW') return 'Taiwan';
				if (country === 'USA') return 'United States';
				if (country === 'United States of America') return 'United States';
				return country;
			},
			
			getPrefixedCountry: function(country) {
				if (!country) {
					return country;
				}
				const withPrefixes = ["United States", "Netherlands", "United Kingdom", "United Arab Emirates", "United Emirates", "Philippines", 
				   "Central African Republic", "Falkland Islands", "Isle of Man", "Central African Republic", "Bahamas", "Republic of Macedonia"];
				return withPrefixes.includes(country) ? ` of the ${country}` : ` of ${country}`;
			},

			// map gps to address and take optional country
			getCountry: function(lat, lon) {
				let country = null;
				const openSteetMapApi = `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lon}&accept-language=en&format=json`;
				$.ajax({ 
					url: openSteetMapApi, 
					async: false,
					success: function(resp) {
					   country = resp && resp.address && resp.address.country;	
					},
				});
				return inat2commons.cleanCountry(country);
			},
			
			displayProgress: function( message ) {
				$( '#import-dialog div' ).remove(); // remove everything else from the dialog box
				$( '#import-dialog' ).append ( $( '<div class="import-progress" style="text-align:center;margin:1.8em 0;"></div>' ).html( message+'<br/><br/><img src="//upload.wikimedia.org/wikipedia/commons/4/42/Loading.gif" />' ) );
			},

			displayMessage: function( message ) {
				$( '#import-dialog div' ).remove(); // remove everything else from the dialog box
				$( '#import-dialog' ).append ( $( '<div class="import-message"></div>' ).html( message ) );
			},

			displayError: function( error ) {
				$( '#import-dialog div' ).remove(); // remove everything else from the dialog box
				$( '#import-dialog' ).append ( $( '<div class="import-error" style="color:#990000;"></div>' ).html( 'Error: '+error ) );
			},

			launchPreview: function( uploadParams ) {
				console.log(uploadParams);
				var imageExtension = uploadParams.thumbUrl.split('.').pop();
				$previewInterface = $( '<div></div>', {
    			id: "preview-dialog",
    			style: "position: relative; text-align: center; min-height: 500px;",
					html: "<p><img src='" + uploadParams.mediumUrl + "' /><\p>"
				} )
				.dialog({
					width: 600,
					autoOpen: false,
					title: 'Preview',
					modal: false,
					position: { my: "top", at: "top+150", of: "body" },
					buttons: [
						{
							text: "Upload image",
							classes: "inaturalist-upload-button",
							click: function() {
								$previewInterface.dialog( 'close' );
								inat2commons.launchUpload( uploadParams );
							}
						}
					]
				});
				$previewInterface.dialog( 'open' );
			},
			
			getMonthName(date) {
				if (!date) return date;
				const monthNames = ["January", "February", "March", "April", "May", "June",
					"July", "August", "September", "October", "November", "December"
				];
				const dateObject = new Date(date);
				return monthNames[dateObject.getMonth()];
			},
			
			generateExtraCats: function(uploadParams) {
				const result = [];
				const regnum  = 'Fungi';
				const { geojson, date } = uploadParams;
				const lat = geojson && geojson.coordinates && geojson.coordinates[1];
				const lon = geojson && geojson.coordinates && geojson.coordinates[0];
				const country = lat && lon && inat2commons.getCountry(lat, lon);
				//add regnum + country
				const prefixedCountry = inat2commons.getPrefixedCountry(country);
				if (prefixedCountry) {
					result.push(`${regnum}${prefixedCountry}`);
				}
				//add taken on
				if (country && date) {
					result.push(`${country} photographs taken on ${date}`);
				}
				if (regnum === 'Fungi' && date) {
					result.push(`${regnum} in ${inat2commons.getMonthName(date)}`);
				}
				return result;
			},
			
			launchUpload: function( uploadParams ) {
				//inat2commons.'displayProgress( 'Loading upload form...' ); keep dialog open
				var href = '';
				var uploadPage = 'https://commons.wikimedia.org/wiki/Special:Upload';
				var license = '';
				var description = '';
				var author = '';
				if ( uploadParams.taxonRank === 'species' || uploadParams.taxonRank === 'subspecies' ) {
					if ( uploadParams.commonName !== undefined ) {
						description = uploadParams.commonName + " (''" + uploadParams.taxon + "'')";
					} else {
						description = "''" + uploadParams.taxon + "''";
					}
				} else {
					description = uploadParams.taxon;
				}
				var ext = uploadParams.thumbUrl.split( '?' )[0].split('.').slice( -1 );
				var targetName = `${uploadParams.taxon} ${uploadParams.photoId}.jpg`;
				var original = uploadParams.originalUrl;
				if ( uploadParams.userName ) {
					author = uploadParams.userName;
				} else {
					author = uploadParams.userLogin;
				}
				var location = ( uploadParams.geojson !== undefined ) ? `
{{Location|${uploadParams.geojson.coordinates[1]}|${uploadParams.geojson.coordinates[0]}}}` : '';
				var extraCats = inat2commons.generateExtraCats(uploadParams);
				var extraCategories = extraCats.map(category => `[[Category:${category}]]`).join('\n');
				var summary = `{{Information
|description={{en|${description}}}
|date=${uploadParams.date}
|source=https://www.inaturalist.org/photos/${uploadParams.photoId}
|author=[https://www.inaturalist.org/users/${uploadParams.userId} ${author}]
|permission=
|other versions=
}}
${location}
{{inaturalist|${uploadParams.observationId}}}
{{INaturalistreview}}
${extraCategories}
[[Category:${uploadParams.category}]]
[[Category:Uploaded with iNaturalist2Commons]]
`;
				switch ( uploadParams.photoLicense ) {
        			case 'cc-by':
            			license = 'cc-by-4.0';
            			break;
        			case 'cc-by-sa':
            			license = 'cc-by-sa-4.0';
            			break;
        			case 'cc0':
            			license = 'Cc-zero';
            			break;
        			default:
            			return '';
    			}
    			debugger;
				var uploadUrl = `${uploadPage}?wpUploadDescription=${encodeURIComponent(summary)}&wpLicense=${license}&wpDestFile=${targetName}&wpSourceType=url&wpUploadFileURL=${original}`;
				window.open(uploadUrl, "uploadWindow");
			},

			launchDialog: function() {
				var iNatApi = 'https://api.inaturalist.org/v1/observations';
				var uri = new mw.Uri();
				var maxImages = 104;
				var params = { 'photo_license': 'cc0,cc-by,cc-by-sa', 'quality_grade': 'research', 'taxon_id': iNatId };
				
				// Allow overriding with an observation ID
				// For example '?inatid=73898408'
				if ( typeof uri.query.inatid !== 'undefined' ) {
					params.id = uri.query.inatid;
				}

				// Allow overriding quality grade with a query string parameter
				// For example '?inatquality=casual' or '?inatquality=needs_id'
				if ( typeof uri.query.inatquality !== 'undefined' ) {
					params.quality_grade = uri.query.inatquality;
				}

				// Allow overriding number of images with a query string parameter
				if ( typeof uri.query.inatquantity !== 'undefined' ) {
					maxImages = parseInt( uri.query.inatquantity );
				}
				params.per_page = maxImages - 20; // Some observations have multiple images

				// Restore dialog to original state
				inat2commons.displayProgress( 'Loading images...');
				// Open the dialog box
				$importInterface.dialog( 'open' );
				// Retrieve images
				$.getJSON( iNatApi, params )
					.done( function( data ) {
						if ( data.results[0] === undefined ) {
							inat2commons.displayMessage( 'No free license images were found for this taxon.');
						} else {
							var headerAdded = false;
							var x = 0;
							// Go through each observation
							data.results.forEach( function( observation ) {
								// Go through each photo
								observation.photos.forEach( function( photoData ) {
									var licenseCode = photoData.license_code;
									// If the license is compatible, display the photo
									if ( ( licenseCode === 'cc-by' || licenseCode === 'cc-by-sa' || licenseCode === 'cc0' ) && x < maxImages ) {
										// Create dialog header once we know there is at least one free-license image
										if ( headerAdded === false ) {
											$( '#import-dialog div' ).remove();
											$( '#import-dialog' ).append( $( '<div id="import-images"></div>' ).html( 'Select an image to preview:<br/>' ).append ( $( '<ol></ol>' ) ) );
											headerAdded = true;
										}
										var uploadParams = {
											photoId: photoData.id,
											photoLicense: photoData.license_code,
											userId: observation.user.id,
											userName: observation.user.name,
											userLogin: observation.user.login,
											observationId: observation.id,
											date: observation.observed_on,
											placeGuess: observation.place_guess,
											taxon: observation.taxon.name,
											taxonRank: observation.taxon.rank,
											thumbUrl: photoData.url,
											category: mw.config.get( 'wgTitle' )
										};
										if ( !observation.geoprivacy ) {
											uploadParams.geojson = observation.geojson;
										}
										if ( observation.taxon.preferred_common_name !== undefined ) {
											uploadParams.commonName = observation.taxon.preferred_common_name;
										}
										$( '#import-dialog ol' ).append ( $( '<li></li>' )
											.html( '<img data-photo-id="' + photoData.id + '" src="' + photoData.url + '" height="75" width="75"/>' )
											.on( 'click', function() {
												uploadParams.mediumUrl =  uploadParams.thumbUrl.replace('/square', '/medium');
												uploadParams.originalUrl =  uploadParams.thumbUrl.replace('/square', '/original')
												inat2commons.launchPreview( uploadParams );
											} )
										);
										x++;
									}
								} );
							} );
							// After going through all the observations, if there are no free-license images, display error
							if ( headerAdded === false ) {
								inat2commons.displayMessage( 'No free license images were found for this taxon.');
							}
						}
					} )
					.fail( function() {
						inat2commons.displayError( 'Loading images failed. If you are using a privacy plug-in like Privacy Badger, you may need to adjust your settings.');
					} );
			},

			tryFallbackQueries: function( params, wikidataApi ) {
				// Try getting the data associated with the main namespace page of the same title
				params.sites = 'commonswiki';
				params.titles = mw.config.get( 'wgTitle' );
				delete params.ids;
				// Make API call to Wikidata
				wikidataApi.get( params ).done( function ( data2 ) {
					// Get the Wikidata item ID
					wikidataId = Object.keys( data2.entities )[0];
					// Wikidata returns "-1" for undefined
					if ( wikidataId !== "-1" && data2.entities[wikidataId].claims.P3151 !== undefined && data2.entities[wikidataId].claims.P3151[0].mainsnak.datavalue.value !== undefined ) {
						// Get the iNaturalist ID (P3151)
						iNatId = data2.entities[wikidataId].claims.P3151[0].mainsnak.datavalue.value;
						// Insert import button into page interface
						$( '#firstHeading' ).append( $button );
					} else {
						// Last resort: Try getting the data associated with the English Wikipedia article
						params.sites = 'enwiki';
						wikidataApi.get( params ).done( function ( data3 ) {
							wikidataId = Object.keys( data3.entities )[0];
							if ( wikidataId !== "-1" && data3.entities[wikidataId].claims.P3151 !== undefined && data3.entities[wikidataId].claims.P3151[0].mainsnak.datavalue.value !== undefined ) {
								// Get the iNaturalist ID (P3151)
								iNatId = data3.entities[wikidataId].claims.P3151[0].mainsnak.datavalue.value;
								// Insert import button into page interface
								$( '#firstHeading' ).append( $button );
							}
						});
					}
				});
			},

			initialize: function() {
				// Define importing interface
				$importInterface = $('<div id="import-dialog" style="position:relative;"></div>')
					.dialog({
						width: 724,
						autoOpen: false,
						title: 'Import images from iNaturalist',
						modal: true,
						position: { my: "top", at: "top+100", of: "body" },
					});
				// Define the import button
				$button = $( '<button>' )
					.attr( 'style', 'margin: 0 0.5em 0.5em 0.5em; text-decoration: none; font-size: 15px;' )
					.append(
						$( '<span>' )
							.attr( 'id', 'inat2commons-buttontextwrapper' )
							.append( $( '<span>' )
								.attr( 'id', 'inat2commons-buttontext' )
								.text( 'iNaturalist import' ) )
					)
					.on( 'click', function () {
						inat2commons.launchDialog();
						return false;
					} )
					.button();

				// Check user rights and get the iNaturalist ID
				$( document ).ready( function() {
					var wikidataId = mw.config.get( 'wgWikibaseItemId' );
					var wikidataApi = new mw.ForeignApi('//www.wikidata.org/w/api.php');
					var params = { 'action': 'wbgetentities', 'props': 'claims' };

					mw.user.getRights().then( function ( rights ) {
						// Make sure the user has the 'upload_by_url' right
						if ( rights.indexOf( 'upload_by_url' ) > -1 ) {
							// Try getting the iNaturalist ID from the Wikidata infobox
							var wdinfobox = document.getElementById( 'wdinfobox' );
							if ( wdinfobox ) {
								var matches = wdinfobox.innerHTML.match(/https:\/\/www\.inaturalist\.org\/taxa\/(\d+)/);
								if ( matches ) {
									iNatId = matches[1];
									// Insert import button into page interface
									$( '#firstHeading' ).append( $button );
								}
							}
							if ( !iNatId ) {
								// If the Category page has an associated Wikidata ID, try that first
								if ( wikidataId ) {
									params.ids = wikidataId;
									// Make API call to Wikidata
									wikidataApi.get( params ).done( function ( data ) {
										if ( data.entities[wikidataId].claims.P3151 !== undefined && data.entities[wikidataId].claims.P3151[0].mainsnak.datavalue.value !== undefined ) {
											// Get the iNaturalist ID (P3151)
											iNatId = data.entities[wikidataId].claims.P3151[0].mainsnak.datavalue.value;
											// Insert import button into page interface
											$( '#firstHeading' ).append( $button );
										} else {
											inat2commons.tryFallbackQueries( params, wikidataApi );
										}
									});
								} else {
									inat2commons.tryFallbackQueries( params, wikidataApi );
								}
							}
						}
					} );
				});

			} // close initialize function

		} // close inat2commons object
		inat2commons.initialize();
	}) // close mw.loader
} // close if
//</nowiki>