<commit_before>var cdb = require('cartodb.js');
var Backbone = require('backbone');
var UploadConfig = require('new_common/upload_config');
var Utils = require('cdb.Utils');

/** 
 *  Model that let user upload files
 *  to our endpoints
 *
 */

module.exports = Backbone.Model.extend({

  url: '/api/v1/imports',

  fileAttribute: 'filename',

  defaults: {
    type: '',
    value: '',
    interval: 0,
    progress: 0,
    state: '',
    service_item_id: '',
    service_name: '',
    option: '',
    content_guessing: true,
    valid: false
  },

  initialize: function(val, opts) {
    this.user = opts.user;
    this._initBinds();
    // We need to validate entry attributes
    this._validate(this.attributes, { validate: true});
  },

  _initBinds: function() {
    this.bind('progress', function(progress) {
      this.set({
        progress: progress*100,
        state: 'uploading'
      });
    }, this);

    this.bind('error invalid', function(m, msg) {
      this.set({
        state: 'error',
        get_error_text: { title: 'Invalid import', what_about: msg || '' }
      }, { silent: true });
      // We need this, if not validate will run again and again and again... :(
      this.trigger('change');
    }, this);
  },

  validate: function(attrs) {
    if (!attrs) return;

    if (attrs.type === "file") {
      // Number of files
      if (attrs.value.length > 1) {
        return "Unfortunately only one file is allowed per upload"
      }
      // File size
      if (this.user && ((this.user.get('remaining_byte_quota') * UploadConfig.fileTimesBigger) < attrs.value[0].size)) {
        return "Unfortunately the size of the file is bigger than your remaining quota"
      }
      // File extension
      var name = attrs.value[0].name;
      var ext = name.substr(name.lastIndexOf('.') + 1);
      if (!_.contains(UploadConfig.fileExtensions, ext)) {
        return "Unfortunately this file extension is not allowed"
      }
    }

    if (attrs.type === "remote") {
      // Valid remote visualization id?
      if (!attrs.remote_visualization_id) {
        return "The remote visualization id was not specified";
      }
      // Remote size?
      if (this.user && attrs.size && ((this.user.get('remaining_byte_quota') * UploadConfig.fileTimesBigger) < attrs.size)) {
        return "Unfortunately the size of the remote dataset is bigger than your remaining quota";
      }
    }

    if (attrs.type === "url") {
      // Valid URL?
      if (!Utils.isURL(attrs.value)) {
        return "Unfortunately the URL provided is not valid"
      }
    }
  },

  upload: function() {
    if (this.get('type') === "file") {
      var self = this;
      this.xhr = this.save(
        {
          filename: this.get('value')
        },
        {
          success: function(m) {
            m.set('state', 'uploaded');
          },
          error: function(m, msg) {
            self.set({
              state: 'error',
              get_error_text: { title: 'There was an error', what_about: 'Unfortunately there was a connection error' }
            });
          },
          complete: function() {
            delete self.xhr;
          }
        }
      );
    }
  },

  stopUpload: function() {
    if (this.xhr) this.xhr.abort();
  }

});
<commit_msg>Shows custom 429 error<commit_after>var cdb = require('cartodb.js');
var Backbone = require('backbone');
var UploadConfig = require('new_common/upload_config');
var Utils = require('cdb.Utils');

/** 
 *  Model that let user upload files
 *  to our endpoints
 *
 */

module.exports = Backbone.Model.extend({

  url: '/api/v1/imports',

  fileAttribute: 'filename',

  defaults: {
    type: '',
    value: '',
    interval: 0,
    progress: 0,
    state: '',
    service_item_id: '',
    service_name: '',
    option: '',
    content_guessing: true,
    valid: false
  },

  initialize: function(val, opts) {
    this.user = opts.user;
    this._initBinds();
    // We need to validate entry attributes
    this._validate(this.attributes, { validate: true});
  },

  _initBinds: function() {
    this.bind('progress', function(progress) {
      this.set({
        progress: progress*100,
        state: 'uploading'
      });
    }, this);

    this.bind('error invalid', function(m, msg) {
      this.set({
        state: 'error',
        get_error_text: { title: 'Invalid import', what_about: msg || '' }
      }, { silent: true });
      // We need this, if not validate will run again and again and again... :(
      this.trigger('change');
    }, this);
  },

  validate: function(attrs) {
    if (!attrs) return;

    if (attrs.type === "file") {
      // Number of files
      if (attrs.value.length > 1) {
        return "Unfortunately only one file is allowed per upload"
      }
      // File size
      if (this.user && ((this.user.get('remaining_byte_quota') * UploadConfig.fileTimesBigger) < attrs.value[0].size)) {
        return "Unfortunately the size of the file is bigger than your remaining quota"
      }
      // File extension
      var name = attrs.value[0].name;
      var ext = name.substr(name.lastIndexOf('.') + 1);
      if (!_.contains(UploadConfig.fileExtensions, ext)) {
        return "Unfortunately this file extension is not allowed"
      }
    }

    if (attrs.type === "remote") {
      // Valid remote visualization id?
      if (!attrs.remote_visualization_id) {
        return "The remote visualization id was not specified";
      }
      // Remote size?
      if (this.user && attrs.size && ((this.user.get('remaining_byte_quota') * UploadConfig.fileTimesBigger) < attrs.size)) {
        return "Unfortunately the size of the remote dataset is bigger than your remaining quota";
      }
    }

    if (attrs.type === "url") {
      // Valid URL?
      if (!Utils.isURL(attrs.value)) {
        return "Unfortunately the URL provided is not valid"
      }
    }
  },

  upload: function() {
    if (this.get('type') === "file") {
      var self = this;
      this.xhr = this.save(
        {
          filename: this.get('value')
        },
        {
          success: function(m) {
            m.set('state', 'uploaded');
          },
          error: function(m, msg) {

            var message = 'Unfortunately there was a connection error';

            if (msg && msg.status === 429) {
              var response = JSON.parse(msg.responseText);
              message = response.errors.imports;
            }

            self.set({
              state: 'error',
              get_error_text: { title: 'There was an error', what_about: message }
            });

          },
          complete: function() {
            delete self.xhr;
          }
        }
      );
    }
  },

  stopUpload: function() {
    if (this.xhr) this.xhr.abort();
  }

});

{'fraction_non_alphanumeric': 0.14199261992619927, 'fraction_numerical': 0.003837638376383764, 'mean_word_length': 2.137037037037037, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3113082', 'n_tokens_mistral': 2068, 'n_tokens_neox': 2001, 'n_words': 531}