@ -0,0 +1,55 @@
|
|||||||
|
// admin/otp.js
|
||||||
|
// Copyright (C) 2021 Digital Telepresence, LLC
|
||||||
|
// License: Apache-2.0
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const express = require('express');
|
||||||
|
// const multer = require('multer');
|
||||||
|
|
||||||
|
const { SiteController, SiteError } = require('../../../lib/site-lib');
|
||||||
|
|
||||||
|
class OtpAdminController extends SiteController {
|
||||||
|
|
||||||
|
constructor (dtp) {
|
||||||
|
super(dtp, module.exports);
|
||||||
|
}
|
||||||
|
|
||||||
|
async start ( ) {
|
||||||
|
// const upload = multer({ dest: `/tmp/${this.dtp.config.site.domainKey}/uploads/${module.exports.slug}` });
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
router.use(async (req, res, next) => {
|
||||||
|
res.locals.currentView = 'admin';
|
||||||
|
res.locals.adminView = 'otp';
|
||||||
|
return next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// router.param('otp', this.populateOtp.bind(this));
|
||||||
|
|
||||||
|
router.get('/', this.getIndex.bind(this));
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getIndex (req, res, next) {
|
||||||
|
try {
|
||||||
|
const { otpAuth: otpAuthService } = this.dtp.services;
|
||||||
|
if (!req.user) {
|
||||||
|
throw new SiteError(402, "Error getting user");
|
||||||
|
}
|
||||||
|
res.locals.tokens = await otpAuthService.getBackupTokens(req.user, "Admin");
|
||||||
|
res.render('admin/otp/index');
|
||||||
|
} catch (error) {
|
||||||
|
this.log.error('failed to get tokens', { error });
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'adminOtp',
|
||||||
|
slug: 'admin-opt',
|
||||||
|
create: async (dtp) => { return new OtpAdminController(dtp); },
|
||||||
|
};
|
@ -0,0 +1,97 @@
|
|||||||
|
// post.js
|
||||||
|
// Copyright (C) 2021 Digital Telepresence, LLC
|
||||||
|
// License: Apache-2.0
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const express = require('express');
|
||||||
|
// const multer = require('multer');
|
||||||
|
|
||||||
|
const { SiteController, SiteError } = require('../../lib/site-lib');
|
||||||
|
|
||||||
|
class TagController extends SiteController {
|
||||||
|
|
||||||
|
constructor (dtp) {
|
||||||
|
super(dtp, module.exports);
|
||||||
|
}
|
||||||
|
|
||||||
|
async start ( ) {
|
||||||
|
const { dtp } = this;
|
||||||
|
// const {
|
||||||
|
// post: postService,
|
||||||
|
// limiter: limiterService,
|
||||||
|
// session: sessionService,
|
||||||
|
// } = dtp.services;
|
||||||
|
|
||||||
|
// const authRequired = sessionService.authCheckMiddleware({ requiredLogin: true });
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
dtp.app.use('/tag', router);
|
||||||
|
|
||||||
|
router.use(async (req, res, next) => {
|
||||||
|
res.locals.currentView = 'home';
|
||||||
|
return next();
|
||||||
|
});
|
||||||
|
|
||||||
|
router.param('tagSlug', this.populateTagSlug.bind(this));
|
||||||
|
|
||||||
|
router.get('/:tagSlug', this.getSearchView.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
async populateTagSlug (req, res, next, tagSlug) {
|
||||||
|
const { post: postService } = this.dtp.services;
|
||||||
|
try {
|
||||||
|
var allPosts = false;
|
||||||
|
var statusArray = ['published'];
|
||||||
|
if (req.user) {
|
||||||
|
if (req.user.flags.isAdmin) {
|
||||||
|
statusArray.push('draft');
|
||||||
|
allPosts = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.locals.allPosts = allPosts;
|
||||||
|
res.locals.tagSlug = tagSlug;
|
||||||
|
tagSlug = tagSlug.replace("_", " ");
|
||||||
|
res.locals.pagination = this.getPaginationParameters(req, 20);
|
||||||
|
res.locals.posts = await postService.getByTags(tagSlug, res.locals.pagination, statusArray);
|
||||||
|
res.locals.tag = tagSlug;
|
||||||
|
return next();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.log.error('failed to populate tagSlug', { tagSlug, error });
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSearchView (req, res) {
|
||||||
|
try {
|
||||||
|
res.locals.pageTitle = `Tag ${res.locals.tag} on ${this.dtp.config.site.name}`;
|
||||||
|
|
||||||
|
res.render('tag/view');
|
||||||
|
} catch (error) {
|
||||||
|
this.log.error('failed to service post view', { postId: res.locals.post._id, error });
|
||||||
|
throw SiteError("Error getting tag view:", error );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getIndex (req, res, next) {
|
||||||
|
const { post: postService } = this.dtp.services;
|
||||||
|
try {
|
||||||
|
res.locals.pagination = this.getPaginationParameters(req, 20);
|
||||||
|
res.locals.posts = await postService.getPosts(res.locals.pagination);
|
||||||
|
res.render('tag/index');
|
||||||
|
} catch (error) {
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
slug: 'tag',
|
||||||
|
name: 'tag',
|
||||||
|
create: async (dtp) => {
|
||||||
|
let controller = new TagController(dtp);
|
||||||
|
return controller;
|
||||||
|
},
|
||||||
|
};
|
@ -1,53 +0,0 @@
|
|||||||
// media-router.js
|
|
||||||
// Copyright (C) 2022 DTP Technologies, LLC
|
|
||||||
// License: Apache-2.0
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const mongoose = require('mongoose');
|
|
||||||
|
|
||||||
const Schema = mongoose.Schema;
|
|
||||||
|
|
||||||
const STATUS_LIST = [
|
|
||||||
'starting', // the router process is starting and configuring itself
|
|
||||||
'active', // the router is active and available for service
|
|
||||||
'capacity', // the router is at or over capacity
|
|
||||||
'closing', // the router is closing/shutting down
|
|
||||||
'closed', // the router no longer exists
|
|
||||||
];
|
|
||||||
|
|
||||||
const RouterHostSchema = new Schema({
|
|
||||||
address: { type: String, required: true, index: 1 },
|
|
||||||
port: { type: Number, required: true },
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A Router is a "multi-user conference call instance" somewhere on the
|
|
||||||
* infrastructure. This model helps us manage them, balance load across them,
|
|
||||||
* and route calls to and between them (for scale).
|
|
||||||
*
|
|
||||||
* These records are created when a call is being created, and are commonly
|
|
||||||
* left in the database after all call participants have left. An expires index
|
|
||||||
* is used to sweep up router records after 30 days. This allows us to perform
|
|
||||||
* statistics aggregation on router use and store aggregated results as part of
|
|
||||||
* long-term reporting.
|
|
||||||
*/
|
|
||||||
const MediaRouterSchema = new Schema({
|
|
||||||
created: { type: Date, default: Date.now, required: true, expires: '30d' },
|
|
||||||
lastActivity: { type: Date, default: Date.now, required: true },
|
|
||||||
status: { type: String, enum: STATUS_LIST, default: 'starting', required: true, index: true },
|
|
||||||
name: { type: String },
|
|
||||||
description: { type: String },
|
|
||||||
access: {
|
|
||||||
isPrivate: { type: Boolean, default: true, required: true },
|
|
||||||
passcodeHash: { type: String, select: false },
|
|
||||||
},
|
|
||||||
host: { type: RouterHostSchema, required: true, select: false },
|
|
||||||
stats: {
|
|
||||||
routerCount: { type: Number, default: 0, required: true },
|
|
||||||
consumerCount: { type: Number, default: 0, required: true },
|
|
||||||
producerCount: { type: Number, default: 0, required: true },
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = mongoose.model('MediaRouter', MediaRouterSchema);
|
|
@ -1,43 +0,0 @@
|
|||||||
// media-worker.js
|
|
||||||
// Copyright (C) 2022 DTP Technologies, LLC
|
|
||||||
// License: Apache-2.0
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const mongoose = require('mongoose');
|
|
||||||
|
|
||||||
const Schema = mongoose.Schema;
|
|
||||||
|
|
||||||
const STATUS_LIST = [
|
|
||||||
'starting', // the router process is starting and configuring itself
|
|
||||||
'active', // the router is active and available for service
|
|
||||||
'capacity', // the router is at or over capacity
|
|
||||||
'closing', // the router is closing/shutting down
|
|
||||||
'closed', // the router no longer exists
|
|
||||||
];
|
|
||||||
|
|
||||||
const WebRtcListenSchema = new Schema({
|
|
||||||
protocol: { type: String, enum: ['tcp','udp'], required: true },
|
|
||||||
ip: { type: String, required: true },
|
|
||||||
port: { type: Number, required: true },
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A media worker is a host process with one or more MediaRouter instances
|
|
||||||
* processing multi-user conference calls.
|
|
||||||
*/
|
|
||||||
const MediaWorkerSchema = new Schema({
|
|
||||||
created: { type: Date, default: Date.now, required: true, expires: '30d' },
|
|
||||||
lastActivity: { type: Date, default: Date.now, required: true },
|
|
||||||
status: { type: String, enum: STATUS_LIST, default: 'starting', required: true, index: true },
|
|
||||||
webRtcServer: {
|
|
||||||
listenInfos: { type: [WebRtcListenSchema] },
|
|
||||||
},
|
|
||||||
stats: {
|
|
||||||
routerCount: { type: Number, default: 0, required: true },
|
|
||||||
consumerCount: { type: Number, default: 0, required: true },
|
|
||||||
producerCount: { type: Number, default: 0, required: true },
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = mongoose.model('MediaWorker', MediaWorkerSchema);
|
|
@ -0,0 +1,51 @@
|
|||||||
|
mixin renderFileUploadImage (actionUrl, containerId, imageId, imageClass, defaultImage, currentImage, cropperOptions)
|
||||||
|
div(id= containerId).dtp-file-upload
|
||||||
|
form(method="POST", action= actionUrl, enctype="multipart/form-data", onsubmit= "return dtp.app.submitImageForm(event);").uk-form
|
||||||
|
.uk-margin
|
||||||
|
.uk-card.uk-card-default.uk-card-small
|
||||||
|
.uk-card-body
|
||||||
|
div(uk-grid).uk-flex-middle.uk-flex-center
|
||||||
|
div(class="uk-width-1-1 uk-width-auto@m")
|
||||||
|
.upload-image-container.size-512
|
||||||
|
if !!currentImage
|
||||||
|
img(id= imageId, src= currentImage.path, class= imageClass).sb-large
|
||||||
|
else
|
||||||
|
img(id= imageId, src= defaultImage, class= imageClass)
|
||||||
|
|
||||||
|
div(class="uk-width-1-1 uk-width-auto@m")
|
||||||
|
.uk-text-small.uk-margin
|
||||||
|
#file-select
|
||||||
|
.uk-margin(class="uk-text-center uk-text-left@m")
|
||||||
|
span.uk-text-middle Select an image
|
||||||
|
div(uk-form-custom).uk-margin-small-left
|
||||||
|
input(
|
||||||
|
type="file",
|
||||||
|
formenctype="multipart/form-data",
|
||||||
|
accept=".jpg,.png,image/jpeg,image/png",
|
||||||
|
data-file-select-container= containerId,
|
||||||
|
data-file-select="test-image-upload",
|
||||||
|
data-file-size-element= "file-size",
|
||||||
|
data-file-max-size= 15 * 1024000,
|
||||||
|
data-image-id= imageId,
|
||||||
|
data-cropper-options= cropperOptions,
|
||||||
|
onchange="return dtp.app.selectImageFile(event);",
|
||||||
|
)
|
||||||
|
button(type="button", tabindex="-1").uk-button.uk-button-default Select
|
||||||
|
|
||||||
|
#file-info(class="uk-text-center uk-text-left@m", hidden)
|
||||||
|
#file-name.uk-text-bold
|
||||||
|
if currentImage
|
||||||
|
div resolution: #[span#image-resolution-w= numeral(currentImage.metadata.width).format('0,0')]x#[span#image-resolution-h= numeral(currentImage.metadata.height).format('0,0')]
|
||||||
|
div size: #[span#file-size= numeral(currentImage.metadata.size).format('0,0.00b')]
|
||||||
|
div last modified: #[span#file-modified= moment(currentImage.created).format('MMM DD, YYYY')]
|
||||||
|
else
|
||||||
|
div resolution: #[span#image-resolution-w 512]x#[span#image-resolution-h 512]
|
||||||
|
div size: #[span#file-size N/A]
|
||||||
|
div last modified: #[span#file-modified N/A]
|
||||||
|
|
||||||
|
.uk-card-footer
|
||||||
|
div(class="uk-flex-center", uk-grid)
|
||||||
|
#file-save-btn(hidden).uk-width-auto
|
||||||
|
button(
|
||||||
|
type="submit",
|
||||||
|
).uk-button.uk-button-primary Save
|
@ -0,0 +1,28 @@
|
|||||||
|
extends ../layouts/main
|
||||||
|
block content
|
||||||
|
|
||||||
|
|
||||||
|
div(uk-grid).uk-flex-middle
|
||||||
|
.uk-width-expand
|
||||||
|
h1.margin-remove Tokens
|
||||||
|
section.uk-section.uk-section-default.uk-section-xsmall
|
||||||
|
.uk-container
|
||||||
|
.uk-text-small
|
||||||
|
h4 This is where you will regenerate OTP tokens for your admin account and destroy your old OTP account.
|
||||||
|
//- .uk-width-auto
|
||||||
|
button(
|
||||||
|
type="button",
|
||||||
|
data-user= user._id,
|
||||||
|
onclick="return dtp.adminApp.generateOTPTokens(event);",
|
||||||
|
).uk-button.dtp-button-danger
|
||||||
|
+renderButtonIcon('fa-repeat', 'Generate OTP Tokens')
|
||||||
|
//- regenerate route should set this so tokens can be viewed once.
|
||||||
|
if otpRegen
|
||||||
|
section.uk-section.uk-section-default.uk-section-xsmall
|
||||||
|
.uk-container
|
||||||
|
h3 You should save these tokens in a safe place. This is the only time you will see them.
|
||||||
|
p These tokens should be saved in a safe place so you can get into your account should you lose your 2FA device
|
||||||
|
each token of tokens
|
||||||
|
ul.uk-list.uk-list-divider
|
||||||
|
li
|
||||||
|
.uk-text-small= token.token
|
@ -0,0 +1,47 @@
|
|||||||
|
extends ../layouts/main
|
||||||
|
block vendorcss
|
||||||
|
link(rel='stylesheet', href=`/cropperjs/cropper.min.css?v=${pkg.version}`)
|
||||||
|
block vendorjs
|
||||||
|
script(src=`/cropperjs/cropper.min.js?v=${pkg.version}`)
|
||||||
|
block content
|
||||||
|
|
||||||
|
include ../components/file-upload-image
|
||||||
|
|
||||||
|
//- h2 Add or replace your site images here
|
||||||
|
div(uk-grid).uk-flex-middle
|
||||||
|
.uk-width-expand
|
||||||
|
fieldset
|
||||||
|
legend Site Icon
|
||||||
|
.uk-margin
|
||||||
|
if siteIcon
|
||||||
|
p.uk-card-title Replace your site icon below.
|
||||||
|
else
|
||||||
|
p.uk-card-title You do not currently have a site icon. Add one below.
|
||||||
|
+renderFileUploadImage(
|
||||||
|
`/admin/settings/images/updateSiteIcon`,
|
||||||
|
'site-icon-upload',
|
||||||
|
'site-icon-file',
|
||||||
|
'site-icon-picture',
|
||||||
|
`/img/icon/dtp-sites.png`,
|
||||||
|
siteIcon,
|
||||||
|
{ aspectRatio: 1 },
|
||||||
|
)
|
||||||
|
|
||||||
|
div(uk-grid).uk-flex-middle
|
||||||
|
.uk-width-expand
|
||||||
|
fieldset
|
||||||
|
legend Default poster
|
||||||
|
.uk-margin
|
||||||
|
if postImage
|
||||||
|
p.uk-card-title Replace your default post image below.
|
||||||
|
else
|
||||||
|
p.uk-card-title You do not currently have a default post image. Add one below.
|
||||||
|
+renderFileUploadImage(
|
||||||
|
`/admin/settings/images/updatePostImage`,
|
||||||
|
'site-post-upload',
|
||||||
|
'site-post-file',
|
||||||
|
'site-post-picture',
|
||||||
|
`/img/default-poster.jpg`,
|
||||||
|
postImage,
|
||||||
|
{ aspectRatio: 16/9 },
|
||||||
|
)
|
@ -0,0 +1,64 @@
|
|||||||
|
mixin renderPostDraftList (posts)
|
||||||
|
if Array.isArray(posts) && (posts.length > 0)
|
||||||
|
ul.uk-list.uk-list-divider
|
||||||
|
each draft in posts
|
||||||
|
li
|
||||||
|
a(href=`/post/${draft.slug}`, title="Preview draft")= draft.title
|
||||||
|
.uk-article-meta
|
||||||
|
div(uk-grid).uk-grid-small.uk-flex-middle
|
||||||
|
.uk-width-expand
|
||||||
|
.uk-article-meta
|
||||||
|
div(uk-grid).uk-grid-small.uk-text-small
|
||||||
|
.uk-width-expand
|
||||||
|
a(href=`/post/${draft.slug}`, title="Edit draft")= moment(draft.created).fromNow()
|
||||||
|
if drafts.all
|
||||||
|
span by
|
||||||
|
a(href=`/user/${draft.author.username}`)=` ${draft.author.username}`
|
||||||
|
.uk-width-auto
|
||||||
|
a(href=`/post/${draft._id}/edit`).uk-display-block
|
||||||
|
+renderButtonIcon('fa-pen', 'edit')
|
||||||
|
|
||||||
|
.uk-width-auto
|
||||||
|
a(
|
||||||
|
href="",
|
||||||
|
title="Delete draft",
|
||||||
|
data-post-id= draft._id,
|
||||||
|
data-post-title= draft.title,
|
||||||
|
onclick="return dtp.app.deletePost(event);",
|
||||||
|
).uk-text-danger
|
||||||
|
+renderButtonIcon('fa-trash', 'delete')
|
||||||
|
else
|
||||||
|
.uk-margin-small You have no drafts.
|
||||||
|
|
||||||
|
mixin renderFullDraftList (posts)
|
||||||
|
if Array.isArray(posts) && (posts.length > 0)
|
||||||
|
ul.uk-list.uk-list-divider
|
||||||
|
each draft in posts
|
||||||
|
li
|
||||||
|
a(href=`/post/${draft.slug}`, title="Preview draft")= draft.title
|
||||||
|
.uk-article-meta
|
||||||
|
div(uk-grid).uk-grid-medium.uk-flex-middle
|
||||||
|
.uk-width-expand
|
||||||
|
.uk-article-meta
|
||||||
|
div(uk-grid).uk-grid-medium.uk-text-medium
|
||||||
|
.uk-width-expand
|
||||||
|
a(href=`/post/${draft.slug}`, title="Edit draft")= moment(draft.created).fromNow()
|
||||||
|
if drafts.all
|
||||||
|
span by
|
||||||
|
a(href=`/user/${draft.author.username}`)=` ${draft.author.username}`
|
||||||
|
.uk-width-auto
|
||||||
|
a(href=`/post/${draft._id}/edit`).uk-display-block
|
||||||
|
+renderButtonIcon('fa-pen', 'edit')
|
||||||
|
|
||||||
|
.uk-width-auto
|
||||||
|
a(
|
||||||
|
href="",
|
||||||
|
title="Delete draft",
|
||||||
|
data-post-id= draft._id,
|
||||||
|
data-post-title= draft.title,
|
||||||
|
onclick="return dtp.app.deletePost(event);",
|
||||||
|
).uk-text-danger
|
||||||
|
+renderButtonIcon('fa-trash', 'delete')
|
||||||
|
+renderPaginationBar('/author/posts', drafts.totalPostCount)
|
||||||
|
else
|
||||||
|
.uk-margin-small You have no drafts.
|
@ -0,0 +1,24 @@
|
|||||||
|
mixin renderBlogPostListItem (post, postIndex = 1, postIndexModulus = 3)
|
||||||
|
a(href=`/post/${post.slug}`).uk-display-block.uk-link-reset
|
||||||
|
div(uk-grid).uk-grid-small
|
||||||
|
|
||||||
|
div(class="uk-width-1-1 uk-width-1-3@s uk-flex-first", class={
|
||||||
|
'uk-flex-first@m': ((postIndex % postIndexModulus) === 0),
|
||||||
|
'uk-flex-last@m': ((postIndex % postIndexModulus) !== 0),
|
||||||
|
})
|
||||||
|
if post.image
|
||||||
|
img(src= `/image/${post.image._id}`).responsive
|
||||||
|
else
|
||||||
|
img(src="/img/default-poster.jpg").responsive
|
||||||
|
|
||||||
|
div(class='uk-width-1-1 uk-width-2-3@s', class="uk-flex-last", class={
|
||||||
|
'uk-flex-first@m': ((postIndex % postIndexModulus) !== 0),
|
||||||
|
'uk-flex-last@m': ((postIndex % postIndexModulus) === 0),
|
||||||
|
})
|
||||||
|
article.uk-article
|
||||||
|
h4(style="line-height: 1.1;").uk-article-title.uk-margin-small= post.title
|
||||||
|
.uk-article-meta
|
||||||
|
div(uk-grid).uk-grid-small
|
||||||
|
.uk-width-auto author: #{post.author.displayName || post.author.username}
|
||||||
|
.uk-width-auto
|
||||||
|
span published: #{moment(post.created).format("MMM DD YYYY HH:MM a")}
|
@ -0,0 +1,70 @@
|
|||||||
|
mixin renderPostList (posts)
|
||||||
|
if Array.isArray(posts) && (posts.length > 0)
|
||||||
|
ul.uk-list.uk-list-divider
|
||||||
|
each post in posts
|
||||||
|
li
|
||||||
|
a(href=`/post/${post.slug}`).uk-display-block
|
||||||
|
div= post.title
|
||||||
|
|
||||||
|
.uk-article-meta
|
||||||
|
div(uk-grid).uk-grid-small.uk-text-small
|
||||||
|
.uk-width-expand
|
||||||
|
a(href=`/post/${post.slug}`)= moment(post.created).fromNow()
|
||||||
|
if posts.all
|
||||||
|
span by
|
||||||
|
a(href=`/user/${post.author.username}`)=` ${post.author.username}`
|
||||||
|
.uk-width-auto
|
||||||
|
a(href=`/post/${post._id}/edit`).uk-display-block
|
||||||
|
+renderButtonIcon('fa-pen', 'edit')
|
||||||
|
|
||||||
|
.uk-width-auto
|
||||||
|
a(
|
||||||
|
href="",
|
||||||
|
data-post-id= post._id,
|
||||||
|
data-post-title= post.title,
|
||||||
|
onclick="return dtp.app.deletePost(event);",
|
||||||
|
).uk-display-block.uk-text-danger
|
||||||
|
+renderButtonIcon('fa-trash', 'delete')
|
||||||
|
|
||||||
|
div(style="width: 65px;")
|
||||||
|
span
|
||||||
|
i.fas.fa-eye
|
||||||
|
span.uk-margin-small-left= formatCount(post.stats.totalVisitCount)
|
||||||
|
else
|
||||||
|
.uk-margin-small There are no posts.
|
||||||
|
|
||||||
|
mixin renderPublishedPostList (posts)
|
||||||
|
if Array.isArray(posts) && (posts.length > 0)
|
||||||
|
ul.uk-list.uk-list-divider
|
||||||
|
each post in posts
|
||||||
|
li
|
||||||
|
a(href=`/post/${post.slug}`).uk-display-block
|
||||||
|
div= post.title
|
||||||
|
|
||||||
|
.uk-article-meta
|
||||||
|
div(uk-grid).uk-grid-small.uk-text-small
|
||||||
|
.uk-width-expand
|
||||||
|
a(href=`/post/${post.slug}`)= moment(post.created).fromNow()
|
||||||
|
if posts.all
|
||||||
|
span by
|
||||||
|
a(href=`/user/${post.author.username}`)=` ${post.author.username}`
|
||||||
|
.uk-width-auto
|
||||||
|
a(href=`/post/${post._id}/edit`).uk-display-block
|
||||||
|
+renderButtonIcon('fa-pen', 'edit')
|
||||||
|
|
||||||
|
.uk-width-auto
|
||||||
|
a(
|
||||||
|
href="",
|
||||||
|
data-post-id= post._id,
|
||||||
|
data-post-title= post.title,
|
||||||
|
onclick="return dtp.app.deletePost(event);",
|
||||||
|
).uk-display-block.uk-text-danger
|
||||||
|
+renderButtonIcon('fa-trash', 'delete')
|
||||||
|
|
||||||
|
div(style="width: 65px;")
|
||||||
|
span
|
||||||
|
i.fas.fa-eye
|
||||||
|
span.uk-margin-small-left= formatCount(post.stats.totalVisitCount)
|
||||||
|
+renderPaginationBar('/author/posts', published.totalPostCount)
|
||||||
|
else
|
||||||
|
.uk-margin-small No published posts.
|
@ -0,0 +1,28 @@
|
|||||||
|
extends ../../layouts/main
|
||||||
|
block content
|
||||||
|
|
||||||
|
include ../components/draft-list
|
||||||
|
include ../components/list
|
||||||
|
include ../../post/components/summary
|
||||||
|
|
||||||
|
include ../../components/pagination-bar
|
||||||
|
|
||||||
|
section.uk-section.uk-section-default.uk-section-xsmall
|
||||||
|
.uk-container.uk-container-expand
|
||||||
|
div(uk-grid).uk-flex-middle
|
||||||
|
.uk-width-expand
|
||||||
|
h2.uk-margin-remove Drafts
|
||||||
|
.uk-width-auto
|
||||||
|
if user.permissions.canAuthorPosts || user.flags.isAdmin
|
||||||
|
a(href= "/post/compose").uk-button.uk-button-primary.uk-border-rounded
|
||||||
|
span
|
||||||
|
i.fas.fa-plus
|
||||||
|
span.uk-margin-small-left.uk-text-bold Create Post
|
||||||
|
.uk-width-medium
|
||||||
|
a(href= "/author").uk-button.uk-button-primary.uk-border-rounded
|
||||||
|
span.uk-margin-small-middle.uk-text-bold Author Dashboard
|
||||||
|
div(uk-grid)
|
||||||
|
div(class="uk-width-1-1 uk-width-3-3@m")
|
||||||
|
+renderSectionTitle('Drafts')
|
||||||
|
+renderFullDraftList(drafts.posts)
|
||||||
|
|
@ -1,58 +1,27 @@
|
|||||||
extends ../../layouts/main
|
extends ../../layouts/main
|
||||||
block content
|
block content
|
||||||
|
|
||||||
include ../../post/components/draft-list
|
include ../components/draft-list
|
||||||
include ../../post/components/list
|
include ../components/list
|
||||||
include ../../post/components/summary
|
include ../../post/components/summary
|
||||||
|
|
||||||
include ../../components/pagination-bar
|
include ../../components/pagination-bar
|
||||||
|
|
||||||
section.uk-section.uk-section-default.uk-section-small
|
section.uk-section.uk-section-default.uk-section-xsmall
|
||||||
.uk-container.uk-container-expand
|
.uk-container.uk-container-expand
|
||||||
h1 Post Author Dashboard
|
div(uk-grid).uk-flex-middle
|
||||||
|
.uk-width-expand
|
||||||
|
h2.uk-margin-remove Published Posts
|
||||||
|
if user.permissions.canAuthorPosts
|
||||||
|
.uk-width-auto
|
||||||
|
a(href= "/post/compose").uk-button.uk-button-primary.uk-border-rounded
|
||||||
|
span
|
||||||
|
i.fas.fa-plus
|
||||||
|
span.uk-margin-small-left.uk-text-bold Create Post
|
||||||
|
.uk-width-medium
|
||||||
|
a(href= "/author").uk-button.uk-button-primary.uk-border-rounded
|
||||||
|
span.uk-margin-small-left.uk-text-bold Author Dashboard
|
||||||
div(uk-grid)
|
div(uk-grid)
|
||||||
.uk-width-2-3
|
div(class="uk-width-1-1 uk-width-3-3@m")
|
||||||
.uk-margin
|
+renderSectionTitle('Posts')
|
||||||
+renderSectionTitle('Your Posts')
|
+renderPublishedPostList(published.posts)
|
||||||
.content-block
|
|
||||||
if published && Array.isArray(published.posts) && (published.posts.length > 0)
|
|
||||||
.uk-margin
|
|
||||||
ul.uk-list.uk-list-divider
|
|
||||||
each post in published.posts
|
|
||||||
li
|
|
||||||
a(href=`/post/${post.slug}`).uk-display-block
|
|
||||||
div= post.title
|
|
||||||
.uk-article-meta
|
|
||||||
div(uk-grid).uk-grid-small.uk-text-small
|
|
||||||
.uk-width-expand
|
|
||||||
a(href=`/post/${post.slug}`)= moment(post.created).fromNow()
|
|
||||||
|
|
||||||
.uk-width-auto
|
|
||||||
a(href=`/post/${post._id}/edit`).uk-display-block
|
|
||||||
+renderButtonIcon('fa-pen', 'edit')
|
|
||||||
|
|
||||||
.uk-width-auto
|
|
||||||
a(
|
|
||||||
href="",
|
|
||||||
data-post-id= post._id,
|
|
||||||
data-post-title= post.title,
|
|
||||||
onclick="return dtp.app.deletePost(event);",
|
|
||||||
).uk-display-block.uk-text-danger
|
|
||||||
+renderButtonIcon('fa-trash', 'delete')
|
|
||||||
|
|
||||||
div(style="width: 65px;")
|
|
||||||
span
|
|
||||||
i.fas.fa-eye
|
|
||||||
span.uk-margin-small-left= formatCount(post.stats.totalVisitCount)
|
|
||||||
+renderPaginationBar('/author/post', published.totalPostCount)
|
|
||||||
else
|
|
||||||
div You have no published posts.
|
|
||||||
|
|
||||||
.uk-width-1-3
|
|
||||||
.uk-margin
|
|
||||||
+renderSectionTitle('Your Drafts')
|
|
||||||
+renderPostDraftList(drafts.posts)
|
|
||||||
|
|
||||||
.uk-margin
|
|
||||||
+renderSectionTitle('Archived')
|
|
||||||
+renderPostList(archive.posts)
|
|
@ -1,5 +1,5 @@
|
|||||||
block twitter-card
|
block twitter-card
|
||||||
meta(name='twitter:card', content='summary_large_image')
|
meta(name='twitter:card', content='summary_large_image')
|
||||||
meta(name='twitter:image' content= `https://${site.domain}/img/social-cards/${site.domainKey}.png?v=${pkg.version}`)
|
meta(name='twitter:image' content= shareImage || `https://${site.domain}/img/social-cards/${site.domainKey}.png?v=${pkg.version}`)
|
||||||
meta(name='twitter:title', content= pageTitle || site.name)
|
meta(name='twitter:title', content= pageTitle || site.name)
|
||||||
meta(name='twitter:description', content= pageDescription || site.description)
|
meta(name='twitter:description', content= pageDescription || site.description)
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
extends ../layouts/main
|
|
||||||
block content
|
|
||||||
|
|
||||||
include ../components/pagination-bar
|
|
||||||
|
|
||||||
section.uk-section.uk-section-default
|
|
||||||
.uk-container
|
|
||||||
|
|
||||||
article.uk-article
|
|
||||||
.uk-margin
|
|
||||||
h1.uk-article-title.uk-margin-remove #{site.name} News Feed
|
|
||||||
.uk-text-bold #{formatCount(newsroom.totalFeedEntryCount)} articles indexed by #{site.name} in one chronological feed.
|
|
||||||
|
|
||||||
.uk-margin
|
|
||||||
if Array.isArray(newsroom.entries) && (newsroom.entries.length > 0)
|
|
||||||
ul.uk-list.uk-list-divider
|
|
||||||
each entry in newsroom.entries
|
|
||||||
li
|
|
||||||
.uk-text-large.uk-text-bold.uk-margin-small
|
|
||||||
a(href= entry.link, target="shing_reader")= entry.title
|
|
||||||
.uk-margin-small= entry.description
|
|
||||||
.uk-text-small source: #[a(href= entry.feed.link, target="_blank")= entry.feed.title]
|
|
||||||
else
|
|
||||||
div There are no news feed entries.
|
|
||||||
|
|
||||||
.uk-margin
|
|
||||||
+renderPaginationBar(`/newsroom/feed`, newsroom.totalFeedEntryCount)
|
|
@ -0,0 +1,16 @@
|
|||||||
|
extends ../../layouts/main-sidebar
|
||||||
|
block content
|
||||||
|
|
||||||
|
include ../../components/pagination-bar
|
||||||
|
include components/credit
|
||||||
|
|
||||||
|
div(uk-grid).uk-flex-expand
|
||||||
|
.uk-width-expand
|
||||||
|
h3.uk-margin-remove= `Author List`
|
||||||
|
if Array.isArray(authors) && (authors.length > 0)
|
||||||
|
ul.uk-list.uk-list-divider
|
||||||
|
each author in authors
|
||||||
|
li
|
||||||
|
+renderAuthorCredit(author)
|
||||||
|
.uk-card-footer
|
||||||
|
+renderPaginationBar(`/post/authors`, totalAuthorCount )
|
@ -0,0 +1,18 @@
|
|||||||
|
mixin renderAuthorCredit (author)
|
||||||
|
div(uk-grid).uk-grid-small
|
||||||
|
.uk-width-auto
|
||||||
|
+renderProfileIcon(author)
|
||||||
|
.uk-width-expand
|
||||||
|
.uk-margin-small
|
||||||
|
div(uk-grid).uk-flex-middle
|
||||||
|
.uk-width-expand
|
||||||
|
- var userUrl = !!author.coreUserId ? `/user/core/${author._id}` : `/user/${author.username}`;
|
||||||
|
a(href= userUrl, title="View member profile")
|
||||||
|
.uk-text-bold(style="line-height: 1em;")= author.displayName || author.username
|
||||||
|
.uk-width-auto
|
||||||
|
.uk-text-small.uk-text-muted(style="line-height: 1em;")
|
||||||
|
if author.coreUserId
|
||||||
|
a(href=`${process.env.DTP_CORE_AUTH_SCHEME}://${author.core.meta.domain}/user/${author.coreUserId}`)= author.core.meta.name
|
||||||
|
else if !Array.isArray(posts)
|
||||||
|
a(href= `/post/author/${author.username}`)= `View posts by author`
|
||||||
|
.uk-text-small= author.bio
|
@ -0,0 +1,15 @@
|
|||||||
|
mixin renderPostSummaryFull (post)
|
||||||
|
div(uk-grid).uk-grid-small
|
||||||
|
if post.image
|
||||||
|
.uk-width-auto
|
||||||
|
img(src= `/image/${post.image._id}`).uk-width-small
|
||||||
|
else
|
||||||
|
.uk-width-auto
|
||||||
|
img(src="/img/default-poster.jpg").uk-width-small
|
||||||
|
.uk-width-expand
|
||||||
|
.uk-text-large.uk-text-bold(style="line-height: 1em;")
|
||||||
|
a(href=`/post/${post.slug}`)= `${post.title}`
|
||||||
|
.uk-text-small.uk-text-muted
|
||||||
|
div
|
||||||
|
div= moment(post.created).fromNow()
|
||||||
|
div= post.summary
|
@ -0,0 +1,16 @@
|
|||||||
|
extends ../../layouts/main-sidebar
|
||||||
|
block content
|
||||||
|
|
||||||
|
include ../../components/pagination-bar
|
||||||
|
include components/list
|
||||||
|
|
||||||
|
div(uk-grid).uk-flex-expand
|
||||||
|
.uk-width-expand
|
||||||
|
h3.uk-margin-remove= `Posts by ${author.username}`
|
||||||
|
if Array.isArray(posts) && (posts.length > 0)
|
||||||
|
ul.uk-list.uk-list-divider
|
||||||
|
each post in posts
|
||||||
|
li
|
||||||
|
+renderPostSummaryFull(post)
|
||||||
|
.uk-card-footer
|
||||||
|
+renderPaginationBar(`/post/author/${author.username}`, posts.length )
|
@ -0,0 +1,19 @@
|
|||||||
|
mixin renderPostSummaryFull (post)
|
||||||
|
div(uk-grid).uk-grid-small
|
||||||
|
if post.image
|
||||||
|
.uk-width-auto
|
||||||
|
img(src= `/image/${post.image._id}`).uk-width-medium
|
||||||
|
else
|
||||||
|
.uk-width-auto
|
||||||
|
img(src="/img/default-poster.jpg").uk-width-medium
|
||||||
|
.uk-width-expand
|
||||||
|
.uk-text-large.uk-text-bold(style="line-height: 1em;")
|
||||||
|
a(href=`/post/${post.slug}`)= `${post.title}`
|
||||||
|
.uk-text-small.uk-text-muted
|
||||||
|
div
|
||||||
|
div= moment(post.created).fromNow()
|
||||||
|
span by
|
||||||
|
a(href=`/user/${post.author.username}`)=` ${post.author.username}`
|
||||||
|
if user && allPosts
|
||||||
|
div= `Status: ${post.status}`
|
||||||
|
div= post.summary
|
@ -0,0 +1,37 @@
|
|||||||
|
extends ../layouts/main-sidebar
|
||||||
|
|
||||||
|
include components/list
|
||||||
|
|
||||||
|
include ../components/pagination-bar
|
||||||
|
|
||||||
|
block content
|
||||||
|
|
||||||
|
|
||||||
|
if Array.isArray(posts) && (posts.length > 0)
|
||||||
|
h3= `Posts with the tag ${tag}.`
|
||||||
|
ul.uk-list.uk-list-divider
|
||||||
|
each post in posts
|
||||||
|
li
|
||||||
|
+renderPostSummaryFull(post)
|
||||||
|
|
||||||
|
.uk-card-footer
|
||||||
|
+renderPaginationBar(`/tag/${tagSlug}`, posts.length )
|
||||||
|
//- li
|
||||||
|
if post.image
|
||||||
|
img(src= `/image/${post.image._id}`, href=`/post/${post.slug}`, style="max-height: 350px; object-fit: cover; vertical-align:middle;margin:0px 20px;").responsive
|
||||||
|
else
|
||||||
|
img(src="/img/default-poster.jpg", href=`/post/${post.slug}`, style="max-height: 350px; object-fit: cover; vertical-align:middle;margin:0px 20px;").responsive
|
||||||
|
a(href=`/post/${post.slug}`).uk-display-block
|
||||||
|
div.h2= post.title
|
||||||
|
|
||||||
|
.uk-article-meta
|
||||||
|
div(uk-grid).uk-grid-small.uk-text-small
|
||||||
|
.uk-width-expand
|
||||||
|
a(href=`/post/${post.slug}`)= moment(post.created).fromNow()
|
||||||
|
span by
|
||||||
|
a(href=`/user/${post.author.username}`)=` ${post.author.username}`
|
||||||
|
.uk-width-expand
|
||||||
|
div= post.summary
|
||||||
|
|
||||||
|
else
|
||||||
|
h3= `There are no posts with the tag ${tag}.`
|
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 942 B |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 48 KiB |
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
git pull prod master
|
||||||
|
yarn --production=false
|
||||||
|
gulp build
|
||||||
|
|
||||||
|
./restart-production
|
@ -1,178 +0,0 @@
|
|||||||
// dtp-media-engine.js
|
|
||||||
// Copyright (C) 2022 DTP Technologies, LLC
|
|
||||||
// All Rights Reserved
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
require('dotenv').config();
|
|
||||||
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const mongoose = require('mongoose');
|
|
||||||
const mediasoup = require('mediasoup');
|
|
||||||
|
|
||||||
const { SiteAsync, SiteCommon, SitePlatform, SiteLog } = require(path.join(__dirname, 'lib', 'site-lib'));
|
|
||||||
|
|
||||||
module.rootPath = __dirname;
|
|
||||||
module.pkg = require(path.join(module.rootPath, 'package.json'));
|
|
||||||
module.config = {
|
|
||||||
component: { name: 'dtpMediaEngine', slug: 'dtp-media-engine' },
|
|
||||||
root: module.rootPath,
|
|
||||||
site: require(path.join(module.rootPath, 'config', 'site')),
|
|
||||||
webRtcServer: [
|
|
||||||
{
|
|
||||||
protocol: 'udp',
|
|
||||||
ip: process.env.MEDIASOUP_WEBRTC_BIND_ADDR || '127.0.0.1',
|
|
||||||
port: process.env.MEDIASOUP_WEBRTC_BIND_PORT || 20000,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
module.log = new SiteLog(module, module.config.component);
|
|
||||||
|
|
||||||
class MediaEngineWorker extends SiteCommon {
|
|
||||||
|
|
||||||
constructor ( ) {
|
|
||||||
super(module, { name: 'dtpMediaWorker', slug: 'dtp-media-worker' });
|
|
||||||
this._id = mongoose.Types.ObjectId();
|
|
||||||
}
|
|
||||||
|
|
||||||
async start ( ) {
|
|
||||||
await super.start();
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.worker = await mediasoup.createWorker({
|
|
||||||
logLevel: 'warn',
|
|
||||||
dtlsCertificateFile: process.env.HTTPS_SSL_CRT,
|
|
||||||
dtlsPrivateKeyFile: process.env.HTTPS_SSL_KEY,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(`failed to start mediasoup worker process: ${error.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const BIND_PORT = 20000 + module.nextWorkerIdx++;
|
|
||||||
this.webRtcServer = await this.worker.createWebRtcServer({
|
|
||||||
listenInfos: [
|
|
||||||
{
|
|
||||||
protocol: 'udp',
|
|
||||||
ip: '127.0.0.1',
|
|
||||||
port: BIND_PORT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
protocol: 'tcp',
|
|
||||||
ip: '127.0.0.1',
|
|
||||||
port: BIND_PORT,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(`failed to start mediasoup WebRTC Server: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async stop ( ) {
|
|
||||||
if (this.webRtcServer && !this.webRtcServer.closed) {
|
|
||||||
this.log.info('closing mediasoup WebRTC server');
|
|
||||||
this.webRtcServer.close();
|
|
||||||
delete this.webRtcServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.worker && !this.worker.closed) {
|
|
||||||
this.log.info('closing mediasoup worker process');
|
|
||||||
this.worker.close();
|
|
||||||
delete this.worker;
|
|
||||||
}
|
|
||||||
|
|
||||||
await super.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.onNewWorker = async (worker) => {
|
|
||||||
module.log.info('new worker created', { worker: worker.pid });
|
|
||||||
worker.observer.on('close', ( ) => {
|
|
||||||
module.log.info('worker shutting down', { worker: worker.pid });
|
|
||||||
});
|
|
||||||
|
|
||||||
worker.observer.on('newrouter', (router) => {
|
|
||||||
module.log.info('new router created', { worker: worker.pid, router: router.id });
|
|
||||||
router.observer.on('close', ( ) => {
|
|
||||||
module.log.info('router shutting down', { worker: worker.pid, router: router.id });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.createWorker = async ( ) => {
|
|
||||||
const worker = new MediaEngineWorker();
|
|
||||||
module.workers.push(worker);
|
|
||||||
await worker.start();
|
|
||||||
};
|
|
||||||
|
|
||||||
module.shutdown = async ( ) => {
|
|
||||||
await SiteAsync.each(module.workers, async (worker) => {
|
|
||||||
try {
|
|
||||||
await worker.stop();
|
|
||||||
} catch (error) {
|
|
||||||
module.log.error('failed to stop worker', { error });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SERVER PROCESS INIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
(async ( ) => {
|
|
||||||
|
|
||||||
process.on('unhandledRejection', (error, p) => {
|
|
||||||
module.log.error('Unhandled rejection', {
|
|
||||||
error: error,
|
|
||||||
promise: p,
|
|
||||||
stack: error.stack
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('warning', (error) => {
|
|
||||||
module.log.alert('warning', { error });
|
|
||||||
});
|
|
||||||
|
|
||||||
process.once('SIGINT', async ( ) => {
|
|
||||||
module.log.info('SIGINT received');
|
|
||||||
module.log.info('requesting shutdown...');
|
|
||||||
await module.shutdown();
|
|
||||||
const exitCode = await SitePlatform.shutdown();
|
|
||||||
process.nextTick(( ) => {
|
|
||||||
process.exit(exitCode);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
process.once('SIGUSR2', async ( ) => {
|
|
||||||
await SitePlatform.shutdown();
|
|
||||||
process.kill(process.pid, 'SIGUSR2');
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
await SitePlatform.startPlatform(module);
|
|
||||||
} catch (error) {
|
|
||||||
module.log.error(`failed to start DTP ${module.config.component.slug} process`, { error });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
module.log.info('registering mediasoup observer callbacks');
|
|
||||||
mediasoup.observer.on('newworker', module.onNewWorker);
|
|
||||||
|
|
||||||
module.log.info('creating mediasoup worker instance');
|
|
||||||
|
|
||||||
module.nextWorkerIdx = 0;
|
|
||||||
module.workers = [ ];
|
|
||||||
|
|
||||||
await module.createWorker();
|
|
||||||
|
|
||||||
module.log.info('DTP Media Engine online');
|
|
||||||
} catch (error) {
|
|
||||||
module.log.error('failed to start DTP Media Engine', { error });
|
|
||||||
process.exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|