<commit_before>"use strict";

const P = require('bluebird');
const uuid = require('cassandra-uuid').TimeUuid;

class OresProcessor {
    constructor(options) {
        this._options = options;
        if (!options.ores_precache_uris || !Array.isArray(options.ores_precache_uris)) {
            throw new Error('OreProcessor is miconfigured. ores_precache_uris is required');
        }
        if (!options.eventbus_uri) {
            throw new Error('OreProcessor is miconfigured. eventbus_uri is required');
        }
    }

    process(hyper, req) {
        const message = req.body;
        return P.all(this._options.ores_precache_uris.map(uri => hyper.post({
            uri,
            headers: {
                'content-type': 'application/json'
            },
            body: message
        })))
        .spread((res) => {
            if (!req.query.postevent || !res.body) {
                return res;
            }
            const now = new Date();
            const newMessage = {
                meta: {
                    topic: 'mediawiki.revision-score',
                    uri: message.meta.uri,
                    request_id: message.meta.request_id,
                    id: uuid.fromDate(now).toString(),
                    dt: now.toISOString(),
                    domain: message.meta.domain,
                },
                database: message.database,
                page_id: message.page_id,
                page_title: message.page_title,
                page_namespace: message.page_namespace,
                rev_id: message.rev_id,
                rev_parent_id: message.rev_parent_id,
                rev_timestamp: message.rev_timestamp,
                scores: []
            };

            const domainScores = res.body[newMessage.database];
            const revScores = domainScores.scores[`${newMessage.rev_id}`];
            Object.keys(revScores).forEach((modelName) => {
                // The example schema for the score object:
                // {
                //   "model_name": "awesomeness",
                //   "model_version": "1.0",
                //   "prediction": ["yes", "mostly"],
                //   "probability": [
                //     {"name": "yes", "value": 0.99},
                //     {"name": "mostly", "value": 0.90},
                //     {"name": "hardly", "value": 0.01}
                //   ]
                // }
                const score = {
                    model_name: modelName,
                    model_version: domainScores.models[modelName].version,
                };
                if (revScores[modelName].error) {
                    score.error = revScores[modelName].error;
                } else {
                    const originalScore = revScores[modelName].score;
                    // Convert prediction to array of strings
                    let prediction = originalScore.prediction;
                    if (!Array.isArray(prediction)) {
                        prediction = [ prediction ];
                    }
                    score.prediction = prediction.map(p => `${p}`);
                    // Convert probabilities to an array of name-value pairs.
                    score.probability = Object.keys(originalScore.probability).map(probName => ({
                        name: probName,
                        value: originalScore.probability[probName]
                    }));
                }
                newMessage.scores.push(score);
            });
            return hyper.post({
                uri: this._options.eventbus_uri,
                headers: {
                    'content-type': 'application/json'
                },
                body: [ newMessage ]
            });
        });
    }
}

module.exports = (options) => {
    const processor = new OresProcessor(options);
    return {
        spec: {
            paths: {
                '/': {
                    post: {
                        summary: 'submit revision-create for processing',
                        operationId: 'process'
                    }
                }
            }
        },
        operations: {
            process: processor.process.bind(processor),
        }
    };
};
<commit_msg>Move the errors out of the scores<commit_after>"use strict";

const P = require('bluebird');
const uuid = require('cassandra-uuid').TimeUuid;

class OresProcessor {
    constructor(options) {
        this._options = options;
        if (!options.ores_precache_uris || !Array.isArray(options.ores_precache_uris)) {
            throw new Error('OreProcessor is miconfigured. ores_precache_uris is required');
        }
        if (!options.eventbus_uri) {
            throw new Error('OreProcessor is miconfigured. eventbus_uri is required');
        }
    }

    process(hyper, req) {
        const message = req.body;
        return P.all(this._options.ores_precache_uris.map(uri => hyper.post({
            uri,
            headers: {
                'content-type': 'application/json'
            },
            body: message
        })))
        .spread((res) => {
            if (!req.query.postevent || !res.body) {
                return res;
            }
            const now = new Date();
            const newMessage = {
                meta: {
                    topic: 'mediawiki.revision-score',
                    uri: message.meta.uri,
                    request_id: message.meta.request_id,
                    id: uuid.fromDate(now).toString(),
                    dt: now.toISOString(),
                    domain: message.meta.domain,
                },
                database: message.database,
                page_id: message.page_id,
                page_title: message.page_title,
                page_namespace: message.page_namespace,
                rev_id: message.rev_id,
                rev_parent_id: message.rev_parent_id,
                rev_timestamp: message.rev_timestamp,
                scores: [],
                errors: []
            };

            const domainScores = res.body[newMessage.database];
            const revScores = domainScores.scores[`${newMessage.rev_id}`];
            Object.keys(revScores).forEach((modelName) => {
                // The example schema for the score object:
                // {
                //   "model_name": "awesomeness",
                //   "model_version": "1.0",
                //   "prediction": ["yes", "mostly"],
                //   "probability": [
                //     {"name": "yes", "value": 0.99},
                //     {"name": "mostly", "value": 0.90},
                //     {"name": "hardly", "value": 0.01}
                //   ]
                // }
                const score = {
                    model_name: modelName,
                    model_version: domainScores.models[modelName].version,
                };
                if (revScores[modelName].error) {
                    Object.assign(score, revScores[modelName].error);
                    newMessage.errors.push(score);
                } else {
                    const originalScore = revScores[modelName].score;
                    // Convert prediction to array of strings
                    let prediction = originalScore.prediction;
                    if (!Array.isArray(prediction)) {
                        prediction = [ prediction ];
                    }
                    score.prediction = prediction.map(p => `${p}`);
                    // Convert probabilities to an array of name-value pairs.
                    score.probability = Object.keys(originalScore.probability).map(probName => ({
                        name: probName,
                        value: originalScore.probability[probName]
                    }));
                    newMessage.scores.push(score);
                }
            });
            return hyper.post({
                uri: this._options.eventbus_uri,
                headers: {
                    'content-type': 'application/json'
                },
                body: [ newMessage ]
            });
        });
    }
}

module.exports = (options) => {
    const processor = new OresProcessor(options);
    return {
        spec: {
            paths: {
                '/': {
                    post: {
                        summary: 'submit revision-create for processing',
                        operationId: 'process'
                    }
                }
            }
        },
        operations: {
            process: processor.process.bind(processor),
        }
    };
};
<|endoftext|>


<commit_before>'use strict';

exports.register = function (plugin, options, next) {

  plugin.ext('onPreResponse', function (request, reply) {
    var res = request.response;
    if (res.source && typeof res.source.then === 'function') {
      return res.source
        .then(function (value) {
          res.source = value;
          return res;
        })
        .catch(function (err) {
          throw err;
        })
        .then(reply, reply);
    }
    reply();
  });

  next();

};

exports.register.attributes = {
  pkg: require('./package.json')
}
<commit_msg>Remove extraneous code from debugging<commit_after>'use strict';

exports.register = function (plugin, options, next) {

  plugin.ext('onPreResponse', function (request, reply) {
    var res = request.response;
    if (res.source && typeof res.source.then === 'function') {
      return res.source
        .then(function (value) {
          res.source = value;
          return res;
        })
        .then(reply, reply);
    }
    reply();
  });

  next();

};

exports.register.attributes = {
  pkg: require('./package.json')
}
<|endoftext|>


<commit_before>var statusConfig = require('../../config/subcampaignStatus')
var app = require('../../server/server')
var roleManager = require('../../public/roleManager')
var utility = require('../../public/utility')
var startStyleList = require('../../config/startStyle.json')
var mediaStyleList = require('../../config/mediaStyle.json')

module.exports = function (campaign) {

  campaign.validatesInclusionOf('startStyle', { in: startStyleList })
  campaign.validatesInclusionOf('mediaStyle', { in: mediaStyleList })

  campaign.beforeRemote('prototype.__create__subcampaigns', function (ctx, modelInstance, next) {
    if (!ctx.args.options.accessToken)
      return next()
    ctx.args.data.clientId = ctx.args.options.accessToken.userId
    ctx.args.data.status = statusConfig.pending
    next()
  })

  campaign.beforeRemote('prototype.__updateById__subcampaigns', function (ctx, modelInstance, next) {
    roleManager.getRolesById(app, ctx.args.options.accessToken.userId, function (err, result) {
      if (err)
        return next(err)
      if (result.lenght == 0) {
        var whiteList = ['minBudget', 'name', 'style', 'plan', 'price']
        if (utility.inputChecker(ctx.args.data, whiteList)) {
          if (ctx.args.data.minBudget) {
            campaign.findById(ctx.req.params.id, function (err, result) {
              if (err)
                throw err
              var subBudget = 0
              for (var i = 0; i < result.subcampaignList.length; i++)
                subBudget += result.subcampaignList[i].minBudget
              if (ctx.args.data.minBudget + subBudget > result.budget)
                next(new Error('Error in Budget (Campaign)'))
              next()
            })
          }
        } else
          next(new Error('White List Error! Allowed Parameters: ' + whiteList.toString()))
        next()
      }
    })
  })

  campaign.afterRemote('prototype.__create__subcampaigns', function (ctx, modelInstance, next) {
    var campaignId = ctx.req.params.id
    campaign.findById(campaignId, function (err, result) {
      if (err)
        throw err
      result.updateAttribute('status', statusConfig.pending, function (err, response) {
        if (err)
          throw err
        next()
      })
    })
  })

  campaign.afterRemote('prototype.__updateById__subcampaigns', function (ctx, modelInstance, next) {
    campaign.findById(ctx.req.params.id, function (err, result) {
      if (err)
        throw err
      for (var i = 0; i < result.subcampaignList.length; i++) {
        if (result.subcampaignList[i].status === statusConfig.pending)
          result.status = status.pending
      }
      for (var i = 0; i < result.subcampaignList.length; i++) {
        if (result.subcampaignList[i].status === statusConfig.suspend)
          result.status = status.suspend
      }
        next()
    })
  })

}
<commit_msg>Fix WriteBack Bug by Using model.updateAttribute() function<commit_after>var statusConfig = require('../../config/subcampaignStatus')
var app = require('../../server/server')
var roleManager = require('../../public/roleManager')
var utility = require('../../public/utility')
var startStyleList = require('../../config/startStyle.json')
var mediaStyleList = require('../../config/mediaStyle.json')

module.exports = function (campaign) {

  campaign.validatesInclusionOf('startStyle', { in: startStyleList })
  campaign.validatesInclusionOf('mediaStyle', { in: mediaStyleList })

  campaign.beforeRemote('prototype.__create__subcampaigns', function (ctx, modelInstance, next) {
    if (!ctx.args.options.accessToken)
      return next()
    ctx.args.data.clientId = ctx.args.options.accessToken.userId
    ctx.args.data.status = statusConfig.pending
    next()
  })

  campaign.beforeRemote('prototype.__updateById__subcampaigns', function (ctx, modelInstance, next) {
    roleManager.getRolesById(app, ctx.args.options.accessToken.userId, function (err, result) {
      if (err)
        return next(err)
      if (result.lenght == 0) {
        var whiteList = ['minBudget', 'name', 'style', 'plan', 'price']
        if (utility.inputChecker(ctx.args.data, whiteList)) {
          if (ctx.args.data.minBudget) {
            campaign.findById(ctx.req.params.id, function (err, result) {
              if (err)
                throw err
              var subBudget = 0
              for (var i = 0; i < result.subcampaignList.length; i++)
                subBudget += result.subcampaignList[i].minBudget
              if (ctx.args.data.minBudget + subBudget > result.budget)
                next(new Error('Error in Budget (Campaign)'))
              next()
            })
          }
        } else
          next(new Error('White List Error! Allowed Parameters: ' + whiteList.toString()))
        next()
      }
    })
  })

  campaign.afterRemote('prototype.__create__subcampaigns', function (ctx, modelInstance, next) {
    var campaignId = ctx.req.params.id
    campaign.findById(campaignId, function (err, result) {
      if (err)
        throw err
      result.updateAttribute('status', statusConfig.pending, function (err, response) {
        if (err)
          throw err
        next()
      })
    })
  })

  campaign.afterRemote('prototype.__updateById__subcampaigns', function (ctx, modelInstance, next) {
    campaign.findById(ctx.req.params.id, function (err, result) {
      if (err)
        throw err
      for (var i = 0; i < result.subcampaignList.length; i++)
        if (result.subcampaignList[i].status === statusConfig.pending || result.subcampaignList[i].status === statusConfig.suspend)
          result.updateAttribute('status', result.subcampaignList[i].status, function (err, response) {
            if (err)
              throw err
            next()
          })
    })
  })

}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt

{% include 'selling/sales_common.js' %}

erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
	refresh: function(doc, dt, dn) {
		this._super();
		this.frm.dashboard.reset();

		if(doc.docstatus==1) {
			if(doc.status != 'Stopped') {

				// cur_frm.dashboard.add_progress(cint(doc.per_delivered) + __("% Delivered"),
				// 	doc.per_delivered);
				// cur_frm.dashboard.add_progress(cint(doc.per_billed) + __("% Billed"),
				// 	doc.per_billed);

				// delivery note
				if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
					cur_frm.add_custom_button(__('Make Delivery'), this.make_delivery_note);

				// indent
				if(!doc.order_type || ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
					cur_frm.add_custom_button(__('Make ') + __('Material Request'),
						this.make_material_request);

				// sales invoice
				if(flt(doc.per_billed, 2) < 100) {
					cur_frm.add_custom_button(__('Make Invoice'), this.make_sales_invoice);
				}
				cur_frm.add_custom_button(__('Make Opportunity'), cur_frm.cscript.make_oppurtunity);

				frappe.call({
					method:"erpnext.selling.custom_methods.get_roles_for_so_cancellation",
					callback:function(r){
							role_list = ['System Manager','Administrator']
							$.each(r.message, function(i){
							     	role_list.push(r.message[i][0])

							   })

							$.each(role_list,function(j){
							  	if(in_list(user_roles,role_list[j])){
							  		cur_frm.add_custom_button(__('Cancel for Exchange and Return'),cur_frm.cscript['cancel_sales_order'],"icon-folder-close")
							  		return false;

								  }
							})
					    }
				})

				// stop
				if(flt(doc.per_delivered, 2) < 100 || doc.per_billed < 100)
					cur_frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Sales Order'])

						// maintenance
						if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)===-1) {
							cur_frm.add_custom_button(__('Make Maint. Visit'), this.make_maintenance_visit);
							cur_frm.add_custom_button(__('Make Maint. Schedule'), this.make_maintenance_schedule);
						}

			} else {
				// un-stop
				cur_frm.add_custom_button(__('Unstop'), cur_frm.cscript['Unstop Sales Order']);
			}
		}

		if (this.frm.doc.docstatus===0) {
			cur_frm.add_custom_button(__('From Quotation'),
				function() {
					frappe.model.map_current_doc({
						method: "erpnext.selling.doctype.quotation.quotation.make_sales_order",
						source_doctype: "Quotation",
						get_query_filters: {
							docstatus: 1,
							status: ["!=", "Lost"],
							order_type: cur_frm.doc.order_type,
							customer: cur_frm.doc.customer || undefined,
							company: cur_frm.doc.company
						}
					})
				});
		}

		this.order_type(doc);
	},

	order_type: function() {
		this.frm.toggle_reqd("delivery_date", this.frm.doc.order_type == "Sales");
	},

	tc_name: function() {
		this.get_terms();
	},

	warehouse: function(doc, cdt, cdn) {
		var item = frappe.get_doc(cdt, cdn);
		if(item.item_code && item.warehouse) {
			return this.frm.call({
				method: "erpnext.stock.get_item_details.get_available_qty",
				child: item,
				args: {
					item_code: item.item_code,
					warehouse: item.warehouse,
				},
			});
		}
	},

	make_material_request: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_material_request",
			frm: cur_frm
		})
	},

	make_delivery_note: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
			frm: cur_frm
		})
	},

	make_oppurtunity: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.custom_methods.make_oppurtunity",
			frm: cur_frm
		})
	},

	make_sales_invoice: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_sales_invoice",
			frm: cur_frm
		})
	},

	make_maintenance_schedule: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_schedule",
			frm: cur_frm
		})
	},

	make_maintenance_visit: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_visit",
			frm: cur_frm
		})
	},
});

// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));

cur_frm.cscript.new_contact = function(){
	tn = frappe.model.make_new_doc_and_get_name('Contact');
	locals['Contact'][tn].is_customer = 1;
	if(doc.customer) locals['Contact'][tn].customer = doc.customer;
	loaddoc('Contact', tn);
}

cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
	return {
		query: "erpnext.controllers.queries.get_project_name",
		filters: {
			'customer': doc.customer
		}
	}
}

cur_frm.cscript['Stop Sales Order'] = function() {
	var doc = cur_frm.doc;

	var check = confirm(__("Are you sure you want to STOP ") + doc.name);

	if (check) {
		return $c('runserverobj', {
			'method':'stop_sales_order',
			'docs': doc
			}, function(r,rt) {
			cur_frm.refresh();
		});
	}
}

cur_frm.cscript['Unstop Sales Order'] = function() {
	var doc = cur_frm.doc;

	var check = confirm(__("Are you sure you want to UNSTOP ") + doc.name);

	if (check) {
		return $c('runserverobj', {
			'method':'unstop_sales_order',
			'docs': doc
		}, function(r,rt) {
			cur_frm.refresh();
		});
	}
}

cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
	if(cint(frappe.boot.notification_settings.sales_order)) {
		cur_frm.email_doc(frappe.boot.notification_settings.sales_order_message);
	}
};

{% include 'selling/custom_so_cancel.js' %}
cur_frm.script_manager.make(erpnext.selling.CustomSoCancel);
<commit_msg>include custom js file<commit_after>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt

{% include 'selling/sales_common.js' %}
{% include 'frappe_subscription/frappe_subscription/ec_sales_order.js' %}

erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
	refresh: function(doc, dt, dn) {
		this._super();
		this.frm.dashboard.reset();

		if(doc.docstatus==1) {
			if(doc.status != 'Stopped') {

				// cur_frm.dashboard.add_progress(cint(doc.per_delivered) + __("% Delivered"),
				// 	doc.per_delivered);
				// cur_frm.dashboard.add_progress(cint(doc.per_billed) + __("% Billed"),
				// 	doc.per_billed);

				// delivery note
				if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
					cur_frm.add_custom_button(__('Make Delivery'), this.make_delivery_note);

				// indent
				if(!doc.order_type || ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
					cur_frm.add_custom_button(__('Make ') + __('Material Request'),
						this.make_material_request);

				// sales invoice
				if(flt(doc.per_billed, 2) < 100) {
					cur_frm.add_custom_button(__('Make Invoice'), this.make_sales_invoice);
				}
				cur_frm.add_custom_button(__('Make Opportunity'), cur_frm.cscript.make_oppurtunity);

				frappe.call({
					method:"erpnext.selling.custom_methods.get_roles_for_so_cancellation",
					callback:function(r){
							role_list = ['System Manager','Administrator']
							$.each(r.message, function(i){
							     	role_list.push(r.message[i][0])

							   })

							$.each(role_list,function(j){
							  	if(in_list(user_roles,role_list[j])){
							  		cur_frm.add_custom_button(__('Cancel for Exchange and Return'),cur_frm.cscript['cancel_sales_order'],"icon-folder-close")
							  		return false;

								  }
							})
					    }
				})

				// stop
				if(flt(doc.per_delivered, 2) < 100 || doc.per_billed < 100)
					cur_frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Sales Order'])

						// maintenance
						if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)===-1) {
							cur_frm.add_custom_button(__('Make Maint. Visit'), this.make_maintenance_visit);
							cur_frm.add_custom_button(__('Make Maint. Schedule'), this.make_maintenance_schedule);
						}

			} else {
				// un-stop
				cur_frm.add_custom_button(__('Unstop'), cur_frm.cscript['Unstop Sales Order']);
			}
		}

		if (this.frm.doc.docstatus===0) {
			cur_frm.add_custom_button(__('From Quotation'),
				function() {
					frappe.model.map_current_doc({
						method: "erpnext.selling.doctype.quotation.quotation.make_sales_order",
						source_doctype: "Quotation",
						get_query_filters: {
							docstatus: 1,
							status: ["!=", "Lost"],
							order_type: cur_frm.doc.order_type,
							customer: cur_frm.doc.customer || undefined,
							company: cur_frm.doc.company
						}
					})
				});
		}

		this.order_type(doc);
	},

	order_type: function() {
		this.frm.toggle_reqd("delivery_date", this.frm.doc.order_type == "Sales");
	},

	tc_name: function() {
		this.get_terms();
	},

	warehouse: function(doc, cdt, cdn) {
		var item = frappe.get_doc(cdt, cdn);
		if(item.item_code && item.warehouse) {
			return this.frm.call({
				method: "erpnext.stock.get_item_details.get_available_qty",
				child: item,
				args: {
					item_code: item.item_code,
					warehouse: item.warehouse,
				},
			});
		}
	},

	make_material_request: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_material_request",
			frm: cur_frm
		})
	},

	make_delivery_note: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
			frm: cur_frm
		})
	},

	make_oppurtunity: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.custom_methods.make_oppurtunity",
			frm: cur_frm
		})
	},

	make_sales_invoice: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_sales_invoice",
			frm: cur_frm
		})
	},

	make_maintenance_schedule: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_schedule",
			frm: cur_frm
		})
	},

	make_maintenance_visit: function() {
		frappe.model.open_mapped_doc({
			method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_visit",
			frm: cur_frm
		})
	},
});

// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));

cur_frm.cscript.new_contact = function(){
	tn = frappe.model.make_new_doc_and_get_name('Contact');
	locals['Contact'][tn].is_customer = 1;
	if(doc.customer) locals['Contact'][tn].customer = doc.customer;
	loaddoc('Contact', tn);
}

cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
	return {
		query: "erpnext.controllers.queries.get_project_name",
		filters: {
			'customer': doc.customer
		}
	}
}

cur_frm.cscript['Stop Sales Order'] = function() {
	var doc = cur_frm.doc;

	var check = confirm(__("Are you sure you want to STOP ") + doc.name);

	if (check) {
		return $c('runserverobj', {
			'method':'stop_sales_order',
			'docs': doc
			}, function(r,rt) {
			cur_frm.refresh();
		});
	}
}

cur_frm.cscript['Unstop Sales Order'] = function() {
	var doc = cur_frm.doc;

	var check = confirm(__("Are you sure you want to UNSTOP ") + doc.name);

	if (check) {
		return $c('runserverobj', {
			'method':'unstop_sales_order',
			'docs': doc
		}, function(r,rt) {
			cur_frm.refresh();
		});
	}
}

cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
	if(cint(frappe.boot.notification_settings.sales_order)) {
		cur_frm.email_doc(frappe.boot.notification_settings.sales_order_message);
	}
};

{% include 'selling/custom_so_cancel.js' %}
cur_frm.script_manager.make(erpnext.selling.CustomSoCancel);
<|endoftext|>


<commit_before>"use strict";
var BuycraftAPI = require("buycraft-js");
var Query = require("mcquery");
var Rcon = require("rcon");
var sleep = require("sleep");
var async = require("async");
var c = require("./config.json");
var debug = c.DEBUG;
var client = new BuycraftAPI(c.BUYCRAFT_API_KEY);
var rclient = new Rcon(c.MINECRAFT_SERVER_RCON_IP, c.MINECRAFT_SERVER_RCON_PORT, c.MINECRAFT_SERVER_RCON_PASSWORD); // connect to Rcon
var rconTimeout, maininfo, players, commands, command, finalcommand, finalcommandsplit, finalcommandd;
var query = new Query(c.MINECRAFT_SERVER_IP, c.MINECRAFT_SERVER_PORT, { timeout: 500 }); // query server for player list

// first check to make sure key works
client.information(function(err, r){
    if(err){
        console.log("[ERROR] " + err);
        process.exit();
    } else {
        checkDue();
    }
});

rclient.on("auth", function() {
    console.log("[INFO] Authenticated with " + c.MINECRAFT_SERVER_RCON_IP + ":" + c.MINECRAFT_SERVER_RCON_PORT);
}).on("response", function(str) {
    if (debug && str) {
        console.log("[DEBUG] Got response: " + str);
    }
}).on("end", function() {
    console.log("[INFO] Rcon closed!");
}).on("error", function() { // rcon reconnect - thanks to Secret_Online
    if (typeof rconTimeout === 'undefined') {
        rclient.disconnect();
        if(debug) {
            console.log("[DEBUG] Trying to reconnect again in " + c.RCON_RECONNECT_DELAY + " seconds...");
        }
        rconTimeout = setTimeout(function() {
            rclient.connect();
            rconTimeout = undefined;
        }, c.RCON_RECONNECT_DELAY * 1000);
    }
});

rclient.connect();

function checkDue() {
    client.duePlayers(function(err, info) { // get due players list from BuyCraft API
        maininfo = info;
        if (err) {
            console.log("[ERROR] Got error: " + err);
        } else {
            if(maininfo.players.length == 0) { // if no players, wait for the amount of time specified in API
                setTimeout(checkDue, maininfo.meta.next_check * 1000);
                if (debug) {
                    console.log("[DEBUG] Waiting for " + maininfo.meta.next_check + " seconds until next check.");
                }
            } else {
                players = maininfo.players;

                async.each(players, function (player, cb) { // if players, loop through them using async
                    //player = players[player];

                    query.connect(function (err) {
                        if (err) {
                            cb(err);
                        } else {
                            query.full_stat(function(err, stat) {
                                if(stat.player_.indexOf(player.name) > -1) { // check if player is online
                                    client.getOnlineCommands(player.id,function(err, online){ // get players commands
                                        if(!err) {
                                            if(online.commands.length !== 0) {
                                                commands = online.commands;
                                                for(command in commands) {
                                                    command = commands[command];

                                                    finalcommand = command.command;

                                                    finalcommandsplit = finalcommand.split(" ");

                                                    for(finalcommandd in finalcommandsplit) { // replace doubles to integers (mc does not support doubles)
                                                        if(!isNaN(finalcommandsplit[finalcommandd])) {
                                                            finalcommandsplit[finalcommandd] = (Math.round(Number(finalcommandsplit[finalcommandd]))).toString();
                                                        }
                                                    }
                                                    finalcommand = finalcommandsplit.join(" ");

                                                    finalcommand = finalcommand.replace("{name}", player.name); // replace name with player name
                                                    rclient.send(finalcommand); // send command to server via rcon
                                                    console.log("[INFO] Processed command " + command.id + " ( " + finalcommand + " ) by " + player.name + ".");
                                                    client.deleteCommands([command.id], function(err, bool) { // delete command from BuyCraft
                                                        if(!err && debug) {
                                                            console.log("[DEBUG] Deleted command.")
                                                        }
                                                    });
                                                    sleep.sleep(c.INTERVAL_BETWEEN_COMMAND_SENT); //ewwww - I will get rid of this ASAP
                                                }
                                            } else {
                                                if(debug) {
                                                    console.log("[DEBUG] No commands found.");
                                                }
                                            }
                                            cb();
                                        } else {
                                            cb(err);
                                        }
                                    });
                                } else {
                                    if(debug) {
                                        console.log("[DEBUG] Player " + player.name + " is not currently online. Trying again soon...")
                                    }
                                    cb();
                                }
                            });
                        }
                    });
                }, function(err) { // wait for the amount of time specified by API to try again
                    if(err) {
                        console.log("[ERROR] "+err);
                    }
                    setTimeout(checkDue, maininfo.meta.next_check * 1000);
                    if (debug) {
                        console.log("[DEBUG] Waiting for " + maininfo.meta.next_check + " seconds until next check.");
                    }
                });

            }
        }
    });
}
<commit_msg>Remove need for async and sleep<commit_after>"use strict";
var BuycraftAPI = require("buycraft-js");
var Query = require("mcquery");
var Rcon = require("rcon");

var c = require("./config.json");
var debug = c.DEBUG;
var client = new BuycraftAPI(c.BUYCRAFT_API_KEY);
var rclient = new Rcon(c.MINECRAFT_SERVER_RCON_IP, c.MINECRAFT_SERVER_RCON_PORT, c.MINECRAFT_SERVER_RCON_PASSWORD); // connect to Rcon
var rconTimeout, maininfo, players, playercount, commands, command, finalcommand, finalcommandsplit, finalcommandd;
var query = new Query(c.MINECRAFT_SERVER_IP, c.MINECRAFT_SERVER_PORT, { timeout: 500 }); // query server for player list

// first check to make sure key works
client.information(function(err, r){
    if(err){
        console.log("[ERROR] " + err);
        process.exit();
    } else {
        checkDue();
    }
});

rclient.on("auth", function() {
    console.log("[INFO] Authenticated with " + c.MINECRAFT_SERVER_RCON_IP + ":" + c.MINECRAFT_SERVER_RCON_PORT);
}).on("response", function(str) {
    if (debug && str) {
        console.log("[DEBUG] Got response: " + str);
    }
}).on("end", function() {
    console.log("[INFO] Rcon closed!");
}).on("error", function() { // rcon reconnect - thanks to Secret_Online
    if (typeof rconTimeout === 'undefined') {
        rclient.disconnect();
        if(debug) {
            console.log("[DEBUG] Trying to reconnect again in " + c.RCON_RECONNECT_DELAY + " seconds...");
        }
        rconTimeout = setTimeout(function() {
            rclient.connect();
            rconTimeout = undefined;
        }, c.RCON_RECONNECT_DELAY * 1000);
    }
});

rclient.connect();

function getCommands(maininfo) {

}

function checkDue() {
    client.duePlayers(function(err, info) { // get due players list from BuyCraft API
        maininfo = info;
        if (err) {
            console.log("[ERROR] Got error: " + err);
        } else {
            if(maininfo.players.length == 0) { // if no players, wait for the amount of time specified in API
                setTimeout(checkDue, maininfo.meta.next_check * 1000);
                if (debug) {
                    console.log("[DEBUG] Waiting for " + maininfo.meta.next_check + " seconds until next check.");
                }
            } else {
                players = maininfo.players;
                playercount = players.length;
                nextPlayer(0);
                function nextPlayer(n) { // if players, loop through them

                    if(n >= players.length){ // done with this cycle
                        setTimeout(checkDue, maininfo.meta.next_check * 1000);
                        if (debug) {
                            console.log("[DEBUG] Waiting for " + maininfo.meta.next_check + " seconds until next check.");
                        }
                        return;
                    }

                    var player = players[n];
                    console.log(player.name);

                    query.connect(function (err) {
                        if (err) {
                            cb(err);
                        } else {
                            if(maininfo.meta.execute_offline) {

                            } else {
                                query.full_stat(function(err, stat) {
                                    if(stat.player_.indexOf(player.name) > -1) { // check if player is online
                                        client.getOnlineCommands(player.id,function(err, online){ // get players commands
                                            if(!err) {
                                                if(online.commands.length !== 0) {
                                                    commands = online.commands;
                                                    runCommands(0);
                                                    function runCommands(i) {

                                                        if(i >= commands.length){
                                                            nextPlayer(n + 1);
                                                            return;
                                                        }

                                                        finalcommand = commands[i].command;

                                                        finalcommandsplit = finalcommand.split(" ");

                                                        for(finalcommandd in finalcommandsplit) { // replace doubles to integers (mc does not support doubles)
                                                            if(!isNaN(finalcommandsplit[finalcommandd])) {
                                                                finalcommandsplit[finalcommandd] = (Math.round(Number(finalcommandsplit[finalcommandd]))).toString();
                                                            }
                                                        }
                                                        finalcommand = finalcommandsplit.join(" ");
                                                        finalcommand = finalcommand.replace("{name}", player.name); // replace name with player name

                                                        rclient.send(finalcommand); // send command to server via rcon
                                                        console.log("[INFO] Processed command " + commands[i].id + " ( " + finalcommand + " ) by " + player.name + ".");
                                                        client.deleteCommands([commands[i].id], function(err, bool) { // delete command from BuyCraft
                                                            if(!err && debug) {
                                                                console.log("[DEBUG] Deleted command.");
                                                            }
                                                        });
                                                        playercount--;

                                                        var b = i+1;
                                                        if(playercount > 0) {
                                                            setTimeout(runCommands.bind(null, i + 1), c.INTERVAL_BETWEEN_COMMAND_SENT * 1000); // set timeout for next command
                                                        } else {
                                                            runCommands(i + 1); // just run again to cancel
                                                        }
                                                    }
                                                } else {
                                                    if(debug) {
                                                        console.log("[DEBUG] No commands found.");
                                                    }
                                                    playercount--;
                                                }
                                            } else {
                                                console.log("[ERROR] "+err);
                                                playercount--;
                                            }
                                        });
                                    } else {
                                        if(debug) {
                                            console.log("[DEBUG] Player " + player.name + " is not currently online. Trying again soon...")
                                        }
                                        playercount--;
                                        nextPlayer(n + 1);
                                        return;
                                    }
                                });
                            }
                        }
                    });
                };

            }
        }
    });
}
<|endoftext|>


<commit_before>// Gauntlet: A wrapper and configuration tool to
// handle multiple Google Analytics accounts
// Version 1.0.0
// Author: Joshua Beckman | @andjosh
// Author URI: http://www.andjosh.com

(function(window,document){
  'use strict';
  var Gauntlet = function(options){
    var defaults = {
      linkId: false,
      displayFeatures: false,
      accounts: [],
      custom: {},
      loadBase: true
    };
    if (!options) {
      throw new Error('A options object is required for Gauntlet to initialize. It should look something like: ' + JSON.stringify(defaults));
    }
    this.opt = extend(options, defaults);
    this.throw();
  };
  Gauntlet.prototype = {
    throw: function() {
      if (this.opt.accounts.length < 1 || !this.opt.accounts[0].profile) {
        throw new Error('At least one analytics account is required for Gauntlet to initialize.');
      }
      if (this.opt.loadBase) {
        this.base();
      }
      this.assets();
      this.view();
    },
    base: function(){
      function isogram(i,s,o,g,r,a,m){
        i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m);
      }
      isogram(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    },
    assets: function(){
      var name, i;
      if(this.opt.displayFeatures){
        window.ga('require', 'displayfeatures');
        for (i = 1; i < this.opt.accounts.length; i++) {
          name = this.opt.accounts[i].name;
          window.ga(name + '.require', 'displayfeatures');
        }
      }
      if(this.opt.linkId){
        window.ga('require', 'linkid', 'linkid.js');
        for (i = 1; i < this.opt.accounts.length; i++) {
          name = this.opt.accounts[i].name;
          window.ga(name + '.require', 'linkid', 'linkid.js');
        }
      }
    },
    view: function(){
      var name,
        customObj = extend((this.opt.accounts[0].custom || {}), this.opt.custom);
      window.ga('create', this.opt.accounts[0].profile, this.opt.accounts[0].domain);
      if (Object.keys(customObj).length > 0){
        window.ga('send', 'pageview', customObj);
      } else {
        window.ga('send', 'pageview');
      }
      for (var i = 1; i < this.opt.accounts.length; i++) {
        name = this.opt.accounts[i].name;
        window.ga('create', this.opt.accounts[i].profile, this.opt.accounts[i].domain, {'name': name});
        customObj = extend((this.opt.accounts[i].custom || {}), this.opt.custom);
        if (Object.keys(customObj).length > 0){
          window.ga(name + '.send', 'pageview', customObj);
        } else {
          window.ga(name + '.send', 'pageview');
        }
      }
    }
  };
  // Fills in empty values in the first argument with values
  // found in subsequent arguments
  function extend (obj) {
    var i, def, n;
    for (i = 1; i < arguments.length; i++) {
      def = arguments[i];
      for (n in def) {
        if (obj[n] === undefined) { obj[n] = def[n]; }
      }
    }
    return obj;
  }
  window.Gauntlet = Gauntlet;
})(this, this.document);
<commit_msg>Update gauntlet.js<commit_after>// Gauntlet: A wrapper and configuration tool to
// handle multiple Google Analytics accounts
// Version 1.0.1
// Author: Joshua Beckman | @andjosh
// Author URI: http://www.andjosh.com

(function(window,document){
  'use strict';
  var Gauntlet = function(options){
    var defaults = {
      linkId: false,
      displayFeatures: false,
      accounts: [],
      custom: {},
      loadBase: true
    };
    if (!options) {
      throw new Error('A options object is required for Gauntlet to initialize. It should look something like: ' + JSON.stringify(defaults));
    }
    this.opt = extend(options, defaults);
    this.throw();
  };
  Gauntlet.prototype = {
    throw: function() {
      if (this.opt.accounts.length < 1 || !this.opt.accounts[0].profile) {
        throw new Error('At least one analytics account is required for Gauntlet to initialize.');
      }
      if (this.opt.loadBase) {
        this.base();
      }
      this.assets();
      this.view();
    },
    base: function(){
      function isogram(i,s,o,g,r,a,m){
        i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m);
      }
      isogram(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    },
    assets: function(){
      var name, i;
      if(this.opt.displayFeatures){
        window.ga('require', 'displayfeatures');
        for (i = 1; i < this.opt.accounts.length; i++) {
          name = this.opt.accounts[i].name;
          window.ga(name + '.require', 'displayfeatures');
        }
      }
      if(this.opt.linkId){
        window.ga('require', 'linkid', 'linkid.js');
        for (i = 1; i < this.opt.accounts.length; i++) {
          name = this.opt.accounts[i].name;
          window.ga(name + '.require', 'linkid', 'linkid.js');
        }
      }
    },
    view: function(){
      var name,
        customObj = extend((this.opt.accounts[0].custom || {}), this.opt.custom);
      window.ga('create', this.opt.accounts[0].profile, this.opt.accounts[0].domain);
      if (Object.keys(customObj).length > 0){
        window.ga('send', 'pageview', customObj);
      } else {
        window.ga('send', 'pageview');
      }
      for (var i = 1; i < this.opt.accounts.length; i++) {
        name = this.opt.accounts[i].name;
        window.ga('create', this.opt.accounts[i].profile, this.opt.accounts[i].domain, {'name': name});
        customObj = extend((this.opt.accounts[i].custom || {}), this.opt.custom);
        if (Object.keys(customObj).length > 0){
          window.ga(name + '.send', 'pageview', customObj);
        } else {
          window.ga(name + '.send', 'pageview');
        }
      }
    }
  };
  // Fills in empty values in the first argument with values
  // found in subsequent arguments
  function extend (obj) {
    var i, def, n;
    for (i = 1; i < arguments.length; i++) {
      def = arguments[i];
      for (n in def) {
        if (obj[n] === undefined) { obj[n] = def[n]; }
      }
    }
    return obj;
  }
  window.Gauntlet = Gauntlet;
})(this, this.document);
<|endoftext|>


<commit_before>/*    Copyright 2020 Firewalla INC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program 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/>.
 */
'use strict';

const log = require('../net2/logger.js')(__filename);
const Sensor = require('./Sensor.js').Sensor;
const sem = require('./SensorEventManager.js').getInstance();
const PM2 = require('../alarm/PolicyManager2.js');
const pm2 = new PM2();
const execAsync = require('child-process-promise').exec;
const scheduler = require('../extension/scheduler/scheduler.js');
const f = require('../net2/Firewalla.js');
const DNSTool = require('../net2/DNSTool.js');
const dnsTool = new DNSTool();
const {Address4, Address6} = require('ip-address');
const Constants = require('../net2/Constants.js');

class RuleCheckSensor extends Sensor {
  constructor() {
    super();
    this.ipsetCache = {
      "block_ip_set": null,
      "sec_block_ip_set": null,
      "allow_ip_set": null,
      "block_net_set": null,
      "sec_block_net_set": null,
      "allow_net_set": null,
      "block_domain_set": null,
      "sec_block_domain_set": null,
      "allow_domain_set": null,
      "block_ib_ip_set": null,
      "allow_ib_ip_set": null,
      "block_ib_net_set": null,
      "allow_ib_net_set": null,
      "block_ib_domain_set": null,
      "allow_ib_domain_set": null,
      "block_ob_ip_set": null,
      "allow_ob_ip_set": null,
      "block_ob_net_set": null,
      "allow_ob_net_set": null,
      "block_ob_domain_set": null,
      "allow_ob_domain_set": null,
      "block_ip_set6": null,
      "sec_block_ip_set6": null,
      "allow_ip_set6": null,
      "block_net_set6": null,
      "sec_block_net_set6": null,
      "allow_net_set6": null,
      "block_domain_set6": null,
      "sec_block_domain_set6": null,
      "allow_domain_set6": null,
      "block_ib_ip_set6": null,
      "allow_ib_ip_set6": null,
      "block_ib_net_set6": null,
      "allow_ib_net_set6": null,
      "block_ib_domain_set6": null,
      "allow_ib_domain_set6": null,
      "block_ob_ip_set6": null,
      "allow_ob_ip_set6": null,
      "block_ob_net_set6": null,
      "allow_ob_net_set6": null,
      "block_ob_domain_set6": null,
      "allow_ob_domain_set6": null
    }
  }

  _clearIpsetCache() {
    for (const set in this.ipsetCache)
      this.ipsetCache[set] = null;
  }

  async _readIpsetEntries(set) {
    if (!set || !Object.keys(this.ipsetCache).includes(set)) {
      log.error(`Ipset ${set} is not supported for checking`);
      return [];
    }
    if (this.ipsetCache[set] === null) {
      this.ipsetCache[set] = await execAsync(`sudo ipset list ${set}`).then((result) => result.stdout && result.stdout.split("\n").filter(l => l && l.length > 0) || []).catch((err) => {
        log.error(`Failed to read entries from ipset ${set}`, err.message);
        return [];
      });
    }
    return this.ipsetCache[set];
  }

  run() {
    sem.once('IPTABLES_READY', () => {
      let interval = (this.config.interval || 10) * 60 * 1000; // 10 minute
      setInterval(() => {
        this._clearIpsetCache();
        this.checkRules();
      }, interval);
    })
  }

  async checkRules() {
    if (await pm2.isDisableAll()) {
      return; // temporarily by DisableAll flag
    }

    let policies = await pm2.loadActivePoliciesAsync({ includingDisabled: 1 });
    for (const policy of policies) {
      const needCheckActive = await this.needCheckActive(policy);
      if (needCheckActive) {
        await this.checkActiveRule(policy);
      }
    }
  }

  async needCheckActive(policy) {
    if (policy.type && ["ip", "net", "domain", "dns"].includes(policy.type)) {
      // other rule types have separate rules
      if (policy.action === "qos")
        return false;
      if (policy.action === "route")
        return false;
      if (policy.action === "match_group")
        return false;
      if (policy.disabled == 1) {
        return false;
      }
      if (Number.isInteger(policy.ipttl))
        return false;
      // device level rule has separate rule in iptables
      if (policy.scope && policy.scope.length > 0) {
        return false;
      }
      // network/group level rule has separate rule in iptables
      if (policy.tag && policy.tag.length > 0) {
        return false;
      }
      // vpn profile rule has separate rule in iptables
      if (policy.vpnProfile && policy.vpnProfile.length > 0) {
        return false;
      }
      // rule group rule has separate chain in iptables
      if (policy.parentRgId && policy.parentRgId.length > 0) {
        return false;
      }
      // non-regular rule has separate rule in iptables
      let seq = policy.seq;
      if (!seq) {
        seq = Constants.RULE_SEQ_REG;
        if (this._isActiveProtectRule(policy))
          seq = Constants.RULE_SEQ_HI;
        if (this._isInboundAllowRule(policy))
          seq = Constants.RULE_SEQ_LO;
        if (this._isInboundFirewallRule(policy))
          seq = Constants.RULE_SEQ_LO;
      }
      if (seq !== Constants.RULE_SEQ_REG)
        return false;
      // do not check expired rules
      if (policy.expire) {
        if (policy.willExpireSoon() || policy.isExpired()) {
          return false;
        }
      }
      // do not check rules that are not scheduled to be effective
      if (policy.cronTime) {
        const x = scheduler.shouldPolicyBeRunning(policy);
        if (x <= 0)
          return false;
      }
      // there is a separate rule for rule that has specified local/remote port
      if (policy.localPort || policy.remotePort) {
        return false;
      }
      return true;
    }
    return false;
  }

  async checkIpSetHasEntry(targets, ipset) {
    if (!targets || !ipset)
      return true;
    const entries = await this._readIpsetEntries(ipset);
    if (entries && Array.isArray(entries)) {
      return targets.filter(t => !entries.includes(t)).length === 0;
    }
    return true;
  }

  _isActiveProtectRule(rule) {
    return rule && rule.type === "category" && rule.target == "default_c" && rule.action == "block";
  }

  _isInboundAllowRule(rule) {
    return rule && rule.direction === "inbound" && rule.action === "allow" && rule.type !== "intranet" && rule.type !== "network" && rule.type !== "tag" && rule.type !== "device";
  }

  _isInboundFirewallRule(rule) {
    return rule && rule.direction === "inbound"
      && (rule.action || "block") === "block"
      && !ht.isMacAddress(rule.target)
      && _.isEmpty(rule.scope)
      && _.isEmpty(rule.tag)
      && _.isEmpty(rule.vpnProfile);
  }

  async checkActiveRule(policy) {
    const type = policy["i.type"] || policy["type"];
    if (pm2.isFirewallaOrCloud(policy)) {
      return;
    }

    let needEnforce = false;
    let { pid, scope, target, action = "block", tag, remotePort, localPort, protocol, direction, upnp, vpnProfile, seq } = policy;
    if (scope && scope.length > 0)
      return;
    if (tag && tag.length > 0)
      return;
    if (vpnProfile && vpnProfile.length > 0)
      return;
    if (localPort || remotePort)
      return;
    if (!target)
      return;

    log.debug(`Checking rule enforcement ${pid}`);

    const security = policy.method == 'auto' && policy.category == 'intel' && action == 'block'

    switch (type) {
      case "ip":
      case "net": {
        if (!new Address4(target).isValid() && !new Address6(target).isValid())
          return;
        if (type === "net") {
          if (new Address4(target).isValid()) {
            const addr4 = new Address4(target);
            target = `${addr4.startAddress().addressMinusSuffix}${addr4.subnet === "/32" ? "" : addr4.subnet}`;
          } else {
            const addr6 = new Address4(target);
            target = `${addr6.startAddress().addressMinusSuffix}${addr6.subnet === "/128" ? "" : addr6.subnet}`;
          }
        }
        const set = (security ? 'sec_' : '' )
          + (action === "allow" ? 'allow_' : 'block_')
          + (direction === "inbound" ? "ib_" : (direction === "outbound" ? "ob_" : ""))
          + type + "_set" + (new Address4(target).isValid() ? "" : "6");
        const result = await this.checkIpSetHasEntry([target], set);
        if (!result)
          needEnforce = true;
        break;
      }
      case "dns":
      case "domain": {
        let ips = await dnsTool.getIPsByDomain(target);
        if (ips) {
          const ip4Addrs = ips && ips.filter((ip) => !f.isReservedBlockingIP(ip) && new Address4(ip).isValid());
          const ip6Addrs = ips && ips.filter((ip) => !f.isReservedBlockingIP(ip) && new Address6(ip).isValid());
          const set4 = (security ? 'sec_' : '' )
            + (action === "allow" ? 'allow_' : 'block_')
            + (direction === "inbound" ? "ib_" : (direction === "outbound" ? "ob_" : ""))
            + "domain_set";
          const set6 = `${set4}6`;
          const result = await this.checkIpSetHasEntry(ip4Addrs, set4) && await this.checkIpSetHasEntry(ip6Addrs, set6);
          if (!result)
            needEnforce = true;
        }
        break;
      }
      default:
    }

    if (needEnforce) {
      log.info(`Need to reenforce rule ${pid}`);
      await pm2.tryPolicyEnforcement(policy, 'reenforce', policy);
    }
  }
}

module.exports = RuleCheckSensor;
<commit_msg>only match non-local type in _isInboundFirewallRule in RuleCheckSensor<commit_after>/*    Copyright 2020 Firewalla INC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program 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/>.
 */
'use strict';

const log = require('../net2/logger.js')(__filename);
const Sensor = require('./Sensor.js').Sensor;
const sem = require('./SensorEventManager.js').getInstance();
const PM2 = require('../alarm/PolicyManager2.js');
const pm2 = new PM2();
const execAsync = require('child-process-promise').exec;
const scheduler = require('../extension/scheduler/scheduler.js');
const f = require('../net2/Firewalla.js');
const DNSTool = require('../net2/DNSTool.js');
const dnsTool = new DNSTool();
const {Address4, Address6} = require('ip-address');
const Constants = require('../net2/Constants.js');

class RuleCheckSensor extends Sensor {
  constructor() {
    super();
    this.ipsetCache = {
      "block_ip_set": null,
      "sec_block_ip_set": null,
      "allow_ip_set": null,
      "block_net_set": null,
      "sec_block_net_set": null,
      "allow_net_set": null,
      "block_domain_set": null,
      "sec_block_domain_set": null,
      "allow_domain_set": null,
      "block_ib_ip_set": null,
      "allow_ib_ip_set": null,
      "block_ib_net_set": null,
      "allow_ib_net_set": null,
      "block_ib_domain_set": null,
      "allow_ib_domain_set": null,
      "block_ob_ip_set": null,
      "allow_ob_ip_set": null,
      "block_ob_net_set": null,
      "allow_ob_net_set": null,
      "block_ob_domain_set": null,
      "allow_ob_domain_set": null,
      "block_ip_set6": null,
      "sec_block_ip_set6": null,
      "allow_ip_set6": null,
      "block_net_set6": null,
      "sec_block_net_set6": null,
      "allow_net_set6": null,
      "block_domain_set6": null,
      "sec_block_domain_set6": null,
      "allow_domain_set6": null,
      "block_ib_ip_set6": null,
      "allow_ib_ip_set6": null,
      "block_ib_net_set6": null,
      "allow_ib_net_set6": null,
      "block_ib_domain_set6": null,
      "allow_ib_domain_set6": null,
      "block_ob_ip_set6": null,
      "allow_ob_ip_set6": null,
      "block_ob_net_set6": null,
      "allow_ob_net_set6": null,
      "block_ob_domain_set6": null,
      "allow_ob_domain_set6": null
    }
  }

  _clearIpsetCache() {
    for (const set in this.ipsetCache)
      this.ipsetCache[set] = null;
  }

  async _readIpsetEntries(set) {
    if (!set || !Object.keys(this.ipsetCache).includes(set)) {
      log.error(`Ipset ${set} is not supported for checking`);
      return [];
    }
    if (this.ipsetCache[set] === null) {
      this.ipsetCache[set] = await execAsync(`sudo ipset list ${set}`).then((result) => result.stdout && result.stdout.split("\n").filter(l => l && l.length > 0) || []).catch((err) => {
        log.error(`Failed to read entries from ipset ${set}`, err.message);
        return [];
      });
    }
    return this.ipsetCache[set];
  }

  run() {
    sem.once('IPTABLES_READY', () => {
      let interval = (this.config.interval || 10) * 60 * 1000; // 10 minute
      setInterval(() => {
        this._clearIpsetCache();
        this.checkRules();
      }, interval);
    })
  }

  async checkRules() {
    if (await pm2.isDisableAll()) {
      return; // temporarily by DisableAll flag
    }

    let policies = await pm2.loadActivePoliciesAsync({ includingDisabled: 1 });
    for (const policy of policies) {
      const needCheckActive = await this.needCheckActive(policy);
      if (needCheckActive) {
        await this.checkActiveRule(policy);
      }
    }
  }

  async needCheckActive(policy) {
    if (policy.type && ["ip", "net", "domain", "dns"].includes(policy.type)) {
      // other rule types have separate rules
      if (policy.action === "qos")
        return false;
      if (policy.action === "route")
        return false;
      if (policy.action === "match_group")
        return false;
      if (policy.disabled == 1) {
        return false;
      }
      if (Number.isInteger(policy.ipttl))
        return false;
      // device level rule has separate rule in iptables
      if (policy.scope && policy.scope.length > 0) {
        return false;
      }
      // network/group level rule has separate rule in iptables
      if (policy.tag && policy.tag.length > 0) {
        return false;
      }
      // vpn profile rule has separate rule in iptables
      if (policy.vpnProfile && policy.vpnProfile.length > 0) {
        return false;
      }
      // rule group rule has separate chain in iptables
      if (policy.parentRgId && policy.parentRgId.length > 0) {
        return false;
      }
      // non-regular rule has separate rule in iptables
      let seq = policy.seq;
      if (!seq) {
        seq = Constants.RULE_SEQ_REG;
        if (this._isActiveProtectRule(policy))
          seq = Constants.RULE_SEQ_HI;
        if (this._isInboundAllowRule(policy))
          seq = Constants.RULE_SEQ_LO;
        if (this._isInboundFirewallRule(policy))
          seq = Constants.RULE_SEQ_LO;
      }
      if (seq !== Constants.RULE_SEQ_REG)
        return false;
      // do not check expired rules
      if (policy.expire) {
        if (policy.willExpireSoon() || policy.isExpired()) {
          return false;
        }
      }
      // do not check rules that are not scheduled to be effective
      if (policy.cronTime) {
        const x = scheduler.shouldPolicyBeRunning(policy);
        if (x <= 0)
          return false;
      }
      // there is a separate rule for rule that has specified local/remote port
      if (policy.localPort || policy.remotePort) {
        return false;
      }
      return true;
    }
    return false;
  }

  async checkIpSetHasEntry(targets, ipset) {
    if (!targets || !ipset)
      return true;
    const entries = await this._readIpsetEntries(ipset);
    if (entries && Array.isArray(entries)) {
      return targets.filter(t => !entries.includes(t)).length === 0;
    }
    return true;
  }

  _isActiveProtectRule(rule) {
    return rule && rule.type === "category" && rule.target == "default_c" && rule.action == "block";
  }

  _isInboundAllowRule(rule) {
    return rule && rule.direction === "inbound" && rule.action === "allow" && rule.type !== "intranet" && rule.type !== "network" && rule.type !== "tag" && rule.type !== "device";
  }

  _isInboundFirewallRule(rule) {
    return rule && rule.direction === "inbound"
      && (rule.action || "block") === "block"
      && !ht.isMacAddress(rule.target)
      && _.isEmpty(rule.scope)
      && _.isEmpty(rule.tag)
      && _.isEmpty(rule.vpnProfile)
      && rule.type !== "intranet" && rule.type !== "network" && rule.type !== "tag" && rule.type !== "device";
  }

  async checkActiveRule(policy) {
    const type = policy["i.type"] || policy["type"];
    if (pm2.isFirewallaOrCloud(policy)) {
      return;
    }

    let needEnforce = false;
    let { pid, scope, target, action = "block", tag, remotePort, localPort, protocol, direction, upnp, vpnProfile, seq } = policy;
    if (scope && scope.length > 0)
      return;
    if (tag && tag.length > 0)
      return;
    if (vpnProfile && vpnProfile.length > 0)
      return;
    if (localPort || remotePort)
      return;
    if (!target)
      return;

    log.debug(`Checking rule enforcement ${pid}`);

    const security = policy.method == 'auto' && policy.category == 'intel' && action == 'block'

    switch (type) {
      case "ip":
      case "net": {
        if (!new Address4(target).isValid() && !new Address6(target).isValid())
          return;
        if (type === "net") {
          if (new Address4(target).isValid()) {
            const addr4 = new Address4(target);
            target = `${addr4.startAddress().addressMinusSuffix}${addr4.subnet === "/32" ? "" : addr4.subnet}`;
          } else {
            const addr6 = new Address4(target);
            target = `${addr6.startAddress().addressMinusSuffix}${addr6.subnet === "/128" ? "" : addr6.subnet}`;
          }
        }
        const set = (security ? 'sec_' : '' )
          + (action === "allow" ? 'allow_' : 'block_')
          + (direction === "inbound" ? "ib_" : (direction === "outbound" ? "ob_" : ""))
          + type + "_set" + (new Address4(target).isValid() ? "" : "6");
        const result = await this.checkIpSetHasEntry([target], set);
        if (!result)
          needEnforce = true;
        break;
      }
      case "dns":
      case "domain": {
        let ips = await dnsTool.getIPsByDomain(target);
        if (ips) {
          const ip4Addrs = ips && ips.filter((ip) => !f.isReservedBlockingIP(ip) && new Address4(ip).isValid());
          const ip6Addrs = ips && ips.filter((ip) => !f.isReservedBlockingIP(ip) && new Address6(ip).isValid());
          const set4 = (security ? 'sec_' : '' )
            + (action === "allow" ? 'allow_' : 'block_')
            + (direction === "inbound" ? "ib_" : (direction === "outbound" ? "ob_" : ""))
            + "domain_set";
          const set6 = `${set4}6`;
          const result = await this.checkIpSetHasEntry(ip4Addrs, set4) && await this.checkIpSetHasEntry(ip6Addrs, set6);
          if (!result)
            needEnforce = true;
        }
        break;
      }
      default:
    }

    if (needEnforce) {
      log.info(`Need to reenforce rule ${pid}`);
      await pm2.tryPolicyEnforcement(policy, 'reenforce', policy);
    }
  }
}

module.exports = RuleCheckSensor;
<|endoftext|>


<commit_before>var loopback = require('loopback');
var assert = require('assert');
var debug = require('debug')('freecoder:pomodoro');

module.exports = function (Pomodoro) {
  var STATUS = {
    'INPROGRESS': 'inProgress',
    'SKIPPED': 'skipped',
    'FINISHED': 'finished'
  };
  Pomodoro.beforeRemote('create', function (ctx, modelInstance, next) {
    console.log(arguments);
    // Fill default values if not set.
    var reqBody = ctx.req.body;
    if (!reqBody.duration) {
      reqBody.duration = 25 * 60 * 1000; // default is 25 minutes, TODO: read this from user config.
    }
    if (!reqBody.status) {
      reqBody.status = STATUS.INPROGRESS;
    }
    next();
  });

  Pomodoro.remoteMethod('skipPomodoro', {
      description: 'Skip a in progress pomodoro.',
      accepts: [
        {arg: 'id', type: 'string', required: true}
      ],
      http: {verb: 'put', path: '/:id/status/skipped'}
    }
  );

  Pomodoro.remoteMethod('finishPomodoro', {
      description: 'Finish a in progress pomodoro.',
      accepts: [
        {arg: 'id', type: 'string', required: true}
      ],
      http: {verb: 'put', path: '/:id/status/finished'}
    }
  );

  Pomodoro.skipPomodoro = function (id, cb) {
    Pomodoro.findById(id, function (err, pomodoro) {
      if (err)
        cb(err);

      checkPomodoroInstance(pomodoro, cb);
      checkPomodoroStatus(pomodoro, cb);
      debug('Setting pomodoro status to "skipped" of id:', id);
      pomodoro.updateAttribute('status', STATUS.SKIPPED, function (err, inst) {
        if (err)
          cb(err);
        debug('..success');
        cb(null, inst);
      });
    });
  };

  Pomodoro.finishPomodoro = function (id, cb) {
    Pomodoro.findById(id, function (err, pomodoro) {
      if (err)
        cb(err);

      checkPomodoroInstance(pomodoro, cb);
      checkPomodoroStatus(pomodoro, cb);
      debug('Setting pomodoro status to "finished" of id:', id);
      pomodoro.updateAttribute('status', STATUS.SKIPPED, function (err, inst) {
        if (err)
          cb(err);
        debug('..success');
        cb(null, inst);
      });
    });
  };

  var checkPomodoroInstance = function (pomodoro, cb) {
    if (!pomodoro) {
      var e = new Error('Not found');
      e.status = e.statusCode = 404;
      e.code = 'NOT_FOUND';
      cb(e);
    }
  };

  var checkPomodoroStatus = function (pomodoro, cb) {
    if (pomodoro.status != STATUS.INPROGRESS) {
      e = new Error('Incorrect status of Pomodoro');
      e.status = e.statusCode = 400;
      e.code = 'BAD_REQUEST';
      cb(e);
    }
  };
};
<commit_msg>Fix wrong status set in finishPomodoro method.<commit_after>var loopback = require('loopback');
var assert = require('assert');
var debug = require('debug')('freecoder:pomodoro');

module.exports = function (Pomodoro) {
  var STATUS = {
    'INPROGRESS': 'inProgress',
    'SKIPPED': 'skipped',
    'FINISHED': 'finished'
  };
  Pomodoro.beforeRemote('create', function (ctx, modelInstance, next) {
    console.log(arguments);
    // Fill default values if not set.
    var reqBody = ctx.req.body;
    if (!reqBody.duration) {
      reqBody.duration = 25 * 60 * 1000; // default is 25 minutes, TODO: read this from user config.
    }
    if (!reqBody.status) {
      reqBody.status = STATUS.INPROGRESS;
    }
    next();
  });

  Pomodoro.remoteMethod('skipPomodoro', {
      description: 'Skip a in progress pomodoro.',
      accepts: [
        {arg: 'id', type: 'string', required: true}
      ],
      http: {verb: 'put', path: '/:id/status/skipped'}
    }
  );

  Pomodoro.remoteMethod('finishPomodoro', {
      description: 'Finish a in progress pomodoro.',
      accepts: [
        {arg: 'id', type: 'string', required: true}
      ],
      http: {verb: 'put', path: '/:id/status/finished'}
    }
  );

  Pomodoro.skipPomodoro = function (id, cb) {
    Pomodoro.findById(id, function (err, pomodoro) {
      if (err)
        cb(err);

      checkPomodoroInstance(pomodoro, cb);
      checkPomodoroStatus(pomodoro, cb);
      debug('Setting pomodoro status to "skipped" of id:', id);
      pomodoro.updateAttribute('status', STATUS.SKIPPED, function (err, inst) {
        if (err)
          cb(err);
        debug('..success');
        cb(null, inst);
      });
    });
  };

  Pomodoro.finishPomodoro = function (id, cb) {
    Pomodoro.findById(id, function (err, pomodoro) {
      if (err)
        cb(err);

      checkPomodoroInstance(pomodoro, cb);
      checkPomodoroStatus(pomodoro, cb);
      debug('Setting pomodoro status to "finished" of id:', id);
      pomodoro.updateAttribute('status', STATUS.FINISHED, function (err, inst) {
        if (err)
          cb(err);
        debug('..success');
        cb(null, inst);
      });
    });
  };

  var checkPomodoroInstance = function (pomodoro, cb) {
    if (!pomodoro) {
      var e = new Error('Not found');
      e.status = e.statusCode = 404;
      e.code = 'NOT_FOUND';
      cb(e);
    }
  };

  var checkPomodoroStatus = function (pomodoro, cb) {
    if (pomodoro.status != STATUS.INPROGRESS) {
      e = new Error('Incorrect status of Pomodoro');
      e.status = e.statusCode = 400;
      e.code = 'BAD_REQUEST';
      cb(e);
    }
  };
};
<|endoftext|>


<commit_before>/**
 * Socket.io configuration
 */

'use strict';

var config = require('./environment');

// When the user disconnects.. perform this
function onDisconnect(socket) {
}

// When the user connects.. perform this
function onConnect(socket) {
  // When the client emits 'info', this listens and executes
  socket.on('info', function (data) {
    console.info('[%s] %s', socket.address, JSON.stringify(data, null, 2));
  });

  // Insert sockets below
  require('../api/status/status.socket').register(socket);
  require('../api/subformtext/subformtext.socket').register(socket);
  require('../api/submission/submission.socket').register(socket);
}

module.exports = function (socketio) {
  // socket.io (v1.x.x) is powered by debug.
  // In order to see all the debug output, set DEBUG (in server/config/local.env.js) to including the desired scope.
  //
  // ex: DEBUG: "http*,socket.io:socket"

  // We can authenticate socket.io users and access their token through socket.handshake.decoded_token
  //
  // 1. You will need to send the token in `client/components/socket/socket.service.js`
  //
  // 2. Require authentication here:
  // socketio.use(require('socketio-jwt').authorize({
  //   secret: config.secrets.session,
  //   handshake: true
  // }));

  socketio.on('connection', function (socket) {
    socket.address = socket.handshake.address !== null ?
            socket.handshake.address.address + ':' + socket.handshake.address.port :
            process.env.DOMAIN;

    socket.connectedAt = new Date();

    // Call onDisconnect.
    socket.on('disconnect', function () {
      onDisconnect(socket);
      console.info('[%s] DISCONNECTED', socket.address);
    });

    // Call onConnect.
    onConnect(socket);
    console.info('[%s] CONNECTED', socket.address);
  });
};<commit_msg>Everything seems to be back in order after the big mess...<commit_after>/**
 * Socket.io configuration
 */

'use strict';

var config = require('./environment');

// When the user disconnects.. perform this
function onDisconnect(socket) {
}

// When the user connects.. perform this
function onConnect(socket) {
  // When the client emits 'info', this listens and executes
  socket.on('info', function (data) {
    console.info('[%s] %s', socket.address, JSON.stringify(data, null, 2));
  });

  // Insert sockets below
 // require('../api/status/status.socket').register(socket);
  require('../api/subformtext/subformtext.socket').register(socket);
  require('../api/submission/submission.socket').register(socket);
}

module.exports = function (socketio) {
  // socket.io (v1.x.x) is powered by debug.
  // In order to see all the debug output, set DEBUG (in server/config/local.env.js) to including the desired scope.
  //
  // ex: DEBUG: "http*,socket.io:socket"

  // We can authenticate socket.io users and access their token through socket.handshake.decoded_token
  //
  // 1. You will need to send the token in `client/components/socket/socket.service.js`
  //
  // 2. Require authentication here:
  // socketio.use(require('socketio-jwt').authorize({
  //   secret: config.secrets.session,
  //   handshake: true
  // }));

  socketio.on('connection', function (socket) {
    socket.address = socket.handshake.address !== null ?
            socket.handshake.address.address + ':' + socket.handshake.address.port :
            process.env.DOMAIN;

    socket.connectedAt = new Date();

    // Call onDisconnect.
    socket.on('disconnect', function () {
      onDisconnect(socket);
      console.info('[%s] DISCONNECTED', socket.address);
    });

    // Call onConnect.
    onConnect(socket);
    console.info('[%s] CONNECTED', socket.address);
  });
};<|endoftext|>


<commit_before>'use strict';

var _ = require('underscore');
var fs = require('fs');

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/triviabot');
var Question = require('./question_schema');

var mkdirp = require('mkdirp');
mkdirp(process.env.HOME + '/.triviabot');

var highScores = {};
try {
    highScores = JSON.parse(fs.readFileSync(process.env.HOME + '/.triviabot/highscores.json'));
} catch(e) {
    console.log('unable to find highscores, will start without them!');
}

var hintTime = 15000;
var intermissionTime = 10000;

var states = {};

var sendHint = function(chat) {
    var gs = states[chat];
    var answer = gs.question.answers[0];

    var remainingChars = _.difference(_.range(answer.length), gs.hintChars);
    remainingChars = _.shuffle(remainingChars);

    // reveal 1/4 of remaining characters
    var numChars = Math.ceil(remainingChars.length / 4);

    for (var i = 0; i < numChars; i++) {
        gs.hintChars.push(remainingChars[i]);
    }

    var hint = answer;

    for (var i = 0; i < hint.length; i++) {
        // character is not in hintChars, obfuscate it
        if (gs.hintChars.indexOf(i) === -1) {
            hint = hint.substr(0, i) + '*' + hint.substr(i + 1);
        }
    }

    gs.numHints++;

    if (gs.numHints > 2) {
        bot.sendMessage({
            text: 'Time\'s up! The answer was: "' + answer + '"',
            chat_id: chat
        });

        printStandings(chat);
        gs.active = false;
        gs.intermissionTimeout = setTimeout(function() {
            nextRound(chat);
        }, intermissionTime);
    } else {
        bot.sendMessage({
            text: 'Hint: ' + hint,
            chat_id: chat
        });

        gs.hintTimeout = setTimeout(function() {
            sendHint(chat);
        }, hintTime);
    }
};

var printStandings = function(chat) {
    var gs = states[chat];

    if (!_.keys(gs.scores).length) {
        return;
    }

    var standings = '';

    var scores = [];

    _.each(_.keys(gs.scores), function(id) {
        scores.push(gs.scores[id]);
    });

    scores = _.sortBy(scores, 'score');
    scores.reverse();

    _.each(scores, function(score) {
        standings += score.firstName + ': ' + score.score + '\n';
    })

    bot.sendMessage({
        text: 'Current standings: \n' + standings,
        chat_id: chat
    });
};

var nextRound = function(chat) {
    var gs = states[chat];

    clearTimeout(gs.hintTimeout);
    gs.hintTimeout = null;

    gs.round++;
    gs.active = true;

    if (gs.round > 10) {
        var s = '';

        if (_.keys(gs.scores).length) {
            var standings = '';

            var scores = [];

            _.each(_.keys(gs.scores), function(id) {
                scores.push(gs.scores[id]);
            });

            scores = _.sortBy(scores, 'score');
            scores.reverse();

            if (!scores[0].score) {
                s = 'Nobody scored any points!';
            } else {
                var draw = false;
                if (scores[1] && scores[0].score === scores[1].score) {
                    s = 'It\'s a draw!\n';
                    draw = true;
                } else {
                    s = scores[0].firstName + ' wins the game!';
                }

                if (!highScores[chat]) {
                    highScores[chat] = {};
                }
                _.each(scores, function(score) {
                    if (!highScores[chat][score.id]) {
                        highScores[chat][score.id] = {
                            firstName: score.firstName,
                            lastName: score.lastName,
                            wins: 0,
                            score: 0
                        };
                    }
                    if (!draw && score.id === scores[0].id) {
                        highScores[chat][score.id].wins++;
                    }
                    highScores[chat][score.id].score += score.score;
                });

                fs.writeFileSync(process.env.HOME + '/.triviabot/highscores.json', JSON.stringify(highScores));
            }

            s += '\n\nHighscores for this group:\n\n';

            if (_.keys(highScores[chat]).length) {
                var scores = [];

                _.each(_.keys(highScores[chat]), function(id) {
                    scores.push(highScores[chat][id]);
                });

                scores = _.sortBy(scores, 'score');
                scores.reverse();

                for (var i = 0; i < 10 && i < scores.length; i++) {
                    var score = scores[i];
                    s += (i + 1) + ': ' + score.firstName + ': ' + score.score + ' (wins: ' + score.wins + ')\n';
                }
            }
        }

        bot.sendMessage({
            text: 'Game over! ' + s,
            chat_id: chat
        });

        delete states[chat];
    } else {
        Question.count(function(err, questionCnt) {
            var skipCnt = Math.floor(Math.random() * questionCnt);
            Question.findOne().skip(skipCnt).exec(function(err, question) {
                gs.question = question;
                gs.hintChars = [];

                // add spaces to hint chars
                var answer = gs.question.answers[0];
                for (var i = 0; i < answer.length; i++) {
                    if (answer[i] === ' ') {
                        gs.hintChars.push(i);
                    }
                }

                gs.numHints = 0;

                bot.sendMessage({
                    text: 'Round: ' + gs.round + '/10:\nQuestion (' + (question.category || 'no category') + '): ' + question.question,
                    chat_id: chat
                });

                gs.hintTimeout = setTimeout(function() {
                    sendHint(chat);
                }, hintTime);
            });
        });
    }
};

var stopTrivia = function(chat, from) {
    var gs = states[chat];

    if (from.id !== gs.startedBy) {
        bot.sendMessage({
            text: 'Trivia can only be stopped by whomever started it.',
            chat_id: chat
        });

        return;
    }

    clearTimeout(gs.hintTimeout);
    clearTimeout(gs.intermissionTimeout);

    bot.sendMessage({
        text: 'Trivia stopped.',
        chat_id: chat
    });

    delete states[chat];
};

var startTrivia = function(chat, from) {
    if (states[chat]) {
        bot.sendMessage({
            text: 'Trivia already started!',
            chat_id: chat
        });
        return;
    }

    states[chat] = {
        hintChars: [],
        startedBy: from.id,
        question: null,
        round: 0,
        scores: {},
        numHints: 0,
        active: false,
        hintTimeout: null,
        intermissionTimeout: null
    };

    bot.sendMessage({
        text: 'Trivia started!',
        chat_id: chat
    }, function() {
        nextRound(chat);
    });
};

var verifyAnswer = function(chat, from, text) {
    var gs = states[chat];

    if (!gs.active) {
        return;
    }

    text = text.toLowerCase();
    for (var i = 0; i < gs.question.answers.length; i++) {
        var answer = gs.question.answers[i].toLowerCase();

        if (answer === text) {
            if (!gs.scores[from.id]) {
                gs.scores[from.id] = {
                    id: from.id,
                    firstName: from.first_name,
                    lastName: from.last_name,
                    score: 0
                }
            }

            gs.scores[from.id].score++;

            bot.sendMessage({
                text: 'Points to ' + from.first_name + '! "' + answer + '" is the correct answer!',
                chat_id: chat
            }, function() {
                printStandings(chat);
            });

            gs.active = false;
            clearTimeout(gs.hintTimeout);
            gs.intermissionTimeout = setTimeout(function() {
                nextRound(chat);
            }, intermissionTime);

            break;
        }
    }
};

var reportQuestion = function(chat) {
    var gs = states[chat];

    if (!gs.active) {
        return;
    }

    Question.findById(gs.question._id, function(err, question) {
        if (err) {
            console.log('error while reporting question!');
            console.log(err);
            return;
        }

        question.rating -= 1;

        question.save(function(err) {
            if (err) {
                console.log('error while saving question report!');
                console.log(err);
                return;
            }

            bot.sendMessage({
                text: 'Reported question as bad.',
                chat_id: chat
            });
        });
    });
};

var bot;
Question.count(function(err, questionCnt) {
    if (!questionCnt) {
        console.log('no questions found in database!');
        console.log('please add some questions before launching triviabot.');
        process.exit(0);
    }

    var token = require(process.env.HOME + '/.triviabot/token.js');
    var Bot = require('node-telegram-bot');
    bot = new Bot({
        token: token
    })
    .on('message', function(msg) {
        if (msg.text) {
            if (!msg.text.indexOf('/trivia')) {
                startTrivia(msg.chat.id, msg.from);
            } else if (states[msg.chat.id]) {
                if (!msg.text.indexOf('/stoptrivia')) {
                    stopTrivia(msg.chat.id, msg.from);
                } else if (!msg.text.indexOf('/badquestion')) {
                    reportQuestion(msg.chat.id);
                } else {
                    verifyAnswer(msg.chat.id, msg.from, msg.text);
                }
            }
        }
    });

    bot.start();
});
<commit_msg>game does not have to be active for reporting<commit_after>'use strict';

var _ = require('underscore');
var fs = require('fs');

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/triviabot');
var Question = require('./question_schema');

var mkdirp = require('mkdirp');
mkdirp(process.env.HOME + '/.triviabot');

var highScores = {};
try {
    highScores = JSON.parse(fs.readFileSync(process.env.HOME + '/.triviabot/highscores.json'));
} catch(e) {
    console.log('unable to find highscores, will start without them!');
}

var hintTime = 15000;
var intermissionTime = 10000;

var states = {};

var sendHint = function(chat) {
    var gs = states[chat];
    var answer = gs.question.answers[0];

    var remainingChars = _.difference(_.range(answer.length), gs.hintChars);
    remainingChars = _.shuffle(remainingChars);

    // reveal 1/4 of remaining characters
    var numChars = Math.ceil(remainingChars.length / 4);

    for (var i = 0; i < numChars; i++) {
        gs.hintChars.push(remainingChars[i]);
    }

    var hint = answer;

    for (var i = 0; i < hint.length; i++) {
        // character is not in hintChars, obfuscate it
        if (gs.hintChars.indexOf(i) === -1) {
            hint = hint.substr(0, i) + '*' + hint.substr(i + 1);
        }
    }

    gs.numHints++;

    if (gs.numHints > 2) {
        bot.sendMessage({
            text: 'Time\'s up! The answer was: "' + answer + '"',
            chat_id: chat
        });

        printStandings(chat);
        gs.active = false;
        gs.intermissionTimeout = setTimeout(function() {
            nextRound(chat);
        }, intermissionTime);
    } else {
        bot.sendMessage({
            text: 'Hint: ' + hint,
            chat_id: chat
        });

        gs.hintTimeout = setTimeout(function() {
            sendHint(chat);
        }, hintTime);
    }
};

var printStandings = function(chat) {
    var gs = states[chat];

    if (!_.keys(gs.scores).length) {
        return;
    }

    var standings = '';

    var scores = [];

    _.each(_.keys(gs.scores), function(id) {
        scores.push(gs.scores[id]);
    });

    scores = _.sortBy(scores, 'score');
    scores.reverse();

    _.each(scores, function(score) {
        standings += score.firstName + ': ' + score.score + '\n';
    })

    bot.sendMessage({
        text: 'Current standings: \n' + standings,
        chat_id: chat
    });
};

var nextRound = function(chat) {
    var gs = states[chat];

    clearTimeout(gs.hintTimeout);
    gs.hintTimeout = null;

    gs.round++;
    gs.active = true;

    if (gs.round > 10) {
        var s = '';

        if (_.keys(gs.scores).length) {
            var standings = '';

            var scores = [];

            _.each(_.keys(gs.scores), function(id) {
                scores.push(gs.scores[id]);
            });

            scores = _.sortBy(scores, 'score');
            scores.reverse();

            if (!scores[0].score) {
                s = 'Nobody scored any points!';
            } else {
                var draw = false;
                if (scores[1] && scores[0].score === scores[1].score) {
                    s = 'It\'s a draw!\n';
                    draw = true;
                } else {
                    s = scores[0].firstName + ' wins the game!';
                }

                if (!highScores[chat]) {
                    highScores[chat] = {};
                }
                _.each(scores, function(score) {
                    if (!highScores[chat][score.id]) {
                        highScores[chat][score.id] = {
                            firstName: score.firstName,
                            lastName: score.lastName,
                            wins: 0,
                            score: 0
                        };
                    }
                    if (!draw && score.id === scores[0].id) {
                        highScores[chat][score.id].wins++;
                    }
                    highScores[chat][score.id].score += score.score;
                });

                fs.writeFileSync(process.env.HOME + '/.triviabot/highscores.json', JSON.stringify(highScores));
            }

            s += '\n\nHighscores for this group:\n\n';

            if (_.keys(highScores[chat]).length) {
                var scores = [];

                _.each(_.keys(highScores[chat]), function(id) {
                    scores.push(highScores[chat][id]);
                });

                scores = _.sortBy(scores, 'score');
                scores.reverse();

                for (var i = 0; i < 10 && i < scores.length; i++) {
                    var score = scores[i];
                    s += (i + 1) + ': ' + score.firstName + ': ' + score.score + ' (wins: ' + score.wins + ')\n';
                }
            }
        }

        bot.sendMessage({
            text: 'Game over! ' + s,
            chat_id: chat
        });

        delete states[chat];
    } else {
        Question.count(function(err, questionCnt) {
            var skipCnt = Math.floor(Math.random() * questionCnt);
            Question.findOne().skip(skipCnt).exec(function(err, question) {
                gs.question = question;
                gs.hintChars = [];

                // add spaces to hint chars
                var answer = gs.question.answers[0];
                for (var i = 0; i < answer.length; i++) {
                    if (answer[i] === ' ') {
                        gs.hintChars.push(i);
                    }
                }

                gs.numHints = 0;

                bot.sendMessage({
                    text: 'Round: ' + gs.round + '/10:\nQuestion (' + (question.category || 'no category') + '): ' + question.question,
                    chat_id: chat
                });

                gs.hintTimeout = setTimeout(function() {
                    sendHint(chat);
                }, hintTime);
            });
        });
    }
};

var stopTrivia = function(chat, from) {
    var gs = states[chat];

    if (from.id !== gs.startedBy) {
        bot.sendMessage({
            text: 'Trivia can only be stopped by whomever started it.',
            chat_id: chat
        });

        return;
    }

    clearTimeout(gs.hintTimeout);
    clearTimeout(gs.intermissionTimeout);

    bot.sendMessage({
        text: 'Trivia stopped.',
        chat_id: chat
    });

    delete states[chat];
};

var startTrivia = function(chat, from) {
    if (states[chat]) {
        bot.sendMessage({
            text: 'Trivia already started!',
            chat_id: chat
        });
        return;
    }

    states[chat] = {
        hintChars: [],
        startedBy: from.id,
        question: null,
        round: 0,
        scores: {},
        numHints: 0,
        active: false,
        hintTimeout: null,
        intermissionTimeout: null
    };

    bot.sendMessage({
        text: 'Trivia started!',
        chat_id: chat
    }, function() {
        nextRound(chat);
    });
};

var verifyAnswer = function(chat, from, text) {
    var gs = states[chat];

    if (!gs.active) {
        return;
    }

    text = text.toLowerCase();
    for (var i = 0; i < gs.question.answers.length; i++) {
        var answer = gs.question.answers[i].toLowerCase();

        if (answer === text) {
            if (!gs.scores[from.id]) {
                gs.scores[from.id] = {
                    id: from.id,
                    firstName: from.first_name,
                    lastName: from.last_name,
                    score: 0
                }
            }

            gs.scores[from.id].score++;

            bot.sendMessage({
                text: 'Points to ' + from.first_name + '! "' + answer + '" is the correct answer!',
                chat_id: chat
            }, function() {
                printStandings(chat);
            });

            gs.active = false;
            clearTimeout(gs.hintTimeout);
            gs.intermissionTimeout = setTimeout(function() {
                nextRound(chat);
            }, intermissionTime);

            break;
        }
    }
};

var reportQuestion = function(chat) {
    var gs = states[chat];

    Question.findById(gs.question._id, function(err, question) {
        if (err) {
            console.log('error while reporting question!');
            console.log(err);
            return;
        }

        question.rating -= 1;

        question.save(function(err) {
            if (err) {
                console.log('error while saving question report!');
                console.log(err);
                return;
            }

            bot.sendMessage({
                text: 'Reported question as bad.',
                chat_id: chat
            });
        });
    });
};

var bot;
Question.count(function(err, questionCnt) {
    if (!questionCnt) {
        console.log('no questions found in database!');
        console.log('please add some questions before launching triviabot.');
        process.exit(0);
    }

    var token = require(process.env.HOME + '/.triviabot/token.js');
    var Bot = require('node-telegram-bot');
    bot = new Bot({
        token: token
    })
    .on('message', function(msg) {
        if (msg.text) {
            if (!msg.text.indexOf('/trivia')) {
                startTrivia(msg.chat.id, msg.from);
            } else if (states[msg.chat.id]) {
                if (!msg.text.indexOf('/stoptrivia')) {
                    stopTrivia(msg.chat.id, msg.from);
                } else if (!msg.text.indexOf('/badquestion')) {
                    reportQuestion(msg.chat.id);
                } else {
                    verifyAnswer(msg.chat.id, msg.from, msg.text);
                }
            }
        }
    });

    bot.start();
});
<|endoftext|>


<commit_before>/**
 * @Author: liushaobo2005@163.com
 * @Date: 2017.3.20 下午 3:11
 * @Desc: 公共组件 - router
 * @Name: router.js
 * @LifeCycle：https://github.com/kinshasa/react-native-qatest
 */
import scenes from '../../src/scenes';
import * as LauncherController from "../../src/containers/LauncherController";

module.exports = function (state, action) {
    state = state || {
            type: 'USER_INITIAL',
            data: {
                list:[],
                home:[],
                test:[]
            },
        };
    //console.log(`#router state:`,state);
    console.log(`#router action:`,action);
    switch (action.type) {

        case 'ROUTER_SCENES_LIST': {
            state.data.list = LauncherController.getDataSource();
            return {
                ...state,
                ...action,
                data,
            }
        }
        case 'ROUTER_HOME_SCENES_LIST': {
            state.data.home = LauncherController.getDataSource('Home');
            return {
                ...state,
                ...action,
            }
        }
        case 'ROUTER_QATEST_SCENES_LIST': {
            state.data.test = LauncherController.getDataSource('QATest');
            return {
                ...state,
                ...action,
            }
        }
    }

    return {
        ...state
    }
};
<commit_msg>modify files @liushaobo2005@163.com<commit_after>/**
 * @Author: liushaobo2005@163.com
 * @Date: 2017.3.20 下午 3:11
 * @Desc: 公共组件 - router
 * @Name: router.js
 * @LifeCycle：https://github.com/kinshasa/react-native-qatest
 */
import * as LauncherController from "../../src/containers/LauncherController";

module.exports = function (state, action) {
    state = state || {
            type: 'USER_INITIAL',
            data: {
                list:[],
                home:[],
                test:[]
            },
        };
    //console.log(`#router state:`,state);
    console.log(`#router action:`,action);
    switch (action.type) {

        case 'ROUTER_SCENES_LIST': {
            state.data.list = LauncherController.getDataSource();
            return {
                ...state,
                ...action,
                data,
            }
        }
        case 'ROUTER_HOME_SCENES_LIST': {
            state.data.home = LauncherController.getDataSource('Home');
            return {
                ...state,
                ...action,
            }
        }
        case 'ROUTER_QATEST_SCENES_LIST': {
            state.data.test = LauncherController.getDataSource('QATest');
            return {
                ...state,
                ...action,
            }
        }
    }

    return {
        ...state
    }
};
<|endoftext|>