はじめに
- heroku + electron でニコニコメソッドを作ってみました。でプレゼンテーションをインタラクティブにできるツールを作りましたが、機能を少し追加しました。
追加機能
- ルーム分け : コントローラからの入力を指定されたディスプレーのみに送信する機能。
どんなものか使ってみたい方は(64bit windows PC限定ですが)
- https://github.com/UC-SADA/package_file のgithubからzipをダウンロード
- 解凍後「nicoG_1_3-win32-x64」⇒「nicoG_1_3.exe」ファイルを実行。
- 下記ウィンドウが表示された、好きなルーム名を入力して ボタンをクリック。
- コントローラーウィンドウが起動します。
- 見えてませんが、透明なスクリーンが表示されているので、コントローラーのボタンをクリックしたり、テキスト入力するとスタンプが表示されたりニコニコの弾幕的な奴が流れます。
- 終了するときは実行ファイルを閉じつつ、タスクマネージャーで「nicoG_1_3.exe」を終了させてください。
実装内容
- 事前準備については「その1」を参考にしてください。
- 今回からテンプレートにjade を使って書いてみました。
- heroku側の実装内容については nico-chat-heroku_ver2にソースコードをアップしています。
- electron側の実装内容については niconico-Displayにソースコードをアップしています
heroku 側の実装内容
index.js
"use strict";
const createError = require('http-errors');
const path = require('path');
const express = require('express');
const app = require('express')();
const http = require('http').Server(app);
module.exports.io = require('socket.io')(http);
const extend = require('util')._extend
const cookieParser = require('cookie-parser');
const session = require("express-session");
const logger = require('morgan');
http.listen(process.env.PORT || 2525, function(){
console.log("PORT : " + (process.env.PORT || 2525));
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser("secret","mycom_secret_key"));
app.use(session({key:"session_id"}));
// Router
const indexRouter = require('./routes/index');
const nicoRouter = require('./routes/nico');
const displayRouter = require('./routes/display');
const controllerRouter = require('./routes/controller');
app.use('/', indexRouter);//TOPページ
app.use("/public",express.static(path.join(__dirname, 'public')));//ニコニコするJavascriptを格納。
app.use('/nico', nicoRouter); //ニコニコの処理
app.use('/display', displayRouter); //このURLをelectronの透明スクリーンで表示
app.use('/controller', controllerRouter); //このURLが配布用に
ここまではほぼExpressのテンプレート通りで各処理ごとにapp.useに割り当て。
nico
/:room_id/:name を追加してルーム名ごとの割り振り
app.io.to(req.params.room_id).emit('like', msg) でルームにメッセージ送信
socket.join(room); 後述、Display画面のルーム指定に使います。
var express = require('express');
var router = express.Router();
var app = require("../index");
var extend = require('util')._extend;
app.io.sockets.on('connection', function(socket) {
socket.on('client_to_server_join', function(room) {
socket.join(room);
});
router.get('/like/:room_id/:name', function (req, res) {
const msg = extend({}, req.query);
app.io.to(req.params.room_id).emit('like', msg);
res.end();
});
router.get('/comment/:room_id/:name', function(req, res) {
const msg = extend({}, req.query);
app.io.to(req.params.room_id).emit('comment', msg);
res.end()
});
});
module.exports = router;
controller
/:room_id/:name をコントローラ画面にも追加。
room : req.params.room_id,
name : req.params.name,
でjadeに受け渡し、
router.get('/:room_id/:name', function(req, res, next) {
var msg = req.params.name + "さんで<BR>" + "「" + req.params.room_id + "」ルームにログインしています。";
res.render("controller",{
room:req.params.room_id,
name:req.params.name,
msg : msg
});
});
.jadeの中で
#{room}/#{name}
で受け取り nico.js に受け渡し
function handleSubmit (form) {
const action = $(form).attr('action')
const params = $(form).serialize()
const url = `${action}/#{room}/#{name}/?${params}`
console.log(url)
$.get(url)
.fail(function () {
alert('failed to send message.')
});
}
function like (type) {
const url = `/nico/like/#{room}/#{name}/?image=${type}`
console.log(url)
$.get(url)
.fail(function () {
alert('failed to like.')
})
}
Display
/:room_id/:name をDisplay画面にも追加。
room : req.params.room_id,
name : req.params.name,
でjadeに受け渡し、
router.get('/:room_id/:name', function(req, res, next) {
var room = req.params.room_id
var name = req.params.name
res.render("display",{
room:room,
name:name
});
});
.jadeの中で
socket.emit("client_to_server_join", "#{room}"); でルームの指定
script(type='text/javascript').
var socket = io.connect();
socket.emit("client_to_server_join", "#{room}");
socket.on('comment', function(msg){
handleComment (msg) ;
});
socket.on('like', function(msg){
handleLike (msg) ;
});
できたらコマンドプロンプト画面でheroku側のディレクトリまで移動し下記コマンドで起動
$ node index
electron 側の実装内容
index
ルーム名を入力する簡単なwindowを作成。
"use strict";
const electron = require('electron');
const elc_app = electron.app;
let inputWindow;
elc_app.on('ready', function (event) {
inputWindow = new electron.BrowserWindow({
width: 300,
height: 180,
});
inputWindow.loadURL('file://' + __dirname + '/input.html');
});
input.htmlの中で
ルーム名をテキスト入力してボタンを押したら
win.loadURL("https://nico-chat.herokuapp.com/display/" + room) というURLの透明スクリーンのブラウザで起動し
win2.loadURL("https://nico-chat.herokuapp.com/controller/" + room); というURLを普通のブラウザで起動
window.close(); でインプットウィンドウを閉じる。
localhostで動かす場合はそれぞれ、
win.loadURL("localhost:2525/display/" + room)
win.loadURL("localhost:2525/controller/" + room)
に変更
<html>
<head>
<meta charset="UTF-8">
<title>Room</title>
</head>
<body>
<p>開くルームを入力してください。</p>
<input type="text" id="room">
<button id="nico-window">Open niconico-Display</button>
<script>
const electron = require("electron")
const BrowserWindow = require('electron').remote.BrowserWindow
const path = require('path')
const nicoWindowBtn = document.getElementById('nico-window')
let win
let win2
// ボタンクリック時に、レンダラープロセスから別ウィンドウを表示
nicoWindowBtn.addEventListener('click', function(event) {
var room = document.getElementById('room').value
var size = electron.screen.getPrimaryDisplay().size;
win = new BrowserWindow({
left: 0,
top: 0,
width: size.width,
height: size.height,
frame: false,
show: true,
transparent: true,
resizable: true,
webPreferences: {nodeIntegration: false}
});
win.setIgnoreMouseEvents(true);
win.maximize();
win.setAlwaysOnTop(true);
win.loadURL("https://nico-chat.herokuapp.com/display/" + room)
// win.loadURL("localhost:2525/display/" + room)
win2 = new BrowserWindow({
left: 0,
top: 0,
width: 400,
height: size.height,
frame: true,
show: true,
transparent: false,
resizable: true,
webPreferences: {nodeIntegration: false}
});
win2.loadURL("https://nico-chat.herokuapp.com/controller/" + room);
// win.loadURL("localhost:2525/controller/" + room)
window.close();
})
</script>
</body>
<html>
できたらコマンドプロンプト画面でelectron側のディレクトリまで移動し下記コマンドで起動
$ electron .