const { MongoClient } = require("mongodb") const { database_url, database_name } = require('../../config') const crypto = require("crypto") const time = require('../../lib/src/time') let max_database_connection_timeout = 1000 const client = new MongoClient(database_url, { serverSelectionTimeoutMS: max_database_connection_timeout, useUnifiedTopology: true }) const get_db = async () => { try { await client.connect() await client.db(database_name).command({ ping: 1 }) return client.db(database_name) } catch (err) { console.error('can not connect to database') await client.close() return null } } const get_titles = async (start, count) => { let db = await get_db() if (!db) { return null } let titles = await db.collection('title').find().skip(parseInt(start)).limit(parseInt(count)).toArray() return (!titles.length) ? null : titles } const get_titles_for_language = async (start, count, language) => { let db = await get_db() if (!db) { return null } let titles = await db.collection('title').find({language:language}).skip(parseInt(start)).limit(parseInt(count)).toArray() return (!titles.length) ? null : titles } const get_private_titles_with_key = async (key) => { let db = await get_db() if (!db) { return null } let titles = await db.collection('private_title').find({key:key}).toArray() return (!titles.length) ? null : titles } const get_free_session_servers = async (title) => { let db = await get_db() if (!db) { return null } let servers = await db.collection('session_server').find({title:title}).toArray() if (!servers.length) { return null } let active_session = db.collection('active_session') let free_servers = [] for (const server of servers) { let sessions = await active_session.find({server_url:server.url}).toArray() if (server.limit > sessions.length) { free_servers.push(server) } } return (free_servers.length) ? free_servers : null } const add_active_session = async (title, server_url, session_id, websocket_url) => { let db = await get_db() if (!db) { return false } let active_session = db.collection('active_session') await active_session.insertOne({ title: title, server_url: server_url, session_id: session_id, websocket_url: websocket_url }) return true } const generate_session_id = async () => { let db = await get_db() if (!db) { return null } let active_session = db.collection('active_session') let session_id = {} let max_id_len = 6 let sessions_with_id = 0 while(true) { session_id = crypto.randomBytes(max_id_len/2).toString('hex').toUpperCase() sessions_with_id = await active_session.find({session_id:session_id}).toArray().length if (!sessions_with_id) { return session_id } } } const get_active_session = async (session_id) => { let db = await get_db() if (!db) { return null } let active_session = await db.collection('active_session').findOne({session_id:session_id}) return active_session } const remove_active_session = async (session_id) => { let db = await get_db() if (!db) { return false } await db.collection('active_session').deleteOne({session_id:{$in:[session_id]}}) return true } const get_session_websocket_url = async (session_id) => { let db = await get_db() if (!db) { return null } let active_session = db.collection('active_session') let session = await active_session.findOne({session_id:session_id}) if (!session) { return null } return session.websocket_url } const get_statuses = async () => { let db = await get_db() if (!db) { return null } let statuses = await db.collection('status').find().toArray() return (!statuses.length) ? null : statuses } const get_all_session_servers = async () => { let db = await get_db() if (!db) { return null } let servers = await db.collection('session_server').find().toArray() if (!servers.length) { return null } return servers } const add_error = async (error_message) => { let db = await get_db() if (!db) { return false } let error_collection = db.collection('error_history') await error_collection.insertOne({error_message:error_message, time: time.get_date_time(), unix_timestamp: time.get_unix_timestamp()}) return true } const get_errors = async () => { let db = await get_db() if (!db) { return null } let errors = await db.collection('error_history').find().toArray() return (!errors.length) ? null : errors } const get_all_active_sessions = async () => { let db = await get_db() if (!db) { return null } let active_sessions = await db.collection('active_session').find().toArray() if (!active_sessions.length) { return null } return active_sessions } const add_session_to_history = async (session_id, title, server_url, websocket_url, max_uniq_users, users_at_close, time_start, unix_timestamp_start, time_end, unix_timestamp_end ) => { let db = await get_db() if (!db) { return false } let session_history = db.collection('session_history') let duration_in_seconds = unix_timestamp_end - unix_timestamp_start await session_history.insertOne({ session_id: session_id, title: title, server_url: server_url, websocket_url: websocket_url, max_uniq_users: max_uniq_users, users_at_close: users_at_close, time_start: time_start, unix_timestamp_start: unix_timestamp_start, time_end: time_end, unix_timestamp_end: unix_timestamp_end, duration_in_seconds: duration_in_seconds, duration_in_minutes: duration_in_seconds / 60 }) return true } const get_all_session_history = async () => { let db = await get_db() if (!db) { return null } let session_history = await db.collection('session_history').find().toArray() if (!session_history.length) { return null } return session_history } module.exports = { get_titles, get_free_session_servers, add_active_session, generate_session_id, remove_active_session, get_active_session, get_session_websocket_url, get_titles_for_language, get_private_titles_with_key, get_statuses, get_all_session_servers, add_error, get_errors, get_all_active_sessions, add_session_to_history, get_all_session_history }