Bionus / imgbrd-grabber

Very customizable imageboard/booru downloader with powerful filenaming features.
https://www.bionus.org/imgbrd-grabber/
Apache License 2.0
2.42k stars 212 forks source link

need help non stop crashing when clicking on a image to view #2993

Open sinkiller21st opened 1 year ago

sinkiller21st commented 1 year ago

can anyone tell me why every time I update Grabber to its latest version, I always have to uninstall it, use version 7.2.1, and wait months to be able to use the newest version?

I tried everything and no one is helping it keeps crashing every time I click on an image to view.

I tried uninstalling it and reinstalling it I tried looking in the main fail and it said I was missing things I tried to download them but that doesn't even work is grabber dead am I the only one having this issue can any one help or guide me

sinkiller21st commented 1 year ago

main.log

the text if the link doesn't work

[21:12:40.961][Warning] Javascript 'model.js' file not found for 'Sankaku' in `C:/Program Files/Grabber/sites/Sankaku/model.js`
[21:12:41.166][Info] Temp directory purged of 0/0 files (0 failed)
[21:12:41.176][Warning] [Qt][default] QNetworkRequest::setHeader: QVariant of type QByteArray cannot be used with header User-Agent
[21:12:42.318][Warning] [Qt][default] content-type missing in HTTP POST, defaulting to application/x-www-form-urlencoded. Use QNetworkRequest::setHeader() to fix this problem.
[21:12:42.557][Info] Software version: 7.11.1.
[21:12:42.557][Info] Software CPU architecture: x64.
[21:12:42.558][Info] Computer CPU architecture: x86_64.
[21:12:42.558][Info] Qt CPU architecture: x86_64.
[21:12:42.559][Info] Computer platform: Windows 10 Version 2009.
[21:12:42.559][Info] Path: `C:/Program Files/Grabber`
[21:12:42.560][Info] Loading preferences from `C:/Users/sinki/AppData/Local/Bionus/Grabber/settings.ini`
[21:12:42.561][Info] Temporary path: `C:/Users/sinki/AppData/Local/Temp\Grabber`
[21:12:42.562][Info] Sources found: 32
[21:12:42.562][Info] SSL libraries: OpenSSL 1.1.1u  30 May 2023
[21:12:42.574][Info] Setting language to 'English' (`C:\Program Files\Grabber\languages\English.qm`)...
[21:12:42.581][Info] 32 sources found: anime-pictures.net (Anime pictures), api.twitter.com (Twitter), behoimi.org (Danbooru), booru.allthefallen.moe (Danbooru (2.0)), booru.io (Booru.io), danbooru.donmai.us (Danbooru (2.0)), derpibooru.org (Philomena), e-hentai.org (E-Hentai), e621.net (E621), exhentai.org (E-Hentai), gelbooru.com (Gelbooru (0.2)), hijiribe.donmai.us (Danbooru (2.0)), kemono.party (Kemono), konachan.com (Moebooru), nhentai.net (NHentai), nijie.info (Nijie), pawoo.net (Mastodon), rule34.paheal.net (Shimmie), rule34.us (Modified Gelbooru (0.1)), rule34.xxx (Gelbooru (0.2)), safebooru.org (Gelbooru (0.2)), sonohara.donmai.us (Danbooru (2.0)), tbib.org (Gelbooru (0.2)), tentaclerape.net (Shimmie), wallhaven.cc (WallHaven), www.artstation.com (ArtStation), www.deviantart.com (DeviantArt), www.newgrounds.com/art (Newgrounds Art), www.pixiv.net (Pixiv), www.reddit.com (Reddit), www.zerochan.net (Zerochan), yande.re (Moebooru)
[21:12:42.803][Info] Loading 0 downloads
[21:12:42.831][Info] Updating checkboxes.
[21:12:43.062][Info] [exhentai.org] Logging in...
[21:12:43.063][Info] [rule34.paheal.net] Logging in...
[21:12:43.806][Info] [rule34.paheal.net] Login finished: failure.
[21:12:44.218][Info] [exhentai.org] Login finished: failure.
[21:12:44.260][Info] Updating checkboxes.
[21:12:44.266][Info] Saving sources...
[21:12:44.267][Info] Updating checkboxes.
[21:12:44.282][Info] Loading results...
[21:12:44.286][Info] [booru.allthefallen.moe][Html] Loading page `https://booru.allthefallen.moe/posts?limit=20&page=1&tags=pikmin`
[21:12:44.286][Info] [booru.allthefallen.moe][Xml] Loading page `https://booru.allthefallen.moe/posts.xml?limit=20&page=1&tags=pikmin`
[21:12:44.288][Info] [derpibooru.org][Html] Loading page `https://derpibooru.org/search?per_page=20&page=1&q=pikmin`
[21:12:44.288][Info] [derpibooru.org][Json] Loading page `https://derpibooru.org/api/v1/json/search/images?per_page=20&page=1&q=pikmin`
[21:12:44.291][Info] [e621.net][Html] Loading page `https://e621.net/posts?limit=20&page=1&tags=pikmin`
[21:12:44.292][Info] [e621.net][Json] Loading page `https://e621.net/posts.json?limit=20&page=1&tags=pikmin`
[21:12:44.293][Info] [exhentai.org][Html] Loading page `https://exhentai.org/?&f_cats=0&f_search=pikmin`
[21:12:44.295][Info] [rule34.paheal.net][Html] Loading page `http://rule34.paheal.net/post/list/pikmin/1`
[21:12:44.296][Info] [rule34.xxx][Html] Loading page `https://rule34.xxx/index.php?page=post&s=list&tags=pikmin&pid=0`
[21:12:44.297][Info] [rule34.xxx][Xml] Loading page `https://api.rule34.xxx//index.php?page=dapi&s=post&q=index&limit=20&pid=0&tags=pikmin`
[21:12:44.298][Info] [tbib.org][Html] Loading page `https://tbib.org/index.php?page=post&s=list&tags=pikmin&pid=0`
[21:12:44.298][Info] [tbib.org][Xml] Loading page `https://tbib.org/index.php?page=dapi&s=post&q=index&limit=20&pid=0&tags=pikmin`
[21:12:44.300][Warning] [Qt][default] QNetworkRequest::setHeader: QVariant of type QByteArray cannot be used with header User-Agent
[21:12:44.300][Info] Monitoring starting
[21:12:44.322][Warning] [Qt][default] content-type missing in HTTP POST, defaulting to application/x-www-form-urlencoded. Use QNetworkRequest::setHeader() to fix this problem.
[21:12:44.440][Info] [rule34.paheal.net][Html] Receiving page `http://rule34.paheal.net/post/list/pikmin/1`
[21:12:44.492][Info] [rule34.paheal.net][Html] Parsed page `http://rule34.paheal.net/post/list/pikmin/1`: 70 images (70), 0 tags (62), -1 total (560), 8 pages (8)
[21:12:44.496][Warning] [Qt][default] QNetworkRequest::setHeader: QVariant of type QByteArray cannot be used with header User-Agent
[21:12:44.532][Warning] [Qt][default] content-type missing in HTTP POST, defaulting to application/x-www-form-urlencoded. Use QNetworkRequest::setHeader() to fix this problem.
[21:12:44.996][Info] [tbib.org][Html] Receiving page `https://tbib.org/index.php?page=post&s=list&tags=pikmin&pid=0`
[21:12:45.040][Info] [tbib.org][Html] Parsed page `https://tbib.org/index.php?page=post&s=list&tags=pikmin&pid=0`: 42 images (42), 29 tags (29), 485 total (485), 12 pages (12)
[21:12:45.197][Info] [tbib.org][Xml] Receiving page `https://tbib.org/index.php?page=dapi&s=post&q=index&limit=20&pid=0&tags=pikmin`
[21:12:45.223][Info] [tbib.org][Xml] Parsed page `https://tbib.org/index.php?page=dapi&s=post&q=index&limit=20&pid=0&tags=pikmin`: 20 images (20), 0 tags (360), 485 total (485), 25 pages (25)
[21:12:45.224][Warning] [Qt][default] QNetworkRequest::setHeader: QVariant of type QByteArray cannot be used with header User-Agent
[21:12:45.229][Warning] [Qt][default] content-type missing in HTTP POST, defaulting to application/x-www-form-urlencoded. Use QNetworkRequest::setHeader() to fix this problem.
[21:12:45.273][Info] [booru.allthefallen.moe][Html] Receiving page `https://booru.allthefallen.moe/posts?limit=20&page=1&tags=pikmin`
[21:12:45.276][Info] [booru.allthefallen.moe][Html] Parsed page `https://booru.allthefallen.moe/posts?limit=20&page=1&tags=pikmin`: 0 images (0), 25 tags (25), -1 total (9), -1 pages (1)
[21:12:45.429][Info] [rule34.xxx][Xml] Receiving page `https://api.rule34.xxx//index.php?page=dapi&s=post&q=index&limit=20&pid=0&tags=pikmin`
[21:12:45.443][Info] [rule34.xxx][Xml] Parsed page `https://api.rule34.xxx//index.php?page=dapi&s=post&q=index&limit=20&pid=0&tags=pikmin`: 20 images (20), 0 tags (94), 404 total (404), 21 pages (21)
[21:12:45.443][Warning] [Qt][default] QNetworkRequest::setHeader: QVariant of type QByteArray cannot be used with header User-Agent
[21:12:45.450][Info] [exhentai.org][Html] Receiving page `https://exhentai.org/?&f_cats=0&f_search=pikmin`
[21:12:45.451][Error] [exhentai.org][Html] Loading error: Unknown error (0)
[21:12:45.455][Warning] [Qt][default] QNetworkRequest::setHeader: QVariant of type QByteArray cannot be used with header User-Agent
[21:12:45.456][Warning] [exhentai.org] No valid source of the site returned result.
[21:12:45.464][Info] [booru.allthefallen.moe][Xml] Receiving page `https://booru.allthefallen.moe/posts.xml?limit=20&page=1&tags=pikmin`
[21:12:45.481][Info] [booru.allthefallen.moe][Xml] Parsed page `https://booru.allthefallen.moe/posts.xml?limit=20&page=1&tags=pikmin`: 9 images (9), 0 tags (161), -1 total (-1), -1 pages (-1)
[21:12:45.481][Warning] [Qt][default] QNetworkRequest::setHeader: QVariant of type QByteArray cannot be used with header User-Agent
sinkiller21st commented 1 year ago

Javascript 'model.js'.txt

sinkiller21st commented 1 year ago

text version if javascript 'model.js'.txt won't work

/*  js-model JavaScript library, version 0.11.0
 *  (c) 2010-2012 Ben Pickles
 *
 *  Released under MIT license.
 */
var Model = function(name, func) {
  // The model constructor.
  var model = function(attributes) {
    this.attributes = Model.Utils.extend({}, attributes)
    this.changes = {};
    this.errors = new Model.Errors(this);
    this.uid = [name, Model.UID.generate()].join("-")
    if (Model.Utils.isFunction(this.initialize)) this.initialize()
  };

  // Use module functionality to extend itself onto the constructor. Meta!
  Model.Module.extend.call(model, Model.Module)

  model._name = name
  model.collection = []
  model.unique_key = "id"
  model
    .extend(Model.Callbacks)
    .extend(Model.ClassMethods)

  model.prototype = new Model.Base
  model.prototype.constructor = model

  if (Model.Utils.isFunction(func)) func.call(model, model, model.prototype)

  return model;
};

Model.Callbacks = {
  bind: function(event, callback) {
    this.callbacks = this.callbacks || {}
    this.callbacks[event] = this.callbacks[event] || [];
    this.callbacks[event].push(callback);
    return this;
  },

  trigger: function(name, data) {
    this.callbacks = this.callbacks || {}

    var callbacks = this.callbacks[name];

    if (callbacks) {
      for (var i = 0; i < callbacks.length; i++) {
        callbacks[i].apply(this, data || []);
      }
    }

    return this;
  },

  unbind: function(event, callback) {
    this.callbacks = this.callbacks || {}

    if (callback) {
      var callbacks = this.callbacks[event] || [];

      for (var i = 0; i < callbacks.length; i++) {
        if (callbacks[i] === callback) {
          this.callbacks[event].splice(i, 1);
        }
      }
    } else {
      delete this.callbacks[event];
    }

    return this;
  }
};

Model.ClassMethods = {
  add: function(model) {
    var id = model.id()

    if (Model.Utils.inArray(this.collection, model) === -1 && !(id && this.find(id))) {
      this.collection.push(model)
      this.trigger("add", [model])
    }

    return this;
  },

  all: function() {
    return this.collection.slice()
  },

  // Convenience method to allow a simple method of chaining class methods.
  chain: function(collection) {
    return Model.Utils.extend({}, this, { collection: collection || [] })
  },

  count: function() {
    return this.all().length;
  },

  detect: function(func) {
    var all = this.all(),
        model

    for (var i = 0, length = all.length; i < length; i++) {
      model = all[i]
      if (func.call(model, model, i)) return model
    }
  },

  each: function(func, context) {
    var all = this.all()

    for (var i = 0, length = all.length; i < length; i++) {
      func.call(context || all[i], all[i], i, all)
    }

    return this;
  },

  find: function(id) {
    return this.detect(function() {
      return this.id() == id;
    })
  },

  first: function() {
    return this.all()[0]
  },

  load: function(callback) {
    if (this._persistence) {
      var self = this

      this._persistence.read(function(models) {
        for (var i = 0, length = models.length; i < length; i++) {
          self.add(models[i])
        }

        if (callback) callback.call(self, models)
      })
    }

    return this
  },

  last: function() {
    var all = this.all();
    return all[all.length - 1]
  },

  map: function(func, context) {
    var all = this.all()
    var values = []

    for (var i = 0, length = all.length; i < length; i++) {
      values.push(func.call(context || all[i], all[i], i, all))
    }

    return values
  },

  persistence: function(adapter) {
    if (arguments.length == 0) {
      return this._persistence
    } else {
      var options = Array.prototype.slice.call(arguments, 1)
      options.unshift(this)
      this._persistence = adapter.apply(adapter, options)
      return this
    }
  },

  pluck: function(attribute) {
    var all = this.all()
    var plucked = []

    for (var i = 0, length = all.length; i < length; i++) {
      plucked.push(all[i].attr(attribute))
    }

    return plucked
  },

  remove: function(model) {
    var index

    for (var i = 0, length = this.collection.length; i < length; i++) {
      if (this.collection[i] === model) {
        index = i
        break
      }
    }

    if (index != undefined) {
      this.collection.splice(index, 1);
      this.trigger("remove", [model]);
      return true;
    } else {
      return false;
    }
  },

  reverse: function() {
    return this.chain(this.all().reverse())
  },

  select: function(func, context) {
    var all = this.all(),
        selected = [],
        model

    for (var i = 0, length = all.length; i < length; i++) {
      model = all[i]
      if (func.call(context || model, model, i, all)) selected.push(model)
    }

    return this.chain(selected);
  },

  sort: function(func) {
    var sorted = this.all().sort(func)
    return this.chain(sorted);
  },

  sortBy: function(attribute_or_func) {
    var is_func = Model.Utils.isFunction(attribute_or_func)
    var extract = function(model) {
      return attribute_or_func.call(model)
    }

    return this.sort(function(a, b) {
      var a_attr = is_func ? extract(a) : a.attr(attribute_or_func)
      var b_attr = is_func ? extract(b) : b.attr(attribute_or_func)

      if (a_attr < b_attr) {
        return -1
      } else if (a_attr > b_attr) {
        return 1
      } else {
        return 0
      }
    })
  },

  use: function(plugin) {
    var args = Array.prototype.slice.call(arguments, 1)
    args.unshift(this)
    plugin.apply(this, args)
    return this
  }
};

Model.Errors = function(model) {
  this.errors = {};
  this.model = model;
};

Model.Errors.prototype = {
  add: function(attribute, message) {
    if (!this.errors[attribute]) this.errors[attribute] = [];
    this.errors[attribute].push(message);
    return this
  },

  all: function() {
    return this.errors;
  },

  clear: function() {
    this.errors = {};
    return this
  },

  each: function(func) {
    for (var attribute in this.errors) {
      for (var i = 0; i < this.errors[attribute].length; i++) {
        func.call(this, attribute, this.errors[attribute][i]);
      }
    }
    return this
  },

  on: function(attribute) {
    return this.errors[attribute] || [];
  },

  size: function() {
    var count = 0;
    this.each(function() { count++; });
    return count;
  }
};

Model.InstanceMethods = {
  asJSON: function() {
    return this.attr()
  },

  attr: function(name, value) {
    if (arguments.length === 0) {
      // Combined attributes/changes object.
      return Model.Utils.extend({}, this.attributes, this.changes);
    } else if (arguments.length === 2) {
      // Don't write to attributes yet, store in changes for now.
      if (this.attributes[name] === value) {
        // Clean up any stale changes.
        delete this.changes[name];
      } else {
        this.changes[name] = value;
      }
      this.trigger("change:" + name, [this])
      return this;
    } else if (typeof name === "object") {
      // Mass-assign attributes.
      for (var key in name) {
        this.attr(key, name[key]);
      }
      this.trigger("change", [this])
      return this;
    } else {
      // Changes take precedent over attributes.
      return (name in this.changes) ?
        this.changes[name] :
        this.attributes[name];
    }
  },

  callPersistMethod: function(method, callback) {
    var self = this;

    // Automatically manage adding and removing from the model's Collection.
    var manageCollection = function() {
      if (method === "destroy") {
        self.constructor.remove(self)
      } else {
        self.constructor.add(self)
      }
    };

    // Wrap the existing callback in this function so we always manage the
    // collection and trigger events from here rather than relying on the
    // persistence adapter to do it for us. The persistence adapter is
    // only required to execute the callback with a single argument - a
    // boolean to indicate whether the call was a success - though any
    // other arguments will also be forwarded to the original callback.
    var wrappedCallback = function(success) {
      if (success) {
        // Merge any changes into attributes and clear changes.
        self.merge(self.changes).reset();

        // Add/remove from collection if persist was successful.
        manageCollection();

        // Trigger the event before executing the callback.
        self.trigger(method);
      }

      // Store the return value of the callback.
      var value;

      // Run the supplied callback.
      if (callback) value = callback.apply(self, arguments);

      return value;
    };

    if (this.constructor._persistence) {
      this.constructor._persistence[method](this, wrappedCallback);
    } else {
      wrappedCallback.call(this, true);
    }
  },

  destroy: function(callback) {
    this.callPersistMethod("destroy", callback);
    return this;
  },

  id: function() {
    return this.attributes[this.constructor.unique_key];
  },

  merge: function(attributes) {
    Model.Utils.extend(this.attributes, attributes);
    return this;
  },

  newRecord: function() {
    return this.id() === undefined
  },

  reset: function() {
    this.errors.clear();
    this.changes = {};
    return this;
  },

  save: function(callback) {
    if (this.valid()) {
      var method = this.newRecord() ? "create" : "update";
      this.callPersistMethod(method, callback);
    } else if (callback) {
      callback(false);
    }

    return this;
  },

  valid: function() {
    this.errors.clear();
    this.validate();
    return this.errors.size() === 0;
  },

  validate: function() {
    return this;
  }
};

Model.localStorage = function(klass) {
  if (!window.localStorage) {
    return {
      create: function(model, callback) {
        callback(true)
      },

      destroy: function(model, callback) {
        callback(true)
      },

      read: function(callback) {
        callback([])
      },

      update: function(model, callback) {
        callback(true)
      }
    }
  }

  var collection_uid = [klass._name, "collection"].join("-")
  var readIndex = function() {
    var data = localStorage[collection_uid]
    return data ? JSON.parse(data) : []
  }
  var writeIndex = function(uids) {
    localStorage.setItem(collection_uid, JSON.stringify(uids))
  }
  var addToIndex = function(uid) {
    var uids = readIndex()

    if (Model.Utils.inArray(uids, uid) === -1) {
      uids.push(uid)
      writeIndex(uids)
    }
  }
  var removeFromIndex = function(uid) {
    var uids = readIndex()
    var index = Model.Utils.inArray(uids, uid)

    if (index > -1) {
      uids.splice(index, 1)
      writeIndex(uids)
    }
  }
  var store = function(model) {
    localStorage.setItem(model.uid, JSON.stringify(model.asJSON()))
    addToIndex(model.uid)
  }

  return {
    create: function(model, callback) {
      store(model)
      callback(true)
    },

    destroy: function(model, callback) {
      localStorage.removeItem(model.uid)
      removeFromIndex(model.uid)
      callback(true)
    },

    read: function(callback) {
      if (!callback) return false

      var existing_uids = klass.map(function() { return this.uid })
      var uids = readIndex()
      var models = []
      var attributes, model, uid

      for (var i = 0, length = uids.length; i < length; i++) {
        uid = uids[i]

        if (Model.Utils.inArray(existing_uids, uid) == -1) {
          attributes = JSON.parse(localStorage[uid])
          model = new klass(attributes)
          model.uid = uid
          models.push(model)
        }
      }

      callback(models)
    },

    update: function(model, callback) {
      store(model)
      callback(true)
    }
  }
};

Model.Log = function() {
  if (window.console) window.console.log.apply(window.console, arguments);
};

Model.Module = {
  extend: function(obj) {
    Model.Utils.extend(this, obj)
    return this
  },

  include: function(obj) {
    Model.Utils.extend(this.prototype, obj)
    return this
  }
};

Model.REST = function(klass, resource, methods) {
    var PARAM_NAME_MATCHER = /:([\w\d]+)/g;
  var resource_param_names = (function() {
    var resource_param_names = []
    var param_name

    while ((param_name = PARAM_NAME_MATCHER.exec(resource)) !== null) {
      resource_param_names.push(param_name[1])
    }

    return resource_param_names
  })()

  return Model.Utils.extend({
        path: function(model) {
      var path = resource;
      jQuery.each(resource_param_names, function(i, param) {
                path = path.replace(":" + param, model.attributes[param]);
            });
            return path;
        },

    create: function(model, callback) {
      return this.xhr('POST', this.create_path(model), model, callback);
    },

    create_path: function(model) {
      return this.path(model);
    },

    destroy: function(model, callback) {
      return this.xhr('DELETE', this.destroy_path(model), model, callback);
    },

    destroy_path: function(model) {
      return this.update_path(model);
    },

    params: function(model) {
      var params;
      if (model) {
        var attributes = model.asJSON()
        delete attributes[model.constructor.unique_key];
        params = {};
        params[model.constructor._name.toLowerCase()] = attributes;
      } else {
        params = null;
      }
      if(jQuery.ajaxSettings.data){
        params = Model.Utils.extend({}, jQuery.ajaxSettings.data, params)
      }
      return JSON.stringify(params)
    },

    read: function(callback) {
      return this.xhr("GET", this.read_path(), null, function(success, xhr, data) {
        data = jQuery.makeArray(data)
        var models = []

        for (var i = 0, length = data.length; i < length; i++) {
          models.push(new klass(data[i]))
        }

        callback(models)
      })
    },

    read_path: function() {
      return resource
    },

    update: function(model, callback) {
      return this.xhr('PUT', this.update_path(model), model, callback);
    },

    update_path: function(model) {
      return [this.path(model), model.id()].join('/');
    },

    xhr: function(method, url, model, callback) {
      var self = this;
      var data = method == 'GET' ? undefined : this.params(model);

      return jQuery.ajax({
        type: method,
        url: url,
        contentType: "application/json",
        dataType: "json",
        data: data,
        dataFilter: function(data, type) {
          return /\S/.test(data) ? data : undefined;
        },
        complete: function(xhr, textStatus) {
          self.xhrComplete(xhr, textStatus, model, callback)
        }
      });
    },

    xhrComplete: function(xhr, textStatus, model, callback) {
      // Allow custom handlers to be defined per-HTTP status code.
      var handler = Model.REST["handle" + xhr.status]
      if (handler) handler.call(this, xhr, textStatus, model)

      var success = textStatus === "success"
      var data = Model.REST.parseResponseData(xhr)

      // Remote data is the definitive source, update model.
      if (success && model && data) model.attr(data)

      if (callback) callback.call(model, success, xhr, data)
    }
  }, methods)
};

// TODO: Remove in v1 if it ever gets there.
Model.RestPersistence = Model.REST;

// Rails' preferred failed validation response code, assume the response
// contains errors and replace current model errors with them.
Model.REST.handle422 = function(xhr, textStatus, model) {
  var data = Model.REST.parseResponseData(xhr);

  if (data) {
    model.errors.clear()

    for (var attribute in data) {
      for (var i = 0; i < data[attribute].length; i++) {
        model.errors.add(attribute, data[attribute][i])
      }
    }
  }
};

Model.REST.parseResponseData = function(xhr) {
  try {
    return /\S/.test(xhr.responseText) ?
      jQuery.parseJSON(xhr.responseText) :
      undefined;
  } catch(e) {
    Model.Log(e);
  }
};

Model.UID = {
  counter: 0,

  generate: function() {
    return [new Date().valueOf(), this.counter++].join("-")
  },

  reset: function() {
    this.counter = 0
    return this
  }
};

Model.Utils = {
  extend: function(receiver) {
    var objs = Array.prototype.slice.call(arguments, 1)

    for (var i = 0, length = objs.length; i < length; i++) {
      for (var property in objs[i]) {
        receiver[property] = objs[i][property]
      }
    }

    return receiver
  },

  inArray: function(array, obj) {
    if (array.indexOf) return array.indexOf(obj)

    for (var i = 0, length = array.length; i < length; i++) {
      if (array[i] === obj) return i
    }

    return -1
  },

  isFunction: function(obj) {
    return Object.prototype.toString.call(obj) === "[object Function]"
  }
}

Model.VERSION = "0.11.0";

Model.Base = (function() {
  function Base() {}
  Base.prototype = Model.Utils.extend({}, Model.Callbacks, Model.InstanceMethods)
  return Base
})();
Bionus commented 1 year ago

Can you enable debug mode by adding -d when starting the program?

Cf below: image

text version if javascript 'model.js'.txt won't work

Where did you get this file from? This is not a Grabber model.js file.

Bionus commented 12 months ago

Could it be the same issue as #3006 ? Is your Windows scaling setting high? Did you try setting it to 100% and see if that solves it?