Add ability to embed a video in Twitter

The instance should be whitelisted first
pull/559/head
Chocobozzz 2018-05-10 12:26:47 +02:00
parent c7b0dacb28
commit 8be1afa12b
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
14 changed files with 355 additions and 213 deletions

View File

@ -1,222 +1,259 @@
<div class="form-sub-title">Update PeerTube configuration</div>
<form role="form" [formGroup]="form">
<div class="inner-form-title">Instance</div>
<tabset class="root-tabset bootstrap">
<div class="form-group">
<label for="instanceName">Name</label>
<input
type="text" id="instanceName"
formControlName="instanceName" [ngClass]="{ 'input-error': formErrors['instanceName'] }"
>
<div *ngIf="formErrors.instanceName" class="form-error">
{{ formErrors.instanceName }}
</div>
</div>
<tab heading="Basic configuration">
<div class="form-group">
<label for="instanceShortDescription">Short description</label>
<textarea
id="instanceShortDescription" formControlName="instanceShortDescription"
[ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }"
></textarea>
<div *ngIf="formErrors.instanceShortDescription" class="form-error">
{{ formErrors.instanceShortDescription }}
</div>
</div>
<div class="inner-form-title">Instance</div>
<div class="form-group">
<label for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help>
<my-markdown-textarea
id="instanceDescription" formControlName="instanceDescription" textareaWidth="500px" [previewColumn]="true"
[classes]="{ 'input-error': formErrors['instanceDescription'] }"
></my-markdown-textarea>
<div *ngIf="formErrors.instanceDescription" class="form-error">
{{ formErrors.instanceDescription }}
</div>
</div>
<div class="form-group">
<label for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
<my-markdown-textarea
id="instanceTerms" formControlName="instanceTerms" textareaWidth="500px" [previewColumn]="true"
[ngClass]="{ 'input-error': formErrors['instanceTerms'] }"
></my-markdown-textarea>
<div *ngIf="formErrors.instanceTerms" class="form-error">
{{ formErrors.instanceTerms }}
</div>
</div>
<div class="form-group">
<label for="instanceDefaultClientRoute">Default client route</label>
<div class="peertube-select-container">
<select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute">
<option value="/videos/trending">Videos Trending</option>
<option value="/videos/recently-added">Videos Recently Added</option>
<option value="/videos/local">Local videos</option>
</select>
</div>
<div *ngIf="formErrors.instanceDefaultClientRoute" class="form-error">
{{ formErrors.instanceDefaultClientRoute }}
</div>
</div>
<div class="form-group">
<label for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
<my-help helpType="custom" customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."></my-help>
<div class="peertube-select-container">
<select id="instanceDefaultNSFWPolicy" formControlName="instanceDefaultNSFWPolicy">
<option value="do_not_list">Do not list</option>
<option value="blur">Blur thumbnails</option>
<option value="display">Display</option>
</select>
</div>
<div *ngIf="formErrors.instanceDefaultNSFWPolicy" class="form-error">
{{ formErrors.instanceDefaultNSFWPolicy }}
</div>
</div>
<div class="inner-form-title">Cache</div>
<div class="form-group">
<label for="cachePreviewsSize">Preview cache size</label>
<input
type="text" id="cachePreviewsSize"
formControlName="cachePreviewsSize" [ngClass]="{ 'input-error': formErrors['cachePreviewsSize'] }"
>
<div *ngIf="formErrors.cachePreviewsSize" class="form-error">
{{ formErrors.cachePreviewsSize }}
</div>
</div>
<div class="inner-form-title">Signup</div>
<div class="form-group">
<input type="checkbox" id="signupEnabled" formControlName="signupEnabled">
<label for="signupEnabled"></label>
<label for="signupEnabled">Signup enabled</label>
</div>
<div *ngIf="isSignupEnabled()" class="form-group">
<label for="signupLimit">Signup limit</label>
<input
type="text" id="signupLimit"
formControlName="signupLimit" [ngClass]="{ 'input-error': formErrors['signupLimit'] }"
>
<div *ngIf="formErrors.signupLimit" class="form-error">
{{ formErrors.signupLimit }}
</div>
</div>
<div class="inner-form-title">Administrator</div>
<div class="form-group">
<label for="adminEmail">Admin email</label>
<input
type="text" id="adminEmail"
formControlName="adminEmail" [ngClass]="{ 'input-error': formErrors['adminEmail'] }"
>
<div *ngIf="formErrors.adminEmail" class="form-error">
{{ formErrors.adminEmail }}
</div>
</div>
<div class="inner-form-title">Users</div>
<div class="form-group">
<label for="userVideoQuota">User default video quota</label>
<div class="peertube-select-container">
<select id="userVideoQuota" formControlName="userVideoQuota">
<option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
{{ videoQuotaOption.label }}
</option>
</select>
</div>
<div *ngIf="formErrors.userVideoQuota" class="form-error">
{{ formErrors.userVideoQuota }}
</div>
</div>
<div class="inner-form-title">Transcoding</div>
<div class="form-group">
<input type="checkbox" id="transcodingEnabled" formControlName="transcodingEnabled">
<label for="transcodingEnabled"></label>
<label for="transcodingEnabled">Transcoding enabled</label>
</div>
<ng-template [ngIf]="isTranscodingEnabled()">
<div class="form-group">
<label for="transcodingThreads">Transcoding threads</label>
<div class="peertube-select-container">
<select id="transcodingThreads" formControlName="transcodingThreads">
<option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value">
{{ transcodingThreadOption.label }}
</option>
</select>
<div class="form-group">
<label for="instanceName">Name</label>
<input
type="text" id="instanceName"
formControlName="instanceName" [ngClass]="{ 'input-error': formErrors['instanceName'] }"
>
<div *ngIf="formErrors.instanceName" class="form-error">
{{ formErrors.instanceName }}
</div>
</div>
<div *ngIf="formErrors.transcodingThreads" class="form-error">
{{ formErrors.transcodingThreads }}
<div class="form-group">
<label for="instanceShortDescription">Short description</label>
<textarea
id="instanceShortDescription" formControlName="instanceShortDescription"
[ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }"
></textarea>
<div *ngIf="formErrors.instanceShortDescription" class="form-error">
{{ formErrors.instanceShortDescription }}
</div>
</div>
</div>
<div class="form-group" *ngFor="let resolution of resolutions">
<input
type="checkbox" [id]="getResolutionKey(resolution)"
[formControlName]="getResolutionKey(resolution)"
>
<label [for]="getResolutionKey(resolution)"></label>
<label [for]="getResolutionKey(resolution)">Resolution {{ resolution }} enabled</label>
</div>
</ng-template>
<div class="form-group">
<label for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help>
<my-markdown-textarea
id="instanceDescription" formControlName="instanceDescription" textareaWidth="500px" [previewColumn]="true"
[classes]="{ 'input-error': formErrors['instanceDescription'] }"
></my-markdown-textarea>
<div *ngIf="formErrors.instanceDescription" class="form-error">
{{ formErrors.instanceDescription }}
</div>
</div>
<div class="inner-form-title">Customizations</div>
<div class="form-group">
<label for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
<my-markdown-textarea
id="instanceTerms" formControlName="instanceTerms" textareaWidth="500px" [previewColumn]="true"
[ngClass]="{ 'input-error': formErrors['instanceTerms'] }"
></my-markdown-textarea>
<div *ngIf="formErrors.instanceTerms" class="form-error">
{{ formErrors.instanceTerms }}
</div>
</div>
<div class="form-group">
<label for="customizationJavascript">JavaScript</label>
<my-help helpType="custom" customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>"></my-help>
<textarea
id="customizationJavascript" formControlName="customizationJavascript"
[ngClass]="{ 'input-error': formErrors['customizationJavascript'] }"
></textarea>
<div *ngIf="formErrors.customizationJavascript" class="form-error">
{{ formErrors.customizationJavascript }}
</div>
</div>
<div class="form-group">
<label for="instanceDefaultClientRoute">Default client route</label>
<div class="peertube-select-container">
<select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute">
<option value="/videos/trending">Videos Trending</option>
<option value="/videos/recently-added">Videos Recently Added</option>
<option value="/videos/local">Local videos</option>
</select>
</div>
<div *ngIf="formErrors.instanceDefaultClientRoute" class="form-error">
{{ formErrors.instanceDefaultClientRoute }}
</div>
</div>
<div class="form-group">
<label for="customizationCSS">CSS</label>
<my-help
helpType="custom"
customHtml="
Write directly CSS code. Example:<br />
<pre>
body {
background-color: red;
}
</pre>
<div class="form-group">
<label for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
<my-help helpType="custom" customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."></my-help>
Prepend with <em>#custom-css</em> to override styles. Example:
<pre>
#custom-css .logged-in-email {
color: red;
}
</pre>
"
></my-help>
<textarea
id="customizationCSS" formControlName="customizationCSS"
[ngClass]="{ 'input-error': formErrors['customizationCSS'] }"
></textarea>
<div *ngIf="formErrors.customizationCSS" class="form-error">
{{ formErrors.customizationCSS }}
</div>
</div>
<div class="peertube-select-container">
<select id="instanceDefaultNSFWPolicy" formControlName="instanceDefaultNSFWPolicy">
<option value="do_not_list">Do not list</option>
<option value="blur">Blur thumbnails</option>
<option value="display">Display</option>
</select>
</div>
<div *ngIf="formErrors.instanceDefaultNSFWPolicy" class="form-error">
{{ formErrors.instanceDefaultNSFWPolicy }}
</div>
</div>
<div class="inner-form-title">Signup</div>
<div class="form-group">
<input type="checkbox" id="signupEnabled" formControlName="signupEnabled">
<label for="signupEnabled"></label>
<label for="signupEnabled">Signup enabled</label>
</div>
<div *ngIf="isSignupEnabled()" class="form-group">
<label for="signupLimit">Signup limit</label>
<input
type="text" id="signupLimit"
formControlName="signupLimit" [ngClass]="{ 'input-error': formErrors['signupLimit'] }"
>
<div *ngIf="formErrors.signupLimit" class="form-error">
{{ formErrors.signupLimit }}
</div>
</div>
<div class="inner-form-title">Administrator</div>
<div class="form-group">
<label for="adminEmail">Admin email</label>
<input
type="text" id="adminEmail"
formControlName="adminEmail" [ngClass]="{ 'input-error': formErrors['adminEmail'] }"
>
<div *ngIf="formErrors.adminEmail" class="form-error">
{{ formErrors.adminEmail }}
</div>
</div>
<div class="inner-form-title">Users</div>
<div class="form-group">
<label for="userVideoQuota">User default video quota</label>
<div class="peertube-select-container">
<select id="userVideoQuota" formControlName="userVideoQuota">
<option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
{{ videoQuotaOption.label }}
</option>
</select>
</div>
<div *ngIf="formErrors.userVideoQuota" class="form-error">
{{ formErrors.userVideoQuota }}
</div>
</div>
</tab>
<tab heading="Services">
<div class="inner-form-title">Twitter</div>
<div class="form-group">
<label for="signupLimit">Your Twitter username</label>
<my-help helpType="custom" customHtml="The Twitter @username the cards (created by PeerTube video shares) should be attributed to."></my-help>
<input
type="text" id="servicesTwitterUsername"
formControlName="servicesTwitterUsername" [ngClass]="{ 'input-error': formErrors['servicesTwitterUsername'] }"
>
<div *ngIf="formErrors.servicesTwitterUsername" class="form-error">
{{ formErrors.servicesTwitterUsername }}
</div>
</div>
<div class="form-group">
<input type="checkbox" id="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted">
<label for="servicesTwitterWhitelisted"></label>
<label for="servicesTwitterWhitelisted">Instance whitelisted by Twitter</label>
<my-help helpType="custom" customHtml="If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br />
Check this checkbox, save the configuration and test on <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a> to see if you instance is whitelisted."></my-help>
</div>
</tab>
<tab heading="Advanced configuration">
<div class="inner-form-title">Transcoding</div>
<div class="form-group">
<input type="checkbox" id="transcodingEnabled" formControlName="transcodingEnabled">
<label for="transcodingEnabled"></label>
<label for="transcodingEnabled">Transcoding enabled</label>
</div>
<ng-template [ngIf]="isTranscodingEnabled()">
<div class="form-group">
<label for="transcodingThreads">Transcoding threads</label>
<div class="peertube-select-container">
<select id="transcodingThreads" formControlName="transcodingThreads">
<option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value">
{{ transcodingThreadOption.label }}
</option>
</select>
</div>
<div *ngIf="formErrors.transcodingThreads" class="form-error">
{{ formErrors.transcodingThreads }}
</div>
</div>
<div class="form-group" *ngFor="let resolution of resolutions">
<input
type="checkbox" [id]="getResolutionKey(resolution)"
[formControlName]="getResolutionKey(resolution)"
>
<label [for]="getResolutionKey(resolution)"></label>
<label [for]="getResolutionKey(resolution)">Resolution {{ resolution }} enabled</label>
</div>
</ng-template>
<div class="inner-form-title">Cache</div>
<div class="form-group">
<label for="cachePreviewsSize">Preview cache size</label>
<my-help helpType="custom" customHtml="Previews are not federated. We fetch them directly from the origin instance and cache them."></my-help>
<input
type="text" id="cachePreviewsSize"
formControlName="cachePreviewsSize" [ngClass]="{ 'input-error': formErrors['cachePreviewsSize'] }"
>
<div *ngIf="formErrors.cachePreviewsSize" class="form-error">
{{ formErrors.cachePreviewsSize }}
</div>
</div>
<div class="inner-form-title">Customizations</div>
<div class="form-group">
<label for="customizationJavascript">JavaScript</label>
<my-help helpType="custom" customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>"></my-help>
<textarea
id="customizationJavascript" formControlName="customizationJavascript"
[ngClass]="{ 'input-error': formErrors['customizationJavascript'] }"
></textarea>
<div *ngIf="formErrors.customizationJavascript" class="form-error">
{{ formErrors.customizationJavascript }}
</div>
</div>
<div class="form-group">
<label for="customizationCSS">CSS</label>
<my-help
helpType="custom"
customHtml="
Write directly CSS code. Example:<br />
<pre>
body {
background-color: red;
}
</pre>
Prepend with <em>#custom-css</em> to override styles. Example:
<pre>
#custom-css .logged-in-email {
color: red;
}
</pre>
"
></my-help>
<textarea
id="customizationCSS" formControlName="customizationCSS"
[ngClass]="{ 'input-error': formErrors['customizationCSS'] }"
></textarea>
<div *ngIf="formErrors.customizationCSS" class="form-error">
{{ formErrors.customizationCSS }}
</div>
</div>
</tab>
</tabset>
<input (click)="formValidated()" type="submit" value="Update configuration" [disabled]="!form.valid">
</form>

View File

@ -8,7 +8,7 @@ import { FormReactive, USER_VIDEO_QUOTA } from '@app/shared'
import {
ADMIN_EMAIL,
CACHE_PREVIEWS_SIZE,
INSTANCE_NAME, INSTANCE_SHORT_DESCRIPTION,
INSTANCE_NAME, INSTANCE_SHORT_DESCRIPTION, SERVICES_TWITTER_USERNAME,
SIGNUP_LIMIT,
TRANSCODING_THREADS
} from '@app/shared/forms/form-validators/custom-config'
@ -49,6 +49,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
instanceTerms: '',
instanceDefaultClientRoute: '',
instanceDefaultNSFWPolicy: '',
servicesTwitterUsername: '',
cachePreviewsSize: '',
signupLimit: '',
adminEmail: '',
@ -60,6 +61,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
validationMessages = {
instanceShortDescription: INSTANCE_SHORT_DESCRIPTION.MESSAGES,
instanceName: INSTANCE_NAME.MESSAGES,
servicesTwitterUsername: SERVICES_TWITTER_USERNAME,
cachePreviewsSize: CACHE_PREVIEWS_SIZE.MESSAGES,
signupLimit: SIGNUP_LIMIT.MESSAGES,
adminEmail: ADMIN_EMAIL.MESSAGES,
@ -92,6 +94,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
instanceTerms: [ '' ],
instanceDefaultClientRoute: [ '' ],
instanceDefaultNSFWPolicy: [ '' ],
servicesTwitterUsername: [ '', SERVICES_TWITTER_USERNAME.VALIDATORS ],
servicesTwitterWhitelisted: [ ],
cachePreviewsSize: [ '', CACHE_PREVIEWS_SIZE.VALIDATORS ],
signupEnabled: [ ],
signupLimit: [ '', SIGNUP_LIMIT.VALIDATORS ],
@ -175,6 +179,12 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
css: this.form.value['customizationCSS']
}
},
services: {
twitter: {
username: this.form.value['servicesTwitterUsername'],
whitelisted: this.form.value['servicesTwitterWhitelisted']
}
},
cache: {
previews: {
size: this.form.value['cachePreviewsSize']
@ -228,6 +238,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
instanceTerms: this.customConfig.instance.terms,
instanceDefaultClientRoute: this.customConfig.instance.defaultClientRoute,
instanceDefaultNSFWPolicy: this.customConfig.instance.defaultNSFWPolicy,
servicesTwitterUsername: this.customConfig.services.twitter.username,
servicesTwitterWhitelisted: this.customConfig.services.twitter.whitelisted,
cachePreviewsSize: this.customConfig.cache.previews.size,
signupEnabled: this.customConfig.signup.enabled,
signupLimit: this.customConfig.signup.limit,

View File

@ -14,6 +14,13 @@ export const INSTANCE_SHORT_DESCRIPTION = {
}
}
export const SERVICES_TWITTER_USERNAME = {
VALIDATORS: [ Validators.required ],
MESSAGES: {
'required': 'Twitter username is required.'
}
}
export const CACHE_PREVIEWS_SIZE = {
VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
MESSAGES: {

View File

@ -35,6 +35,7 @@ import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';
import 'core-js/es7/object';
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
@ -44,7 +45,6 @@ import 'core-js/es6/set';
// For Google Bot
import 'core-js/es6/reflect';
/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import 'core-js/es7/reflect'

View File

@ -90,3 +90,12 @@ instance:
customizations:
javascript: '' # Directly your JavaScript code (without <script> tags). Will be eval at runtime
css: '' # Directly your CSS code (without <style> tags). Will be injected at runtime
services:
# Cards configuration to format video in Twitter
twitter:
username: '@Chocobozzz' # The Twitter @username the card should be attributed to
# If true, a video player will be embedded in the Twitter feed on PeerTube video share
# If false, we use an image link card that will redirect on your PeerTube instance
# Change it to "true", and then test on https://cards-dev.twitter.com/validator to see if you are whitelisted
whitelisted: false

View File

@ -106,3 +106,12 @@ instance:
customizations:
javascript: '' # Directly your JavaScript code (without <script> tags). Will be eval at runtime
css: '' # Directly your CSS code (without <style> tags). Will be injected at runtime
services:
# Cards configuration to format video in Twitter
twitter:
username: '@Chocobozzz' # The Twitter @username the card should be attributed to
# If true, a video player will be embedded in the Twitter feed on PeerTube video share
# If false, we use an image link card that will redirect on your PeerTube instance
# Test on https://cards-dev.twitter.com/validator to see if you are whitelisted
whitelisted: false

View File

@ -161,6 +161,12 @@ function customConfig (): CustomConfig {
javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT
}
},
services: {
twitter: {
username: CONFIG.SERVICES.TWITTER.USERNAME,
whitelisted: CONFIG.SERVICES.TWITTER.WHITELISTED
}
},
cache: {
previews: {
size: CONFIG.CACHE.PREVIEWS.SIZE

View File

@ -77,8 +77,8 @@ function addOpenGraphAndOEmbedTags (htmlStringPage: string, video: VideoModel) {
'description': videoDescriptionEscaped,
'image': previewUrl,
'twitter:card': 'summary_large_image',
'twitter:site': '@Chocobozzz',
'twitter:card': CONFIG.SERVICES.TWITTER.WHITELISTED ? 'player' : 'summary_large_image',
'twitter:site': CONFIG.SERVICES.TWITTER.USERNAME,
'twitter:title': videoNameEscaped,
'twitter:description': videoDescriptionEscaped,
'twitter:image': previewUrl,

View File

@ -29,7 +29,8 @@ function checkMissedConfig () {
'user.video_quota',
'cache.previews.size', 'admin.email', 'signup.enabled', 'signup.limit', 'transcoding.enabled', 'transcoding.threads',
'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route',
'instance.default_nsfw_policy'
'instance.default_nsfw_policy',
'services.twitter.username', 'services.twitter.whitelisted'
]
const miss: string[] = []

View File

@ -174,6 +174,12 @@ const CONFIG = {
get JAVASCRIPT () { return config.get<string>('instance.customizations.javascript') },
get CSS () { return config.get<string>('instance.customizations.css') }
}
},
SERVICES: {
TWITTER: {
get USERNAME () { return config.get<string>('services.twitter.username') },
get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') }
}
}
}

View File

@ -26,6 +26,12 @@ describe('Test config API validators', function () {
css: 'body { background-color: red; }'
}
},
services: {
twitter: {
username: '@MySuperUsername',
whitelisted: true
}
},
cache: {
previews: {
size: 2

View File

@ -62,6 +62,8 @@ describe('Test config', function () {
expect(data.instance.defaultNSFWPolicy).to.equal('display')
expect(data.instance.customizations.css).to.be.empty
expect(data.instance.customizations.javascript).to.be.empty
expect(data.services.twitter.username).to.equal('@Chocobozzz')
expect(data.services.twitter.whitelisted).to.be.false
expect(data.cache.previews.size).to.equal(1)
expect(data.signup.enabled).to.be.true
expect(data.signup.limit).to.equal(4)
@ -90,6 +92,12 @@ describe('Test config', function () {
css: 'body { background-color: red; }'
}
},
services: {
twitter: {
username: '@Kuja',
whitelisted: true
}
},
cache: {
previews: {
size: 2
@ -130,6 +138,8 @@ describe('Test config', function () {
expect(data.instance.defaultNSFWPolicy).to.equal('blur')
expect(data.instance.customizations.javascript).to.equal('alert("coucou")')
expect(data.instance.customizations.css).to.equal('body { background-color: red; }')
expect(data.services.twitter.username).to.equal('@Kuja')
expect(data.services.twitter.whitelisted).to.be.true
expect(data.cache.previews.size).to.equal(2)
expect(data.signup.enabled).to.be.false
expect(data.signup.limit).to.equal(5)
@ -162,6 +172,8 @@ describe('Test config', function () {
expect(data.instance.defaultNSFWPolicy).to.equal('blur')
expect(data.instance.customizations.javascript).to.equal('alert("coucou")')
expect(data.instance.customizations.css).to.equal('body { background-color: red; }')
expect(data.services.twitter.username).to.equal('@Kuja')
expect(data.services.twitter.whitelisted).to.be.true
expect(data.cache.previews.size).to.equal(2)
expect(data.signup.enabled).to.be.false
expect(data.signup.limit).to.equal(5)
@ -205,6 +217,8 @@ describe('Test config', function () {
expect(data.instance.defaultNSFWPolicy).to.equal('display')
expect(data.instance.customizations.css).to.be.empty
expect(data.instance.customizations.javascript).to.be.empty
expect(data.services.twitter.username).to.equal('@Chocobozzz')
expect(data.services.twitter.whitelisted).to.be.false
expect(data.cache.previews.size).to.equal(1)
expect(data.signup.enabled).to.be.true
expect(data.signup.limit).to.equal(4)

View File

@ -11,7 +11,7 @@ import {
runServer,
serverLogin,
uploadVideo,
getVideosList
getVideosList, updateCustomConfig, getCustomConfig
} from './utils'
describe('Test a client controllers', function () {
@ -73,6 +73,34 @@ describe('Test a client controllers', function () {
expect(res.text).to.contain(expectedLink)
})
it('Should have valid twitter card', async function () {
const res = await request(server.url)
.get('/videos/watch/' + server.video.uuid)
.set('Accept', 'text/html')
.expect(200)
expect(res.text).to.contain('<meta property="twitter:card" content="summary_large_image" />')
expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
})
it('Should have valid twitter card if Twitter is whitelisted', async function () {
const res1 = await getCustomConfig(server.url, server.accessToken)
const config = res1.body
config.services.twitter = {
username: '@Kuja',
whitelisted: true
}
await updateCustomConfig(server.url, server.accessToken, config)
const res = await request(server.url)
.get('/videos/watch/' + server.video.uuid)
.set('Accept', 'text/html')
.expect(200)
expect(res.text).to.contain('<meta property="twitter:card" content="player" />')
expect(res.text).to.contain('<meta property="twitter:site" content="@Kuja" />')
})
after(async function () {
process.kill(-server.app.pid)

View File

@ -14,6 +14,13 @@ export interface CustomConfig {
}
}
services: {
twitter: {
username: string
whitelisted: boolean
}
}
cache: {
previews: {
size: number