Git Product home page Git Product logo

botgart's People

Contributors

cubimon avatar dependabot[bot] avatar github-actions[bot] avatar jendrsczok avatar jeybla avatar ogrady avatar xyaren avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

botgart's Issues

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!)

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();

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.

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

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.

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.

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.

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.

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...)

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 .

Re-Test all commands

After overhauling the API and logging, we could use another round of testing...

(can we mock this??)

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.

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...)

Create command to remove discordlog-channel

Equivalent to DiscordLog, but removes the connection.

  • create method removeLogChannel in logChannelRepository that deletes the entry from the DB.
  • create command RemoveDiscordLogChannel in src/commands that receives a type of message and a text channel and destroys that connection, analogue to how it is being created in DiscordLog (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).

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.

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.

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
      }
    ]
  }
}

https://leovoel.github.io/embed-visualizer/

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)

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());
});

https://www.npmjs.com/package/node-schedule

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

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.

Streamline Locale

Integrate the new functionality of BotgartCommand.desc() into the locale.

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.

Whois-Command

,whois @discorduser should display basic account information. This is especially useful when dealing with impostors, as has happend with Amhai.

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

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.

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.

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.