Skip to content

Commit

Permalink
message functions test
Browse files Browse the repository at this point in the history
  • Loading branch information
Vulwsztyn committed Feb 14, 2023
1 parent 0026dda commit 5fb3fde
Show file tree
Hide file tree
Showing 19 changed files with 562 additions and 17 deletions.
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"license": "GPL-3.0-only",
"private": false,
"_moduleAliases": {
"@lib": "dist/lib"
"@lib": "src/lib/index.ts"
},
"scripts": {
"build": "yarn clean && tsc",
Expand All @@ -18,15 +18,20 @@
"lint": "eslint --ignore-path .eslintignore --ext .js,.ts .",
"prettier": "prettier .",
"format": "prettier-eslint --eslint-config-path src/../.eslintrc.js --config src/../.prettierrc \"src/**/*.ts\"",
"check-tsc": "tsc --noEmit"
"check-tsc": "tsc --noEmit",
"webstorm": "ts-node ./src/index.ts"
},
"dependencies": {
"@ef-carbon/tspm": "^2.2.5",
"@lavaclient/queue": "^2.0.4",
"@lavaclient/spotify": "^3.1.0",
"discord.js": "^14.3.0",
"dotenv": "^10.0.0",
"lavaclient": "^4.0.4",
"module-alias": "^2.2.2"
"module-alias": "^2.2.2",
"ramda": "^0.28.0",
"tsconfig-paths": "^4.1.2",
"zod": "^3.20.6"
},
"devDependencies": {
"@types/node": "^16.10.2",
Expand Down
5 changes: 5 additions & 0 deletions src/functions2/echo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { CommonParams2, type EchoParams } from './types'

export async function Echo({ send, msg }: EchoParams): Promise<void> {
await send(msg)
}
24 changes: 24 additions & 0 deletions src/functions2/join.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { type CommonParams2Validated } from './types'
import { TextChannel, type VoiceBasedChannel, VoiceChannel } from 'discord.js'
import { type Node, type Player } from 'lavaclient'
import { type Bot, type MessageChannel } from '@lib'

export const createPlayer = async ({
userTextChannel,
userVc,
bot
}: {
userTextChannel: MessageChannel
userVc: VoiceBasedChannel
bot: Bot
}): Promise<Player<Node>> => {
const player = bot.music.createPlayer(userVc.guild.id)
player.queue.channel = userTextChannel
player.connect(userVc.id)
return player
}

export async function Join({ userVc, bot, userTextChannel, send }: CommonParams2Validated): Promise<void> {
await createPlayer({ userVc, bot, userTextChannel })
await send(`Joined ${userVc.toString()}`)
}
6 changes: 6 additions & 0 deletions src/functions2/leave.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { type CommonParams2Validated } from './types'

export async function Leave({ bot, player }: CommonParams2Validated): Promise<void> {
player.disconnect()
await bot.music.destroyPlayer(player.guildId)
}
25 changes: 25 additions & 0 deletions src/functions2/nightcore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { CommonParams2Validated, type NightcoreParams } from './types'

export async function Nightcore({
send,
speed: speedParam,
pitch: pitchParam,
rate: rateParam,
player
}: NightcoreParams): Promise<void> {
const shouldEnable = !player.nightcore || speedParam != null || pitchParam != null || rateParam != null
if (!shouldEnable) {
await send("Nightcoren't")
player.nightcore = false
player.filters.timescale = undefined
} else {
player.nightcore = true
const speed = speedParam ?? 1.125
const pitch = pitchParam ?? 1.125
const rate = rateParam ?? 1
await send(`Nightcore enabled with speed ${speed}, pitch ${pitch}, and rate ${rate}`)
player.filters.timescale = { speed, pitch, rate }
}

await player.setFilters()
}
13 changes: 13 additions & 0 deletions src/functions2/pause.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { millisecondsToString } from '@lib'
import { type CommonParams2Validated } from './types'

export async function Pause({ sendIfError, send, player }: CommonParams2Validated): Promise<void> {
const current = player.queue.current
if (current == null) {
await sendIfError("I'm not playing anything bozo")
return
}
await player.pause(true)
const positionHumanReadable = millisecondsToString(player.position ?? 0)
await send(`Paused ${current.title} at ${positionHumanReadable}`)
}
5 changes: 5 additions & 0 deletions src/functions2/ping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { type CommonParams2 } from './types'

export async function Ping2({ send, bot }: CommonParams2): Promise<void> {
await send(`Pong! **Heartbeat:** *${Math.round(bot.ws.ping)}ms*`)
}
94 changes: 94 additions & 0 deletions src/functions2/play.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { SpotifyItemType } from '@lavaclient/spotify'

import type { Addable } from '@lavaclient/queue'
import { type PlayParams } from './types'

export const Play =
({ next }: { next: boolean }) =>
async ({
userVc,
send,
sendIfError,
userTextChannel,
bot,
query,
guild,
player,
requesterId
}: PlayParams): Promise<void> => {
let tracks: Addable[] = []
let msg = ''
if (query !== '') {
if (bot.music.spotify.isSpotifyUrl(query)) {
const item = await bot.music.spotify.load(query)
switch (item?.type) {
case SpotifyItemType.Track: {
const track = await item.resolveYoutubeTrack()
tracks = [track]
msg = `Queued track [**${item.name}**](${query}).`
break
}
case SpotifyItemType.Artist: {
tracks = await item.resolveYoutubeTracks()
msg = `Queued the **Top ${tracks.length} tracks** for [**${item.name}**](${query}).`
break
}
case SpotifyItemType.Album:
case SpotifyItemType.Playlist: {
tracks = await item.resolveYoutubeTracks()
msg = `Queued **${tracks.length} tracks** from ${SpotifyItemType[item.type].toLowerCase()} [**${
item.name
}**](${query}).`
break
}
default: {
await sendIfError("Sorry, couldn't find anything :/")
return
}
}
} else {
const results = await bot.music.rest.loadTracks(/^https?:\/\//.test(query) ? query : `ytsearch:${query}`)

switch (results.loadType) {
case 'LOAD_FAILED':
case 'NO_MATCHES': {
await sendIfError('uh oh something went wrong')
return
}
case 'PLAYLIST_LOADED': {
tracks = results.tracks
msg = `Queued playlist [**${results.playlistInfo.name}**](${query}), it has a total of **${tracks.length}** tracks.`
break
}
case 'TRACK_LOADED':
case 'SEARCH_RESULT': {
const [track] = results.tracks
tracks = [track]
msg = `Queued [**${track.info.title}**](${track.info.uri})`
break
}
}
}
}
/* create a player and/or join the member's userVc. */
if (!player?.connected) {
player ??= bot.music.createPlayer(guild.id)
player.queue.channel = userTextChannel
player.connect(userVc.id, { deafened: true })
}

/* reply with the queued message. */
const started = player.playing || player.paused
if (msg !== '') {
// TODO: make it better (this checks if play was used to unpause)
await send(msg, next != null ? 'At the top of the queue.' : '', started)
player.queue.add(tracks, { requester: requesterId, next })
} else {
await send('Resumed playback')
await player.pause(false)
}
/* do queue tings. */
if (!started) {
await player.queue.start()
}
}
18 changes: 18 additions & 0 deletions src/functions2/queue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { type CommonParams2Validated } from './types'

const formatIndex = (index: number, size: number): string =>
(index + 1).toString().padStart(size.toString().length, '0')

export async function Queue({ player, send, guild }: CommonParams2Validated): Promise<void> {
const size = player.queue.tracks.length
const str = player.queue.tracks
.map(
(t, idx) =>
`\`#${formatIndex(idx, size)}\` [**${t.title}**](${t.uri}) ${
t.requester !== undefined ? `<@${t.requester}>` : ''
}`
)
.join('\n')

await send(`Queue for **${guild.name}**`, str)
}
11 changes: 11 additions & 0 deletions src/functions2/remove.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { type RemoveParams } from './types'

export async function Remove({ player, sendIfError, send, index }: RemoveParams): Promise<void> {
const removedTrack = player.queue.remove(index - 1)
if (removedTrack == null) {
await sendIfError('No tracks were removed.')
return
}

await send(`The track [**${removedTrack.title}**](${removedTrack.uri}) was removed.`)
}
8 changes: 8 additions & 0 deletions src/functions2/resume.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { millisecondsToString } from '@lib'
import { type CommonParams2Validated } from './types'

export async function Resume({ player, send, current }: CommonParams2Validated): Promise<void> {
await player.pause(false)
const positionHumanReadable = millisecondsToString(player.position ?? 0)
await send(`Resumed ${current?.title} at ${positionHumanReadable}`)
}
18 changes: 18 additions & 0 deletions src/functions2/seek.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { millisecondsToString, stringToMilliseconds } from '@lib'

import { type SeekParams } from './types'

export const Seek =
({ add = false, multiplier = 1 }: { add?: boolean, multiplier?: 1 | -1 }) =>
async ({ current, sendIfError, send, player, position }: SeekParams): Promise<void> => {
const positionNumerised = (add ? player.position ?? 0 : 0) + multiplier * stringToMilliseconds(position)
if (isNaN(positionNumerised)) {
await sendIfError('Position must be a number')
return
}
await player.seek(positionNumerised)

const positionHumanReadable = millisecondsToString(positionNumerised)

await send(`Sought ${current?.title} to ${positionHumanReadable}`)
}
7 changes: 7 additions & 0 deletions src/functions2/skip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { type CommonParams2Validated } from './types'

export async function Skip({ player, send, current }: CommonParams2Validated): Promise<void> {
await player.queue.skip()
await player.queue.start()
await send(`Skipped ${current?.title}`)
}
66 changes: 66 additions & 0 deletions src/functions2/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { type Guild, type VoiceBasedChannel } from 'discord.js'
import { type Bot, type MessageChannel } from '@lib'
import { z } from 'zod'
import { type Node, type Player } from 'lavaclient'
import { type Song } from '@lavaclient/queue'

const numericCore = z.string().regex(/^[+-]?(\d*[.])?\d+$/, { message: 'not a number' })
const intigerishCore = z.string().regex(/^\d+$/, { message: 'not an int' })
export const numeric = () => numericCore.transform(Number)
export const intigerish = () => intigerishCore.transform((x) => parseInt(x, 10))

export const optionalNumeric = () => numericCore.optional().transform((x) => (x == null ? undefined : Number(x)))

type SendFnType = (text: string, ...rest: any[]) => Promise<void>

export interface CommonParams2 {
userVc: VoiceBasedChannel | null | undefined
userTextChannel: MessageChannel
bot: Bot
guild: Guild | null | undefined
send: SendFnType
sendIfError: SendFnType
player: Player<Node> | undefined
requesterId: string
current: Song | null | undefined
}

export type CommonParams2Validated = CommonParams2 & {
userVc: VoiceBasedChannel
guild: Guild
player: Player<Node>
}

export type TextChannelCheckParams = Omit<CommonParams2, 'send' | 'sendIfError'>

export const EchoParamsSchema = z.object({
msg: z.string().min(1)
})

export type EchoParams = z.infer<typeof EchoParamsSchema> & CommonParams2Validated

export const NightcoreParamsSchema = z.object({
speed: optionalNumeric(),
pitch: optionalNumeric(),
rate: optionalNumeric()
})

export type NightcoreParams = z.infer<typeof NightcoreParamsSchema> & CommonParams2Validated

export const PlayParamsSchema = z.object({
query: z.string().min(1)
})

export type PlayParams = z.infer<typeof PlayParamsSchema> & CommonParams2Validated

export const RemoveParamsSchema = z.object({
index: intigerish()
})

export type RemoveParams = z.infer<typeof RemoveParamsSchema> & CommonParams2Validated

export const SeekParamsSchema = z.object({
position: z.string().min(1)
})

export type SeekParams = z.infer<typeof SeekParamsSchema> & CommonParams2Validated
Loading

0 comments on commit 5fb3fde

Please sign in to comment.