<commit_before>'use strict';

const Application = require('./documentModels/application');
const ApplicationAccess = require('./documentModels/applicationAccess');
const ioServer = require('socket.io');
const redis = require('redis');
const methods = require('methods');

module.exports = (http, directoryRouter, subscribers, db, config) => {
	const ioServerToClient = ioServer(http);

	const checkAuthorization = async (clientManager, applicationKey, accessKey) => {
		if (applicationKey == null) {
			clientManager.stream('authorization', {success: false, message: 'applicationKey parameter is empty'});
			return null;
		}

		if (accessKey == null) {
			clientManager.stream('authorization', {success: false, message: 'accessKey parameter is empty'});
			return null;
		}

		if (!await Application.verifyKeyAsync(applicationKey, db, config)) {
			clientManager.stream('authorization', {success: false, message: 'applicationKey parameter is invalid'});
			return null;
		}

		if (!await ApplicationAccess.verifyKeyAsync(accessKey, db, config)) {
			clientManager.stream('authorization', {success: false, message: 'accessKey parameter is invalid'});
			return null;
		}

		clientManager.stream('authorization', {success: true, message: 'successful authorization'});
		return {
			applicationId: Application.splitKey(applicationKey, db, config).applicationId,
			userId: ApplicationAccess.splitKey(accessKey, db, config).userId
		};
	};

	const timelineTypes = ['public', 'home'];

	ioServerToClient.sockets.on('connection', ioServerToClientSocket => {
		(async () => {
			const clientManager = new (require('./helpers/server-streaming-manager'))(ioServerToClient, ioServerToClientSocket, {});

			const applicationKey = ioServerToClientSocket.handshake.query.applicationKey;
			const accessKey = ioServerToClientSocket.handshake.query.accessKey;
			const checkResult = await checkAuthorization(clientManager, applicationKey, accessKey);
			if (checkResult == null) {
				return clientManager.disconnect();
			}
			const userId = checkResult.userId;
			const applicationId = checkResult.applicationId;

			ioServerToClientSocket.application = (await db.applications.findByIdAsync(applicationId));
			ioServerToClientSocket.user = (await db.users.findByIdAsync(userId));

			// クライアント側からRESTリクエストを受信したとき
			clientManager.on('rest', data => {
				(async () => {
					if (data.request.method == null || data.request.endpoint == null) {
						return clientManager.stream('rest', {success: false, message: 'request format is invalid'});
					}

					if (data.request.endpoint.indexOf('..') != -1)
						return clientManager.stream('rest', {success: false, message: '\'endpoint\' parameter is invalid'});

					const method = methods.find(i => i.toLowerCase() === data.request.method.toLowerCase()).toLowerCase();

					if (method == null)
						return clientManager.stream('rest', {success: false, message: '\'method\' parameter is invalid'});

					let params = [];
					let routeFuncAsync;
					try {
						const route = directoryRouter.findRoute(data.request.method, data.request.endpoint, params);
						routeFuncAsync = (require(route.getMoludePath()))[method];
					}
					catch(e) {
						console.log('error: faild to parse route info');
						console.log('reason: ' + e);
					}

					if (routeFuncAsync == null)
						return clientManager.stream('rest', {success: false, message: '\'endpoint\' parameter is invalid'});

					const req = {
						method: data.request.method,
						endpoint: data.request.endpoint,
						query: data.request.query,
						params: params,
						headers: data.request.headers,
						body: data.request.body,
						db: db,
						config: config,
						user: ioServerToClientSocket.user,
						application: ioServerToClientSocket.application
					};

					require('./helpers/middlewares/checkRequest')(req);

					const apiResult = await routeFuncAsync(req);

					if (apiResult.statusCode == null)
						apiResult.statusCode = 200;

					let sendData;
					if (typeof apiResult.data == 'string')
						sendData = {message: apiResult.data};
					else if (apiResult.data != null)
						sendData = apiResult.data;
					else
						sendData = {};

					return clientManager.stream('rest', {success: true, request: data.request, response: sendData, statusCode: apiResult.statusCode});
				})();
			});

			let publicSubscriber = null;
			let homeSubscriber = null;

			// クライアント側からタイムラインの購読リクエストを受信したとき
			clientManager.on('timeline-connect', data => {
				const timelineType = data.type;

				if (timelineType == null)
					return clientManager.stream('timeline-connect', {success: false, message: '\'type\' parameter is require'});

				if (!timelineTypes.some(i => i == timelineType))
					return clientManager.stream('timeline-connect', {success: false, message: '\'type\' parameter is invalid'});

				// Redis: 購読状態の初期化
				if (timelineType == timelineTypes[0]) { // public
					if (publicSubscriber != null)
						return clientManager.stream('timeline-connect', {success: false, message: 'public timeline is already subscribed'});
<commit_msg>update streaming server<commit_after>'use strict';

const Application = require('./documentModels/application');
const ApplicationAccess = require('./documentModels/applicationAccess');
const ioServer = require('socket.io');
const redis = require('redis');
const methods = require('methods');

module.exports = (http, directoryRouter, subscribers, db, config) => {
	const ioServerToClient = ioServer(http);

	const checkAuthorization = async (clientManager, applicationKey, accessKey) => {
		if (applicationKey == null) {
			clientManager.stream('authorization', {success: false, message: 'applicationKey parameter is empty'});
			return null;
		}

		if (accessKey == null) {
			clientManager.stream('authorization', {success: false, message: 'accessKey parameter is empty'});
			return null;
		}

		if (!await Application.verifyKeyAsync(applicationKey, db, config)) {
			clientManager.stream('authorization', {success: false, message: 'applicationKey parameter is invalid'});
			return null;
		}

		if (!await ApplicationAccess.verifyKeyAsync(accessKey, db, config)) {
			clientManager.stream('authorization', {success: false, message: 'accessKey parameter is invalid'});
			return null;
		}

		clientManager.stream('authorization', {success: true, message: 'successful authorization'});
		return {
			applicationId: Application.splitKey(applicationKey, db, config).applicationId,
			userId: ApplicationAccess.splitKey(accessKey, db, config).userId
		};
	};

	const timelineTypes = ['public', 'home'];

	ioServerToClient.sockets.on('connection', ioServerToClientSocket => {
		(async () => {
			const clientManager = new (require('./helpers/server-streaming-manager'))(ioServerToClient, ioServerToClientSocket, {});

			const applicationKey = ioServerToClientSocket.handshake.query.applicationKey;
			const accessKey = ioServerToClientSocket.handshake.query.accessKey;
			const checkResult = await checkAuthorization(clientManager, applicationKey, accessKey);
			if (checkResult == null) {
				return clientManager.disconnect();
			}
			const userId = checkResult.userId;
			const applicationId = checkResult.applicationId;

			ioServerToClientSocket.application = (await db.applications.findByIdAsync(applicationId));
			ioServerToClientSocket.user = (await db.users.findByIdAsync(userId));

			// クライアント側からRESTリクエストを受信したとき
			clientManager.on('rest', data => {
				(async () => {
					const method = data.request.method.toLowerCase();
					const endpoint = data.request.endpoint;
					const query = data.request.query;
					const headers = data.request.headers;
					const body = data.request.body;

					if (method == null || endpoint == null) {
						return clientManager.stream('rest', {success: false, message: 'request format is invalid'});
					}

					if (endpoint.indexOf('..') != -1)
						return clientManager.stream('rest', {success: false, message: '\'endpoint\' parameter is invalid'});

					if (methods.find(i => i.toLowerCase() === method) == null)
						return clientManager.stream('rest', {success: false, message: '\'method\' parameter is invalid'});

					let routeFuncAsync;
					let params = [];
					try {
						const route = directoryRouter.findRoute(method, endpoint);
						routeFuncAsync = (require(route.getMoludePath()))[method];
						params = route.getParams(endpoint);
					}
					catch(e) {
						console.log('error: faild to parse route info');
						console.log('reason: ' + e);
					}

					if (routeFuncAsync == null)
						return clientManager.stream('rest', {success: false, message: '\'endpoint\' parameter is invalid'});

					const req = {
						method: method,
						endpoint: endpoint,
						query: query,
						params: params,
						headers: headers,
						body: body,
						db: db,
						config: config,
						user: ioServerToClientSocket.user,
						application: ioServerToClientSocket.application
					};

					require('./helpers/middlewares/checkRequest')(req);

					const apiResult = await routeFuncAsync(req);

					if (apiResult.statusCode == null)
						apiResult.statusCode = 200;

					let sendData;
					if (typeof apiResult.data == 'string')
						sendData = {message: apiResult.data};
					else if (apiResult.data != null)
						sendData = apiResult.data;
					else
						sendData = {};

					console.log('rest event:', method, endpoint, 'res code:', apiResult.statusCode);
					return clientManager.stream('rest', {success: true, request: data.request, response: sendData, statusCode: apiResult.statusCode});
				})();
			});

			let publicSubscriber = null;
			let homeSubscriber = null;

			// クライアント側からタイムラインの購読リクエストを受信したとき
			clientManager.on('timeline-connect', data => {
				const timelineType = data.type;

				if (timelineType == null)
					return clientManager.stream('timeline-connect', {success: false, message: '\'type\' parameter is require'});

				if (!timelineTypes.some(i => i == timelineType))
					return clientManager.stream('timeline-connect', {success: false, message: '\'type\' parameter is invalid'});

				// Redis: 購読状態の初期化
				if (timelineType == timelineTypes[0]) { // public
					if (publicSubscriber != null)
						return clientManager.stream('timeline-connect', {success: false, message: 'public timeline is already subscribed'});

{'fraction_non_alphanumeric': 0.13420081569236744, 'fraction_numerical': 0.0009710623422023694, 'mean_word_length': 4.060933660933661, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '736735', 'n_tokens_mistral': 3615, 'n_tokens_neox': 2921, 'n_words': 700}