I would like to make a command that enables or disables the unknown command event and is automatically disabled how would i go about doing this?
The Event:
return message.channel.send(new Discord.MessageEmbed()
.setColor(ee.wrongcolor)
.setFooter(ee.footertext, ee.footericon)
.setTitle(`❌ Unkown command, try: **\`${prefix}help\`**`)
.setDescription(`.setup has a list of info you might need`)
).then(msg=>msg.delete({timeout: 5000}).catch(e=>console.log("Couldn't Delete".gray)));
You will have to be able to save a variable somewhere (database, json file, etc). I prefer databases but that is my personal preference. So my answer will be based on saving it to a database. It may not be your choice but it can work.
const con = require('./database.js')
// if doing it as a message command with a prefix
client.on('messageCreate', async message => {
// set up command recognition here
if (command === 'enable-event') {
con.query(`UPDATE database_name SET event = 'enabled' WHERE event_name = 'invalid'`)
} else if (command === 'disable-event') {
con.query(`UPDATE database_name SET event = 'disabled' WHERE event_name = 'invalid'`)
}
if (!command) {
con.query(`SELECT * FROM database_name WHERE event_name = 'invalid'`, (err, rows) => {
if (err) throw err
const status = rows[0].event
if (status === 'enabled') {
const embed = new Discord.MessageEmbed()
.setColor(ee.wrongcolor)
.setFooter(ee.footertext, ee.footericon)
.setTitle(`❌ Unkown command, try: **\`${prefix}help\`**`)
.setDescription(`.setup has a list of info you might need`)
return message.channel.send({
embeds: [embed]
}).then((msg) => {
msg.delete({
timeout: 5000
})
}).catch(e =>
console.log("Couldn't Delete".gray)
)
} else {
return
}
})
}
})
Related
Can a custom command overload be done the same way as a function overload?
There is no answer to this in the documentation.
For example:
Cypress.Commands.add('navigateAndWaitForApi',
(relativePath: string, apisPath: string[], timeout?: number) => {
let options = {};
if (timeout !== undefined) {
options = { timeout: TIMEOUT };
}
apisPath.forEach((api)=> {
cy.intercept(`/api/${api}`).as(api);
})
cy.visit(`/${relativePath}`);
cy.wait(apisPath.map(apiPath => `#${apiPath}`), options);
});
Cypress.Commands.add('navigateAndWaitForApi',
(relativePath: string, apiPath: string, timeout?: number) => {
cy.navigateAndWaitForApi(relativePath, [apiPath], timeout);
});
It does not appear so. The command name navigateAndWaitForApi is the total signature.
Add this after the command definitions
console.log(Cypress.Commands._commands)
shows commands are stored in an object, keyed by the command name.
Adding the same command twice, the second overwrites the first.
It's possible to type-check the params at runtime.
Cypress.Commands.add('navigateAndWaitForApi',
(relativePath: string, apiPaths: string|string[], timeout?: number) => {
if (typeof apiPaths === 'string') {
apiPaths = [apiPaths]
}
let options = {};
if (timeout !== undefined) {
options = { timeout: TIMEOUT };
}
apiPaths.forEach((api)=> {
cy.intercept(`/api/${api}`).as(api);
})
cy.visit(`/${relativePath}`);
// cy.wait(apiPaths.map(apiPath => `#${apiPath}`), options); // look dubious
apiPaths.forEach(apiPath => {
cy.wait(`#${apiPath}`), options)
})
});
I am trying to test for an object to exist in my AngularFire table. I am having issues returning the subject to detect if the file exists or not.
/**
* Check if the Id exists in storage
* #param Id string | number Key value to check
* #returns Subject<boolean>
*/
public Exists(Id:string):Subject<boolean> {
const Status$:Subject<boolean> = new Subject<boolean>();
let RecordExists:boolean = false;
this.AfDb_.object<T>(`_Testing_/${Id}`).valueChanges()
.subscribe( (OneRecord:T) => {
if (OneRecord.Key_ !== undefined && OneRecord.Key_ !== null && OneRecord.Key_.length > 0) {
RecordExists = true;
}
})
;
Status$.next(RecordExists);
return Status$;
}
This is always returning undefined. My automated tests then fail as well.
it('should confirm a record exists in storage', fakeAsync( () => {
let Exists:boolean;
const Status$:Subject<boolean> = ServiceUnderTest.Exists('Good'); // This exists in Firebase
Status$.subscribe( (Result:boolean) => {
Exists = Result;
});
flushMicrotasks();
Status$.unsubscribe();
expect(Exists).toBeTrue();
}));
I have access in Firebase to /Testing/Good which is an object with a structure of Key_ and Name.
Modules from package.json
"#angular/fire": "^5.4.2",
"firebase": "^7.9.3",
However, if I simply try to return a result without going directly to AngularFire, these tests work.
public Exists(Id:string):BehaviorSubject<boolean> {
const Status:BehaviorSubject<boolean | undefined> = new BehaviorSubject<boolean | undefined>(undefined);
Status.next(true);
return Status;
}
You have to call next on subject when RecordExists came from .valueChanges() e.g.:
let RecordExists:boolean = false;
this.AfDb_.object<T>(`_Testing_/${Id}`).valueChanges()
.subscribe( (OneRecord:T) => {
if (OneRecord.Key_ !== undefined && OneRecord.Key_ !== null && OneRecord.Key_.length > 0) {
Status$.next(true);
} else {
Status$.next(false);
}
})
;
return Status$;
Your code behave in different way in test and simple example because both are call this .valueChanges() in synchronous way so .next() is called after subscribe. In real life valueChanges is async so subscribe is called before next.
====================Edited=====================
to connect with real database you have to modify your test to be async (because connection is async:
it('should confirm a record exists in storage',((done) => {
Status$.subscribe( (Result:boolean) => {
expect(Exists).toBeTrue();
done()
});
d}))
the userList result contains only one userRecord while all the users are around 8
corsHandler(request, response, () => {
admin.auth().listUsers(10, 'token')
.then((UserListResult) => {
if (UserListResult.pageToken) { console.log('is found') }
response.status(200).send(UserListResult)
})
.catch(error => response.send(error))
})
Finally, I resolved this.
It seems that if the pageToken is a null or an invalid string, it returns just one record (based on a couple of tests, last user record)
I changed my code as below and it is working
import * as express from 'express'
import * as admin from 'firebase-admin'
import { validate } from '../middleware/auth.middleware';
const router = express.Router()
/** List users */
router.get('/', async (req, res) => {
let { limit, page } = req.query
limit = parseInt(limit) || 25;
page = page === 'null' ? null : page;
try {
// Adding a conditional operator here, one with pageToken & other with just limit
const users: admin.auth.ListUsersResult = page ? await admin.auth().listUsers(limit, page || null) : await admin.auth().listUsers(limit);
const nextPageToken: string = users.pageToken;
res.status(200).json({ message: 'Success', users: [...users.users], nextPageToken }).end();
} catch (err) {
console.error(err);
res.status(500).json({ message: 'Internal Server Error' }).end();
}
});
export { router }
I am trying to build A CONVERSATIONAL BOT. when I am trying to pass the response with next , its not getting reflected din the next functions .
bot.dialog('Barcode',
(session, args, next) => {
var intent = args.intent;
var id = builder.EntityRecognizer.findEntity(intent.entities, 'Report.Id');
if (id) {
next({ response: id.entity });
} else {
builder.Prompts.text(session, 'Please enter your id');
}
session.endDialog();
} ,
(session,results) => {
var id = results.response;
session.send(id.toString()); -- i want the value to be passed here
}
).triggerAction({
matches: 'Barcode'
})
If you want to implement a workflow in a dialog, you can set IDialogWaterfallStep|IDialogWaterfallStep[] in the second parameter in dialog() function.
In your code, you forget to cover [] outside the steps.
Try:
bot.dialog('Barcode',[
(session, args, next) => {
var intent = args.intent;
var id = builder.EntityRecognizer.findEntity(intent.entities, 'Report.Id');
if (id) {
next({ response: id.entity });
} else {
builder.Prompts.text(session, 'Please enter your id');
}
session.endDialog();
} ,
(session,results) => {
var id = results.response;
session.send(id.toString()); -- i want the value to be passed here
}]
).triggerAction({
matches: 'Barcode'
})
I'm having a real hard time understanding how to implement aor-realtime (trying to use it with firebase; reads only, no write).
The first place I get stuck: This library generates a saga, right? How do I connect that with a restClient/resource? I have a few custom sagas that alert me on errors, but there is a main restClient/resource backing those. Those sagas just handles some side-effects. In this case, I just don't understand what the role of the client is, and how it interacts with the generated saga (or visa-versa)
The other question is with persistence: Updates stream in and the initial set of records is not loaded in one go. Should I be calling observer.next() with each update? or cache the updated records and call next() with the entire collection to-date.
Here's my current attempt at doing the later, but I'm still lost with how to connect it to my Admin/Resource.
import realtimeSaga from 'aor-realtime';
import { client, getToken } from '../firebase';
import { union } from 'lodash'
let cachedToken
const observeRequest = path => (type, resource, params) => {
// Filtering so that only chats are updated in real time
if (resource !== 'chat') return;
let results = {}
let ids = []
return {
subscribe(observer) {
let databaseRef = client.database().ref(path).orderByChild('at')
let events = [ 'child_added', 'child_changed' ]
events.forEach(e => {
databaseRef.on(e, ({ key, val }) => {
results[key] = val()
ids = union([ key ], ids)
observer.next(ids.map(id => results[id]))
})
})
const subscription = {
unsubscribe() {
// Clean up after ourselves
databaseRef.off()
results = {}
ids = []
// Notify the saga that we cleaned up everything
observer.complete();
}
};
return subscription;
},
};
};
export default path => realtimeSaga(observeRequest(path));
How do I connect that with a restClient/resource?
Just add the created saga to the custom sagas of your Admin component.
About the restClient, if you need it in your observer, then pass it the function which return your observer as you did with path. That's actually how it's done in the readme.
Should I be calling observer.next() with each update? or cache the updated records and call next() with the entire collection to-date.
It depends on the type parameter which is one of the admin-on-rest fetch types:
CRUD_GET_LIST: you should return the entire collection, updated
CRUD_GET_ONE: you should return the resource specified in params (which should contains its id)
Here's the solution I came up with, with guidance by #gildas:
import realtimeSaga from "aor-realtime";
import { client } from "../../../clients/firebase";
import { union } from "lodash";
const observeRequest = path => {
return (type, resource, params) => {
// Filtering so that only chats are updated in real time
if (resource !== "chats") return;
let results = {}
let ids = []
const updateItem = res => {
results[res.key] = { ...res.val(), id: res.key }
ids = Object.keys(results).sort((a, b) => results[b].at - results[a].at)
}
return {
subscribe(observer) {
const { page, perPage } = params.pagination
const offset = perPage * (page - 1)
const databaseRef = client
.database()
.ref(path)
.orderByChild("at")
.limitToLast(offset + perPage)
const notify = () => observer.next({ data: ids.slice(offset, offset + perPage).map(e => results[e]), total: ids.length + 1 })
databaseRef.once('value', snapshot => {
snapshot.forEach(updateItem)
notify()
})
databaseRef.on('child_changed', res => {
updateItem(res)
notify()
})
const subscription = {
unsubscribe() {
// Clean up after ourselves
databaseRef.off();
// Notify the saga that we cleaned up everything
observer.complete();
}
};
return subscription;
}
};
}
};
export default path => realtimeSaga(observeRequest(path));