mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-03 09:49:20 +02:00
Add ability for admins to refuse remote comments
This commit is contained in:
parent
031b61c466
commit
f5fd593976
12 changed files with 157 additions and 14 deletions
|
@ -463,6 +463,19 @@
|
||||||
|
|
||||||
<div class="content-col">
|
<div class="content-col">
|
||||||
|
|
||||||
|
<ng-container formGroupName="videoComments">
|
||||||
|
<div class="form-group">
|
||||||
|
<my-peertube-checkbox
|
||||||
|
inputName="videoCommentsAcceptRemoteComments" formControlName="acceptRemoteComments"
|
||||||
|
i18n-labelText labelText="Accept comments made on remote platforms"
|
||||||
|
>
|
||||||
|
<ng-container ngProjectAs="description">
|
||||||
|
<span i18n>This setting is not retroactive: current remote comments platform will not be deleted</span>
|
||||||
|
</ng-container>
|
||||||
|
</my-peertube-checkbox>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ng-container formGroupName="followers">
|
<ng-container formGroupName="followers">
|
||||||
<ng-container formGroupName="channels">
|
<ng-container formGroupName="channels">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
|
@ -198,6 +198,10 @@ type Form = {
|
||||||
autoPlay: FormControl<boolean>
|
autoPlay: FormControl<boolean>
|
||||||
}>
|
}>
|
||||||
}>
|
}>
|
||||||
|
|
||||||
|
videoComments: FormGroup<{
|
||||||
|
acceptRemoteComments: FormControl<boolean>
|
||||||
|
}>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -424,6 +428,9 @@ export class AdminConfigGeneralComponent implements OnInit, OnDestroy, CanCompon
|
||||||
player: {
|
player: {
|
||||||
autoPlay: null
|
autoPlay: null
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
videoComments: {
|
||||||
|
acceptRemoteComments: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -546,7 +546,7 @@ signup:
|
||||||
user:
|
user:
|
||||||
history:
|
history:
|
||||||
videos:
|
videos:
|
||||||
# Enable or disable video history by default for new users.
|
# Enable or disable video history by default for new users
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
# Default value of maximum video bytes the user can upload
|
# Default value of maximum video bytes the user can upload
|
||||||
|
@ -797,7 +797,7 @@ import:
|
||||||
# * https://yt-dl.org/downloads/latest/youtube-dl
|
# * https://yt-dl.org/downloads/latest/youtube-dl
|
||||||
#
|
#
|
||||||
# You can also use a youtube-dl standalone binary (requires python_path: null)
|
# You can also use a youtube-dl standalone binary (requires python_path: null)
|
||||||
# GNU/Linux binaries with support for impersonating browser requests (required by some platforms such as Vimeo) examples:
|
# GNU/Linux binaries with support for impersonating browser requests (required by some i such as Vimeo) examples:
|
||||||
# * https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux (x64)
|
# * https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux (x64)
|
||||||
# * https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_armv7l (ARMv7)
|
# * https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_armv7l (ARMv7)
|
||||||
# * https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_armv7l (ARMv8/AArch64/ARM64)
|
# * https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_armv7l (ARMv8/AArch64/ARM64)
|
||||||
|
@ -1143,3 +1143,8 @@ email:
|
||||||
subject:
|
subject:
|
||||||
# Support {{instanceName}} template variable
|
# Support {{instanceName}} template variable
|
||||||
prefix: '[{{instanceName}}] '
|
prefix: '[{{instanceName}}] '
|
||||||
|
|
||||||
|
video_comments:
|
||||||
|
# Accept or not comments from remote instances
|
||||||
|
# This setting is not retroactive: current remote comments of your instance will not be affected
|
||||||
|
accept_remote_comments: true
|
||||||
|
|
|
@ -358,4 +358,8 @@ export interface CustomConfig {
|
||||||
autoPlay: boolean
|
autoPlay: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
videoComments: {
|
||||||
|
acceptRemoteComments: boolean
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,8 @@ function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
|
||||||
|
|
||||||
expect(data.email.body.signature).to.equal('')
|
expect(data.email.body.signature).to.equal('')
|
||||||
expect(data.email.subject.prefix).to.equal('[{{instanceName}}] ')
|
expect(data.email.subject.prefix).to.equal('[{{instanceName}}] ')
|
||||||
|
|
||||||
|
expect(data.videoComments.acceptRemoteComments).to.be.true
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildNewCustomConfig (server: PeerTubeServer): CustomConfig {
|
function buildNewCustomConfig (server: PeerTubeServer): CustomConfig {
|
||||||
|
@ -464,6 +466,9 @@ function buildNewCustomConfig (server: PeerTubeServer): CustomConfig {
|
||||||
subject: {
|
subject: {
|
||||||
prefix: 'my prefix'
|
prefix: 'my prefix'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
videoComments: {
|
||||||
|
acceptRemoteComments: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,15 @@ import {
|
||||||
PeerTubeServer,
|
PeerTubeServer,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createSingleServer,
|
createSingleServer,
|
||||||
|
doubleFollow,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultAccountAvatar,
|
setDefaultAccountAvatar,
|
||||||
setDefaultChannelAvatar
|
setDefaultChannelAvatar,
|
||||||
|
waitJobs
|
||||||
} from '@peertube/peertube-server-commands'
|
} from '@peertube/peertube-server-commands'
|
||||||
import { dateIsValid, testImage } from '@tests/shared/checks.js'
|
import { dateIsValid, testImage } from '@tests/shared/checks.js'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
|
import { VideoCreateResult } from '../../../../models/src/videos/video-create-result.model.js'
|
||||||
|
|
||||||
describe('Test video comments', function () {
|
describe('Test video comments', function () {
|
||||||
let server: PeerTubeServer
|
let server: PeerTubeServer
|
||||||
|
@ -431,6 +434,95 @@ describe('Test video comments', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Disabling remote comments', function () {
|
||||||
|
let server2: PeerTubeServer
|
||||||
|
let server3: PeerTubeServer
|
||||||
|
|
||||||
|
let video1: VideoCreateResult
|
||||||
|
let video2: VideoCreateResult
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.timeout(120000)
|
||||||
|
|
||||||
|
server2 = await createSingleServer(2)
|
||||||
|
server3 = await createSingleServer(3)
|
||||||
|
|
||||||
|
await setAccessTokensToServers([ server2, server3 ])
|
||||||
|
await doubleFollow(server, server2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should federate comments', async function () {
|
||||||
|
video1 = await server.videos.quickUpload({ name: 'video on server 1' })
|
||||||
|
video2 = await server2.videos.quickUpload({ name: 'video on server 2' })
|
||||||
|
|
||||||
|
await server2.comments.createThread({ videoId: video1.uuid, text: 'comment on server 2' })
|
||||||
|
await server2.comments.createThread({ videoId: video2.uuid, text: 'comment on server 2' })
|
||||||
|
|
||||||
|
await waitJobs([ server, server2 ])
|
||||||
|
|
||||||
|
for (const s of [ server, server2 ]) {
|
||||||
|
const threads = await s.comments.listThreads({ videoId: video1.uuid })
|
||||||
|
expect(threads.total).to.equal(1)
|
||||||
|
expect(threads.data[0].text).to.equal('comment on server 2')
|
||||||
|
|
||||||
|
const threads2 = await s.comments.listThreads({ videoId: video2.uuid })
|
||||||
|
expect(threads2.total).to.equal(1)
|
||||||
|
expect(threads2.data[0].text).to.equal('comment on server 2')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should not accept remote comments anymore', async function () {
|
||||||
|
await server.config.updateExistingConfig({
|
||||||
|
newConfig: {
|
||||||
|
videoComments: {
|
||||||
|
acceptRemoteComments: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await server2.comments.createThread({ videoId: video1.uuid, text: 'comment on server 2 - 2' })
|
||||||
|
await server2.comments.createThread({ videoId: video2.uuid, text: 'comment on server 2 - 2' })
|
||||||
|
|
||||||
|
await waitJobs([ server, server2 ])
|
||||||
|
|
||||||
|
// Server 1
|
||||||
|
{
|
||||||
|
const threads = await server.comments.listThreads({ videoId: video1.uuid })
|
||||||
|
expect(threads.total).to.equal(1)
|
||||||
|
|
||||||
|
const threads2 = await server.comments.listThreads({ videoId: video2.uuid })
|
||||||
|
expect(threads2.total).to.equal(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server 2
|
||||||
|
{
|
||||||
|
const threads = await server2.comments.listThreads({ videoId: video1.uuid })
|
||||||
|
expect(threads.total).to.equal(2)
|
||||||
|
|
||||||
|
const threads2 = await server2.comments.listThreads({ videoId: video2.uuid })
|
||||||
|
expect(threads2.total).to.equal(2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should not fetch remote comments on new follow', async function () {
|
||||||
|
const video3 = await server3.videos.quickUpload({ name: 'video on server 2' })
|
||||||
|
await server3.comments.createThread({ videoId: video3.uuid, text: 'comment on server 3' })
|
||||||
|
|
||||||
|
await waitJobs([ server3 ])
|
||||||
|
await doubleFollow(server, server3)
|
||||||
|
|
||||||
|
{
|
||||||
|
const threads = await server3.comments.listThreads({ videoId: video3.uuid })
|
||||||
|
expect(threads.total).to.equal(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const threads = await server.comments.listThreads({ videoId: video3.uuid })
|
||||||
|
expect(threads.total).to.equal(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
await cleanupTests([ server ])
|
await cleanupTests([ server ])
|
||||||
})
|
})
|
||||||
|
|
|
@ -540,6 +540,10 @@ function customConfig (): CustomConfig {
|
||||||
subject: {
|
subject: {
|
||||||
prefix: CONFIG.EMAIL.SUBJECT.PREFIX
|
prefix: CONFIG.EMAIL.SUBJECT.PREFIX
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
videoComments: {
|
||||||
|
acceptRemoteComments: CONFIG.VIDEO_COMMENTS.ACCEPT_REMOTE_COMMENTS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,7 +251,8 @@ export function checkMissedConfig () {
|
||||||
'storyboards.enabled',
|
'storyboards.enabled',
|
||||||
'webrtc.stun_servers',
|
'webrtc.stun_servers',
|
||||||
'nsfw_flags_settings.enabled',
|
'nsfw_flags_settings.enabled',
|
||||||
'download_generate_video.max_parallel_downloads'
|
'download_generate_video.max_parallel_downloads',
|
||||||
|
'video_comments.accept_remote_comments'
|
||||||
]
|
]
|
||||||
|
|
||||||
const requiredAlternatives = [
|
const requiredAlternatives = [
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
import bytes from 'bytes'
|
|
||||||
import { IConfig } from 'config'
|
|
||||||
import { createRequire } from 'module'
|
|
||||||
import { dirname, join } from 'path'
|
|
||||||
import {
|
import {
|
||||||
BroadcastMessageLevel,
|
BroadcastMessageLevel,
|
||||||
NSFWPolicyType,
|
NSFWPolicyType,
|
||||||
|
@ -10,10 +6,14 @@ import {
|
||||||
VideoRedundancyConfigFilter,
|
VideoRedundancyConfigFilter,
|
||||||
VideosRedundancyStrategy
|
VideosRedundancyStrategy
|
||||||
} from '@peertube/peertube-models'
|
} from '@peertube/peertube-models'
|
||||||
import { decacheModule } from '@server/helpers/decache.js'
|
|
||||||
import { buildPath, root } from '@peertube/peertube-node-utils'
|
import { buildPath, root } from '@peertube/peertube-node-utils'
|
||||||
import { parseBytes, parseDurationToMs } from '../helpers/core-utils.js'
|
|
||||||
import { TranscriptionEngineName, WhisperBuiltinModelName } from '@peertube/peertube-transcription'
|
import { TranscriptionEngineName, WhisperBuiltinModelName } from '@peertube/peertube-transcription'
|
||||||
|
import { decacheModule } from '@server/helpers/decache.js'
|
||||||
|
import bytes from 'bytes'
|
||||||
|
import { IConfig } from 'config'
|
||||||
|
import { createRequire } from 'module'
|
||||||
|
import { dirname, join } from 'path'
|
||||||
|
import { parseBytes, parseDurationToMs } from '../helpers/core-utils.js'
|
||||||
|
|
||||||
const require = createRequire(import.meta.url)
|
const require = createRequire(import.meta.url)
|
||||||
let config: IConfig = require('config')
|
let config: IConfig = require('config')
|
||||||
|
@ -1090,6 +1090,11 @@ const CONFIG = {
|
||||||
return config.get<string>('email.subject.prefix')
|
return config.get<string>('email.subject.prefix')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
VIDEO_COMMENTS: {
|
||||||
|
get ACCEPT_REMOTE_COMMENTS () {
|
||||||
|
return config.get<boolean>('video_comments.accept_remote_comments')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1125,8 +1130,8 @@ export {
|
||||||
CONFIG,
|
CONFIG,
|
||||||
getConfigModule,
|
getConfigModule,
|
||||||
getLocalConfigFilePath,
|
getLocalConfigFilePath,
|
||||||
registerConfigChangedHandler,
|
isEmailEnabled,
|
||||||
isEmailEnabled
|
registerConfigChangedHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { arrayify } from '@peertube/peertube-core-utils'
|
||||||
import {
|
import {
|
||||||
AbuseObject,
|
AbuseObject,
|
||||||
ActivityCreate,
|
ActivityCreate,
|
||||||
|
@ -9,6 +10,7 @@ import {
|
||||||
VideoObject,
|
VideoObject,
|
||||||
WatchActionObject
|
WatchActionObject
|
||||||
} from '@peertube/peertube-models'
|
} from '@peertube/peertube-models'
|
||||||
|
import { CONFIG } from '@server/initializers/config.js'
|
||||||
import { isBlockedByServerOrAccount } from '@server/lib/blocklist.js'
|
import { isBlockedByServerOrAccount } from '@server/lib/blocklist.js'
|
||||||
import { isRedundancyAccepted } from '@server/lib/redundancy.js'
|
import { isRedundancyAccepted } from '@server/lib/redundancy.js'
|
||||||
import { VideoCommentModel } from '@server/models/video/video-comment.js'
|
import { VideoCommentModel } from '@server/models/video/video-comment.js'
|
||||||
|
@ -27,7 +29,6 @@ import { sendReplyApproval } from '../send/send-reply-approval.js'
|
||||||
import { forwardVideoRelatedActivity } from '../send/shared/send-utils.js'
|
import { forwardVideoRelatedActivity } from '../send/shared/send-utils.js'
|
||||||
import { resolveThread } from '../video-comments.js'
|
import { resolveThread } from '../video-comments.js'
|
||||||
import { canVideoBeFederated, getOrCreateAPVideo } from '../videos/index.js'
|
import { canVideoBeFederated, getOrCreateAPVideo } from '../videos/index.js'
|
||||||
import { arrayify } from '@peertube/peertube-core-utils'
|
|
||||||
|
|
||||||
async function processCreateActivity (options: APProcessorOptions<ActivityCreate<ActivityCreateObject>>) {
|
async function processCreateActivity (options: APProcessorOptions<ActivityCreate<ActivityCreateObject>>) {
|
||||||
const { activity, byActor } = options
|
const { activity, byActor } = options
|
||||||
|
@ -123,10 +124,11 @@ async function processCreateVideoComment (
|
||||||
byActor: MActorSignature,
|
byActor: MActorSignature,
|
||||||
fromFetch: false
|
fromFetch: false
|
||||||
) {
|
) {
|
||||||
|
if (CONFIG.VIDEO_COMMENTS.ACCEPT_REMOTE_COMMENTS !== true) return
|
||||||
|
|
||||||
if (fromFetch) throw new Error('Processing create video comment from fetch is not supported')
|
if (fromFetch) throw new Error('Processing create video comment from fetch is not supported')
|
||||||
|
|
||||||
const byAccount = byActor.Account
|
const byAccount = byActor.Account
|
||||||
|
|
||||||
if (!byAccount) throw new Error('Cannot create video comment with the non account actor ' + byActor.url)
|
if (!byAccount) throw new Error('Cannot create video comment with the non account actor ' + byActor.url)
|
||||||
|
|
||||||
let video: MVideoAccountLightBlacklistAllFiles
|
let video: MVideoAccountLightBlacklistAllFiles
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { fetchAP } from './activity.js'
|
||||||
import { getOrCreateAPActor } from './actors/index.js'
|
import { getOrCreateAPActor } from './actors/index.js'
|
||||||
import { checkUrlsSameHost } from './url.js'
|
import { checkUrlsSameHost } from './url.js'
|
||||||
import { canVideoBeFederated, getOrCreateAPVideo } from './videos/index.js'
|
import { canVideoBeFederated, getOrCreateAPVideo } from './videos/index.js'
|
||||||
|
import { CONFIG } from '@server/initializers/config.js'
|
||||||
|
|
||||||
type ResolveThreadParams = {
|
type ResolveThreadParams = {
|
||||||
url: string
|
url: string
|
||||||
|
@ -30,6 +31,8 @@ type ResolveThreadParams = {
|
||||||
type ResolveThreadResult = Promise<{ video: MVideoAccountLightBlacklistAllFiles, comment: MCommentOwnerVideo, commentCreated: boolean }>
|
type ResolveThreadResult = Promise<{ video: MVideoAccountLightBlacklistAllFiles, comment: MCommentOwnerVideo, commentCreated: boolean }>
|
||||||
|
|
||||||
export async function addVideoComments (commentUrls: string[]) {
|
export async function addVideoComments (commentUrls: string[]) {
|
||||||
|
if (CONFIG.VIDEO_COMMENTS.ACCEPT_REMOTE_COMMENTS !== true) return
|
||||||
|
|
||||||
return Bluebird.map(commentUrls, async commentUrl => {
|
return Bluebird.map(commentUrls, async commentUrl => {
|
||||||
try {
|
try {
|
||||||
await resolveThread({ url: commentUrl, isVideo: false })
|
await resolveThread({ url: commentUrl, isVideo: false })
|
||||||
|
|
|
@ -147,6 +147,8 @@ const customConfigUpdateValidator = [
|
||||||
body('email.body.signature').exists(),
|
body('email.body.signature').exists(),
|
||||||
body('email.subject.prefix').exists(),
|
body('email.subject.prefix').exists(),
|
||||||
|
|
||||||
|
body('videoComments.acceptRemoteComments').isBoolean(),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
if (!checkInvalidConfigIfEmailDisabled(req.body, res)) return
|
if (!checkInvalidConfigIfEmailDisabled(req.body, res)) return
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue