-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinat2commons.js
337 lines (313 loc) · 13.8 KB
/
inat2commons.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
// 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).
// The code for this script is hosted on GitHub (https://github.com/kaldari/iNaturalist2Commons)
// and any issues may be reported there. It is dual licensed under the MIT License
// and the Creative Commons Attribution-ShareAlike License.
//<nowiki>
// 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() {
// Construct object (to prevent namespace conflicts)
inat2commons = {
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 ) );
},
capitalizeFirstLetter: function( string ) {
return string.charAt(0).toUpperCase() + string.slice(1);
},
launchPreview: function( uploadParams ) {
var imageExtension = uploadParams.thumbUrl.split('.').pop();
uploadParams.mediumUrl = uploadParams.thumbUrl.replace('/square', '/medium');
$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() {
uploadParams.originalUrl = uploadParams.thumbUrl.replace('/square', '/original');
$previewInterface.dialog( 'close' );
inat2commons.launchUpload( uploadParams );
}
}
]
});
$previewInterface.dialog( 'open' );
},
launchUpload: function( uploadParams ) {
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 = inat2commons.capitalizeFirstLetter( uploadParams.commonName ) + " (''" + uploadParams.taxon + "'')";
} else {
description = "''" + uploadParams.taxon + "''";
}
} else {
description = uploadParams.taxon;
}
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 '';
}
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 placeList = uploadParams.places.toString();
var iNatApi = 'https://api.inaturalist.org/v1/places/' + placeList;
var params = { 'admin_level': '0' };
$.getJSON( iNatApi, params )
.always( function( data ) {
if ( data.results[0] !== undefined && data.results[0].name !== undefined ) {
var country = data.results[0].name;
var theCountries = ["Bahamas", "Cayman Islands", "Central African Republic", "Channel Islands", "Comoros", "Czech Republic", "Dominican Republic", "Falkland Islands", "Gambia", "Isle of Man", "Ivory Coast", "Leeward Islands", "Maldives", "Marshall Islands", "Netherlands", "Netherlands Antilles", "Philippines", "Solomon Islands", "Turks and Caicos Islands", "United Arab Emirates", "United Kingdom", "United States", "Virgin Islands"];
if ( theCountries.includes( country ) ) {
country = "the " + country;
}
description += " in " + country;
}
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}}
[[Category:${uploadParams.category}]]
[[Category:Uploaded with iNaturalist2Commons]]
`;
var href = `${uploadPage}?wpUploadDescription=${encodeURIComponent(summary)}&wpLicense=${license}&wpDestFile=${targetName}&wpSourceType=url&wpUploadFileURL=${original}`;
window.open( href, "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,
taxon: observation.taxon.name,
taxonRank: observation.taxon.rank,
places: observation.place_ids,
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() {
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>