npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

discord-dynamic-messages

v4.0.0

Published

Create auto-updating component-like messages in discord.js with ease.

Downloads

7

Readme

discord-dynamic-messages

What exactly is the usage of this lib?

Basically it helps with creating messages that dynamically change their contents based on how ppl react on it. Aka, the message content acts as a screen, and the reactions act as input buttons.

import { Client } from 'discord.js';
import { DynamicMessage, OnReaction } from 'discord-dynamic-messages';

export class CounterMessage extends DynamicMessage {
  private counter;
  constructor(args) {
    super();
    this.counter = args.initialCounterValue;
  }

  @OnReaction(':thumbsup:')
  public increment(user, channel, reaction) {
    this.counter += 1;
  }

  @OnReaction(':thumbsdown:')
  public decrement(user, channel, reaction) {
    this.counter -= 1;
  }

  public render() {
    return `Counter: ${this.counter}`;
  }
}

const client = new Client();
client.on('ready', () => {
  client.on('message', (message) => {
    new CounterMessage({
      initialCounterValue: 0,
    }).sendTo(message.channel);
  });
});
client.login(discord_secret);

Install

Note: This library depends on typescript decorators, and will therefore not work properly unless used in a correctly configured typescript project.

  1. Install library: npm i discord-dynamic-messages.
  2. Enable experimentalDecorators and emitDecoratorMetadata in tsconfig.json.
  3. Try the example above.

Note: If you are using vscode you might need to set javascript.implicitProjectConfig.experimentalDecorators to true in the workspace settings.

Discord.js v11

From here on out support for v11 has been discontinued.

However an old version of the library can be found here: https://github.com/Olian04/discord-dynamic-messages/tree/Discord.js-v11

Documentation

DynamicMessage

abstract class DynamicMessage {
  constructor(config: IDynamicMessageConfig);
  abstract public render(): string | RichEmbed;
}
interface IDynamicMessageConfig {
  volatile: boolean;
  onError?: (error: Error) => void;
}

This is the base class of the library, every dynamic message must extend this class. Every class that extends this DynamicMessage must implement a render method. The volatile config option determines wether or not errors should be thrown, or passed to the error handler. The render method is used to determine the contents of the corresponding "discord text message".

DynamicMessage#reRender

type reRender = () => void

Used to manually trigger a rerender.

class Foo extends DynamicMessage {
  public doStuff() {
    // do some stuff
    this.reRender()
  }
  
  public render() {
    return 'stuff';
  }
}

DynamicMessage#addReactions

type addReactions = (emoji: string[]) => void

Used to manually add reactions to a message.

class Foo extends DynamicMessage {
  public addOneTwoThree() {
    this.addReactions([
      ':one:', ':two:', ':three:',
    ]);
  }
  
  public render() {
    return 'stuff';
  }
}

DynamicMessage#sendTo

type sendTo = (channel: Discord.Channel) => DynamicMessage

Sends the dynamic message to the given channel.

class Foo extends DynamicMessage {
  public render() {
    return 'stuff';
  }
}

client.on('message', (msg) => {
  new Foo().sendTo(msg.channel)
})

DynamicMessage#replyTo

type replyTo = (message: Discord.Message) => DynamicMessage

Sends the dynamic message as a reply to the given message.

class Foo extends DynamicMessage {
  public render() {
    return 'stuff';
  }
}

client.on('message', (msg) => {
  new Foo().replyTo(msg)
})

DynamicMessage#attachTo

type attachTo = (message: Discord.Message, responseTo?: Discord.User) => DynamicMessage

Attaches an existing message to the DynamicMessage instance, then call render on the instance and overwrite the content of the existing message.

class Foo extends DynamicMessage {
  public render() {
    return 'stuff';
  }
}

client.on('message', (msg) => {
  const reply = msg.reply('tmp');

  // Attach in the same way as DynamicMessage#sendTo
  new Foo().attachTo(reply);

  // Attach in the same way as DynamicMessage#replyTo
  new Foo().attachTo(reply, msg.author);
})

OnInit

type OnInit = Decorator<() => void>

OnInit is a decorator that tells the dynamic message what functions to call when a discord text message is attached to the dynamic message. Note that if the dynamic message is reused (aka attached to another discord text message after the first one) the init function will fire again.

class Foo extends DynamicMessage {

  @OnInit
  public initialize() {
    console.log(this.message.content);
    // => stuff
  }

  public render() {
    return 'stuff';
  }
}

OnReaction

type OnReaction = (emoji: string, config?:IReactionConfig) => Decorator<(user: Discord.User, channel: Discord.Channel, reaction: Discord.Reaction) => void>

OnReaction is a decorator that tells the dynamic message what functions to call in response to what emoji when a reaction is made on the corresponding "discord text message".

interface IReactionConfig {

  // (default: false) when false the bot will react with the given emoji to show the users what emoji the message is prepared to react to.
  hidden?: boolean;
  
  // (default: true) when true the bot will call the render method of the dynamic message after the reaction callback have executed.
  triggerRender?: boolean;
  
  // (default: true) when true the bot will remove user reactions after the callback have executed.
  removeWhenDone?: boolean;
  
  // (default: true) should reactions from bots trigger this callback?
  ignoreBots?: boolean;
  
  // (default: false) should reactions from humans trigger this callback?
  ignoreHumans?: boolean;

  // (default: true) should reactions made while the bot was offline / not setup trigger this callback
  doRetroactiveCallback?: boolean;
 }
class Foo extends DynamicMessage {

  @OnReaction(':thumbsup:')
  public react(user, channel, reaction) {
    console.log('WOW!');
  }

  public render() {
    return 'stuff';
  }
}

OnReactionRemoved

type OnReactionRemoved = (emoji: string, config?:IReactionRemovedConfig) => Decorator<(user: Discord.User, channel: Discord.Channel, reaction: Discord.Reaction) => void>

OnReactionRemoved is a decorator that tells the dynamic message what functions to call in response to what emoji when a reaction removed from the corresponding "discord text message".

interface IReactionRemovedConfig {
  
  // (default: true) when true the bot will call the render method of the dynamic message after the reaction callback have executed.
  triggerRender?: boolean;
  
  // (default: true) should reactions from bots trigger this callback?
  ignoreBots?: boolean;
  
  // (default: false) should reactions from humans trigger this callback?
  ignoreHumans?: boolean;
 }
class Foo extends DynamicMessage {
  private toggle: boolean = false;

  @OnReaction(":thumbsup:", {
    removeWhenDone: false,
  })
  public on() {
    this.toggle = true;
  }

  @OnReactionRemoved(":thumbsup:")
  public off() {
    this.toggle = false;
  }

  public render() {
    return '```diff\n' + (this.toggle ? '+ on' : '- off') + '\n```';
  }
}

OnAnyReaction

type OnAnyReaction = (config?:ICatchAllConfig) => Decorator<(user: Discord.User, channel: Discord.Channel, reaction: Discord.Reaction) => void>

OnAnyReaction is a decorator that tells the dynamic message what functions to call when any reaction is made on the corresponding "discord text message".

interface ICatchAllConfig {

  // (default: true) when true the bot will call the render method of the dynamic message after the reaction callback have executed.
  triggerRender?: boolean;
  
  // (default: true) should reactions from bots trigger this callback?
  ignoreBots?: boolean;
  
  // (default: false) should reactions from humans trigger this callback?
  ignoreHumans?: boolean;
 }
export class Foo extends DynamicMessage {
  private accumulator: string = '';

  @OnAnyReaction()
  public accumulate(user, channel, reaction) {
    this.accumulator += reaction.emoji.name;
  }

  public render() {
    return `Accumulator: ${this.addAccumulator}`;
  }
}

OnAnyReactionRemoved

type OnAnyReactionRemoved = (config?:ICatchAllConfig) => Decorator<(user: Discord.User, channel: Discord.Channel, reaction: Discord.Reaction) => void>

OnAnyReaction is a decorator that tells the dynamic message what functions to call when any reaction is removed from the corresponding "discord text message".

interface ICatchAllConfig {

  // (default: true) when true the bot will call the render method of the dynamic message after the reaction callback have executed.
  triggerRender?: boolean;
  
  // (default: true) should reactions from bots trigger this callback?
  ignoreBots?: boolean;
  
  // (default: false) should reactions from humans trigger this callback?
  ignoreHumans?: boolean;
 }
export class Foo extends DynamicMessage {
  private accumulator: string = '';

  @OnAnyReactionRemoved()
  public accumulate(user, channel, reaction) {
    this.accumulator += reaction.emoji.name;
  }

  public render() {
    return `Accumulator: ${this.addAccumulator}`;
  }
}

Demos

See the /demo folder

Development

  1. Grab your discord-bot secret from the discord developer portal.
  2. Create a secrets.json file and store your discord-bot secret as discord_token inside it.
  3. Install dependencies: npm i.
  4. Start demo: npm run demo.