pinano-discord / Pinano-Discord-Bot

A Discord bot for the Pinano guild
MIT License
9 stars 11 forks source link

Pinano Bot

Build Status

This is the open source for Pinano Bot, which tracks stats and enhances the experience in the Pinano Discord server.

Getting started

Pinano Bot is written in Javascript using NodeJS.

To start developing, you should install nodenv to ensure you use the same version of Node as other developers.

On MacOS, you can run:

brew install nodenv node-build
nodenv install $(cat .node-version)

If you just want to jump in without installing nodenv, make sure you look at .node-version for the current version we are using.

You must have mongodb installed and running. One way to achieve this is to use Docker:

docker run --name pinano-mongo -p 27017:27017 -d mongo:latest

Then you can install all dependencies:

npm install

And run any tests:

npm test

Running a test bot

If you'd like to actually run a test bot, you will need to follow the instructions to create a bot user. Replace the placeholder in config.json with the token from the bot's Discord settings page, and follow the instructions to add the bot to a server. You can either use your own test server, or the Pinano bot development server (feel free to ask any staff member on Pinano for an invite).

For your bot to do anything, you'll need to add a config document to the pinano.config mongodb collection specifying which modules to activate. The following config can be used for basic testing:

{
  id: "[SERVER ID]",
  commandPrefix: "pb!!",
  enableHelp: true
}

This bot responds to two commands: pb!!help and p!!config. The pb!!help command DMs you the commands it knows about (this requires that your Discord privacy settings permit receiving DMs from the bot, i.e. on your test server you have the privacy setting "Allow direct messages from server members" enabled).

Modules

Pinano Bot functionality is implemented by modules, the configuration of which is specified in the config document for a given server (i.e. modules can be configured differently per server). For ease of testing, some modules are split into a logic module and an adapter module for talking to Discord.

Pinano Bot provides the following modules:

Badges

Controlled by the configuration setting enableBadges. When enabled, the stats command shows a list of personal achievements attained. Each badge must also be enabled individually via config. Badges associated with specific modules are described in that module's description. If defined in config, this module awards the following badges:

The badgesPerPage config setting (default value: 12) determines how many badges can appear on a user's stats card until scrolling behaviour is enabled.

Channel Raiding

Controlled by the configuration setting enableChannelRaiding. When enabled, the occupant of a locked room may invoke the raid command to send everybody in the occupant's room (including the occupant) into another user's locked room.

Configuration Management

This module is always enabled, and allows members of the role specified by managementRoleId to change configuration settings by invoking the config command. If no managementRoleId is specified, or managementRoleId does not refer to a valid role, then initialization of this module will fail.

Only a small number of config settings are currently reloadable without restarting Pinano Bot; these are listed in base/config_manager.js.

Daily Time

Controlled by the configuration setting enableDailyTime. When enabled, users can invoke the setdailyreset command to configure daily time tracking. The parameter to the setdailyreset command represents the UTC hour at which the user's daily time tracking will reset every day. (Note that this means that users in time zones that are not offset from UTC by an integer multiple of an hour cannot configure their time to reset at midnight in their local time zone.) This module requires the Practice Manager module to be enabled.

If a user has daily time tracking enabled, then daily streaks will be calculated for that user. If defined in config, streakBadgeIcon configures the icon for a badge that is awarded for having a qualifying practice session for five or more days in a row.

By using the setdailyreset to modify the reset hour at appropriate times, the user can effectively lengthen a "day" to be longer than twenty-four hours (similar to the normal adjustment of UTC offset during Daylight Savings Time switches). If, by doing this, the user attains a daily practice time of forty hours or more, the linglingBadge, if defined in config, is awarded to the user.

Frequently Asked Questions

Controlled by the configuration setting enableFaq. When enabled, the configuration setting faqEntries defines an array of questions. Each question contains a question field, an answer field, as well as an array of tags that can be used as the parameter to the faq command to cause that question to display as the result of the command. For example:

"faqEntries" : [
  {
    "question" : "What is the answer to the ultimate question of life, the universe and everything?",
    "answer" : "42.",
    "tags" : ["sky", "blue"]
  }
]

defines a single FAQ entry which can be displayed by using invoking faq sky or faq blue.

Help

Controlled by the configuration setting enableHelp. When enabled, users can invoke the help command to have Pinano Bot send them a DM containing a list of supported commands. The list of commands is dependent on what modules are enabled, e.g. if the Statistics module is not enabled, then stats will not appear on the list of commands.

Pinano Bot does not check whether the user is DMable. In order to receive the command list, the user's Discord privacy settings must permit receiving DMs from the bot, i.e. the user must have privacy setting "Allow direct messages from server members" enabled for the server.

Listening Graph

Controlled by the configuration setting enableListeningGraph. When enabled, Pinano Bot tracks per-user listening statistics, i.e. the amount of time each user has spent listening to each person practicing is tracked separately. The top command can be invoked for a given user to display the top five Listeners (i.e. users who have listened to the subject) and the top five Listened To (i.e. users whom the subject has listened to). This module requires the Practice Manager module to be enabled.

If defined in config, this module awards the following badges:

Badge updates are not immediate; the Top Fan and Top Choice are recalculated according to the listeningGraphUpdateSpec config setting. By default this is set to 0 * * * *, i.e. the badges are recalculated at the top of every hour.

Literature Quiz

Controlled by the configuration setting enableLiteratureQuiz. This module enables an identification game in the channel specified by literatureQuizChannelId. Users post an excerpt to be identified in the channel; other users attempt to guess it, and either the original user, or a member of the role specified by quizMasterRoleId, can mark the guess as correct or incorrect. When a riddle is added but there is no room for a new active riddle, the riddle is added to a persistent queue and posted at an appropriate time later.

The behaviour of the Literature Quiz module is modified by the following configuration settings:

If defined in config, this module awards the following badges:

Policy Enforcer

Controlled by the configuration setting enablePolicyEnforcer. When enabled, the lock and unlock commands can be used to lock and unlock the room currently occupied by the invoking user for exclusive use. Members with the role specified by managementRoleId can additionally lock rooms they are not currently occupying, as well as unlock rooms they do not have locked. If no managementRoleId is specified, or managementRoleId does not refer to a valid role, then initialization of this module will fail.

The Policy Enforcer also provides the following additional features:

Practice Manager

Controlled by the configuration setting enablePracticeManager. This module is the core of most Pinano Bot stat tracking. When enabled, Pinano Bot tracks session and overall practice time, as well as overall listening time. If enableLeaderboardDisplay is true, then the leaderboards for these statistics are displayed in the channel specified by informationChannelId, and updated according to updateLeaderboardCronSpec. By default, updateLeaderboardCronSpec is set to */15 * * * * *, i.e. the information channel is updated every fifteen seconds.

Session practice time is reset according to the resetCronSpec config setting; on reset, the practice manager saves all active sessions, and optionally posts the final result to the channel specified by announcementsChannelId if postLeaderboardOnReset is true.

enableSanityCheck is a configuration setting to provide defense-in-depth against a ghost session, i.e. a session that Pinano Bot thinks is active, but the user is not unmuted in a practice room. This may happen, for example, if Pinano Bot missed a channel leave event. If enableSanityCheck is true, then every minute, Pinano Bot will audit current sessions to ensure that they correspond to currently unmuted Discord users; if not, then Pinano Bot will delete the session without committing the time to the database.

Restart

Controlled by the configuration setting enableRestart. When enabled, this module allows members of the role specified by managementRoleId to exit the Pinano Bot process. If managementRoleId is not specified, or managementRoleId does not refer to a valid role, then initialization of this module will fail. This module should not be enabled on untrusted servers; otherwise, any member of the management role on that server can restart the bot for all servers without committing active practice sessions to the database.

Stage Manager

Controlled by the configuration setting enableStageManager. Requires recitalManagerRoleId, performerRoleId, controlChannelId, textChannelId, voiceChannelId, programChannelId to be configured and to refer to valid roles and channels. When enabled, this module creates a control panel in the channel specified by controlChannelId to apply pre-defined permissions presets to a recital voice channel, and text channels for a recital programme and chat.

Statistics

Controlled by the configuration setting enablePStats. When enabled, users can use the stats command to display their own statistics or statistics of another user. The stats card is modified by other modules such as the Daily Time module and the Badges module.

Subscriptions

Controlled by the configuration setting enableSubscriptions. This module requires the Policy Enforcer module to be enabled. When enabled, users can use the subscribe command to receive a DM from Pinano Bot when the subscribee locks a practice room (this includes when a room locks automatically due to autolock). The subscribee can control whether other users can subscribe to them with the subscribers command. subscribers off means that other users can no longer subscribe to them; subscribers silent means that other users can subscribe to them, but notifications are disabled.

Pinano Bot does not check whether the user is DMable. In order to receive subscription notifications, the user's Discord privacy settings must permit receiving DMs from the bot, i.e. the user must have privacy setting "Allow direct messages from server members" enabled for the server.

Token Collecting

Controlled by the configuration setting enableTokenCollecting. This module requires the Practice Manager module to be enabled. When enabled, this module enables a collection game based on the names of practice rooms that are spawned by the Policy Enforcer's autocreation feature.

By practicing in a room for some length of time (configurable via minimumSessionTimeToEarnToken), a user earns the token associated with that room, which is displayed in the channel name. The user's stats card shows which tokens the user has earned. The RoomIdentifiers collection contains the list of available tokens. Some collections have special behaviour:

Additionally, if enableCustomTokens is true, then an egg token is awarded for any listening session exceeding the minimum session time. An egg token hatches after a randomly-selected amount of practice subsequent to being awarded the egg token; the range is configurable using the config settings timeToHatchCustomToken and hatchCustomTokenTimeRange (default: 7200). A user may only have one egg token at a time. An egg token hatches into the defaultCustomToken with probability defaultCustomTokenProbability, one of rareCustomTokens with probability rareCustomTokenProbability, and one of customTokens otherwise. If a user's ID is present in alwaysGetsDefault (default: []), then irrespective of the preceding probability distribution, that user's eggs always hatch into the default custom token, unless they have no custom tokens yet. If announceCustomTokens is true, then egg token awards and custom token hatches are announced in the channel described by announcementsChannelId.

If defined in config, this module awards the following badges:

User Management

Controlled by the configuration setting enableUserManagement. When enabled, this module allows members of the role specified by managementRoleId to use the addtime or deltime commands to adjust the session playtimes of a given user. Users may not adjust their own times. If managementRoleId is not specified, or managementRoleId does not refer to a valid role, then initialization of this module will fail.

Writing a new module

Modules are passed in a single argument when constructed: the module manager. The module manager exposes access to several components:

For scheduled tasks, Pinano Bot uses node-cron.

An example of a module implementing a command using the event dispatcher and a scheduled task via node-cron to modify the user repository is the Daily Times module.

Required permissions

Pinano Bot requires the following permissions:

Contribution instructions

If you have anything to improve, you can either open an issue or you can submit a pullrequest directly.