Add ability to search by URL with query params
This commit is contained in:
parent
ebe9b6b3f3
commit
400043b1be
10 changed files with 109 additions and 33 deletions
|
@ -25,6 +25,7 @@ import {
|
||||||
} from '../../../middlewares'
|
} from '../../../middlewares'
|
||||||
import { VideoChannelModel } from '../../../models/video/video-channel'
|
import { VideoChannelModel } from '../../../models/video/video-channel'
|
||||||
import { MChannelAccountDefault } from '../../../types/models'
|
import { MChannelAccountDefault } from '../../../types/models'
|
||||||
|
import { searchLocalUrl } from './shared'
|
||||||
|
|
||||||
const searchChannelsRouter = express.Router()
|
const searchChannelsRouter = express.Router()
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ async function searchVideoChannelURI (search: string, isWebfingerSearch: boolean
|
||||||
logger.info('Cannot search remote video channel %s.', uri, { err })
|
logger.info('Cannot search remote video channel %s.', uri, { err })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
videoChannel = await VideoChannelModel.loadByUrlAndPopulateAccount(sanitizeLocalUrl(uri))
|
videoChannel = await searchLocalUrl(sanitizeLocalUrl(uri), url => VideoChannelModel.loadByUrlAndPopulateAccount(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
|
|
|
@ -24,6 +24,7 @@ import {
|
||||||
videoPlaylistsListSearchValidator,
|
videoPlaylistsListSearchValidator,
|
||||||
videoPlaylistsSearchSortValidator
|
videoPlaylistsSearchSortValidator
|
||||||
} from '../../../middlewares'
|
} from '../../../middlewares'
|
||||||
|
import { searchLocalUrl } from './shared'
|
||||||
|
|
||||||
const searchPlaylistsRouter = express.Router()
|
const searchPlaylistsRouter = express.Router()
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ async function searchVideoPlaylistsURI (search: string, res: express.Response) {
|
||||||
logger.info('Cannot search remote video playlist %s.', search, { err })
|
logger.info('Cannot search remote video playlist %s.', search, { err })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
videoPlaylist = await VideoPlaylistModel.loadByUrlWithAccountAndChannelSummary(sanitizeLocalUrl(search))
|
videoPlaylist = await searchLocalUrl(sanitizeLocalUrl(search), url => VideoPlaylistModel.loadByUrlWithAccountAndChannelSummary(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
} from '../../../middlewares'
|
} from '../../../middlewares'
|
||||||
import { VideoModel } from '../../../models/video/video'
|
import { VideoModel } from '../../../models/video/video'
|
||||||
import { MVideoAccountLightBlacklistAllFiles } from '../../../types/models'
|
import { MVideoAccountLightBlacklistAllFiles } from '../../../types/models'
|
||||||
|
import { searchLocalUrl } from './shared'
|
||||||
|
|
||||||
const searchVideosRouter = express.Router()
|
const searchVideosRouter = express.Router()
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ async function searchVideoURI (url: string, res: express.Response) {
|
||||||
logger.info('Cannot search remote video %s.', url, { err })
|
logger.info('Cannot search remote video %s.', url, { err })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
video = await VideoModel.loadByUrlAndPopulateAccount(sanitizeLocalUrl(url))
|
video = await searchLocalUrl(sanitizeLocalUrl(url), url => VideoModel.loadByUrlAndPopulateAccount(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
|
|
1
server/controllers/api/search/shared/index.ts
Normal file
1
server/controllers/api/search/shared/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './utils'
|
16
server/controllers/api/search/shared/utils.ts
Normal file
16
server/controllers/api/search/shared/utils.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
async function searchLocalUrl <T> (url: string, finder: (url: string) => Promise<T>) {
|
||||||
|
const data = await finder(url)
|
||||||
|
if (data) return data
|
||||||
|
|
||||||
|
return finder(removeQueryParams(url))
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
searchLocalUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function removeQueryParams (url: string) {
|
||||||
|
return url.split('?').shift()
|
||||||
|
}
|
|
@ -59,7 +59,7 @@ function getHostWithPort (host: string) {
|
||||||
return host
|
return host
|
||||||
}
|
}
|
||||||
|
|
||||||
function badRequest (req: express.Request, res: express.Response) {
|
function badRequest (_req: express.Request, res: express.Response) {
|
||||||
return res.type('json')
|
return res.type('json')
|
||||||
.status(HttpStatusCode.BAD_REQUEST_400)
|
.status(HttpStatusCode.BAD_REQUEST_400)
|
||||||
.end()
|
.end()
|
||||||
|
|
|
@ -20,7 +20,7 @@ async function getOrCreateAPVideoPlaylist (playlistObjectArg: APObject): Promise
|
||||||
const { playlistObject } = await fetchRemoteVideoPlaylist(playlistUrl)
|
const { playlistObject } = await fetchRemoteVideoPlaylist(playlistUrl)
|
||||||
if (!playlistObject) throw new Error('Cannot fetch remote playlist with url: ' + playlistUrl)
|
if (!playlistObject) throw new Error('Cannot fetch remote playlist with url: ' + playlistUrl)
|
||||||
|
|
||||||
// playlistUrl is just an alias/rediraction, so process object id instead
|
// playlistUrl is just an alias/redirection, so process object id instead
|
||||||
if (playlistObject.id !== playlistUrl) return getOrCreateAPVideoPlaylist(playlistObject)
|
if (playlistObject.id !== playlistUrl) return getOrCreateAPVideoPlaylist(playlistObject)
|
||||||
|
|
||||||
const playlistCreated = await createOrUpdateVideoPlaylist(playlistObject)
|
const playlistCreated = await createOrUpdateVideoPlaylist(playlistObject)
|
||||||
|
|
|
@ -64,7 +64,7 @@ describe('Test ActivityPub video channels search', function () {
|
||||||
this.timeout(15000)
|
this.timeout(15000)
|
||||||
|
|
||||||
{
|
{
|
||||||
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server3'
|
const search = servers[1].url + '/video-channels/channel1_server3'
|
||||||
const body = await command.searchChannels({ search, token: servers[0].accessToken })
|
const body = await command.searchChannels({ search, token: servers[0].accessToken })
|
||||||
|
|
||||||
expect(body.total).to.equal(0)
|
expect(body.total).to.equal(0)
|
||||||
|
@ -74,7 +74,7 @@ describe('Test ActivityPub video channels search', function () {
|
||||||
|
|
||||||
{
|
{
|
||||||
// Without token
|
// Without token
|
||||||
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server2'
|
const search = servers[1].url + '/video-channels/channel1_server2'
|
||||||
const body = await command.searchChannels({ search })
|
const body = await command.searchChannels({ search })
|
||||||
|
|
||||||
expect(body.total).to.equal(0)
|
expect(body.total).to.equal(0)
|
||||||
|
@ -85,7 +85,7 @@ describe('Test ActivityPub video channels search', function () {
|
||||||
|
|
||||||
it('Should search a local video channel', async function () {
|
it('Should search a local video channel', async function () {
|
||||||
const searches = [
|
const searches = [
|
||||||
'http://localhost:' + servers[0].port + '/video-channels/channel1_server1',
|
servers[0].url + '/video-channels/channel1_server1',
|
||||||
'channel1_server1@localhost:' + servers[0].port
|
'channel1_server1@localhost:' + servers[0].port
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ describe('Test ActivityPub video channels search', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should search a local video channel with an alternative URL', async function () {
|
it('Should search a local video channel with an alternative URL', async function () {
|
||||||
const search = 'http://localhost:' + servers[0].port + '/c/channel1_server1'
|
const search = servers[0].url + '/c/channel1_server1'
|
||||||
|
|
||||||
for (const token of [ undefined, servers[0].accessToken ]) {
|
for (const token of [ undefined, servers[0].accessToken ]) {
|
||||||
const body = await command.searchChannels({ search, token })
|
const body = await command.searchChannels({ search, token })
|
||||||
|
@ -114,11 +114,30 @@ describe('Test ActivityPub video channels search', function () {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should search a local video channel with a query in URL', async function () {
|
||||||
|
const searches = [
|
||||||
|
servers[0].url + '/video-channels/channel1_server1',
|
||||||
|
servers[0].url + '/c/channel1_server1'
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const search of searches) {
|
||||||
|
for (const token of [ undefined, servers[0].accessToken ]) {
|
||||||
|
const body = await command.searchChannels({ search: search + '?param=2', token })
|
||||||
|
|
||||||
|
expect(body.total).to.equal(1)
|
||||||
|
expect(body.data).to.be.an('array')
|
||||||
|
expect(body.data).to.have.lengthOf(1)
|
||||||
|
expect(body.data[0].name).to.equal('channel1_server1')
|
||||||
|
expect(body.data[0].displayName).to.equal('Channel 1 server 1')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('Should search a remote video channel with URL or handle', async function () {
|
it('Should search a remote video channel with URL or handle', async function () {
|
||||||
const searches = [
|
const searches = [
|
||||||
'http://localhost:' + servers[1].port + '/video-channels/channel1_server2',
|
servers[1].url + '/video-channels/channel1_server2',
|
||||||
'http://localhost:' + servers[1].port + '/c/channel1_server2',
|
servers[1].url + '/c/channel1_server2',
|
||||||
'http://localhost:' + servers[1].port + '/c/channel1_server2/videos',
|
servers[1].url + '/c/channel1_server2/videos',
|
||||||
'channel1_server2@localhost:' + servers[1].port
|
'channel1_server2@localhost:' + servers[1].port
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -178,7 +197,7 @@ describe('Test ActivityPub video channels search', function () {
|
||||||
// Expire video channel
|
// Expire video channel
|
||||||
await wait(10000)
|
await wait(10000)
|
||||||
|
|
||||||
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server2'
|
const search = servers[1].url + '/video-channels/channel1_server2'
|
||||||
const body = await command.searchChannels({ search, token: servers[0].accessToken })
|
const body = await command.searchChannels({ search, token: servers[0].accessToken })
|
||||||
expect(body.total).to.equal(1)
|
expect(body.total).to.equal(1)
|
||||||
expect(body.data).to.have.lengthOf(1)
|
expect(body.data).to.have.lengthOf(1)
|
||||||
|
@ -201,7 +220,7 @@ describe('Test ActivityPub video channels search', function () {
|
||||||
// Expire video channel
|
// Expire video channel
|
||||||
await wait(10000)
|
await wait(10000)
|
||||||
|
|
||||||
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server2'
|
const search = servers[1].url + '/video-channels/channel1_server2'
|
||||||
await command.searchChannels({ search, token: servers[0].accessToken })
|
await command.searchChannels({ search, token: servers[0].accessToken })
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
@ -223,7 +242,7 @@ describe('Test ActivityPub video channels search', function () {
|
||||||
// Expire video
|
// Expire video
|
||||||
await wait(10000)
|
await wait(10000)
|
||||||
|
|
||||||
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server2'
|
const search = servers[1].url + '/video-channels/channel1_server2'
|
||||||
const body = await command.searchChannels({ search, token: servers[0].accessToken })
|
const body = await command.searchChannels({ search, token: servers[0].accessToken })
|
||||||
expect(body.total).to.equal(0)
|
expect(body.total).to.equal(0)
|
||||||
expect(body.data).to.have.lengthOf(0)
|
expect(body.data).to.have.lengthOf(0)
|
||||||
|
|
|
@ -71,7 +71,7 @@ describe('Test ActivityPub playlists search', function () {
|
||||||
|
|
||||||
it('Should not find a remote playlist', async function () {
|
it('Should not find a remote playlist', async function () {
|
||||||
{
|
{
|
||||||
const search = 'http://localhost:' + servers[1].port + '/video-playlists/43'
|
const search = servers[1].url + '/video-playlists/43'
|
||||||
const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
|
const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
|
||||||
|
|
||||||
expect(body.total).to.equal(0)
|
expect(body.total).to.equal(0)
|
||||||
|
@ -81,7 +81,7 @@ describe('Test ActivityPub playlists search', function () {
|
||||||
|
|
||||||
{
|
{
|
||||||
// Without token
|
// Without token
|
||||||
const search = 'http://localhost:' + servers[1].port + '/video-playlists/' + playlistServer2UUID
|
const search = servers[1].url + '/video-playlists/' + playlistServer2UUID
|
||||||
const body = await command.searchPlaylists({ search })
|
const body = await command.searchPlaylists({ search })
|
||||||
|
|
||||||
expect(body.total).to.equal(0)
|
expect(body.total).to.equal(0)
|
||||||
|
@ -91,7 +91,7 @@ describe('Test ActivityPub playlists search', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should search a local playlist', async function () {
|
it('Should search a local playlist', async function () {
|
||||||
const search = 'http://localhost:' + servers[0].port + '/video-playlists/' + playlistServer1UUID
|
const search = servers[0].url + '/video-playlists/' + playlistServer1UUID
|
||||||
const body = await command.searchPlaylists({ search })
|
const body = await command.searchPlaylists({ search })
|
||||||
|
|
||||||
expect(body.total).to.equal(1)
|
expect(body.total).to.equal(1)
|
||||||
|
@ -103,8 +103,8 @@ describe('Test ActivityPub playlists search', function () {
|
||||||
|
|
||||||
it('Should search a local playlist with an alternative URL', async function () {
|
it('Should search a local playlist with an alternative URL', async function () {
|
||||||
const searches = [
|
const searches = [
|
||||||
'http://localhost:' + servers[0].port + '/videos/watch/playlist/' + playlistServer1UUID,
|
servers[0].url + '/videos/watch/playlist/' + playlistServer1UUID,
|
||||||
'http://localhost:' + servers[0].port + '/w/p/' + playlistServer1UUID
|
servers[0].url + '/w/p/' + playlistServer1UUID
|
||||||
]
|
]
|
||||||
|
|
||||||
for (const search of searches) {
|
for (const search of searches) {
|
||||||
|
@ -120,11 +120,30 @@ describe('Test ActivityPub playlists search', function () {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should search a local playlist with a query in URL', async function () {
|
||||||
|
const searches = [
|
||||||
|
servers[0].url + '/videos/watch/playlist/' + playlistServer1UUID,
|
||||||
|
servers[0].url + '/w/p/' + playlistServer1UUID
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const search of searches) {
|
||||||
|
for (const token of [ undefined, servers[0].accessToken ]) {
|
||||||
|
const body = await command.searchPlaylists({ search: search + '?param=1', token })
|
||||||
|
|
||||||
|
expect(body.total).to.equal(1)
|
||||||
|
expect(body.data).to.be.an('array')
|
||||||
|
expect(body.data).to.have.lengthOf(1)
|
||||||
|
expect(body.data[0].displayName).to.equal('playlist 1 on server 1')
|
||||||
|
expect(body.data[0].videosLength).to.equal(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('Should search a remote playlist', async function () {
|
it('Should search a remote playlist', async function () {
|
||||||
const searches = [
|
const searches = [
|
||||||
'http://localhost:' + servers[1].port + '/video-playlists/' + playlistServer2UUID,
|
servers[1].url + '/video-playlists/' + playlistServer2UUID,
|
||||||
'http://localhost:' + servers[1].port + '/videos/watch/playlist/' + playlistServer2UUID,
|
servers[1].url + '/videos/watch/playlist/' + playlistServer2UUID,
|
||||||
'http://localhost:' + servers[1].port + '/w/p/' + playlistServer2UUID
|
servers[1].url + '/w/p/' + playlistServer2UUID
|
||||||
]
|
]
|
||||||
|
|
||||||
for (const search of searches) {
|
for (const search of searches) {
|
||||||
|
@ -155,7 +174,7 @@ describe('Test ActivityPub playlists search', function () {
|
||||||
await wait(10000)
|
await wait(10000)
|
||||||
|
|
||||||
// Will run refresh async
|
// Will run refresh async
|
||||||
const search = 'http://localhost:' + servers[1].port + '/video-playlists/' + playlistServer2UUID
|
const search = servers[1].url + '/video-playlists/' + playlistServer2UUID
|
||||||
await command.searchPlaylists({ search, token: servers[0].accessToken })
|
await command.searchPlaylists({ search, token: servers[0].accessToken })
|
||||||
|
|
||||||
// Wait refresh
|
// Wait refresh
|
||||||
|
@ -179,7 +198,7 @@ describe('Test ActivityPub playlists search', function () {
|
||||||
await wait(10000)
|
await wait(10000)
|
||||||
|
|
||||||
// Will run refresh async
|
// Will run refresh async
|
||||||
const search = 'http://localhost:' + servers[1].port + '/video-playlists/' + playlistServer2UUID
|
const search = servers[1].url + '/video-playlists/' + playlistServer2UUID
|
||||||
await command.searchPlaylists({ search, token: servers[0].accessToken })
|
await command.searchPlaylists({ search, token: servers[0].accessToken })
|
||||||
|
|
||||||
// Wait refresh
|
// Wait refresh
|
||||||
|
|
|
@ -46,7 +46,7 @@ describe('Test ActivityPub videos search', function () {
|
||||||
|
|
||||||
it('Should not find a remote video', async function () {
|
it('Should not find a remote video', async function () {
|
||||||
{
|
{
|
||||||
const search = 'http://localhost:' + servers[1].port + '/videos/watch/43'
|
const search = servers[1].url + '/videos/watch/43'
|
||||||
const body = await command.searchVideos({ search, token: servers[0].accessToken })
|
const body = await command.searchVideos({ search, token: servers[0].accessToken })
|
||||||
|
|
||||||
expect(body.total).to.equal(0)
|
expect(body.total).to.equal(0)
|
||||||
|
@ -56,7 +56,7 @@ describe('Test ActivityPub videos search', function () {
|
||||||
|
|
||||||
{
|
{
|
||||||
// Without token
|
// Without token
|
||||||
const search = 'http://localhost:' + servers[1].port + '/videos/watch/' + videoServer2UUID
|
const search = servers[1].url + '/videos/watch/' + videoServer2UUID
|
||||||
const body = await command.searchVideos({ search })
|
const body = await command.searchVideos({ search })
|
||||||
|
|
||||||
expect(body.total).to.equal(0)
|
expect(body.total).to.equal(0)
|
||||||
|
@ -66,7 +66,7 @@ describe('Test ActivityPub videos search', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should search a local video', async function () {
|
it('Should search a local video', async function () {
|
||||||
const search = 'http://localhost:' + servers[0].port + '/videos/watch/' + videoServer1UUID
|
const search = servers[0].url + '/videos/watch/' + videoServer1UUID
|
||||||
const body = await command.searchVideos({ search })
|
const body = await command.searchVideos({ search })
|
||||||
|
|
||||||
expect(body.total).to.equal(1)
|
expect(body.total).to.equal(1)
|
||||||
|
@ -76,7 +76,7 @@ describe('Test ActivityPub videos search', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should search a local video with an alternative URL', async function () {
|
it('Should search a local video with an alternative URL', async function () {
|
||||||
const search = 'http://localhost:' + servers[0].port + '/w/' + videoServer1UUID
|
const search = servers[0].url + '/w/' + videoServer1UUID
|
||||||
const body1 = await command.searchVideos({ search })
|
const body1 = await command.searchVideos({ search })
|
||||||
const body2 = await command.searchVideos({ search, token: servers[0].accessToken })
|
const body2 = await command.searchVideos({ search, token: servers[0].accessToken })
|
||||||
|
|
||||||
|
@ -88,10 +88,28 @@ describe('Test ActivityPub videos search', function () {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should search a local video with a query in URL', async function () {
|
||||||
|
const searches = [
|
||||||
|
servers[0].url + '/w/' + videoServer1UUID,
|
||||||
|
servers[0].url + '/videos/watch/' + videoServer1UUID
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const search of searches) {
|
||||||
|
for (const token of [ undefined, servers[0].accessToken ]) {
|
||||||
|
const body = await command.searchVideos({ search: search + '?startTime=4', token })
|
||||||
|
|
||||||
|
expect(body.total).to.equal(1)
|
||||||
|
expect(body.data).to.be.an('array')
|
||||||
|
expect(body.data).to.have.lengthOf(1)
|
||||||
|
expect(body.data[0].name).to.equal('video 1 on server 1')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('Should search a remote video', async function () {
|
it('Should search a remote video', async function () {
|
||||||
const searches = [
|
const searches = [
|
||||||
'http://localhost:' + servers[1].port + '/w/' + videoServer2UUID,
|
servers[1].url + '/w/' + videoServer2UUID,
|
||||||
'http://localhost:' + servers[1].port + '/videos/watch/' + videoServer2UUID
|
servers[1].url + '/videos/watch/' + videoServer2UUID
|
||||||
]
|
]
|
||||||
|
|
||||||
for (const search of searches) {
|
for (const search of searches) {
|
||||||
|
@ -134,7 +152,7 @@ describe('Test ActivityPub videos search', function () {
|
||||||
await wait(10000)
|
await wait(10000)
|
||||||
|
|
||||||
// Will run refresh async
|
// Will run refresh async
|
||||||
const search = 'http://localhost:' + servers[1].port + '/videos/watch/' + videoServer2UUID
|
const search = servers[1].url + '/videos/watch/' + videoServer2UUID
|
||||||
await command.searchVideos({ search, token: servers[0].accessToken })
|
await command.searchVideos({ search, token: servers[0].accessToken })
|
||||||
|
|
||||||
// Wait refresh
|
// Wait refresh
|
||||||
|
@ -160,7 +178,7 @@ describe('Test ActivityPub videos search', function () {
|
||||||
await wait(10000)
|
await wait(10000)
|
||||||
|
|
||||||
// Will run refresh async
|
// Will run refresh async
|
||||||
const search = 'http://localhost:' + servers[1].port + '/videos/watch/' + videoServer2UUID
|
const search = servers[1].url + '/videos/watch/' + videoServer2UUID
|
||||||
await command.searchVideos({ search, token: servers[0].accessToken })
|
await command.searchVideos({ search, token: servers[0].accessToken })
|
||||||
|
|
||||||
// Wait refresh
|
// Wait refresh
|
||||||
|
|
Loading…
Reference in a new issue