LoginSignup
3
1

More than 5 years have passed since last update.

Discordに画像を投稿するBOT #1準備編

Last updated at Posted at 2019-03-09

以前Weakened Fun Timeで作っていたスクリーンショットをDiscordに投稿するボットは、大分前にメンテナンスを放棄してしまった。というのも、以前のバージョンはコマンドライン上で動かすので使い勝手が悪く、かといってElectronで作るのも大変だしメモリを食うし微妙になってしまったためだ。

なので最近のWebアプリ風に、ブラウザから設定できるようにしようと思う。こうすれば、スマホやタブレット上で操作できるようになり、ゲーム中でも操作できるようになる。

やろうとしてること

  • スクリーンショットフォルダに追加された画像をDiscordに投稿する
  • 画像はPNG→JPGに変換する(FullHDだと5MBくらいなのでDiscordのレートリミットにすぐ引っかかる)
  • 投稿先のサーバ・チャネルを設定できる
  • 投稿のON/OFFを切り替えられる
  • ゲーム中でも設定できる(スマホやタブレットから設定できる)

準備

最初に空のプロジェクトを立ち上げることから始める。設定画面を作るAngularのプロジェクトをclientに作成し、設定画面をブラウザに送るサNestJSサーバのプロジェクトをserverに作成する。

npm install -g @angular/cli
ng new client

npm install -g @nestjs/cli
nest new server

ブラウザでAngularの画面を表示する

まず、クライアント側の設定を変更する。client/angular.jsonoutputPathを変更し、Angularプロジェクトのビルド結果を、server/public以下に置くように設定変更する。

これをサーバで表示できるように、server/main.tsで静的ファイルのパスを設定する。

server/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { join } from 'path';

async function bootstrap() {
    const app = await NestFactory.create( AppModule );

    app.useStaticAssets( join( __dirname, '..', 'public') );    // server/public にバンドルしたファイルを置く

    await app.listen( 3000 );   // TODO: コマンドライン引数でポートを変えられるようにする
}
bootstrap();

この変更後、以下コマンドでサーバを立ち上げる。

npm run start
または
npm run start:dev

そして自PCからlocalhost:3000を開くか、LAN内のPCから<IP>:3000を開くかすると、以下のような画面が現れるはずである。これで、基本的な準備が完了する。
image.png

ブラウザからDiscordのBOTを操作する

試しに、DiscordのBotを操作する簡単なREST APIを設けてみる。ここまでに用意したAngular画面にボタンやテキストボックスを配置し、そこからNestJSで用意したREST APIを操作できるようにしてみる。

コードはGitHub参照
image.png

バックエンド抜粋: コントローラ

とりあえず簡易REST APIで操作できるよう、servermessageという2つのエンドポイントを用意する。serverでは、リクエストボディのactiveプロパティの値(truefalse)で、接続・切断を切り替えられるようにする。messageでは、messageプロパティの値をそのままDiscordのボットに送信する。ボットや送信先のチャネルはconfig.ts内で定義してある。(GitHubには入れていない)

コントローラ
import { Controller, Get, Body, Res, Post, Patch } from '@nestjs/common';
import { ApiModelProperty, ApiResponse } from '@nestjs/swagger';

import { DiscordBotService } from './service'

export class MessageDto {
    @ApiModelProperty( { required: true } )
    message: string;
}

export class ServerStatusDto {
    @ApiModelProperty( { required: true } )
    active: boolean;
}

@Controller()
export class DiscordBotController {
    constructor( private bot$: DiscordBotService ) {}

    @Post('message')
    async message( @Body() message: MessageDto ) {
        await this.bot$.send( message.message );
    }

    @Patch('server')
    async connect( @Body() serverStatus: ServerStatusDto ) {
        if( serverStatus.active ) {
            await this.bot$.connect();
        } else {
            await this.bot$.disconnect();
        }
    }   
}

フロントエンド抜粋:操作画面

上記のバックエンドの2つのエンドポイントを操作するメソッドを用意し、簡易画面から操作できるようにする。
image.png

Angularコンポーネント
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component( {
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss']
} )
export class AppComponent {
    message: string = '';

    constructor( private http$: HttpClient ) {}

    async connect() {
        await this.http$.patch( '/server', { "active": true } ).toPromise();
    }

    async disconnect() {
        await this.http$.patch( '/server', { "active": false } ).toPromise();
    }

    async send() {
        await this.http$.post( '/message', { "message": this.message } ).toPromise();
        this.message = '';
    }
}

動作イメージ

コード: https://github.com/WeakenedPlayer/botty/releases/tag/0.0.3
動作イメージ

3
1
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
3
1