botgart's People
botgart's Issues
Error in ConfigChecker
Starting up...
Akairo: Exports of module instances are deprecated. Consider exporting module classes.
Started up...
2019-05-02T14:14:10.027Z error [ConfigChecker.js]: Error while validating config entry 'owner_id': ["Owner id can't be blank"]
2019-05-02T14:14:10.031Z error [ConfigChecker.js]: Error while validating config entry 'world_assignments': ["World assignments can't be blank","World assignments not an array."]
2019-05-02T14:14:10.031Z crit [ConfigChecker.js]: config.json contains invalid entries. Shutting down preventively. Please fix the config according to the log.
2019-05-02T14:14:10.034Z info [Disabler.js]: Done disabling 0 modules as specified by the config.
2019-05-02T14:14:10.035Z info [Startup.js]: Bot started!
2019-05-02T14:14:10.037Z info [Startup.js]: Database initialised.
2019-05-02T14:14:10.037Z info [Startup.js]: Rescheduling cronjobs from database.
2019-05-02T14:14:10.038Z info [MakeCron.js]: Done rescheduling 0 cronjobs.
erroooooor TypeError: Cannot read property 'Symbol(Symbol.iterator)' of object
at Function.all (<anonymous>)
at Promise (/home/user/Sync/Botgart/built/listeners/ConfigChecker.js:34:110)
at new Promise (<anonymous>)
at Function.validate.validators.allAsync (/home/user/Sync/Botgart/built/listeners/ConfigChecker.js:34:69)
at Function.runValidations (/home/user/Sync/Botgart/node_modules/validate.js/validate.js:129:30)
at Object.async (/home/user/Sync/Botgart/node_modules/validate.js/validate.js:176:23)
at ConfigChecker.exec (/home/user/Sync/Botgart/built/listeners/ConfigChecker.js:155:18)
at BotgartClient.emit (events.js:198:15)
at WebSocketConnection.triggerReady (/home/user/Sync/Botgart/node_modules/discord.js/src/client/websocket/WebSocketConnection.js:125:17)
at WebSocketConnection.checkIfReady (/home/user/Sync/Botgart/node_modules/discord.js/src/client/websocket/WebSocketConnection.js:141:61)
Agile Defender Granted During Reset
DiscordLog-Function
Create a function
Botgartclient.discordLog(l: LogLevel, m: string);
That works like the regular logging function, but instead posts the output to a specified Discord-channel:
CREATE TABLE discord_log_channels(
log_level TEXT,
guild TEXT,
channel TEXT
)
Admins can specify loglevel/channel-pairs to specify what kind of message lands in which channel. It is up to debate whether these should work hierarchically. (If not, log_type
could be more appropriate.)
With this feature in place, notifying admins when a new user registers/ their key runs out becomes achievable.
Try to resolve `mapInput` in `Util.resolveWvWObjective`
Create REST API
Given that OAuth2 will be used to protect sensitive information on the Riverside homepage, we need to verify that a certain user is registered on RS. One possible workflow would be:
- generate an OAuth2 token on the website
- send the now verified user-ID to Botgart
- have Botgart look that user up in the table of registered users
- if the user is registered on RS, give the website a positive reply, if not send false
Based on Botgart's reply, either display the protected area or not.
https://github.com/MonsantoCo/express-client-validator
Syncronise Information from TS with Discord
Some information, such as current reset leads, are only available in TS. They should be synced automatically, preferably into one post that is repeatedly edited.
Cronjobs should get another parameter for Once-Crons
A lot of crons are actually only supposed to run once, like when an event is being announced.
We wouldn't want them to run again next year, so another boolean parameter should specify crons that have to run only once and should be purged from the DB after their one run.
First Startup After Patch Causes Error
client.wvwWatcher.on("new-matchup",
mu => this.client
.db
.getCommandersDuring(U.sqliteTimestampToMoment(mu.lastMatchup.start)
, U.sqliteTimestampToMoment(mu.lastMatchup.end))
In Achievements.ts causes an error upon first startup when no matchup was written to the DB yet. Solves itself after the first DB write, not nice anyway.
Log Performance Scores of Commanders During Tagup
https://api.guildwars2.com/v2/wvw/matches?world=2202
CREATE TABLE performances(
performance_id INTEGER PRIMARY KEY,
timestamp TEXT
);
CREATE TABLE faction_performances(
faction_performance_id INTEGER PRIMARY KEY,
performance_id INTEGER,
world_id INTEGER,
colour TEXT,
kills INTEGER,
deaths INTEGER,
victory_points INTEGER,
FOREIGN KEY(performance_id) REFERENCES performances(performance_id),
CHECK(colour IN ('red', 'blue', 'green'))
);
Event-Commands
Create command to automatically create and cancel events:
.makeevent dd.mm.yyyy hh:mm label [description]
creates a new event which is posted to the appropriate channel. Afterwards, the bot prompts for additional input, like a time to post a reminder, localisation etc.
.deleteevent id
deletes an event.
.lsevents
lists all upcoming events.
Auto-Commander and announcement in #meldungen
Since the TS-bot is now under our control as well, we can easily synchronise roles in TS and Discord.
The TS-sided functionality has mostly been implemented
ogrady/ts-gw2-verifyBot@6bf99e6
The Discord-Bot can listen to the TS-Bot and read the JSON messages (proof of concept: https://github.com/ogrady/Botgart/blob/master/src/listeners/TS3Listener.ts). We still need to
- resolve the players (TS-Bot passes the account names Foobar.1234, Discord-Bot only know them by their account-UID -- this requires a DB patch and lookup for all already registered members!)
- create a command to be ignored by the bot (not really required imho, but some users are a bit weird about it...)
- create a command to be un-ignored by the bot (same as above...)
Convert projekt to Typescript
Check config upon startup
When starting the bot, check the config for validity as far as possible, e.g. finding duplicate entries for the server-roles etc.
Make command to unregister users from TS
Guild-creation command
Guild creation involves several steps right now:
- Downloading the emblem from the API and uploading it to TS
- Creating a guild channel with restricted permissions and memberlimit with the emblem as icon
- Setting the channel description to the ingame name of the contact person
- Creating the two subchannels
- Creating a servergroup
- Adding the guild-servergroup-tuple to the DB for the TS bot to automatically assign the group
- Granting the guild contact person in TS the appropriate group
This can be highly automated for pink tags to do!
Permission-System
The built-in permission system natively restricts us to a very coarse permission system, where we can basically distinguish between admins and non-admins.
userPermissions: ['ADMINISTRATOR']
But we can also use permission functions to check whether a user has permission to execute a command.
https://discord-akairo.github.io/#/docs/main/stable/class/Command?scrollTo=userPermissions
This enables us to have role- and/or user-granularity to allow or forbid certain commands, like finally granting @Jeybla the ,addcron
command.
Schema
I propose the following schema:
CREATE TABLE command_permissions(
command_permssions_id INTEGER PRIMARY KEY AUTOINCREMENT,
command TEXT, -- primary name of the command
receiver TEXT, -- either a unique user ID or a unique role ID. Discord uses Twitter-Snowflakes as IDs, so they should be compatible with each other and still unique https://discordapp.com/developers/docs/reference
value INTEGER, -- a positive or negative value to either allow or forbid the command
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL -- when this permission was granted
)
Whether a UNIQUE(command,receiver)
constraint should be enforced is open to debate.
Then passing the name of the command cname
to be executed and a list of [user_id, group_id1, group_id2, ..., group_idn]
can resolve the permission as
SELECT
SUM(value) > 0
FROM
command_permissions
WHERE
command = cname
AND receiver IN (user_id, group_id1, group_id2, ..., group_idn)
New Commands
This should be accompanied by a new command:
,permit <command:string> <target:User|Group> <value:integer>
allows a user or group <target>
to execute <command>
. <value>
is an integer used to allow (positive) or disallow (negative) the execution. Passing 0
removes the entry from the database.
Required Updates
The additional check has to be introduced into https://github.com/ogrady/Botgart/blob/master/src/BotgartCommand.ts .
Achievement roles are sometimes created multiple times
Iterating over a list of players for an achievement A which gives out role R that does not exist yet, will cause both iteration steps to create the role and give out both.
Never Surrender! Achievement is granted to everyone tagging up on reset
since KD is 0 at that point, it causes the achievevement to be handed out to every commander who tags up exactly during reset.
`storeAPIKey` doesn't store the gw2 account name!
storeAPIKey
must store the account name, as was introduced in an earlier DB patch.
Make patch-application script for db patches
Changes in the DB schema are now done by writing a patch and put it in db/patches
. Patches are supposed to be incremental and have a running number prefix, going up in increments of 100 (should hopefully not be needed, but if we ever need to slip in a patch out of order, we can use that).
So an exemplary db/patches
could look like this:
1_patch.sql
100_patch.sql
200_patch.sql
250_patch.sql <- this one was slipped in due to a merge
300_patch.sql
Patches must be applied to the database system in numeric order. A script should be provided to do just that, having two alternative parameters first
and last
to specify a range of patches, or just do all patches a default behaviour.
Patches can be applied manually by using
$ sqlite3 database.db
sqlite> .read patch_X.sql
(X
being the number of the patch, obviously...)
Bot doesn't revalidate keys
Jul 15 00:13:02 xxxx.stratoserver.net node[13722]: 2019-07-14T22:13:02.349Z error [Util.js]: Encountered an error while trying to validate a key. This is most likely an expected error: {"response":{"size":0,"timeout":0},"content":{"text":"too many requests"}}
Jul 15 00:13:02 xxxx.stratoserver.net node[13722]: 2019-07-14T22:13:02.349Z error [DB.js]: Error occured while revalidating key xxxxxxxxxxxxxxxxx. User will be excempt from this revalidation.
Getting a lot of these. Bot doesn't seem to be able to revalidate any keys. Probably need to use some sort of slowdown for the requests.
Autoprune
Prune members idling in the lobby. Doing this automatically gives us the opportunity to add a custom message.
https://discord.js.org/#/docs/main/stable/class/Guild?scrollTo=pruneMembers
Make Prune available as cronjob
Raffle
Players can buy raffle tickets by donating a fixed amount of money to the guild bank, say 1g1s1c. The majority (90%?) goes into the raffle, while the rest remains with "the house". Users can buy as many tickets as they want.
The bot continuously monitors the guild bank log. If a ticket purchase is read, an announcement is made in a separate channel to spread awareness that the jackpot has increased.
At the end of a fixed period (a month?) a user is randomly selected and the admin is notified to send the user their prize.
Streamline Locale
Integrate the new functionality of BotgartCommand.desc() into the locale.
Exception when running ResetRoster as Cron
(node:32405) UnhandledPromiseRejectionWarning: TypeError: args.channel.send is not a function
at getBotgartClient.db.getRosterPost.then (/home/discord/Botgart/built/commands/resetlead/ResetRoster.js:268:30)
Guild ID must be incorporated into the roster key
https://github.com/ogrady/Botgart/blob/master/src/BotgartClient.ts#L32
Probably not very relevant, since the bot only runs on one server, but since the roster is guild-sensitive, the guild ID should be placed somewhere in the roster key.
Finish the PermanentRole feature
Feature-development was started but never finished. https://github.com/ogrady/Botgart/blob/master/src/commands/PermanentRole.ts
Gives a user a role he will retain upon rejoining. This helps with users who try to avoid punishment roles by rejoining the server.
Create command to remove discordlog-channel
Equivalent to DiscordLog
, but removes the connection.
- create method
removeLogChannel
inlogChannelRepository
that deletes the entry from the DB. - create command
RemoveDiscordLogChannel
insrc/commands
that receives a type of message and a text channel and destroys that connection, analogue to how it is being created inDiscordLog
(command will be renamed). - create all required localisation strings in
Locale.ts
(HELPTEXT_
,DESC_
, and everything else you might need in both English and German).
Make TS3Listener reconnect after a while when connection is lost
Implement Achievements
{
"embed": {
"title": "Schimmer | Glimmer",
"description": "Errungenschaft freigeschaltet!",
"color": 8580840,
"timestamp": "2019-12-04T15:15:05.463Z",
"thumbnail": {
"url": "https://wiki.guildwars2.com/images/a/a9/Solar_Beam.png"
},
"author": {
"name": "Len",
"icon_url": "https://cdn.discordapp.com/embed/avatars/0.png"
},
"fields": [
{
"name": ":flag_de:",
"value": "Leite für eine Stunde.\n\n_Willkommen auf der Brücke, Kommandeur!_",
"inline": true
},
{
"name": ":flag_gb:",
"value": "Tag up for an hour.\n\n_Welcome to the bridge, commander!_",
"inline": true
}
]
}
}
Replace `winston.log` in HelpCommand with `Util.log`
Fix basepath relative imports [Typescript]
#7
In Node, we could do require.main.require('foo/bar.js')
to import a module root/foo/bar.js
no matter how deeply nested the caller.
In Typescript, we are nailed down to either doing this sort of import or being able to import modules from the node_modules/
directory through a compiler flag. So in order to import Node modules, we have to do our relative imports with shit like ../../../../foo/bar.js
. There is probably an answer to this somewhere in https://www.typescriptlang.org/docs/handbook/module-resolution.html
Have reset date in roster post
Store duration someone tagged up
Events of tagging up and down already are sent to Discord.
Store the duration of a lead to the DB to generate statistics and reward active commanders in some way.
Cronjobs should display when they run the next time
Mixing up the order of parameters in cron-strings happens easily and posting the date on which the cron is actually being scheduled should serve as a great sanity check.
node-schedule
already offers this functionality, so it should be easy to post this date as feedback to the issuer of the command.
var j = schedule.scheduleJob('0 1 * * *', function(fireDate){
console.log('This job was supposed to run at ' + fireDate + ', but actually ran at ' + new Date());
});
Make Listeners optional
Since Botgart is also used in our internal guild discord (on another instance tho), we should have a way to disable listeners, as the JoinListener
currently prompts new RoE members to send them an API key to be registered as Riverside player. Since the Akairo Client automatically loads all listeners in the specified listener-directory, this needs bits of code to achieve.
Listeners can easily be disabled within the ReadyListener.js
by name:
this.client.listenerHandler.modules.get("guildMemberAdd").disable();
TSSync doesn't work for some users
When tagging up, some users are not properly posted to Discord. This might be a problem with the TSBot.
Affected users so far:
- Len
- Der Zerquetscher
- Goodendly
Whois-Command
,whois @discorduser
should display basic account information. This is especially useful when dealing with impostors, as has happend with Amhai.
Error in ConfigValidator
"Error: Unknown validator pattern"
Maybe
pattern: /^.+\.\d+$/,
Pipe [Side]-Log to Discord
Make cronable command that pipes alle in- and out-going transactions to the vault since a certain transaction.
Should look like this:
,stash <Guild ID> <Leader API Key> <Discord Channel to post to>
Require endpoints
https://wiki.guildwars2.com/wiki/API:2/guild/:id/log
https://github.com/queicherius/gw2api-client/blob/HEAD/docs/endpoints.md#apiguildidlog
Behaviour
- on startup, fetch the current latest ID of stash transactions
- when issued, fetch all log messages related to the stash since the latest ID and post them to a channel
- update the latest ID
Checks
- check for valid Guild
- check for API Key to be entitled to retrieve guild log (leader only!)
Create command to repair the DB
Due to an oversight, newly registered users have nothing placed in their account_name
field.
But this problem can also occur naturally, when the lookup for their account name fails several times during registration (very unlikely, since then the preceding server-lookup would probably have failed as well, but well...).
So having a command that fetches all rows with account_name = null
and attempts another lookup for them should be the easiest solution.
Feedback for saved cronjob incorrectly separated
Current:
:flag_de: Dein Cronjob wurde gespeichert mit der ID 44. Nächste Ausführung: Your cronjob has been saved with ID 44. Next execution: Fri Aug 02 2019 18:45:00 GMT+0200..
:flag_gb: Your cronjob has been saved with ID 44. Next execution: Fri Aug 02 2019 18:45:00 GMT+0200.
Expected:
:flag_de: Dein Cronjob wurde gespeichert mit der ID 44. Nächste Ausführung: Fri Aug 02 2019 18:45:00 GMT+0200.
:flag_gb: Your cronjob has been saved with ID 44. Next execution: Fri Aug 02 2019 18:45:00 GMT+0200.
Users with multiple registrations receive too much progress for achievements
Der Zerquetscher is registered twice in Discord. Since achievements group by GW2Account, he receives double the progress for every achievement!
ConfigChecker not detecting faulty owner_id
user#1234
apparently works just as well, although only \d+ should be allowed.
Faulty string formatting in revalidate process
2020-02-02T23:25:54.543Z error [Reauthenticate.js]: Can not find a role {0} to assign.
Re-Test all commands
After overhauling the API and logging, we could use another round of testing...
(can we mock this??)
DiscordLog (re)authentification results
Use feature from #24 to pipe results of (re)authentification to a Discord channel.
ResetRoster.isUpcoming broken
The function doesn't properly predict the next reset day, resulting in Botgart not publishing changes to the roster to the TS-Bot (resulting in me debugging the TCP-connection for a whole week to find out that that part was actually fine...).
Also a function Util.compareDatesWithoutTime
was created to make comparing two dates independent of their time, which should be used where ever reset day checks are being made.
Permit doesn't seem to work reliably
On the live server, several permissions were granted to a role and the holders of that role could not use the commands regardless. Allowing singular users to perform commands couldn't even get past the command.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.