<commit_before>/*
 Copyright 2017 Paul Zuehlcke - paul.zuehlcke.de

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/**
 * Stores state/config and manages cookies
 * Depends on cookie.js
 * @param name name of cookie stored in browser
 * @param expiryTime time to store config-cookie in browser for (days)
 * @param defaultConfig initial config options
 * @constructor
 */
function CookieConfig(name, expiryTime, defaultConfig) {
    let config;
    if (!name) {
        name = "consoleConfig";
    }
    if (!expiryTime) {
        expiryTime = 7;
    }
    getConfig();

    function resetConfig() {
        config = {};
        //copy defaultConfig to config. Beware: Nested objects are still copied as reference
        for (let p in defaultConfig) {
            if (defaultConfig.hasOwnProperty(p)) {
                config[p] = defaultConfig[p];
            }
        }
        storeConfig();
    }

    function storeConfig() {
        Cookies.set(name, config, {expires: expiryTime});
    }

    function getConfig() {
        let result = Cookies.get(name);
        if (typeof result === "undefined") {
            resetConfig();
        }
        else {
            try {
                config = JSON.parse(result);
            }
            catch (e) {
                console.error("CookieConfig: Error while parsing config from cookies");
                resetConfig();
            }
        }
        // console.debug("CookieConfig: Loaded config", config);
    }

    /**
     * Store a value in config by key
     * This triggers a cookie-write
     * @param key
     * @param value
     */
    this.store = function (key, value) {
        if (typeof key === "undefined" || typeof value === "undefined") {
            console.warn("config.store() called with invalid parameters");
        }
        else {
            config[key] = value;
            storeConfig();
        }
    };

    /**
     * Get a value from config by key
     * @param key
     * @returns {*}
     */
    this.get = function (key) {
        if (config.hasOwnProperty(key)) {
            return config[key];
        }
    };

    /**
     * Reset config to default values
     * @type {resetConfig}
     */
    this.reset = resetConfig;

    /**
     * Trigger config refresh (reload from cookies)
     * @type {getConfig}
     */
    this.load = getConfig;
}<commit_msg>CookieConfig: Use built-in json parse method<commit_after>/*
 Copyright 2017 Paul Zuehlcke - paul.zuehlcke.de

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/**
 * Stores state/config and manages cookies
 * Depends on cookie.js
 * @param name name of cookie stored in browser
 * @param expiryTime time to store config-cookie in browser for (days)
 * @param defaultConfig initial config options
 * @constructor
 */
function CookieConfig(name, expiryTime, defaultConfig) {
    let config;
    if (!name) {
        name = "consoleConfig";
    }
    if (!expiryTime) {
        expiryTime = 7;
    }
    getConfig();

    function resetConfig() {
        config = {};
        //copy defaultConfig to config. Beware: Nested objects are still copied as reference
        for (let p in defaultConfig) {
            if (defaultConfig.hasOwnProperty(p)) {
                config[p] = defaultConfig[p];
            }
        }
        storeConfig();
    }

    function storeConfig() {
        Cookies.set(name, config, {expires: expiryTime});
    }

    function getConfig() {
        try {
            let result = Cookies.getJSON(name);
            if (typeof result === "undefined") {
                resetConfig();
            }
            else {
                config = result;
            }
        }
        catch (e) {
            console.error("CookieConfig: Error while getting config from cookies");
            resetConfig();
        }
    }

    /**
     * Store a value in config by key
     * This triggers a cookie-write
     * @param key
     * @param value
     */
    this.store = function (key, value) {
        if (typeof key === "undefined" || typeof value === "undefined") {
            console.warn("config.store() called with invalid parameters");
        }
        else {
            config[key] = value;
            storeConfig();
        }
    };

    /**
     * Get a value from config by key
     * @param key
     * @returns {*}
     */
    this.get = function (key) {
        if (config.hasOwnProperty(key)) {
            return config[key];
        }
    };

    /**
     * Reset config to default values
     * @type {resetConfig}
     */
    this.reset = resetConfig;

    /**
     * Trigger config refresh (reload from cookies)
     * @type {getConfig}
     */
    this.load = getConfig;
}<|endoftext|>


<commit_before>var config = {
  baseUrl: window.location.pathname.slice(0, -1),
  backgroundColor: 'rgb(200, 200, 200)',
  zoomDistance: {
    init: 150,
    min: 150,
    max: 300
  },
  orbitAngle: {
    min: 0,
    max: Math.PI / 2
  },
  model: {
    url: './data/ionic/model.js'
  },
  progress: {
    current: 0
  },
  cards: {
    url: '/data/ionic/cards/',
    json: 'cards.json',
    key: 'https://docs.google.com/spreadsheet/pub?hl=en_US&hl=en_US&key=1YvF9U7nR3VqzaivHjKV8Yh9QrfCfILUnZc9O1A3-er0&output=html'
  },
  groups: {
    url: './data/ionic/cards/',
    json: 'floors.json'
  }
};<commit_msg>update path<commit_after>var config = {
  baseUrl: window.location.pathname.slice(0, -1),
  backgroundColor: 'rgb(200, 200, 200)',
  zoomDistance: {
    init: 150,
    min: 150,
    max: 300
  },
  orbitAngle: {
    min: 0,
    max: Math.PI / 2
  },
  model: {
    url: '/data/ionic/model.js'
  },
  progress: {
    current: 0
  },
  cards: {
    url: '/data/ionic/cards/',
    json: 'cards.json',
    key: 'https://docs.google.com/spreadsheet/pub?hl=en_US&hl=en_US&key=1YvF9U7nR3VqzaivHjKV8Yh9QrfCfILUnZc9O1A3-er0&output=html'
  },
  groups: {
    url: '/data/ionic/cards/',
    json: 'floors.json'
  }
};<|endoftext|>


<commit_before>'use_strict';
import _ from 'lodash';
import ReactNativePropRegistry from 'react/lib/ReactNativePropRegistry';
// For compatibility with RN 0.25
// import ReactNativePropRegistry from "react-native/Libraries/ReactNative/ReactNativePropRegistry";
module.exports = function(incomingProps, defaultProps) {
    // External props has a higher precedence
    var computedProps = {};

    incomingProps = _.clone(incomingProps);
    delete incomingProps.children;

    var incomingPropsStyle = incomingProps.style;
    delete incomingProps.style;

    // console.log(defaultProps, incomingProps);
    if(incomingProps)
        _.merge(computedProps, defaultProps, incomingProps);
    else
        computedProps = defaultProps;
    // Pass the merged Style Object instead
    if(incomingPropsStyle) {

        var computedPropsStyle = {};
        computedProps.style = {};
        if (Array.isArray(incomingPropsStyle)) {
            _.forEach(incomingPropsStyle, (style)=>{
                if(typeof style == 'number') {
                    _.merge(computedPropsStyle, ReactNativePropRegistry.getByID(style));
                } else {
                    _.merge(computedPropsStyle, style);
                }
            })

        }
        else {
            if(typeof incomingPropsStyle == 'number') {
                computedPropsStyle = ReactNativePropRegistry.getByID(incomingPropsStyle);
            } else {
                computedPropsStyle = incomingPropsStyle;
            }
        }

        _.merge(computedProps.style, defaultProps.style, computedPropsStyle);

    }
    // console.log("computedProps ", computedProps);
    return computedProps;
}<commit_msg>Fix 'call stack size exceeded' error when parsing props with React components as values<commit_after>'use_strict';
import _ from 'lodash';
import ReactNativePropRegistry from 'react/lib/ReactNativePropRegistry';
// For compatibility with RN 0.25
// import ReactNativePropRegistry from "react-native/Libraries/ReactNative/ReactNativePropRegistry";
module.exports = function(incomingProps, defaultProps) {
    // External props has a higher precedence
    var computedProps = {};

    incomingProps = _.clone(incomingProps);
    delete incomingProps.children;

    var incomingPropsStyle = incomingProps.style;
    delete incomingProps.style;

    // console.log(defaultProps, incomingProps);
    if(incomingProps) {
        try {
            _.merge(computedProps, defaultProps, incomingProps);
        } catch (exception) {
            console.log('Warning: Call stack size exceeded when merging props, falling back to shallow merge.');
            _.assign(computedProps, defaultProps, incomingProps);
        }
    } else
        computedProps = defaultProps;
    // Pass the merged Style Object instead
    if(incomingPropsStyle) {

        var computedPropsStyle = {};
        computedProps.style = {};
        if (Array.isArray(incomingPropsStyle)) {
            _.forEach(incomingPropsStyle, (style)=>{
                if(typeof style == 'number') {
                    _.merge(computedPropsStyle, ReactNativePropRegistry.getByID(style));
                } else {
                    _.merge(computedPropsStyle, style);
                }
            })

        }
        else {
            if(typeof incomingPropsStyle == 'number') {
                computedPropsStyle = ReactNativePropRegistry.getByID(incomingPropsStyle);
            } else {
                computedPropsStyle = incomingPropsStyle;
            }
        }

        _.merge(computedProps.style, defaultProps.style, computedPropsStyle);

    }
    // console.log("computedProps ", computedProps);
    return computedProps;
}
<|endoftext|>


<commit_before>"use strict";jQuery(document).ready(function(){var e="DD/MM/YYYY",i={previousMonth:"Mois précédent",nextMonth:"Mois suivant",months:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],weekdays:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],weekdaysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"]};$(".mpec-date").each(function(a,r){new Pikaday({field:r,firstDay:1,format:e,i18n:i})});var a=$('select[name="children_number"]');a.change(function(){if("redNaoNone"!==a.val())for(var e=1;e<=a.val();e++)$("#child"+e).fadeIn(),$("#child"+e+" input").prop("required",!0),$("#child"+(e+1)+", #child"+(e+2)).fadeOut(),$("#child"+(e+1)+" input, #child"+(e+2)+" input").prop("required",!1);else $("#child1, #child2, #child3").fadeOut()});var r=$("#zip"),t=$("#city");if(r.autocomplete({source:function(e,i){$.ajax({url:"https://icare.maplaceencreche.com/api/static/zipcode/"+e.term,dataType:"json",success:function(e){i($.map(e,function(e){return e.z+", "+e.c}))}})},select:function(e,i){t.val(i.item.value.substring(7))},minLength:3}),r.focusout(function(){var e=$(this).val();$(this).val(e.slice(0,5))}),r.change(function(){r.val().length<4&&t.val("")}),null!==localStorage.getItem("MPECData")){var n=JSON.parse(localStorage.getItem("MPECData")).meta;for(var c in n){var o=n[c];$("#meta-inputs").append('<input type="hidden" name="meta_'+c+'" value="'+o+'">')}}$("form#family-register").submit(function(e){e.preventDefault(),$(".error-block").html(""),t.prop("disabled",!1),$.ajax({url:"https://icare.maplaceencreche.com/api/input/register",type:"post",dataType:"json",data:$(this).serialize(),success:function(e){window.location.href="/merci-famille",$("#city").prop("disabled",!0)},error:function(e){$("#city").prop("disabled",!0),$(".error-block").html("Une erreur est survenue lors de l'envoi du formulaire, veuillez réessayer.")}})})});<commit_msg>Add loader to submit button<commit_after>"use strict";jQuery(document).ready(function(){var e="DD/MM/YYYY",i={previousMonth:"Mois précédent",nextMonth:"Mois suivant",months:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],weekdays:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],weekdaysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"]};$(".mpec-date").each(function(t,a){new Pikaday({field:a,firstDay:1,format:e,i18n:i})});var t=$('select[name="children_number"]');t.change(function(){if("redNaoNone"!==t.val())for(var e=1;e<=t.val();e++)$("#child"+e).fadeIn(),$("#child"+e+" input").prop("required",!0),$("#child"+(e+1)+", #child"+(e+2)).fadeOut(),$("#child"+(e+1)+" input, #child"+(e+2)+" input").prop("required",!1);else $("#child1, #child2, #child3").fadeOut()});var a=$("#zip"),r=$("#city");if(a.autocomplete({source:function(e,i){$.ajax({url:"https://icare.maplaceencreche.com/api/static/zipcode/"+e.term,dataType:"json",success:function(e){i($.map(e,function(e){return e.z+", "+e.c}))}})},select:function(e,i){r.val(i.item.value.substring(7))},minLength:3}),a.focusout(function(){var e=$(this).val();$(this).val(e.slice(0,5))}),a.change(function(){a.val().length<4&&r.val("")}),null!==localStorage.getItem("MPECData")){var n=JSON.parse(localStorage.getItem("MPECData")).meta;for(var c in n){var o=n[c];$("#meta-inputs").append('<input type="hidden" name="meta_'+c+'" value="'+o+'">')}}$("#main-submit").click(function(){$(this).button("loading")}),$("form#family-register").submit(function(e){e.preventDefault(),$(".error-block").html(""),r.prop("disabled",!1),$.ajax({url:"https://icare.maplaceencreche.com/api/input/register",type:"post",dataType:"json",data:$(this).serialize(),success:function(e){window.location.href="/merci-famille",$("#city").prop("disabled",!0)},error:function(e){$("#city").prop("disabled",!0),$(".error-block").html("Une erreur est survenue lors de l'envoi du formulaire, veuillez réessayer."),$("#main-submit").button("reset")}})})});<|endoftext|>


<commit_before>const axios=require('axios');
const Terminal=require('./util').Terminal;
const FGFS_HOST='http://localhost:8123/'
module.exports=class{
    data=undefined;
    constructor(stream,_exit){
        this.terminal=new Terminal(stream,{
            outputEncoding:'shift-jis'
        });
        this._exit=_exit;
        this.terminal.pc98SetBottomLine(false);
        this.terminal.clrscr();
        this.terminal.locate(0,0);
        this.terminal.setcursor(false);
        this.terminal.print('Loading...');
        this.refresh();
        this.drawFrame();
        this.refreshTimer=setInterval(()=>{
            this.refresh()
        },1000);
    }
    drawFrame(){
        this.terminal.clrscr();
        this.terminal.locate(0,1);
        this.terminal.setattr(46);
        for(let i=0;i<80;i++){
            this.terminal.print(' ');
        }
        this.terminal.locate(Math.round((80-16)/2),1);
        this.terminal.print('飛行制御センター');

        this.terminal.locate(0,25);
        this.terminal.setattr(46);
        for(let i=0;i<80;i++){
            this.terminal.print(' ');
        }
        this.terminal.locate(2,25);
        this.terminal.print('Esc：終了    s:ｻｳﾝﾄﾞｵﾝ/ｵﾌ    p:一時停止/再開');
        this.terminal.setattr(0);

        //this.terminal.locate(0,25);
        //this.terminal.print('Press \'s\' to toggle sound.');
    }
    async refresh(){
        let data=null;
        try{
            data=await axios({
                method:'GET',
                url:FGFS_HOST+'/json/fgreport'
            });
        }catch(e){
            if(null!==this.data){
                this.data=null;
                this.drawFrame();
                this.terminal.locate(Math.floor((80-22)/2),12);
                this.terminal.print('飛行任務がありません。');
            }
            return;
        }

        try{
            let fgreport={};
            for(let item of data.data.children){
                fgreport[item.name]=item.value;
            }

            if(!this.data){
                this.drawFrame();
            }
            this.data=fgreport;
            fgreport['longitude'] = Math.abs(fgreport['longitude-deg']).toFixed(6)+(fgreport['longitude-deg']>=0 ? 'E' : 'W');
            fgreport['latitude'] = Math.abs(fgreport['latitude-deg']).toFixed(6)+(fgreport['latitude-deg']>=0 ? 'N' : 'S');
            this.terminal.locate(0,3);
            this.terminal.print('機種：'+fgreport.aircraft+'        ');
            this.terminal.locate(0,4);
            this.terminal.print('経度：'+fgreport['longitude']+'        ');
            this.terminal.locate(0,5);
            this.terminal.print('緯度：'+fgreport['latitude']+'        ');
            this.terminal.locate(0,6);
            this.terminal.print('飛行時間：'+fgreport['flight-time-string']+'        ');
            this.terminal.locate(0,7);
            this.terminal.print('残り時間：'+fgreport['ete-string']+'        ');
            this.terminal.locate(0,8);
            this.terminal.print('総距離：'+fgreport['total-distance'].toFixed(1)+'nm        ');
            this.terminal.locate(0,9);
            this.terminal.print('残り距離：'+fgreport['distance-remaining-nm'].toFixed(1)+'nm        ');
            this.terminal.locate(0,10);
            this.terminal.print('飛行距離：'+(Number(fgreport['total-distance'])-Number(fgreport['distance-remaining-nm'])).toFixed(1)+'nm        ');

            this.terminal.locate(0,24);
            if(fgreport['crashed']){
                this.terminal.setattr(5,41);
                this.terminal.print('墜落しました');
            }else if(fgreport['paused']){
                this.terminal.setattr(21);
                this.terminal.print('一時停止');
            }else{
                this.terminal.setattr(20);
                this.terminal.print('飛行中');
            }
            this.terminal.setattr(0);
            this.terminal.print('                ');
        }catch(e){
            console.error(e);
        }
    }
    destroy(){
        try{
            if(this.refreshTimer){
                clearInterval(this.refreshTimer);
                this.refreshTimer=null;
            }
            this.terminal.reset();
        }catch(e){
            console.error(e);
        }finally{
            this._exit();
        }
    }
    async toggleSound(){
        let {data}=await axios({
            method:'GET',
            url:FGFS_HOST+'/json/sim/sound/enabled'
        });
        await axios({
            method:'GET',
            url:FGFS_HOST+`/props/sim/sound?submit=set&enabled=${data.value ? 'false' : 'true'}`
        });
    }
    async togglePause(){
        await axios({
            method:'GET',
            url:FGFS_HOST+'/run.cgi?value=pause'
        });
    }
    ondata(data){
        try{
            switch(data[0]){
                case 0x1b:
                    this.destroy();
                    return;
                break;
                case 0x73:
                    this.toggleSound();
                break;
                case 0x70:
                    this.togglePause();
                break;
            }
        }catch(e){
            console.error(e);
        }
    }
}
<commit_msg>fgconsole.js updated<commit_after>const axios=require('axios');
const Terminal=require('./util').Terminal;
const FGFS_HOST='http://localhost:8123/'
module.exports=class{
    data=undefined;
    constructor(stream,_exit){
        this.terminal=new Terminal(stream,{
            outputEncoding:'shift-jis'
        });
        this._exit=_exit;
        this.terminal.pc98SetBottomLine(false);
        this.terminal.clrscr();
        this.terminal.locate(0,0);
        this.terminal.setcursor(false);
        this.terminal.print('Loading...');
        this.refresh();
        this.drawFrame();
        this.refreshTimer=setInterval(()=>{
            this.refresh()
        },1000);
    }
    drawFrame(){
        this.terminal.clrscr();
        this.terminal.locate(0,1);
        this.terminal.setattr(46);
        for(let i=0;i<80;i++){
            this.terminal.print(' ');
        }
        this.terminal.locate(Math.round((80-16)/2),1);
        this.terminal.print('飛行制御センター');

        this.terminal.locate(0,25);
        this.terminal.setattr(46);
        for(let i=0;i<80;i++){
            this.terminal.print(' ');
        }
        this.terminal.locate(2,25);
        this.terminal.print('Esc：終了    s:ｻｳﾝﾄﾞｵﾝ/ｵﾌ    p:一時停止/再開');
        this.terminal.setattr(0);

        //this.terminal.locate(0,25);
        //this.terminal.print('Press \'s\' to toggle sound.');
    }
    async refresh(){
        let data=null;
        try{
            data=await axios({
                method:'GET',
                url:FGFS_HOST+'/json/fgreport'
            });
        }catch(e){
            if(null!==this.data){
                this.data=null;
                this.drawFrame();
                this.terminal.locate(Math.floor((80-22)/2),12);
                this.terminal.print('飛行任務がありません。');
            }
            return;
        }

        try{
            let fgreport={};
            for(let item of data.data.children){
                fgreport[item.name]=item.value;
            }

            if(!this.data){
                this.drawFrame();
            }
            this.data=fgreport;
            fgreport['longitude'] = Math.abs(fgreport['longitude-deg']).toFixed(6)+(fgreport['longitude-deg']>=0 ? 'E' : 'W');
            fgreport['latitude'] = Math.abs(fgreport['latitude-deg']).toFixed(6)+(fgreport['latitude-deg']>=0 ? 'N' : 'S');
            this.terminal.locate(0,3);
            this.terminal.print('機種：    '+fgreport.aircraft+'        ');
            this.terminal.locate(0,4);
            this.terminal.print('経度：    '+fgreport['longitude']+'        ');
            this.terminal.locate(0,5);
            this.terminal.print('緯度：    '+fgreport['latitude']+'        ');
            this.terminal.locate(0,6);
            this.terminal.print('飛行時間：'+fgreport['flight-time-string']+'        ');
            this.terminal.locate(0,7);
            this.terminal.print('残り時間：'+fgreport['ete-string']+'        ');
            this.terminal.locate(0,8);
            this.terminal.print('総距離：  '+fgreport['total-distance'].toFixed(1)+'nm        ');
            this.terminal.locate(0,9);
            this.terminal.print('残り距離：'+fgreport['distance-remaining-nm'].toFixed(1)+'nm        ');
            this.terminal.locate(0,10);
            this.terminal.print('飛行距離：'+(Number(fgreport['total-distance'])-Number(fgreport['distance-remaining-nm'])).toFixed(1)+'nm        ');

            this.terminal.locate(0,24);
            if(fgreport['crashed']){
                this.terminal.setattr(5,41);
                this.terminal.print('墜落しました');
            }else if(fgreport['paused']){
                this.terminal.setattr(21);
                this.terminal.print('一時停止');
            }else{
                this.terminal.setattr(20);
                this.terminal.print('飛行中');
            }
            this.terminal.setattr(0);
            this.terminal.print('                ');
        }catch(e){
            console.error(e);
        }
    }
    destroy(){
        try{
            if(this.refreshTimer){
                clearInterval(this.refreshTimer);
                this.refreshTimer=null;
            }
            this.terminal.reset();
        }catch(e){
            console.error(e);
        }finally{
            this._exit();
        }
    }
    async toggleSound(){
        let {data}=await axios({
            method:'GET',
            url:FGFS_HOST+'/json/sim/sound/enabled'
        });
        await axios({
            method:'GET',
            url:FGFS_HOST+`/props/sim/sound?submit=set&enabled=${data.value ? 'false' : 'true'}`
        });
    }
    async togglePause(){
        await axios({
            method:'GET',
            url:FGFS_HOST+'/run.cgi?value=pause'
        });
    }
    ondata(data){
        try{
            switch(data[0]){
                case 0x1b:
                    this.destroy();
                    return;
                break;
                case 0x73:
                    this.toggleSound();
                break;
                case 0x70:
                    this.togglePause();
                break;
            }
        }catch(e){
            console.error(e);
        }
    }
}
<|endoftext|>


<commit_before>var http = require('http'),
    request = require('request'),
    helpers = require('./helpers');

/**
 * eventbrite API wrapper for the API version 3. This object should not be
 * instantiated directly but by using the version wrapper {@link eventbriteAPI}.
 *
 * @param apiKey The API key to access the eventbrite API with
 * @param options Configuration options
 * @return Instance of {@link eventbriteAPI_v3}
 */
function eventbriteAPI_v3 (options) {

  if (!options) {
    throw new Error('Something went wrong, API requires: {token: YOUR_TOKEN}');
  } else if (!options.token) {
    throw new Error('You have to provide a token for this to work.');
  }

  this.version     = 'v3';
  this.httpUri     = 'https://www.eventbriteapi.com'
  this.token       = options.token;
  this.userAgent   = options.userAgent || 'node-eventbrite/' + this.version;
}

module.exports = eventbriteAPI_v3;

/**
 * Sends a given request as a JSON object to the eventbrite API and finally
 * calls the given callback function with the resulting JSON object. This
 * method should not be called directly but will be used internally by all API
 * methods defined.
 *
 * @param resource eventbrite API resource to call
 * @param method eventbrite API method to call
 * @param availableParams Parameters available for the specified API method
 * @param givenParams Parameters to call the eventbrite API with
 * @param callback Callback function to call on success
 */
eventbriteAPI_v3.prototype.execute = function (resource, method, availableParams, givenParams, callback) {

  var finalParams = {};
  var currentParam;

  for (var i = 0; i < availableParams.length; i++) {
    currentParam = availableParams[i];
    if (typeof givenParams[currentParam] !== 'undefined')
      finalParams[currentParam] = givenParams[currentParam];
  }

  request({
    uri : this.httpUri + '/' + this.version + '/' + resource + '/' + method,
    method: 'POST',

    headers : { 'Authorization' : 'bearer ' + this.token,
                'Content-Type' : 'application/json',
                'User-Agent' : this.userAgent},
    body : JSON.stringify(finalParams)
  }, function (error, response, body) {
    var parsedResponse;
    if (error) {
      callback(new Error('Unable to connect to the eventbrite API endpoint.'));
    } else {

      try {
        parsedResponse = JSON.parse(body);
      } catch (error) {
        callback(new Error('Error parsing JSON answer from eventbrite API.'));
        return;
      }

      if (parsedResponse.errmsg) {
        callback(helpers.createEventbriteError(parsedResponse.errmsg, parsedResponse.status));
        return;
      }

      callback(null, parsedResponse);

    }
  });

};

/*****************************************************************************/
/************************* xxx Related Methods **************************/
/*****************************************************************************/

/**
 * Retrieves a user by ID
 *
 * @see http://developer.eventbrite.com/docs/user-details/
**/

eventbriteAPI_v3.prototype.userDetails = function (params, callback) {
  var availableParams = [];

  if (typeof params === 'function') callback = params, params = {};

  this.execute('users', params.id, availableParams, params, callback);
};

/**
 * Retrieves the current authenticated user
 *
 * @see http://developer.eventbrite.com/docs/user-details/
 **/

eventbriteAPI_v3.prototype.me = function (callback) {
  this.userDetails({id: 'me'}, callback);
};<commit_msg>create get and post requests<commit_after>var http = require('http'),
    request = require('request'),
    helpers = require('./helpers');

/**
 * eventbrite API wrapper for the API version 3. This object should not be
 * instantiated directly but by using the version wrapper {@link eventbriteAPI}.
 *
 * @param apiKey The API key to access the eventbrite API with
 * @param options Configuration options
 * @return Instance of {@link eventbriteAPI_v3}
 */
function eventbriteAPI_v3 (options) {

  if (!options) {
    throw new Error('Something went wrong, API requires: {token: YOUR_TOKEN}');
  } else if (!options.token) {
    throw new Error('You have to provide a token for this to work.');
  }

  this.version     = 'v3';
  this.httpUri     = 'https://www.eventbriteapi.com'
  this.token       = options.token;
  this.contentType = options.contentType || 'application/json';
  this.userAgent   = options.userAgent || 'node-eventbrite/' + this.version;
}

module.exports = eventbriteAPI_v3;

/**
 * Sends a given request as a JSON object to the eventbrite API and finally
 * calls the given callback function with the resulting JSON object. This
 * method should not be called directly but will be used internally by all API
 * methods defined.
 *
 * @param resource eventbrite API resource to call
 * @param method eventbrite API method to call
 * @param availableParams Parameters available for the specified API method
 * @param givenParams Parameters to call the eventbrite API with
 * @param callback Callback function to call on success
 */
eventbriteAPI_v3.prototype.execute = function (verb, resource, method, availableParams, givenParams, callback) {
  if (!verb) {
    verb = "GET";
  }
  var headers = {
    "Content-Type": this.contentType,
    "Authorization":  'Bearer ' + this.token
  };

  var uri = this.httpUri + '/' + this.version + '/' + resource + '/' + method;

  var finalParams = {};
  var currentParam;

  for (var i = 0; i < availableParams.length; i++) {
    currentParam = availableParams[i];
    if (typeof givenParams[currentParam] !== 'undefined')
      finalParams[currentParam] = givenParams[currentParam];
  }

  request({
    uri: uri,
    method: verb,
    headers: headers,
    body: JSON.stringify(finalParams)
  }, function (error, response, body) {
    var parsedResponse;
    if (error) {
      callback(new Error('Unable to connect to the eventbrite API endpoint.'));
    } else {

      try {
        parsedResponse = JSON.parse(body);
      } catch (error) {
        callback(new Error('Error parsing JSON answer from eventbrite API.'));
        return;
      }

      if (parsedResponse.errmsg) {
        callback(helpers.createEventbriteError(parsedResponse.errmsg, parsedResponse.status));
        return;
      }

      callback(null, parsedResponse);

    }
  });

};

eventbriteAPI_v3.prototype.get = function (resource, method, availableParams, givenParams, callback) {
  this.execute("GET", resource, method, availableParams, givenParams, callback)
};

eventbriteAPI_v3.prototype.post = function (resource, method, availableParams, givenParams, callback) {
  this.execute("POST", resource, method, availableParams, givenParams, callback)
};

/*****************************************************************************/
/************************* xxx Related Methods **************************/
/*****************************************************************************/

/**
 * Retrieves a user by ID
 *
 * @see http://developer.eventbrite.com/docs/user-details/
**/

eventbriteAPI_v3.prototype.userDetails = function (params, callback) {
  var availableParams = [];

  if (typeof params === 'function') callback = params, params = {};

  params.user_id = params.user_id || "me";

  this.get('users', params.user_id, availableParams, params, callback);
};

/**
 * Retrieves the current authenticated user
 *
 * @see http://developer.eventbrite.com/docs/user-details/
 **/

eventbriteAPI_v3.prototype.me = function (callback) {
  this.userDetails({user_id: 'me'}, callback);
};

/**
 * Retrieves user_owned_events for a given user_id
 * If you do not include a user_id, we will include one for you :)
 * @see http://developer.eventbrite.com/docs/user-details/
 **/

eventbriteAPI_v3.prototype.owned_events = function (params, callback) {
  var user_id = params.user_id || "me";

  var availableParams = [
    "page",
    "status",   //Pull a user’s events based upon the ‘status’ of the event. Potential request parameters are ‘all’, ‘draft’, ‘live’, ‘cancelled’, ‘started’, and ‘ended’.
    "order_by"  //Determine the order of a user’s events based upon the start date or creation date. Sort by ‘start_asc’, ‘start_desc’, ‘created_asc’, and ‘created_desc’.
  ];

  var method = user_id + "/owned_events/"
  this.get('users', method, availableParams, params, callback);
};
<|endoftext|>


<commit_before>var UT_TWEAK = {};
UT_TWEAK.CustomEventsManager = (function(global, isIframe)
{
	//Test if it is an iOS device and that we may swap the implementation
	if ( ! /(iPad|iPhone|iPod)/g.test(global.navigator.userAgent) || ! Element.prototype.addEventListener)
	{
		return null;
	};

	var nativeAddEventListener = global.Element.prototype.addEventListener,
		nativeRemoveEventListener = global.Element.prototype.removeEventListener,
		uuid = 0,
		eventListeners = {},
		returnObj,
		touchEventsEnabled = true,
		debug = true;

	//Run the tweak
	swapEventListenerImplementation();

	//Default behaviour
	enableCapture();

	//Disable logging when in production or not available
	console.log = (global.console && global.console.log && debug) ? global.console.log : function() {};

	function swapEventListenerImplementation()
	{
		var newAddEventListener = function()
		{
			var	type = arguments[0],
        		listener = arguments[1],
        		shouldAddListener = true;

			if ((type === 'touchstart' || type === 'touchend' || type === 'touchcancel' || type === 'touchmove' || type === 'touchleave') &&
				typeof listener === 'function')
			{
				if (touchEventsEnabled)
				{
					this.__UT__uuid = this.__UT__uuid || getUUID();
					eventListeners[this.__UT__uuid] = eventListeners[this.__UT__uuid] || {};
					eventListeners[this.__UT__uuid][type] = {node: this, callback: listener};
				}
				else
				{
					shouldAddListener = false;
				}
			}

			console.log("_");
        	console.log("->> Called addEventListener, type: " +  type + ", in iframe: " + isIframe + ", will be added: " + shouldAddListener);

			if (shouldAddListener)
			{
				nativeAddEventListener.apply(this, arguments);
			};
		}

		var newRemoveEventListener = function()
		{
			var	type = arguments[0],
        		listener = arguments[1];

			if ((type === 'touchstart' || type === 'touchend' || type === 'touchcancel' || type === 'touchmove' || type === 'touchleave') &&
				typeof listener === 'function')
			{
              if (eventListeners[this.__UT__uuid][type])
              {
                delete eventListeners[this.__UT__uuid][type];
              }
            }

			nativeRemoveEventListener.apply(this, arguments);
		}

		global.Element.prototype.addEventListener = newAddEventListener;
		global.Element.prototype.removeEventListener = newRemoveEventListener;
		global.document.addEventListener = newAddEventListener;
		global.document.removeEventListener = newRemoveEventListener;
	}

	//Not public for now
	function restoreEventListenerImplementation()
	{
		global.Element.prototype.addEventListener = nativeAddEventListener;
		global.Element.prototype.removeEventListener = nativeRemoveEventListener;
		global.document.addEventListener = nativeAddEventListener;
		global.document.removeEventListener = nativeRemoveEventListener;
	}

	function onFocus(event)
	{
		if (global.document.activeElement.nodeName == 'TEXTAREA' ||
			global.document.activeElement.nodeName == 'INPUT' ||
			global.document.activeElement.getAttribute('contenteditable'))
		{
			disableTouchEvents();
		}
	}

	function enableTouchEvents()
	{
		var obj1, obj2, obj3, obj4, obj5;

		touchEventsEnabled = true;
		console.log("->> enableTouchEvents");

		if (isIframe)
		{
			global.top.postMessage("touchevents:enable", "*");
		}

		for (var key in eventListeners)
		{
			if (eventListeners.hasOwnProperty(key))
			{
				obj1 = eventListeners[key].touchstart;
    			obj2 = eventListeners[key].touchend;
    			obj3 = eventListeners[key].touchcancel;
    			obj4 = eventListeners[key].touchmove;
    			obj5 = eventListeners[key].touchleave;

    			if (obj1) {nativeAddEventListener.call(obj1.node, 'touchstart', obj1.callback, false);}
    			if (obj2) {nativeAddEventListener.call(obj2.node, 'touchend', obj2.callback, false);}
    			if (obj3) {nativeAddEventListener.call(obj3.node, 'touchcancel', obj3.callback, false);}
    			if (obj4) {nativeAddEventListener.call(obj4.node, 'touchmove', obj4.callback, false);}
    			if (obj5) {nativeAddEventListener.call(obj5.node, 'touchleave', obj5.callback, false);}
			};
		}
	}

	function disableTouchEvents()
	{
		var obj1, obj2, obj3, obj4, obj5;
		touchEventsEnabled = false;

		console.log("->> disableTouchEvents");

		if (isIframe)
		{
			global.top.postMessage("touchevents:disable", "*");
		}

		for (var key in eventListeners)
		{
			if (eventListeners.hasOwnProperty(key))
			{
    			obj1 = eventListeners[key].touchstart;
    			obj2 = eventListeners[key].touchend;
    			obj3 = eventListeners[key].touchcancel;
    			obj4 = eventListeners[key].touchmove;
    			obj5 = eventListeners[key].touchleave;

    			if (obj1) {nativeRemoveEventListener.call(obj1.node, 'touchstart', obj1.callback, false);}
    			if (obj2) {nativeRemoveEventListener.call(obj2.node, 'touchend', obj2.callback, false);}
    			if (obj3) {nativeRemoveEventListener.call(obj3.node, 'touchcancel', obj3.callback, false);}
    			if (obj4) {nativeRemoveEventListener.call(obj4.node, 'touchmove', obj4.callback, false);}
    			if (obj5) {nativeRemoveEventListener.call(obj5.node, 'touchleave', obj5.callback, false);}
    		}
		}
	}

	function enableCapture()
	{
		if (isIframe)
		{
			nativeAddEventListener.call(global.document, 'focus', onFocus, true);
			nativeAddEventListener.call(global.document, 'blur', enableTouchEvents, true)
		}
		else
		{
			global.addEventListener("message", didReceiveMessage, true);
		}
	}

	function disableCapture()
	{
		if (isIframe)
		{
			nativeRemoveEventListener.call(global.document, 'focus', onFocus, true);
			nativeRemoveEventListener.call(global.document, 'blur', enableTouchEvents, true);
		}
		else
		{
			global.removeEventListener("message", didReceiveMessage, true);
		}
	}

	function didReceiveMessage (event)
	{
        console.log("didReceiveMessage" + " " + event.data);

		if (event.data === "touchevents:enable")
		{
			enableTouchEvents();
		}
		else if (event.data === "touchevents:disable")
		{
			disableTouchEvents();
		}
	}

	function getUUID()
	{
		return parseInt(uuid++);
	}

    function getEventListenersDescription()
    {
    	console.group("EventListeners description:");

    	for (var key in eventListeners)
		{
			console.group("%s:", key);

			if (eventListeners.hasOwnProperty(key))
			{
    			console.log(eventListeners[key]);
    		}

    		console.groupEnd();
		}

		console.groupEnd();
    }

    returnObj =
    {
    	enableCapture: enableCapture,
    	disableCapture: disableCapture,
    	enableTouchEvents: enableTouchEvents,
    	disableTouchEvents: disableTouchEvents,
    	getEventListenersDescription: getEventListenersDescription
    };

	return returnObj;

}(window, true));<commit_msg>jslint tweak.js<commit_after>var UT_TWEAK = {};
UT_TWEAK.CustomEventsManager = (function (global, isIframe) {
  //Test if it is an iOS device and that we may swap the implementation
  if (!/(iPad|iPhone|iPod)/g.test(global.navigator.userAgent) || !Element.prototype.addEventListener) {
    return null;
  }

  var nativeAddEventListener = global.Element.prototype.addEventListener,
    nativeRemoveEventListener = global.Element.prototype.removeEventListener,
    uuid = 0,
    eventListeners = {},
    returnObj,
    touchEventsEnabled = true,
    debug = true;

  //Run the tweak
  swapEventListenerImplementation();

  //Default behaviour
  enableCapture();

  //Disable logging when in production or not available
  console.log = (global.console && global.console.log && debug) ? global.console.log : function () {};

  function swapEventListenerImplementation() {
    var newAddEventListener = function () {
      var type = arguments[0],
        listener = arguments[1],
        shouldAddListener = true;

      if ((type === 'touchstart' || type === 'touchend' || type === 'touchcancel' || type === 'touchmove' || type === 'touchleave') &&
        typeof listener === 'function') {
        if (touchEventsEnabled) {
          this.__UT__uuid = this.__UT__uuid || getUUID();
          eventListeners[this.__UT__uuid] = eventListeners[this.__UT__uuid] || {};
          eventListeners[this.__UT__uuid][type] = {
            node: this,
            callback: listener
          };
        } else {
          shouldAddListener = false;
        }
      }

      console.log("_");
      console.log("->> Called addEventListener, type: " + type + ", in iframe: " + isIframe + ", will be added: " + shouldAddListener);

      if (shouldAddListener) {
        nativeAddEventListener.apply(this, arguments);
      }
    };

    var newRemoveEventListener = function () {
      var type = arguments[0],
        listener = arguments[1];

      if ((type === 'touchstart' || type === 'touchend' || type === 'touchcancel' || type === 'touchmove' || type === 'touchleave') &&
        typeof listener === 'function') {
        if (eventListeners[this.__UT__uuid][type]) {
          delete eventListeners[this.__UT__uuid][type];
        }
      }

      nativeRemoveEventListener.apply(this, arguments);
    };

    global.Element.prototype.addEventListener = newAddEventListener;
    global.Element.prototype.removeEventListener = newRemoveEventListener;
    global.document.addEventListener = newAddEventListener;
    global.document.removeEventListener = newRemoveEventListener;
  }

  //Not public for now

  function restoreEventListenerImplementation() {
    global.Element.prototype.addEventListener = nativeAddEventListener;
    global.Element.prototype.removeEventListener = nativeRemoveEventListener;
    global.document.addEventListener = nativeAddEventListener;
    global.document.removeEventListener = nativeRemoveEventListener;
  }

  function onFocus(event) {
    if (global.document.activeElement.nodeName == 'TEXTAREA' ||
      global.document.activeElement.nodeName == 'INPUT' ||
      global.document.activeElement.getAttribute('contenteditable')) {
      disableTouchEvents();
    }
  }

  function enableTouchEvents() {
    var obj1, obj2, obj3, obj4, obj5;

    touchEventsEnabled = true;
    console.log("->> enableTouchEvents");

    if (isIframe) {
      global.top.postMessage("touchevents:enable", "*");
    }

    for (var key in eventListeners) {
      if (eventListeners.hasOwnProperty(key)) {
        obj1 = eventListeners[key].touchstart;
        obj2 = eventListeners[key].touchend;
        obj3 = eventListeners[key].touchcancel;
        obj4 = eventListeners[key].touchmove;
        obj5 = eventListeners[key].touchleave;

        if (obj1) {
          nativeAddEventListener.call(obj1.node, 'touchstart', obj1.callback, false);
        }
        if (obj2) {
          nativeAddEventListener.call(obj2.node, 'touchend', obj2.callback, false);
        }
        if (obj3) {
          nativeAddEventListener.call(obj3.node, 'touchcancel', obj3.callback, false);
        }
        if (obj4) {
          nativeAddEventListener.call(obj4.node, 'touchmove', obj4.callback, false);
        }
        if (obj5) {
          nativeAddEventListener.call(obj5.node, 'touchleave', obj5.callback, false);
        }
      }
    }
  }

  function disableTouchEvents() {
    var obj1, obj2, obj3, obj4, obj5;
    touchEventsEnabled = false;

    console.log("->> disableTouchEvents");

    if (isIframe) {
      global.top.postMessage("touchevents:disable", "*");
    }

    for (var key in eventListeners) {
      if (eventListeners.hasOwnProperty(key)) {
        obj1 = eventListeners[key].touchstart;
        obj2 = eventListeners[key].touchend;
        obj3 = eventListeners[key].touchcancel;
        obj4 = eventListeners[key].touchmove;
        obj5 = eventListeners[key].touchleave;

        if (obj1) {
          nativeRemoveEventListener.call(obj1.node, 'touchstart', obj1.callback, false);
        }
        if (obj2) {
          nativeRemoveEventListener.call(obj2.node, 'touchend', obj2.callback, false);
        }
        if (obj3) {
          nativeRemoveEventListener.call(obj3.node, 'touchcancel', obj3.callback, false);
        }
        if (obj4) {
          nativeRemoveEventListener.call(obj4.node, 'touchmove', obj4.callback, false);
        }
        if (obj5) {
          nativeRemoveEventListener.call(obj5.node, 'touchleave', obj5.callback, false);
        }
      }
    }
  }

  function enableCapture() {
    if (isIframe) {
      nativeAddEventListener.call(global.document, 'focus', onFocus, true);
      nativeAddEventListener.call(global.document, 'blur', enableTouchEvents, true);
    } else {
      global.addEventListener("message", didReceiveMessage, true);
    }
  }

  function disableCapture() {
    if (isIframe) {
      nativeRemoveEventListener.call(global.document, 'focus', onFocus, true);
      nativeRemoveEventListener.call(global.document, 'blur', enableTouchEvents, true);
    } else {
      global.removeEventListener("message", didReceiveMessage, true);
    }
  }

  function didReceiveMessage(event) {
    console.log("didReceiveMessage" + " " + event.data);

    if (event.data === "touchevents:enable") {
      enableTouchEvents();
    } else if (event.data === "touchevents:disable") {
      disableTouchEvents();
    }
  }

  function getUUID() {
    return parseInt(uuid++,10);
  }

  function getEventListenersDescription() {
    console.group("EventListeners description:");

    for (var key in eventListeners) {
      console.group("%s:", key);

      if (eventListeners.hasOwnProperty(key)) {
        console.log(eventListeners[key]);
      }

      console.groupEnd();
    }

    console.groupEnd();
  }

  returnObj = {
    enableCapture: enableCapture,
    disableCapture: disableCapture,
    enableTouchEvents: enableTouchEvents,
    disableTouchEvents: disableTouchEvents,
    getEventListenersDescription: getEventListenersDescription
  };

  return returnObj;

}(window, true));<|endoftext|>


<commit_before>// Slingshot.fileRestrictions("cropUploader", {
//   allowedFileTypes: ["image/png", "image/jpeg", "image/gif"],
//   maxSize: 10 * 1024 * 1024 // 10 MB (use null for unlimited)
// });
CropUploader = {
	images: new Meteor.Collection('images'),
	name: 'cropUploader',
	urlBase: null,
	derivative: {
		replace:function(imageId, name, derivative) {
			var self = this;
			// console.log( derivative );
			check(imageId, String);
			check(name, String);
			// derivative needs to be File or Blob
			if (! (derivative instanceof window.File) && ! (derivative instanceof window.Blob))
				throw new Meteor.Error("The derivative to replace must be File or Blob");
			// check(derivative, Blob);
			var image = CropUploader.images.findOne(imageId);
			if(!image) throw new Meteor.Error(401, "the provided image does not exist");
			if(image.userId != Meteor.userId()) throw new Meteor.Error(403, "you don't have permission to replace derivative for "+imageid);
			//
			// setup slingshot with uuid from parent
			//
			var uploader = new Slingshot.Upload(CropUploader.name, {uuid: image.uuid });
			var oldfile = name in image['derivatives'] ? image['derivatives'][name] : null;
			// set name of blob so it will put in the right place
			derivative.name = 'derivative/'+name+'/';
			uploader.send(derivative, function (error, thumbnailUrl) {
			  if (error) {
				console.error('Error uploading', uploader.xhr.response);
				alert (error);
			  } else {
				//
				// update the collection object
				//
				var set = {}
				set['derivatives.'+name] = thumbnailUrl;
				CropUploader.images.update(image._id,{$set: set}, function(err,res){
					if(err) console.error(err);
					else console.log('uploaded and updated', res);
				});
				//
				// this should actually happen in the allow.update
				//
				if(oldfile)
				{
					// console.log('delete', oldfile);
					Meteor.call('cropUploaderS3Delete', oldfile, function (error, result) {
						if(error) console.err(error);
					});
				}
			  }
			});
		},
	},
	_hooks: {},
	hooks: function(hooks) {
		var self = this;
		self._hooks = hooks;
	},
	insert:function(image) {
		var self = this;
		if('insert' in self._hooks && typeof self._hooks.insert == 'function')
			image = self._hooks.insert(image);
		if(image)
			CropUploader.images.insert( image );
	},
	crop: {
		template: null,
		save: function(type) {
			var self = this;
			var imageid = self.template.imageid;
			type = type || 'thumbnail';
			self.template.canvas = self.template.cropimage.cropper('getCroppedCanvas',{
			  width: self.template.data.thumbnailWidth,
			  height: self.template.data.thumbnailHeight
			});

			if(self.template.canvas && self.template.canvas.toBlob)
			{
			  self.template.canvas.toBlob(function(blob){
				CropUploader.derivative.replace( imageid, type, blob );
			  },'image/png');
			} else console.log('no canvas', self.template.canvas);
		},
		rotate: function() {
			var self = this;
			self.template.cropimage.cropper('rotate',90);
		}
	},
	init: function(name, directory, consolidate) {
		var self = this;
		directory = directory || '';
		consolidate = consolidate || false;
		check(name, String);
		check(directory, String);
		check(consolidate, Boolean);
		if(directory.length>0 && directory[directory.length-1]!="/") directory+='/';
		self.directory = directory;
		self.name = name;
		// console.log('init', self.directory);
		if(Meteor.isServer)
		{
			var Knox = Npm.require("knox");
			var directive = Slingshot.getDirective(self.name);
			// console.log(directive._directive.region);
			self.knox = Knox.createClient({
				key: directive._directive.AWSAccessKeyId,
				secret: directive._directive.AWSSecretAccessKey,
				region: directive._directive.region,
				bucket: directive._directive.bucket,
			});
			directive._directive.key = function (file, meta) {
				// file
				// {
				//  name: '11075296_10152631810352261_1337077077459889796_n.jpg',
				//  size: 17224,
				//  type: 'image/jpeg'
				// }
				// console.log(file, meta);
				var ext = file.type.split('/')[1];
				if(file.name.match('derivative/'))
				{
					var d = new Date().getTime();
					return CropUploader.directory + file.name + meta.uuid +'.'+d+'.'+ext;
				}
				else
				{
					return CropUploader.directory+meta.uuid+'.'+ext;
				}
			}
			if(consolidate) Meteor.call('cropUploaderConsolidate');
		}
	}
};

if(Meteor.isClient)
{
	CropUploader.errorMessage = new ReactiveVar('');
}<commit_msg>add check for roles<commit_after>// Slingshot.fileRestrictions("cropUploader", {
//   allowedFileTypes: ["image/png", "image/jpeg", "image/gif"],
//   maxSize: 10 * 1024 * 1024 // 10 MB (use null for unlimited)
// });
CropUploader = {
	images: new Meteor.Collection('images'),
	name: 'cropUploader',
	urlBase: null,
	derivative: {
		replace:function(imageid, name, derivative) {
			var self = this;
			// console.log( derivative );
			check(imageid, String);
			check(name, String);
			var userId = Meteor.userId();
			// derivative needs to be File or Blob
			if (! (derivative instanceof window.File) && ! (derivative instanceof window.Blob))
				throw new Meteor.Error("The derivative to replace must be File or Blob");
			// check(derivative, Blob);
			var image = CropUploader.images.findOne(imageid);
			if(!image) throw new Meteor.Error(401, "the provided image does not exist");
			if(!Roles.userIsInRole(userId, 'admin') && image.userId != userId)
				throw new Meteor.Error(403, "you don't have permission to replace derivative for "+imageid);
			//
			// setup slingshot with uuid from parent
			//
			var uploader = new Slingshot.Upload(CropUploader.name, {uuid: image.uuid });
			var oldfile = name in image['derivatives'] ? image['derivatives'][name] : null;
			// set name of blob so it will put in the right place
			derivative.name = 'derivative/'+name+'/';
			uploader.send(derivative, function (error, thumbnailUrl) {
			  if (error) {
				console.error('Error uploading', uploader.xhr.response);
				alert (error);
			  } else {
				//
				// update the collection object
				//
				var set = {}
				set['derivatives.'+name] = thumbnailUrl;
				CropUploader.images.update(image._id,{$set: set}, function(err,res){
					if(err) console.error(err);
					else console.log('uploaded and updated', res);
				});
				//
				// this should actually happen in the allow.update
				//
				if(oldfile)
				{
					// console.log('delete', oldfile);
					Meteor.call('cropUploaderS3Delete', oldfile, function (error, result) {
						if(error) console.err(error);
					});
				}
			  }
			});
		},
	},
	_hooks: {},
	hooks: function(hooks) {
		var self = this;
		self._hooks = hooks;
	},
	insert:function(image) {
		var self = this;
		if('insert' in self._hooks && typeof self._hooks.insert == 'function')
			image = self._hooks.insert(image);
		if(image)
			CropUploader.images.insert( image );
	},
	crop: {
		template: null,
		save: function(type) {
			var self = this;
			var imageid = self.template.imageid;
			type = type || 'thumbnail';
			self.template.canvas = self.template.cropimage.cropper('getCroppedCanvas',{
			  width: self.template.data.thumbnailWidth,
			  height: self.template.data.thumbnailHeight
			});

			if(self.template.canvas && self.template.canvas.toBlob)
			{
			  self.template.canvas.toBlob(function(blob){
				CropUploader.derivative.replace( imageid, type, blob );
			  },'image/png');
			} else console.log('no canvas', self.template.canvas);
		},
		rotate: function() {
			var self = this;
			self.template.cropimage.cropper('rotate',90);
		}
	},
	init: function(name, directory, consolidate) {
		var self = this;
		directory = directory || '';
		consolidate = consolidate || false;
		check(name, String);
		check(directory, String);
		check(consolidate, Boolean);
		if(directory.length>0 && directory[directory.length-1]!="/") directory+='/';
		self.directory = directory;
		self.name = name;
		// console.log('init', self.directory);
		if(Meteor.isServer)
		{
			var Knox = Npm.require("knox");
			var directive = Slingshot.getDirective(self.name);
			// console.log(directive._directive.region);
			self.knox = Knox.createClient({
				key: directive._directive.AWSAccessKeyId,
				secret: directive._directive.AWSSecretAccessKey,
				region: directive._directive.region,
				bucket: directive._directive.bucket,
			});
			directive._directive.key = function (file, meta) {
				// file
				// {
				//  name: '11075296_10152631810352261_1337077077459889796_n.jpg',
				//  size: 17224,
				//  type: 'image/jpeg'
				// }
				// console.log(file, meta);
				var ext = file.type.split('/')[1];
				if(file.name.match('derivative/'))
				{
					var d = new Date().getTime();
					return CropUploader.directory + file.name + meta.uuid +'.'+d+'.'+ext;
				}
				else
				{
					return CropUploader.directory+meta.uuid+'.'+ext;
				}
			}
			if(consolidate) Meteor.call('cropUploaderConsolidate');
		}
	}
};

if(Meteor.isClient)
{
	CropUploader.errorMessage = new ReactiveVar('');
}<|endoftext|>


<commit_before>// set up ======================================================================
var express = require('express');
var app = express(); 						// create our app w/ express
var mongoose = require('mongoose'); 				// mongoose for mongodb
var port = process.env.PORT || 8080; 				// set the port
var database = require('./config/database'); 			// load the database config
var morgan = require('morgan');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');

// configuration ===============================================================
mongoose.connect(database.remoteUrl); 	// Connect to local MongoDB instance. A remoteUrl is also available (modulus.io)

app.use(express.static(__dirname + '/public')); 		// set the static files location /public/img will be /img for users
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.urlencoded({'extended': 'true'})); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({type: 'application/vnd.api+json'})); // parse application/vnd.api+json as json
app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method-Override header in the request

// routes ======================================================================
require('./app/routes.js')(app);

// listen (start app with node server.js) ======================================
app.listen(port);
console.log("App listening on port " + port);
<commit_msg>some change<commit_after>// set up ======================================================================
var express = require('express');
var app = express(); 						// create our app w/ express
var mongoose = require('mongoose'); 				// mongoose for mongodb
var port = process.env.PORT || 8080; 				// set the port
var database = require('./config/database'); 			// load the database config
var morgan = require('morgan');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');

// configuration ===============================================================
//mongoose.connect(database.remoteUrl); 	// Connect to local MongoDB instance. A remoteUrl is also available (modulus.io)

app.use(express.static(__dirname + '/public')); 		// set the static files location /public/img will be /img for users
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.urlencoded({'extended': 'true'})); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({type: 'application/vnd.api+json'})); // parse application/vnd.api+json as json
app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method-Override header in the request

// routes ======================================================================
require('./app/routes.js')(app);

// listen (start app with node server.js) ======================================
app.listen(port);
console.log("App listening on port " + port);
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016-present, Alejandro Mantilla <@AlejoJamC>.
 * All rights reserved.
 *
 * This source code is licensed under the MIT license found in the LICENSE
 * file in the root directory of this source tree or translated in the assets folder.
 */

/**
 * Environment variables.
 */

require('dotenv').config();

/**
 * Module dependencies.
 */

var express         = require('express'),
    bodyParser      = require('body-parser'),
    errorhandler    = require('errorhandler'),
    favicon         = require('serve-favicon'),
    hbs             = require('express-hbs'),
    methodOverride  = require('method-override'),
    moment          = require('moment'),
    morgan          = require('morgan'),
    path            = require('path'),
    session         = require('express-session'),

    logger          = require('./config/logger').logger,
    webRoutes       = require('./routes/web'),
    apiRoutes       = require('./routes/api'),
    oracle          = require('./config/oracledb'),

    environment     = process.env.APP_ENV,
    port            = process.env.APP_PORT;

logger.info('Environment: ' + environment);

// Testing Oracle database connection.
oracle.TestOracledb();

// Express app instance.
var app = express();

// Load configuration package and environment to the new express app.
// Port.
app.set('port', port);

// Configure view template engine.
// Using `.hbs` for extensions and find partials in `views/partials`.
app.engine('hbs', hbs.express4({
    partialsDir: __dirname + '/views/partials',
    layoutsDir: __dirname + '/views/layouts'
}));
app.set('view engine', 'hbs');
app.set('views', __dirname + '/views');

// Favicon path.
app.use(favicon(__dirname + '/public/favicon.ico'));

// Logger.
// TODO: Arreglar el error entre wiston y morgan
//app.use(morgan('combined', { 'stream': logger.stream }));
app.use(morgan('dev'));

// Lets you use HTTP verbs such as PUT or DELETE in places where the client doesn't support it.
app.use(methodOverride());

// Set Header 'X-Prowered-By'
logger.info('Analytics Website powered by @AlejoJamC');
app.use(function (req, res, next) {
    res.set('X-Powered-By', 'Alejandro Mantilla < @AlejoJamC >');
    next();
});

// Body parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));

// Import static files.
app.use(express.static(path.join(__dirname, 'public')));

// Session.
app.use(session({
    resave: true,
    saveUninitialized: true,
    secret: '3f1l 4 73g 0t d33n yll43r u s1ht d43r n4c u f1'
}));

// Local variables.
// Current year.
app.locals.currentYear = moment().year();
app.locals.currentEnvironment = environment;

// Setup all routes on express router
webRoutes.SetupWebRouter(app);
apiRoutes.SetupApiRouter(app);

// Error handler available environment
var env = process.env.NODE_ENV || environment;
if ('development' === env){
    app.use(errorhandler());
}

app.listen(app.get('port'), function(){
    logger.info('Analytics website is running on http://localhost:' + port + '/');
});<commit_msg>passport setup<commit_after>/**
 * Copyright (c) 2016-present, Alejandro Mantilla <@AlejoJamC>.
 * All rights reserved.
 *
 * This source code is licensed under the MIT license found in the LICENSE
 * file in the root directory of this source tree or translated in the assets folder.
 */

/**
 * Environment variables.
 */

require('dotenv').config();

/**
 * Module dependencies.
 */

var express         = require('express'),
    bodyParser      = require('body-parser'),
    coockieParser   = require('cookie-parser'),
    errorhandler    = require('errorhandler'),
    favicon         = require('serve-favicon'),
    hbs             = require('express-hbs'),
    methodOverride  = require('method-override'),
    moment          = require('moment'),
    morgan          = require('morgan'),
    path            = require('path'),
    passport        = require('passport'),
    session         = require('express-session'),

    logger          = require('./config/logger').logger,
    webRoutes       = require('./routes/web'),
    apiRoutes       = require('./routes/api'),
    oracle          = require('./config/oracledb'),

    environment     = process.env.APP_ENV,
    port            = process.env.APP_PORT;

logger.info('Environment: ' + environment);

// Testing Oracle database connection.
oracle.TestOracledb();

// Express app instance.
var app = express();

// Load configuration package and environment to the new express app.
// Port.
app.set('port', port);

// Configure view template engine.
// Using `.hbs` for extensions and find partials in `views/partials`.
app.engine('hbs', hbs.express4({
    partialsDir: __dirname + '/views/partials',
    layoutsDir: __dirname + '/views/layouts'
}));
app.set('view engine', 'hbs');
app.set('views', __dirname + '/views');

// Favicon path.
app.use(favicon(__dirname + '/public/favicon.ico'));

// Logger.
// TODO: Arreglar el error entre wiston y morgan
//app.use(morgan('combined', { 'stream': logger.stream }));
app.use(morgan('dev'));

// Lets you use HTTP verbs such as PUT or DELETE in places where the client doesn't support it.
app.use(methodOverride());

// Set Header 'X-Prowered-By'
logger.info('Analytics Website powered by @AlejoJamC');
app.use(function (req, res, next) {
    res.set('X-Powered-By', 'Alejandro Mantilla < @AlejoJamC >');
    next();
});

// Body parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));

// Import static files.
app.use(express.static(path.join(__dirname, 'public')));

// Coockies
app.use(coockieParser());

// Session.
app.use(session({
    resave: true,
    saveUninitialized: true,
    secret: '3f1l 4 73g 0t d33n yll43r u s1ht d43r n4c u f1'
}));

// Passport middleware
app.use(passport.initialize());
app.use(passport.session());

// Local variables.
// Current year.
app.locals.currentYear = moment().year();
app.locals.currentEnvironment = environment;

// Setup all routes on express router
webRoutes.SetupWebRouter(app);
apiRoutes.SetupApiRouter(app);

// Error handler available environment
var env = process.env.NODE_ENV || environment;
if ('development' === env){
    app.use(errorhandler());
}

app.listen(app.get('port'), function(){
    logger.info('Analytics website is running on http://localhost:' + port + '/');
});<|endoftext|>


<commit_before>var nomnom          = require('nomnom')
var request         = require('request');
var EventEmitter    = require('events').EventEmitter
var fs              = require('fs')
var util            = require('util')
var path            = require('path')
var stream          = require('stream')

// var http            = require("http");
// var im              = require("imagemagick-stream");
// var im              = require("imagemagick");
// var gm              = require('graphicsmagick-stream')
var gm              = require('gm')

var entulib         = require('./entulib.js')
var helper          = require('./helper.js')

// console.log(process.argv)
var pjson = require('./package.json')
console.log(pjson.name + ' v.' + pjson.version)
// console.log(process)

var opts = nomnom.options({
    USER_ID: {
        abbr     : 'e',
        required : true,
        help     : 'Entity ID for Entu API user'
    },
    API_KEY: {
        abbr     : 'k',
        metavar  : 'STRING',
        required : true,
        help     : 'Authentication key'
    },
}).parse()
opts.HOSTNAME = 'okupatsioon.entu.ee'
// console.log(opts)

HOME_DIR = path.dirname(process.argv[1])
TEMP_DIR = path.resolve(HOME_DIR, 'temp')
PAGE_SIZE_LIMIT = 5
MAX_DOWNLOAD_COUNT = 10
PIC_READ_ENTITY = 'eksponaat'
PIC_READ_PROPERTY = 'photo'
PIC_WRITE_PROPERTY = 'thumb'

var EntuLib = entulib(opts.USER_ID, opts.API_KEY, opts.HOSTNAME)
var connection_counter = 0
var download_counter = 0

ENTU_URI = 'https://' + opts.HOSTNAME + '/'
ENTU_API = ENTU_URI + 'api2/'
ENTU_API_ENTITY = ENTU_API + 'entity-'
ENTU_API_POST_FILE = ENTU_API + 'file/s3'

var fetchNextPage = function fetchNextPage(page) {

    connection_counter ++
    EntuLib.findEntity(PIC_READ_ENTITY, '', PAGE_SIZE_LIMIT, page, function findEntityCB(err, result) {
        connection_counter --
        if (err) {
            console.log('findEntityCB: Can\'t reach Entu', err, result)
            process.exit(99)
        }
        else if (result.error !== undefined) {
            console.log (result.error, 'Failed to fetch from Entu.')
            process.exit(99)
        } else {

            // console.log('Fetched ' + result.result.length + '/' + result.count
            //     + ' results on page ' + page + '/' + Math.ceil(result.count / PAGE_SIZE_LIMIT))
            // console.log(result.result)
            result.result.forEach(function entityLoop(entity) {

                connection_counter ++
                EntuLib.getEntity(entity.id, function getEntityCB(err, result) {
                    connection_counter --
                    // console.log('#:' + connection_counter)
                    if (err) {
                        console.log('getEntityCB: Can\'t reach Entu', err, result)
                        process.exit(99)
                    }
                    else if (result.error !== undefined) {
                        console.log(result.error, 'Failed to fetch from Entu.')
                        process.exit(99)
                    } else {
                        // console.log(entity.id + ':', result.result.displayname, result.result.displayinfo)
                        var photo_property = result.result.properties[PIC_READ_PROPERTY]
                        var code_value = result.result.properties['code'].values ? result.result.properties['code'].values[0].value : ''
                        var nimetus_value = result.result.properties['tag'].values ? result.result.properties['tag'].values[0].value : ''
                        if (photo_property.values) {
                            photo_property.values.forEach(function photoLoop(photo_val) {
                                // console.log(entity.id + '/' + photo_val.id + '[' + photo_val.db_value + ']:', photo_val.value)
                                var ff = new fetchFile(entity.id, photo_val.db_value, photo_val.value, code_value, nimetus_value)
                                .on('error', function fileFetchError(err_msg, err_no) {
                                    console.log('fetchFile error: ', err_msg, err_no)
                                    process.exit(err_no)
                                })
                            })
                        }
                    }
                })
            })

            if (PAGE_SIZE_LIMIT * page < result.count) {
                // console.log('Currently connections: #' + connection_counter + '; downloads: #' + download_counter)
                var fetchIfReady = function fetchIfReady(page) {
                    if (download_counter < MAX_DOWNLOAD_COUNT) {
                        fetchNextPage(page)
                    } else {
                        // console.log('Postponing load of page #' + page)
                        setTimeout(function() { fetchIfReady(page) }, 1000)
                    }
                }
                fetchIfReady(page + 1)
            } else {
                console.log('No more pages for today.')
                // process.exit(0)
                // setTimeout(function() { fetchNextPage(1) }, 1000 * 10 * 1 * 1)
                // setTimeout(function() { fetchNextPage(1) }, 1000 * 60 * 60 * 24)
            }

        }
    })
}

fetchNextPage(1)

var MAX_DOWNLOAD_TIME = 60 * 60 // seconds
var total_download_size = 0
var bytes_downloaded = 0
var decrementProcessCount = function decrementProcessCount() {
    -- download_counter
}
var incrementProcessCount = function incrementProcessCount() {
    ++ download_counter
}
var countLoadingProcesses = function countLoadingProcesses() {
    return download_counter
}

var append_background = path.resolve(HOME_DIR, 'text_background.png')

var THUMB_TYPE = 'jpg'

var fetchFile = function fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) {
    incrementProcessCount()
    EventEmitter.call(this)
    var self = this

    var t = setTimeout(function() {
        decrementProcessCount()
        self.emit('error', 'Error: ' + fetch_uri + ' timed out!', 95)
    }, MAX_DOWNLOAD_TIME * 1000)

    var fetch_uri = 'https://' + opts.HOSTNAME + '/api2/file-' + file_id
    var download_filename = path.resolve(TEMP_DIR, file_id + '.' + THUMB_TYPE)

    gm(request
        .get(fetch_uri)
        .on('error', function(err) {
            decrementProcessCount()
            console.log('WARNING: request: ' + fetch_uri , err)
            setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
            return
        })
        .on('response', function response_handler( response ) {
            var filesize = response.headers['content-length']
            // console.log(response.headers)
            if (filesize === undefined) {
                decrementProcessCount()
                console.log('WARNING: filesize === undefined: ' + fetch_uri )
                setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
                return
            } else {
                total_download_size += Number(filesize)
                // console.log('Downloading: ' + fetch_uri + ' - ' + filesize + ' bytes.')
            }
            response.on('data', function(chunk) {
                bytes_downloaded += chunk.length
                if (filesize === undefined) {
                    // console.log('WARNING: filesize === undefined:' + fetch_uri + ' loaded chunk of ' + chunk.length + ' bytes.')
                    total_download_size += chunk.length
                    // console.log(chunk.toString('utf8'))
                }
                // console.log('Progress: ' + file_name + ' - ' + helper.bytesToSize(total_download_size) + ' - ' + helper.bytesToSize(bytes_downloaded) + ' = ' + helper.bytesToSize(total_download_size - bytes_downloaded) )
            })
            response.on('end', function() {
                if (response.statusCode === 200) {
                    // console.log('Finished: ' + fetch_uri + ' - ' + helper.bytesToSize(total_download_size) + ' - ' + helper.bytesToSize(bytes_downloaded) + ' = ' + helper.bytesToSize(total_download_size - bytes_downloaded) )
                }
                decrementProcessCount()
                clearTimeout(t)
            })
        })
    )
    .resize(800, 530)
    .stream(THUMB_TYPE, function(err, stdout, stderr) {
        gm(stdout)
        .append(append_background)
        // .append(gm(240, 70))
        .stream(function(err, stdout, stderr) {
            gm(stdout)
            .drawText(0, 15, 'Okupatsioonide Muuseum #' + exp_nr + '\n' + nimetus + '\nokupatsioon.entu.ee', 'south')
            .stream(function(err, stdout, stderr) {
                if (err) {
                    console.log('WARNING: ' + fetch_uri , err, stdout, stderr)
                    setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
                    return
                }
                var f = fs.createWriteStream(download_filename)
                stdout.pipe(f)
                f.on('finish', function() {
                    if (f.bytesWritten === 0) {
                        console.log('WARNING: f.bytesWritten === 0: ' + fetch_uri )
                        setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
                        return
                    }
                    console.log('bytes written: ' + f.bytesWritten);
                    incrementProcessCount()
                    EntuLib.addFile(entity_id, PIC_READ_ENTITY + '-' + PIC_WRITE_PROPERTY, file_name, 'image/' + THUMB_TYPE, f.bytesWritten, download_filename, function addFileCB(err, result) {
                        decrementProcessCount()
                        if (err) {
                            console.log('WARNING: addFileCB: ' + fetch_uri , err, result)
                            setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
                            return
                        }
                        console.log('SUCCESS: ' + fetch_uri + '|' + helper.bytesToSize(f.bytesWritten) + 'b')
                    })
                })
            })
        })
    })

}
util.inherits(fetchFile, EventEmitter)

var pulse_cnt = 0
var pulse = function pulse(ms) {
    console.log('tick ' + (pulse_cnt ++))
    setTimeout(function() { pulse(ms) }, ms)
}
pulse(60 * 1000)

/*
BUILD, RUN and LOG
docker kill puhh
docker rm puhh
docker build -t mitselek/pildimaag ~/Documents/github/pildimaag/
docker run -d -v ~/Documents/github/pildimaag/:/pildimaag/ --name puhh mitselek/pildimaag:latest -e 155005 -k 378c2VuY
docker logs -f puhh

RESTART and LOG
docker kill puhh
docker start puhh
docker logs -f --tail=15 puhh
*/
<commit_msg>better output<commit_after>var nomnom          = require('nomnom')
var request         = require('request');
var EventEmitter    = require('events').EventEmitter
var fs              = require('fs')
var util            = require('util')
var path            = require('path')
var stream          = require('stream')

// var http            = require("http");
// var im              = require("imagemagick-stream");
// var im              = require("imagemagick");
// var gm              = require('graphicsmagick-stream')
var gm              = require('gm')

var entulib         = require('./entulib.js')
var helper          = require('./helper.js')

// console.log(process.argv)
var pjson = require('./package.json')
console.log(pjson.name + ' v.' + pjson.version)
// console.log(process)

var opts = nomnom.options({
    USER_ID: {
        abbr     : 'e',
        required : true,
        help     : 'Entity ID for Entu API user'
    },
    API_KEY: {
        abbr     : 'k',
        metavar  : 'STRING',
        required : true,
        help     : 'Authentication key'
    },
}).parse()
opts.HOSTNAME = 'okupatsioon.entu.ee'
// console.log(opts)

HOME_DIR = path.dirname(process.argv[1])
TEMP_DIR = path.resolve(HOME_DIR, 'temp')
PAGE_SIZE_LIMIT = 5
MAX_DOWNLOAD_COUNT = 10
PIC_READ_ENTITY = 'eksponaat'
PIC_READ_PROPERTY = 'photo'
PIC_WRITE_PROPERTY = 'thumb'

var EntuLib = entulib(opts.USER_ID, opts.API_KEY, opts.HOSTNAME)
var connection_counter = 0
var download_counter = 0

ENTU_URI = 'https://' + opts.HOSTNAME + '/'
ENTU_API = ENTU_URI + 'api2/'
ENTU_API_ENTITY = ENTU_API + 'entity-'
ENTU_API_POST_FILE = ENTU_API + 'file/s3'

var fetchNextPage = function fetchNextPage(page) {

    connection_counter ++
    EntuLib.findEntity(PIC_READ_ENTITY, '', PAGE_SIZE_LIMIT, page, function findEntityCB(err, result) {
        connection_counter --
        if (err) {
            console.log('findEntityCB: Can\'t reach Entu', err, result)
            process.exit(99)
        }
        else if (result.error !== undefined) {
            console.log (result.error, 'Failed to fetch from Entu.')
            process.exit(99)
        } else {

            // console.log('Fetched ' + result.result.length + '/' + result.count
            //     + ' results on page ' + page + '/' + Math.ceil(result.count / PAGE_SIZE_LIMIT))
            // console.log(result.result)
            result.result.forEach(function entityLoop(entity) {

                connection_counter ++
                EntuLib.getEntity(entity.id, function getEntityCB(err, result) {
                    connection_counter --
                    // console.log('#:' + connection_counter)
                    if (err) {
                        console.log('getEntityCB: Can\'t reach Entu', err, result)
                        process.exit(99)
                    }
                    else if (result.error !== undefined) {
                        console.log(result.error, 'Failed to fetch from Entu.')
                        process.exit(99)
                    } else {
                        // console.log(entity.id + ':', result.result.displayname, result.result.displayinfo)
                        var photo_property = result.result.properties[PIC_READ_PROPERTY]
                        var code_value = result.result.properties['code'].values ? result.result.properties['code'].values[0].value : ''
                        var nimetus_value = result.result.properties['tag'].values ? result.result.properties['tag'].values[0].value : ''
                        if (photo_property.values) {
                            photo_property.values.forEach(function photoLoop(photo_val) {
                                // console.log(entity.id + '/' + photo_val.id + '[' + photo_val.db_value + ']:', photo_val.value)
                                var ff = new fetchFile(entity.id, photo_val.db_value, photo_val.value, code_value, nimetus_value)
                                .on('error', function fileFetchError(err_msg, err_no) {
                                    console.log('fetchFile error: ', err_msg, err_no)
                                    process.exit(err_no)
                                })
                            })
                        }
                    }
                })
            })

            if (PAGE_SIZE_LIMIT * page < result.count) {
                // console.log('Currently connections: #' + connection_counter + '; downloads: #' + download_counter)
                var fetchIfReady = function fetchIfReady(page) {
                    if (download_counter < MAX_DOWNLOAD_COUNT) {
                        fetchNextPage(page)
                    } else {
                        // console.log('Postponing load of page #' + page)
                        setTimeout(function() { fetchIfReady(page) }, 1000)
                    }
                }
                fetchIfReady(page + 1)
            } else {
                console.log('No more pages for today.')
                // process.exit(0)
                // setTimeout(function() { fetchNextPage(1) }, 1000 * 10 * 1 * 1)
                // setTimeout(function() { fetchNextPage(1) }, 1000 * 60 * 60 * 24)
            }

        }
    })
}

fetchNextPage(1)

var MAX_DOWNLOAD_TIME = 60 * 60 // seconds
var total_download_size = 0
var bytes_downloaded = 0
var decrementProcessCount = function decrementProcessCount() {
    -- download_counter
}
var incrementProcessCount = function incrementProcessCount() {
    ++ download_counter
}
var countLoadingProcesses = function countLoadingProcesses() {
    return download_counter
}

var append_background = path.resolve(HOME_DIR, 'text_background.png')

var THUMB_TYPE = 'jpg'

var fetchFile = function fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) {
    incrementProcessCount()
    EventEmitter.call(this)
    var self = this

    var t = setTimeout(function() {
        decrementProcessCount()
        self.emit('error', 'Error: ' + fetch_uri + ' timed out!', 95)
    }, MAX_DOWNLOAD_TIME * 1000)

    var fetch_uri = 'https://' + opts.HOSTNAME + '/api2/file-' + file_id
    var download_filename = path.resolve(TEMP_DIR, file_id + '.' + THUMB_TYPE)

    gm(request
        .get(fetch_uri)
        .on('error', function(err) {
            decrementProcessCount()
            console.log('WARNING: request: ' + fetch_uri , err)
            setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
            return
        })
        .on('response', function response_handler( response ) {
            var filesize = response.headers['content-length']
            // console.log(response.headers)
            if (filesize === undefined) {
                decrementProcessCount()
                console.log('WARNING: filesize === undefined: ' + fetch_uri )
                setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
                return
            } else {
                total_download_size += Number(filesize)
                // console.log('Downloading: ' + fetch_uri + ' - ' + filesize + ' bytes.')
            }
            response.on('data', function(chunk) {
                bytes_downloaded += chunk.length
                if (filesize === undefined) {
                    // console.log('WARNING: filesize === undefined:' + fetch_uri + ' loaded chunk of ' + chunk.length + ' bytes.')
                    total_download_size += chunk.length
                    // console.log(chunk.toString('utf8'))
                }
                // console.log('Progress: ' + file_name + ' - ' + helper.bytesToSize(total_download_size) + ' - ' + helper.bytesToSize(bytes_downloaded) + ' = ' + helper.bytesToSize(total_download_size - bytes_downloaded) )
            })
            response.on('end', function() {
                if (response.statusCode === 200) {
                    // console.log('Finished: ' + fetch_uri + ' - ' + helper.bytesToSize(total_download_size) + ' - ' + helper.bytesToSize(bytes_downloaded) + ' = ' + helper.bytesToSize(total_download_size - bytes_downloaded) )
                }
                decrementProcessCount()
                clearTimeout(t)
            })
        })
    )
    .resize(800, 530)
    .stream(THUMB_TYPE, function(err, stdout, stderr) {
        gm(stdout)
        .append(append_background)
        // .append(gm(240, 70))
        .stream(function(err, stdout, stderr) {
            gm(stdout)
            .drawText(0, 15, 'Okupatsioonide Muuseum #' + exp_nr + '\n' + nimetus + '\nokupatsioon.entu.ee', 'south')
            .stream(function(err, stdout, stderr) {
                if (err) {
                    console.log('WARNING: ' + fetch_uri , err, stdout, stderr)
                    setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
                    return
                }
                var f = fs.createWriteStream(download_filename)
                stdout.pipe(f)
                f.on('finish', function() {
                    if (f.bytesWritten === 0) {
                        console.log('WARNING: f.bytesWritten === 0: ' + fetch_uri )
                        setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
                        return
                    }
                    // console.log('bytes written: ' + f.bytesWritten);
                    incrementProcessCount()
                    EntuLib.addFile(entity_id, PIC_READ_ENTITY + '-' + PIC_WRITE_PROPERTY, file_name, 'image/' + THUMB_TYPE, f.bytesWritten, download_filename, function addFileCB(err, result) {
                        decrementProcessCount()
                        if (err) {
                            console.log('WARNING: addFileCB: ' + fetch_uri , err, result)
                            setTimeout(function() { fetchFile(entity_id, file_id, file_name, exp_nr, nimetus) }, 10 * 1000)
                            return
                        }
                        console.log('SUCCESS: ' + fetch_uri + '|' + helper.bytesToSize(f.bytesWritten) + 'b')
                    })
                })
            })
        })
    })

}
util.inherits(fetchFile, EventEmitter)

var pulse_cnt = 0
var pulse = function pulse(ms) {
    console.log('tick ' + (pulse_cnt ++))
    setTimeout(function() { pulse(ms) }, ms)
}
pulse(60 * 1000)

/*
BUILD, RUN and LOG
docker kill puhh
docker rm puhh
docker build -t mitselek/pildimaag ~/Documents/github/pildimaag/
docker run -d -v ~/Documents/github/pildimaag/:/pildimaag/ --name puhh mitselek/pildimaag:latest -e 155005 -k 378c2VuY
docker logs -f puhh

RESTART and LOG
docker kill puhh
docker start puhh
docker logs -f --tail=15 puhh
*/
<|endoftext|>