Discord.js Breaking down Ban Command for Command Handler issues - arguments

I have a rather large index.js so iv been busy stripping it out into individual command files, i have successfully exported all my code into separate commands, all but ban. So far the ban code works as intended, but if a 18 digit user ID is entered, and they have left the server it should check and log it in a .json file but currently its not getting past if (isNaN(args[1])) it just plain wont accept anything, number and or letters all result in "You need to enter a vlaid #Member or UserID #" This is very frustrating as it took me hours to get working within my index.js
run: async (bot, message, args) => {
if (!message.member.hasPermission(["BAN_MEMBERS", "ADMINISTRATOR"])) return message.channel.send("You do not have permission to perform this command!")
const user1 = message.mentions.users.first();
var member = message.mentions.members.first()
if (member) {
const member = message.mentions.members.first()
let reason = args.slice(2).join(' '); // arguments should already be defined
var user = message.mentions.users.first();
member.ban({ reason: `${args.slice(2).join(' ')}` }).then(() => {
let uEmbed = new RichEmbed()
.setTitle('**' + `Sucessfully Banned ${user1.tag}!` + '**')
.setThumbnail('https://i.gyazo.com/8988806671312f358509cf0fd69341006.jpg')
.setImage('https://media3.giphy.com/media/H99r2HtnYs492/giphy.gif?cid=ecf05e47db8ad81dd0dbb6b132bb551add0955f9b92ba021&rid=giphy.gif')
.setColor(0x320b52)
.setTimestamp()
.setFooter('Requested by ' + message.author.tag, 'https://i.gyazo.com/8988806671312f358509cf0fd69341006.jpg')
message.channel.send(uEmbed);
}).catch(err => {
message.channel.send('I was unable to kick the member');
console.log(err);
});
} else {
let user = message.mentions.users.first(),
userID = user ? user.id : args[1]
if (isNaN(args[1])) return message.channel.send("You need to enter a vlaid #Member or UserID #");
if (args[1].length <= 17 || args[1].length >= 19) return message.channel.send("UserID # must be 18 Digits");
if (userID) {
let bannedIDs = require('./bannedIDs.json').ids || []
if (!bannedIDs.includes(userID)) bannedIDs.push(userID)
fs.writeFileSync('./bannedIDs.json', JSON.stringify({ ids: bannedIDs }))
let reason = args.slice(2).join(' ');
let uEmbed = new RichEmbed()
.setTitle('**' + `UserID #${args[1]}\n Will be Banned on Return!` + '**')
.setThumbnail('https://i.gyazo.com/8988806671312f358509cf0fd69341006.jpg')
.setImage('https://i.imgur.com/6Sh8csf.gif')
.setColor(0x320b52)
.setTimestamp()
.setFooter('Requested by ' + message.author.tag, 'https://i.gyazo.com/8988806671312f358509cf0fd69341006.jpg')
message.channel.send(uEmbed);
} else {
message.channel.send('Error')
}
}
}
}

Firstly, if (args[1].length <= 17 || args[1].length >= 19 can be reduced to if(args[1].length !== 18), I saw your other post and it suggests you got passed this bug, is this correct?

Related

Epson js SDK unable to use multiple printers

Intro
We're developing this javascript based web application that is supposed to print receipts using the epson javascript sdk.
Right now we've got this poc where multiple printers can be added to the app and where receipts can be printed per individual printer.
The problem is that the receipt will ONLY be printer from the last added printer.
Further investigating tells us that the sdk just uses the last added (connected) printer. This can be seen at the following images.
In the first image there are 2 printers setup. Notice the different ip addresses.
In the second image we log what EpsonPrinter instance is being used while printing. Notice the ip address is clearly the first printer.
In the third image we trace the network. Notice the ip address that is actually used (ignore the error).
We created our own EpsonPrinter class that can be found here or here below.
EpsonPrinter
export default class EpsonPrinter {
name = null
ipAddress = null
port = null
deviceId = null
crypto = false
buffer = false
eposdev = null
printer = null
intervalID = null
restry = 0
constructor (props) {
const {
name = 'Epson printer',
ipAddress,
port = 8008,
deviceId = 'local_printer',
crypto = false,
buffer = false
} = props
this.name = name
this.ipAddress = ipAddress
this.port = port
this.deviceId = deviceId
this.crypto = crypto
this.buffer = buffer
this.eposdev = new window.epson.ePOSDevice()
this.eposdev.onreconnecting = this.onReconnecting
this.eposdev.onreconnect = this.onReconnect
this.eposdev.ondisconnect = this.onDisconnect
this.connect()
}
onReconnecting = () => {
this.consoleLog('reconnecting')
}
onReconnect = () => {
this.consoleLog('reconnect')
}
onDisconnect = () => {
this.consoleLog('disconnect')
if (this.intervalID === null ){
this.intervalID = setInterval(() => this.reconnect(), 5000)
}
}
connect = () => {
this.consoleLog('connect')
this.eposdev.ondisconnect = null
this.eposdev.disconnect()
this.eposdev.connect(this.ipAddress, this.port, this.connectCallback)
}
reconnect = () => {
this.consoleLog('(Re)connect')
this.eposdev.connect(this.ipAddress, this.port, this.connectCallback)
}
connectCallback = (data) => {
clearInterval(this.intervalID)
this.intervalID = null
this.eposdev.ondisconnect = this.onDisconnect
if (data === 'OK' || data === 'SSL_CONNECT_OK') {
this.createDevice()
} else {
setTimeout(() => this.reconnect(), 5000)
}
}
createDevice = () => {
console.log('create device, try: ' + this.restry)
const options = {
crypto: this.crypto,
buffer: this.buffer
}
this.eposdev.createDevice(this.deviceId, this.eposdev.DEVICE_TYPE_PRINTER, options, this.createDeviceCallback)
}
createDeviceCallback = (deviceObj, code) => {
this.restry++
if (code === 'OK') {
this.printer = deviceObj
this.printer.onreceive = this.onReceive
} else if (code === 'DEVICE_IN_USE') {
if (this.restry < 5) {
setTimeout(() => this.createDevice(), 3000)
}
}
}
onReceive = (response) => {
this.consoleLog('on receive: ', response)
let message = `Print ${this.name} ${response.success ? 'success' : 'failute'}\n`
message += `Code: ${response.code}\n`
message += `Status: \n`
if (response.status === this.printer.ASB_NO_RESPONSE) { message += ' No printer response\n' }
if (response.status === this.printer.ASB_PRINT_SUCCESS) { message += ' Print complete\n' }
if (response.status === this.printer.ASB_DRAWER_KICK) { message += ' Status of the drawer kick number 3 connector pin = "H"\n' }
if (response.status === this.printer.ASB_OFF_LINE) { message += ' Offline status\n' }
if (response.status === this.printer.ASB_COVER_OPEN) { message += ' Cover is open\n' }
if (response.status === this.printer.ASB_PAPER_FEED) { message += ' Paper feed switch is feeding paper\n' }
if (response.status === this.printer.ASB_WAIT_ON_LINE) { message += ' Waiting for online recovery\n' }
if (response.status === this.printer.ASB_PANEL_SWITCH) { message += ' Panel switch is ON\n' }
if (response.status === this.printer.ASB_MECHANICAL_ERR) { message += ' Mechanical error generated\n' }
if (response.status === this.printer.ASB_AUTOCUTTER_ERR) { message += ' Auto cutter error generated\n' }
if (response.status === this.printer.ASB_UNRECOVER_ERR) { message += ' Unrecoverable error generated\n' }
if (response.status === this.printer.ASB_AUTORECOVER_ERR) { message += ' Auto recovery error generated\n' }
if (response.status === this.printer.ASB_RECEIPT_NEAR_END) { message += ' No paper in the roll paper near end detector\n' }
if (response.status === this.printer.ASB_RECEIPT_END) { message += ' No paper in the roll paper end detector\n' }
if (response.status === this.printer.ASB_SPOOLER_IS_STOPPED) { message += ' Stop the spooler\n' }
if (!response.success) {
alert(message)
// TODO: error message?
} else {
// TODO: success -> remove from queue
}
}
printReceipt = () => {
this.consoleLog(`Print receipt, `, this)
try {
if (!this.printer) {
throw `No printer created for ${this.name}`
}
this.printer.addPulse(this.printer.DRAWER_1, this.printer.PULSE_100)
this.printer.addText(`Printed from: ${this.name}\n`)
this.printer.send()
} catch (err) {
let message = `Print ${this.name} failure\n`
message += `Error: ${err}`
alert(message)
}
}
consoleLog = (...rest) => {
console.log(`${this.name}: `, ...rest)
}
}
Poc
The full working poc can be found here.
Epson javascript sdk
2.9.0
Does anyone have any experience with the epson sdk? It it supposed to be able to support multiple connections on the same time? Please let use know.
For the ones looking for a way to handle multiple printers using this SDK. We came up with the following work around:
We created a separated 'printer app' that is responsible for handling ONE printer connection and hosted it online. We then 'load' this printer app into our app that needs multiple connections using Iframes. Communication between app and printer app is done by means of window.PostMessage API to, for example, initialise the printer with the correct printer connection and providing data that has to be printed.
It takes some effort but was the most stable solution we could come up with handling multiple connections.
If anyone else comes up with a better approach please let me know!
You can checkout our printer app here for inspiration (inspect the app because it doesn't show much visiting it just like that).
For use your class EpsonPrinter, i add also myPrinters class after your class:
class myPrinters {
printers = null;
cantidad = 0;
constructor() {
console.log("Creo la coleccion de printers");
this.printers = [];
}
inicializarConeccionImpresora(idImpresora, ip, puerto, _deviceId) {
let ipAddress = ip;
let port = puerto;
let deviceId = _deviceId;
console.log("Agrego una impresora");
let myPrinter = new EpsonPrinter(ipAddress);
myPrinter.port = port;
myPrinter.deviceId = deviceId;
myPrinter.id = idImpresora;
console.log('Id impresora antes de connect es: ' + idImpresora);
myPrinter.connect();
this.printers[this.cantidad] = myPrinter;
this.cantidad ++;
}
imprimirPruebaJS(idImpresora) {
let printer = null;
let printerTemp = null
for(var i = 0; i < this.printers.length; i++) {
printerTemp = this.printers[i];
if (printerTemp.id == idImpresora) {
printer = printerTemp.printer;
}
}
if (printer == null) {
console.log("La impresora no esta iniciada en clase myPrinters");
return;
}
printer.addText('Hola mundo texto normal\n');
printer.addFeed();
printer.addCut(printer.CUT_FEED);
}
}
call myPrinters class in this way :
myEpsonPrinters = new myPrinters();
myEpsonPrinters.inicializarConeccionImpresora(1, '192.168.0.51', 8008, 'local_printer');
myEpsonPrinters.inicializarConeccionImpresora(2, '192.168.0.52', 8008, 'local_printer');
myEpsonPrinters.imprimirPruebaJS(1)
or
myEpsonPrinters.imprimirPruebaJS(2)
Test it and tell me.
Juan
Just create multiple objects for printing simple as this
this.eposdev = [];
let printersCnt = 3;
let self = this;
for(let i=1 ; i <= printersCnt ; i++){
this.eposdev[i] = new window.epson.ePOSDevice()
this.eposdev[i].onreconnecting = function (){
this.consoleLog('reConnecting')
}
this.eposdev[i].onreconnect = function (){
this.consoleLog('onReconnect')
}
this.eposdev[i].ondisconnect = function (){
this.consoleLog('onDisconnect')
}
}
function connect(printerKey) => {
this.consoleLog('connect')
this.eposdev.ondisconnect = null
this.eposdev.disconnect()
this.eposdev.connect(self.ipAddress[printerKey], self.port[printerKey], function(){
clearInterval(self.intervalID)
self.intervalID = null
self.eposdev[i].ondisconnect = self.ondisconnect
if (data === 'OK' || data === 'SSL_CONNECT_OK') {
console.log('create device, try: ' + self.restry)
const options = {
crypto: self.crypto,
buffer: self.buffer
}
self.eposdev[printerKey].createDevice(self.deviceId, self.eposdev[printerKey].DEVICE_TYPE_PRINTER, options, function(deviceObj, code){
this.restry++
if (code === 'OK') {
self.printer[printerKey] = deviceObj
self.printer.onreceive = function(){
console.log("onreceive");
}
} else if (code === 'DEVICE_IN_USE') {
if (self.restry < 5) {
setTimeout(() => self.createDevice(printerKey), 3000)
}
})
}
} else {
setTimeout(() => self.reconnect(printerKey), 5000)
}
})
}
Epson says that with version 2.12.0 you can add more than one printer.

502 on AWS Cognito ListUsers with PaginationToken

Using AWSMibileHub to set up my backend. Working on an admin page that shows all the users from AWS Cognito.
I’m using ListUsers to get user list and noticed 502 error on the request with a PagenationToken and it seems to be happening randomly.
In CloudWatch shows this error below.
InvalidParameterException: 1 validation error detected: Value 'CAISlAIIARLtAQgDEugBADSdLB5dZXQEaQjoL8y8CE1RGGT3PZ4FpCqxFwJkNuhIeyJAbiI6IlBhZ2luYXRpb25Db250aW51YXRpb25EVE8iLCJuZXh0S2V5IjoiQUFBQUFBQUFCZHM4QVFFQmJBZmU5OFgzUnJTM1BHcnYzVmRiVWNScVdIck82VXFZaTdlZklleVRCSEZsYm1ZN01UVTRPV1k0TVRNdE9UYzVZUzAwWTJKakxUazROekl0TkdRek9UYzROMlpoWmpVM093PT0iLCJwcmV2aW91c1JlcXVlc3RUaW1lIjoxNTQzMDkzODIyNDk5fRogNk7FThSKBOuwQGi DoZBnmNN85UY5oFiSAbHWfOzreY=' at 'paginationToken' failed to satisfy constraint: Member must satisfy regular expression pattern: [\S]+
Does anybody have the same issue or any idea how to fix this issue?
Store the pagination Token in a variable and then add this .replace(/\ /g,'+') to the variable to change the space back to +.
e.g:
const pagination = 'TOKEN FROM COGNITO'.replace(/\ /g,'+')
The pagination_token consists of non alphanumeric characters, so its better to encrypt and decrypt when required.
Encrypt?decrypt utility file
const crypto = require("crypto");
const algorithm = "aes-256-ctr";
const password = "sassed";
class Util {
static encrypt_aes(text) {
let cipher = crypto.createCipher(algorithm, password);
let crypted = cipher.update(text, "utf8", "hex");
crypted += cipher.final("hex");
return crypted;
}
static decrypt_aes(text) {
let decipher = crypto.createDecipher(algorithm, password);
let dec = decipher.update(text, "hex", "utf8");
dec += decipher.final("utf8");
return dec;
}
}
module.exports = Util;
PaginationToken encryption/decription
const Util = require("./utils");
class Users {
static async getUsersAttributes(params) {
let listparams = {
UserPoolId: userPoolID /* required */,
Limit: params.limit || 10,
};
if (params.paginationToken) {
listparams.PaginationToken = Util.decrypt_aes(params.paginationToken);
}
let response = await cognitoISPClient.listUsers(listparams).promise();
response.PaginationToken = Util.encrypt_aes(response.PaginationToken);
return response;
}
}

NetSuite / Suitescript - Why does this Validate Field script enter an infinite loop?

My script is entering into an infinite loop and I have no idea why. I am running this on validate field and I am preventing a change to the field if another vendor bill exists with the same reference number, forcing the user to change the "Reference Number" to be unique. Here is my code:
function validateField(type, name) {
if (uniqueReferenceNum(type, name) === false) {
return false;
}
return true;
}
function uniqueReferenceNum(type, name) {
if (name !== 'tranid') {
return true;
}
var tranID = nlapiGetFieldValue('tranid');
var vendor = nlapiGetFieldValue('entity');
var vendorName = nlapiGetFieldText('entity');
var filters = new Array();
var columns = new Array();
filters[0] = new nlobjSearchFilter('entity', null, 'is', vendor);
filters[1] = new nlobjSearchFilter('tranid', null, 'is', tranID);
filters[2] = new nlobjSearchFilter('mainline', null, 'is', 'T');
columns[0] = new nlobjSearchColumn('internalid');
results = nlapiSearchRecord('vendorbill', null, filters, columns);
if (!results) {
return true;
}
alert("There is already a vendor bill with reference # " + tranID + " for " + vendorName + ". Please verify and change the reference number before continuing.");
return false;
}
For those still facing this issue, you can set the field in question - in this case, Reference Number - to a 'falsy' value such as an empty string. Only return false after checking that the field contains a 'truthy' value. Then display the alert or dialog to the user. This should break the validation loop.

Parse Cloud Code - How to query the User Class

I'm trying to query the Parse User Class but I'm not getting any results. The User class has a column labeled "phone", and I'm passing an array of dictionaries where each dictionary has a key "phone_numbers" that corresponds to an array of phone numbers. I'm trying to determine if a User in my table has one of those phone numbers. I'm not getting any errors running the code, but there does exist a user in my table with a matching phone number. What am I doing wrong?
Parse.Cloud.define("hasApp", function(request, response) {
var dict = request.params.contacts;
var num = 0;
var found = 0;
var error = 0;
var phoneNumbers = "";
for (var i = 0; i < dict.length; i++){
var result = dict[i].phone_numbers;
num += result.length;
for (var j = 0; j < result.length; j++){
phoneNumbers += result[j] + ", ";
var query = new Parse.Query(Parse.User);
query.equalTo("phone", result[j]);
query.find({
success: function(results) {
found = 1;
},
error: function() {
error = 1;
}
});
}
}
response.success("hasApp " + dict.length + " numbers " + num + " found " + found + " error " + error + " phoneNumbers " + phoneNumbers);
});
My response from calling this is
hasApp 337 numbers 352 found 0 error 0 phoneNumbers "list of phone numbers"
where some of those phone numbers appear in my User class. As far as I can tell I'm not getting any errors but I'm also not successfully querying the User table
UPDATE
After moving
response.success("hasApp " + dict.length + " numbers " + num + " found " + found + " error " + error + " phoneNumbers " + phoneNumbers);
to the body of the success block, I get the following error because I'm only allowed to call response.success once per cloud function.
Error Domain=Parse Code=141 "The operation couldn’t be completed. (Parse error 141.)"
UserInfo=0x14d035e0 {code=141, error=Error: Can't call success/error multiple times
at Object.success (<anonymous>:99:13)
at query.find.success (main.js:44:12)
at Parse.js:2:5786
at r (Parse.js:2:4981)
at Parse.js:2:4531
at Array.forEach (native)
at Object.w.each.w.forEach [as _arrayEach] (Parse.js:1:666)
at n.extend.resolve (Parse.js:2:4482)
at r (Parse.js:2:5117)
at Parse.js:2:4531}
Does this mean that I'm only able to verify one phone number at a time? So I can't pass an array of phone numbers and get the PFUser objects corresponding to those phone numbers (if they exist)?
I understand that my internal query to Parse.User is happening synchronously with my "hasApp" call, so is there a way to query Parse.User asynchronously? That way I can respond back to the client after checking all the phone numbers?
You can use Parse.Promise to solve logic where you need to iterate through O(n) number of database queries in one asynchronous Cloud Code definition:
var _ = require("underscore"),
isEmpty = function (o) { // standard function to check for empty objects
if (o == null) return true;
if (o.length > 0) return false;
if (o.length === 0) return true;
for (var p in o) {
if (hasOwnProperty.call(o, p)) return false;
}
return true;
};
Parse.Cloud.define("hasApp", function (request, response) {
var dict = request.params.contacts,
users = [];
var promise = Parse.Promise.as();
_.each(dict, function (obj) {
_.each(obj.phone_numbers, function (num) {
promise = promise.then(function () {
var promiseQuery = new Parse.Query(Parse.User);
promiseQuery.equalTo("phone", parseInt(num));
return promiseQuery.find({
success: function (result) {
if (isEmpty(result)) // don't save empty results e.g., "[]"
return;
users.push(result); // save results to a model to prevent losing it in scope
}
});
});
});
});
return promise.then(function () {
response.success("Found user(s): " + JSON.stringify(users));
});
});
Note a few things about this block:
You can append functionality iteratively to a Parse.Promise.
You can loose scope of database results in your iteration. Use a local array model to save your query results to. Although, I presume there is a better way to achieve the same functionality without the use of a user model, someone else can quote me on that.
Pay close attention to the way Parse handles data. For example, if you are storing your phone numbers as numbers, you have to make sure you use parseInt() when querying for it.
Be aware that you must attach your response.success() function to your promise to assure it is resolved after your iterations have run. From this block, your response from Parse will look similar to an array of User objects. You can decide on the many different ways you can save the data model depending on what you need it for.
As a final note, this block doesn't account for any validation or error handling that should be accounted for otherwise.
The problem seems to be that your response.success call is happening before the query can even happen. While you have response.success calls in your query success block, they are never called because you return success before the query is executed.
Try commenting out the line:
response.success("hasApp " + dict.length + " numbers " + num + " found " + found + " error " + error + " phoneNumbers " + phoneNumbers);
This should let the code go to your query, and maybe move it into the success block of your query.
Let me know if this works.
You're now calling response.success in a loop now. You should only call response.success/response.error once per cloud function.
It would help if you can show the original code with no commented out lines (to show your original intention) and the new code with no commented out lines as two separate code samples.
Querying a Parse.User is fairly easy and well explained in the documentation, here is an example taken from it
var query = new Parse.Query(Parse.User);
query.equalTo("gender", "female"); // find all the women
query.find({
success: function(women) {
// Do stuff
}
});
For your case it will be something like this:
Parse.Cloud.define("getAllFemales", function(request, response) {
var query = new Parse.Query(Parse.User);
query.equalTo("gender", "female"); // find all the women
query.find({
success: function(women) {
// Do stuff
}
});
});
Hope it helps, as always more info on the Documentation

Inconsistent data corruption in a store loaded through a proxy reader

We're experiencing inconsistent data corruption in a store loaded through a proxy reader.
It's browser dependant.
Works fine in Chrome and Safari on the desktop all the time.
On our two testing iPhones it intermittently breaks depending on the data the store has loaded, larger data volume seems to cause more breaks. We can't see any errors or patterns in the JSON data where it breaks.
Symptoms:
data loads, but some of the data belonging to the last few items is missing
a read listener attached to the store doesn't fire when this data loss occurs, it does fire on the desktop browser where we experience not data loss
The piece of data that always seems to be lost is the start_time.
We've been trying to debug this one for a while now and are really stumped.
Thank you for any ideas you might have as to why this is occurring.
Our regModel
Ext.regModel('Booking', {
fields: ['id', 'start', 'end', 'title', 'service', 'service_id', 'client_note', 'stylist_note', 'utc_start','day_date', 'start_time', 'end_time', "home_ph", "mobile_ph", 'work_ph', 'work_ext', 'email', 'utc_end']
});
Our store
var store = new Ext.data.JsonStore({
model : 'Booking',
sorters: 'utc_start',
autoLoad: false,
proxy: {
type: 'ajax',
url: '../includes/get_appointments.php',
extraParams: {
req_start: '1295251200',
req_end: '1295856000'
},
reader: {
type: 'json',
root: 'events'
}
},
listeners: {
load:function(store, records, success) {
bookings.setLoading(false);
// check to see length of records, start i from there
for (var i = 0; i < records.length; i++){
utc_start = records[i].get('utc_start');
utc_end = records[i].get('utc_end');
// create day of week
// y,m,d
// time
var this_start_date = new Date((utc_start * 1000));
var this_end_date = new Date((utc_end * 1000));
var day_of_week = days_of_week[this_start_date.getDay()];
var date_of_month = this_start_date.getDate();
var month_of_year = month_names[this_start_date.getMonth()];
var full_year = this_start_date.getFullYear();
var start_military_hours = this_start_date.getHours();
var this_start_minutes = this_start_date.getMinutes();
var end_military_hours = this_end_date.getHours();
var this_end_minutes = this_end_date.getMinutes();
if(this_start_minutes == "0")
{
this_start_minutes = "00";
}
if(parseInt(start_military_hours) < 12)
{
var start_time = start_military_hours + ":" + this_start_minutes + " AM";
}
else if(parseInt(start_military_hours) == 12)
{
var start_time = start_military_hours + ":" + this_start_minutes + " PM";
}
else
{
var start_time = (parseInt(start_military_hours) - 12) + ":" + this_start_minutes + " PM";
}
if(this_end_minutes == "0")
{
this_end_minutes = "00";
}
if(parseInt(end_military_hours) < 12)
{
var end_time = end_military_hours + ":" + this_end_minutes + " AM";
}
else if(parseInt(end_military_hours) == 12)
{
var end_time = end_military_hours + ":" + this_end_minutes + " PM";
}
else
{
var end_time = (parseInt(end_military_hours) - 12) + ":" + this_end_minutes + " PM";
}
var day_date = day_of_week + ", " + full_year + " " + month_of_year + " " + date_of_month;
if(records[i].get('service_id') == 0)
{
records[i].set('title', 'Booked off');
records[i].set('service', '');
}
records[i].set('day_date', day_date);
records[i].set('start_time', start_time);
records[i].set('end_time', end_time);
}
if(store.proxy.reader.rawData.next_page_num == undefined)
{
store.start = store.proxy.reader.rawData.prev_page_num;
}
else
{
store.currentPage = store.proxy.reader.rawData.next_page_num;
}
}, read:function(store,records,success){
Ext.Msg.alert('data read');
}
},
getGroupString : function(record) {
return record.get('day_date'); // optional char from array removed
}
});
Our JSON
{"events":[{"id":"3739","start":"2011-01-18T10:00:00-08:00","end":"2011-01-18T11:45:00-08:00","title":"Jen Cannor","service":"Haircut & Highlights","service_id":"67","client_note":"","stylist_note":"Looking forward to seeing Jen when she comes in next.","utc_start":"1295373600","email":"jen.c#cannorfarms.net","home_ph":"232-433-2222","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295379900"},{"id":"3740","start":"2011-01-18T12:00:00-08:00","end":"2011-01-18T13:30:00-08:00","title":"Michelle Steves","service":"Root Colour","service_id":"69","client_note":"","stylist_note":"","utc_start":"1295380800","email":"michelle5b64#telus.net","home_ph":"604-555-5555","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295386200"},{"id":"3741","start":"2011-01-18T13:30:00-08:00","end":"2011-01-18T14:00:00-08:00","title":"Amanda Brenner","service":"Wash & blow dry","service_id":"70","client_note":"","stylist_note":"","utc_start":"1295386200","email":"amandab#coastfitness.com","home_ph":"555-235-2366","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295388000"},{"id":"3742","start":"2011-01-18T14:00:00-08:00","end":"2011-01-18T15:45:00-08:00","title":"Janice Potters","service":"Haircut & Colour","service_id":"66","client_note":"","stylist_note":"","utc_start":"1295388000","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295394300"},{"id":"3743","start":"2011-01-18T15:45:00-08:00","end":"2011-01-18T16:45:00-08:00","title":"Angus Middleton","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1295394300","email":"angusman#hotmaile.com","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295397900"},{"id":"3025","start":"2011-01-19T08:00:00-08:00","end":"2011-01-19T09:45:00-08:00","title":"Jen Cannor","service":"Haircut & Highlights","service_id":"67","client_note":"","stylist_note":"","utc_start":"1295452800","email":"jen.c#cannorfarms.net","home_ph":"232-433-2222","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295459100"},{"id":"3026","start":"2011-01-19T10:00:00-08:00","end":"2011-01-19T11:45:00-08:00","title":"Karen Walker","service":"Haircut & Colour","service_id":"66","client_note":"","stylist_note":"","utc_start":"1295460000","email":"karenwalker#officesurplusdirect.net","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295466300"},{"id":"3027","start":"2011-01-19T11:45:00-08:00","end":"2011-01-19T12:45:00-08:00","title":"Amanda Brenner","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1295466300","email":"amandab#coastfitness.com","home_ph":"555-235-2366","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295469900"},{"id":"3028","start":"2011-01-19T13:00:00-08:00","end":"2011-01-19T14:30:00-08:00","title":"Mary Thacker","service":"Root Colour","service_id":"69","client_note":"","stylist_note":"","utc_start":"1295470800","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295476200"},{"id":"3029","start":"2011-01-19T14:30:00-08:00","end":"2011-01-19T15:00:00-08:00","title":"Malcolm Anderson","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1295476200","email":"malcolm#testserveraddy.com","home_ph":"240-444-4444","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1295478000"},{"id":"4856","start":"2011-03-09T09:00:00-08:00","end":"2011-03-09T10:00:00-08:00","title":"Simon Chalk","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299690000","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299693600"},{"id":"4858","start":"2011-03-09T10:00:00-08:00","end":"2011-03-09T10:15:00-08:00","title":"Brian Lytton","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299693600","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299694500"},{"id":"4859","start":"2011-03-09T10:15:00-08:00","end":"2011-03-09T10:30:00-08:00","title":"Brad Wicker","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299694500","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299695400"},{"id":"4860","start":"2011-03-09T10:30:00-08:00","end":"2011-03-09T10:45:00-08:00","title":"Brad Wicker","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299695400","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299696300"},{"id":"4861","start":"2011-03-09T10:45:00-08:00","end":"2011-03-09T11:00:00-08:00","title":"Brian Lytton","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299696300","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299697200"},{"id":"4862","start":"2011-03-09T11:00:00-08:00","end":"2011-03-09T11:15:00-08:00","title":"Brian Lytton","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299697200","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299698100"},{"id":"4863","start":"2011-03-09T11:15:00-08:00","end":"2011-03-09T11:30:00-08:00","title":"Simon Chalk","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299698100","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299699000"},{"id":"4864","start":"2011-03-09T11:30:00-08:00","end":"2011-03-09T11:45:00-08:00","title":"Chester Welling","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299699000","email":"chester#eastern.pharma.net","home_ph":"604-555-5555","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299699900"},{"id":"4865","start":"2011-03-09T11:45:00-08:00","end":"2011-03-09T12:00:00-08:00","title":"Brad Wicker","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299699900","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299700800"},{"id":"4866","start":"2011-03-09T12:00:00-08:00","end":"2011-03-09T13:00:00-08:00","title":"Janice Potters","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1299700800","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299704400"},{"id":"4867","start":"2011-03-09T13:00:00-08:00","end":"2011-03-09T13:15:00-08:00","title":"Jacqui Chan","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1299704400","email":"jc#rebelfrontier.net","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299705300"},{"id":"4876","start":"2011-03-09T13:15:00-08:00","end":"2011-03-09T13:30:00-08:00","title":"Mary Thacker","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1299705300","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299706200"},{"id":"4868","start":"2011-03-10T10:15:00-08:00","end":"2011-03-10T11:15:00-08:00","title":"Trisha Roberts","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1299780900","email":"trb483408#gmail.com","home_ph":"604-555-5555","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299784500"},{"id":"4870","start":"2011-03-10T11:30:00-08:00","end":"2011-03-10T12:30:00-08:00","title":"Jenson Bryant","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1299785400","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299789000"},{"id":"4872","start":"2011-03-10T12:45:00-08:00","end":"2011-03-10T13:00:00-08:00","title":"Jenson Bryant","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1299789900","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299790800"},{"id":"4873","start":"2011-03-10T13:00:00-08:00","end":"2011-03-10T13:15:00-08:00","title":"Jenson Bryant","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1299790800","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299791700"},{"id":"4874","start":"2011-03-10T13:15:00-08:00","end":"2011-03-10T14:15:00-08:00","title":"Simon Chalk","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299791700","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299795300"},{"id":"4875","start":"2011-03-11T10:15:00-08:00","end":"2011-03-11T11:15:00-08:00","title":"Karen Walker","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1299867300","email":"karenwalker#officesurplusdirect.net","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299870900"},{"id":"4877","start":"2011-03-11T12:00:00-08:00","end":"2011-03-11T12:15:00-08:00","title":"Amanda Brenner","service":"Women's Haircut","service_id":"65","client_note":"","stylist_note":"","utc_start":"1299873600","email":"amandab#coastfitness.com","home_ph":"555-235-2366","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299874500"},{"id":"4878","start":"2011-03-11T12:30:00-08:00","end":"2011-03-11T13:30:00-08:00","title":"Arnold Fieldman","service":"Men's haircut","service_id":"61","client_note":"","stylist_note":"","utc_start":"1299875400","email":"","home_ph":"","mobile_ph":"","work_ph":"","work_ext":"","utc_end":"1299879000"}], "next_page_num":"7"}
This is not a Sencha Touch specific issue: there are limits on the size of Ajax response that mobile safari can handle: see Too large an AJAX response for mobile safari?
Update: apparently this is not a mobile safari problem, this is a cellular network problem. Some networks will helpfully "paginate" the Ajax call -- thinking it's a regular web page download. Can you check to see if this is still the case on a wifi network?
After much head banging it appears that Sencha Touch stores only work well with up to approximately 10,000 characters I'm guess 8192 + the json delimiters?
After that it seems to start losing part of the data for us.
Can anyone else corroborate this?

Resources