Store song cache in XDG_CACHE_HOME

This commit is contained in:
Sam Morris 2016-02-23 21:40:41 +00:00
parent 6bea261d68
commit cb9a410caf
7 changed files with 33 additions and 25 deletions

View file

@ -3,3 +3,4 @@ github.com/layeh/gumble/gumble #8b9989d9c4090874546c45ceaa6ff21e95705bc4
github.com/layeh/gumble/gumble_ffmpeg #c9fcce8fc4b71c7c53a5d3d9d48a1e001ad19a19 github.com/layeh/gumble/gumble_ffmpeg #c9fcce8fc4b71c7c53a5d3d9d48a1e001ad19a19
github.com/scalingdata/gcfg #37aabad69cfd3d20b8390d902a8b10e245c615ff github.com/scalingdata/gcfg #37aabad69cfd3d20b8390d902a8b10e245c615ff
github.com/jmoiron/jsonq #7c27c8eb9f6831555a4209f6a7d579159e766a3c github.com/jmoiron/jsonq #7c27c8eb9f6831555a4209f6a7d579159e766a3c
github.com/mildred/go-xdg #96b70c9133fdb4c32f9c551d50455152dea68d73

View file

@ -11,7 +11,6 @@ clean:
install: install:
mkdir -p ~/.mumbledj/config mkdir -p ~/.mumbledj/config
mkdir -p ~/.mumbledj/songs
if [ -f ~/.mumbledj/config/mumbledj.gcfg ]; then mv ~/.mumbledj/config/mumbledj.gcfg ~/.mumbledj/config/mumbledj_backup.gcfg; fi; if [ -f ~/.mumbledj/config/mumbledj.gcfg ]; then mv ~/.mumbledj/config/mumbledj.gcfg ~/.mumbledj/config/mumbledj_backup.gcfg; fi;
cp -u config.gcfg ~/.mumbledj/config/mumbledj.gcfg cp -u config.gcfg ~/.mumbledj/config/mumbledj.gcfg
sed -i 's/YouTube = \"/YouTube = \"'$(YOUTUBE_API_KEY)'/' ~/.mumbledj/config/mumbledj.gcfg sed -i 's/YouTube = \"/YouTube = \"'$(YOUTUBE_API_KEY)'/' ~/.mumbledj/config/mumbledj.gcfg

View file

@ -66,7 +66,7 @@ Command | Description | Arguments | Admin | Example
**setcomment** | Sets the comment for the bot. If no argument is given, the current comment will be removed. | None OR new_comment | Yes | `!setcomment Hello! I am a bot. Type !help for the available commands.` **setcomment** | Sets the comment for the bot. If no argument is given, the current comment will be removed. | None OR new_comment | Yes | `!setcomment Hello! I am a bot. Type !help for the available commands.`
**numcached** | Outputs the number of songs currently cached on disk. | None | Yes | `!numcached` **numcached** | Outputs the number of songs currently cached on disk. | None | Yes | `!numcached`
**cachesize** | Outputs the total file size of the cache in MB. | None | Yes | `!cachesize` **cachesize** | Outputs the total file size of the cache in MB. | None | Yes | `!cachesize`
**kill** | Safely cleans the bot environment and disconnects from the server. Please use this command to stop the bot instead of force closing, as the kill command deletes any remaining songs in the `~/.mumbledj/songs` directory. | None | Yes | `!kill` **kill** | Safely cleans the bot environment and disconnects from the server. Please use this command to stop the bot instead of force closing, as the kill command deletes any remaining songs in the song cache directory. | None | Yes | `!kill`

View file

@ -47,7 +47,7 @@ func NewSongCache() *SongCache {
// GetNumSongs returns the number of songs currently cached. // GetNumSongs returns the number of songs currently cached.
func (c *SongCache) GetNumSongs() int { func (c *SongCache) GetNumSongs() int {
songs, _ := ioutil.ReadDir(fmt.Sprintf("%s/.mumbledj/songs", dj.homeDir)) songs, _ := ioutil.ReadDir(dj.songCacheDir)
return len(songs) return len(songs)
} }
@ -55,7 +55,7 @@ func (c *SongCache) GetNumSongs() int {
// the cache and returns it. // the cache and returns it.
func (c *SongCache) GetCurrentTotalFileSize() int64 { func (c *SongCache) GetCurrentTotalFileSize() int64 {
var totalSize int64 var totalSize int64
songs, _ := ioutil.ReadDir(fmt.Sprintf("%s/.mumbledj/songs", dj.homeDir)) songs, _ := ioutil.ReadDir(dj.songCacheDir)
for _, song := range songs { for _, song := range songs {
totalSize += song.Size() totalSize += song.Size()
} }
@ -83,16 +83,16 @@ func (c *SongCache) Update() {
// the user configuration. // the user configuration.
func (c *SongCache) ClearExpired() { func (c *SongCache) ClearExpired() {
for range time.Tick(5 * time.Minute) { for range time.Tick(5 * time.Minute) {
songs, _ := ioutil.ReadDir(fmt.Sprintf("%s/.mumbledj/songs", dj.homeDir)) songs, _ := ioutil.ReadDir(dj.songCacheDir)
for _, song := range songs { for _, song := range songs {
hours := time.Since(song.ModTime()).Hours() hours := time.Since(song.ModTime()).Hours()
if hours >= dj.conf.Cache.ExpireTime { if hours >= dj.conf.Cache.ExpireTime {
if dj.queue.Len() > 0 { if dj.queue.Len() > 0 {
if (dj.queue.CurrentSong().Filename()) != song.Name() { if (dj.queue.CurrentSong().Filename()) != song.Name() {
os.Remove(fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, song.Name())) os.Remove(fmt.Sprintf("%s/%s", dj.songCacheDir, song.Name()))
} }
} else { } else {
os.Remove(fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, song.Name())) os.Remove(fmt.Sprintf("%s/%s", dj.songCacheDir, song.Name()))
} }
} }
} }
@ -101,13 +101,13 @@ func (c *SongCache) ClearExpired() {
// ClearOldest deletes the oldest item in the cache. // ClearOldest deletes the oldest item in the cache.
func (c *SongCache) ClearOldest() error { func (c *SongCache) ClearOldest() error {
songs, _ := ioutil.ReadDir(fmt.Sprintf("%s/.mumbledj/songs", dj.homeDir)) songs, _ := ioutil.ReadDir(dj.songCacheDir)
sort.Sort(ByAge(songs)) sort.Sort(ByAge(songs))
if dj.queue.Len() > 0 { if dj.queue.Len() > 0 {
if (dj.queue.CurrentSong().Filename()) != songs[0].Name() { if (dj.queue.CurrentSong().Filename()) != songs[0].Name() {
return os.Remove(fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, songs[0].Name())) return os.Remove(fmt.Sprintf("%s/%s", dj.songCacheDir, songs[0].Name()))
} }
return errors.New("Song is currently playing.") return errors.New("Song is currently playing.")
} }
return os.Remove(fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, songs[0].Name())) return os.Remove(fmt.Sprintf("%s/%s", dj.songCacheDir, songs[0].Name()))
} }

View file

@ -11,6 +11,7 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"strconv" "strconv"
"strings" "strings"
@ -355,7 +356,7 @@ func reload(user *gumble.User) {
} }
// reset performs !reset functionality. Clears the song queue, stops playing audio, and deletes all // reset performs !reset functionality. Clears the song queue, stops playing audio, and deletes all
// remaining songs in the ~/.mumbledj/songs directory. // remaining songs in the song cache directory.
func reset(username string) { func reset(username string) {
dj.queue.queue = dj.queue.queue[:0] dj.queue.queue = dj.queue.queue[:0]
if dj.audioStream.IsPlaying() { if dj.audioStream.IsPlaying() {
@ -413,7 +414,7 @@ func setComment(user *gumble.User, comment string) {
dj.SendPrivateMessage(user, COMMENT_UPDATED_MSG) dj.SendPrivateMessage(user, COMMENT_UPDATED_MSG)
} }
// numCached performs !numcached functionality. Displays the number of songs currently cached on disk at ~/.mumbledj/songs. // numCached performs !numcached functionality. Displays the number of songs currently cached on disk.
func numCached(user *gumble.User) { func numCached(user *gumble.User) {
if dj.conf.Cache.Enabled { if dj.conf.Cache.Enabled {
dj.cache.Update() dj.cache.Update()
@ -433,7 +434,7 @@ func cacheSize(user *gumble.User) {
} }
} }
// kill performs !kill functionality. First cleans the ~/.mumbledj/songs directory to get rid of any // kill performs !kill functionality. First cleans the song cache directory to get rid of any
// excess m4a files. The bot then safely disconnects from the server. // excess m4a files. The bot then safely disconnects from the server.
func kill() { func kill() {
if err := deleteSongs(); err != nil { if err := deleteSongs(); err != nil {
@ -447,14 +448,16 @@ func kill() {
} }
} }
// deleteSongs deletes songs from ~/.mumbledj/songs. // deleteSongs deletes songs from the song cache.
func deleteSongs() error { func deleteSongs() error {
songsDir := fmt.Sprintf("%s/.mumbledj/songs", dj.homeDir) songs, err := ioutil.ReadDir(dj.songCacheDir)
if err := os.RemoveAll(songsDir); err != nil { if err != nil {
return errors.New("An error occurred while deleting the audio files.") return errors.New(fmt.Sprintf("An error occured while clearing %q: %v", dj.songCacheDir, err))
} }
if err := os.Mkdir(songsDir, 0777); err != nil { for _, file := range songs {
return errors.New("An error occurred while recreating the songs directory.") if err2 := os.Remove(fmt.Sprintf("%s/%s", dj.songCacheDir, file.Name())); err2 != nil {
return errors.New(fmt.Sprintf("An error occurred while removing %q: %v", file.Name(), err2))
}
} }
return nil return nil
} }

View file

@ -21,6 +21,7 @@ import (
"github.com/layeh/gumble/gumble" "github.com/layeh/gumble/gumble"
"github.com/layeh/gumble/gumble_ffmpeg" "github.com/layeh/gumble/gumble_ffmpeg"
"github.com/layeh/gumble/gumbleutil" "github.com/layeh/gumble/gumbleutil"
"github.com/mildred/go-xdg"
) )
// mumbledj is a struct that keeps track of all aspects of the bot's current // mumbledj is a struct that keeps track of all aspects of the bot's current
@ -34,6 +35,7 @@ type mumbledj struct {
queue *SongQueue queue *SongQueue
audioStream *gumble_ffmpeg.Stream audioStream *gumble_ffmpeg.Stream
homeDir string homeDir string
songCacheDir string
playlistSkips map[string][]string playlistSkips map[string][]string
cache *SongCache cache *SongCache
} }
@ -190,6 +192,9 @@ func main() {
if currentUser, err := user.Current(); err == nil { if currentUser, err := user.Current(); err == nil {
dj.homeDir = currentUser.HomeDir dj.homeDir = currentUser.HomeDir
} }
if songCacheDir, err := xdg.Cache.EnsureDir("mumbledj/songs"); err == nil {
dj.songCacheDir = songCacheDir
}
if err := loadConfiguration(); err == nil { if err := loadConfiguration(); err == nil {
fmt.Println("Configuration successfully loaded!") fmt.Println("Configuration successfully loaded!")

View file

@ -51,12 +51,12 @@ type AudioPlaylist struct {
// ------------ // ------------
// Download downloads the song via youtube-dl if it does not already exist on disk. // Download downloads the song via youtube-dl if it does not already exist on disk.
// All downloaded songs are stored in ~/.mumbledj/songs and should be automatically cleaned. // All downloaded songs are stored in the song cache and should be automatically cleaned.
func (dl *AudioTrack) Download() error { func (dl *AudioTrack) Download() error {
// Checks to see if song is already downloaded // Checks to see if song is already downloaded
if _, err := os.Stat(fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, dl.Filename())); os.IsNotExist(err) { if _, err := os.Stat(fmt.Sprintf("%s/%s", dj.songCacheDir, dl.Filename())); os.IsNotExist(err) {
cmd := exec.Command("youtube-dl", "--verbose", "--no-mtime", "--output", fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, dl.Filename()), "--format", dl.format, "--prefer-ffmpeg", dl.url) cmd := exec.Command("youtube-dl", "--verbose", "--no-mtime", "--output", fmt.Sprintf("%s/%s", dj.songCacheDir, dl.Filename()), "--format", dl.format, "--prefer-ffmpeg", dl.url)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if err == nil { if err == nil {
if dj.conf.Cache.Enabled { if dj.conf.Cache.Enabled {
@ -82,7 +82,7 @@ func (dl *AudioTrack) Play() {
offsetDuration, _ := time.ParseDuration(fmt.Sprintf("%ds", dl.offset)) offsetDuration, _ := time.ParseDuration(fmt.Sprintf("%ds", dl.offset))
dj.audioStream.Offset = offsetDuration dj.audioStream.Offset = offsetDuration
} }
dj.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, dl.Filename())) dj.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/%s", dj.songCacheDir, dl.Filename()))
if err := dj.audioStream.Play(); err != nil { if err := dj.audioStream.Play(); err != nil {
panic(err) panic(err)
} else { } else {
@ -101,10 +101,10 @@ func (dl *AudioTrack) Play() {
} }
} }
// Delete deletes the song from ~/.mumbledj/songs if the cache is disabled. // Delete deletes the song from the song cache if the cache is disabled.
func (dl *AudioTrack) Delete() error { func (dl *AudioTrack) Delete() error {
if dj.conf.Cache.Enabled == false { if dj.conf.Cache.Enabled == false {
filePath := fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, dl.Filename()) filePath := fmt.Sprintf("%s/%s", dj.songCacheDir, dl.Filename())
if _, err := os.Stat(filePath); err == nil { if _, err := os.Stat(filePath); err == nil {
if err := os.Remove(filePath); err == nil { if err := os.Remove(filePath); err == nil {
return nil return nil