Alchemy.Voice (alchemy v0.7.0)

Contains the types and functions related to voice communication with discord.

To use the functions in this module, make sure to configure the paths to ffmpeg, as well as youtube-dl, like so:

config :alchemy,
  ffmpeg_path: "path/to/ffmpeg"
  youtube_dl_path: "path/to/youtube-dl"

If these are not configured, the necessary supervisors for maintaining voice connections won't be started, and you'll run into errors when trying to use the functions in this module.

Link to this section Summary

Types

Represents the audio options that can be passed to different play methods.

Represents a voice region.

Represents the state of a user's voice connection.

Functions

Joins a voice channel in a guild.

Disconnects from voice in a guild.

Lets this process listen for the end of an audio track in a guild.

Starts playing a music file on a guild's voice connection.

Starts playing audio from an iodata, or a stream of iodata.

Starts playing audio from a url.

Stops playing audio on a guild's voice connection.

Blocks the current process until audio has stopped playing in a guild.

Returns which channel the client is connected to in a guild.

Link to this section Types

Link to this type

audio_options()

Specs

audio_options() :: [{:vol, integer()}]

Represents the audio options that can be passed to different play methods.

Options

  • vol audio volume, in %. Can go above 100 to multiply, e.g. 150.

Specs

region() :: %Alchemy.VoiceRegion{
  custom: Boolean,
  deprecated: Boolean,
  id: snowflake(),
  name: String.t(),
  optimal: Boolean,
  sample_hostname: String.t(),
  sample_port: Integer,
  vip: Boolean
}

Represents a voice region.

  • id Represent the unique ID for this region.
  • name The name of this region.
  • sample_hostname An example hostname for the region.
  • sample_port An example port for the region.
  • vip True if this is a vip-only server.
  • optimal True for a single server that is closest to the client.
  • deprecated Whether this is a deprecated voice region.
  • custom Whether this is a custom voice region.

Specs

snowflake() :: String.t()

Specs

state() :: %Alchemy.VoiceState{
  channel_id: snowflake(),
  deaf: Boolean,
  guild_id: snowflake() | nil,
  mute: Boolean,
  self_deaf: Boolean,
  self_mute: Boolean,
  session_id: String.t(),
  suppress: Boolean,
  user_id: snowflake()
}

Represents the state of a user's voice connection.

  • guild_id The guild id this state is for.
  • channel_id The channel id this user is connected to.
  • user_id The id of the user this state belongs to.
  • session_id The session id for this voice state.
  • deaf Whether this user is deafened by the server.
  • mute Whether this user is muted by the server.
  • self_deaf Whether this user is locally deafened.
  • self_mute Whether this user is locally muted.
  • suppress Whether this user is muted by the current user.

Link to this section Functions

Link to this function

join(guild, channel, timeout \\ 6000)

Specs

join(snowflake(), snowflake(), integer()) :: :ok | {:error, String.t()}

Joins a voice channel in a guild.

Only one voice connection per guild is possible with the api. If you're already connected to the guild, this will not restart the voice connections, but instead just move you to the channel.

This function also checks if you're already connected to this channel, and does nothing if that is the case.

The timeout will be spread across 2 different message receptions, i.e. a timeout of 6000 will only wait 3s at every reception.

Specs

leave(snowflake()) :: :ok | {:error, String.t()}

Disconnects from voice in a guild.

Returns an error if the connection hadn’t been established.

Link to this function

listen_for_end(guild)

Specs

listen_for_end(snowflake()) :: :ok | {:error, String.t()}

Lets this process listen for the end of an audio track in a guild.

This will subscribe this process up until the next time an audio track ends, to react to this, you'll want to handle the message in some way, e.g.

Voice.listen_for_end(guild)
receive do
  {:audio_stopped, ^guild} -> IO.puts "audio has stopped"
end

This is mainly designed for use in genservers, or other places where you don't want to block. If you do want to block and wait immediately, try wait_for_end/2 instead.

Examples

Use in a genserver:

def handle_info({:audio_stopped, guild}, state) do
  IO.puts "audio has stopped in #{guild}"
  Voice.listen_for_end(guild)
  {:noreply, state}
end
Link to this function

play_file(guild, file_path, options \\ [])

Specs

play_file(snowflake(), Path.t(), audio_options()) :: :ok | {:error, String.t()}

Starts playing a music file on a guild's voice connection.

Returns an error if the client isn't connected to the guild, or if the file does not exist.

Examples

Voice.join("666", "666")
Voice.play_file("666", "cool_song.mp3")
Link to this function

play_iodata(guild, data, options \\ [])

Specs

play_iodata(snowflake(), iodata() | Enumerable.t(), audio_options()) ::
  :ok | {:error, String.t()}

Starts playing audio from an iodata, or a stream of iodata.

Similar to play_url/2 except it doesn't create a stream from youtube-dl for you.

Link to this function

play_url(guild, url, options \\ [])

Specs

play_url(snowflake(), String.t(), audio_options()) :: :ok | {:error, String.t()}

Starts playing audio from a url.

For this to work, the url must be one of the supported sites. This function does not check the validity of this url, so if it's invalid, an error will get logged, and no audio will be played.

Link to this function

stop_audio(guild)

Specs

stop_audio(snowflake()) :: :ok | {:error, String.t()}

Stops playing audio on a guild's voice connection.

Returns an error if the connection hadn't been established.

Link to this function

wait_for_end(guild, timeout \\ :infinity)

Specs

wait_for_end(snowflake(), integer() | :infinity) :: :ok | {:error, String.t()}

Blocks the current process until audio has stopped playing in a guild.

This is a combination of listen_for_end/1 and a receive block, however this will return an error if the provided timeout is exceeded. This is useful for implementing automatic track listing, e.g.

def playlist(guild, tracks) do
  Enum.map(tracks, fn track ->
    Voice.play_file(guild, track)
    Voice.wait_for_end(guild)
  end)
end
Link to this function

which_channel(guild)

Specs

which_channel(snowflake()) :: snowflake() | nil

Returns which channel the client is connected to in a guild.

Returns nil if there is no connection.