3 var async = require('async')
4 var config = require('config')
6 var request = require('request')
8 var constants = require('../initializers/constants')
9 var logger = require('../helpers/logger')
10 var peertubeCrypto = require('../helpers/peertubeCrypto')
11 var Pods = require('../models/pods')
12 var poolRequests = require('../lib/poolRequests')
13 var requests = require('../helpers/requests')
14 var Videos = require('../models/videos')
16 var http = config.get('webserver.https') ? 'https' : 'http'
17 var host = config.get('webserver.host')
18 var port = config.get('webserver.port')
21 addVideoToFriends: addVideoToFriends,
22 hasFriends: hasFriends,
23 makeFriends: makeFriends,
24 quitFriends: quitFriends,
25 removeVideoToFriends: removeVideoToFriends
28 function addVideoToFriends (video) {
29 // To avoid duplicates
30 var id = video.name + video.magnetUri
31 // ensure namePath is null
33 poolRequests.addRequest(id, 'add', video)
36 function hasFriends (callback) {
37 Pods.count(function (err, count) {
38 if (err) return callback(err)
40 var has_friends = (count !== 0)
41 callback(null, has_friends)
45 function makeFriends (callback) {
48 logger.info('Make friends!')
49 fs.readFile(peertubeCrypto.getCertDir() + 'peertube.pub', 'utf8', function (err, cert) {
51 logger.error('Cannot read public cert.')
55 var urls = config.get('network.friends')
57 async.each(urls, computeForeignPodsList, function (err) {
58 if (err) return callback(err)
60 logger.debug('Pods scores computed.', { pods_score: pods_score })
61 var pods_list = computeWinningPods(urls, pods_score)
62 logger.debug('Pods that we keep computed.', { pods_to_keep: pods_list })
64 makeRequestsToWinningPods(cert, pods_list)
68 // -----------------------------------------------------------------------
70 function computeForeignPodsList (url, callback) {
71 // Let's give 1 point to the pod we ask the friends list
74 getForeignPodsList(url, function (err, foreign_pods_list) {
75 if (err) return callback(err)
76 if (foreign_pods_list.length === 0) return callback()
78 async.each(foreign_pods_list, function (foreign_pod, callback_each) {
79 var foreign_url = foreign_pod.url
81 if (pods_score[foreign_url]) pods_score[foreign_url]++
82 else pods_score[foreign_url] = 1
91 function computeWinningPods (urls, pods_score) {
92 // Build the list of pods to add
93 // Only add a pod if it exists in more than a half base pods
95 var base_score = urls.length / 2
96 Object.keys(pods_score).forEach(function (pod) {
97 if (pods_score[pod] > base_score) pods_list.push({ url: pod })
103 function makeRequestsToWinningPods (cert, pods_list) {
104 // Stop pool requests
105 poolRequests.deactivate()
106 // Flush pool requests
107 poolRequests.forceSend()
109 // Get the list of our videos to send to our new friends
110 Videos.listOwned(function (err, videos_list) {
112 logger.error('Cannot get the list of videos we own.')
117 url: http + '://' + host + ':' + port,
122 requests.makeMultipleRetryRequest(
123 { method: 'POST', path: '/api/' + constants.API_VERSION + '/pods/', data: data },
127 function eachRequest (err, response, body, url, pod, callback_each_request) {
128 // We add the pod if it responded correctly with its public certificate
129 if (!err && response.statusCode === 200) {
130 Pods.add({ url: pod.url, publicKey: body.cert, score: constants.FRIEND_BASE_SCORE }, function (err) {
131 if (err) logger.error('Error with adding %s pod.', pod.url, { error: err })
133 Videos.addRemotes(body.videos, function (err) {
134 if (err) logger.error('Error with adding videos of pod.', pod.url, { error: err })
136 logger.debug('Adding remote videos from %s.', pod.url, { videos: body.videos })
137 return callback_each_request()
141 logger.error('Error with adding %s pod.', pod.url, { error: err || new Error('Status not 200') })
142 return callback_each_request()
146 function endRequests (err) {
147 // Now we made new friends, we can re activate the pool of requests
148 poolRequests.activate()
151 logger.error('There was some errors when we wanted to make friends.')
155 logger.debug('makeRequestsToWinningPods finished.')
156 return callback(null)
163 function quitFriends (callback) {
164 // Stop pool requests
165 poolRequests.deactivate()
166 // Flush pool requests
167 poolRequests.forceSend()
169 Pods.list(function (err, pods) {
170 if (err) return callback(err)
174 path: '/api/' + constants.API_VERSION + '/pods/remove',
178 url: 'me' // Fake data
182 // Announce we quit them
183 requests.makeMultipleRetryRequest(request, pods, function () {
184 Pods.removeAll(function (err) {
185 poolRequests.activate()
187 if (err) return callback(err)
189 logger.info('Broke friends, so sad :(')
191 Videos.removeAllRemotes(function (err) {
192 if (err) return callback(err)
194 logger.info('Removed all remote videos.')
202 function removeVideoToFriends (video) {
203 // To avoid duplicates
204 var id = video.name + video.magnetUri
205 poolRequests.addRequest(id, 'remove', video)
208 // ---------------------------------------------------------------------------
210 module.exports = pods
212 // ---------------------------------------------------------------------------
214 function getForeignPodsList (url, callback) {
215 var path = '/api/' + constants.API_VERSION + '/pods'
217 request.get(url + path, function (err, response, body) {
218 if (err) return callback(err)
220 callback(null, JSON.parse(body))