Compare commits
20 Commits
0b6f383a63
...
nctv-avata
Author | SHA1 | Date | |
---|---|---|---|
21ecdf77c6 | |||
cfe2ac0607 | |||
74566a895a | |||
587334a3e1 | |||
30cce2ec03 | |||
24f48788ab | |||
bed00aa4c5 | |||
fd16c95b8f | |||
39f6e4c637 | |||
f8c34213cb | |||
eb889711f5 | |||
8dd6ed7888 | |||
0cc38ac575 | |||
cde9b3f74a | |||
75245c0858 | |||
be59329581 | |||
6d103af5c9 | |||
e57d39c8ab | |||
9526a19aab | |||
db1993f97e |
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,5 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 10.3.3
|
||||||
|
|
||||||
|
### Minor changes and fixes
|
||||||
|
|
||||||
|
* Fix #481: Moderation bot was not able to connect when remote chat was disabled.
|
||||||
|
* Some cleaning in code generating Prosody configuration file.
|
||||||
|
|
||||||
|
## 10.3.2
|
||||||
|
|
||||||
|
### Minor changes and fixes
|
||||||
|
|
||||||
|
* Fix #477: ended polls never disappear when archiving is disabled (and no more than 20 new messages).
|
||||||
|
|
||||||
## 10.3.1
|
## 10.3.1
|
||||||
|
|
||||||
### Minor changes and fixes
|
### Minor changes and fixes
|
||||||
|
BIN
assets/images/avatars/nctv/hat_01.png
Normal file
BIN
assets/images/avatars/nctv/hat_01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 350 B |
BIN
assets/images/avatars/nctv/nigbot.png
Normal file
BIN
assets/images/avatars/nctv/nigbot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
@ -28,6 +28,57 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
converse-muc {
|
converse-muc {
|
||||||
min-height: max(30vh, 200px);
|
min-height: max(59vh, 400px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// /* Media query for mobile devices */
|
||||||
|
// @media only screen and (max-width: 767px) {
|
||||||
|
// #peertube-plugin-livechat-container converse-root {
|
||||||
|
// converse-muc {
|
||||||
|
// min-height: 58vh;
|
||||||
|
// /* 100vh - 30vh for video = 70vh remaining */
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /* Media query for tablets in portrait mode */
|
||||||
|
// @media only screen and (min-width: 768px) and (max-width: 1023px) {
|
||||||
|
// #peertube-plugin-livechat-container converse-root {
|
||||||
|
// converse-muc {
|
||||||
|
// min-height: 25vh;
|
||||||
|
// /* Slightly less to account for other elements */
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /* Media query for tablets in landscape mode */
|
||||||
|
// @media only screen and (min-width: 1024px) and (max-width: 1279px) {
|
||||||
|
// #peertube-plugin-livechat-container converse-root {
|
||||||
|
// converse-muc {
|
||||||
|
// min-height: 25vh;
|
||||||
|
// /* Assuming more height can be used */
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/* Media query for desktops */
|
||||||
|
@media only screen and (min-width: 1280px) {
|
||||||
|
#peertube-plugin-livechat-container converse-root {
|
||||||
|
converse-muc {
|
||||||
|
height: inherit;
|
||||||
|
/* Full desktop experience */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* custom toolbar CSS */
|
||||||
|
|
||||||
|
.send-button {
|
||||||
|
border-radius: 0.25rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-button:hover {
|
||||||
|
background-color: #0067c1 !important;
|
||||||
|
}
|
@ -58,6 +58,9 @@ const avatarPartsDef = {
|
|||||||
fur: 10,
|
fur: 10,
|
||||||
eyes: 15,
|
eyes: 15,
|
||||||
mouth: 10
|
mouth: 10
|
||||||
|
},
|
||||||
|
'nctv': {
|
||||||
|
body: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +172,23 @@ async function generateAvatars (part) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const generateNigbotAvatar = async () => {
|
||||||
|
console.log('Starting generating nigbot avatar');
|
||||||
|
|
||||||
|
const inputDir = './assets/images/avatars/nctv/';
|
||||||
|
const outputDir = './dist/server/avatars/nctv/';
|
||||||
|
fs.mkdirSync(outputDir, { recursive: true });
|
||||||
|
|
||||||
|
const buff = await sharp(path.join(inputDir, 'nigbot.png')).toBuffer();
|
||||||
|
await sharp(buff)
|
||||||
|
.resize(60, 60)
|
||||||
|
.png({ palette: true })
|
||||||
|
.toFile(path.join(outputDir, '1.png'));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function generateBotsAvatars () {
|
async function generateBotsAvatars () {
|
||||||
{
|
{
|
||||||
// Moderation bot avatar: choosing some parts, and turning it so it is facing left.
|
// Moderation bot avatar: choosing some parts, and turning it so it is facing left.
|
||||||
@ -294,6 +314,21 @@ async function generateBotsAvatars () {
|
|||||||
})
|
})
|
||||||
.toFile(path.join(botOutputDir, '1.png'))
|
.toFile(path.join(botOutputDir, '1.png'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Nigbot avatar for users
|
||||||
|
const inputDir = './assets/images/avatars/nctv'
|
||||||
|
const botOutputDir = './dist/server/bot_avatars/nctv/'
|
||||||
|
fs.mkdirSync(botOutputDir, { recursive: true })
|
||||||
|
const buff = await sharp(path.join(inputDir, 'nigbot.png'))
|
||||||
|
.toBuffer()
|
||||||
|
|
||||||
|
await sharp(buff)
|
||||||
|
// .resize(60, 60)
|
||||||
|
.png()
|
||||||
|
.toFile(path.join(botOutputDir, '1.png'))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMainThread) {
|
if (isMainThread) {
|
||||||
@ -337,6 +372,9 @@ if (isMainThread) {
|
|||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
} else if (part === 'nctv') {
|
||||||
|
generateNigbotAvatar();
|
||||||
|
parentPort.postMessage('done');
|
||||||
} else {
|
} else {
|
||||||
generateAvatars(part).then(
|
generateAvatars(part).then(
|
||||||
() => {
|
() => {
|
||||||
|
@ -12,6 +12,8 @@ import './components/poll-form-view.js'
|
|||||||
|
|
||||||
const { sizzle } = converse.env
|
const { sizzle } = converse.env
|
||||||
|
|
||||||
|
const delayedTimeout = 2 // for delayed poll message, how long must the be considered as valid.
|
||||||
|
|
||||||
converse.plugins.add('livechat-converse-poll', {
|
converse.plugins.add('livechat-converse-poll', {
|
||||||
dependencies: ['converse-muc', 'converse-disco'],
|
dependencies: ['converse-muc', 'converse-disco'],
|
||||||
|
|
||||||
@ -97,6 +99,23 @@ converse.plugins.add('livechat-converse-poll', {
|
|||||||
if (attrs.is_archived) {
|
if (attrs.is_archived) {
|
||||||
return this.__super__.onMessage(attrs)
|
return this.__super__.onMessage(attrs)
|
||||||
}
|
}
|
||||||
|
if (attrs.is_delayed) {
|
||||||
|
// When archiving is disabled, the "history" mechanism is still available:
|
||||||
|
// Last X (20 by default) messages will be kept, and sent to users.
|
||||||
|
// The only thing that differentiates such messages is that they are delayed.
|
||||||
|
// We can't just ignore all delayed messages, because if one day we enable SMACKS
|
||||||
|
// (to handle deconnections on poor network), there could be some legitimate delayed messages.
|
||||||
|
// So we will only ignore the poll if it was sent more than X minutes ago.
|
||||||
|
console.debug('Got a delayed poll message, checking if old or not')
|
||||||
|
const d = new Date()
|
||||||
|
d.setMinutes(d.getMinutes() - delayedTimeout)
|
||||||
|
if (attrs.time < d.toISOString()) {
|
||||||
|
console.debug(
|
||||||
|
`Poll message was delayed fore more than ${delayedTimeout} minutes (${attrs.time} < ${d.toISOString()}).`
|
||||||
|
)
|
||||||
|
return this.__super__.onMessage(attrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.info('Got a poll message, setting it as the current_poll')
|
console.info('Got a poll message, setting it as the current_poll')
|
||||||
// this will be displayed by the livechat-converse-muc-poll custom element,
|
// this will be displayed by the livechat-converse-muc-poll custom element,
|
||||||
|
@ -175,6 +175,7 @@ avatar_set_description: |
|
|||||||
Please refer to the documentation:
|
Please refer to the documentation:
|
||||||
<a href="https://livingston.frama.io/peertube-plugin-livechat/documentation/admin/settings/" target="_blank">Settings</a>.
|
<a href="https://livingston.frama.io/peertube-plugin-livechat/documentation/admin/settings/" target="_blank">Settings</a>.
|
||||||
avatar_set_option_sepia: "Sepia (Peertube mascot)"
|
avatar_set_option_sepia: "Sepia (Peertube mascot)"
|
||||||
|
avatar_set_option_nctv: "NCTV Branded"
|
||||||
avatar_set_option_cat: "Cats"
|
avatar_set_option_cat: "Cats"
|
||||||
avatar_set_option_bird: "Birds"
|
avatar_set_option_bird: "Birds"
|
||||||
avatar_set_option_fenec: "Fenecs (Mobilizon mascot)"
|
avatar_set_option_fenec: "Fenecs (Mobilizon mascot)"
|
||||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "peertube-plugin-livechat",
|
"name": "peertube-plugin-livechat",
|
||||||
"version": "10.3.1",
|
"version": "10.3.3",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "peertube-plugin-livechat",
|
"name": "peertube-plugin-livechat",
|
||||||
"version": "10.3.1",
|
"version": "10.3.3",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@xmpp/jid": "^0.13.1",
|
"@xmpp/jid": "^0.13.1",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "peertube-plugin-livechat",
|
"name": "peertube-plugin-livechat",
|
||||||
"description": "PeerTube plugin livechat: create chat rooms for your Peertube lives! Comes with many features: federation, moderation tools, chat bot, chat persistence, OBS integration, ...",
|
"description": "PeerTube plugin livechat: create chat rooms for your Peertube lives! Comes with many features: federation, moderation tools, chat bot, chat persistence, OBS integration, ...",
|
||||||
"version": "10.3.1",
|
"version": "10.3.3",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "John Livingston",
|
"name": "John Livingston",
|
||||||
|
@ -102,7 +102,7 @@ async function getProsodyFilePaths (options: RegisterServerOptions): Promise<Pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
let avatarSet: AvatarSet = (settings['avatar-set'] ?? 'sepia') as AvatarSet
|
let avatarSet: AvatarSet = (settings['avatar-set'] ?? 'sepia') as AvatarSet
|
||||||
if (!['sepia', 'cat', 'bird', 'fenec', 'abstract', 'legacy'].includes(avatarSet)) {
|
if (!['sepia', 'cat', 'bird', 'fenec', 'abstract', 'legacy', 'nctv'].includes(avatarSet)) {
|
||||||
logger.error('Invalid avatar-set setting, using sepia as default')
|
logger.error('Invalid avatar-set setting, using sepia as default')
|
||||||
avatarSet = 'sepia'
|
avatarSet = 'sepia'
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ abstract class ProsodyConfigBlock {
|
|||||||
this.entries.set(name, value)
|
this.entries.set(name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
add (name: string, value: ConfigEntryValue): void {
|
add (name: string, value: ConfigEntryValue, allowDuplicate?: boolean): void {
|
||||||
if (!this.entries.has(name)) {
|
if (!this.entries.has(name)) {
|
||||||
this.entries.set(name, [])
|
this.entries.set(name, [])
|
||||||
}
|
}
|
||||||
@ -101,6 +101,9 @@ abstract class ProsodyConfigBlock {
|
|||||||
if (!Array.isArray(entry)) {
|
if (!Array.isArray(entry)) {
|
||||||
entry = [entry]
|
entry = [entry]
|
||||||
}
|
}
|
||||||
|
if (!allowDuplicate && entry.includes(value)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
entry.push(value)
|
entry.push(value)
|
||||||
this.entries.set(name, entry)
|
this.entries.set(name, entry)
|
||||||
}
|
}
|
||||||
@ -239,7 +242,7 @@ class ProsodyConfigContent {
|
|||||||
this.muc.set('muc_room_default_history_length', 20)
|
this.muc.set('muc_room_default_history_length', 20)
|
||||||
|
|
||||||
this.muc.add('modules_enabled', 'muc_slow_mode')
|
this.muc.add('modules_enabled', 'muc_slow_mode')
|
||||||
this.muc.add('slow_mode_duration_form_position', 120)
|
this.muc.set('slow_mode_duration_form_position', 120)
|
||||||
|
|
||||||
this.muc.add('modules_enabled', 'pubsub_peertubelivechat')
|
this.muc.add('modules_enabled', 'pubsub_peertubelivechat')
|
||||||
this.muc.add('modules_enabled', 'muc_peertubelivechat_roles')
|
this.muc.add('modules_enabled', 'muc_peertubelivechat_roles')
|
||||||
@ -251,7 +254,7 @@ class ProsodyConfigContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.muc.add('modules_enabled', 'muc_moderation_delay')
|
this.muc.add('modules_enabled', 'muc_moderation_delay')
|
||||||
this.muc.add('moderation_delay_form_position', 118)
|
this.muc.set('moderation_delay_form_position', 118)
|
||||||
}
|
}
|
||||||
|
|
||||||
useAnonymous (autoBanIP: boolean): void {
|
useAnonymous (autoBanIP: boolean): void {
|
||||||
@ -445,7 +448,7 @@ class ProsodyConfigContent {
|
|||||||
|
|
||||||
useMucHttpDefault (url: string): void {
|
useMucHttpDefault (url: string): void {
|
||||||
this.muc.add('modules_enabled', 'muc_http_defaults')
|
this.muc.add('modules_enabled', 'muc_http_defaults')
|
||||||
this.muc.add('muc_create_api_url', url)
|
this.muc.set('muc_create_api_url', url)
|
||||||
|
|
||||||
// restrict_room_creation: we can override the 'local' value.
|
// restrict_room_creation: we can override the 'local' value.
|
||||||
// Indeed, when muc_http_default is used, room creation will be managed by api.
|
// Indeed, when muc_http_default is used, room creation will be managed by api.
|
||||||
@ -517,7 +520,7 @@ class ProsodyConfigContent {
|
|||||||
*/
|
*/
|
||||||
useBotsVirtualHost (botAvatarPath: string, botAvatarFiles: string[]): void {
|
useBotsVirtualHost (botAvatarPath: string, botAvatarFiles: string[]): void {
|
||||||
this.bot = new ProsodyConfigVirtualHost('bot.' + this.prosodyDomain)
|
this.bot = new ProsodyConfigVirtualHost('bot.' + this.prosodyDomain)
|
||||||
this.bot.set('modules_enabled', ['ping'])
|
this.bot.set('modules_enabled', ['ping', 'tls'])
|
||||||
this.bot.set('authentication', 'peertubelivechat_bot')
|
this.bot.set('authentication', 'peertubelivechat_bot')
|
||||||
|
|
||||||
// For now, just using random_vcard_peertubelivechat to set bot avatar
|
// For now, just using random_vcard_peertubelivechat to set bot avatar
|
||||||
|
@ -13,7 +13,7 @@ import { LivechatProsodyAuth } from './prosody/auth'
|
|||||||
import { loc } from './loc'
|
import { loc } from './loc'
|
||||||
const escapeHTML = require('escape-html')
|
const escapeHTML = require('escape-html')
|
||||||
|
|
||||||
type AvatarSet = 'sepia' | 'cat' | 'bird' | 'fenec' | 'abstract' | 'legacy'
|
type AvatarSet = 'sepia' | 'cat' | 'bird' | 'fenec' | 'abstract' | 'legacy' | 'nctv'
|
||||||
|
|
||||||
async function initSettings (options: RegisterServerOptions): Promise<void> {
|
async function initSettings (options: RegisterServerOptions): Promise<void> {
|
||||||
const { peertubeHelpers, settingsManager } = options
|
const { peertubeHelpers, settingsManager } = options
|
||||||
@ -506,6 +506,7 @@ function initThemingSettings ({ registerSetting }: RegisterServerOptions): void
|
|||||||
private: true,
|
private: true,
|
||||||
options: [
|
options: [
|
||||||
{ value: 'sepia', label: loc('avatar_set_option_sepia') },
|
{ value: 'sepia', label: loc('avatar_set_option_sepia') },
|
||||||
|
{ value: 'nctv', label: loc('avatar_set_option_nctv') },
|
||||||
{ value: 'cat', label: loc('avatar_set_option_cat') },
|
{ value: 'cat', label: loc('avatar_set_option_cat') },
|
||||||
{ value: 'bird', label: loc('avatar_set_option_bird') },
|
{ value: 'bird', label: loc('avatar_set_option_bird') },
|
||||||
{ value: 'fenec', label: loc('avatar_set_option_fenec') },
|
{ value: 'fenec', label: loc('avatar_set_option_fenec') },
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// Note: API request body size is limited to 100Kb (expressjs body-parser defaut limit, and Peertube nginx config).
|
// Note: API request body size is limited to 100Kb (expressjs body-parser defaut limit, and Peertube nginx config).
|
||||||
// So we must be sure to never send more than 100Kb. The front end sends new emojis by batch, but maxSize must remain
|
// So we must be sure to never send more than 100Kb. The front end sends new emojis by batch, but maxSize must remain
|
||||||
// as little as possible, so that we never reach 100Kb in JSON/base64 format.
|
// as little as possible, so that we never reach 100Kb in JSON/base64 format.
|
||||||
export const maxSize: number = 30 * 1024
|
export const maxSize: number = 800 * 1024
|
||||||
export const allowedExtensions = ['png', 'jpg', 'jpeg', 'gif']
|
export const allowedExtensions = ['png', 'jpg', 'jpeg', 'gif']
|
||||||
export const inputFileAccept = ['image/jpg', 'image/png', 'image/gif']
|
export const inputFileAccept = ['image/jpg', 'image/png', 'image/gif']
|
||||||
export const allowedMimeTypes = ['image/jpg', 'image/png', 'image/gif']
|
export const allowedMimeTypes = ['image/jpg', 'image/png', 'image/gif']
|
||||||
|
@ -28,6 +28,7 @@ These files are used to generate multiple avatars (see the `build-avatars.js` sc
|
|||||||
* `assets/images/avatars/bird` contains new birds avatar set, based on the work of David Revoy (see copyright informations)
|
* `assets/images/avatars/bird` contains new birds avatar set, based on the work of David Revoy (see copyright informations)
|
||||||
* `assets/images/avatars/fenec` contains new fenecs avatar set, based on the work of David Revoy (see copyright informations)
|
* `assets/images/avatars/fenec` contains new fenecs avatar set, based on the work of David Revoy (see copyright informations)
|
||||||
* `assets/images/avatars/abstract` contains new abstract avatar set, based on the work of David Revoy (see copyright informations)
|
* `assets/images/avatars/abstract` contains new abstract avatar set, based on the work of David Revoy (see copyright informations)
|
||||||
|
* `assets/images/avatars/nctv` contains NCTV avatar, based on the work of The Almighty Kek
|
||||||
|
|
||||||
### assets/styles
|
### assets/styles
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user