1
0
mirror of https://github.com/mgerb/go-discord-bot synced 2026-01-09 08:32:48 +00:00

feat: add player controls to uploaded clips on stats page

This commit is contained in:
2019-08-24 11:12:58 -05:00
parent d29c23d9e4
commit 72ba1e5621
11 changed files with 201 additions and 70 deletions

View File

@@ -0,0 +1,74 @@
import React from 'react';
import { SoundService } from '../../services';
interface IProps {
sound: SoundType;
type: 'sounds' | 'clips';
showDiscordPlay?: boolean;
}
interface IState {}
export interface SoundType {
extension: string;
name: string;
}
export class ClipPlayerControl extends React.Component<IProps, IState> {
checkExtension(extension: string) {
switch (extension) {
case 'wav':
return true;
case 'mp3':
return true;
case 'mpeg':
return true;
default:
return false;
}
}
handlePlayAudioInBrowser(sound: SoundType, type: string) {
const url = `/public/${type.toLowerCase()}/` + sound.name + '.' + sound.extension;
const audio = new Audio(url);
audio.play();
}
onPlayDiscord = (sound: SoundType) => {
SoundService.playSound(sound);
};
render() {
const { sound, showDiscordPlay, type } = this.props;
return (
this.checkExtension(sound.extension) && (
<div className="flex flex--v-center">
<a
href={`/public/${type.toLowerCase()}/` + sound.name + '.' + sound.extension}
download
title="Download"
className="fa fa-download link"
aria-hidden="true"
/>
<i
title="Play in browser"
className="fa fa-play link"
aria-hidden="true"
style={{ paddingLeft: '15px' }}
onClick={() => this.handlePlayAudioInBrowser(sound, type)}
/>
{showDiscordPlay && (
<i
title="Play in discord"
className="fa fa-play-circle link fa-lg"
aria-hidden="true"
style={{ paddingLeft: '10px' }}
onClick={() => this.onPlayDiscord(sound)}
/>
)}
</div>
)
);
}
}

View File

@@ -1,9 +1,10 @@
import React from 'react';
import { ClipPlayerControl } from '../clip-player-control/clip-player-control';
import './sound-list.scss';
interface Props {
soundList: SoundType[];
type: string;
type: 'sounds' | 'clips';
onPlayDiscord?: (sound: SoundType) => void;
showDiscordPlay?: boolean;
}
@@ -46,7 +47,7 @@ export class SoundList extends React.Component<Props, State> {
}
render() {
const { onPlayDiscord, showDiscordPlay, soundList, type } = this.props;
const { showDiscordPlay, soundList, type } = this.props;
return (
<div className="card">
@@ -65,41 +66,7 @@ export class SoundList extends React.Component<Props, State> {
<div key={index} className="sound-list__item">
<div className="text-wrap">{(sound.prefix || '') + sound.name}</div>
{this.checkExtension(sound.extension) && this.state.showAudioControls[index] ? (
<audio
controls
src={`/public/${type.toLowerCase()}/` + sound.name + '.' + sound.extension}
itemType={'audio/' + sound.extension}
style={{ width: '100px' }}
/>
) : (
<div>
<a
href={`/public/${type.toLowerCase()}/` + sound.name + '.' + sound.extension}
download
title="Download"
className="fa fa-download link"
aria-hidden="true"
/>
<i
title="Play in browser"
className="fa fa-play link"
aria-hidden="true"
style={{ paddingLeft: '15px' }}
onClick={() => this.handlePlayAudioInBrowser(sound, type)}
/>
{showDiscordPlay &&
onPlayDiscord && (
<i
title="Play in discord"
className="fa fa-play-circle link fa-lg"
aria-hidden="true"
style={{ paddingLeft: '10px' }}
onClick={() => onPlayDiscord!(sound)}
/>
)}
</div>
)}
<ClipPlayerControl showDiscordPlay={showDiscordPlay} sound={sound} type={type} />
</div>
);
})

View File

@@ -2,12 +2,14 @@ import * as _ from 'lodash';
import { DateTime } from 'luxon';
import React from 'react';
import { ISound } from '../../model';
import { ClipPlayerControl } from '../clip-player-control/clip-player-control';
interface IProps {
sounds: ISound[];
showDiscordPlay?: boolean;
}
export const UploadHistory = ({ sounds }: IProps) => {
export const UploadHistory = ({ sounds, showDiscordPlay }: IProps) => {
const sortedSounds = _.orderBy(sounds, 'created_at', 'desc');
return (
<div className="card">
@@ -15,7 +17,7 @@ export const UploadHistory = ({ sounds }: IProps) => {
<table className="table">
<thead>
<tr>
<th>Date</th>
<th className="hide-tiny">Date</th>
<th>Sound</th>
<th className="hide-tiny">Ext</th>
<th>Username</th>
@@ -27,7 +29,9 @@ export const UploadHistory = ({ sounds }: IProps) => {
const formattedDate = DateTime.fromISO(s.created_at).toLocaleString();
return (
<tr key={i}>
<td title={formattedDate}>{formattedDate}</td>
<td className="hide-tiny" title={formattedDate}>
{formattedDate}
</td>
<td title={s.name}>{s.name}</td>
<td className="hide-tiny" title={s.extension}>
{s.extension}
@@ -36,6 +40,9 @@ export const UploadHistory = ({ sounds }: IProps) => {
<td className="hide-tiny" title={s.user.email}>
{s.user.email}
</td>
<td>
<ClipPlayerControl showDiscordPlay={showDiscordPlay} sound={s} type="sounds"></ClipPlayerControl>
</td>
</tr>
);
})}

View File

@@ -37,7 +37,7 @@ export class Clips extends React.Component<Props, State> {
return (
<div className="content">
<div className="column">
<SoundList soundList={this.state.clipList} type="Clips" />
<SoundList soundList={this.state.clipList} type="clips" />
</div>
</div>
);

View File

@@ -1,7 +1,6 @@
import { inject, observer } from 'mobx-react';
import React from 'react';
import { SoundList, SoundType, Uploader } from '../../components';
import { Permissions } from '../../model';
import { axios, SoundService } from '../../services';
import { AppStore } from '../../stores';
import './soundboard.scss';
@@ -73,9 +72,9 @@ export class Soundboard extends React.Component<Props, State> {
<Uploader onComplete={this.onUploadComplete} />
<SoundList
soundList={soundList}
type="Sounds"
type="sounds"
onPlayDiscord={this.onPlayDiscord}
showDiscordPlay={appStore!.claims && appStore!.claims!.permissions >= Permissions.Mod}
showDiscordPlay={appStore!.hasModPermissions()}
/>
</div>
);

View File

@@ -74,7 +74,7 @@ export class Stats extends Component<IProps, IState> {
},
};
const { claims } = this.props.appStore;
const { claims, hasModPermissions } = this.props.appStore;
return (
<div className="content">
@@ -82,7 +82,7 @@ export class Stats extends Component<IProps, IState> {
<div className="card__header">Posts containing links</div>
<HorizontalBar data={data} />
</div>
{claims && <UploadHistory sounds={this.state.sounds} />}
{claims && <UploadHistory sounds={this.state.sounds} showDiscordPlay={hasModPermissions()} />}
</div>
);
}

View File

@@ -1,6 +1,6 @@
import jwt_decode from 'jwt-decode';
import { action, observable } from 'mobx';
import { IClaims } from '../model';
import { IClaims, Permissions } from '../model';
import { axios, StorageService } from '../services';
import { Util } from '../util';
@@ -40,4 +40,8 @@ export class AppStore {
public toggleNavbar = () => {
this.navbarOpen = !this.navbarOpen;
};
public hasModPermissions = () => {
return this.claims && this.claims.permissions >= Permissions.Mod;
};
}

View File

@@ -20,9 +20,9 @@
"integrity": "sha512-aWw2YTtAdT7CskFyxEX2K21/zSDStuf/ikI3yBqmwpwJF0pS+/IX5DWv+1UFffZIbruP6cnT9/LAJV1gFwAT1A=="
},
"@types/lodash": {
"version": "4.14.110",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.110.tgz",
"integrity": "sha512-iXYLa6olt4tnsCA+ZXeP6eEW3tk1SulWeYyP/yooWfAtXjozqXgtX4+XUtMuOCfYjKGz3F34++qUc3Q+TJuIIw=="
"version": "4.14.137",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.137.tgz",
"integrity": "sha512-g4rNK5SRKloO+sUGbuO7aPtwbwzMgjK+bm9BBhLD7jGUiGR7zhwYEhSln/ihgYQBeIJ5j7xjyaYzrWTcu3UotQ=="
},
"@types/luxon": {
"version": "1.2.2",
@@ -5405,9 +5405,9 @@
}
},
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
},
"lodash.assign": {
"version": "4.2.0",
@@ -6237,9 +6237,9 @@
}
},
"normalize.css": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.0.tgz",
"integrity": "sha512-iXcbM3NWr0XkNyfiSBsoPezi+0V92P9nj84yVV1/UZxRUrGczgX/X91KMAGM0omWLY2+2Q1gKD/XRn4gQRDB2A=="
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz",
"integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
},
"npm-run-path": {
"version": "2.0.2",
@@ -7983,9 +7983,9 @@
}
},
"react-chartjs-2": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.7.2.tgz",
"integrity": "sha512-ncTSOZjlI9j3aXGbsiXEoCtb6oS5nixYe9wLWK+3af1aq7K/vcFkzA9faA5Z/q+fgMDWLEa078cWAyzymxvvYg==",
"version": "2.7.6",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.7.6.tgz",
"integrity": "sha512-xDr0jhgt/o26atftXxTVsepz+QYZI2GNKBYpxtLvYgwffLUm18a9n562reUJAHvuwKsy2v+qMlK5HyjFtSW0mg==",
"requires": {
"lodash": "^4.17.4",
"prop-types": "^15.5.8"

View File

@@ -12,7 +12,7 @@
"dependencies": {
"@types/chart.js": "^2.7.22",
"@types/jwt-decode": "^2.2.1",
"@types/lodash": "^4.14.110",
"@types/lodash": "^4.14.137",
"@types/luxon": "^1.2.2",
"@types/node": "^10.3.4",
"@types/nprogress": "0.0.29",
@@ -39,18 +39,18 @@
"font-awesome": "^4.7.0",
"html-webpack-plugin": "^3.2.0",
"jwt-decode": "^2.2.0",
"lodash": "^4.17.10",
"lodash": "^4.17.15",
"luxon": "^1.3.3",
"mini-css-extract-plugin": "^0.4.2",
"mobx": "^5.0.3",
"mobx-react": "^5.2.5",
"node-sass": "^4.9.3",
"normalize.css": "^8.0.0",
"normalize.css": "^8.0.1",
"nprogress": "^0.2.0",
"postcss-loader": "^2.1.5",
"query-string": "^6.1.0",
"react": "^16.4.1",
"react-chartjs-2": "^2.7.2",
"react-chartjs-2": "^2.7.6",
"react-dom": "^16.4.1",
"react-dropzone": "^4.2.11",
"react-router-dom": "^4.3.1",

92
server/Gopkg.lock generated
View File

@@ -2,226 +2,306 @@
[[projects]]
digest = "1:a62f6ed230a8cd138a9efbe718e7d0b0294f139266f5f55cd942769a9aac8de2"
name = "github.com/PuerkitoBio/goquery"
packages = ["."]
pruneopts = "UT"
revision = "dc2ec5c7ca4d9aae063b79b9f581dd3ea6afd2b2"
version = "v1.4.1"
[[projects]]
digest = "1:66b3310cf22cdc96c35ef84ede4f7b9b370971c4025f394c89a2638729653b11"
name = "github.com/andybalholm/cascadia"
packages = ["."]
pruneopts = "UT"
revision = "901648c87902174f774fac311d7f176f8647bdaa"
version = "v1.0.0"
[[projects]]
digest = "1:4fd5ce7844c22e194005b9e12fee8adc70fb5ba0bbba9e1964d2e3d1f301d789"
name = "github.com/bwmarrin/discordgo"
packages = ["."]
pruneopts = "UT"
revision = "4a33b9bc7c56cfdb9bb244e33e83cb3941fe2bdc"
version = "v0.18.0"
[[projects]]
branch = "master"
digest = "1:36fe9527deed01d2a317617e59304eb2c4ce9f8a24115bcc5c2e37b3aee5bae4"
name = "github.com/gin-contrib/sse"
packages = ["."]
pruneopts = "UT"
revision = "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae"
[[projects]]
digest = "1:d5083934eb25e45d17f72ffa86cae3814f4a9d6c073c4f16b64147169b245606"
name = "github.com/gin-gonic/gin"
packages = [
".",
"binding",
"json",
"render"
"render",
]
pruneopts = "UT"
revision = "b869fe1415e4b9eb52f247441830d502aece2d4d"
version = "v1.3.0"
[[projects]]
branch = "master"
digest = "1:602a78a9834f7b1f67186a69970dc0f5f6f9557ef52fd786586e5be14f5a6ed6"
name = "github.com/go-audio/audio"
packages = ["."]
pruneopts = "UT"
revision = "b697a35b5608fcf1c4f90a9d4f33d76bd70e8fe6"
[[projects]]
branch = "master"
digest = "1:505ceb99060820f1c99a687795774a1df5a6fd4a3a5dbb4eb915bff3ac3a94d7"
name = "github.com/go-audio/wav"
packages = ["."]
pruneopts = "UT"
revision = "87c13ac40f038b0316963807a7d476544c7e9136"
[[projects]]
digest = "1:c8ad4ba32ae8b71ef2bf5e1bad402aeb99ce77a1240f9b684db8b1ff5353e7ab"
name = "github.com/gobuffalo/packr"
packages = ["."]
pruneopts = "UT"
revision = "5a2cbb54c4e7d482e3f518c56f1f86f133d5204f"
version = "v1.13.7"
[[projects]]
digest = "1:97df918963298c287643883209a2c3f642e6593379f97ab400c2a2e219ab647d"
name = "github.com/golang/protobuf"
packages = ["proto"]
pruneopts = "UT"
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
version = "v1.2.0"
[[projects]]
digest = "1:7b5c6e2eeaa9ae5907c391a91c132abfd5c9e8a784a341b5625e750c67e6825d"
name = "github.com/gorilla/websocket"
packages = ["."]
pruneopts = "UT"
revision = "66b9c49e59c6c48f0ffce28c2d8b8a5678502c6d"
version = "v1.4.0"
[[projects]]
branch = "v2"
digest = "1:92ac5796b86f454e9b8a9f0f2ceba033747aa8d8fe1fda89b9ec6d6176a431b6"
name = "github.com/hraban/opus"
packages = ["."]
pruneopts = "UT"
revision = "0f2e0b4fc6cd5710fddbb74ba2e5e02c1c1bc22b"
[[projects]]
branch = "master"
digest = "1:5c3444689562053b027ef3b96372e306adbe0d7d109b6cdd48d01eb80f8bab14"
name = "github.com/jinzhu/copier"
packages = ["."]
pruneopts = "UT"
revision = "7e38e58719c33e0d44d585c4ab477a30f8cb82dd"
[[projects]]
digest = "1:2a21d36a5ab33e6e4ce82b3c7ba45c2330ca6e9af247382475e056b06395b8a9"
name = "github.com/jinzhu/gorm"
packages = [
".",
"dialects/sqlite"
"dialects/sqlite",
]
pruneopts = "UT"
revision = "6ed508ec6a4ecb3531899a69cbc746ccf65a4166"
version = "v1.9.1"
[[projects]]
branch = "master"
digest = "1:fd97437fbb6b7dce04132cf06775bd258cce305c44add58eb55ca86c6c325160"
name = "github.com/jinzhu/inflection"
packages = ["."]
pruneopts = "UT"
revision = "04140366298a54a039076d798123ffa108fff46c"
[[projects]]
digest = "1:3e551bbb3a7c0ab2a2bf4660e7fcad16db089fdcfbb44b0199e62838038623ea"
name = "github.com/json-iterator/go"
packages = ["."]
pruneopts = "UT"
revision = "1624edc4454b8682399def8740d46db5e4362ba4"
version = "v1.1.5"
[[projects]]
digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
pruneopts = "UT"
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
version = "v1.0.1"
[[projects]]
branch = "master"
digest = "1:8c2ec3f7fa853d374b340831554f225ead9ab4cc6932256f0cffbfef8c78d9f5"
name = "github.com/mattetti/audio"
packages = ["riff"]
pruneopts = "UT"
revision = "01576cde1f212c296c0b8ef5fa857169770c75b6"
[[projects]]
digest = "1:0981502f9816113c9c8c4ac301583841855c8cf4da8c72f696b3ebedf6d0e4e5"
name = "github.com/mattn/go-isatty"
packages = ["."]
pruneopts = "UT"
revision = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c"
version = "v0.0.4"
[[projects]]
digest = "1:3cafc6a5a1b8269605d9df4c6956d43d8011fc57f266ca6b9d04da6c09dee548"
name = "github.com/mattn/go-sqlite3"
packages = ["."]
pruneopts = "UT"
revision = "25ecb14adfc7543176f7d85291ec7dba82c6f7e4"
version = "v1.9.0"
[[projects]]
digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563"
name = "github.com/modern-go/concurrent"
packages = ["."]
pruneopts = "UT"
revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
version = "1.0.3"
[[projects]]
digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855"
name = "github.com/modern-go/reflect2"
packages = ["."]
pruneopts = "UT"
revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd"
version = "1.0.1"
[[projects]]
digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747"
name = "github.com/pkg/errors"
packages = ["."]
pruneopts = "UT"
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
branch = "master"
digest = "1:d10708438642755d6fd37c570b9d01cb5263e7e4248f813b079b031cdd7cf618"
name = "github.com/rylio/ytdl"
packages = ["."]
pruneopts = "UT"
revision = "0227c2bacb82a434f2332d7d8c64093615c08a40"
[[projects]]
digest = "1:dc2d85c13ac22c22a1f3170a41a8e1b897fa05134aaf533f16df44f66a25b4a1"
name = "github.com/sirupsen/logrus"
packages = ["."]
pruneopts = "UT"
revision = "a67f783a3814b8729bd2dac5780b5f78f8dbd64d"
version = "v1.1.0"
[[projects]]
digest = "1:2cab41f59638fdb77dda96ab4f9b5860ef30f48967557254eba127e43c756f2e"
name = "github.com/tidwall/gjson"
packages = ["."]
pruneopts = "UT"
revision = "1e3f6aeaa5bad08d777ea7807b279a07885dd8b2"
version = "v1.1.3"
[[projects]]
branch = "master"
digest = "1:d3f968e2a2c9f8506ed44b01b605ade0176ba6cf73ff679073e77cfdef2c0d55"
name = "github.com/tidwall/match"
packages = ["."]
pruneopts = "UT"
revision = "1731857f09b1f38450e2c12409748407822dc6be"
[[projects]]
digest = "1:03aa6e485e528acb119fb32901cf99582c380225fc7d5a02758e08b180cb56c3"
name = "github.com/ugorji/go"
packages = ["codec"]
pruneopts = "UT"
revision = "b4c50a2b199d93b13dc15e78929cfb23bfdf21ab"
version = "v1.1.1"
[[projects]]
branch = "master"
digest = "1:207d2e280e7a43845b12d07437538d22d02dbd4c274b49f3940bb3dce2ed70d7"
name = "golang.org/x/crypto"
packages = [
"internal/subtle",
"nacl/secretbox",
"poly1305",
"salsa20/salsa",
"ssh/terminal"
"ssh/terminal",
]
pruneopts = "UT"
revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
[[projects]]
branch = "master"
digest = "1:1a1ecfa7b54ca3f7a0115ab5c578d7d6a5d8b605839c549e80260468c42f8be7"
name = "golang.org/x/net"
packages = [
"html",
"html/atom"
"html/atom",
]
pruneopts = "UT"
revision = "146acd28ed5894421fb5aac80ca93bc1b1f46f87"
[[projects]]
branch = "master"
digest = "1:850d28ab022512e2cd3cf511a77f363c29e22689b4031f2050871f5de47ae4a0"
name = "golang.org/x/sys"
packages = [
"unix",
"windows"
"windows",
]
pruneopts = "UT"
revision = "4497e2df6f9e69048a54498c7affbbec3294ad47"
[[projects]]
digest = "1:76dc72490af7174349349838f2fe118996381b31ea83243812a97e5a0fd5ed55"
name = "gopkg.in/dgrijalva/jwt-go.v3"
packages = ["."]
pruneopts = "UT"
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
version = "v3.2.0"
[[projects]]
digest = "1:cbc72c4c4886a918d6ab4b95e347ffe259846260f99ebdd8a198c2331cf2b2e9"
name = "gopkg.in/go-playground/validator.v8"
packages = ["."]
pruneopts = "UT"
revision = "5f1438d3fca68893a817e4a66806cea46a9e4ebf"
version = "v8.18.2"
[[projects]]
digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = "UT"
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "21c5e86702fc917232102a89282f42f8a97d03b724ea1fcc8923e347a87347bd"
input-imports = [
"github.com/bwmarrin/discordgo",
"github.com/gin-gonic/gin",
"github.com/go-audio/audio",
"github.com/go-audio/wav",
"github.com/gobuffalo/packr",
"github.com/hraban/opus",
"github.com/jinzhu/copier",
"github.com/jinzhu/gorm",
"github.com/jinzhu/gorm/dialects/sqlite",
"github.com/rylio/ytdl",
"github.com/sirupsen/logrus",
"github.com/tidwall/gjson",
"gopkg.in/dgrijalva/jwt-go.v3",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -185,7 +185,7 @@ func (conn *AudioConnection) PlayAudio(soundName string, m *discordgo.MessageCre
// summon bot to channel if new message passed in
if m != nil {
conn.summon(m)
} else if !conn.VoiceConnection.Ready {
} else if conn.VoiceConnection == nil || !conn.VoiceConnection.Ready {
return
}