Compare commits
3 Commits
45900d04d7
...
7ebc2b93b8
Author | SHA1 | Date |
---|---|---|
Thibaut Broggi | 7ebc2b93b8 | |
Thibaut Broggi | 7a910e03ff | |
Thibaut Broggi | f3930a037a |
|
@ -9,6 +9,7 @@
|
|||
|
||||
"stop": { "target": "player", "action": "stop" },
|
||||
"pause": { "target": "player", "action": "stop" },
|
||||
"leave": { "target": "player", "action": "leave" },
|
||||
|
||||
"resume": { "target": "player", "action": "resume" },
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "0.0.0",
|
||||
"description": "A discord music player",
|
||||
"scripts": {
|
||||
"doc": "rm -fr ./doc && jsdoc -a all -R ./README.md -d doc/ ./src",
|
||||
"doc": "rm -fr ./doc && jsdoc -a all -R ./README.md -d doc/ ./src -r",
|
||||
"start": "node index.js",
|
||||
"test": "jest --collectCoverage"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* @param {durationString}
|
||||
* @returns {number}
|
||||
*/
|
||||
function from_string_to_seconds(str = "") {
|
||||
return str
|
||||
.split(':')
|
||||
.map(v => parseInt(v))
|
||||
.reduce((acc, v) => acc * 60 + v)
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {string} durationString
|
||||
* @desc A string representation of the duration, following the [[HH:]mm:]ss format.<br />
|
||||
* This format is the same as the one used by YouTube
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {number}
|
||||
* @returns {durationString}
|
||||
*/
|
||||
|
||||
function from_seconds_to_string(seconds) {
|
||||
const secs = parseInt(seconds % 60)
|
||||
const minutes = parseInt((seconds / 60) % 60)
|
||||
const hours = parseInt(seconds / 3600)
|
||||
return ''
|
||||
+ (hours > 0 ? hours + ':' : '')
|
||||
+ String(minutes).padStart((hours > 0 ? 2 : 1), '0')
|
||||
+ ':'
|
||||
+ String(secs).padStart(2, '0')
|
||||
}
|
||||
|
||||
module.exports = { from_string_to_seconds, from_seconds_to_string }
|
|
@ -75,6 +75,14 @@ class PlayerManager {
|
|||
this.#voice.voice.setSelfDeaf(true)
|
||||
}
|
||||
|
||||
async leave({ message, params }) {
|
||||
if (this.#voice) {
|
||||
this.#voice.channel.leave()
|
||||
this.#is_playing = false
|
||||
this.#playlist
|
||||
}
|
||||
}
|
||||
|
||||
async shuffle({ message, params }) {
|
||||
this.#playlist.shuffle()
|
||||
message.channel.send('Shuffled ! :twisted_rightwards_arrows:')
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const { Track } = require('./track')
|
||||
const { from_seconds_to_string } = require('./helpers/duration')
|
||||
|
||||
// side effect
|
||||
function shuffle_array(arr) {
|
||||
|
@ -119,10 +120,30 @@ class Playlist {
|
|||
return this.#tracks.length === 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @method
|
||||
* @returns {number} The number of tracks in the playlist
|
||||
*/
|
||||
get_length() {
|
||||
return this.#tracks.length
|
||||
}
|
||||
|
||||
/**
|
||||
* @method
|
||||
* @return {number} The duration of the playlist, in seconds
|
||||
*/
|
||||
get_duration() {
|
||||
return this.#tracks.reduce((a, t) => a + t.get_length(), 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* @method
|
||||
* @return {durationString} The duration of the playlist, as a string
|
||||
*/
|
||||
get_duration_as_string() {
|
||||
return from_seconds_to_string(this.get_duration())
|
||||
}
|
||||
|
||||
/**
|
||||
* @method
|
||||
* @returns {string} a string representation of the playlist
|
||||
|
|
|
@ -76,9 +76,9 @@ class PlaylistsManager {
|
|||
|
||||
async list({ message, params }) {
|
||||
message.channel.send(
|
||||
"Playlist:\n" +
|
||||
"Playlists:\n" +
|
||||
"```json\n" +
|
||||
Object.entries(this.#playlists).map(([title, p], idx) => `${idx+1}: ${title}`).join("\n") +
|
||||
Object.entries(this.#playlists).map(([title, p], idx) => `${idx+1}: ${title} (${p.get_duration_as_string()})`).join("\n") +
|
||||
"```\n",
|
||||
)
|
||||
}
|
||||
|
|
16
src/track.js
16
src/track.js
|
@ -1,3 +1,5 @@
|
|||
const { from_string_to_seconds, from_seconds_to_string } = require('./helpers/duration')
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
|
@ -14,7 +16,7 @@ class Track {
|
|||
* @param {Object} parameters={}
|
||||
* @param {string} parameters.url The url of the track
|
||||
* @param {string} parameters.title The title of the track
|
||||
* @param {number|string} parameters.length The length of the track, either in seconds or following the [[HH:]mm:]ss format. Strings from YouTube can be used without any modification
|
||||
* @param {number|durationString} parameters.length The length of the track, either in seconds or following the [[HH:]mm:]ss format.
|
||||
* @param {string} parameters.source The source where the track comes from. Note that as of now, only <code>'youtube'</code> is supported.
|
||||
* @param {number|Date} [parameters.last_played=0] The timestamp when this track has been played for the last time
|
||||
* @param {number} [parameters.play_count=0] The number of times this track has been played
|
||||
|
@ -109,18 +111,10 @@ class Track {
|
|||
}
|
||||
|
||||
/**
|
||||
* @returns {string} A string representation of the track length<br />
|
||||
* The format is the same as YouTube's one
|
||||
* @returns {durationString} A string representation of the track length
|
||||
*/
|
||||
get_length_as_string() {
|
||||
const seconds = parseInt(this.#length % 60)
|
||||
const minutes = parseInt((this.#length / 60) % 60)
|
||||
const hours = parseInt(this.#length / 3600)
|
||||
return ''
|
||||
+ (hours > 0 ? hours + ':' : '')
|
||||
+ String(minutes).padStart((hours > 0 ? 2 : 1), '0')
|
||||
+ ':'
|
||||
+ String(seconds).padStart(2, '0')
|
||||
return from_seconds_to_string(this.#length)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
const { from_string_to_seconds, from_seconds_to_string } = require('../../src/helpers/duration')
|
||||
|
||||
describe('from_string_to_seconds', () => {
|
||||
test('1 second long, various formats', () => {
|
||||
expect(from_string_to_seconds("1")).toBe(1)
|
||||
expect(from_string_to_seconds("0:01")).toBe(1)
|
||||
expect(from_string_to_seconds("0:00:01")).toBe(1)
|
||||
})
|
||||
|
||||
test('1 minute long, various formats', () => {
|
||||
expect(from_string_to_seconds("60")).toBe(60)
|
||||
expect(from_string_to_seconds("1:00")).toBe(60)
|
||||
expect(from_string_to_seconds("01:00")).toBe(60)
|
||||
expect(from_string_to_seconds("0:01:00")).toBe(60)
|
||||
})
|
||||
|
||||
test('1 hour long, various formats', () => {
|
||||
expect(from_string_to_seconds("3600")).toBe(3600)
|
||||
expect(from_string_to_seconds("60:00")).toBe(3600)
|
||||
expect(from_string_to_seconds("59:60")).toBe(3600)
|
||||
expect(from_string_to_seconds("1:00:00")).toBe(3600)
|
||||
})
|
||||
|
||||
test('various values', () => {
|
||||
expect(from_string_to_seconds("12:34")).toBe(754)
|
||||
expect(from_string_to_seconds("1:23:45")).toBe(5025)
|
||||
expect(from_string_to_seconds("100:00:59")).toBe(360059)
|
||||
})
|
||||
})
|
||||
|
||||
describe('track length formating (output)', () => {
|
||||
test('1 second long', () => {
|
||||
expect(from_seconds_to_string(1)).toBe("0:01")
|
||||
})
|
||||
|
||||
test('1 minute long', () => {
|
||||
expect(from_seconds_to_string(60)).toBe("1:00")
|
||||
})
|
||||
|
||||
test('1 hour long', () => {
|
||||
expect(from_seconds_to_string(3600)).toBe("1:00:00")
|
||||
})
|
||||
|
||||
test('various values', () => {
|
||||
expect(from_seconds_to_string(754)).toBe("12:34")
|
||||
expect(from_seconds_to_string(5025)).toBe("1:23:45")
|
||||
expect(from_seconds_to_string(360059)).toBe("100:00:59")
|
||||
})
|
||||
})
|
|
@ -33,71 +33,3 @@ describe('track basic manipulations', () => {
|
|||
expect(t2.toJSON().last_played).toBeGreaterThan(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('track length formating (input)', () => {
|
||||
test('1 second long, various formats', () => {
|
||||
const t1 = new Track({ length: "1" })
|
||||
const t2 = new Track({ length: "0:01" })
|
||||
const t3 = new Track({ length: "0:00:01" })
|
||||
expect(t1.get_length()).toBe(1)
|
||||
expect(t2.get_length()).toBe(1)
|
||||
expect(t3.get_length()).toBe(1)
|
||||
})
|
||||
|
||||
test('1 minute long, various formats', () => {
|
||||
const t1 = new Track({ length: "60" })
|
||||
const t2 = new Track({ length: "1:00" })
|
||||
const t3 = new Track({ length: "01:00" })
|
||||
const t4 = new Track({ length: "0:01:00" })
|
||||
expect(t1.get_length()).toBe(60)
|
||||
expect(t2.get_length()).toBe(60)
|
||||
expect(t3.get_length()).toBe(60)
|
||||
expect(t4.get_length()).toBe(60)
|
||||
})
|
||||
|
||||
test('1 hour long, various formats', () => {
|
||||
const t1 = new Track({ length: "3600" })
|
||||
const t2 = new Track({ length: "60:00" })
|
||||
const t3 = new Track({ length: "59:60" })
|
||||
const t4 = new Track({ length: "1:00:00" })
|
||||
expect(t1.get_length()).toBe(3600)
|
||||
expect(t2.get_length()).toBe(3600)
|
||||
expect(t3.get_length()).toBe(3600)
|
||||
expect(t4.get_length()).toBe(3600)
|
||||
})
|
||||
|
||||
test('various values', () => {
|
||||
const t1 = new Track({ length: "12:34" })
|
||||
const t2 = new Track({ length: "1:23:45" })
|
||||
const t3 = new Track({ length: "100:00:59" })
|
||||
expect(t1.get_length()).toBe(754)
|
||||
expect(t2.get_length()).toBe(5025)
|
||||
expect(t3.get_length()).toBe(360059)
|
||||
})
|
||||
})
|
||||
|
||||
describe('track length formating (output)', () => {
|
||||
test('1 second long', () => {
|
||||
const t1 = new Track({ length: 1 })
|
||||
expect(t1.get_length_as_string()).toBe("0:01")
|
||||
})
|
||||
|
||||
test('1 minute long', () => {
|
||||
const t1 = new Track({ length: 60 })
|
||||
expect(t1.get_length_as_string()).toBe("1:00")
|
||||
})
|
||||
|
||||
test('1 hour long', () => {
|
||||
const t1 = new Track({ length: 3600 })
|
||||
expect(t1.get_length_as_string()).toBe("1:00:00")
|
||||
})
|
||||
|
||||
test('various values', () => {
|
||||
const t1 = new Track({ length: 754 })
|
||||
const t2 = new Track({ length: 5025 })
|
||||
const t3 = new Track({ length: 360059 })
|
||||
expect(t1.get_length_as_string()).toBe("12:34")
|
||||
expect(t2.get_length_as_string()).toBe("1:23:45")
|
||||
expect(t3.get_length_as_string()).toBe("100:00:59")
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue