if(!db['mention'].length)
{
message.channel.send("Komenda wymaga wzmianki gracza");
}
else if(db['mention'].includes("#"))
{
db['v1'] = message.mentions.members.first().voice.channelId;
if(db[`value`]<=10 && db[`value`]>=1)
{
ping()
}
else
{
message.channel.send(`Wpisz ilość od 1 do 10`).then(() => {
message.channel.awaitMessages({
filter: (m) => m.author.id === message.author.id,
max: 1,
time: 6000,
errors: ['time'],
}).then(message => {
db['value'] = message.first();
if (db['value']<=10 && db['value']>=1)
{
ping()
}
else
{
message.channel.send(`Błędna wartość`)
}
})
.catch(collected => {
message.channel.send('Timeout')
})
})
}
}
this part in code is skipped
.then(message => {
db['value'] = message.first();
if (db['value']<=10 && db['value']>=1)
{
ping()
}
and bot only send Timeout. I remember that this was working one month ago. I was looking for solution in internet but i founded nothing.
Did somebody know what im doing wrong?
Not sure how it will interact with code not showing (ping() function and any db code) but the rest should work
const filter = (m) => m.author.id === message.author.id
message.channel.send(`Wpisz ilość od 1 do 10`).then(() => {
message.channel.awaitMessages({
filter,
max: 1,
time: 6000,
errors: ['time'],
}).catch(() => {
throw new Error('Timed Out')
}).then(message => {
db['value'] = message.first();
setTimeout(() => {
message.delete()
}, 10000)
if (db['value'] <= 10 && db['value'] >= 1) {
ping()
} else {
message.channel.send(`Błędna wartość`)
}
}).catch(error => {
switch (error.message) {
case 'Timed Out':
message.channel.send('Timeout');
break
})
})
Related
In order to implement in app purchase using expo am using https://docs.expo.io/versions/latest/sdk/in-app-purchases.
I implemented as per the document and i tested it in sandbox mode.what i have did is:
1)Set up in app purchase in appstore.
2)implement the functionality accordingly.
3)Validate receipt with cloud function and return the expiry date.
My question here is is there anything to do in our end regarding the billing?in sandbox mode if it is a fake transaction it didn't ask anything about payment.How it work in production is it differently and need we do anything for managing billing?
Any explanation, suggestions and corrections will be awesome.
My code is:
........
if (InAppPurchases.setPurchaseListener) {
InAppPurchases.setPurchaseListener(({ responseCode, results, errorCode }) => {
if (responseCode === InAppPurchases.IAPResponseCode.OK) {
results.forEach(purchase => {
if (!purchase.acknowledged) {
if (purchase.transactionReceipt) {
if (Platform.OS === "ios") {
if (!this.flag) {
this.flag = true;
fetch("url", {
method: "POST",
body: JSON.stringify(purchase),
headers: { "Content-type": "application/json;charset=UTF-8" }
})
.then(response => {
if (response.ok) {
return response.json();
}
})
.then(json => {
if (json && Object.keys(json).length) {
let subscriptionDetails = {};
subscriptionDetails.subscribed = json.isExpired;
subscriptionDetails.expiry = JSON.parse(json.expiryDate);
subscriptionDetails.inTrialPeriod = json.inTrial;
subscriptionDetails.productId = json.id;
SecureStore.setItemAsync(
"Subscription",
JSON.stringify(subscriptionDetails)
)
.then(() => {
console.info("subscription Saved:");
store.dispatch(
setWsData("isSubscriptionExpired", json.isExpired)
);
let expired = json.isExpired;
store.dispatch(setUiData("isCheckAnalyze", true));
store.dispatch(setWsData("firstSubscription", false));
this.setState({ checkExpiry: json.isExpired });
if (!expired) {
InAppPurchases.finishTransactionAsync(purchase, true);
alert("Now you are Subscribed!!");
} else {
alert("Expired");
}
})
.catch(error =>
console.error("Cannot save subscription details:", error)
);
}
})
.catch(err => console.log("error:", err));
}
}
}
}
});
In the code below, I am conditionally switching to another observable. If the condition is met it works fine. If the condition is not met and I return EMPTY from switchMap, the code in the subscribe block is not executed.
If I change return EMPTY to return of(x) it works.
this.claimStoreService.setProducts(this.claim.products)
.pipe(switchMap(x => {
if (this.incomeEligibility) {
return this.claimStoreService.saveIncomeEligibility();
} else {
return EMPTY;
}
}))
.subscribe(() => {
this.isSaving = false;
this.goIntoDisplayMode();
}, () => {
this.isSaving = false;
});
Try to use the third callback:
this.claimStoreService.setProducts(this.claim.products)
.pipe(switchMap(x => {
if (this.incomeEligibility) {
return this.claimStoreService.saveIncomeEligibility();
} else {
return EMPTY;
}
}))
.subscribe(
() => this.goIntoDisplayMode(),
console.err,
() => this.isSaving = false,
);
It is probably more clear if you pass to the subscribe function an Observer. Your code would become
this.claimStoreService.setProducts(this.claim.products)
.pipe(switchMap(x => {
if (this.incomeEligibility) {
return this.claimStoreService.saveIncomeEligibility();
} else {
return EMPTY;
}
}))
.subscribe({
next: () => this.goIntoDisplayMode(),
error: err => console.error(err),
complete: () => this.isSaving = false,
});
There isn't any documentation for how the array meta info (arrayLength and sliceStart) should be implemented using facebook's graphql-relay-js helper library.
https://github.com/graphql/graphql-relay-js/issues/199
I managed to get it to work using the following implemention however I am guessing there is an easier/more correct way to do this.
Retrieve rows and row count from database
function transformRole(role: Role) {
return { ...role, roleId: role.id };
}
async function getRolesSlice({ roleId, after, first, last, before }: any): Promise<[Role[], number]> {
const queryBuilder = repository.createQueryBuilder();
if (roleId !== undefined) {
queryBuilder.where('id = :roleId', { roleId });
}
if (before) {
const beforeId = cursorToOffset(before);
queryBuilder.where('id < :id', { id: beforeId });
}
if (after) {
const afterId = cursorToOffset(after);
queryBuilder.where({
id: MoreThan(Number(afterId))
});
}
if (first === undefined && last === undefined) {
queryBuilder.orderBy('id', 'ASC');
}
if (first) {
queryBuilder.orderBy('id', 'ASC').limit(first);
}
if (last) {
queryBuilder.orderBy('id', 'DESC').limit(last);
}
return Promise.all([
queryBuilder.getMany()
.then(roles => roles.map(transformRole)),
repository.count() // Total number of roles
]);
}
Roles resolver
resolve: (_, args) =>
getRolesSlice(args)
.then(([results, count]) => {
const firstId = results[0] && results[0].roleId;
let sliceStart = 0;
if (args.first) {
sliceStart = firstId;
}
if (args.last) {
sliceStart = Math.max(firstId - args.last, 0);
}
if (args.after && args.last) {
sliceStart += 1;
}
return connectionFromArraySlice(
results,
args,
{
arrayLength: count + 1,
sliceStart
}
);
})
},
Edit:
This is what I came up with which is a little cleaner and seems to be working correctly.
const initialize = () => {
repository = getConnection().getRepository(Role);
}
function transformRole(role: Role) {
return { ...role, roleId: role.id };
}
function getRolesSlice(args: any):
Promise<[
Role[],
any,
{ arrayLength: number; sliceStart: number; }
]> {
if (!repository) initialize();
const { roleId, after, first, last, before } = args;
const queryBuilder = repository.createQueryBuilder();
if (roleId !== undefined) {
queryBuilder.where('id = :roleId', { roleId });
}
if (before !== undefined) {
const beforeId = cursorToOffset(before);
queryBuilder.where({
id: LessThan(beforeId)
});
}
if (after !== undefined) {
const afterId = cursorToOffset(after);
queryBuilder.where({
id: MoreThan(Number(afterId))
});
}
if (first !== undefined) {
queryBuilder.orderBy('id', 'ASC').limit(first);
} else if (last !== undefined) {
queryBuilder.orderBy('id', 'DESC').limit(last);
} else {
queryBuilder.orderBy('id', 'ASC');
}
return Promise.all([
queryBuilder.getMany()
.then(roles => roles.map(transformRole))
.then(roles => last !== undefined ? roles.slice().reverse() : roles),
repository.count()
]).then(([roles, totalCount]) =>
[
roles,
args,
{
arrayLength: totalCount + 1,
sliceStart: roles[0] && roles[0].roleId
}
]
);
}
// Resolver
roles: {
type: rolesConnection,
args: {
...connectionArgs,
roleId: {
type: GraphQLString
}
},
resolve: (_, args) =>
getRolesSlice(args)
.then((slice) => connectionFromArraySlice(...slice))
},
I'm trying to create an Observable from an array of items that each regularly check for server updates and then sends an action when it gets the result it wants for each item.
The answer below is helpful, however not quite what I'm looking for
This is the other approach I've been trying:
export function handleProcessingScenes(action$,store) {
return action$.ofType(REQUEST_ALL_SCENES_BY_LOCATION_FULFILLED)
.switchMap(({ scenesByLocation }) => Observable.from(scenesByLocation))
.filter(scene => scene.scenePanoTask)
.mergeMap(scene => updateScene(scene))
}
function updateScene(scene) {
return Observable.interval(3000)
.flatMap(() => requestSceneUpdates(scene.id))
.takeWhile(res => res.payload.status < 4)
.timeout(600000, Observable.throw(new Error('Timeout')))
}
The API function returns an Observable
export function requestSceneUpdates(sceneId){
console.log('requestSceneUpdate')
const request = fetch(`${API_URL}/scene/task/${sceneId}/update`, {
method: 'get',
credentials: 'include',
crossDomain: true,
}).then(res => res.json())
return Observable.fromPromise(request)
}
However this only calls the 'requestSceneUpdate' function once.
I basically want to call that function every 3 seconds for each scene in scenesByLocation. I then want to return an action when each one is finished.
The epic that I have for a single scene is
export function sceneProcessingUpdate(action$) {
return action$.ofType(REQUEST_SCENE_PROCESSING_TASK_SUCCESS)
.switchMap(({task}) =>
Observable.timer(0, 30000).takeUntil(action$.ofType( REQUEST_SCENE_PROCESSING_TASK_UPDATE_SUCCESS))
.exhaustMap(() =>
requestSceneUpdates(task.id)
.map((res) => {
if (res.error)
return { type: REQUEST_SCENE_PROCESSING_TASK_UPDATE_FAILED, message: res.message }
else if(res.payload.status === 4)
return { type: REQUEST_SCENE_PROCESSING_TASK_UPDATE_SUCCESS, task: res.payload }
else
return requestSceneProcessingTaskMessage(res.payload)
})
.catch(err => { return { type: REQUEST_SCENE_PROCESSING_TASK_UPDATE_FAILED, message: err } })
)
)
}
I think you need something like this. The idea is to retry the scene update if it fails, after 3 seconds and not use a timer.
export function handleProcessingScenes(action$) {
return action$.ofType(REQUEST_ALL_SCENES_BY_LOCATION_FULFILLED)
.switchMap(({ scenesByLocation }) => Observable.from(scenesByLocation))
.filter(scene => scene.scenePanoTask)
.mergeMap(scene => updateScene(scene));
}
function updateScene(scene) {
return requestSceneUpdates(scene.id)
.map((res) => {
if (res.error)
throw res.error;
else if (res.payload.status === 4)
return { type: REQUEST_SCENE_PROCESSING_TASK_UPDATE_SUCCESS, task: res.payload }
else
return requestSceneProcessingTaskMessage(res.payload)
})
.retryWhen(errors => errors.delay(3000));
}
This worked in the end, #Andrew fixed the first part.
export function handleProcessingScenes(action$,store) {
return action$.ofType(REQUEST_ALL_SCENES_BY_LOCATION_FULFILLED)
.switchMap(({ scenesByLocation }) => Observable.from(scenesByLocation))
.filter(scene => scene.scenePanoTask)
.flatMap(scene => {
return Observable.timer(0, 5000).takeUntil(action$.ofType( REQUEST_SCENE_PROCESSING_TASK_UPDATE_SUCCESS))
.exhaustMap(() =>
requestSceneUpdates(scene.id)
.map((res) => {
if (res.error)
return { type: REQUEST_SCENE_PROCESSING_TASK_UPDATE_FAILED, message: res.message }
else if(res.payload.status === 4)
return { type: REQUEST_SCENE_PROCESSING_TASK_UPDATE_SUCCESS, task: res.payload }
else
return requestSceneProcessingTaskMessage(res.payload)
})
.catch(err => { return { type: REQUEST_SCENE_PROCESSING_TASK_UPDATE_FAILED, message: err } })
)
})
}
When using Observables for certain tasks that involve a lot of chaining and a lot of asynchronous operations, such as listing all the items in a folder and checking all of the folders in it for a specific file, I often end up either needing to build the complex chain for each task (return Observable.of(folder)...) or having some kind of special value that gets forwarded to the end to signal the end of a batch (every operator starts with if(res === false) return Observable.of(false)).
Sort of like that stick that you put between your groceries and those of the person in front of you at the checkout.
It seems like there should be a better way that doesn't involve forwarding a stop value through all kinds of callbacks and operators.
So what is a good way to call a function that takes a folder path string and returns a list of all the files and folders in it. It also specifies whether the files are HTML files or not, and whether or not the folders contain a file called tiddlywiki.json.
The only requirement is that it can't return anything like Observable.of(...).... It should probably have a subject at the top of the chain, but that is not a requirement.
function listFolders(folder) {
return [
{ type: 'folder', name: 'folder1' },
{ type: 'datafolder', name: 'folder2' }, //contains "tiddlywiki.json" file
{ type: 'folder', name: 'folder3' },
{ type: 'htmlfile', name: 'test.html' },
{ type: 'other', name: 'mytest.txt' }
]
}
Here is one that does not follow the rules I layed out (see below for one that does), but it took about ten minutes, using the first one as a guide.
export function statFolder(subscriber, input: Observable<any>) {
return input.mergeMap(([folder, tag]) => {
return obs_readdir({ folder, tag })(folder);
}).mergeMap(([err, files, { folder, tag }]) => {
if (err) { return Observable.of({ error: err }) as any; }
else return Observable.from(files).mergeMap(file => {
return obs_stat([file,folder])(path.join(folder, file as string));
}).map(statFolderEntryCB).mergeMap<any, any>((res) => {
let [entry, [name, folder]] = res as [any, [string, string, number, any]];
if (entry.type === 'folder')
return obs_readdir([entry])(path.join(entry.folder, entry.name));
else return Observable.of([true, entry]);
}, 20).map((res) => {
if (res[0] === true) return (res);
let [err, files, [entry]] = res as [any, string[], [FolderEntry, number, any]];
if (err) {
entry.type = "error";
} else if (files.indexOf('tiddlywiki.json') > -1)
entry.type = 'datafolder';
return ([true, entry]);
}).reduce((n, [dud, entry]) => {
n.push(entry);
return n;
}, []).map(entries => {
return { entries, folder, tag };
}) as Observable<{ entries: any, folder: any, tag: any }>;
}).subscribe(subscriber);
}
Original: This took a few hours to write...and it works...but...it uses concatMap, so it can only take one request at a time. It uses a custom operator that I wrote for the purpose.
export function statFileBatch(subscriber, input: Observable<any>) {
const signal = new Subject<number>();
var count = 0;
//use set timeout to fire after the buffer recieves this item
const sendSignal = (item) => setTimeout(() => { count = 0; signal.next(item); });
return input.concatMap(([folder, tag]) => {
return obs_readdir({ folder, tag })(folder);
}).lift({
call: (subs: Subscriber<any>, source: Observable<any>) => {
const signalFunction = (count) => signal.mapTo(1), forwardWhenEmpty = true;
const waiting = [];
const _output = new Subject();
var _count = new Subject<number>()
const countFactory = Observable.defer(() => {
return Observable.create(subscriber => {
_count.subscribe(subscriber);
})
});
var isEmpty = true;
const sourceSubs = source.subscribe(item => {
if (isEmpty && forwardWhenEmpty) {
_output.next(item);
} else {
waiting.push(item)
}
isEmpty = false;
})
const pulse = new Subject<any>();
const signalSubs = pulse.switchMap(() => {
return signalFunction(countFactory)
}).subscribe(count => {
//act on the closing observable value
var i = 0;
while (waiting.length > 0 && i++ < count)
_output.next(waiting.shift());
//if nothing was output, then we are empty
//if something was output then we are not
//this is meant to be used with bufferWhen
if (i === 0) isEmpty = true;
_count.next(i);
_count.complete();
_count = new Subject<number>();
pulse.next();
})
pulse.next(); //prime the pump
const outputSubs = Observable.create((subscriber) => {
return _output.subscribe(subscriber);
}).subscribe(subs) as Subscription;
return function () {
outputSubs.unsubscribe();
signalSubs.unsubscribe();
sourceSubs.unsubscribe();
}
}
}).mergeMap(([err, files, { folder, tag }]) => {
if (err) { sendSignal(err); return Observable.empty(); }
return Observable.from(files.map(a => [a, folder, files.length, tag])) as any;
}).mergeMap((res: any) => {
let [file, folder, fileCount, tag] = res as [string, string, number, any];
return obs_stat([file, folder, fileCount, tag])(path.join(folder, file))
}, 20).map(statFolderEntryCB).mergeMap<any, any>((res) => {
let [entry, [name, folder, fileCount, tag]] = res as [any, [string, string, number, any]];
if (entry.type === 'folder')
return obs_readdir([entry, fileCount, tag])(path.join(entry.folder, entry.name));
else return Observable.of([true, entry, fileCount, tag]);
}, 20).map((res) => {
//if (res === false) return (false);
if (res[0] === true) return (res);
let [err, files, [entry, fileCount, tag]] = res as [any, string[], [FolderEntry, number, any]];
if (err) {
entry.type = "error";
} else if (files.indexOf('tiddlywiki.json') > -1)
entry.type = 'datafolder';
return ([true, entry, fileCount, tag]);
}).map(([dud, entry, fileCount, tag]) => {
count++;
if (count === fileCount) {
sendSignal([count, tag]);
}
return entry;
}).bufferWhen(() => signal).withLatestFrom(signal).map(([files, [sigResult, tag]]: any) => {
return [
typeof sigResult !== 'number' ? sigResult : null, //error object
files, //file list
typeof sigResult === 'number' ? sigResult : null, //file count
tag //tag
];
}).subscribe(subscriber);
}