0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【VRChat】OSCを使ってDiscordからチャットボックスに入力する

Posted at

OSCを使ってDiscordからチャットボックスに入力する

こんにちは。VRChat始めたてのぽよたんぴです。
VRChatにはマイクがなくても会話できる「チャットボックス」という機能があります。

ですが、文字を打ってる間は移動などができません(当然ですが)
そこで、VRChatにはOSC1という、外部アプリからVRChatを制御できるAPIのようなものがあります。
今回はOSCとDiscordを使用して、スマホ版Discordから入力した文字をチャットボックスに送信するプログラムを作成していきます。

必要なもの

  • VRChat
  • Node.js
  • Discord

OSCを有効化

VRChatを開き、アクションメニューを開きます

アクションメニューの開き方
  • デスクトップ: Rキー
  • Viveコントローラー: メニューボタン長押し
  • Oculus Touch: B、Y長押し
  • Indexコントローラー: B長押し

参考: リンク

image.png
アクションメニューから「オプション」を選択します

image.png
「OSC」を選択します

image.png
「有効」をONにします

Discord BOTを新規作成

Discord Developer Portalをブラウザ開きます。

ブラウザでDiscordのアカウントにログインしている必要があります

image.png
右上の「New Application」をクリックします。

image.png
お好きなアプリケーション名を入力します。

image.png
左のサイドバーから「BOT」をクリックし、
TOKENの項目にある「Reset Token」をクリックします。

image.png
「本当にBOTのトークンをリセットする?」という確認画面が出てくるので、
「Yes, Do it!」をクリックします。

image.png

ここで二段階認証を求められます。(以下2FAと略します)
「あれ、2FAなんて設定してないよ?」っていう方も居ると思います。
実はこの2FAの入力が画面、実は2FAの入力画面ではありません (え?)
2FAを設定していない場合は「Enter your password」(パスワードを入力)
2FAを設定している場合は「6-digit authentication code」(6桁のコードを入力)
となっていることに注意してください。

image.png
認証コード(またはパスワード)を入力するとこのようにTokenという文字列が出てくると思いますので、忘れないようにメモしておいてください。
これはプログラムからBOTにログインするときに使うもので、
トークンさえあれば誰でもBOTにログインできてしまうので、他人に公開してはいけません。

トークンは一度しか表示されないので、紛失してしまったら再生成しなければなりません。
トークンをリセットすると、元々あったトークンは無効になります。

その後、少し下の方にある「Message Content Intent」という項目を有効化してください。

image.png

この設定は「Botがメッセージの内容を取得できるようにしますか?」という項目です。
この設定を忘れると、この後にプログラムからログインするときに失敗します。

プログラムの実装

ここからは、Node.jsを使用してプログラムを書いていきます。

依存関係をインストール

以下のコマンドで必要なライブラリを入れます。

$ npm i discord.js node-osc

(今回はnpmを使っていますが、yarn2やnpm3などを使うのをおすすめします)

config.jsonを作成

できるだけトークンなどはコード上にハードコードしないほうがいいので、
別のjsonファイルに書いていきます。

内容は適宜置き換えてください。
ユーザーID・チャンネルIDを取得する方法

config.json (例)
{
  "oscPort": 9000,
  "allowedUsers": ["ユーザーID"],
  "discordToken": "トークン",
  "channelId": "DiscordのチャンネルID"
}

コーディング

index.jsというファイルを作成し、ここにコードを書いていきます。

まずライブラリや先程作ったconfig.jsonを読み込みます。

const { Client: DiscordClient, IntentsBitField } = require("discord.js");
const { Client: OSCClient, Message } = require("node-osc");
const config = require("./config.json");

//許可されたユーザー一覧(Discord)
const allowedUserIds = new Set(config.allowedUsers);

VRChatにメッセージを送信できるユーザーを制限するために、
configに許可されているユーザーID一覧を書き、
Setを使用して重複を取り除いています。

変数定義・初期化

タイピング表示に使う変数を定義します。

let typingTimeoutId;
let isTyping = false;

OSCクライアントを初期化します。

//OSCクライアントを初期化
const oscClient = new OSCClient("127.0.0.1", config.oscPort);

Discordクライアントも初期化します。

//Discordクライアントの初期化
const discordClient = new DiscordClient({
    intents: [
        IntentsBitField.Flags.Guilds, //サーバー一覧を受信
        IntentsBitField.Flags.GuildMessages, //サーバーのメッセージを受信
        IntentsBitField.Flags.GuildMessageTyping, //タイピングを受信
        IntentsBitField.Flags.MessageContent //メッセージの内容を受信
    ]
});

※ここでIntentsを指定しておかないと、メッセージの内容やタイピングの受信ができません。

Discordにログインした際に、BOTの名前をログに出すようにします。

discordClient.on("ready", () => {
    console.log(`[Discord] Logined as ${discordClient.user.username}`)
})

タイピング状態の更新

Discordでタイピングした際にisTypingtrueにし、
10秒以内に再度タイピングのイベントが発生しなければisTypingfalseにするコードを書いていきます。

//Discordでタイピングを開始した時のイベント
discordClient.on("typingStart", (event) => {
    if(!allowedUserIds.includes(event.user.id)) return;

    //タイマーが重複しないように、すでにあるタイマーを解除
    clearTimeout(typingTimeoutId);
    
    //10秒後にタイピングを解除
    typingTimeoutId = setTimeout(() => {
        isTyping = false;
    }, 10000);
    
    isTyping = true;
});

定期的にタイピング状態を送信

OSC経由で/chatbox/typing(パラメータはbool)に送信することで、
チャットボックスのタイピング中の表示を変更できます。

パラメータにタイピングしているかしていなかの状態を指定します。

//毎秒(1000msごとに)実行
setInterval(() => {
    //VRChatに送信
    oscClient.send(new Message("/chatbox/typing", isTyping));
}, 1000);

チャットボックスへ送信

ここが一番重要な部分です。
/chatbox/input(パラメータはstring, bool, bool)に送信することで、
チャットボックスへの入力ができます。

1つ目のパラメータには内容を指定します。
2つ目のパラメータがtrueの場合はキーボード画面を表示せずに即座に送信されます。
3つ目のパラメータをfalseにすると通知の効果音を鳴らしません。

//Discordにメッセージを送信した時のイベント
discordClient.on("messageCreate", (event) => {
    //フィルタ
    if(!event.member || !allowedUserIds.includes(event.member?.id)) return;
    if(event.channelId != config.channelId) return;
    //タイピング状態を解除
    isTyping = false;
    //VRChatに送信
    oscClient.send(new Message("/chatbox/input", event.content, true, true));
    console.log(`[Send] ${event.content}`);
});

Discordにログイン

最後にDiscordにログインする処理を書きます。

//Discordにログイン
discordClient.login(config.discordToken);

実行

以下のコマンドで起動できます。

$ node index.js

[Discord] Logined as BOTの名前 と表示されたらDiscordへのログイン成功です。
先程指定したチャンネルIDのチャンネルにメッセージを打ち、
チャットボックスに反映されるか確認してみてください。

全体のコードはこちらに置いてあります。
https://github.com/poyotanp/osc-discord-vrc/blob/master/index-node.js

  1. https://docs.vrchat.com/docs/osc-overview

  2. https://yarnpkg.com/

  3. https://pnpm.io/ja/

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?