Code Monkey home page Code Monkey logo

popple's Introduction

Popple

A karma bot for Discord.

Usage

Command Values Description
@Popple announce on, off, yes, no Whether or not Popple will print a subject's karma level after it has been modified
@Popple karma Something with karma Prints the subjects' karma level. Multiple subjects' karma levels may be checked
@Popple bot Integer > 0 Prints the n subjects with the least karma. The default value is 10 if a value is not supplied
@Popple top Integer > 0 Prints the top n subjects with the most karma. The default value is 10 if a value is not supplied
Subject++ N/A Increases Subject's karma
Subject-- N/A Decreases Subject's karma
(Subject with space or - +) N/A Parentheses may be used for complicated subjects with whitespace or special symbols

Once Popple has joined a Discord server, it will watch for karma events in the chat. Increase or decrease karma by suffixing the subject with a ++ or a --, respectively.

For example,

Person) Thanks for being so neat, Popple++!
Popple) Popple has 1 karma.

Popple will ignore "net-zero" operations on karma.

Person) Popple++ Popple--

*crickets*

A message can have any number of karma events for any number of subjects:

Person) PoeThePotatoPirate++ Popple-- HelloWorld--
Popple) PoeThePotatoPirate has 2 karma. Popple has 3 karma. HelloWorld has -2 karma.

Parentheses may be used for more complicated karma subjects, including those with whitespace, ticks, or other parentheses in their name.

Person) (Poe the Potato Pirate)++ (meme-bot)++
Popple) Poe the Potato Pirate has 2 karma. meme-bot has 2 karma.

Karma levels can be checked without requiring any karma events:

Person) @Popple karma Popple
Popple) Popple has 3 karma.
Person) @Popple karma DoesNotExist
Popple) DoesNotExist has 0 karma.

The above could be combined into one command like so:

Person) @Popple karma Popple DoesNotExist
Popple) Popple has 3 karma. DoesNotExist has 0 karma.

By default, Popple will announce a subject's karma level after it is modified. This behavior can be disabled. Karma levels may still be checked with the karma command.

Person) @Popple announce off
Person) Person++

*crickets*

Or

Person) @Popple announce no
Person) Person++

*crickets*

It can be turned back on with @Popple announce yes or @Popple announce on.

popple's People

Contributors

connorkuehl avatar dependabot[bot] avatar krishnaindani avatar nathannaveen avatar peschkaj avatar pradeepnnv avatar shoebsd31 avatar uttkarsh avatar vrbalu avatar willmadison avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

popple's Issues

Adapt control structures to use short statements where applicable

In Go, a statement can precede a conditional in an if-statement. Refactor structures like this to use those to constrain the scope of variables to the if-else-blocks where appropriate.

I.e.,

diff --git a/command.go b/command.go
index 3dc4f75..94da1a5 100644
--- a/command.go
+++ b/command.go
@@ -46,8 +46,7 @@ func CheckKarma(ctx *Context) {
                sep = " "
        }
 
-       _, err := s.ChannelMessageSend(m.ChannelID, reply.String())
-       if err != nil {
+       if _, err := s.ChannelMessageSend(m.ChannelID, reply.String()); err != nil {
                log.Printf("Error when sending reply to channel: %s\n", err)
        }
 }

Convert all type visibilities to package private

None of these types are exported outside of Popple and therefore, to be consistent, all types should be made package-private.

To do this, just look for functions, types, and constants that start with an uppercase letter and make it a lowercase
letter.

Add a version subcommand

This way, people can ask the bot what version it is.

I.e., @Popple version

Persion) @Popple version
Popple) 1.0.0

Truncate to nearest time.Second when printing uptime

Right now, uptime prints a time.Duration with a huge fractional component. That level of precision is unnecessary. Truncating to a time.Second should allow us to print something like 1h45m3s instead of 1h45m3.234234s.

$ go doc time.Duration.Truncate
package time // import "time"

func (d Duration) Truncate(m Duration) Duration
    Truncate returns the result of rounding d toward zero to a multiple of m. If
    m <= 0, Truncate returns d unchanged.

Karma event parsed from code fence when it shouldn't be

From this message:

error[E0277]: the trait bound `&T: codicon::Read` is not satisfied
    --> src/attest/qemu/mod.rs:62:50
     |
62   |         let query_sev: qmp::Return = from_reader(self).unwrap();
     |                                                  ^^^^ the trait `codicon::Read` is not implemented for `&T`
     | 
    ::: /home/ckuehl/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.59/src/de.rs:2499:8
     |
2499 |     R: crate::io::Read,
     |        --------------- required by this bound in `from_reader`
     |
     = note: `codicon::Read` is implemented for `&mut T`, but not for `&T`
help: consider extending the `where` bound, but there might be an alternative better way to express this requirement
     |
59   |     T: std::io::Read + std::io::Write, &T: codicon::Read
     |                                      ^^^^^^^^^^^^^^^^^^^

Popple says:

------------- has -1 karma.

Remove dependency on GORM

Should be sufficient to just use the sql driver and sql statements. I would still like to retain the AutoMigrate functionality if possible.

Write MANUAL.md

This will replace parts of the README.md. This should be a task-driven how-to document that describes:

  • A pointer to how to create a Discord bot and get a bot token
  • Deploying Popple as a container
  • Deploying Popple as a systemd unit
  • Backing up the Popple database
  • and other helpful things if thought of later

Bot loses connection to Discord

2021/08/13 06:46:44 [DG0] wsapi.go:82:Open() error connecting to gateway wss://gateway.discord.gg/?v=8&encoding=json, dial tcp: lookup gateway.discord.gg on 67.207.67.3:53: read udp 10.88.0.8:57565->67.207.67.3:53: read: no route to host
2021/08/13 06:46:44 [DG0] wsapi.go:835:reconnect() error reconnecting to gateway, dial tcp: lookup gateway.discord.gg on 67.207.67.3:53: read udp 10.88.0.8:57565->67.207.67.3:53: read: no route to host

More investigation is needed. Could be Popple, discordgo, container network configuration, or host network configuration. Probably not Discord's API, since my friend's bot in that same server seemed to have remained online.

Clean up the shutdown logic in cmd/discord/popple/main.go

The worker shutdown is kind of onerous. Instead of tracking how many workers have returned, use a sync.WaitGroup instead.

However, it's not sufficient to just wait for wg.Done() since that will prevent us from quitting even if the deadline has passed, so you might consider something like:

    workersDone := make(chan struct{})
    go func() {
        wg.Wait()
        close(workersDone)
    }()
    
    select {
        case <- deadline:
            // emit warning blah
        case <- workersDone:
            // emit that all workers are done
    }

Rename command.Request GuildID field to ServerID

Any application-specific implementation details should be handled by the respective cmd/implementation/popple command. The top-level Popple package should provide a good-enough interface such that it doesn't need to know about anything implementation-specific.

Rename the command.Request struct's GuildID field to ServerID.

Good First Issues for Newer Contributors

  • Run golint and fix any warnings
  • Tackle any issues with the refactoring or good first issue labels
  • Add test cases to files ending in _test.go
  • Add doc comments to exported symbols in packages
  • Run your own instance of the Popple bot and report any issues or feature requests

Switch "deadline" command line argument from uint to time.Duration

Right now, the "deadline" flag is a uint and converted to a Duration later on.

    timeout := flag.Uint("deadline", 3, "seconds to wait for workers to exit when shutting down")

It looks like the flag package supports Duration types out of the box (rest of output omitted for brevity)

$ go doc flag
func Duration(name string, value time.Duration, usage string) *time.Duration

Change it.

Re-document ARCHITECTURE.md

Development has slowed down and Popple has stabilized, but has changed a lot since ARCHITECTURE.md was written.

Update it to show how various components of Popple work. Things like how it is a primarily event driven application, the work queue, the router, the purpose of the _testing.go files.

Remove the net karma stuff

Being able to chain arbitrary amounts of increments and decrements is kind of an anti-feature and useless.

I.e., remove the ability to do Popple++--++ = Popple += 2. Just parse a number of ++ or a number of -- but not both.

The router should match a command only if the verb is followed by a space or EOF

Right now, the router's route method just uses strings.HasPrefix to determine if the message contains a command.

This means it's possible to concatenate a valid command with garbage:

Person) @Popple helpasdf
Popple) *sends help text*

It's not exactly a bug, since it won't technically hurt anything, but "helpasdf" is also technically not "help".

Fix this.

Add "uptime" subcommand

Person) @Popple uptime
Popple) 2 weeks, 4 days, and 12 hours

The format doesn't have to be the same in the example above.

  • Add func uptime(req request, rsp responseWriter, db *gorm.DB, started time.Time) to command.go
  • Add a route to the router in popple.go can probably get time.Now() in func main and access it via the closure passed into addRoute
  • Add unit tests for func uptime in command_test.go
  • Document this in README.md

Regression: karma subcommand never parses subjects

func ParseSubjects won't include subjects with zero karma in its result but func CheckKarma relies on this behavior.

Right now, the workaround is to invoke the karma subcommand and put an arbitrary increment/decrement against each subject:

Person) @Popple karma asdf++ potato--
Popple) asdf has 3 karma. potato has 0 karma.

This will require changes to most of parse.go.

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.