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">
|
||||
|
||||
<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="channels">
|
||||
<div class="form-group">
|
||||
|
|
|
@ -198,6 +198,10 @@ type Form = {
|
|||
autoPlay: FormControl<boolean>
|
||||
}>
|
||||
}>
|
||||
|
||||
videoComments: FormGroup<{
|
||||
acceptRemoteComments: FormControl<boolean>
|
||||
}>
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
@ -424,6 +428,9 @@ export class AdminConfigGeneralComponent implements OnInit, OnDestroy, CanCompon
|
|||
player: {
|
||||
autoPlay: null
|
||||
}
|
||||
},
|
||||
videoComments: {
|
||||
acceptRemoteComments: null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -546,7 +546,7 @@ signup:
|
|||
user:
|
||||
history:
|
||||
videos:
|
||||
# Enable or disable video history by default for new users.
|
||||
# Enable or disable video history by default for new users
|
||||
enabled: true
|
||||
|
||||
# Default value of maximum video bytes the user can upload
|
||||
|
@ -797,7 +797,7 @@ import:
|
|||
# * https://yt-dl.org/downloads/latest/youtube-dl
|
||||
#
|
||||
# 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_armv7l (ARMv7)
|
||||
# * https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_armv7l (ARMv8/AArch64/ARM64)
|
||||
|
@ -1143,3 +1143,8 @@ email:
|
|||
subject:
|
||||
# Support {{instanceName}} template variable
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
videoComments: {
|
||||
acceptRemoteComments: boolean
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,6 +158,8 @@ function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
|
|||
|
||||
expect(data.email.body.signature).to.equal('')
|
||||
expect(data.email.subject.prefix).to.equal('[{{instanceName}}] ')
|
||||
|
||||
expect(data.videoComments.acceptRemoteComments).to.be.true
|
||||
}
|
||||
|
||||
function buildNewCustomConfig (server: PeerTubeServer): CustomConfig {
|
||||
|
@ -464,6 +466,9 @@ function buildNewCustomConfig (server: PeerTubeServer): CustomConfig {
|
|||
subject: {
|
||||
prefix: 'my prefix'
|
||||
}
|
||||
},
|
||||
videoComments: {
|
||||
acceptRemoteComments: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,15 @@ import {
|
|||
PeerTubeServer,
|
||||
cleanupTests,
|
||||
createSingleServer,
|
||||
doubleFollow,
|
||||
setAccessTokensToServers,
|
||||
setDefaultAccountAvatar,
|
||||
setDefaultChannelAvatar
|
||||
setDefaultChannelAvatar,
|
||||
waitJobs
|
||||
} from '@peertube/peertube-server-commands'
|
||||
import { dateIsValid, testImage } from '@tests/shared/checks.js'
|
||||
import { expect } from 'chai'
|
||||
import { VideoCreateResult } from '../../../../models/src/videos/video-create-result.model.js'
|
||||
|
||||
describe('Test video comments', function () {
|
||||
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 () {
|
||||
await cleanupTests([ server ])
|
||||
})
|
||||
|
|
|
@ -540,6 +540,10 @@ function customConfig (): CustomConfig {
|
|||
subject: {
|
||||
prefix: CONFIG.EMAIL.SUBJECT.PREFIX
|
||||
}
|
||||
},
|
||||
|
||||
videoComments: {
|
||||
acceptRemoteComments: CONFIG.VIDEO_COMMENTS.ACCEPT_REMOTE_COMMENTS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -251,7 +251,8 @@ export function checkMissedConfig () {
|
|||
'storyboards.enabled',
|
||||
'webrtc.stun_servers',
|
||||
'nsfw_flags_settings.enabled',
|
||||
'download_generate_video.max_parallel_downloads'
|
||||
'download_generate_video.max_parallel_downloads',
|
||||
'video_comments.accept_remote_comments'
|
||||
]
|
||||
|
||||
const requiredAlternatives = [
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
import bytes from 'bytes'
|
||||
import { IConfig } from 'config'
|
||||
import { createRequire } from 'module'
|
||||
import { dirname, join } from 'path'
|
||||
import {
|
||||
BroadcastMessageLevel,
|
||||
NSFWPolicyType,
|
||||
|
@ -10,10 +6,14 @@ import {
|
|||
VideoRedundancyConfigFilter,
|
||||
VideosRedundancyStrategy
|
||||
} from '@peertube/peertube-models'
|
||||
import { decacheModule } from '@server/helpers/decache.js'
|
||||
import { buildPath, root } from '@peertube/peertube-node-utils'
|
||||
import { parseBytes, parseDurationToMs } from '../helpers/core-utils.js'
|
||||
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)
|
||||
let config: IConfig = require('config')
|
||||
|
@ -1090,6 +1090,11 @@ const CONFIG = {
|
|||
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,
|
||||
getConfigModule,
|
||||
getLocalConfigFilePath,
|
||||
registerConfigChangedHandler,
|
||||
isEmailEnabled
|
||||
isEmailEnabled,
|
||||
registerConfigChangedHandler
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { arrayify } from '@peertube/peertube-core-utils'
|
||||
import {
|
||||
AbuseObject,
|
||||
ActivityCreate,
|
||||
|
@ -9,6 +10,7 @@ import {
|
|||
VideoObject,
|
||||
WatchActionObject
|
||||
} from '@peertube/peertube-models'
|
||||
import { CONFIG } from '@server/initializers/config.js'
|
||||
import { isBlockedByServerOrAccount } from '@server/lib/blocklist.js'
|
||||
import { isRedundancyAccepted } from '@server/lib/redundancy.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 { resolveThread } from '../video-comments.js'
|
||||
import { canVideoBeFederated, getOrCreateAPVideo } from '../videos/index.js'
|
||||
import { arrayify } from '@peertube/peertube-core-utils'
|
||||
|
||||
async function processCreateActivity (options: APProcessorOptions<ActivityCreate<ActivityCreateObject>>) {
|
||||
const { activity, byActor } = options
|
||||
|
@ -123,10 +124,11 @@ async function processCreateVideoComment (
|
|||
byActor: MActorSignature,
|
||||
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')
|
||||
|
||||
const byAccount = byActor.Account
|
||||
|
||||
if (!byAccount) throw new Error('Cannot create video comment with the non account actor ' + byActor.url)
|
||||
|
||||
let video: MVideoAccountLightBlacklistAllFiles
|
||||
|
|
|
@ -20,6 +20,7 @@ import { fetchAP } from './activity.js'
|
|||
import { getOrCreateAPActor } from './actors/index.js'
|
||||
import { checkUrlsSameHost } from './url.js'
|
||||
import { canVideoBeFederated, getOrCreateAPVideo } from './videos/index.js'
|
||||
import { CONFIG } from '@server/initializers/config.js'
|
||||
|
||||
type ResolveThreadParams = {
|
||||
url: string
|
||||
|
@ -30,6 +31,8 @@ type ResolveThreadParams = {
|
|||
type ResolveThreadResult = Promise<{ video: MVideoAccountLightBlacklistAllFiles, comment: MCommentOwnerVideo, commentCreated: boolean }>
|
||||
|
||||
export async function addVideoComments (commentUrls: string[]) {
|
||||
if (CONFIG.VIDEO_COMMENTS.ACCEPT_REMOTE_COMMENTS !== true) return
|
||||
|
||||
return Bluebird.map(commentUrls, async commentUrl => {
|
||||
try {
|
||||
await resolveThread({ url: commentUrl, isVideo: false })
|
||||
|
|
|
@ -147,6 +147,8 @@ const customConfigUpdateValidator = [
|
|||
body('email.body.signature').exists(),
|
||||
body('email.subject.prefix').exists(),
|
||||
|
||||
body('videoComments.acceptRemoteComments').isBoolean(),
|
||||
|
||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
if (areValidationErrors(req, res)) return
|
||||
if (!checkInvalidConfigIfEmailDisabled(req.body, res)) return
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue