<commit_before>import EventEmitter from "events"

class Fusion {

    constructor(hostString){
        this.hostString = hostString
        this._socket = new Socket(hostString)
        // Hack for fusion(collectionName) syntax
        self = (collectionName) => self.collection(collectionName)
        self.__proto__ = this.__proto__
        return self
    }

    collection(name){
        //Check if collection exists?? Nope, EAFP let server handle it.
        return new Collection(this, name)
    }

    _query(path){
        return this.socket.send("QUERY", {path: path})
    }

    _store(path, document, conflict){
        if(conflict === 'replace'){
            return this.socket.send("STORE_REPLACE", {path: path, data: document})
        }else if(conflict === 'error'){
            return this.socket.send("STORE_ERROR", {path: path, data: document})
        }else{
            return Promise.reject(`value of conflict not understood: ${conflict}`)
        }
    }

    _update(path, document){
        return this.socket.send("UPDATE", {path: path, data: document})
    }

    _remove(path, id){
        return this.socket.send("REMOVE", {path: path, data: id})
    }

    _subscribe(path, updates){
        if(updates){
            return this.socket.subscribe(path)
        }else{
            //Emulate subscription with one-shot query
            var emitter = new EventEmitter()
            this.socket.send("QUERY", path).then(
                // Do we have continues etc like cursors?
                // Right now assuming we get results back as an array
                (results) =>
                    for(result of results) {
                        emitter.emit("added", {new_val: result, old_val: null})
                    }
            )
            return emitter
        }
    }

}

class Socket {
    constructor(hostString){
        this.ws = new WebSocket(connection_string)
        this.ws.onmessage = this._onMessage
        this.ws.onclose = this._onClose
        this.ws.onopen = this._onOpen
        this.promises = {}
        this.emitters = {}
        this.requestCounter = 0
    }

    send(type, data){
        var requestId = this.requestCounter++
        var req = {type: type, data: data, requestId: requestId}
        return new Promise((resolve, reject) =>
            this.promises[requestId] = {resolve: resolve, reject:reject})
    }

    subscribe(path){
        var requestId = this.requestCounter++
        var req = {type: "SUBSCRIBE", data: data, requestId: requestId}
        var emitter = new EventEmitter() // customize?
        this.emitters[requestId] = emitter
        return emitter
    }

    _onClose(event){
        for (emitter of this.emitters){
            emitter.emit('disconnected', event)
        }
        // Do we do something with promises? What if we reconnect
    }

    _onOpen(event){
        for(emitter of this.emitters){
            emitter.emit('reconnected', event)
        }
    }

    _onMessage(event){
        var resp = JSON.parse(event.data)
        if(this.promises.hasOwnProperty(resp.requestId)){
            var promise = this.promises[resp.requestId]
            delete this.promises[resp.requestId]

            if (resp.error !== undefined){
                promise.reject(resp.error)
            } else {
                promise.resolve(resp.value)
            }
        }else if(this.emitters.hasOwnProperty(resp.requestId)){
            var emitter = this.emitters[resp.requestId]
            if(resp.error !== undefined){
                emitter.emit("error", resp.error)
            }else{
                emitter.emit(classify(resp.data), resp.value)
            }
        }else{
            console.error(`Unrecognized response: ${event}`)
        }
    }

    classify(response){
        // response -> responseType
        // this might need to go in another class and be given to this class
        if(response.new_val !== null && response.old_val !== null){
            return 'changed'
        }else if(response.new_val !== null && response.old_val === null){
            return 'added'
        }else if(response.new_val === null && response.old_val !== null){
            return 'removed'
        }else if(response.state === 'synced'){
            return 'synced'
        }else{
            return 'unknown'
        }
    }
}

class TermBase {

    constructor(fusion){
        this.fusion = fusion
    }

    subscribe(updates: true){
        // should create a changefeed query, return eventemitter
        return this.fusion._subscribe(this.path)
    }

    value(){
        // return promise with no changefeed
        return this.fusion._value(this.path)
    }
}

class Collection {

    constructor(fusion, collectionName){
        this.collectionName = collectionName
        this.fusion = fusion
    }

    findOne(id){
        return new findOne(this.fusion, this.collectionName, id)
    }

    find(fieldName, fieldValue){
        return new Find(this.fusion, this.collectionName, fieldName, fieldValue)
    }

    between(minVal, maxVal, field: 'id'){
        return new Between(this.fusion, this.collectionName, minVal, maxVal,field)
    }

    ordered(field: 'id'){
        return new Ordered(this.fusion, this.collectionName, field)
    }

    store(document, conflict: 'replace'){
        return this.fusion._store(path, document, conflict)
    }

    update(document){
        return this.fusion._update(path, document)
    }

    remove(document){
        return this.fusion._remove(path, document)
    }
}

class Find extends TermBase {
    constructor(fusion, path, field, value){
        super(fusion)
        this.field
        this.value = value
        this.path = `${path}/find:${field}:${value}`
  }
}

class FindOne extends TermBase {
    constructor(fusion, path, docId){
        super(fusion)
        this.id = docId
        this.path = `${path}/findOne:${docId}`
    }
}

class Between extends TermBase {
    constructor(fusion, path, minVal, maxVal, field){
        super(fusion)
        this.minVal = minVal
        this.maxVal = maxVal
        this.field = field
        this.path = `${path}/between:${minVal}:${maxVal}:${field}`
    }
}

class Ordered {
    constructor(fusion, path, field){
        this.fusion = fusion
        this.field = field
        this.path = `${path}/ordered:${field}`
    }

    limit(num){
        return new Limit(this.fusion, this.path, num)
    }

    between(minVal, maxVal, field: 'id'){
        return new Between(this.fusion, this.path, minVal, maxVal, field)
    }
}

class Limit extends TermBase {
    constructor(fusion, path, field, num){
        super(fusion)
        this.field = field
        this.num = num
        this.path = `${path}/limit:${field}:${num}`
    }
}
<commit_msg>Avoid letting ordered/between use different fields<commit_after>import EventEmitter from "events"

class Fusion {

    constructor(hostString){
        this.hostString = hostString
        this._socket = new Socket(hostString)
        // Hack for fusion(collectionName) syntax
        self = (collectionName) => self.collection(collectionName)
        self.__proto__ = this.__proto__
        return self
    }

    collection(name){
        //Check if collection exists?? Nope, EAFP let server handle it.
        return new Collection(this, name)
    }

    _query(path){
        return this.socket.send("QUERY", {path: path})
    }

    _store(path, document, conflict){
        if(conflict === 'replace'){
            return this.socket.send("STORE_REPLACE", {path: path, data: document})
        }else if(conflict === 'error'){
            return this.socket.send("STORE_ERROR", {path: path, data: document})
        }else{
            return Promise.reject(`value of conflict not understood: ${conflict}`)
        }
    }

    _update(path, document){
        return this.socket.send("UPDATE", {path: path, data: document})
    }

    _remove(path, id){
        return this.socket.send("REMOVE", {path: path, data: id})
    }

    _subscribe(path, updates){
        if(updates){
            return this.socket.subscribe(path)
        }else{
            //Emulate subscription with one-shot query
            var emitter = new EventEmitter()
            this.socket.send("QUERY", path).then(
                // Do we have continues etc like cursors?
                // Right now assuming we get results back as an array
                (results) =>
                    for(result of results) {
                        emitter.emit("added", {new_val: result, old_val: null})
                    }
            )
            return emitter
        }
    }

}

class Socket {
    constructor(hostString){
        this.ws = new WebSocket(connection_string)
        this.ws.onmessage = this._onMessage
        this.ws.onclose = this._onClose
        this.ws.onopen = this._onOpen
        this.promises = {}
        this.emitters = {}
        this.requestCounter = 0
    }

    send(type, data){
        var requestId = this.requestCounter++
        var req = {type: type, data: data, requestId: requestId}
        return new Promise((resolve, reject) =>
            this.promises[requestId] = {resolve: resolve, reject:reject})
    }

    subscribe(path){
        var requestId = this.requestCounter++
        var req = {type: "SUBSCRIBE", data: data, requestId: requestId}
        var emitter = new EventEmitter() // customize?
        this.emitters[requestId] = emitter
        return emitter
    }

    _onClose(event){
        for (emitter of this.emitters){
            emitter.emit('disconnected', event)
        }
        // Do we do something with promises? What if we reconnect
    }

    _onOpen(event){
        for(emitter of this.emitters){
            emitter.emit('reconnected', event)
        }
    }

    _onMessage(event){
        var resp = JSON.parse(event.data)
        if(this.promises.hasOwnProperty(resp.requestId)){
            var promise = this.promises[resp.requestId]
            delete this.promises[resp.requestId]

            if (resp.error !== undefined){
                promise.reject(resp.error)
            } else {
                promise.resolve(resp.value)
            }
        }else if(this.emitters.hasOwnProperty(resp.requestId)){
            var emitter = this.emitters[resp.requestId]
            if(resp.error !== undefined){
                emitter.emit("error", resp.error)
            }else{
                emitter.emit(classify(resp.data), resp.value)
            }
        }else{
            console.error(`Unrecognized response: ${event}`)
        }
    }

    classify(response){
        // response -> responseType
        // this might need to go in another class and be given to this class
        if(response.new_val !== null && response.old_val !== null){
            return 'changed'
        }else if(response.new_val !== null && response.old_val === null){
            return 'added'
        }else if(response.new_val === null && response.old_val !== null){
            return 'removed'
        }else if(response.state === 'synced'){
            return 'synced'
        }else{
            return 'unknown'
        }
    }
}

class TermBase {

    constructor(fusion){
        this.fusion = fusion
    }

    subscribe(updates: true){
        // should create a changefeed query, return eventemitter
        return this.fusion._subscribe(this.path)
    }

    value(){
        // return promise with no changefeed
        return this.fusion._value(this.path)
    }
}

class Collection {

    constructor(fusion, collectionName){
        this.collectionName = collectionName
        this.fusion = fusion
    }

    findOne(id){
        return new findOne(this.fusion, this.collectionName, id)
    }

    find(fieldName, fieldValue){
        return new Find(this.fusion, this.collectionName, fieldName, fieldValue)
    }

    between(minVal, maxVal, field: 'id'){
        return new Between(this.fusion, this.collectionName, minVal, maxVal,field)
    }

    ordered(field: 'id'){
        return new Ordered(this.fusion, this.collectionName, field)
    }

    store(document, conflict: 'replace'){
        return this.fusion._store(path, document, conflict)
    }

    update(document){
        return this.fusion._update(path, document)
    }

    remove(document){
        return this.fusion._remove(path, document)
    }
}

class Find extends TermBase {
    constructor(fusion, path, field, value){
        super(fusion)
        this.field
        this.value = value
        this.path = `${path}/find:${field}:${value}`
  }
}

class FindOne extends TermBase {
    constructor(fusion, path, docId){
        super(fusion)
        this.id = docId
        this.path = `${path}/findOne:${docId}`
    }
}

class Between extends TermBase {
    constructor(fusion, path, minVal, maxVal, field){
        super(fusion)
        this.minVal = minVal
        this.maxVal = maxVal
        this.field = field
        this.path = `${path}/between:${minVal}:${maxVal}:${field}`
    }
}

class Ordered {
    constructor(fusion, path, field){
        this.fusion = fusion
        this.field = field
        this.path = `${path}/ordered:${field}`
    }

    limit(num){
        return new Limit(this.fusion, this.path, num)
    }

    between(minVal, maxVal){
        return new Between(this.fusion, this.path, minVal, maxVal, this.field)
    }
}

class Limit extends TermBase {
    constructor(fusion, path, field, num){
        super(fusion)
        this.field = field
        this.num = num
        this.path = `${path}/limit:${field}:${num}`
    }
}
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import MyGraphiQL from './MyGraphiQL';

function graphQLFetcher(graphQLParams) {
  return fetch('window.location.origin'+ '/graphql', {
    method: 'post',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(graphQLParams),
  }).then(response => response.json());
}

ReactDOM.render(
  <MyGraphiQL fetcher={graphQLFetcher} enpoint={'window.location.origin'+ '/graphql'}/>,
  document.body
);<commit_msg>change hostname dynamically<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import MyGraphiQL from './MyGraphiQL';

var endpoint = "http://" + window.location.hostname + ':8080/graphql';
console.log(endpoint);

function graphQLFetcher(graphQLParams) {
  return fetch(endpoint, {
    method: 'post',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(graphQLParams),
  }).then(response => response.json());
}

ReactDOM.render(
  <MyGraphiQL fetcher={graphQLFetcher} enpoint={endpoint}/>,
  document.body
);
<|endoftext|>


<commit_before>// This function cleans all the elements that could leak user data
// before sending to the server. It also removes any attributes that
// could have personal data so we end up with a clean dom tree.
const selectors = [
  'video',
  'input',
  'button',
  'iframe',
  'a[href=""]',
  '.accessible_elem',
  '.uiLikePagebutton',
  '.uiPopOver',
  '.uiCloseButton',
  '.uiChevronSelectorButton',
  'h5._1qbu',
  '.commentable_item'
].join(', ');

const TIMELINE_SELECTOR = '.fbUserContent, .fbUserPost, ._5pcr';
const SIDEBAR_SELECTOR = '.ego_unit';

const cleanAd = (html) => {
  let node = document.createElement("div");
  node.innerHTML = html;

  // We're not saving video ads for now, we don't need buttons, hidden forms,
  // or like links
  Array.from(node.querySelectorAll(selectors))
    .forEach((i) => i.remove());

  // remove attributes
  const killAttrs = (node) => {
    Array.from(node.attributes).forEach(attr => {
      if(attr.name !== "id" &&
         attr.name !== "class" &&
         attr.name !== "src" &&
         attr.name !== "href")
        node.removeAttribute(attr.name);
      // remove tracking get variables from links and l.facebook.com
      if(attr.name === "href") {
        try {
          let url = new URL(attr.value);
          if(url.host === 'l.facebook.com')
            url = new URL(new URLSearchParams(url.search).get("u"));
          if(url.origin && url.pathname) {
            node.setAttribute(attr.name, url.origin + url.pathname);
          } else {
            node.removeAttribute(attr.name);
          }
        } catch(e) {
          node.removeAttribute(attr.name);
        }
      }
    });
    // walk through the tree.
    Array.from(node.children).forEach(killAttrs);
  };
  Array.from(node.children).forEach(killAttrs);
  return node.innerHTML.replace(/&/g, '&');
};

const checkSponsor = (node) => {
  return Array.from(node.querySelectorAll("a")).some((a) => {
    return ['Sponsored','Gesponsert','Sponsrad','Sponsorlu','إعلان مُموَّل','Sponsoreret'].some((sponsor) => a.textContent === sponsor);
  });
};

// We have to do this because content scripts can't read window variables
const grabVariable = (fn, args)  => {
  let script = document.createElement("script");
  script.textContent = 'localStorage.setItem("pageVariable", (' + fn + ').apply(this, ' + JSON.stringify(args) + '));';
  script.setAttribute('id', 'pageVariable');
  (document.head||document.documentElement).appendChild(script);
  script.remove();
  return localStorage.getItem("pageVariable");
};

// Getting the targeting information. We're careful to cache any results so as to avoid being
// blocked by facebook.
let targetingBlocked = false;
let targetingCache = new Map();
const getTargeting = (ad) => {
  if(ad.targeting) {
    if(targetingCache.has(ad.targeting)) return {
      ...ad,
      targeting: targetingCache.get(ad.targeting)
    };
    const url = ad.targeting;
    delete ad.targeting;
    if(targetingBlocked) return ad;
    return new Promise((resolve) => {
      let req = new XMLHttpRequest();
      req.onreadystatechange = function() {
        if(req.readyState === 4) {
          try {
            const targeting = cleanAd(JSON.parse(req.response.replace('for (;;);', ''))["jsmods"]["markup"][0][1]["__html"]);
            if(!targeting) {
              return resolve(ad);
            }
            targetingCache.set(url, targeting);
            resolve({
              ...ad,
              targeting
            });
          } catch(e) {
            targetingBlocked = true;
            setTimeout(() => targetingBlocked = false, 15 * 60 * 100);
            resolve(ad);
          }
        }
      };

      // This is all built out from a close reading of facebook's code.
      let built = grabVariable((url) => {
        let parsed = new (window.require('URI'))(url);
        localStorage.setItem('url', url);
        let req = new window.AsyncRequest()
          .setURI(url)
          .setData(parsed)
          .setMethod('GET')
          .setRelativeTo(document.body)
          .setNectarModuleDataSafe(document.body)
          .setReadOnly(true);
        Object.assign(req.data, {__asyncDialog: 1});
        Object.assign(req.data, window.require('getAsyncParams')(req.method));
        req._setUserActionID();
        req.setNewSerial();
        return req.uri.addQueryData(req.data).toString();
      }, [url]);
      // AsyncRequest builds out the correct targeting url
      req.open('GET', "https://www.facebook.com" + built, true);
      req.send();
    });
  } else {
    return ad;
  }
};

// We want to minimize the impact of a user's experience using facebook, so this function tries to
// restore the state of the page when the extension clicks around.
const refocus = (cb) => {
  const focus = document.activeElement;
  cb();
  if(focus) focus.focus();
};

// Getting the extension to show targeting information for timeline ads is hard, so we have this
// gnarly function.
let timelineCache = new Map();
const getTimelineId = (parent, ad) => {
  const control = parent.querySelector(".uiPopover");
  if(!control && control.id === "")
    return null;

  const toggle = control.querySelector("a");
  if(!toggle)
    return null;

  if(timelineCache.has(toggle.id))
    return Promise.resolve(timelineCache.get(toggle.id));

  // this is async, we have to wait until our popup shows up.
  let promise = new Promise((resolve, reject) => {
    let cb = (record, self) => {
      const layer = Array.from(document.querySelectorAll(".uiLayer"))
        .filter((a) => {
          return a.getAttribute("data-ownerid") === toggle.id;
        })[0];
      if(!layer) return null;
      const li = Array.from(layer.querySelectorAll("li"))
        .filter((it) => it.getAttribute("data-feed-option-name") === "FeedAdSeenReasonOption")[0];
      if(!li) return null;
      const endpoint = li.querySelector("a");
      if(!endpoint) return null;
      const url =  endpoint.getAttribute("ajaxify");
      refocus(() => toggle.click());
      self.disconnect();
      try {
        const resolved = {
          ...ad,
          id: new URL("https://facebook.com" + url).searchParams.get("id"),
          targeting: url
        };

        if(resolved.id) {
          timelineCache.set(toggle.id, resolved);
          resolve(resolved);
        } else {
          reject("No ad id");
        }
      } catch(e) {
        reject(e);
      }
    };

    new MutationObserver(cb).observe(document, {childList: true, subtree:true});
  }).then(getTargeting);
  refocus(() => toggle.click());
  return promise;
};

const getSidebarId = (parent, ad) => {
  const control = parent.querySelector(".uiSelectorMenuWrapper");

  //Replicating getTimelineId.
  // Since the sidebar DOM structure is slightly different we need to pull out
  // the toggle Id from the data-gt attribute. I was unable to find a dataowner-id attribute
  const toggle = parent.querySelector('a')
  const toggleData = JSON.parse(toggle.getAttribute('data-gt'))
  const toggleId = toggleData["data_to_log"]["ad_id"]
  if (!toggle && !toggleData)
    return null;

  if (sidebarCache.has(toggleId))
    return Promise.resolve(sidebarCache.get(toggleId));

  // Leaving this here becuase you'll need to test the above code works.
  // console.log(toggle, toggleData)
  let promise = new Promise((resolve, reject) => {
    let cb = (record, self) => {
      const menu = Array.from(document.querySelectorAll(".uiMenu"))

      if(!menu) return null;

      const li = Array.from(layer.querySelectorAll("li"))
        .filter((it) => it.getAttribute("data-label") === "Why am I seeing this?")[0];
      const endpoint = li.querySelector("a");
      if(!endpoint) return null;
      const url =  endpoint.getAttribute("ajaxify");
      refocus(() => toggle.click());
      self.disconnect();
      try {
        const resolved = {
          ...ad,
          id: new URL("https://facebook.com" + url).searchParams.get("id"),
          targeting: url
        };

        if(resolved.id) {
          timelineCache.set(toggleId, resolved);
          resolve(resolved);
        } else {
          reject("No ad id");
        }

      } catch(e) {
        reject(e);
      }
    };
    new MutationObserver(cb).observe(document, {childList: true, subtree:true});
  }).then(getTargeting)

  refocus(() => toggle.click());
  return promise;
}
const timeline = (node) => {
  // First we check if it is actually a sponsored post
  if(!checkSponsor(node)) return Promise.resolve(false);

  // And then we try to grab the parent container that has a hyperfeed id
  let parent = node;
  while(parent) {
    let id = parent.getAttribute("id");
    if(id && id.startsWith("hyperfeed")) break;
    parent = parent.parentElement;
  }

  // If we've walked off the top of the parent heirarchy that's an error
  if(!parent) return Promise.resolve(false);

  // Also if there's nothing to save that's an error
  if(node.children.length === 0) return Promise.resolve(false);

  // Check to see that we have the innermost fbUserContent, this cuts out like's
  // and shares.
  if(node.querySelector(TIMELINE_SELECTOR))
    node = node.querySelector(TIMELINE_SELECTOR);

  // Finally we have something to save.
  return getTimelineId(parent, {
    html: cleanAd(node.children[0].outerHTML),
    created_at: (new Date()).valueOf()
  });
};

// Sidebar ads are a bit more complicated.
const sidebar = (node) => {
  // Although first we still need to make sure we are in a sponsored box;
  let parent = node;
  while(parent) {
    if(checkSponsor(parent)) break;
    parent = parent.parentElement;
  }

  // As before it is an error if we haven't found a sponsor node.
  if(!(parent &&
       parent.classList &&
       parent.classList.contains('ego_section'))) return Promise.resolve(false);

  // Sanity check to make sure we have a salvageable id
  if(!node.hasAttribute("data-ego-fbid")) return Promise.resolve(false);

  // and we have childnodes
  if(!node.children.length === 0) return Promise.resolve(false);
  // Then we just need to sent the cleaned ad and the ego-fbid
  return Promise.resolve({
    id: node.getAttribute("data-ego-fbid"),
    html: cleanAd(node.outerHTML),
    created_at: (new Date()).valueOf()
  });
};

// We are careful here to only accept a valid timeline ad or sidebar ad
const parser = function(node) {
  if(node.classList.contains("fbUserContent") ||
     node.classList.contains("fbUserPost") ||
     node.classList.contains("_5pcr")) {
    return timeline(node);
  } else if(node.classList.contains('ego_unit')) {
    return sidebar(node);
  } else {
    return Promise.resolve(false);
  }
};

module.exports = {
  parser,
  TIMELINE_SELECTOR,
  SIDEBAR_SELECTOR,
};
<commit_msg>Update parser.js<commit_after>// This function cleans all the elements that could leak user data
// before sending to the server. It also removes any attributes that
// could have personal data so we end up with a clean dom tree.
const selectors = [
  'video',
  'input',
  'button',
  'iframe',
  'a[href=""]',
  '.accessible_elem',
  '.uiLikePagebutton',
  '.uiPopOver',
  '.uiCloseButton',
  '.uiChevronSelectorButton',
  'h5._1qbu',
  '.commentable_item'
].join(', ');

const TIMELINE_SELECTOR = '.fbUserContent, .fbUserPost, ._5pcr';
const SIDEBAR_SELECTOR = '.ego_unit';

const cleanAd = (html) => {
  let node = document.createElement("div");
  node.innerHTML = html;

  // We're not saving video ads for now, we don't need buttons, hidden forms,
  // or like links
  Array.from(node.querySelectorAll(selectors))
    .forEach((i) => i.remove());

  // remove attributes
  const killAttrs = (node) => {
    Array.from(node.attributes).forEach(attr => {
      if(attr.name !== "id" &&
         attr.name !== "class" &&
         attr.name !== "src" &&
         attr.name !== "href")
        node.removeAttribute(attr.name);
      // remove tracking get variables from links and l.facebook.com
      if(attr.name === "href") {
        try {
          let url = new URL(attr.value);
          if(url.host === 'l.facebook.com')
            url = new URL(new URLSearchParams(url.search).get("u"));
          if(url.origin && url.pathname) {
            node.setAttribute(attr.name, url.origin + url.pathname);
          } else {
            node.removeAttribute(attr.name);
          }
        } catch(e) {
          node.removeAttribute(attr.name);
        }
      }
    });
    // walk through the tree.
    Array.from(node.children).forEach(killAttrs);
  };
  Array.from(node.children).forEach(killAttrs);
  return node.innerHTML.replace(/&/g, '&');
};

const checkSponsor = (node) => {
  return Array.from(node.querySelectorAll("a")).some((a) => {
    return ['Sponsored','Gesponsert','Sponsrad','Sponsorlu','إعلان مُموَّل','Sponsoreret'].some((sponsor) => a.textContent === sponsor);
  });
};

// We have to do this because content scripts can't read window variables
const grabVariable = (fn, args)  => {
  let script = document.createElement("script");
  script.textContent = 'localStorage.setItem("pageVariable", (' + fn + ').apply(this, ' + JSON.stringify(args) + '));';
  script.setAttribute('id', 'pageVariable');
  (document.head||document.documentElement).appendChild(script);
  script.remove();
  return localStorage.getItem("pageVariable");
};

// Getting the targeting information. We're careful to cache any results so as to avoid being
// blocked by facebook.
let targetingBlocked = false;
let targetingCache = new Map();
const getTargeting = (ad) => {
  if(ad.targeting) {
    if(targetingCache.has(ad.targeting)) return {
      ...ad,
      targeting: targetingCache.get(ad.targeting)
    };
    const url = ad.targeting;
    delete ad.targeting;
    if(targetingBlocked) return ad;
    return new Promise((resolve) => {
      let req = new XMLHttpRequest();
      req.onreadystatechange = function() {
        if(req.readyState === 4) {
          try {
            const targeting = cleanAd(JSON.parse(req.response.replace('for (;;);', ''))["jsmods"]["markup"][0][1]["__html"]);
            if(!targeting) {
              return resolve(ad);
            }
            targetingCache.set(url, targeting);
            resolve({
              ...ad,
              targeting
            });
          } catch(e) {
            targetingBlocked = true;
            setTimeout(() => targetingBlocked = false, 15 * 60 * 100);
            resolve(ad);
          }
        }
      };

      // This is all built out from a close reading of facebook's code.
      let built = grabVariable((url) => {
        let parsed = new (window.require('URI'))(url);
        localStorage.setItem('url', url);
        let req = new window.AsyncRequest()
          .setURI(url)
          .setData(parsed)
          .setMethod('GET')
          .setRelativeTo(document.body)
          .setNectarModuleDataSafe(document.body)
          .setReadOnly(true);
        Object.assign(req.data, {__asyncDialog: 1});
        Object.assign(req.data, window.require('getAsyncParams')(req.method));
        req._setUserActionID();
        req.setNewSerial();
        return req.uri.addQueryData(req.data).toString();
      }, [url]);
      // AsyncRequest builds out the correct targeting url
      req.open('GET', "https://www.facebook.com" + built, true);
      req.send();
    });
  } else {
    return ad;
  }
};

// We want to minimize the impact of a user's experience using facebook, so this function tries to
// restore the state of the page when the extension clicks around.
const refocus = (cb) => {
  const focus = document.activeElement;
  cb();
  if(focus) focus.focus();
};

// Getting the extension to show targeting information for timeline ads is hard, so we have this
// gnarly function.
let timelineCache = new Map();
const getTimelineId = (parent, ad) => {
  const control = parent.querySelector(".uiPopover");
  if(!control && control.id === "")
    return null;

  const toggle = control.querySelector("a");
  if(!toggle)
    return null;

  if(timelineCache.has(toggle.id))
    return Promise.resolve(timelineCache.get(toggle.id));

  // this is async, we have to wait until our popup shows up.
  let promise = new Promise((resolve, reject) => {
    let cb = (record, self) => {
      const layer = Array.from(document.querySelectorAll(".uiLayer"))
        .filter((a) => {
          return a.getAttribute("data-ownerid") === toggle.id;
        })[0];
      if(!layer) return null;
      const li = Array.from(layer.querySelectorAll("li"))
        .filter((it) => it.getAttribute("data-feed-option-name") === "FeedAdSeenReasonOption")[0];
      if(!li) return null;
      const endpoint = li.querySelector("a");
      if(!endpoint) return null;
      const url =  endpoint.getAttribute("ajaxify");
      refocus(() => toggle.click());
      self.disconnect();
      try {
        const resolved = {
          ...ad,
          id: new URL("https://facebook.com" + url).searchParams.get("id"),
          targeting: url
        };

        if(resolved.id) {
          timelineCache.set(toggle.id, resolved);
          resolve(resolved);
        } else {
          reject("No ad id");
        }
      } catch(e) {
        reject(e);
      }
    };

    new MutationObserver(cb).observe(document, {childList: true, subtree:true});
  }).then(getTargeting);
  refocus(() => toggle.click());
  return promise;
};

const getSidebarId = (parent, ad) => {
  const control = parent.querySelector(".uiSelectorMenuWrapper");

  //Replicating getTimelineId.
  // Since the sidebar DOM structure is slightly different we need to pull out
  // the toggle Id from the data-gt attribute. I was unable to find a dataowner-id attribute
  const toggle = parent.querySelector('a');
  const toggleData = JSON.parse(toggle.getAttribute('data-gt'));
  const toggleId = toggleData["data_to_log"]["ad_id"];
  if (!toggle && !toggleData)
    return null;

  if (sidebarCache.has(toggleId))
    return Promise.resolve(sidebarCache.get(toggleId));

  // Leaving this here becuase you'll need to test the above code works.
  // console.log(toggle, toggleData)
  let promise = new Promise((resolve, reject) => {
    let cb = (record, self) => {
      const menu = Array.from(document.querySelectorAll(".uiMenu"))

      if(!menu) return null;

      const li = Array.from(layer.querySelectorAll("li"))
        .filter((it) => it.getAttribute("data-label") === "Why am I seeing this?")[0];
      const endpoint = li.querySelector("a");
      if(!endpoint) return null;
      const url =  endpoint.getAttribute("ajaxify");
      refocus(() => toggle.click());
      self.disconnect();
      try {
        const resolved = {
          ...ad,
          id: new URL("https://facebook.com" + url).searchParams.get("id"),
          targeting: url
        };

        if(resolved.id) {
          timelineCache.set(toggleId, resolved);
          resolve(resolved);
        } else {
          reject("No ad id");
        }

      } catch(e) {
        reject(e);
      }
    };
    new MutationObserver(cb).observe(document, {childList: true, subtree:true});
  }).then(getTargeting)

  refocus(() => toggle.click());
  return promise;
}
const timeline = (node) => {
  // First we check if it is actually a sponsored post
  if(!checkSponsor(node)) return Promise.resolve(false);

  // And then we try to grab the parent container that has a hyperfeed id
  let parent = node;
  while(parent) {
    let id = parent.getAttribute("id");
    if(id && id.startsWith("hyperfeed")) break;
    parent = parent.parentElement;
  }

  // If we've walked off the top of the parent heirarchy that's an error
  if(!parent) return Promise.resolve(false);

  // Also if there's nothing to save that's an error
  if(node.children.length === 0) return Promise.resolve(false);

  // Check to see that we have the innermost fbUserContent, this cuts out like's
  // and shares.
  if(node.querySelector(TIMELINE_SELECTOR))
    node = node.querySelector(TIMELINE_SELECTOR);

  // Finally we have something to save.
  return getTimelineId(parent, {
    html: cleanAd(node.children[0].outerHTML),
    created_at: (new Date()).valueOf()
  });
};

// Sidebar ads are a bit more complicated.
const sidebar = (node) => {
  // Although first we still need to make sure we are in a sponsored box;
  let parent = node;
  while(parent) {
    if(checkSponsor(parent)) break;
    parent = parent.parentElement;
  }

  // As before it is an error if we haven't found a sponsor node.
  if(!(parent &&
       parent.classList &&
       parent.classList.contains('ego_section'))) return Promise.resolve(false);

  // Sanity check to make sure we have a salvageable id
  if(!node.hasAttribute("data-ego-fbid")) return Promise.resolve(false);

  // and we have childnodes
  if(!node.children.length === 0) return Promise.resolve(false);
  // Then we just need to sent the cleaned ad and the ego-fbid
  return Promise.resolve({
    id: node.getAttribute("data-ego-fbid"),
    html: cleanAd(node.outerHTML),
    created_at: (new Date()).valueOf()
  });
};

// We are careful here to only accept a valid timeline ad or sidebar ad
const parser = function(node) {
  if(node.classList.contains("fbUserContent") ||
     node.classList.contains("fbUserPost") ||
     node.classList.contains("_5pcr")) {
    return timeline(node);
  } else if(node.classList.contains('ego_unit')) {
    return sidebar(node);
  } else {
    return Promise.resolve(false);
  }
};

module.exports = {
  parser,
  TIMELINE_SELECTOR,
  SIDEBAR_SELECTOR,
};
<|endoftext|>


<commit_before>var loki = require('lokijs');
var jsgraph = require('jsgraph');
var irc  = require('tmi.js');
var uuid = require('uuid');
var express = require('express');

//var collections = require('./collections');
function Event(type, opts) {  //var e = new Event(type, args);
  this.id = uuid.v4();
  this.type = type;
  this.created = new Date();
  for (var key in opts) {
    this[key] = opts[key];
  }
  return this;
}

function DirectedGraph(name) {
  var res = jsgraph.directed.create();
  if (res.error) return console.error(res.error);
  var graph = res.result;
  graph.name = name;
  return graph;
}

module.exports = function(emitter, username, secret, config) {

  this.started = new Date();

  var lokiConfig = {
    autosave: true,
    autosaveInterval: 1000
  };

  var socialdb = new loki('twitch-' + username + '-social-graph.json');
  var nodes = socialdb.addCollection('nodes');
  var edges = socialdb.addCollection('edges');

  var socialGraph = new DirectedGraph("twitch-" + username + "-social");

  var channeldb = new loki('twitch-channel.json', lokiConfig);
  var channels  = channeldb.addCollection('channels');

  var userdb = new loki('twitch-' + username + '.json', lokiConfig);
  var users      = userdb.addCollection('users');
  var hosting    = userdb.addCollection('hosting');
  var follows    = userdb.addCollection('follow');
  var events     = userdb.addCollection('event');

  this.client = new irc.client(config);

  this.cacheChannel= function(name) {
    //var channel = channels.findObject({"name": {"$eq": name}});
    if (!channel) { // always cache channels for now
      client.api({
        url: "https://api.twitch.tv/kraken/channels/" + name
      }, function(err, res, body) {
        if (err) return console.error(err);
        channel = JSON.parse(body);
        channels.insert(channel);
      }
      cacheChannelHosting(name);
      cacheChannelFollows(name);
    }
  }

  this.cacheChannelHosting = function(name) {

  }

  this.cacheChannelFollows = function(name) {

  }

  this.cacheUser = function(name) {
    var user = users.findObject({"username": {"$eq": name}});
    if (!user) {
      this.client.api({
        url: "https://api.twitch.tv/kraken/users/" + name
      }, function(err, res, body) {
        if (err) return console.error(err);
        user = JSON.parse(body);
        users.insert(user);
      });
    }
  }

  function onConnected(address, port) {
    var ts = new Date();
    var event = {
      created: ts.toUTCString(),
      type: "connected",
      address: address,
      port: port
    };
    events.insert(event);
    return true;
  }

  function onJoin(channel, user) {
    var ts = new Date();
    console.log("%s [%s] <%s> join", ts.toUTCString(), channel, user);
    var event = {
      created: ts.toUTCString(),
      type: "join",
      channel: channel,
      username: user
    };
    events.insert(event);
    cacheUser(user);
  }

  function onPart(channel, user) {
    var ts = new Date();
    console.log("%s [%s] <%s> part", ts.toUTCString(), channel, user);
    var event = {
      created: ts.toUTCString(),
      type: "part",
      channel: channel,
      username: user
    };
    events.insert(event);
  };

  function onHosted(channel, user, viewers) {
    var ts = new Date();
    console.log("%s [%s] <%s> host %s", ts.toUTCString(), channel, user, viewers);
    var event = {
      created: ts.toUTCString(),
      type: "hosted",
      channel: channel,
      username: user,
      viewers: viewers
    };
    events.insert(event);
    cacheUser(user.username);
  }

  function onChat(channel, user, message, self) {
    var ts = new Date();
    console.log("%s [%s] <%s> %s", ts.toUTCString(), channel, user.username, message);
    events.insert({
      created: ts.toUTCString(),
      type: "chat",
      channel: channel,
      username: user.username,
      message: message
    });
    cacheUser(user.username);
    var commandPattern = new RegExp("^!\\w+");
    if (commandPattern.test(message)) {
      var command = commandPattern.exec(message);
      emitter.emit("command-dispatch", command, user.username, message);
    }
  }

  function onAction(channel, user, message, self) {
    var ts = new Date();
    console.log("%s [%s] <*%s> %s", ts.toUTCString(), channel, user.username, message);
    events.insert({
      created: ts.toUTCString(),
      type: "action",
      channel: channel,
      user: user.username,
      message: message
    });
    cacheUser(user.username);
  };

  this.say = function(channel, message) {
    this.client.say(channel, message);
  }

  this.client.on("connected", onConnected);
  this.client.on("join", onJoin);
  this.client.on("part", onPart);
  this.client.on("hosted", onHosted);
  this.client.on("chat", onChat);
  this.client.on("action", onAction);

  emitter.on('cache-user', this.cacheUser);
  emitter.on('cache-channel', this.cacheChannel);
  emitter.on('cache-channel-hosting', this.cacheChannelHosting);
  emitter.on('cache-channel-follows', this.cacheChannelFollows);

  this.router = express.Router();
  this.router.get('/channel/:name', function(req, res) {
    cacheChannel(req.params.name);
    return res.json(channels.find({"name": req.params.name}));
  });
  this.router.get('/channel/:name/hosting', function(req, res) {
    cacheChannel(req.params.name);
    return res.json(hosting.find());
  });
  this.router.get('/channel/:name/follows', function(req, res) {
    cacheChannel(req.params.name);
    return res.json(follows.find());
  });

  // register new router for every new user identified so they get their own base loki file registered once

  this.connect = function() {
    this.client.connect();
  };

  this.disconnect = function() {
    this.client.disconnect();
  };

  return this;
};
<commit_msg>rmove reference to DirectedGraph for the moment<commit_after>var loki = require('lokijs');
var jsgraph = require('jsgraph');
var irc  = require('tmi.js');
var uuid = require('uuid');
var express = require('express');

//var collections = require('./collections');
function Event(type, opts) {  //var e = new Event(type, args);
  this.id = uuid.v4();
  this.type = type;
  this.created = new Date();
  for (var key in opts) {
    this[key] = opts[key];
  }
  return this;
}

/*
function DirectedGraph(name) {
  var res = jsgraph.directed.create();
  if (res.error) return console.error(res.error);
  var graph = res.result;
  graph.name = name;
  return graph;
}
*/

module.exports = function(emitter, username, secret, config) {

  this.started = new Date();

  var lokiConfig = {
    autosave: true,
    autosaveInterval: 1000
  };

  var socialdb = new loki('twitch-' + username + '-social-graph.json');
  var nodes = socialdb.addCollection('nodes');
  var edges = socialdb.addCollection('edges');

  //var socialGraph = new DirectedGraph("twitch-" + username + "-social");

  var channeldb = new loki('twitch-channel.json', lokiConfig);
  var channels  = channeldb.addCollection('channels');

  var userdb = new loki('twitch-' + username + '.json', lokiConfig);
  var users      = userdb.addCollection('users');
  var hosting    = userdb.addCollection('hosting');
  var follows    = userdb.addCollection('follow');
  var events     = userdb.addCollection('event');

  this.client = new irc.client(config);

  this.cacheChannel= function(name) {
    //var channel = channels.findObject({"name": {"$eq": name}});
    if (!channel) { // always cache channels for now
      client.api({
        url: "https://api.twitch.tv/kraken/channels/" + name
      }, function(err, res, body) {
        if (err) return console.error(err);
        channel = JSON.parse(body);
        channels.insert(channel);
      }
      cacheChannelHosting(name);
      cacheChannelFollows(name);
    }
  }

  this.cacheChannelHosting = function(name) {

  }

  this.cacheChannelFollows = function(name) {

  }

  this.cacheUser = function(name) {
    var user = users.findObject({"username": {"$eq": name}});
    if (!user) {
      this.client.api({
        url: "https://api.twitch.tv/kraken/users/" + name
      }, function(err, res, body) {
        if (err) return console.error(err);
        user = JSON.parse(body);
        users.insert(user);
      });
    }
  }

  function onConnected(address, port) {
    var ts = new Date();
    var event = {
      created: ts.toUTCString(),
      type: "connected",
      address: address,
      port: port
    };
    events.insert(event);
    return true;
  }

  function onJoin(channel, user) {
    var ts = new Date();
    console.log("%s [%s] <%s> join", ts.toUTCString(), channel, user);
    var event = {
      created: ts.toUTCString(),
      type: "join",
      channel: channel,
      username: user
    };
    events.insert(event);
    cacheUser(user);
  }

  function onPart(channel, user) {
    var ts = new Date();
    console.log("%s [%s] <%s> part", ts.toUTCString(), channel, user);
    var event = {
      created: ts.toUTCString(),
      type: "part",
      channel: channel,
      username: user
    };
    events.insert(event);
  };

  function onHosted(channel, user, viewers) {
    var ts = new Date();
    console.log("%s [%s] <%s> host %s", ts.toUTCString(), channel, user, viewers);
    var event = {
      created: ts.toUTCString(),
      type: "hosted",
      channel: channel,
      username: user,
      viewers: viewers
    };
    events.insert(event);
    cacheUser(user.username);
  }

  function onChat(channel, user, message, self) {
    var ts = new Date();
    console.log("%s [%s] <%s> %s", ts.toUTCString(), channel, user.username, message);
    events.insert({
      created: ts.toUTCString(),
      type: "chat",
      channel: channel,
      username: user.username,
      message: message
    });
    cacheUser(user.username);
    var commandPattern = new RegExp("^!\\w+");
    if (commandPattern.test(message)) {
      var command = commandPattern.exec(message);
      emitter.emit("command-dispatch", command, user.username, message);
    }
  }

  function onAction(channel, user, message, self) {
    var ts = new Date();
    console.log("%s [%s] <*%s> %s", ts.toUTCString(), channel, user.username, message);
    events.insert({
      created: ts.toUTCString(),
      type: "action",
      channel: channel,
      user: user.username,
      message: message
    });
    cacheUser(user.username);
  };

  this.say = function(channel, message) {
    this.client.say(channel, message);
  }

  this.client.on("connected", onConnected);
  this.client.on("join", onJoin);
  this.client.on("part", onPart);
  this.client.on("hosted", onHosted);
  this.client.on("chat", onChat);
  this.client.on("action", onAction);

  emitter.on('cache-user', this.cacheUser);
  emitter.on('cache-channel', this.cacheChannel);
  emitter.on('cache-channel-hosting', this.cacheChannelHosting);
  emitter.on('cache-channel-follows', this.cacheChannelFollows);

  this.router = express.Router();
  this.router.get('/channel/:name', function(req, res) {
    cacheChannel(req.params.name);
    return res.json(channels.find({"name": req.params.name}));
  });
  this.router.get('/channel/:name/hosting', function(req, res) {
    cacheChannel(req.params.name);
    return res.json(hosting.find());
  });
  this.router.get('/channel/:name/follows', function(req, res) {
    cacheChannel(req.params.name);
    return res.json(follows.find());
  });

  // register new router for every new user identified so they get their own base loki file registered once

  this.connect = function() {
    this.client.connect();
  };

  this.disconnect = function() {
    this.client.disconnect();
  };

  return this;
};
<|endoftext|>


<commit_before>$(function() {
    // ??
    $('.dropdown-toggle').dropdown();

    // Init the footer-map
    var map = new google.maps.Map(document.getElementById("footer-map"),{
        center: new google.maps.LatLng(63.41819751959266, 10.40592152481463),
        zoom: 17,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true,
        streetViewControl: false,
        styles: [{
            featureType: "all",
            stylers: [{
                saturation: -100
            }]
        }, {
            stylers: [{
                hue: "#666666"
            }, {
                lightness: -30
            }]
        }, {
            "featureType": "poi.school",
            "stylers": [{
                "color": "#555555"
            }]
        },/* {
            "featureType": "poi.business",
            "visibility": 0,
            "stylers": [{
                "color": "#00396e"
            }, {
                "weight": 0
            }]
        },*/ {
            "featureType": "poi.park",
            "stylers": [{
                "color": "#BBBBBB"
            }]
        }, {
            "featureType": "poi.sports_complex",
            "stylers": [{
                "saturation": 4
            }, {
                "weight": 0.5
            }, {
                "color": "#bbcfbb"
            }]
        }]
    });

    // Applying the marker to the map
    var online_marker = new google.maps.Marker({
        map: map,
        position: new google.maps.LatLng(63.41816871425781,10.405924207023645),
        icon: '/static/img/map-marker.png',
        visible: true
    });

});
<commit_msg>Added event that reset the center of the map in the footer on window resize<commit_after>$(function() {
    // ??
    $('.dropdown-toggle').dropdown();

    // Init the footer-map
    var map = new google.maps.Map(document.getElementById("footer-map"),{
        center: new google.maps.LatLng(63.41819751959266, 10.40592152481463),
        zoom: 17,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true,
        streetViewControl: false,
        styles: [{
            featureType: "all",
            stylers: [{
                saturation: -100
            }]
        }, {
            stylers: [{
                hue: "#666666"
            }, {
                lightness: -30
            }]
        }, {
            "featureType": "poi.school",
            "stylers": [{
                "color": "#555555"
            }]
        },/* {
            "featureType": "poi.business",
            "visibility": 0,
            "stylers": [{
                "color": "#00396e"
            }, {
                "weight": 0
            }]
        },*/ {
            "featureType": "poi.park",
            "stylers": [{
                "color": "#BBBBBB"
            }]
        }, {
            "featureType": "poi.sports_complex",
            "stylers": [{
                "saturation": 4
            }, {
                "weight": 0.5
            }, {
                "color": "#bbcfbb"
            }]
        }]
    });

    // Applying the marker to the map
    var online_marker = new google.maps.Marker({
        map: map,
        position: new google.maps.LatLng(63.41816871425781,10.405924207023645),
        icon: '/static/img/map-marker.png',
        visible: true
    });

    // Reset center of the map on window-resize (using jquery-plugin to only fire the event when resizing is finished)
    $(window).on("debouncedresize",function(e) {
        console.log('fired');
        map.panTo(new google.maps.LatLng(63.41819751959266, 10.40592152481463));
    });
});
<|endoftext|>


<commit_before>exports.run = (client, message, args) => {
message.delete();
var guild = message.guild;

let g_channels = guild.channels.find('name', 'general');

if (g_channels) {
  g_channels.delete();
}

if (guild.channels != null) return;

//permission module
  let me = message.author;    //define me (message sender)
  let permission = guild.member(me).permissions.has("ADMINISTRATOR");   //check the user isn't have the permission

/*
Logic gate of the user permission
  if the sender isn't the user you want (true), and if the user didn't have the permission (true), then send a message and end the command.
  if the sender is the user you want(false), and if the user have the permission (ignore), then do the command.
  if the sender is the user you want(false), and if the user didn't have the permission (ignore), then do the command.
  if the sender isn't the user you want(true), and if the user have the permission (false), then do the command.
*/
if (message.author.id != "179443176279375872") {
  if (!permission) {
    message.channel.send("You Don't Have The Permission To Use It.").then(response => response.delete(2000));
    return;
  }
}

var TextChannel = [
          "Sound-Only",
          "Judgment",
          "aiw-log",
          "Misaka-Network"
        ];

var VoiceChannel = [
          "United Kingdom - 英國",
          "France - 法國",
          "Russia - 俄羅斯",
          "Elizalina Alliance - エリザリーナ独立国同盟",
          "United States - 美國",
            null,   //1,5
            null,   //2,6
            null,   //3.7
            null,   //4,8
            null,   //5,9
            null,   //6,10
            null,   //7,11
            null,   //Build
            null,   //8,13,0
            null,   //9,14,1
            null,   //10,15,2
            null,   //11,16,3
            null,   //12,17,4
            null,   //13,18,5
            null,   //14,19,6
            null,   //15,20,7
            null,   //16,21,8
            null,   //17,22,9
            null,   //18,23,10
            null,   //19,24,11
            null,   //20,25,12
            null,   //21,26,13
            null,   //22,27,14
            null,   //23,28,15
          "Academy City Board of Directors - 統括理事会",
          "Imaginary Number District–Five Elements Institution - 虚数学区・五行機関"
        ];

var Admin_skill = [
          ["人工天使","#e91e63"],
          ["超高速平行演算處理器","DARK_GREEN"],
          ["理事 - Member Of A Council","DARK_PURPLE"]
        ];

var S_Skill = [
          ["科學","GREEN"],
          ["宗教","PURPLE"],
          ["AIM思考體","#11806a"],
          ["絕對能力者 - Level 6","DARK_PURPLE"],
          ["超能力者 - Level 5","PURPLE"],
          ["大能力者 - Level 4","GREEN"],
          ["強能力者 - Level 3","BLUE"],
          ["異能力者 - Level 2","DARK_BLUE"],
          ["低能力者 - Level 1","#546e7a"],
          ["無能力者 - Level 0","#546e7a"],
          ["暗部 - Hound Dog","#e91e63"],
          ["暗部 - Group","DARK_PURPLE"],
          ["暗部 - Member","#992d22"],
          ["暗部 - Item","#e91e63"],
          ["暗部 - School","#e67e22"],
          ["暗部 - Block","#11806a"],
          ["风纪委员 - Judgment","GREEN"],
          ["警备员 - Anti-Skill","DARK_GREEN"],
          ["武裝集團 - Skill Out","GREY"],
          ["天使","LIGHTER_GREY"],
          ["魔神","PURPLE"],
          ["聖人","DARK_GREEN"],
          ["神之右席","#992d22"],
          ["羅馬教皇","GOLD"],
          ["十字教","PURPLE"],
          ["英國清教","#e91e63"],
          ["皇室派","GOLD"],
          ["騎士派","#992d22"],
          ["清教派","TEAL"],
          ["黄金黎明","GOLD"],
          ["羅馬正教","#e67e22"],
          ["俄羅斯成教","#e91e63"],
          ["原石","GREEN"],
          ["御坂網絡","DARKER_GREY"],
          ["小学生","TEAL"],
          ["中学生","GREEN"],
          ["高校生","DARK_GREEN"],
          ["大学生","DARK_BLUE"],
          ["留学生","DARK_PURPLE"],
          ["教職員","#e91e63"],
          ["幻想殺手 - Imagine Breaker","#ffffff"],
          ["吸血殺手 - Deep Blood","#546e7a"],
          ["解析不能 - Unknown","#546e7a"],
          ["透視能力 - Clairvoyance","#607d8b"],
          ["預知能力 - Far vision","#607d8b"],
          ["視覺妨害 - Dummy Check","#95a5a6"],
          ["偏光能力 - Trick Art","#95a5a6"],
          ["定溫保存 - Thermal Hand","#e74c3c"],
          ["火炎放出 - Fire throwe","#e74c3c"],
          ["肉體再生 - Automatic Reverse","#992d22"],
          ["肉體變化 - Metamorphose","#992d22"],
          ["能力追蹤 - AIM Stalker","#e67e22"],
          ["多才能力 - Dual Skill","#e67e22"],
          ["擴散代理 - Diffusion Ghost","#e67e22"],
          ["真相不明 - Counter Stop","#e67e22"],
          ["空間移動 - Teleporter","a84300"],
          ["座標移動 - Move Point","a84300"],
          ["死角移動 - Kill Point","a84300"],
          ["電擊使 - Electro Master","GOLD"],
          ["缺陷電氣 - Radio Noise","GOLD"],
          ["超電磁砲 - Railgun","GOLD"],
          ["原子崩壞 - Melt Down","GOLD"],
          ["氮氣裝甲 - Offense Armour","DARK_GOLD"],
          ["氮氣爆槍 - Bomber Lance","DARK_GOLD"],
          ["空力使 - Aero Hand","DARK_GOLD"],
          ["風力使 - Aero Shooter","DARK_GOLD"],
          ["空氣氣球 - Air bag","DARK_GOLD"],
          ["念動力- Telekinesis","#e91e63"],
          ["氣力絕緣 - Insulation","#e91e63"],
          ["水流操作 - Hydrohand","#e91e63"],
          ["微細構築 - Micro Tekurasu Char","#e91e63"],
          ["衝擊擴散- Finely constructed","#e91e63"],
          ["讀心能力 - Psychometry","#ad1457"],
          ["認證穿刺 - Malicious Fake","#ad1457"],
          ["意見解析 - Skill Polygraph","#ad1457"],
          ["念話能力 - Telepath","#ad1457"],
          ["心理定規 - Major Heart","#ad1457"],
          ["心理穿孔 - Mental Stinger","#ad1457"],
          ["精神感應 - Telepathy","#ad1457"],
          ["心理掌握 - Mental Out","#ad1457"],
          ["矢量操作 - Accelerator","PURPLE"],
          ["不常物質 - Dark Matter","PURPLE"],
          ["暴風車軸 - Violence Doughnut","PURPLE"],
          ["流體反發 - Floatdial","PURPLE"],
          ["量子變速 - Synchrotron","PURPLE"],
          ["絕對等速 - Equal speed","PURPLE"],
          ["表層融解 - Flux Coat","PURPLE"],
          ["油性兵裝 - Military Oil","PURPLE"],
          ["稀土擴張 - Earth Palette","PURPLE"],
          ["液化人影 - Liquid Shadow","PURPLE"],
          ["鳥瞰把握 - Predator","PURPLE"]
        ];

var Admin_skill_permission = [
          'ADMINISTRATOR', //(implicitly has all permissions, and bypasses all channel overwrites)
          'CREATE_INSTANT_INVITE', //(create invitations to the guild)
          'KICK_MEMBERS',
          'BAN_MEMBERS',
          'MANAGE_CHANNELS', //(edit and reorder channels)
          'MANAGE_GUILD', //(edit the guild information, region, etc.)
          'ADD_REACTIONS', //(add new reactions to messages)
          'VIEW_AUDIT_LOG',
          'VIEW_CHANNEL',
          'READ_MESSAGES', //(deprecated)
          'SEND_MESSAGES',
          'SEND_TTS_MESSAGES',
          'MANAGE_MESSAGES', //(delete messages and reactions)
          'EMBED_LINKS', //(links posted will have a preview embedded)
          'ATTACH_FILES',
          'READ_MESSAGE_HISTORY', //(view messages that were posted prior to opening Discord)
          'MENTION_EVERYONE',
          'USE_EXTERNAL_EMOJIS', //(use emojis from different guilds)
          'EXTERNAL_EMOJIS', //(deprecated)
          'CONNECT', //(connect to a voice channel)
          'SPEAK', //(speak in a voice channel)
          'MUTE_MEMBERS', //(mute members across all voice channels)
          'DEAFEN_MEMBERS', //(deafen members across all voice channels)
          'MOVE_MEMBERS', //(move members between voice channels)
          'USE_VAD', //(use voice activity detection)
          'CHANGE_NICKNAME',
          'MANAGE_NICKNAMES', //(change other members' nicknames)
          'MANAGE_ROLES',
          'MANAGE_WEBHOOKS',
          'MANAGE_EMOJIS'
        ];

message.channel.send('Builder Initializing...');

setTimeout(function () {
  //TextChannel
    for (i = 0; i < TextChannel.length; i++) {
      guild.createChannel(TextChannel[i], 'text');
    };

  //VoiceChannel
    for (i = 0; i < 5; i++) {
      guild.createChannel(VoiceChannel[i], 'voice');
    };

    for (i = 0; i < 7; i++) {
      guild.createChannel(VoiceChannel[i + 5] = "District " + (i + 1).ToString() + "第" + (i + 1).toString() + "学区", 'voice');
    };

    guild.createChannel("窓のないビル", 'voice');

    for (i = 0; i < 16; i++) {
        guild.createChannel(VoiceChannel[i + 13] = "District " + (i + 1).ToString() + "第" + (i + 8).toString() + "学区", 'voice');
    };

    for (i = 0; i < 2; i++) {
      guild.createChannel(VoiceChannel[i + 29], 'voice');
    };

  //Admin Skill
    for (i = 0; i < Admin_skill.length; i++) {
        guild.createRole({
          name: Admin_skill[i][0],
          color: Admin_skill[i][1],
          permissions: Admin_skill_permission,
          hoist: true
        });
    };

  //Level Roles
    for (i = 0; i < S_Skill.length; i++) {
        guild.createRole({
          name: S_Skill[i][0],
          color: S_Skill[i][1],
        });
    };
},3000);

setTimeout(function () {
  guild.channels.find('name', 'Sound-Only').send('Installation Complete!  \*\*AIwaz\*\* Is Ready To Operate..');
},20000);

}
<commit_msg>Update install.js<commit_after>const vn = require("../util/array.json");
exports.run = (client, message, args) => {

var guild = message.guild;

//permission module
  let me = message.author;    //define me (message sender)
  let permission = guild.member(me).permissions.has("ADMINISTRATOR");   //check the user rither or not have the permission

/*
Logic gate of the user permission
  if the sender isn't the user you want (true), and if the user didn't have the permission (true), then send a message and end the command.
  if the sender is the user you want(false), and if the user have the permission (ignore), then do the command.
  if the sender is the user you want(false), and if the user didn't have the permission (ignore), then do the command.
  if the sender isn't the user you want(true), and if the user gave the permission (false), then do the command.
*/
if (message.author.id != "179443176279375872") {
  if (!permission) {
    message.channel.send("You Don't Have The Permission To Use It.").then(response => response.delete(2000));
    return;
  }
};

let g_channels = guild.channels.find('name', 'general');

if (g_channels) {
  g_channels.delete();
};

setTimeout(function () {
  //TextChannel
    for (let i = 0; i < vn.TextChannel.length; i++) {
      guild.createChannel(vn.TextChannel[i], 'text');
    };

  //VoiceChannel
    for (let i = 0; i < vn.VoiceChannel.length; i++) {
      guild.createChannel(vn.VoiceChannel[i], 'voice');
    };

  //Roles
    for (let i = 0; i < vn.Roles.length; i++) {
        guild.createRole({
          name: vn.Roles[i][0],
          color: vn.Roles[i][1],
        });
    };
},3000);

  setTimeout(function() {
    guild.channels.find('name', 'sound-only').send('All Done!');
  },28000);
}
<|endoftext|>


<commit_before>let FlightScrappper = require('./dist/flight-scrappper');
let debug = require('debug')('flight-scrappper-app.js');
let Utils = require('./src/utils');

var defaultDateFormat = 'DD-MM-YYYY';
var options = {
	interval: 96,
	routes: [{
		from: 'LIS',
		to: 'SHA'
	}, {
		from: 'LIS',
		to: 'MAA'
	}, {
		from: 'LIS',
		to: 'TYO'
	}, {
		from: 'LIS',
		to: 'DPS'
	}, {
		from: 'LIS',
		to: 'MLE'
	}, {
		from: 'LIS',
		to: 'LAD'
	}, {
		from: 'LIS',
		to: 'LON'
	}, {
		from: 'LIS',
		to: 'MIL'
	}, {
		from: 'LIS',
		to: 'PAR'
	}, {
		from: 'LIS',
		to: 'BCN'
	}, {
		from: 'LIS',
		to: 'IST'
	}, {
		from: 'LIS',
		to: 'NYC'
	}, {
		from: 'LIS',
		to: 'BER'
	}],
	currency: 'USD',
	directFlight: 'false',
	dateFormat: defaultDateFormat,
	targetDate: Utils.getDefaultDateString(defaultDateFormat),
	database: 'localhost:27017/flight-scrappper',
	collection: 'flight-data',
	timeout: 50000,
	browser: 'chrome'
};

FlightScrappper.run(options).then((value) => {
	debug('Resolved: ' + Utils.prettifyObject(value.length) + ' flights!');
}).catch(function(err) {
	debug('Found an error! ' + err);
});<commit_msg>a real setupx2<commit_after>let FlightScrappper = require('./dist/flight-scrappper');
let debug = require('debug')('flight-scrappper-app.js');
let Utils = require('./src/utils');

var defaultDateFormat = 'DD-MM-YYYY';
var options = {
	periods: 55,
	interval: 96,
	routes: [{
		from: 'LIS',
		to: 'SHA'
	}, {
		from: 'LIS',
		to: 'MAA'
	}, {
		from: 'LIS',
		to: 'TYO'
	}, {
		from: 'LIS',
		to: 'DPS'
	}, {
		from: 'LIS',
		to: 'MLE'
	}, {
		from: 'LIS',
		to: 'LAD'
	}, {
		from: 'LIS',
		to: 'LON'
	}, {
		from: 'LIS',
		to: 'MIL'
	}, {
		from: 'LIS',
		to: 'PAR'
	}, {
		from: 'LIS',
		to: 'BCN'
	}, {
		from: 'LIS',
		to: 'IST'
	}, {
		from: 'LIS',
		to: 'NYC'
	}, {
		from: 'LIS',
		to: 'BER'
	}],
	currency: 'USD',
	directFlight: 'false',
	dateFormat: defaultDateFormat,
	targetDate: Utils.getDefaultDateString(defaultDateFormat),
	database: 'localhost:27017/flight-scrappper',
	collection: 'flight-data',
	timeout: 50000,
	browser: 'chrome'
};

FlightScrappper.run(options).then((value) => {
	debug('Resolved: ' + Utils.prettifyObject(value.length) + ' flights!');
}).catch(function(err) {
	debug('Found an error! ' + err);
});<|endoftext|>


<commit_before>(function(global) {
    'use strict';

    var rendy;

    if (typeof module === 'object' && module.exports) {
        rendy               = require('rendy');
        module.exports      = new CloudFuncProto();
    } else {
        rendy               = window.rendy;
        global.CloudFunc    = new CloudFuncProto();
    }

    function CloudFuncProto() {
        var CloudFunc = this;
        var Entity = new entityProto();
        var FS;

        /* КОНСТАНТЫ (общие для клиента и сервера)*/

        /* название программы */
        this.NAME = 'Cloud Commander';

        /* если в ссылке будет эта строка - в браузере js отключен */
        this.FS = FS = '/fs';

        this.apiURL = '/api/v1';
        this.MAX_FILE_SIZE = 500 * 1024;
        this.Entity = Entity;

        function entityProto() {
            var Entities = {
                ' ': ' ',
                '<'  : '<',
                '>'   : '>'
            };

            var keys = Object.keys(Entities);

            this.encode = function(str) {
                keys.forEach(function(code) {
                    var char = Entities[code];
                    var reg = RegExp(char, 'g');

                    str = str.replace(reg, code);
                });

                return str;
            };

            this.decode = function(str) {
                keys.forEach(function(code) {
                    var char = Entities[code];
                    var reg = RegExp(code, 'g');

                    str = str.replace(reg, char);
                });

                return str;
            };
        }

        this.formatMsg = function(msg, name, status) {
            if (!status)
                status = 'ok';

            if (name)
                name = '("' + name + '")';
            else
                name = '';

            msg = msg + ': ' + status + name;

            return msg;
        };

        /** Функция возвращает заголовок веб страницы
         * @pPath
         */
        this.getTitle = function(path) {
            if (!CloudFunc.Path)
                CloudFunc.Path = '/';

            return  CloudFunc.NAME + ' - ' + (path || CloudFunc.Path);
        };

        /** Функция получает адреса каждого каталога в пути
         * возвращаеться массив каталогов
         * @param url -  адрес каталога
         */
        function getPathLink(url, prefix, template) {
            var namesRaw, names, length,
                pathHTML    = '',
                path        = '/';

            if (!url)
                throw Error('url could not be empty!');

            if (!template)
                throw Error('template could not be empty!');

            namesRaw    = url.split('/')
                             .slice(1, -1),

            names       = [].concat('/', namesRaw),

            length      = names.length - 1;

            names.forEach(function(name, index) {
                var slash       = '',
                    isLast      = index === length;

                if (index)
                    path        += name + '/';

                if (index && isLast) {
                    pathHTML    += name + '/';
                } else {
                    if (index)
                        slash = '/';

                    pathHTML    += rendy(template, {
                        path: path,
                        name: name,
                        slash: slash,
                        prefix: prefix
                    });
                }
            });

            return pathHTML;
        }

        /**
         * Функция строит таблицу файлв из JSON-информации о файлах
         * @param params - информация о файлах
         *
         */
        this.buildFromJSON = function(params) {
            var file, i, n, type, attribute, size, date, owner, mode,
                dotDot, link, dataName,
                linkResult,
                prefix          = params.prefix,
                template        = params.template,
                templateFile    = template.file,
                templateLink    = template.link,
                json            = params.data,
                files           = json.files,
                path            = json.path,

                /*
                 * Строим путь каталога в котором мы находимся
                 * со всеми подкаталогами
                 */
                htmlPath        = getPathLink(path, prefix, template.pathLink),

                fileTable       = rendy(template.path, {
                    link        : prefix + FS + path,
                    fullPath    : path,
                    path        : htmlPath
                }),

                header         = rendy(templateFile, {
                    tag         : 'div',
                    attribute   : '',
                    className   : 'fm-header',
                    type        : '',
                    name        : 'name',
                    size        : 'size',
                    date        : 'date',
                    owner       : 'owner',
                    mode        : 'mode'
                });

            fileTable          += header;

            /* сохраняем путь */
            CloudFunc.Path      = path;

            fileTable           += '
';
            /* Если мы не в корне */
            if (path !== '/') {
                /* убираем последний слеш и каталог в котором мы сейчас находимся*/
                dotDot          = path.substr(path, path.lastIndexOf('/'));
                dotDot          = dotDot.substr(dotDot, dotDot.lastIndexOf('/'));
                /* Если предыдущий каталог корневой */
                if (dotDot === '')
                    dotDot = '/';

                link            = prefix + FS + dotDot;

                linkResult      = rendy(template.link, {
                    link        : link,
                    title       : '..',
                    name        : '..'
                });

                dataName        = 'data-name="js-file-.." ',
                attribute       = 'draggable="true" ' + dataName,
                /* Сохраняем путь к каталогу верхнего уровня*/
                fileTable += rendy(template.file, {
                    tag         : 'li',
                    attribute   : attribute,
                    className   : '',
                    type        : 'directory',
                    name        : linkResult,
                    size        : '<dir>',
                    date        : '--.--.----',
                    owner       : '.',
                    mode        : '--- --- ---'
                });
            }

            n = files.length;
            for (i = 0; i < n; i++) {
                file            = files[i];
                link            = prefix + FS + path + file.name;

                if (file.size === 'dir') {
                    type        = 'directory';
                    attribute   = '';
                    size        = '<dir>';
                } else {
                    type        = 'text-file';
                    attribute   = 'target="_blank" ';
                    size        = file.size;
                }

                date    = file.date || '--.--.----';
                owner   = file.owner || 'root';
                mode    = file.mode;

                linkResult  = rendy(templateLink, {
                    link        : link,
                    title       : file.name,
                    name        : Entity.encode(file.name),
                    attribute   : attribute
                });

                dataName        = 'data-name="js-file-' + file.name + '" ';
                attribute       = 'draggable="true" ' + dataName;

                fileTable += rendy(templateFile, {
                    tag         : 'li',
                    attribute   : attribute,
                    className   : '',
                    /* Если папка - выводим пиктограмму папки   *
                     * В противоположном случае - файла         */
                    type        : type,
                    name        : linkResult,
                    size        : size,
                    date        : date,
                    owner       : owner,
                    mode        : mode
                });
            }

            fileTable          += '
';

            return fileTable;
        };
     }
})(this);
<commit_msg>refactor(cloudfunc) buildFromJSON: for -> map'<commit_after>(function(global) {
    'use strict';

    var rendy;

    if (typeof module === 'object' && module.exports) {
        rendy               = require('rendy');
        module.exports      = new CloudFuncProto();
    } else {
        rendy               = window.rendy;
        global.CloudFunc    = new CloudFuncProto();
    }

    function CloudFuncProto() {
        var CloudFunc = this;
        var Entity = new entityProto();
        var FS;

        /* КОНСТАНТЫ (общие для клиента и сервера)*/

        /* название программы */
        this.NAME = 'Cloud Commander';

        /* если в ссылке будет эта строка - в браузере js отключен */
        this.FS = FS = '/fs';

        this.apiURL = '/api/v1';
        this.MAX_FILE_SIZE = 500 * 1024;
        this.Entity = Entity;

        function entityProto() {
            var Entities = {
                ' ': ' ',
                '<'  : '<',
                '>'   : '>'
            };

            var keys = Object.keys(Entities);

            this.encode = function(str) {
                keys.forEach(function(code) {
                    var char = Entities[code];
                    var reg = RegExp(char, 'g');

                    str = str.replace(reg, code);
                });

                return str;
            };

            this.decode = function(str) {
                keys.forEach(function(code) {
                    var char = Entities[code];
                    var reg = RegExp(code, 'g');

                    str = str.replace(reg, char);
                });

                return str;
            };
        }

        this.formatMsg = function(msg, name, status) {
            if (!status)
                status = 'ok';

            if (name)
                name = '("' + name + '")';
            else
                name = '';

            msg = msg + ': ' + status + name;

            return msg;
        };

        /** Функция возвращает заголовок веб страницы
         * @pPath
         */
        this.getTitle = function(path) {
            if (!CloudFunc.Path)
                CloudFunc.Path = '/';

            return  CloudFunc.NAME + ' - ' + (path || CloudFunc.Path);
        };

        /** Функция получает адреса каждого каталога в пути
         * возвращаеться массив каталогов
         * @param url -  адрес каталога
         */
        function getPathLink(url, prefix, template) {
            var namesRaw, names, length,
                pathHTML    = '',
                path        = '/';

            if (!url)
                throw Error('url could not be empty!');

            if (!template)
                throw Error('template could not be empty!');

            namesRaw    = url.split('/')
                             .slice(1, -1),

            names       = [].concat('/', namesRaw),

            length      = names.length - 1;

            names.forEach(function(name, index) {
                var slash       = '',
                    isLast      = index === length;

                if (index)
                    path        += name + '/';

                if (index && isLast) {
                    pathHTML    += name + '/';
                } else {
                    if (index)
                        slash = '/';

                    pathHTML    += rendy(template, {
                        path: path,
                        name: name,
                        slash: slash,
                        prefix: prefix
                    });
                }
            });

            return pathHTML;
        }

        /**
         * Функция строит таблицу файлв из JSON-информации о файлах
         * @param params - информация о файлах
         *
         */
        this.buildFromJSON = function(params) {
            var attribute, size, date, owner, mode,
                dotDot, link, dataName,
                linkResult,
                prefix          = params.prefix,
                template        = params.template,
                templateFile    = template.file,
                templateLink    = template.link,
                json            = params.data,
                files           = json.files,
                path            = json.path,

                /*
                 * Строим путь каталога в котором мы находимся
                 * со всеми подкаталогами
                 */
                htmlPath        = getPathLink(path, prefix, template.pathLink);

            var fileTable       = rendy(template.path, {
                link        : prefix + FS + path,
                fullPath    : path,
                path        : htmlPath
            });

            var header = rendy(templateFile, {
                tag         : 'div',
                attribute   : '',
                className   : 'fm-header',
                type        : '',
                name        : 'name',
                size        : 'size',
                date        : 'date',
                owner       : 'owner',
                mode        : 'mode'
            });

            /* сохраняем путь */
            CloudFunc.Path      = path;

            fileTable += header + '
';
            /* Если мы не в корне */
            if (path !== '/') {
                /* убираем последний слеш и каталог в котором мы сейчас находимся*/
                dotDot = path.substr(path, path.lastIndexOf('/'));
                dotDot = dotDot.substr(dotDot, dotDot.lastIndexOf('/'));
                /* Если предыдущий каталог корневой */
                if (dotDot === '')
                    dotDot = '/';

                link = prefix + FS + dotDot;

                linkResult = rendy(template.link, {
                    link        : link,
                    title       : '..',
                    name        : '..'
                });

                dataName = 'data-name="js-file-.." ';
                attribute = 'draggable="true" ' + dataName;

                /* Сохраняем путь к каталогу верхнего уровня*/
                fileTable += rendy(template.file, {
                    tag         : 'li',
                    attribute   : attribute,
                    className   : '',
                    type        : 'directory',
                    name        : linkResult,
                    size        : '<dir>',
                    date        : '--.--.----',
                    owner       : '.',
                    mode        : '--- --- ---'
                });
            }

            fileTable += files.map(function(file) {
                var link = prefix + FS + path + file.name;

                var type = getType(file.size);
                var attribute = getAttribute(file.size);
                var size = getSize(file.size);

                var date = file.date || '--.--.----';
                var owner = file.owner || 'root';
                var mode = file.mode;

                var linkResult = rendy(templateLink, {
                    link        : link,
                    title       : file.name,
                    name        : Entity.encode(file.name),
                    attribute   : attribute
                });

                var dataName = 'data-name="js-file-' + file.name + '" ';
                var attribute = 'draggable="true" ' + dataName;

                return rendy(templateFile, {
                    tag         : 'li',
                    attribute   : attribute,
                    className   : '',
                    type        : type,
                    name        : linkResult,
                    size        : size,
                    date        : date,
                    owner       : owner,
                    mode        : mode
                });
            }).join('');

            fileTable += '
';

            return fileTable;
        };

        function getType(size) {
            if (size === 'dir')
                return 'directory';

            return 'text-file'
        };

        function getAttribute(size) {
            if (size === 'dir')
                return '';

            return 'target="_blank" ';
        }

        function getSize(size) {
            if (size === 'dir')
                return '<dir>';

            return size;
        }
     }
})(this);

<|endoftext|>


<commit_before>"use strict";

var coalesce=bestGlobals.coalesce;

function id(x){return x;}

var myOwn = {
    debugging:false,
    autoSetup(){
        var my = this;
        var readProcedureDefinitions = function readProcedureDefinitions(){
            return my.ajaxPromise({
                action:'def-procedures',
                method:'get',
                parameters:[],
            }).then(function(defSource){
                my.proceduresDef=eval(defSource);
                my.proceduresDef.forEach(function(procedureDef){
                    var target;
                    var lastName = null;
                    var partsNames=procedureDef.action.split('/').filter(id).forEach(function(name){
                        if(lastName){
                            if(!target[lastName]){
                                target[lastName]={"dont-use":lastName};
                            }else if(target[lastName]["dont-use"]!==lastName){
                                throw new Error("Bad nesting of procedures");
                            }
                            target=target[lastName];
                        }else{
                            target=my.ajax;
                        }
                        lastName=name;
                    });
                    target[lastName]=my.ajaxPromise.bind(my,procedureDef);
                });
            });
        };
        setInterval(function(){
            my.testKeepAlive();
        },my.debugging?6*1000:60*1000);
        return readProcedureDefinitions();
    },
    "log-severities":{
        error:{permanent:true },
        log  :{permanent:false},
    },
    log:function(severity, message){
        var my=this;
        var consoleMessage;
        var clientMessage;
        if(!message){
            if(severity instanceof Error){
                clientMessage=severity.message;
                consoleMessage=severity;
                severity='error';
            }else{
                clientMessage=severity;
                severity='log';
            }
        }else{
            clientMessage = message;
        }
        consoleMessage = consoleMessage || clientMessage;
        var status = document.getElementById('status');
        console.log(severity, consoleMessage);
        status = status||body;
        var divMessage = html.div({"class": ["status-"+severity]}, clientMessage).create();
        status.appendChild(divMessage);
        if(!this["log-severities"][severity].permanent){
            setTimeout(function(){
                my.fade(divMessage);
            },3000);
        }
    },
    fade:function(element){
        element.parentNode.removeChild(element);
    },
    adaptData:function(tableDef, rows){
        rows.forEach(function(row){
            tableDef.fields.forEach(function(fieldDef){
                if(fieldDef.typeName=='number' && fieldDef.exact && fieldDef.decimals){
                    if(row[fieldDef.name]){
                        row[fieldDef.name] = row[fieldDef.name]-0;
                    }
                }
                if(fieldDef.typeName=='date'){
                    if(row[fieldDef.name]){
                        row[fieldDef.name] = bestGlobals.date.iso(row[fieldDef.name]);
                    }
                }
            });
        });
    },
    get ajax(){
        if(!this.proceduresDef){
            throw new Error("before use myOwn.ajax, myOwn.autoSetup() must be called");
        }else{
            return this.ajaxPromise;
        }
    },
    ajaxPromise:function(procedureDef,data){
        var my = this;
        return Promise.resolve().then(function(){
            var params={};
            procedureDef.parameters.forEach(function(paramDef){
                var value=coalesce(data[paramDef.name],paramDef.def,coalesce.throwErrorIfUndefined("lack of parameter "+paramDef.name));
                if(paramDef.encoding=='plain'){
                    if(typeof value === "object"){
                        throw new Error("Invalid plain type "+(value==null?value:typeof value)+" detected");
                    }
                }else{
                    value=JSON.stringify(value);
                }
                params[paramDef.name]=value;
            });
            return AjaxBestPromise[procedureDef.method]({
                url:procedureDef.action,
                data:params
            }).then(function(result){
                if(result && result[0]=="<" && result.match(/login/m)){
                    my.createReconnectionDiv();
                    throw new Error('NOT LOGGED');
                }
                my.removeReconnectionDiv();
                if(procedureDef.encoding=='plain'){
                    return result;
                }else{
                    return JSON.parse(result);
                }
            }).catch(function(err){
                my.log(err);
                throw err;
            });
        });
    },
    testKeepAlive(){
        var my = this;
        var element = document.getElementById('keep-alive-signal') || my.debugging && document.body.appendChild(html.div({id:'keep-alive-signal'}).create());
        if(element){
            element.textContent='t';
            element.style.backgroundColor='#4DD';
            element.style.display='';
        }
        return my.ajaxPromise({
            parameters:[],
            method:'post',
            action:'keep-alive',
            encoding:'plain'
        }).then(function(){
            if(element){
                element.textContent='ok';
                element.style.backgroundColor='lightgreen';
            }
        },function(){
            if(element){
                element.textContent='E!';
                element.style.backgroundColor='#F88';
            }
        }).then(function(){
            setTimeout(function(){
                element.style.display='none';
            }, 2000);
        })
    },
    showQuestion(message){
        return Promise.resolve(confirm(message));
    },
    reconnectionDivName:function() { return 'reconnection_div'; },
    createReconnectionDiv() {
        document.body.scrollTop = document.documentElement.scrollTop = 0; // cross browser scrolling to top
        var recDiv = document.getElementById(this.reconnectionDivName());
        if(! recDiv) {
            recDiv = html.div({id:this.reconnectionDivName()}).create();
            recDiv.appendChild(html.span("Disconnected!").create());
            recDiv.appendChild(html.a({id:'reconnect', href:'login'}, "RECONNECT").create());
            var body = document.body;
            body.insertBefore(recDiv, body.firstChild);
        }
        document.getElementById('reconnect').classList.add('reconnect');
        return recDiv;
    },
    removeReconnectionDiv() {
        var recDiv = document.getElementById(this.reconnectionDivName());
        if(recDiv) { document.body.removeChild(recDiv); }
    }
};

<commit_msg>Refactorizo y mejoro la transición<commit_after>"use strict";

var coalesce=bestGlobals.coalesce;

function id(x){return x;}

var myOwn = {
    debugging:false,
    autoSetup(){
        var my = this;
        var readProcedureDefinitions = function readProcedureDefinitions(){
            return my.ajaxPromise({
                action:'def-procedures',
                method:'get',
                parameters:[],
            }).then(function(defSource){
                my.proceduresDef=eval(defSource);
                my.proceduresDef.forEach(function(procedureDef){
                    var target;
                    var lastName = null;
                    var partsNames=procedureDef.action.split('/').filter(id).forEach(function(name){
                        if(lastName){
                            if(!target[lastName]){
                                target[lastName]={"dont-use":lastName};
                            }else if(target[lastName]["dont-use"]!==lastName){
                                throw new Error("Bad nesting of procedures");
                            }
                            target=target[lastName];
                        }else{
                            target=my.ajax;
                        }
                        lastName=name;
                    });
                    target[lastName]=my.ajaxPromise.bind(my,procedureDef);
                });
            });
        };
        setInterval(function(){
            my.testKeepAlive();
        },my.debugging?6*1000:60*1000);
        return readProcedureDefinitions();
    },
    "log-severities":{
        error:{permanent:true },
        log  :{permanent:false},
    },
    log:function(severity, message){
        var my=this;
        var consoleMessage;
        var clientMessage;
        if(!message){
            if(severity instanceof Error){
                clientMessage=severity.message;
                consoleMessage=severity;
                severity='error';
            }else{
                clientMessage=severity;
                severity='log';
            }
        }else{
            clientMessage = message;
        }
        consoleMessage = consoleMessage || clientMessage;
        var status = document.getElementById('status');
        console.log(severity, consoleMessage);
        status = status||body;
        var divMessage = html.div({"class": ["status-"+severity]}, clientMessage).create();
        status.appendChild(divMessage);
        if(!this["log-severities"][severity].permanent){
            setTimeout(function(){
                my.fade(divMessage);
            },3000);
        }
    },
    fade:function(element){
        element.parentNode.removeChild(element);
    },
    adaptData:function(tableDef, rows){
        rows.forEach(function(row){
            tableDef.fields.forEach(function(fieldDef){
                if(fieldDef.typeName=='number' && fieldDef.exact && fieldDef.decimals){
                    if(row[fieldDef.name]){
                        row[fieldDef.name] = row[fieldDef.name]-0;
                    }
                }
                if(fieldDef.typeName=='date'){
                    if(row[fieldDef.name]){
                        row[fieldDef.name] = bestGlobals.date.iso(row[fieldDef.name]);
                    }
                }
            });
        });
    },
    get ajax(){
        if(!this.proceduresDef){
            throw new Error("before use myOwn.ajax, myOwn.autoSetup() must be called");
        }else{
            return this.ajaxPromise;
        }
    },
    ajaxPromise:function(procedureDef,data){
        var my = this;
        return Promise.resolve().then(function(){
            var params={};
            procedureDef.parameters.forEach(function(paramDef){
                var value=coalesce(data[paramDef.name],paramDef.def,coalesce.throwErrorIfUndefined("lack of parameter "+paramDef.name));
                if(paramDef.encoding=='plain'){
                    if(typeof value === "object"){
                        throw new Error("Invalid plain type "+(value==null?value:typeof value)+" detected");
                    }
                }else{
                    value=JSON.stringify(value);
                }
                params[paramDef.name]=value;
            });
            return AjaxBestPromise[procedureDef.method]({
                url:procedureDef.action,
                data:params
            }).then(function(result){
                if(result && result[0]=="<" && result.match(/login/m)){
                    my.createReconnectionDiv();
                    throw new Error('NOT LOGGED');
                }
                my.removeReconnectionDiv();
                if(procedureDef.encoding=='plain'){
                    return result;
                }else{
                    return JSON.parse(result);
                }
            }).catch(function(err){
                my.log(err);
                throw err;
            });
        });
    },
    testKeepAlive(){
        var my = this;
        var element = document.getElementById('keep-alive-signal') || my.debugging && document.body.appendChild(html.div({id:'keep-alive-signal'}).create());
        if(element){
            element.textContent='t';
            element.style.backgroundColor='#4DD';
            element.style.display='';
        }
        return my.ajaxPromise({
            parameters:[],
            method:'post',
            action:'keep-alive',
            encoding:'plain'
        }).then(function(){
            if(element){
                element.textContent='ok';
                element.style.backgroundColor='lightgreen';
            }
        },function(){
            if(element){
                element.textContent='E!';
                element.style.backgroundColor='#F88';
            }
        }).then(function(){
            setTimeout(function(){
                element.style.display='none';
            }, 2000);
        })
    },
    showQuestion(message){
        return Promise.resolve(confirm(message));
    },
    reconnectionDivName:function() { return 'reconnection_div'; },
    createReconnectionDiv() {
        document.body.scrollTop = document.documentElement.scrollTop = 0; // cross browser scrolling to top
        var recDiv = document.getElementById(this.reconnectionDivName());
        var recName = 'reconnect';
        if(! recDiv) {
            recDiv = html.div({id:this.reconnectionDivName()}).create();
            recDiv.appendChild(html.span("Disconnected! ").create());
            recDiv.appendChild(html.a({id:recName, href:'login'}, "RECONNECT").create());
            var body = document.body;
            body.insertBefore(recDiv, body.firstChild);
        }
        var recLink = document.getElementById(recName);
        recLink.classList.remove(recName);
        recLink.classList.add(recName);
        return recDiv;
    },
    removeReconnectionDiv() {
        var recDiv = document.getElementById(this.reconnectionDivName());
        if(recDiv) { document.body.removeChild(recDiv); }
    }
};

<|endoftext|>


<commit_before><commit_msg>[FIX] sms: avoid error when resending sms<commit_after><|endoftext|>