MediaWiki:Gadget-UploadFromURL/Runtime.js

From Nookipedia, the Animal Crossing wiki

Note: After saving, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Go to Menu → Settings (Opera → Preferences on a Mac) and then to Privacy & security → Clear browsing data → Cached images and files.
/**
 * Turns Special:UploadFromURL into an upload form that lets users upload from a public image URL.
 * Also automatically converts webp images to png on-upload.
 * Created by SuperHamster on Nookipedia (https://nookipedia.com/wiki/User:SuperHamster)
 * Licensed under CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0/)
 **/

(function() {
  "use strict";

  // Set title of page as it appears in the browser tab:
  const PAGETITLE = "Upload from URL - Animal Crossing Wiki - Nookipedia";

  // List of warnings that always result in upload failure, even if ignorewarnings is checked:
  const FATALWARNINGS = ["fileexists-no-change", "verification-error", "abusefilter-disallowed"];

  // Default file description that is loaded in the form:
  const DEFAULTDESCRIPTION = `== Summary ==
{{File Info
|description = Describe the file (THIS IS NOT OPTIONAL)
|source = Where you found the file (THIS IS NOT OPTIONAL)
}}

== Licensing ==
{{Fairuse}}`;

  document.title = PAGETITLE;
  document.getElementById('firstHeading').innerHTML = 'Upload from URL';
  document.getElementById('bodyContent').innerHTML = '';
  document.getElementById('bodyContent').innerHTML = `<p>Use this form to upload a file from a URL. WebP images are automatically converted to PNG.</p>
<p><b>Note:</b> Many websites block cross-origin requests, which will result in a NetworkError when uploading. There are browser extensions available to enable CORS, but if you use one, be sure to turn it off after uploading.</p>
<fieldset>
<legend>Files and info</legend>
<div style="display:flex; line-height:45px;">
<label for="urlUploadURL">Source URL:&nbsp;</label>
<input type="text" id="urlUploadURL" name="urlUploadURL" style="flex:1;">
</div>
<p style="margin: 2px 0px 20px 20px;">
Maximum file size: 10 MB<br>
Permitted file types: png, gif, jpg, jpeg, webp, svg, flac, mkv, mov, mp3, mp4, oga, ogg, ogv, wav, webm
</p>
<div style="display:flex; line-height:45px;">
<label for="urlUploadFilename">Destination filename:&nbsp;</label>
<input type="text" id="urlUploadFilename" name="urlUploadFilename" style="flex:1;">
</div>
<p style="margin: 2px 0px 20px 20px;">
Include the extension (.png, .jpg, etc.)
</p>
<br>
<label for="urlUploadInfo">File description</legend>
<br>
<textarea id="urlUploadInfo" cols="80" rows="12">` + DEFAULTDESCRIPTION + `</textarea>
<br><br>
<input type="checkbox" id="urlUploadIgnoreWarnings"><label for="urlUploadIgnoreWarnings">Ignore warnings (check to override existing files)</label><br><br>
<button id="urlUploadButton" type="button">Upload file</button>
</fieldset>
<br>
<fieldset>
<legend>Upload status</legend>
<span id="urlUploadStatus">Waiting for user to start upload.</span>
</fieldset>
`;
  document.getElementById('urlUploadURL').addEventListener('change', function() {
    var filenameInput = document.getElementById('urlUploadFilename');
    var parts = document.getElementById('urlUploadURL').value.split('/');
    filenameInput.value = parts[parts.length - 1];
  });

  function upload(file) {
    var uploadParams = {};
    if (document.getElementById('urlUploadIgnoreWarnings').checked) {
      uploadParams = {
        filename: document.getElementById('urlUploadFilename').value,
        text: document.getElementById('urlUploadInfo').value,
        comment: 'Uploaded via upload-from-URL gadget',
        ignorewarnings: "yes",
        format: "json"
      };
    } else {
      uploadParams = {
        filename: document.getElementById('urlUploadFilename').value,
        text: document.getElementById('urlUploadInfo').value,
        comment: 'Uploaded via upload-from-URL gadget',
        format: "json"
      };
    }

    const api = new mw.Api();
    api.upload(file, uploadParams).always(response => {
      var status = "";
      if (typeof response === 'object') {
        if (response.hasOwnProperty('upload') && upload.result == 'Success') {
          status = 'Upload succeeded!';
        } else {
          status = 'Upload <span style="color: red;">failed</span> due to unknown error';
        }
      } else if (typeof response === 'string') {
        if (FATALWARNINGS.includes(response)) {
          status = 'Upload <span style="color: red;">failed</span> with error "' + response + '"';
        } else {
          if (document.getElementById('urlUploadIgnoreWarnings').checked) {
            status = 'Upload succeeded with warning "' + response + '"';
          } else {
            status = 'Upload <span style="color: red;">failed</span> with error "' + response + '"';
          }
        }
      } else {
        status = 'Upload <span style="color: red;">failed</span> due to unknown error';
      }
      document.getElementById('urlUploadStatus').innerHTML = status;
      document.getElementById('urlUploadButton').disabled = false;
    });
  }

  document.getElementById('urlUploadButton').addEventListener("click", function() {
    document.getElementById('urlUploadButton').disabled = true;
    document.getElementById('urlUploadStatus').innerHTML = 'Uploading...';

    var fileURL = document.getElementById('urlUploadURL').value;

    fetch(fileURL)
      .then(res => res.blob()) // Gets the response and returns it as a blob
      .then(file => {
        const mime = file.type;
        if (mime === 'image/webp') { // If webp, convert to PNG
          let image = new Image();
          image.src = URL.createObjectURL(file); // Create image from blob
          image.onload = function() { // Create canvas element with image
            let canvas = document.createElement('canvas');
            canvas.width = image.width;
            canvas.height = image.height;
            let ctx = canvas.getContext('2d');
            ctx.drawImage(image, 0, 0);
            function getCanvasBlob(canvas) { // Get image blob from canvas
              return new Promise(function(resolve, reject) {
                canvas.toBlob(function(blob) {
                  resolve(blob);
                })
              })
            }
            var canvasBlob = getCanvasBlob(canvas);
            canvasBlob.then(function(blob) {
              file = blob;
              upload(file);
            }, function(err) {
              console.log(err);
            });
          }
        } else {
          upload(file);
        }
      }).catch((error) => {
        document.getElementById('urlUploadStatus').innerHTML = 'Upload <span style="color: red;">failed</span> due to error: ' + error;
        document.getElementById('urlUploadButton').disabled = false;
      });
  });
})();