<commit_before>(function ($) {
    var genericError = {
        it: "Si è verificato un errore tecnico. Non è possibile caricare i Twits!",
        en: "A technical error has occoured. Cannot load Twits!",
        es: "Se ha producido un error técnico. No se puede cargar los Twits!"
    };
    /* SHARED FUNCTIONS */
    var closeBox = function () {
        var el = $(this).parents(".twit-fetcher-container");
        el.fadeOut(undefined, function () {
            el.remove();
        });
    };
    var generateErrorBox = function (text) {
        return '

' + text + '

';
    };

    var generateSpinner = function () {
        return '

';
    };

    var generateYTframe = function (src, columnsClass) {
        return '

';
    };
    var decodeUrl = function (t) {
        var e = t.split(" ");
        this.url = decodeURIComponent(e[0].trim()),
            this.width = +e[1].replace(/w$/, "").trim()
    };
    var checkDevice = function (t, e, n) {
        var i, o, a, s, h = window;
        if (t = h.devicePixelRatio ? t * h.devicePixelRatio : t,
                o = e.split(",").map(function (t) {
                    return new decodeUrl(t.trim())
                }),
                n)
            for (s = 0; s < o.length; s++)
                o[s].url === n && (i = o[s]);
        return a = o.reduce(function (e, n) {
            return n.width < e.width && n.width >= t ? n : e
        }, o[0]),
            i && i.width > a.width ? i : a
    };

    var fixSrc = function (img) {
        var n, srcSet = $(img).attr("data-srcset"), o = $(img)[0].src;
        if (!!srcSet) {
            n = checkDevice($(window).width(), srcSet, o);
            return n.url;
        }
        return "";
    };
    var imageExists = function (src) {

        var deferred = $.Deferred();

        var image = new Image();
        image.onerror = function () {
            deferred.resolve(false);
        };
        image.onload = function () {
            deferred.resolve(true);
        };
        image.src = src;

        return deferred;
    };
    var datefix = function (dateString, lang) {
        var dateStringISO = dateString.replace(/([+\-]\d\d)(\d\d)$/, "$1:$2");
        d = new Date(dateStringISO);
        var hh = (d.getHours()) > 9 ?
            (d.getHours()) : "0" + (d.getHours());
        var mm = (d.getMinutes()) > 9 ?
            (d.getMinutes()) : "0" + (d.getMinutes());
        var day = (d.getDate() + 1) > 9 ?
            (d.getDate()) : "0" + (d.getDate());
        var month = d.getMonth();
        var months = {
            it: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"],
            en: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
            es: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"]
        };
        if (!!months[lang] && !!months[lang][month])
            month = months[lang][month];
        else
            month = months["en"][month];
        var at = {
            it: " alle ",
            en: " at ",
            es: " a las "
        };
        var at = !!at[lang] ? at[lang] : at["en"];
        var d = day + " " + month + at + hh + ":" + mm;
        return d;
    };
    var strTrim = function (t, l) {
        t = t.substring(0, l);
        return (t);
    };
    var w = function (a) {
        return a.replace(/]*>(.*?)<\/b>/gi, function (a, f) {
            return f;
        }).replace(/class=".*?"|data-query-source=".*?"|dir=".*?"|rel=".*?"/gi, "");
    };

    var twtCallback = function (response, settings, $target) {

        var list = $(response.body).find('*[data-scribe="component:tweet"]');
        var user = [], usrLnk = [], usrName = [], a = [], b = [], avatarImg = [], d = [], e = [], p = [];

        list.each(function () {
            var cur = $(this);

            user.push(cur.find("[data-scribe='element:name']").text());
            usrLnk.push(cur.find("[data-scribe='element:user_link']").attr("href"));

            var retweet = cur.find(".retweet-credit").html() != undefined;

            if (!settings.showRetweet && retweet) {
                return true;
            }

            var shortUrl = cur.find('a[data-scribe="element:url"]');
            if (shortUrl.length > 0) {
                shortUrl = shortUrl.attr("href");
                //shortUrl = strTrim(shortUrl, 50) + "...";
                cur.find('a[data-scribe="element:url"]').empty().append(shortUrl);
            }
            var postContent = $(cur.find(".timeline-Tweet-text"));
            var postLinks = postContent.find("a");

            postLinks.each(function () {
                var extRef = $(this).attr("data-expanded-url");
                if (!!extRef) {
                    $(this).attr("href", extRef);
                    $(this).html(extRef);
                }
            });

            a.push(postContent.html());
            b.push(cur.find(".data-tweet-id"));

            avatarImg.push(
                settings.avatar !== "default" ?
                    settings.avatar : cur.find("[data-scribe='element:avatar']").attr("data-src-1x")
            );

            p.push(cur.find('[data-scribe="element:mini_timestamp"]').attr("href"));
            usrName.push(cur.find('[data-scribe="element:screen_name"]').html());
            d.push(datefix(cur.find(".dt-updated").attr("datetime"), settings.lang));
            if (settings.showImages === true) {
                var row = $('

');
                var media = $(cur.find("div.MediaCard-media"));
                media.find("footer").remove();
                var media = media.find("a").not('[role="presentation"]');
                var countMedia = media.length;
                var columnsClass = countMedia > 1 ? "col-xs-6" : "col-xs-10 col-xs-offset-1";
                var columnHtml = '

';
                media.each(function (index) {
                    var elem = $(this);
                    elem.attr("target", "_blank");
                    var playerSrc = elem.attr("data-player-src");
                    if (!!playerSrc) {
                        if (playerSrc.indexOf("youtube") >= 0) {
                            $("body").one("click", '[data-scribe="element:play_button"]', function (event) {
                                event.preventDefault();
                                var target = $(event.target).parents(".row:first");
                                target.empty().append(generateYTframe(playerSrc, columnsClass));
                            });
                            var mediaResult = $(columnHtml).append(elem.html());
                            row.append(mediaResult);
                        }
                        return true;
                    }
                    var mediaResult = elem.wrap(columnHtml);
                    if (index === countMedia - 1) {
                        if (countMedia % 2 !== 0 && countMedia > 1) {
                            elem.parent().addClass("col-offset-xs-3");
                        }
                    }
                    innerImg = elem.find("img");
                    var fixedSrc = fixSrc(innerImg);
                    if (fixedSrc !== "")
                        innerImg.attr("src", fixedSrc);
                    else {
                        elem.remove();
                        return true;
                    }
                    row.append(mediaResult);
                });

                e.push(row[0].outerHTML);
            }
            if (a.length === parseInt(settings.maxTweets))
                return false;
        });

        var html = '
\n';

        for (var i = 0; i < a.length; i++) {
            html += '
\n' +
                '
\n' +
                '\n' +
                '\n' +
                '\n' +
                '
\n' +
                '
\n' +
                '
\n' +
                '
\n' +
                '\n' +
                usrName[i] + '\n' +
                '\n - \n';

            if (settings.enablePermalink === true) {
                html += '\n' +
                    '' + d[i] + '\n' +
                    '\n';
            }
            else {
                html += '' + d[i] + '\n';
            }
            html += '
\n' +
                '
\n' +
                '
\n' +
                '
\n' +
                '
' + w(a[i]) + '
\n';
            if (settings.showImages === true && e[i] !== null) {
                html += e[i];
            }
            html += '
\n';
            html += '
\n';
            html += '
\n' +
                '
\n';
        }

        html += "
";
        $(html).find("*").removeAttr("data-scribe");
        $target.append(html);

    };

    $.fn.twitterFetcher = function (settings) {

        settings = jQuery.extend({
            avatar: "default",
            uniqueId: null,
            widgetid: null,
            maxTweets: 20,
            enableLinks: true,
            showImages: false,
            showRetweet: true,
            lang: "it",
            enablePermalink: false
        }, settings);

        if (typeof settings.widgetid === "undefined" || settings.widgetid === null) {
            console.error("TWITLINE: WIDGETID MUST BE DEFINED!");
            return false;
        }

        if (settings.avatar !== "default" && !imageExists(settings.avatar)) {
            settings.avatar = "default";
            console.warn("Invalid avatar override: setting default avatar");
        }

        return this.each(function () {
            var $target = $(this);
            $target.addClass("twit-fetcher-container");
            var spinner = $(generateSpinner());
            $target.append(spinner);
            var protocol = window.location.protocol === "https:" ? "https" : "http";
            var url = protocol + "://cdn.syndication.twimg.com/widgets/timelines/" + settings.widgetid + "?&lang=" + (settings.lang || "en") +
                "&suppress_response_codes=true&rnd=" + Math.random();

            var ajaxConfig = {
                url: url,
                contentType: 'application/json',
                cache: 'true',
                dataType: 'jsonp'
            };

            $.ajax(ajaxConfig).done(function (data) {
                if (data.headers.status === 404) {
                    var error = data.headers.message || genericError[settings.lang || "en"];
                    $target.empty().append(generateErrorBox(error));
                    $("body").off("click.twitsFetcher").on("click.twitsFetcher", ".twit-fetcher-close", closeBox);
                    return;
                }
                twtCallback(data, settings, $target);
                spinner.fadeOut();
            });

            return false; //PREVENT USING COLLECTIONS
        });
    };

})(jQuery);
<commit_msg>TwitFetcher FIXED!!!<commit_after>(function ($) {
	var script = null;
	var twtCount = 0;
	window.__twttrf = {

	};

    var genericError = {
        it: "Si è verificato un errore tecnico. Non è possibile caricare i Twits!",
        en: "A technical error has occoured. Cannot load Twits!",
        es: "Se ha producido un error técnico. No se puede cargar los Twits!"
    };
    /* SHARED FUNCTIONS */
    var closeBox = function(){
        var el = $(this).parents(".twit-fetcher-container");
		el.fadeOut(undefined,function(){
		  el.remove();
		});
    };
    var generateErrorBox = function(text){
        return '

' + text + '

';
    };

    var generateSpinner = function(){
        return '

';
    };

    var generateYTframe = function (src,columnsClass) {
        return '

';
    };
    var decodeUrl = function (t) {
        var e = t.split(" ");
        this.url = decodeURIComponent(e[0].trim()),
            this.width = +e[1].replace(/w$/, "").trim()
    };
    var checkDevice = function (t, e, n) {
        var i, o, a, s, h = window;
        if (t = h.devicePixelRatio ? t * h.devicePixelRatio : t,
                o = e.split(",").map(function (t) {
                    return new decodeUrl(t.trim())
                }),
                n)
            for (s = 0; s < o.length; s++)
                o[s].url === n && (i = o[s]);
        return a = o.reduce(function (e, n) {
            return n.width < e.width && n.width >= t ? n : e
        }, o[0]),
            i && i.width > a.width ? i : a
    };

    var fixSrc = function (img) {
        var n;
		var srcSet = $(img).attr("data-srcset");
		var o = $(img).attr("src");
        if (!!srcSet) {
            n = checkDevice($(window).width(), srcSet, o);
            return n.url;
        }
        return "";
    };
    var imageExists = function (src) {

        var deferred = $.Deferred();

        var image = new Image();
        image.onerror = function () {
            deferred.resolve(false);
        };
        image.onload = function () {
            deferred.resolve(true);
        };
        image.src = src;

        return deferred;
    };
    var datefix = function (dateString, lang) {
        var dateStringISO = dateString.replace(/([+\-]\d\d)(\d\d)$/, "$1:$2");
        d = new Date(dateStringISO);
        var hh = (d.getHours()) > 9 ?
            (d.getHours()) : "0" + (d.getHours());
        var mm = (d.getMinutes()) > 9 ?
            (d.getMinutes()) : "0" + (d.getMinutes());
        var day = (d.getDate() + 1) > 9 ?
            (d.getDate()) : "0" + (d.getDate());
        var month = d.getMonth();
        var months = {
            it: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"],
            en: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
            es: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"]
        };
        if (!!months[lang] && !!months[lang][month])
            month = months[lang][month];
        else
            month = months["en"][month];
        var at = {
            it: " alle ",
            en: " at ",
            es: " a las "
        };
        var at = !!at[lang] ? at[lang] : at["en"];
        var d = day + " " + month + at + hh + ":" + mm;
        return d;
    };
    var strTrim = function (t, l) {
        t = t.substring(0, l);
        return (t);
    };
    var w = function (a) {
        return a.replace(/]*>(.*?)<\/b>/gi, function (a, f) {
            return f;
        }).replace(/class=".*?"|data-query-source=".*?"|dir=".*?"|rel=".*?"/gi, "");
    };

    var  twtCallback = function (response, settings, $target) {

        var list = $(response.body).find('*[data-scribe="component:tweet"]');
        var user = [], usrLnk = [], usrName = [], a = [], b = [], avatarImg = [], d = [], e = [], p = [];

        list.each(function () {
            var cur = $(this);

            user.push(cur.find("[data-scribe='element:name']").text());
            usrLnk.push(cur.find("[data-scribe='element:user_link']").attr("href"));

            var retweet = cur.find(".retweet-credit").html() != undefined;

            if (!settings.showRetweet && retweet) {
                return true;
            }

            var shortUrl = cur.find('a[data-scribe="element:url"]');
            if (shortUrl.length > 0) {
                shortUrl = shortUrl.attr("href");
                //shortUrl = strTrim(shortUrl, 50) + "...";
                cur.find('a[data-scribe="element:url"]').empty().append(shortUrl);
            }
            var postContent = $(cur.find(".timeline-Tweet-text"));
            var postLinks = postContent.find("a");

            postLinks.each(function () {
                var extRef = $(this).attr("data-expanded-url");
                if (!!extRef) {
                    $(this).attr("href", extRef);
                    $(this).html(extRef);
                }
            });

            a.push(postContent.html());
            b.push(cur.find(".data-tweet-id"));

            avatarImg.push(
                settings.avatar !== "default" ?
                    settings.avatar : cur.find("[data-scribe='element:avatar']").attr("data-src-1x")
            );

            p.push(cur.find('[data-scribe="element:mini_timestamp"]').attr("href"));
            usrName.push(cur.find('[data-scribe="element:screen_name"]').html());
            d.push(datefix(cur.find(".dt-updated").attr("datetime"), settings.lang));
            if (settings.showImages === true) {
                var row = $('

');
                var media = $(cur.find("div.MediaCard-media"));
                media.find("footer").remove();
                var media = media.find("a").not('[role="presentation"]');
                var countMedia = media.length;
                var columnsClass = countMedia > 1 ? "col-xs-6" : "col-xs-10 col-xs-offset-1";
                var columnHtml = '

';
                media.each(function (index) {
                    var elem = $(this);
                    elem.attr("target","_blank");
                    var playerSrc = elem.attr("data-player-src");
                    if (!!playerSrc) {
                        if (playerSrc.indexOf("youtube") >= 0) {
                            $("body").one("click", '[data-scribe="element:play_button"]', function (event) {
                                event.preventDefault();
                                var target = $(event.target).parents(".row:first");
                                target.empty().append(generateYTframe(playerSrc,columnsClass));
                            });
                            var mediaResult = $(columnHtml).append(elem.html());
                            row.append(mediaResult);
                        }
                        return true;
                    }
                    var mediaResult = elem.wrap(columnHtml);
                    if (index === countMedia - 1) {
                        if (countMedia % 2 !== 0 && countMedia > 1) {
                            elem.parent().addClass("col-offset-xs-3");
                        }
                    }
                    innerImg = elem.find("img");
                    var fixedSrc = fixSrc(innerImg);
                    if (fixedSrc !== "")
                        innerImg.attr("src", fixedSrc);
                    else {
                        elem.remove();
                        return true;
                    }
                    row.append(mediaResult);
                });

                e.push(row[0].outerHTML);
            }
            if (a.length === parseInt(settings.maxTweets))
                return false;
        });

        var html = '
\n';

        for (var i = 0; i < a.length; i++) {
            html += '
\n' +
                '
\n' +
                '\n' +
                '\n' +
                '\n' +
                '
\n' +
                '
\n' +
                '
\n' +
                '
\n' +
                '\n' +
                usrName[i] + '\n' +
                '\n - \n';

            if (settings.enablePermalink === true) {
                html += '\n' +
                    '' + d[i] + '\n' +
                    '\n';
            }
            else {
                html += '' + d[i] + '\n';
            }
            html += '
\n' +
                '
\n' +
                '
\n' +
                '
\n' +
                '
' + w(a[i]) + '
\n';
            if (settings.showImages === true && e[i] !== null) {
                html += e[i];
            }
            html += '
\n';
            html += '
\n';
            html += '
\n' +
                '
\n';
        }

        html += "
";
        $(html).find("*").removeAttr("data-scribe");
        $target.append(html);

    };

    $.fn.twitterFetcher = function (settings) {

        settings = jQuery.extend({
            avatar: "default",
            uniqueId: null,
            widgetid: null,
            maxTweets: 20,
            enableLinks: true,
            showImages: false,
            showRetweet: true,
            lang: "it",
            enablePermalink: false
        }, settings);

        if (typeof settings.widgetid === "undefined" || settings.widgetid === null) {
            console.error("TWITLINE: WIDGETID MUST BE DEFINED!");
            return false;
        }

        if (settings.avatar !== "default" && !imageExists(settings.avatar)) {
            settings.avatar = "default";
            console.warn("Invalid avatar override: setting default avatar");
        }

        return this.each(function () {
            twtCount++;
			var $target = $(this);
            $target.addClass("twit-fetcher-container");
            var spinner = $(generateSpinner());
            $target.append(spinner);
            var protocol = window.location.protocol === "https:" ? "https" : "http";
			var callbackProp = "callback"+twtCount;
			window.__twttrf[callbackProp] = function(data){
				console.info("TWT CALLBACK DATA", data);
				spinner.fadeOut();
				twtCallback(data, settings, $target);
			};

            var url = protocol + "://cdn.syndication.twimg.com/widgets/timelines/" + settings.widgetid + "?&lang=" + (settings.lang || "en") +
                "&callback=__twttrf." + callbackProp + "&suppress_response_codes=true&rnd=" + Math.random();

			var url2 = protocol + "://cdn.syndication.twimg.com/widgets/timelines/" + "502160051226681344" + "?&lang=en&callback=__twttrf.callback&suppress_response_codes=true&rnd=0.5226350122345014"

			var url3 = protocol + "://cdn.syndication.twimg.com/widgets/timelines/" + "502160051226681344" + "?&lang=en&callback=__twtcbs.callback&suppress_response_codes=true&rnd=0.5226350122345014"

            /*$.ajax({
                url: url,
                contentType: 'application/json',
                cache: 'true',
                dataType: 'json'
            })
			*/
			/*$.getJSON(url).done(function (data) {
                if(data.headers.status === 404){
                    var error = data.headers.message || genericError[settings.lang || "en"];
                    $target.empty().append(generateErrorBox(error));
                    $("body").off("click.twitsFetcher").on("click.twitsFetcher",".twit-fetcher-close", closeBox);
                    return;
                }
                twtCallback(data, settings, $target);
                spinner.fadeOut();
            });*/

			var head = document.getElementsByTagName("head")[0];
			if(script !== null){
				head.removeChild(script);
			}
			script = document.createElement("script");
			script.type = "text/javascript";
			script.onerror = function(a){
				console.info("TFERROR", a);
				var error = genericError[settings.lang || "en"];
				$target.empty().append(generateErrorBox(error));
				$("body").off("click.twitsFetcher").on("click.twitsFetcher",".twit-fetcher-close", closeBox);
			}

			script.src = url;
			head.appendChild(script);

            return false; //PREVENT USING COLLECTIONS
        });
    };

})(jQuery);
<|endoftext|>


<commit_before>require('blanket')({
    pattern: "//^((?!\/test|node_modules\/).)*$/ig"
});
<commit_msg>Simplify instrumentation pattern.<commit_after>require('blanket')({
    pattern: '/espower/lib/'
});
<|endoftext|>


<commit_before>/*
 Copyright 2012 - $Date $ by PeopleWare n.v.

 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.
 */

define(["dojo/_base/declare",
        "../../ANewCrudDao2",
        "../../_Cache2", "../../UrlBuilder",
        "../../PersistentObject", "../../VersionedPersistentObject", "../../AuditableObject", "../../IdNotFoundException",
        "dojo/Deferred"],
  function(declare,
           CrudDao,
           _Cache, UrlBuilder,
           PersistentObject, VersionedPersistentObject, AuditableObject, IdNotFoundException,
           Deferred) {

    function markDeletedFromServer(cache, p) {
      var entry = cache.get(p);
      if (!entry) {
        throw "ERROR: to delete, p must be in cache";
      }
      var json = p.toJSON();
      json.persistenceId = null;
      if (p.isInstanceOf(VersionedPersistentObject)) {
        json.persistenceVersion = null;
      }
      if (p.isInstanceOf(AuditableObject)) {
        json.createdAt = null;
        json.createdBy = null;
        json.lastModifiedAt = null;
        json.lastModifiedBy = null;
      }
      p.reload(json); // should remove from cache
    }

    var CrudDaoMock = declare([CrudDao], {
      // summary:
      //   This is a mock of CrudDao. We inherit from CrudDao, and overwrite meaningful methods.
      //   All methods are supported. They're behavior can be changed for a number of cases, with
      //   extra properties on parameters that are already there.
      //   Private. Contains a CacheEntry for each retrieved object, that is not yet released.

      constructor: function() {
        this.urlBuilder = new UrlBuilder();
        this.revive = function(/*Object*/ json, /*Object*/ referer, /*_Cache*/ cache) {
          return null; // TODO rewrite to use the reviver
        }
      },

      retrieve: function(/*String*/ serverType, /*Number*/ persistenceId, /*Any*/ referer) {
        // description:
        //   referer.error will result in that error
        //   referer.idNotFoundException will result in that exception
        //   referer.resultJson will be the result, of type referer.PoType
        //   referer.waitMillis is the time the promise will take

        var cachedPo = this._cache.getByTypeAndId(serverType, persistenceId);
        var p = null;
        if (! cachedPo) {
          p = new referer.PoType();
          p.reload(referer.resultJson);
          p._changeAttrValue("persistenceId", persistenceId);
        }
        else {
          p = cachedPo;
        }
        this.track(p, referer);
        var thisDao = this;
        var resultDeferred = new Deferred();
        if (referer.error) {
          setTimeout(
            function() {
              resultDeferred.reject("ERROR: could not GET " + persistenceId + " (" + referer.error + ")");
            },
            referer.waitMillis
          );
        }
        else if (referer.idNotFoundException) {
          setTimeout(
            function() {
              markDeletedFromServer(thisDao._cache, p);
              resultDeferred.reject(referer.idNotFoundException);
            },
            referer.waitMillis
          );
        }
        else {
          setTimeout(
            function() {
              p.reload(referer.resultJson);
              resultDeferred.resolve(p);
            },
            referer.waitMillis
          );
        }
        return resultDeferred.promise;
      },

      create: function(/*PersistentObject*/ p, /*Any*/ referer) {
        // description:
        //   p.error will result in that error
        //   p.semanticException will result in that exception
        //   p.waitMillis is the time the promise will take

        var thisDao = this;
        var resultDeferred = new Deferred();
        if (p.error) {
          setTimeout(
            function() {
              resultDeferred.reject("ERROR: could not POST " + p.toString() + " (" + p.error + ")");
            },
            p.waitMillis
          );
        }
        else if (p.semanticException) {
          setTimeout(
            function() {
              resultDeferred.reject(p.semanticException);
            },
            p.waitMillis
          );
        }
        else {
          setTimeout(
            function() {
              console.log("Simulated positive outcome of remote create - " + p.toString());
              var json = p.toJSON();
              json.persistenceId = Math.floor(Math.random() * 1000000000);
              if (p.isInstanceOf(VersionedPersistentObject)) {
                json.persistenceVersion = 1;
              }
              if (p.isInstanceOf(AuditableObject)) {
                var now = new Date();
                json.createdBy= "De Maker";
                json.createdAt= now;
                json.lastModifiedBy = "De Maker";
                json.lastModifiedAt = now;
              }
              p.reload(json);
              thisDao.track(p, referer);
              resultDeferred.resolve(p);
            },
            p.waitMillis
          );
        }
        return resultDeferred.promise;
      },

      update: function(/*PersistentObject*/ p) {
        // description:
        //   p.error will result in that error
        //   p.semanticException will result in that exception
        //   p.waitMillis is the time the promise will take

        var thisDao = this;
        var resultDeferred = new Deferred();
        if (p.error) {
          setTimeout(
            function() {
              resultDeferred.reject("ERROR: could not PUT " + p.toString() + " (" + p.error + ")");
            },
            p.waitMillis
          );
        }
        else if (p.semanticException) {
          setTimeout(
            function() {
              if (p.semanticException.isInstanceOf && p.semanticException.isInstanceOf(IdNotFoundException)) {
                markDeletedFromServer(thisDao._cache, p);
              }
              resultDeferred.reject(p.semanticException);
            },
            p.waitMillis
          );
        }
        else {
          setTimeout(
            function() {
              var json = p.toJSON();
              if (p.isInstanceOf(VersionedPersistentObject)) {
                json.persistenceVersion = p.get("persistenceVersion") + 1;
              }
              if (p.isInstanceOf(AuditableObject)) {
                json.createdBy = p.get("createdBy");
                json.createdAt = p.get("createdAt");
                json.lastModifiedBy = "André Aanpassing";
                json.lastModifiedAt = new Date();
              }
              p.reload(json);
              resultDeferred.resolve(p);
            },
            p.waitMillis
          );
        }
        return resultDeferred.promise;
      },

      remove: function(/*PersistentObject*/ p) {
        // description:
        //   p.error will result in that error
        //   p.semanticException will result in that exception
        //   p.waitMillis is the time the promise will take

        var thisDao = this;
        var resultDeferred = new Deferred();
        if (p.error) {
          setTimeout(
            function() {
              resultDeferred.reject("ERROR: could not DELETE " + p.toString() + " (" + p.error + ")");
            },
            p.waitMillis
          );
        }
        else if (p.semanticException) {
          setTimeout(
            function() {
              resultDeferred.reject(p.semanticException);
            },
            p.waitMillis
          );
        }
        else {
          setTimeout(
            function() {
              markDeletedFromServer(thisDao._cache, p);
              resultDeferred.resolve(p);
            },
            p.waitMillis
          );
        }
        return resultDeferred.promise;
      },

      _refresh: function(result, url, query, referer) {
        // description:
        //   result.error will result in that error
        //   result.semanticException will result in that exception
        //   result.waitMillis is the time the promise will take
        //   Promise resolves to result.arrayOfResult
        var resultDeferred = new Deferred();
        if (result.error) {
          setTimeout(
            function() {
              resultDeferred.reject("ERROR: could not GET all from" + url + " (" + result.error + ")");
            },
            result.waitMillis
          );
        }
        else if (result.semanticException) {
          setTimeout(
            function() {
              resultDeferred.reject(result.semanticException);
            },
            result.waitMillis
          );
        }
        else {
          setTimeout(
            function() {
              result.loadAll(result.arrayOfResult);
            },
            result.waitMillis
          );
        }
        return resultDeferred.promise;
      }

    });

    return CrudDaoMock; // return Function
  }
);
<commit_msg>Mock for LazyToManyStore<commit_after>/*
 Copyright 2012 - $Date $ by PeopleWare n.v.

 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.
 */

define(["dojo/_base/declare",
        "../../ANewCrudDao2",
        "../../_Cache2", "../../UrlBuilder",
        "../../PersistentObject", "../../VersionedPersistentObject", "../../AuditableObject", "../../IdNotFoundException",
        "./Person", "ppwcode/oddsAndEnds/typeOf",
        "dojo/Deferred", "require"],
  function(declare,
           CrudDao,
           _Cache, UrlBuilder,
           PersistentObject, VersionedPersistentObject, AuditableObject, IdNotFoundException,
           Person, typeOf,
           Deferred, require) {

    function markDeletedFromServer(cache, p) {
      var entry = cache.get(p);
      if (!entry) {
        throw "ERROR: to delete, p must be in cache";
      }
      var json = p.toJSON();
      json.persistenceId = null;
      if (p.isInstanceOf(VersionedPersistentObject)) {
        json.persistenceVersion = null;
      }
      if (p.isInstanceOf(AuditableObject)) {
        json.createdAt = null;
        json.createdBy = null;
        json.lastModifiedAt = null;
        json.lastModifiedBy = null;
      }
      p.reload(json); // should remove from cache
    }

    var UrlBuilderMock = declare([UrlBuilder], {
      toMany: function(serverType, id, serverPropertyName) {
        return require.toUrl("./persons.json");
      }
    });

    var CrudDaoMock = declare([CrudDao], {
      // summary:
      //   This is a mock of CrudDao. We inherit from CrudDao, and overwrite meaningful methods.
      //   All methods are supported. They're behavior can be changed for a number of cases, with
      //   extra properties on parameters that are already there.
      //   Private. Contains a CacheEntry for each retrieved object, that is not yet released.

      constructor: function() {
        this.urlBuilder = new UrlBuilderMock();
        this.revive = function revive(/*Object*/ json, /*Object*/ referer, /*_Cache*/ cache) {
          if (typeOf(json) === "array") {
            return json.map(function(e) {
              return revive(e, referer, cache);
            });
          }
          else {
            var p = new Person();
            p.reload(json);
            return p;
          }
        }
      },

      retrieve: function(/*String*/ serverType, /*Number*/ persistenceId, /*Any*/ referer) {
        // description:
        //   referer.error will result in that error
        //   referer.idNotFoundException will result in that exception
        //   referer.resultJson will be the result, of type referer.PoType
        //   referer.waitMillis is the time the promise will take

        var cachedPo = this._cache.getByTypeAndId(serverType, persistenceId);
        var p = null;
        if (! cachedPo) {
          p = new referer.PoType();
          p.reload(referer.resultJson);
          p._changeAttrValue("persistenceId", persistenceId);
        }
        else {
          p = cachedPo;
        }
        this.track(p, referer);
        var thisDao = this;
        var resultDeferred = new Deferred();
        if (referer.error) {
          setTimeout(
            function() {
              resultDeferred.reject("ERROR: could not GET " + persistenceId + " (" + referer.error + ")");
            },
            referer.waitMillis
          );
        }
        else if (referer.idNotFoundException) {
          setTimeout(
            function() {
              markDeletedFromServer(thisDao._cache, p);
              resultDeferred.reject(referer.idNotFoundException);
            },
            referer.waitMillis
          );
        }
        else {
          setTimeout(
            function() {
              p.reload(referer.resultJson);
              resultDeferred.resolve(p);
            },
            referer.waitMillis
          );
        }
        return resultDeferred.promise;
      },

      create: function(/*PersistentObject*/ p, /*Any*/ referer) {
        // description:
        //   p.error will result in that error
        //   p.semanticException will result in that exception
        //   p.waitMillis is the time the promise will take

        var thisDao = this;
        var resultDeferred = new Deferred();
        if (p.error) {
          setTimeout(
            function() {
              resultDeferred.reject("ERROR: could not POST " + p.toString() + " (" + p.error + ")");
            },
            p.waitMillis
          );
        }
        else if (p.semanticException) {
          setTimeout(
            function() {
              resultDeferred.reject(p.semanticException);
            },
            p.waitMillis
          );
        }
        else {
          setTimeout(
            function() {
              console.log("Simulated positive outcome of remote create - " + p.toString());
              var json = p.toJSON();
              json.persistenceId = Math.floor(Math.random() * 1000000000);
              if (p.isInstanceOf(VersionedPersistentObject)) {
                json.persistenceVersion = 1;
              }
              if (p.isInstanceOf(AuditableObject)) {
                var now = new Date();
                json.createdBy= "De Maker";
                json.createdAt= now;
                json.lastModifiedBy = "De Maker";
                json.lastModifiedAt = now;
              }
              p.reload(json);
              thisDao.track(p, referer);
              resultDeferred.resolve(p);
            },
            p.waitMillis
          );
        }
        return resultDeferred.promise;
      },

      update: function(/*PersistentObject*/ p) {
        // description:
        //   p.error will result in that error
        //   p.semanticException will result in that exception
        //   p.waitMillis is the time the promise will take

        var thisDao = this;
        var resultDeferred = new Deferred();
        if (p.error) {
          setTimeout(
            function() {
              resultDeferred.reject("ERROR: could not PUT " + p.toString() + " (" + p.error + ")");
            },
            p.waitMillis
          );
        }
        else if (p.semanticException) {
          setTimeout(
            function() {
              if (p.semanticException.isInstanceOf && p.semanticException.isInstanceOf(IdNotFoundException)) {
                markDeletedFromServer(thisDao._cache, p);
              }
              resultDeferred.reject(p.semanticException);
            },
            p.waitMillis
          );
        }
        else {
          setTimeout(
            function() {
              var json = p.toJSON();
              if (p.isInstanceOf(VersionedPersistentObject)) {
                json.persistenceVersion = p.get("persistenceVersion") + 1;
              }
              if (p.isInstanceOf(AuditableObject)) {
                json.createdBy = p.get("createdBy");
                json.createdAt = p.get("createdAt");
                json.lastModifiedBy = "André Aanpassing";
                json.lastModifiedAt = new Date();
              }
              p.reload(json);
              resultDeferred.resolve(p);
            },
            p.waitMillis
          );
        }
        return resultDeferred.promise;
      },

      remove: function(/*PersistentObject*/ p) {
        // description:
        //   p.error will result in that error
        //   p.semanticException will result in that exception
        //   p.waitMillis is the time the promise will take

        var thisDao = this;
        var resultDeferred = new Deferred();
        if (p.error) {
          setTimeout(
            function() {
              resultDeferred.reject("ERROR: could not DELETE " + p.toString() + " (" + p.error + ")");
            },
            p.waitMillis
          );
        }
        else if (p.semanticException) {
          setTimeout(
            function() {
              resultDeferred.reject(p.semanticException);
            },
            p.waitMillis
          );
        }
        else {
          setTimeout(
            function() {
              markDeletedFromServer(thisDao._cache, p);
              resultDeferred.resolve(p);
            },
            p.waitMillis
          );
        }
        return resultDeferred.promise;
      }

//      _refresh: function(result, url, query, referer) {
//        // description:
//        //   result.error will result in that error
//        //   result.semanticException will result in that exception
//        //   result.waitMillis is the time the promise will take
//        //   Promise resolves to result.arrayOfResult
//        var resultDeferred = new Deferred();
//        if (result.error) {
//          setTimeout(
//            function() {
//              resultDeferred.reject("ERROR: could not GET all from" + url + " (" + result.error + ")");
//            },
//            result.waitMillis
//          );
//        }
//        else if (result.semanticException) {
//          setTimeout(
//            function() {
//              resultDeferred.reject(result.semanticException);
//            },
//            result.waitMillis
//          );
//        }
//        else {
//          setTimeout(
//            function() {
//              result.loadAll(result.arrayOfResult);
//            },
//            result.waitMillis
//          );
//        }
//        return resultDeferred.promise;
//      }

    });

    return CrudDaoMock; // return Function
  }
);
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import React from 'react'
import ReactDOM from 'react-dom'
import {Button, IconButton} from '@instructure/ui-buttons'
import {SVGIcon} from '@instructure/ui-svg-images'
import I18n from 'i18n!ImmersiveReader'
import {showFlashError} from '../FlashAlert'
import {defaultFetchOptions} from '@instructure/js-utils'
import {CookiePolicy} from '@microsoft/immersive-reader-sdk'
import WithBreakpoints from '../WithBreakpoints'

/**
 * This comes from https://github.com/microsoft/immersive-reader-sdk/blob/master/assets/icon.svg
 */
const LOGO = `
<!-- Copyright (c) Microsoft Corporation. All rights reserved.
     Licensed under the MIT License. -->

<svg viewBox="0 0 40 37" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g fill-rule="nonzero">
            <path d="M37.4,0.9 L37.4,9.6 L35.4,9.6 L35.4,2.9 L24.4,2.9 C22.9,3.3 20,4.5 20,6 L20,17.2 L18,17.2 L18,6 C18,5 15.6,3.6 13.8,2.9 L2,2.9 L2,29 L12.4,29 L12.4,31 L0,31 L0,0.9 L14.1,0.9 L14.3,1 C15,1.2 17.5,2.2 18.9,3.7 C20.5,1.9 23.5,1.1 23.9,1 L24.1,1 L37.4,1 L37.4,0.9 Z" fill="#000000"></path>
            <path d="M27.4,37 L25.8,37 L18.4,29.4 L14,29.4 L14,21 L18.4,20.9 L26.1,13 L27.4,13 L27.4,37 Z M16,27.4 L19.2,27.4 L25.3,33.7 L25.3,16.6 L19.2,22.9 L15.9,22.9 L15.9,27.4 L16,27.4 Z" fill="#0197F2"></path>
            <path d="M31.3,32.7 L29.6,31.7 C29.6,31.7 31.7,28.3 31.7,25.2 C31.7,21.9 29.6,18.5 29.6,18.4 L31.3,17.4 C31.4,17.6 33.7,21.3 33.7,25.2 C33.7,28.8 31.4,32.6 31.3,32.7 Z" fill="#0197F2"></path>
            <path d="M36.4,36.2 L34.8,35 C34.8,35 38,30.8 38,25.2 C38,19.6 34.8,15.4 34.8,15.4 L36.4,14.2 C36.5,14.4 40,19 40,25.3 C40,31.5 36.5,36 36.4,36.2 Z" fill="#0197F2"></path>
        </g>
    </g>
</svg>
`

function handleClick({title, content}, readerSDK) {
  ;(readerSDK || import('@microsoft/immersive-reader-sdk'))
    .then(({launchAsync}) => {
      fetch('/api/v1/immersive_reader/authenticate', defaultFetchOptions)
        .then(response => response.json())
        .then(({token, subdomain}) => {
          const requestContent = {
            title,
            chunks: [{content, mimeType: 'text/html'}]
          }
          const options = {
            cookiePolicy: CookiePolicy.Enable
          }
          launchAsync(token, subdomain, requestContent, options)
        })
        .catch(e => {
          // eslint-disable-next-line no-console
          console.error('Getting authentication details failed', e)
          showFlashError(I18n.t('Immersive Reader Failed to Load'))()
        })
    })
    .catch(e => {
      // eslint-disable-next-line no-console
      console.error('Loading the Immersive Reader SDK failed', e)
      showFlashError(I18n.t('Immersive Reader Failed to Load'))()
    })
}

export function ImmersiveReaderButton({content, readerSDK, breakpoints}) {
  return breakpoints?.miniTablet ? (
    <Button onClick={() => handleClick(content, readerSDK)} icon={<SVGIcon src={LOGO} />}>
      {I18n.t('Immersive Reader')}
    </Button>
  ) : (
    <IconButton
      onClick={() => handleClick(content, readerSDK)}
      screenReaderLabel={I18n.t('Immersive Reader')}
    >
      <SVGIcon src={LOGO} />
    </IconButton>
  )
}

const ImmersiveReaderButtonWithBreakpoints = WithBreakpoints(ImmersiveReaderButton)

export function initializeReaderButton(mountPoint, content) {
  ReactDOM.render(<ImmersiveReaderButtonWithBreakpoints content={content} />, mountPoint)
}
<commit_msg>Disable Immersive Reader Cookie policy<commit_after>/*
 * Copyright (C) 2019 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import React from 'react'
import ReactDOM from 'react-dom'
import {Button, IconButton} from '@instructure/ui-buttons'
import {SVGIcon} from '@instructure/ui-svg-images'
import I18n from 'i18n!ImmersiveReader'
import {showFlashError} from '../FlashAlert'
import {defaultFetchOptions} from '@instructure/js-utils'
import {CookiePolicy} from '@microsoft/immersive-reader-sdk'
import WithBreakpoints from '../WithBreakpoints'

/**
 * This comes from https://github.com/microsoft/immersive-reader-sdk/blob/master/assets/icon.svg
 */
const LOGO = `
<!-- Copyright (c) Microsoft Corporation. All rights reserved.
     Licensed under the MIT License. -->

<svg viewBox="0 0 40 37" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g fill-rule="nonzero">
            <path d="M37.4,0.9 L37.4,9.6 L35.4,9.6 L35.4,2.9 L24.4,2.9 C22.9,3.3 20,4.5 20,6 L20,17.2 L18,17.2 L18,6 C18,5 15.6,3.6 13.8,2.9 L2,2.9 L2,29 L12.4,29 L12.4,31 L0,31 L0,0.9 L14.1,0.9 L14.3,1 C15,1.2 17.5,2.2 18.9,3.7 C20.5,1.9 23.5,1.1 23.9,1 L24.1,1 L37.4,1 L37.4,0.9 Z" fill="#000000"></path>
            <path d="M27.4,37 L25.8,37 L18.4,29.4 L14,29.4 L14,21 L18.4,20.9 L26.1,13 L27.4,13 L27.4,37 Z M16,27.4 L19.2,27.4 L25.3,33.7 L25.3,16.6 L19.2,22.9 L15.9,22.9 L15.9,27.4 L16,27.4 Z" fill="#0197F2"></path>
            <path d="M31.3,32.7 L29.6,31.7 C29.6,31.7 31.7,28.3 31.7,25.2 C31.7,21.9 29.6,18.5 29.6,18.4 L31.3,17.4 C31.4,17.6 33.7,21.3 33.7,25.2 C33.7,28.8 31.4,32.6 31.3,32.7 Z" fill="#0197F2"></path>
            <path d="M36.4,36.2 L34.8,35 C34.8,35 38,30.8 38,25.2 C38,19.6 34.8,15.4 34.8,15.4 L36.4,14.2 C36.5,14.4 40,19 40,25.3 C40,31.5 36.5,36 36.4,36.2 Z" fill="#0197F2"></path>
        </g>
    </g>
</svg>
`

function handleClick({title, content}, readerSDK) {
  ;(readerSDK || import('@microsoft/immersive-reader-sdk'))
    .then(({launchAsync}) => {
      fetch('/api/v1/immersive_reader/authenticate', defaultFetchOptions)
        .then(response => response.json())
        .then(({token, subdomain}) => {
          const requestContent = {
            title,
            chunks: [{content, mimeType: 'text/html'}]
          }
          const options = {
            cookiePolicy: CookiePolicy.Disable
          }
          launchAsync(token, subdomain, requestContent, options)
        })
        .catch(e => {
          // eslint-disable-next-line no-console
          console.error('Getting authentication details failed', e)
          showFlashError(I18n.t('Immersive Reader Failed to Load'))()
        })
    })
    .catch(e => {
      // eslint-disable-next-line no-console
      console.error('Loading the Immersive Reader SDK failed', e)
      showFlashError(I18n.t('Immersive Reader Failed to Load'))()
    })
}

export function ImmersiveReaderButton({content, readerSDK, breakpoints}) {
  return breakpoints?.miniTablet ? (
    <Button onClick={() => handleClick(content, readerSDK)} icon={<SVGIcon src={LOGO} />}>
      {I18n.t('Immersive Reader')}
    </Button>
  ) : (
    <IconButton
      onClick={() => handleClick(content, readerSDK)}
      screenReaderLabel={I18n.t('Immersive Reader')}
    >
      <SVGIcon src={LOGO} />
    </IconButton>
  )
}

const ImmersiveReaderButtonWithBreakpoints = WithBreakpoints(ImmersiveReaderButton)

export function initializeReaderButton(mountPoint, content) {
  ReactDOM.render(<ImmersiveReaderButtonWithBreakpoints content={content} />, mountPoint)
}
<|endoftext|>


<commit_before>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else
if (myDate.getHours() <=8  && myDate.getHours() > 20 )
{
  groet = 'Goedenavond, bedankt voor je bezoek. Op dit moment is Independer echter gesloten. Uiteraard kun je met onze IndyBot praten maar er is er helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan altijd je vraag doormailen naar inf@independer. Dan komt het altijd goed.';
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
//prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}, wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`%[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    receive: (bot, message) => {
      switch(message.text) {
      case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => 'askName')
          break;
      case 'Starters hypotheek':
      //prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)

          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[Appartement](postback:hypotheekkeuze_appartement) %[Huis](postback:hypotheekkeuze_huis) %[Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'hypotheek_starter')
              break;
        case 'Nieuwe hypotheek':
          return bot.say(`Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say(`Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja - graag](postback:update_ja) %[Nee,bedankt](postback:update_nee)`))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`...`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja - graag':
            return bot.say(`Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.`)
            .then(() => 'update_ja');
          break;
          case 'Nee, bedankt':
              receive: () => 'bye'
              break;
          default:
            return bot.say('...')
              .then(() => 'processing')
            break;
}
}
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
          const emailVisitor=message.text.trim();
          return bot.setProp('emailVisitor', emailVisitor)
              .then(()  => bot.say(`Ok - dan hou ik je via ${emailVisitor} op de hoogte.`))
              .then(()  =>'lastCheck')
    }
},
update_nee: {
  receive: () => 'bye'
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheektype_starter: {
    prompt: (bot) => bot.say('Pleasure meeting you - starter'),
    receive: () => 'processing'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say('Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)'),
    receive: () => 'processing'
},

askName: {
  receive: (bot, message) => {
    switch(message.text) {
        case 'Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case 'Huis':
          return bot.say(`Leuk :)`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say(`...`)
          .then(() => 'processing')
        break;
        }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...'),
  receive: (bot, message) => {
      const name = message.text;
      return bot.setProp('name', name)
          .then(() => bot.say(`Hoi ${name}. Ik heb nog wat vragen voor je om verder te kunnen.`))
          .then(() => 'lastCheck');
    }
},

lastCheck: {
    prompt: (bot) => bot.say('Is er nog iets waar ik  je bij kan helpen?  %[Ja](postback:speak) %[Nee](postback:bye)'),
          receive: (bot, message) => {
            switch(message.text) {
              case 'Nee hoor':
                  receive: ()  => 'bye'
                  break;
             case 'Ja':
                  receive: () => 'speak'
                  break;
            case 'Nee':
                  receive: () => 'bye'
                  break;
            default:
              return bot.say(`...`)
                .then(() => 'processing')
              break;
            }
        }
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd'),
    receive: ()  => 'finish'
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<commit_msg>script<commit_after>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else
if (myDate.getHours() <=8  || myDate.getHours() > 20 )
{
  groet = 'Goedenavond, bedankt voor je bezoek. Op dit moment is Independer echter gesloten. Uiteraard kun je met onze IndyBot praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen naar info@independer. Dan komt het altijd goed.';
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
//prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}... Wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`))
        .then(() => bot.say(`%[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    receive: (bot, message) => {
      switch(message.text) {
      case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => 'askName')
          break;
      case 'Starters hypotheek':
      //prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)

          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[Appartement](postback:hypotheekkeuze_appartement) %[Huis](postback:hypotheekkeuze_huis) %[Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'hypotheek_starter')
              break;
        case 'Nieuwe hypotheek':
          return bot.say(`Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say(`Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja - graag](postback:update_ja) %[Nee,bedankt](postback:update_nee)`))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`...`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja - graag':
            return bot.say(`Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.`)
            .then(() => 'update_ja');
          break;
          case 'Nee, bedankt':
              receive: () => 'bye'
              break;
          default:
            return bot.say('...')
              .then(() => 'processing')
            break;
}
}
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
          const emailVisitor=message.text.trim();
          return bot.setProp('emailVisitor', emailVisitor)
              .then(()  => bot.say(`Ok - dan hou ik je via ${emailVisitor} op de hoogte.`))
              .then(()  =>'lastCheck')
    }
},
update_nee: {
  receive: () => 'bye'
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheektype_starter: {
    prompt: (bot) => bot.say('Pleasure meeting you - starter'),
    receive: () => 'processing'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say('Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)'),
    receive: () => 'processing'
},

askName: {
  receive: (bot, message) => {
    switch(message.text) {
        case 'Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case 'Huis':
          return bot.say(`Leuk :)`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say(`...`)
          .then(() => 'processing')
        break;
        }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...'),
  receive: (bot, message) => {
      const name = message.text;
      return bot.setProp('name', name)
          .then(() => bot.say(`Hoi ${name}. Ik heb nog wat vragen voor je om verder te kunnen.`))
          .then(() => 'lastCheck');
    }
},

lastCheck: {
    prompt: (bot) => bot.say('Is er nog iets waar ik  je bij kan helpen?  %[Ja](postback:speak) %[Nee](postback:bye)'),
          receive: (bot, message) => {
            switch(message.text) {
              case 'Nee hoor':
                  receive: ()  => 'bye'
                  break;
             case 'Ja':
                  receive: () => 'speak'
                  break;
            case 'Nee':
                  receive: () => 'bye'
                  break;
            default:
              return bot.say(`...`)
                .then(() => 'processing')
              break;
            }
        }
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd'),
    receive: ()  => 'finish'
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<|endoftext|>


<commit_before>var hotkeys = (function () {

var exports = {};

var directional_hotkeys = {
    40:  rows.next_visible,  // down arrow
    106: rows.next_visible,  // 'j'
    38:  rows.prev_visible,  // up arrow
    107: rows.prev_visible,  // 'k'
    36:  rows.first_visible, // Home
    35:  rows.last_visible   // End
};

var narrow_hotkeys = {
    115: narrow.by_recipient,           // 's'
    83:  narrow.by_subject,             // 'S'
    118: function () {                  // 'v'
        narrow.by('is', 'private-message');
    }
};

// Process a keydown or keypress event.
//
// Returns true if we handled it, false if the browser should.
function process_hotkey(e) {
    var code = e.which;
    var next_message;

    // Disable hotkeys on settings page etc., and when a modal pop-up
    // is visible.
    if (ui.home_tab_obscured())
        return false;

    // In browsers where backspace sends the browser back (e.g. Mac Chrome),
    // do not go back if the send button is in focus
    if ($('#compose-send-button:focus').length > 0 && code === 8) {
        e.preventDefault();
        return false;
    }

    // Process hotkeys specially when in an input, textarea, or send button
    if ($('input:focus,textarea:focus,#compose-send-button:focus').length > 0) {
        if (code === 27) {
            // If one of our typeaheads is open, do nothing so that the Esc
            // will go to close it
            if ($("#subject").data().typeahead.shown ||
                $("#stream").data().typeahead.shown ||
                $("#private_message_recipient").data().typeahead.shown ||
                $("#new_message_content").data().typeahead.shown) {
                return false;
            } else {
                // If the user hit the escape key, cancel the current compose
                compose.cancel();
            }
        }
        // Keycode 13 is Return.
        if ((code === 13) && $("#search_query").is(":focus")) {
            // Pass it along to the search up button.
            $("#search_up").focus();
        }
        // Let the browser handle the key normally.
        return false;
    }

    if (directional_hotkeys.hasOwnProperty(code)) {
        next_message = directional_hotkeys[code](selected_message);
        if (next_message.length !== 0) {
            select_message(next_message, {then_scroll: true});
        }
        if ((next_message.length === 0) && (code === 40 || code === 106)) {
            // At the last message, scroll to the bottom so we have
            // lots of nice whitespace for new messages coming in.
            //
            // FIXME: this doesn't work for End because rows.last_visible()
            // always returns a message.
            viewport.scrollTop($("#main_div").outerHeight(true));
        }
        return true;
    }

    if (narrow_hotkeys.hasOwnProperty(code)) {
        narrow.target(selected_message_id);
        narrow_hotkeys[code]();
        return true;
    }

    // We're in the middle of a combo; stop processing because
    // we want the browser to handle it (to avoid breaking
    // things like Ctrl-C or Command-C for copy).
    if (e.metaKey || e.ctrlKey) {
        return false;
    }

    switch (code) {
    case 33: // Page Up
        if (at_top_of_viewport()) {
            select_message(rows.first_visible(), {then_scroll: false});
        }
        return false; // We want the browser to actually page up and down
    case 32: // Spacebar
    case 34: // Page Down
        if (at_bottom_of_viewport()) {
            select_message(rows.last_visible(), {then_scroll: false});
        }
        return false;
    case 27: // Esc: close userinfo popup, cancel compose, clear a find, or un-narrow
        if (ui.userinfo_currently_popped()) {
            ui.hide_userinfo_popover();
        } else if (compose.composing()) {
            compose.cancel();
        } else {
            search.clear_search();
        }
        return true;
    case 99: // 'c': compose
        compose.start('stream');
        return true;
    case 67: // 'C': compose private message
        compose.start('private');
        return true;
    case  13: // Enter: respond to message (unless we need to do something else)
        if (search.keyboard_currently_finding()) {
            // Pass through to our searchbox (to advance to next result)
            return false;
        } else {
            respond_to_message();
            return true;
        }
    case 114: // 'r': respond to message
        respond_to_message();
        return true;
    case 82: // 'R': respond to author
        respond_to_message("personal");
        return true;
    case 47: // '/': initiate search
        search.initiate_search();
        return true;
    case 63: // '?': Show keyboard shortcuts page
        $('#keyboard-shortcuts').modal('show');
        return true;
    }

    return false;
}

/* We register both a keydown and a keypress function because
   we want to intercept pgup/pgdn, escape, etc, and process them
   as they happen on the keyboard. However, if we processed
   letters/numbers in keydown, we wouldn't know what the case of
   the letters were.

   We want case-sensitive hotkeys (such as in the case of r vs R)
   so we bail in .keydown if the event is a letter or number and
   instead just let keypress go for it. */

$(document).keydown(function (e) {
    // Restrict to non-alphanumeric keys
    if (48 > e.which || 90 < e.which) {
        if (process_hotkey(e))
            e.preventDefault();
    }
});

$(document).keypress(function (e) {
    // What exactly triggers .keypress may vary by browser.
    // Welcome to compatability hell.
    //
    // In particular, when you press tab in Firefox, it fires a
    // keypress event with keycode 0 after processing the original
    // event.
    if (e.which !== 0 && e.charCode !== 0) {
        if (process_hotkey(e))
            e.preventDefault();
    }
});

return exports;

}());
<commit_msg>Have 'c' and 'C' behave identically to their buttons.<commit_after>var hotkeys = (function () {

var exports = {};

var directional_hotkeys = {
    40:  rows.next_visible,  // down arrow
    106: rows.next_visible,  // 'j'
    38:  rows.prev_visible,  // up arrow
    107: rows.prev_visible,  // 'k'
    36:  rows.first_visible, // Home
    35:  rows.last_visible   // End
};

var narrow_hotkeys = {
    115: narrow.by_recipient,           // 's'
    83:  narrow.by_subject,             // 'S'
    118: function () {                  // 'v'
        narrow.by('is', 'private-message');
    }
};

// Process a keydown or keypress event.
//
// Returns true if we handled it, false if the browser should.
function process_hotkey(e) {
    var code = e.which;
    var next_message;

    // Disable hotkeys on settings page etc., and when a modal pop-up
    // is visible.
    if (ui.home_tab_obscured())
        return false;

    // In browsers where backspace sends the browser back (e.g. Mac Chrome),
    // do not go back if the send button is in focus
    if ($('#compose-send-button:focus').length > 0 && code === 8) {
        e.preventDefault();
        return false;
    }

    // Process hotkeys specially when in an input, textarea, or send button
    if ($('input:focus,textarea:focus,#compose-send-button:focus').length > 0) {
        if (code === 27) {
            // If one of our typeaheads is open, do nothing so that the Esc
            // will go to close it
            if ($("#subject").data().typeahead.shown ||
                $("#stream").data().typeahead.shown ||
                $("#private_message_recipient").data().typeahead.shown ||
                $("#new_message_content").data().typeahead.shown) {
                return false;
            } else {
                // If the user hit the escape key, cancel the current compose
                compose.cancel();
            }
        }
        // Keycode 13 is Return.
        if ((code === 13) && $("#search_query").is(":focus")) {
            // Pass it along to the search up button.
            $("#search_up").focus();
        }
        // Let the browser handle the key normally.
        return false;
    }

    if (directional_hotkeys.hasOwnProperty(code)) {
        next_message = directional_hotkeys[code](selected_message);
        if (next_message.length !== 0) {
            select_message(next_message, {then_scroll: true});
        }
        if ((next_message.length === 0) && (code === 40 || code === 106)) {
            // At the last message, scroll to the bottom so we have
            // lots of nice whitespace for new messages coming in.
            //
            // FIXME: this doesn't work for End because rows.last_visible()
            // always returns a message.
            viewport.scrollTop($("#main_div").outerHeight(true));
        }
        return true;
    }

    if (narrow_hotkeys.hasOwnProperty(code)) {
        narrow.target(selected_message_id);
        narrow_hotkeys[code]();
        return true;
    }

    // We're in the middle of a combo; stop processing because
    // we want the browser to handle it (to avoid breaking
    // things like Ctrl-C or Command-C for copy).
    if (e.metaKey || e.ctrlKey) {
        return false;
    }

    switch (code) {
    case 33: // Page Up
        if (at_top_of_viewport()) {
            select_message(rows.first_visible(), {then_scroll: false});
        }
        return false; // We want the browser to actually page up and down
    case 32: // Spacebar
    case 34: // Page Down
        if (at_bottom_of_viewport()) {
            select_message(rows.last_visible(), {then_scroll: false});
        }
        return false;
    case 27: // Esc: close userinfo popup, cancel compose, clear a find, or un-narrow
        if (ui.userinfo_currently_popped()) {
            ui.hide_userinfo_popover();
        } else if (compose.composing()) {
            compose.cancel();
        } else {
            search.clear_search();
        }
        return true;
    case 99: // 'c': compose
        compose.set_mode('stream');
        return true;
    case 67: // 'C': compose private message
        compose.set_mode('private');
        return true;
    case  13: // Enter: respond to message (unless we need to do something else)
        if (search.keyboard_currently_finding()) {
            // Pass through to our searchbox (to advance to next result)
            return false;
        } else {
            respond_to_message();
            return true;
        }
    case 114: // 'r': respond to message
        respond_to_message();
        return true;
    case 82: // 'R': respond to author
        respond_to_message("personal");
        return true;
    case 47: // '/': initiate search
        search.initiate_search();
        return true;
    case 63: // '?': Show keyboard shortcuts page
        $('#keyboard-shortcuts').modal('show');
        return true;
    }

    return false;
}

/* We register both a keydown and a keypress function because
   we want to intercept pgup/pgdn, escape, etc, and process them
   as they happen on the keyboard. However, if we processed
   letters/numbers in keydown, we wouldn't know what the case of
   the letters were.

   We want case-sensitive hotkeys (such as in the case of r vs R)
   so we bail in .keydown if the event is a letter or number and
   instead just let keypress go for it. */

$(document).keydown(function (e) {
    // Restrict to non-alphanumeric keys
    if (48 > e.which || 90 < e.which) {
        if (process_hotkey(e))
            e.preventDefault();
    }
});

$(document).keypress(function (e) {
    // What exactly triggers .keypress may vary by browser.
    // Welcome to compatability hell.
    //
    // In particular, when you press tab in Firefox, it fires a
    // keypress event with keycode 0 after processing the original
    // event.
    if (e.which !== 0 && e.charCode !== 0) {
        if (process_hotkey(e))
            e.preventDefault();
    }
});

return exports;

}());
<|endoftext|>