Git Product home page Git Product logo

catnip's Introduction

PROJECT STATUS

This project is no longer maintained. I don't have time to maintain it anymore, and I don't really use Discord's API much anymore anyway. If you want to maintain this library, please see issue #729.

catnip

Github Actions -- tests Github Actions -- docs powered by potato GitHub tag (latest by date) LGTM Grade

A Discord API wrapper in Java. Fully async / reactive, built on top of RxJava. catnip tries to map roughly 1:1 to how the Discord API works, both in terms of events and REST methods available. catnip uses Java 17+.

catnip is part of the amyware Discord server.

Licensed under the BSD 3-Clause License.

Installation

Get it on Jitpack

Current version: GitHub tag (latest by date)

Can I just download a JAR directly?

No. Use a real build tool like Maven or Gradle.

Javadocs?

Get them here.

Features

Basic usage

This is the simplest possible bot you can make right now:

final Catnip catnip = Catnip.catnip("your token goes here");
catnip.observable(DiscordEvent.MESSAGE_CREATE)
    .filter(msg -> msg.content().equals("!ping"))
    .subscribe(msg -> {
        msg.respond("pong!");
    }, error -> error.printStackTrace());
catnip.connect();

catnip returns RxJava operators (Completable/Observable/Single/...) from all REST methods. For example, editing your ping message to include time it took to create the message:

final Catnip catnip = Catnip.catnip("your token goes here");
catnip.observable(DiscordEvent.MESSAGE_CREATE)
        .filter(msg -> msg.content().equals("!ping"))
        .subscribe(msg -> {
            long start = System.currentTimeMillis();
            msg.respond("pong!")
                    .subscribe(ping -> {
                        long end = System.currentTimeMillis();
                        ping.edit("pong! (took " + (end - start) + "ms).");
                    });
        }, error -> error.printStackTrace());
catnip.connect();

You can also create a catnip instance asynchronously:

Catnip.catnipAsync("your token here").subscribe(catnip -> {
    catnip.observable(DiscordEvent.MESSAGE_CREATE)
        .filter(msg -> msg.content().equals("!ping"))
        .subscribe(msg -> {
            msg.respond("pong!");
        }, error -> error.printStackTrace());
    catnip.connect();
});

Also check out the examples for Kotlin and Scala usage.

A note on Observable#subscribe vs. Observable#forEach

Observable#forEach seems like the obvious way to use the reactive methods, but as it turns out, it's also the wrong thing to do. Observable#forEach is generally intended for finite streams of data; the events that catnip emits aren't finite, and as such, Observable#forEach isn't the correct tool to use. In addition, Observable#forEach will stop processing events if an uncaught exception is thrown. Instead, you should use Observable#subscribe(eventCallback, exceptionCallback), which will handle exceptions properly.

Modular usage

catnip supports being used in REST-only or shards-only configurations. The nice thing about catnip is that using it like this is exactly the same as using it normally. The only difference is that to use catnip in REST-only mode, you don't call catnip.connect() and use catnip.rest().whatever() instead.

RxJava schedulers

By default, RxJava's Observable#subscribe() and related methods will not operate on any particular scheduler by default. That is, they will run on the calling thread. catnip will automatically subscribe RxJava objects onto a scheduler provided by catnip, that defaults to being a ForkJoinPool-based scheduler. You can customize the scheduler used with the corresponding option in CatnipOptions.

Useful extensions

Why write a fourth Java lib?

  • I didn't want ten billion events for every possible case. catnip maps more/less 1:1 with the Discord API, and any "extra" events on top of that need to be user-provided via extensions or other means. I guess really I just didn't want my lib to be as "high-level" as other libs are.
  • I wanted to try to maximize extensibility / customizability, beyond just making it modular. Things like being able to intercept raw websocket messages (as JSON), write custom distributed cache handlers, ... are incredibly useful.
  • I like everything returning Rx classes instead of custom Future-like classes. I do get why other libs have them, I just wanted to not.
  • I wanted modular usage to be exactly the same more / less no matter what; everything should be doable through the catnip instance that you create.
  • I wanted to make a lib built on RxJava.
  • To take over the world and convert all Java bots. :^)

catnip's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

catnip's Issues

Properly calculate REST request latency

This isn't a big thing per se, just would be better for the end-user experience. Request latency should be factored into REST ratelimit reset time because the 500ms pause we currently use may be too {slow,fast} depending on a number of circumstances.

REST API Coverage

Gateway

  • Get gateway bot There basically since the beginning

Channels

  • Create message Complete as of 744e124
  • Delete channel Added in b1c34ef
  • Get channel Added in b1c34ef
  • Modify channel Added in 14a15d7
  • Get channel invites Added in 13a9181
  • Create channel invite Added in 13a9181
  • Get channel messages Added in 12c09be
  • Bulk delete messages Added in ec0c23a
  • Delete message Added in 1f85f7c
  • Get channel message Added in 29e0537
  • Edit message Added in 8e2dcdc
  • Delete all reactions Added in ec0c23a
  • Get reactions Added in ec0c23a
  • Delete own reaction Added in 61b60ce
  • Create reaction Added in 5bb963d
  • Delete channel permission Added in ec0c23a
  • Edit channel permissions Added in ec0c23a
  • Get pinned messages Added in ec0c23a
  • Delete pinned channel message Added in ec0c23a
  • Add pinned channel message Added in ec0c23a
  • Trigger typing indicator Added in 4f56d96
  • Get channel webhooks Added in 403f2ad
  • Create webhook~~ Added in ec0c23a

Guilds

  • Create guild Added in 2017bac
  • Delete guild Added in 2017bac
  • Get guild Added in e3c68fa
  • Modify guild Added in 14a15d7
  • Get guild audit log Added in 81548bf
  • Get guild bans Added in adbd138
  • Get guild ban Added in 5818ad4
  • Remove guild ban Added in 842ed41
  • Create guild ban Added in 7ebd294
  • Get guild channels Added in 2017bac
  • Modify guild channel positions
  • Create guild channel
  • Get guild embed
  • Modify guild embed
  • Get guild integrations Probably not needed
  • Create guild integration Probably not needed
  • Delete guild integration Probably not needed
  • Modify guild integration Probably not needed
  • Sync guild integration Probably not needed
  • Get guild invites Added in 13a9181
  • List guild members Added in ac49864
  • Modify current user's nick Added in 549e71e
  • Remove guild member Added in 930c543
  • Get guild member Added in 3754719
  • Modify guild member
  • Add guild member Requires OAuth, which is currently a non-goal
  • Remove guild member role Added in 6b969ca
  • Add guild member role Added in 2970b70
  • Get guild prune count Added in 88b0fe1
  • Begin guild prune Added in 667facb
  • Get guild voice regions Added in 3a29123
  • Get guild roles Added in efd612c
  • Modify guild role positions
  • Create guild role
  • Delete guild role
  • Modify guild role
  • Get guild webhooks Added in 403f2ad

Webhooks

Invites

User

  • Get current user Added in ac2dae0
  • Modify current user Added in 8e28092
  • Get user DMs Not used for bots anymore
  • Create DM Added in b1c34ef
  • Leave guild Added in 2017bac
  • Get user Added in efd612c

Misc

  • Get current application information Added in d9889d6
  • List voice regions Added in 2017bac

Add support for all DISPATCH events

Fix bad RESUME logic

Sometimes - but only sometimes - when a shard disconnects, after it RESUMEs it will fail(?) at doing proper heartbeat detection and close the websocket connection, even if it isn't necessary to do so.

Better abstractions for custom shard managers

Right now, the DefaultShardManager implementation is heavily dependent on knowing how shards work internally, which isn't ideal. We should provide a friendlier interface to this if at all possible.

Add option(s) to prevent firing event objects

In some cases (eg. just listening on raw websocket events and doing something with them), it may be undesirable to waste cpu/memory on creating and firing events that won't be used ever.

Add proper event buffering to allow caching later on

Effectively this means optional support for event buffering while streaming guilds after we receive a READY DISPATCH event.

Things to figure out:

  • Some kind of EventBuffer standard
  • Implementations for caching-buffering and noop-buffering
  • Have an instance per shard, or globally?
  • Figure out nice way to attach shard data to gateway payloads for buffering correctness

Unit-test the REST ratelimiter

This is more complicated than the existing ratelimiter tests, but is a good idea to make sure it works as expected without potentially spamming the API.

Allow disabling individual events

In some cases, it is desirable that we recv. all the events from the gateway, and emit proper objects, but don't emit certain events. For example, I personally don't like PRESENCE_UPDATE and don't want to decode it to an object ever, but need it for cache updates.

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.