fixup! Initial commit
parent
d25655ef4a
commit
ef2d568a6e
60
events.go
60
events.go
|
@ -3,7 +3,9 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"dndmusicbot/ffmpeg"
|
"dndmusicbot/ffmpeg"
|
||||||
|
"dndmusicbot/loop"
|
||||||
discordspeaker "dndmusicbot/speaker"
|
discordspeaker "dndmusicbot/speaker"
|
||||||
|
"dndmusicbot/ytdl"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
@ -40,8 +42,10 @@ func init() {
|
||||||
app.events.On("preload_song", app.preloadSong)
|
app.events.On("preload_song", app.preloadSong)
|
||||||
app.events.On("song_over", app.songOver)
|
app.events.On("song_over", app.songOver)
|
||||||
//app.events.On("song_position", app.songPosition)
|
//app.events.On("song_position", app.songPosition)
|
||||||
|
|
||||||
app.events.On("ambiance_play", app.ambiancePlay)
|
app.events.On("ambiance_play", app.ambiancePlay)
|
||||||
app.events.On("ambiance_stop", app.ambianceStop)
|
app.events.On("ambiance_stop", app.ambianceStop)
|
||||||
|
app.events.On("ambiance_add", app.ambianceAdd)
|
||||||
|
|
||||||
app.events.On("stop", app.stop)
|
app.events.On("stop", app.stop)
|
||||||
app.events.On("next", app.nextSong)
|
app.events.On("next", app.nextSong)
|
||||||
|
@ -127,7 +131,9 @@ func (app *App) ambiancePlay(payload ...interface{}) {
|
||||||
if app.ambiance.IsPlaying() {
|
if app.ambiance.IsPlaying() {
|
||||||
app.ambiance.Reset()
|
app.ambiance.Reset()
|
||||||
}
|
}
|
||||||
app.ambiance.Add(play)
|
|
||||||
|
loop := loop.Loop(-1, play)
|
||||||
|
app.ambiance.Add(loop)
|
||||||
discordspeaker.Unlock()
|
discordspeaker.Unlock()
|
||||||
|
|
||||||
msg := make(map[string]interface{})
|
msg := make(map[string]interface{})
|
||||||
|
@ -153,6 +159,48 @@ func (app *App) ambianceStop(payload ...interface{}) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *App) ambianceAdd(payload ...interface{}) {
|
||||||
|
if !(len(payload) > 0) {
|
||||||
|
log.Println("addPlaylist called without a payload.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("ambiance_add event received")
|
||||||
|
|
||||||
|
var data map[string]string
|
||||||
|
switch js := payload[0].(type) {
|
||||||
|
case json.RawMessage:
|
||||||
|
json.Unmarshal(js, &data)
|
||||||
|
default:
|
||||||
|
log.Println("newPlaylist called with invalid payload.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
amburl, ok := data["url"]
|
||||||
|
if !ok {
|
||||||
|
log.Println("addPlaylist without url")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ambtitle, ok := data["title"]
|
||||||
|
if !ok {
|
||||||
|
log.Println("addPlaylist without title")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ytdl.DownloadAmbiance(amburl, ambtitle)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := make(map[string]interface{})
|
||||||
|
out := make(map[string]interface{})
|
||||||
|
msg["event"] = "ambiance_add"
|
||||||
|
out["type"] = ambtitle
|
||||||
|
msg["payload"] = out
|
||||||
|
ws_msg <- msg
|
||||||
|
}
|
||||||
|
|
||||||
func (app *App) songPosition(payload ...interface{}) {
|
func (app *App) songPosition(payload ...interface{}) {
|
||||||
if !app.queue.IsPlaying() {
|
if !app.queue.IsPlaying() {
|
||||||
return
|
return
|
||||||
|
@ -256,16 +304,6 @@ func (app *App) nextSong(payload ...interface{}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
if app.queue.QLen() == 0 {
|
|
||||||
log.Println("retrying...")
|
|
||||||
song = app.GetSong(app.active)
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
discordspeaker.Lock()
|
discordspeaker.Lock()
|
||||||
app.queue.Reset()
|
app.queue.Reset()
|
||||||
app.queue.Add(f)
|
app.queue.Add(f)
|
||||||
|
|
|
@ -24,6 +24,7 @@ type FFmpeg struct {
|
||||||
PMutex *sync.RWMutex
|
PMutex *sync.RWMutex
|
||||||
ProcessState *os.ProcessState
|
ProcessState *os.ProcessState
|
||||||
err chan error
|
err chan error
|
||||||
|
fb chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFFmpeg(uri string, sampleRate int, channels int) (ff *FFmpeg, err error) {
|
func NewFFmpeg(uri string, sampleRate int, channels int) (ff *FFmpeg, err error) {
|
||||||
|
@ -42,6 +43,7 @@ func NewFFmpeg(uri string, sampleRate int, channels int) (ff *FFmpeg, err error)
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RETRY:
|
||||||
ff = new(FFmpeg)
|
ff = new(FFmpeg)
|
||||||
ff.PMutex = &sync.RWMutex{}
|
ff.PMutex = &sync.RWMutex{}
|
||||||
ff.Len = yt.Len
|
ff.Len = yt.Len
|
||||||
|
@ -53,6 +55,7 @@ func NewFFmpeg(uri string, sampleRate int, channels int) (ff *FFmpeg, err error)
|
||||||
ff.Cmd = exec.CommandContext(
|
ff.Cmd = exec.CommandContext(
|
||||||
ctx,
|
ctx,
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
|
"-xerror",
|
||||||
"-i", yt.Url,
|
"-i", yt.Url,
|
||||||
"-f", "s16le",
|
"-f", "s16le",
|
||||||
"-v", "error",
|
"-v", "error",
|
||||||
|
@ -71,18 +74,23 @@ func NewFFmpeg(uri string, sampleRate int, channels int) (ff *FFmpeg, err error)
|
||||||
ff.Out = bytes.NewBuffer(make([]byte, 43920))
|
ff.Out = bytes.NewBuffer(make([]byte, 43920))
|
||||||
ff.Cmd.Stdout = ff.Out
|
ff.Cmd.Stdout = ff.Out
|
||||||
|
|
||||||
ff.Start()
|
exitctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ff *FFmpeg) Start() {
|
|
||||||
go func() {
|
go func() {
|
||||||
ff.Cmd.Start()
|
ff.Cmd.Start()
|
||||||
ff.err <- ff.Cmd.Wait()
|
ff.err <- ff.Cmd.Wait()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-exitctx.Done():
|
||||||
ff.Started = true
|
ff.Started = true
|
||||||
|
case <-ff.err:
|
||||||
|
log.Println("ffmpeg exited early, retry...")
|
||||||
|
goto RETRY
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ff *FFmpeg) Close() error {
|
func (ff *FFmpeg) Close() error {
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -2,8 +2,6 @@ module dndmusicbot
|
||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
replace github.com/3d0c/gmf => /home/steino/dev/go/gmf
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bwmarrin/discordgo v0.26.1
|
github.com/bwmarrin/discordgo v0.26.1
|
||||||
github.com/dpup/gohubbub v0.0.0-20140517235056-2dc6969d22d8
|
github.com/dpup/gohubbub v0.0.0-20140517235056-2dc6969d22d8
|
||||||
|
|
27
js/script.js
27
js/script.js
|
@ -122,12 +122,32 @@ window.onload = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.querySelector("#addambiance").addEventListener("click", (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
output.innerText = ""
|
||||||
|
var title = document.querySelector("#inputambiance > input[name='title']")
|
||||||
|
var url = document.querySelector("#inputambiance > input[name='url']")
|
||||||
|
if (title.value == "" || url.value == "") {
|
||||||
|
output.innerText = "Title or Url is empty!"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
"event": "ambiance_add",
|
||||||
|
"payload": {
|
||||||
|
"title": title.value,
|
||||||
|
"url": url.value
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
submit.addEventListener("click", (e) => {
|
submit.addEventListener("click", (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
output.innerText = ""
|
output.innerText = ""
|
||||||
var title = document.querySelector(".container2 input[name='title'")
|
var title = document.querySelector("#inputplaylist > input[name='title']")
|
||||||
var url = document.querySelector(".container2 input[name='url'")
|
var url = document.querySelector("#inputplaylist > input[name='url']")
|
||||||
if (title.value == "" || url.value == "") {
|
if (title.value == "" || url.value == "") {
|
||||||
output.innerText = "Title or Url is empty!"
|
output.innerText = "Title or Url is empty!"
|
||||||
return
|
return
|
||||||
|
@ -140,6 +160,9 @@ window.onload = function() {
|
||||||
"url": url.value
|
"url": url.value
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
title.innerText = ""
|
||||||
|
url.innerText = ""
|
||||||
})
|
})
|
||||||
|
|
||||||
document.querySelectorAll("#items").forEach(item => item.addEventListener("click", (e) => {
|
document.querySelectorAll("#items").forEach(item => item.addEventListener("click", (e) => {
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<title>D&D Music Bot!</title>
|
<title>D&D Music Bot!</title>
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
|
||||||
<link rel="stylesheet" href="/css/solarized-dark.min.css">
|
<link rel="stylesheet" href="/css/solarized-dark.min.css">
|
||||||
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div><h2 class="bot">Playlists</h2></div>
|
<div><h2 class="bot">Playlists</h2></div>
|
||||||
|
@ -16,17 +16,17 @@
|
||||||
{{ end}}
|
{{ end}}
|
||||||
<div class="item locked" data-id="reset">Stop</div>
|
<div class="item locked" data-id="reset">Stop</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container2">
|
<div id="inputplaylist" class="container2">
|
||||||
<input name="title" type="text" placeholder="Enter name..">
|
<input name="title" type="text" placeholder="Enter name..">
|
||||||
<input name="url" type="text" placeholder="https://youtube.com/playlist?list=...">
|
<input name="url" type="text" placeholder="https://youtube.com/playlist?list=...">
|
||||||
<input id="addplaylist" name="submit" value="Add" type="submit">
|
<input id="addplaylist" name="submit" value="Add" type="submit">
|
||||||
<input id="prev" name="prev" type="button" value="prev">
|
|
||||||
<input id="next" name="next" type="button" value="next">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="container2">
|
<div class="container2">
|
||||||
<p id="output"></p>
|
<p id="output"></p>
|
||||||
</div>
|
</div>
|
||||||
<div id="info" class="container2">
|
<div id="info" class="container2">
|
||||||
|
<input id="prev" name="prev" type="button" value="prev">
|
||||||
|
<input id="next" name="next" type="button" value="next">
|
||||||
<a id="link" style="text-decoration: none;">
|
<a id="link" style="text-decoration: none;">
|
||||||
<span id="channel"></span>
|
<span id="channel"></span>
|
||||||
<span> - </span>
|
<span> - </span>
|
||||||
|
@ -41,6 +41,11 @@
|
||||||
{{ end}}
|
{{ end}}
|
||||||
<div class="item locked" data-id="reset">Stop</div>
|
<div class="item locked" data-id="reset">Stop</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="inputambiance" class="container2">
|
||||||
|
<input name="title" type="text" placeholder="Enter name..">
|
||||||
|
<input name="url" type="text" placeholder="Enter url...">
|
||||||
|
<input id="addambiance" name="submit" value="Add" type="submit">
|
||||||
|
</div>
|
||||||
<!-- The Modal -->
|
<!-- The Modal -->
|
||||||
<div id="waiting" class="modal">
|
<div id="waiting" class="modal">
|
||||||
<!-- Modal content -->
|
<!-- Modal content -->
|
||||||
|
|
23
ytdl/ytdl.go
23
ytdl/ytdl.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
|
@ -45,3 +46,25 @@ func NewYTdl(uri string) (*YTdl, error) {
|
||||||
|
|
||||||
return &YTdl{title, geturl, channel, duration}, nil
|
return &YTdl{title, geturl, channel, duration}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DownloadAmbiance(uri string, name string) error {
|
||||||
|
err := exec.Command(
|
||||||
|
"./bin/yt-dlp_linux",
|
||||||
|
uri,
|
||||||
|
"-x",
|
||||||
|
"--audio-format", "mp3",
|
||||||
|
"--postprocessor-args", "-ar 48000 -ac 2",
|
||||||
|
"--cookies", "./cookies.txt",
|
||||||
|
"--no-call-home",
|
||||||
|
"--no-cache-dir",
|
||||||
|
"--restrict-filenames",
|
||||||
|
"-f", "140",
|
||||||
|
"-o", filepath.Join("./ambiance/", name+".mp3"),
|
||||||
|
).Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue