-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
1,391 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
--- | ||
kind: pipeline | ||
type: docker | ||
name: backend | ||
|
||
steps: | ||
- name: build | ||
image: golang:latest | ||
volumes: | ||
- name: deps | ||
path: /go | ||
commands: | ||
- make | ||
|
||
- name: linter | ||
image: golang:latest | ||
volumes: | ||
- name: deps | ||
path: /go | ||
commands: | ||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.32.2 | ||
- ./bin/golangci-lint run | ||
|
||
- name: telegram | ||
image: appleboy/drone-telegram | ||
settings: | ||
to: 790376882 | ||
format: markdown | ||
token: | ||
from_secret: telegram_token | ||
message: > | ||
*{{repo.name}}* | ||
[Build {{build.number}}]({{build.link}}) by {{commit.author}} {{#success build.status}}succeeded{{else}}failed{{/success}} in {{buildtime build.started}} | ||
`{{truncate commit.sha 8}}`: "{{commit.message}}" | ||
volumes: | ||
- name: deps | ||
host: | ||
path: /var/lib/cache/godeps/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,3 +13,5 @@ | |
|
||
# Dependency directories (remove the comment below to include it) | ||
# vendor/ | ||
conf.yml | ||
fox |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
.DEFAULT_GOAL := build | ||
|
||
export GO111MODULE=on | ||
export CGO_ENABLED=0 | ||
export VERSION=$(shell git describe --abbrev=0 --tags 2> /dev/null || echo "0.1.0") | ||
export BUILD=$(shell git rev-parse HEAD 2> /dev/null || echo "undefined") | ||
BINARY=fox | ||
LDFLAGS=-ldflags "-X main.Version=$(VERSION) -X main.Build=$(BUILD) -s -w" | ||
|
||
.PHONY: help | ||
help: | ||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' | ||
|
||
.PHONY: build | ||
build: ## Build | ||
go build $(LDFLAGS) -o $(BINARY) | ||
|
||
.PHONY: compressed | ||
compressed: fullbuild | ||
upx --brute $(BINARY) | ||
|
||
.PHONY: docker | ||
docker: ## Build the docker image | ||
docker build -t $(BINARY):latest -t $(BINARY):$(BUILD) \ | ||
--build-arg build=$(BUILD) --build-arg version=$(VERSION) \ | ||
-f Dockerfile . | ||
|
||
.PHONY: lint | ||
lint: ## Runs the linter | ||
$(GOPATH)/bin/golangci-lint run --exclude-use-default=false | ||
|
||
.PHONY: test | ||
test: ## Run the test suite | ||
CGO_ENABLED=1 go test -race -coverprofile="coverage.txt" ./... | ||
|
||
.PHONY: clean | ||
clean: ## Remove the binary | ||
if [ -f $(BINARY) ] ; then rm $(BINARY) ; fi | ||
if [ -f coverage.txt ] ; then rm coverage.txt ; fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,10 @@ | ||
# fox | ||
Discord bot playing your Soundcloud musics and playlists in a voice channel | ||
|
||
[![Build Status](https://drone.depa.do/api/badges/Depado/fox/status.svg)](https://drone.depa.do/Depado/fox) | ||
|
||
|
||
## Note | ||
|
||
This project is still in an early phase and helps with the amelioration of the | ||
[github.com/Depado/soundcloud](https://github.com/Depado/soundcloud) lib. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package bot | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math/rand" | ||
"time" | ||
|
||
"github.com/Depado/fox/cmd" | ||
"github.com/Depado/soundcloud" | ||
"github.com/bwmarrin/discordgo" | ||
"github.com/rs/zerolog" | ||
"go.uber.org/fx" | ||
) | ||
|
||
type BotInstance struct { | ||
conf *cmd.Conf | ||
log *zerolog.Logger | ||
Session *discordgo.Session | ||
Soundcloud *soundcloud.Client | ||
Voice *discordgo.VoiceConnection | ||
Player *Player | ||
} | ||
|
||
func NewBotInstance(lc fx.Lifecycle, c *cmd.Conf, log *zerolog.Logger, sc *soundcloud.Client) *BotInstance { | ||
rand.Seed(time.Now().UnixNano()) | ||
dg, err := discordgo.New("Bot " + c.Bot.Token) | ||
if err != nil { | ||
log.Fatal().Err(err).Msg("unable to init") | ||
} | ||
dg.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAllWithoutPrivileged) | ||
if err := dg.Open(); err != nil { | ||
log.Fatal().Err(err).Msg("unable to open") | ||
} | ||
|
||
voice, err := dg.ChannelVoiceJoin(c.Bot.Guild, c.Bot.Channels.Voice, false, true) | ||
if err != nil { | ||
log.Fatal().Err(err).Msg("unable to initiate voice connection") | ||
} | ||
|
||
b := &BotInstance{ | ||
conf: c, | ||
log: log, | ||
Soundcloud: sc, | ||
Session: dg, | ||
Voice: voice, | ||
Player: &Player{tracks: soundcloud.Tracks{}}, | ||
} | ||
b.Session.AddHandler(b.MessageCreated) | ||
|
||
lc.Append(fx.Hook{ | ||
OnStop: func(ctx context.Context) error { | ||
b.log.Debug().Msg("cleanup") | ||
if b.Player.playing { | ||
b.Player.stop = true | ||
b.Player.session.Stop() // nolint:errcheck | ||
b.Player.session.Cleanup() | ||
} | ||
b.Voice.Close() | ||
b.Session.Close() | ||
return nil | ||
}, | ||
}) | ||
|
||
return b | ||
} | ||
|
||
// Start is a simple function invoked by fx to bootstrap the dependecy chain | ||
func Start(l *zerolog.Logger, b *BotInstance) { | ||
l.Info().Msg("Bot is now running") | ||
} | ||
|
||
// SalvageVoice will attempt to disconnect and reconnect to the vocal channel | ||
func (b *BotInstance) SalvageVoice() error { | ||
if b.Voice != nil { | ||
if err := b.Voice.Disconnect(); err != nil { | ||
return fmt.Errorf("unable to disonncet vocal channel: %w", err) | ||
} | ||
} | ||
|
||
voice, err := b.Session.ChannelVoiceJoin(b.conf.Bot.Guild, b.conf.Bot.Channels.Voice, false, true) | ||
if err != nil { | ||
return fmt.Errorf("unable to establish connection to vocal channel: %w", err) | ||
} | ||
b.Voice = voice | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package bot | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
"time" | ||
|
||
"github.com/Depado/soundcloud" | ||
"github.com/bwmarrin/discordgo" | ||
"github.com/hako/durafmt" | ||
"github.com/rs/zerolog/log" | ||
) | ||
|
||
func (b *BotInstance) SendNowPlaying(t soundcloud.Track) { | ||
e := &discordgo.MessageEmbed{ | ||
Title: t.Title, | ||
URL: t.PermalinkURL, | ||
Author: &discordgo.MessageEmbedAuthor{ | ||
IconURL: t.User.AvatarURL, | ||
Name: t.User.Username, | ||
URL: t.User.PermalinkURL, | ||
}, | ||
Thumbnail: &discordgo.MessageEmbedThumbnail{URL: t.ArtworkURL}, | ||
Description: "**Now Playing**", | ||
Color: 0xff5500, | ||
Fields: []*discordgo.MessageEmbedField{ | ||
{Name: "Plays", Value: strconv.Itoa(t.PlaybackCount), Inline: true}, | ||
{Name: "Likes", Value: strconv.Itoa(t.LikesCount), Inline: true}, | ||
{Name: "Reposts", Value: strconv.Itoa(t.RepostsCount), Inline: true}, | ||
{Name: "Duration", Value: durafmt.Parse(time.Duration(t.Duration) * time.Millisecond).LimitFirstN(2).String(), Inline: true}, | ||
}, | ||
} | ||
|
||
_, err := b.Session.ChannelMessageSendEmbed(b.conf.Bot.Channels.Public, e) | ||
if err != nil { | ||
log.Err(err).Msg("unable to send embed") | ||
} | ||
} | ||
|
||
func (b *BotInstance) DisplayQueue(m *discordgo.MessageCreate) { | ||
b.Player.tracksM.Lock() | ||
defer b.Player.tracksM.Unlock() | ||
|
||
var body string | ||
var tot int | ||
if len(b.Player.tracks) > 0 { | ||
for i, t := range b.Player.tracks { | ||
if i <= 10 { | ||
body += fmt.Sprintf("[%s - %s](%s)\n", t.Title, t.User.Username, t.PermalinkURL) | ||
} | ||
tot += t.Duration | ||
} | ||
if len(b.Player.tracks) > 10 { | ||
body += fmt.Sprintf("\nAnd **%d** other tracks", len(b.Player.tracks)-10) | ||
} | ||
} else { | ||
body = "There is currently no track in queue" | ||
} | ||
|
||
e := &discordgo.MessageEmbed{ | ||
Title: "Current Queue", | ||
Description: body, | ||
Color: 0xff5500, | ||
Fields: []*discordgo.MessageEmbedField{ | ||
{Name: "Tracks", Value: strconv.Itoa(len(b.Player.tracks)), Inline: true}, | ||
{Name: "Duration", Value: durafmt.Parse(time.Duration(tot) * time.Millisecond).LimitFirstN(2).String(), Inline: true}, | ||
}, | ||
Footer: &discordgo.MessageEmbedFooter{ | ||
Text: fmt.Sprintf("Tip: Add new tracks using '%s add' or '%s a'", b.conf.Bot.Prefix, b.conf.Bot.Prefix), | ||
}, | ||
} | ||
_, err := b.Session.ChannelMessageSendEmbed(m.ChannelID, e) | ||
if err != nil { | ||
log.Err(err).Msg("unable to send embed") | ||
} | ||
} | ||
|
||
func (b *BotInstance) SendPublicMessage(title, body string) { | ||
b.SendNotice(title, body, "", b.conf.Bot.Channels.Public) | ||
} | ||
|
||
func (b *BotInstance) SendControlMessage(title, body string) { | ||
b.SendNotice(title, body, "", b.conf.Bot.Channels.Control) | ||
} | ||
|
||
func (b *BotInstance) SendNotice(title, body, footer string, channel string) { | ||
e := &discordgo.MessageEmbed{ | ||
Title: title, | ||
Description: body, | ||
Footer: &discordgo.MessageEmbedFooter{Text: footer}, | ||
Color: 0xff5500, | ||
} | ||
_, err := b.Session.ChannelMessageSendEmbed(channel, e) | ||
if err != nil { | ||
log.Err(err).Msg("unable to send embed") | ||
} | ||
} | ||
|
||
func (b *BotInstance) SendNamedNotice(m *discordgo.MessageCreate, prefix, title, body, footer string) { | ||
e := &discordgo.MessageEmbed{ | ||
Title: title, | ||
Description: body, | ||
Fields: []*discordgo.MessageEmbedField{ | ||
{Name: prefix, Value: fmt.Sprintf("<@%s>", m.Author.ID)}, | ||
}, | ||
Footer: &discordgo.MessageEmbedFooter{Text: footer}, | ||
Color: 0xff5500, | ||
} | ||
_, err := b.Session.ChannelMessageSendEmbed(m.ChannelID, e) | ||
if err != nil { | ||
log.Err(err).Msg("unable to send embed") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package bot | ||
|
||
var QueueDoc = `!fox <q|queue> : Displays the current queue (todo) | ||
!fox <q|queue> <soundcloud track or playlist URL> : Adds to queue` | ||
|
||
// var QueueDoc = &discordgo.MessageEmbed{ | ||
|
||
// } |
Oops, something went wrong.