質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

494閲覧

jsonを複製した時、元のjsonに変更が加えられないようにしたい

sumwave

総合スコア11

Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2022/10/02 22:57

問題

Discord Botで音楽botを作っていて、その際に取得されているjsonをファイルに出力するとき、
いらないコードを{}に置き換えるコードを書いた結果、元のデータまで影響してしまいました。
僕が作っているbotの全体コードも置いておきます。1000行あるので見ないでもいいです。

環境

インストールしてるパッケージです。

  • Discord.js v14.5.0
  • @discordjs/voice
  • @discordjs/opus
  • libsodium-wrappers
  • ytdl-core
  • json-cyclic
  • dotenv

実現したいこと

js

1let data = { 2 voice: { 3 text: "hoge" 4 } 5}; 6let output = data.voice; 7output.text = "hogehoge"; 8console.log(output); 9console.log("データ: " + data.voice.text);

このコードの際ログには

{ text: "hogehoge" } データ: hoge

と出てほしいのですが、「データ: hoge」の部分が「データ: hogehoge」置き換わってしまいます。
これをどうにかして置き換えないようにしたいです。

テスト用のソースコード

ちょっと雑ですがお許しを...

js

1import dotenv from "dotenv"; dotenv.config(); 2import fs from "fs"; 3import ytdl from "ytdl-core"; 4import { decycle } from "json-cyclic"; 5import { Client, Partials, GatewayIntentBits, EmbedBuilder } from "discord.js"; 6import { entersState, createAudioPlayer, createAudioResource, joinVoiceChannel, StreamType, AudioPlayerStatus } from "@discordjs/voice"; 7const client = new Client({ 8 partials: [Partials.Channel], 9 intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent] 10}); 11let dynamic = { voice: {} }; 12client.on("ready", async () => { 13 console.log("準備完了です~"); 14}); 15client.on("messageCreate", async message => { 16 if (message.author.bot) return; 17 if (!dynamic.voice[message.guildId]) { 18 dynamic.voice[message.guildId] = { 19 connection: {}, 20 stream: {}, 21 resource: {}, 22 playing: null 23 }; 24 }; 25 const uservoice = String(message.member.voice.channel).replace("<#", "").replace(">", ""); 26 if (!dynamic.voice[message.guildId][uservoice] && uservoice != "null") { 27 dynamic.voice[message.guildId][uservoice] = { 28 repeat: 0, 29 volumes: 50, 30 playing: { 31 url: "", 32 username: "", 33 title: "", 34 time: "", 35 thumbnails: "" 36 }, 37 playlist: [], 38 selected: false 39 }; 40 }; 41 switch (message.content.split(" ")[0]) { 42 case "add": 43 const url = message.content.split(" ")[1]; 44 if (!uservoice) return message.reply(message.author.username + "さんがボイスチャットにいません...\n入ってからまたやってみてくださいね!"); 45 if (!ytdl.validateURL(url)) return message.reply("`" + url + "`が理解できませんでした..."); 46 const videoid = ytdl.getURLVideoID(url); 47 let title, time, thumbnails; 48 await ytdl.getInfo(url).then(info => { 49 const data = info.player_response.videoDetails; 50 title = data.title; time = data.lengthSeconds; thumbnails = data.thumbnail.thumbnails[0].url.split("?")[0]; 51 }); 52 dynamic.voice[message.guildId][uservoice].playlist.push({ url: videoid, username: message.author.username, title: title, time: time, thumbnails: thumbnails }); 53 54 const embed = new EmbedBuilder().setTitle("状態").setDescription("再生リストを表示します。"); 55 let list = ""; 56 for (let i = 0; i != dynamic.voice[message.guildId][uservoice].playlist.length; i++) { 57 list += "・" + (i + 1) + "本目"; 58 if (i == 0) list += "(次再生されます。)"; 59 list += "\n[**" + dynamic.voice[message.guildId][uservoice].playlist[i].title + "**](https://youtu.be/" + dynamic.voice[message.guildId][uservoice].playlist[i].url + ")" + 60 "(" + (await timeString(dynamic.voice[message.guildId][uservoice].playlist[i].time)) + ")\n"; 61 }; 62 if (!dynamic.voice[message.guildId][uservoice].playlist[0]) list = "リストの内容はありません。"; 63 embed.addFields({ name: "再生リスト", value: list }); 64 if (dynamic.voice[message.guildId][uservoice].playlist[0]) embed.setThumbnail(dynamic.voice[message.guildId][uservoice].playlist[dynamic.voice[message.guildId][uservoice].playlist.length - 1].thumbnails); 65 message.reply({ content: "追加ができました!", embeds: [embed] }); 66 break; 67 case "play": 68 if (!uservoice) return message.reply(message.author.username + "さんがボイスチャットにいません...\n入ってからまたやってみてくださいね!"); 69 if (dynamic.voice[message.guildId].playing == uservoice) return message.reply("既にVC再生をしています。"); 70 if (dynamic.voice[message.guildId].playing) return message.reply("既に別のVCで再生をしています。"); 71 if (!dynamic.voice[message.guildId][uservoice].playlist[0]) return message.reply("プレイリストが空です...`add [URL]`でプレイリストに追加してください!"); 72 73 dynamic.voice[message.guildId].connection = joinVoiceChannel({ 74 adapterCreator: message.guild.voiceAdapterCreator, 75 channelId: uservoice, 76 guildId: message.guildId, 77 selfDeaf: true 78 }); 79 ytplay(message.guildId, uservoice); 80 81 let viplay; 82 const embed2 = new EmbedBuilder().setTitle("状態").setDescription("全ての状態を表示します。"); 83 viplay = 84 "```タイトル: " + dynamic.voice[message.guildId][uservoice].playing.title + 85 "\n動画時間: " + (await timeString(dynamic.voice[message.guildId][uservoice].playing.time)) + 86 "\nURL: https://youtu.be/" + dynamic.voice[message.guildId][uservoice].playing.url + 87 "\n追加者: " + dynamic.voice[message.guildId][uservoice].playing.username + "```"; 88 if (dynamic.voice[message.guildId].playing != uservoice) viplay = "現在再生されていません。"; 89 embed2.addFields({ name: "再生中の曲の詳細", value: viplay }); 90 let vilist = ""; 91 for (let i = 0; i != dynamic.voice[message.guildId][uservoice].playlist.length; i++) { 92 vilist += "・" + (i + 1) + "本目"; 93 if (i == 0) vilist += "(次再生されます。)"; 94 vilist += "\n[**" + dynamic.voice[message.guildId][uservoice].playlist[i].title + "**](https://youtu.be/" + dynamic.voice[message.guildId][uservoice].playlist[i].url + ")" + 95 "(" + (await timeString(dynamic.voice[message.guildId][uservoice].playlist[i].time)) + ")\n"; 96 }; 97 if (!dynamic.voice[message.guildId][uservoice].playlist[0]) vilist = "リストの内容はありません。"; 98 embed2.addFields({ name: "再生リスト", value: vilist }); 99 embed2.setThumbnail(dynamic.voice[message.guildId][uservoice].playing.thumbnails); 100 message.reply({ content: "曲の再生を始めます!", embeds: [embed2] }); 101 break; 102 case "stop": 103 if (!uservoice) return message.reply(message.author.username + "さんがボイスチャットにいません...\n入ってからまたやってみてくださいね!"); 104 if (dynamic.voice[message.guildId].playing != uservoice) return message.reply("現在、音楽を再生していません。後で実行してください。"); 105 106 dynamic.voice[message.guildId].stream.destroy(); 107 dynamic.voice[message.guildId].connection.destroy(); 108 dynamic.voice[message.guildId].playing = null; 109 110 message.reply({ content: "曲を止めました~" }); 111 break; 112 case "skip": 113 output(outState.GetSubCommand, "skip"); 114 if (dynamic.voice[message.guildId].playing != voiceid) return message.reply("現在、音楽を再生していません。後で実行してください。"); 115 dynamic.voice[message.guildId].stream.destroy(); //ストリームの切断 116 message.reply("スキップしました!"); 117 ytplay(message.guildId, uservoice); 118 break; 119 case "console": 120 let json = dynamic; 121 if (Object.keys(json.voice)[0]) { 122 for (let i = 0; Object.keys(json.voice).length != i; i++) { 123 json.voice[Object.keys(json.voice)[i]].connection = {}; 124 json.voice[Object.keys(json.voice)[i]].stream = {}; 125 json.voice[Object.keys(json.voice)[i]].resource = {}; 126 }; 127 }; 128 fs.writeFile("dataOutput.json", JSON.stringify(decycle(json), null, "\t"), e => { if (e) throw e; }); 129 130 message.reply("voiceのデータを出力しました!出力ファイルを確認しましょう!"); 131 break; 132 }; 133}); 134const ytplay = async (guildId, voiceid) => { 135 if (dynamic.voice[guildId][voiceid].playlist[0]) { 136 dynamic.voice[guildId][voiceid].playing = dynamic.voice[guildId][voiceid].playlist[0]; 137 if (dynamic.voice[guildId][voiceid].repeat != 2) dynamic.voice[guildId][voiceid].playlist.shift(); 138 if (dynamic.voice[guildId][voiceid].repeat == 1) dynamic.voice[guildId][voiceid].playlist.push(dynamic.voice[guildId][voiceid].playing); 139 }; 140 dynamic.voice[guildId].playing = voiceid; 141 let player = createAudioPlayer(); 142 dynamic.voice[guildId].connection.subscribe(player); 143 dynamic.voice[guildId].stream = ytdl(dynamic.voice[guildId][voiceid].playing.url, { 144 filter: format => format.audioCodec === 'opus' && format.container === 'webm', 145 quality: "highest", 146 highWaterMark: 32 * 1024 * 1024, 147 }); 148 dynamic.voice[guildId].resource = createAudioResource(dynamic.voice[guildId].stream, { inputType: StreamType.WebmOpus, inlineVolume: true }); 149 dynamic.voice[guildId].resource.volume.setVolume(dynamic.voice[guildId][voiceid].volumes / 100); 150 151 player.play(dynamic.voice[guildId].resource); 152 await entersState(player, AudioPlayerStatus.Playing); 153 await entersState(player, AudioPlayerStatus.Idle); 154 ytplay(guildId, voiceid); 155}; 156/** 157 * 秒のデータを文字列として置き換えます。 158 * @param seconds - 秒数を入力します。 159 * @returns - 時間、分、秒が組み合わさった文字列を出力します。 160 */ 161const timeString = async seconds => { 162 let minutes = 0, hour = 0, timeset = ""; 163 try { 164 for (minutes; seconds > 59; minutes++) seconds -= 60; 165 for (hour; minutes > 59; hour++) minutes -= 60; 166 if (hour != 0) timeset += hour + "時間"; 167 if (minutes != 0) timeset += minutes + "分"; 168 if (seconds != 0) timeset += seconds + "秒"; 169 } catch (e) { output(outState.Error, e); }; 170 return timeset; 171}; 172client.login(process.env.token);

VCに入りadd https://youtu.be/00000000000で動画を追加し、playで再生。
再生中にconsoleと入力して再生が終わるまで待つとエラーが出ます。
consoleと入力した際、ファイルが出力されますのでご了承ください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

let output = data.voice;

outputdata.voice が同一のオブジェクトを指すようになるので、質問文のような結果になります。

対処としては、単純な代入ではなくディープコピーする必要があります。シンプルなコードでディープコピーするなら、let output = JSON.parse(JSON.stringify(data.voice)); でよいです。

投稿2022/10/02 23:06

int32_t

総合スコア20927

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sumwave

2022/10/02 23:21

めっちゃ早いですねΣ(・□・;) 超シンプルで超わかりやすい回答ありがとうございました! 一応用途も用途でコードが JSON.parse(JSON.stringify(decycle(dynamic[datanames]))) という大変な長さになりましたねぇ
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問