Initial LBRY First To Allow publishing to youtube channels.
moar
This commit is contained in:
parent
85f0f574bd
commit
67d8540ccc
8 changed files with 577 additions and 5 deletions
|
@ -12,4 +12,5 @@ module.name_mapper='^redux\(.*\)$' -> '<PROJECT_ROOT>/src/redux\1'
|
||||||
module.name_mapper='^util\(.*\)$' -> '<PROJECT_ROOT>/src/util\1'
|
module.name_mapper='^util\(.*\)$' -> '<PROJECT_ROOT>/src/util\1'
|
||||||
module.name_mapper='^constants\(.*\)$' -> '<PROJECT_ROOT>/src/constants\1'
|
module.name_mapper='^constants\(.*\)$' -> '<PROJECT_ROOT>/src/constants\1'
|
||||||
module.name_mapper='^lbry\(.*\)$' -> '<PROJECT_ROOT>/src/lbry\1'
|
module.name_mapper='^lbry\(.*\)$' -> '<PROJECT_ROOT>/src/lbry\1'
|
||||||
|
module.name_mapper='^lbry-first\(.*\)$' -> '<PROJECT_ROOT>/src/lbry-first\1'
|
||||||
module.name_mapper='^lbryURI\(.*\)$' -> '<PROJECT_ROOT>/src/lbryURI\1'
|
module.name_mapper='^lbryURI\(.*\)$' -> '<PROJECT_ROOT>/src/lbryURI\1'
|
||||||
|
|
183
dist/bundle.es.js
vendored
183
dist/bundle.es.js
vendored
|
@ -1217,6 +1217,174 @@ const lbryProxy = new Proxy(Lbry, {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const CHECK_LBRYFIRST_STARTED_TRY_NUMBER = 200;
|
||||||
|
//
|
||||||
|
// Basic LBRYFIRST connection config
|
||||||
|
// Offers a proxy to call LBRYFIRST methods
|
||||||
|
|
||||||
|
//
|
||||||
|
const LbryFirst = {
|
||||||
|
isConnected: false,
|
||||||
|
connectPromise: null,
|
||||||
|
lbryFirstConnectionString: 'http://localhost:1337/rpc',
|
||||||
|
apiRequestHeaders: { 'Content-Type': 'application/json' },
|
||||||
|
|
||||||
|
// Allow overriding lbryFirst connection string (e.g. to `/api/proxy` for lbryweb)
|
||||||
|
setLbryFirstConnectionString: value => {
|
||||||
|
LbryFirst.lbryFirstConnectionString = value;
|
||||||
|
},
|
||||||
|
|
||||||
|
setApiHeader: (key, value) => {
|
||||||
|
LbryFirst.apiRequestHeaders = Object.assign(LbryFirst.apiRequestHeaders, { [key]: value });
|
||||||
|
},
|
||||||
|
|
||||||
|
unsetApiHeader: key => {
|
||||||
|
Object.keys(LbryFirst.apiRequestHeaders).includes(key) && delete LbryFirst.apiRequestHeaders['key'];
|
||||||
|
},
|
||||||
|
// Allow overriding Lbry methods
|
||||||
|
overrides: {},
|
||||||
|
setOverride: (methodName, newMethod) => {
|
||||||
|
LbryFirst.overrides[methodName] = newMethod;
|
||||||
|
},
|
||||||
|
getApiRequestHeaders: () => LbryFirst.apiRequestHeaders,
|
||||||
|
|
||||||
|
//
|
||||||
|
// LbryFirst Methods
|
||||||
|
//
|
||||||
|
status: (params = {}) => lbryFirstCallWithResult('server.Status', params),
|
||||||
|
stop: () => lbryFirstCallWithResult('stop', {}),
|
||||||
|
version: () => lbryFirstCallWithResult('version', {}),
|
||||||
|
|
||||||
|
// Upload to youtube
|
||||||
|
upload: (params = {}) => {
|
||||||
|
// Only upload when originally publishing for now
|
||||||
|
if (!params.file_path) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const uploadParams = {};
|
||||||
|
uploadParams.Title = params.title;
|
||||||
|
uploadParams.Description = params.description;
|
||||||
|
uploadParams.FilePath = params.file_path;
|
||||||
|
uploadParams.Category = '';
|
||||||
|
uploadParams.ThumbnailURL = params.thumbnail_url;
|
||||||
|
uploadParams.Keywords = params.tags.join(',');
|
||||||
|
// Needs to be configurable?
|
||||||
|
uploadParams.PublishType = 'private';
|
||||||
|
uploadParams.PublishAt = ''; // Premiere Date
|
||||||
|
uploadParams.MonetizationOff = false;
|
||||||
|
uploadParams.ClaimName = params.name;
|
||||||
|
uploadParams.URI = params.permanent_url;
|
||||||
|
return lbryFirstCallWithResult('youtube.Upload', uploadParams);
|
||||||
|
},
|
||||||
|
|
||||||
|
hasYTAuth: token => {
|
||||||
|
const hasYTAuthParams = {};
|
||||||
|
hasYTAuthParams.AuthToken = token;
|
||||||
|
return lbryFirstCallWithResult('youtube.HasAuth', hasYTAuthParams);
|
||||||
|
},
|
||||||
|
|
||||||
|
ytSignup: () => {
|
||||||
|
const emptyParams = {};
|
||||||
|
return lbryFirstCallWithResult('youtube.Signup', emptyParams);
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: () => {
|
||||||
|
const emptyParams = {};
|
||||||
|
return lbryFirstCallWithResult('youtube.Remove', emptyParams);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Connect to lbry-first
|
||||||
|
connect: () => {
|
||||||
|
if (LbryFirst.connectPromise === null) {
|
||||||
|
LbryFirst.connectPromise = new Promise((resolve, reject) => {
|
||||||
|
let tryNum = 0;
|
||||||
|
// Check every half second to see if the lbryFirst is accepting connections
|
||||||
|
function checkLbryFirstStarted() {
|
||||||
|
tryNum += 1;
|
||||||
|
LbryFirst.status().then(resolve).catch(() => {
|
||||||
|
if (tryNum <= CHECK_LBRYFIRST_STARTED_TRY_NUMBER) {
|
||||||
|
setTimeout(checkLbryFirstStarted, tryNum < 50 ? 400 : 1000);
|
||||||
|
} else {
|
||||||
|
reject(new Error('Unable to connect to LBRY'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkLbryFirstStarted();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flow thinks this could be empty, but it will always return a promise
|
||||||
|
// $FlowFixMe
|
||||||
|
return LbryFirst.connectPromise;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function checkAndParse$1(response) {
|
||||||
|
if (response.status >= 200 && response.status < 300) {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
return response.json().then(json => {
|
||||||
|
let error;
|
||||||
|
if (json.error) {
|
||||||
|
const errorMessage = typeof json.error === 'object' ? json.error.message : json.error;
|
||||||
|
error = new Error(errorMessage);
|
||||||
|
} else {
|
||||||
|
error = new Error('Protocol error with unknown response signature');
|
||||||
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function apiCall$1(method, params, resolve, reject) {
|
||||||
|
const counter = new Date().getTime();
|
||||||
|
params = [params];
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
headers: LbryFirst.apiRequestHeaders,
|
||||||
|
body: JSON.stringify({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
id: counter
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
return fetch(LbryFirst.lbryFirstConnectionString, options).then(checkAndParse$1).then(response => {
|
||||||
|
const error = response.error || response.result && response.result.error;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return reject(error);
|
||||||
|
}
|
||||||
|
return resolve(response.result);
|
||||||
|
}).catch(reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
function lbryFirstCallWithResult(name, params = {}) {
|
||||||
|
console.log(`LbryFirst: calling ${name}`);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
apiCall$1(name, params, result => {
|
||||||
|
resolve(result);
|
||||||
|
}, reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is only for a fallback
|
||||||
|
// If there is a LbryFirst method that is being called by an app, it should be added to /flow-typed/LbryFirst.js
|
||||||
|
const lbryFirstProxy = new Proxy(LbryFirst, {
|
||||||
|
get(target, name) {
|
||||||
|
if (name in target) {
|
||||||
|
return target[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (params = {}) => new Promise((resolve, reject) => {
|
||||||
|
apiCall$1(name, params, resolve, reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
const DEFAULT_SEARCH_RESULT_FROM = 0;
|
const DEFAULT_SEARCH_RESULT_FROM = 0;
|
||||||
const DEFAULT_SEARCH_SIZE = 20;
|
const DEFAULT_SEARCH_SIZE = 20;
|
||||||
|
|
||||||
|
@ -4462,6 +4630,7 @@ const doPublish = (success, fail) => (dispatch, getState) => {
|
||||||
language,
|
language,
|
||||||
license,
|
license,
|
||||||
licenseUrl,
|
licenseUrl,
|
||||||
|
useLBRYUploader,
|
||||||
licenseType,
|
licenseType,
|
||||||
otherLicenseDescription,
|
otherLicenseDescription,
|
||||||
thumbnail,
|
thumbnail,
|
||||||
|
@ -4547,8 +4716,14 @@ const doPublish = (success, fail) => (dispatch, getState) => {
|
||||||
// Only pass file on new uploads, not metadata only edits.
|
// Only pass file on new uploads, not metadata only edits.
|
||||||
// The sdk will figure it out
|
// The sdk will figure it out
|
||||||
if (filePath) publishPayload.file_path = filePath;
|
if (filePath) publishPayload.file_path = filePath;
|
||||||
|
// if (useLBRYUploader) return LbryFirst.upload(publishPayload);
|
||||||
return lbryProxy.publish(publishPayload).then(success, fail);
|
return lbryProxy.publish(publishPayload).then(response => {
|
||||||
|
if (!useLBRYUploader) {
|
||||||
|
return success(response);
|
||||||
|
}
|
||||||
|
publishPayload.permanent_url = response.outputs[0].permanent_url;
|
||||||
|
return lbryFirstProxy.upload(publishPayload).then(success(response), fail);
|
||||||
|
}, fail);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calls file_list until any reflecting files are done
|
// Calls file_list until any reflecting files are done
|
||||||
|
@ -6215,7 +6390,8 @@ const defaultState$5 = {
|
||||||
publishing: false,
|
publishing: false,
|
||||||
publishSuccess: false,
|
publishSuccess: false,
|
||||||
publishError: undefined,
|
publishError: undefined,
|
||||||
optimize: false
|
optimize: false,
|
||||||
|
useLBRYUploader: false
|
||||||
};
|
};
|
||||||
|
|
||||||
const publishReducer = handleActions({
|
const publishReducer = handleActions({
|
||||||
|
@ -6938,6 +7114,7 @@ exports.DEFAULT_FOLLOWED_TAGS = DEFAULT_FOLLOWED_TAGS;
|
||||||
exports.DEFAULT_KNOWN_TAGS = DEFAULT_KNOWN_TAGS;
|
exports.DEFAULT_KNOWN_TAGS = DEFAULT_KNOWN_TAGS;
|
||||||
exports.LICENSES = licenses;
|
exports.LICENSES = licenses;
|
||||||
exports.Lbry = lbryProxy;
|
exports.Lbry = lbryProxy;
|
||||||
|
exports.LbryFirst = lbryFirstProxy;
|
||||||
exports.MATURE_TAGS = MATURE_TAGS;
|
exports.MATURE_TAGS = MATURE_TAGS;
|
||||||
exports.PAGES = pages;
|
exports.PAGES = pages;
|
||||||
exports.SEARCH_OPTIONS = SEARCH_OPTIONS;
|
exports.SEARCH_OPTIONS = SEARCH_OPTIONS;
|
||||||
|
|
100
dist/flow-typed/LbryFirst.js
vendored
Normal file
100
dist/flow-typed/LbryFirst.js
vendored
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// @flow
|
||||||
|
declare type StatusResponse = {
|
||||||
|
Version: string,
|
||||||
|
Message: string,
|
||||||
|
Running: boolean,
|
||||||
|
Commit: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type VersionResponse = {
|
||||||
|
build: string,
|
||||||
|
lbrynet_version: string,
|
||||||
|
os_release: string,
|
||||||
|
os_system: string,
|
||||||
|
platform: string,
|
||||||
|
processor: string,
|
||||||
|
python_version: string,
|
||||||
|
};
|
||||||
|
/* SAMPLE UPLOAD RESPONSE (FULL)
|
||||||
|
"Video": {
|
||||||
|
"etag": "\"Dn5xIderbhAnUk5TAW0qkFFir0M/xlGLrlTox7VFTRcR8F77RbKtaU4\"",
|
||||||
|
"id": "8InjtdvVmwE",
|
||||||
|
"kind": "youtube#video",
|
||||||
|
"snippet": {
|
||||||
|
"categoryId": "22",
|
||||||
|
"channelId": "UCXiVsGTU88fJjheB2rqF0rA",
|
||||||
|
"channelTitle": "Mark Beamer",
|
||||||
|
"liveBroadcastContent": "none",
|
||||||
|
"localized": {
|
||||||
|
"title": "my title"
|
||||||
|
},
|
||||||
|
"publishedAt": "2020-05-05T04:17:53.000Z",
|
||||||
|
"thumbnails": {
|
||||||
|
"default": {
|
||||||
|
"height": 90,
|
||||||
|
"url": "https://i9.ytimg.com/vi/8InjtdvVmwE/default.jpg?sqp=CMTQw_UF&rs=AOn4CLB6dlhZMSMrazDlWRsitPgCsn8fVw",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
"high": {
|
||||||
|
"height": 360,
|
||||||
|
"url": "https://i9.ytimg.com/vi/8InjtdvVmwE/hqdefault.jpg?sqp=CMTQw_UF&rs=AOn4CLB-Je_7l6qvASRAR_bSGWZHaXaJWQ",
|
||||||
|
"width": 480
|
||||||
|
},
|
||||||
|
"medium": {
|
||||||
|
"height": 180,
|
||||||
|
"url": "https://i9.ytimg.com/vi/8InjtdvVmwE/mqdefault.jpg?sqp=CMTQw_UF&rs=AOn4CLCvSnDLqVznRNMKuvJ_0misY_chPQ",
|
||||||
|
"width": 320
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "my title"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"embeddable": true,
|
||||||
|
"license": "youtube",
|
||||||
|
"privacyStatus": "private",
|
||||||
|
"publicStatsViewable": true,
|
||||||
|
"uploadStatus": "uploaded"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
declare type UploadResponse = {
|
||||||
|
Video: {
|
||||||
|
id: string,
|
||||||
|
snippet: {
|
||||||
|
channelId: string,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
uploadStatus: string,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type HasYTAuthResponse = {
|
||||||
|
HashAuth: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
declare type YTSignupResponse = {}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Types used in the generic LbryFirst object that is exported
|
||||||
|
//
|
||||||
|
declare type LbryFirstTypes = {
|
||||||
|
isConnected: boolean,
|
||||||
|
connectPromise: ?Promise<any>,
|
||||||
|
connect: () => void,
|
||||||
|
lbryFirstConnectionString: string,
|
||||||
|
apiRequestHeaders: { [key: string]: string },
|
||||||
|
setApiHeader: (string, string) => void,
|
||||||
|
unsetApiHeader: string => void,
|
||||||
|
overrides: { [string]: ?Function },
|
||||||
|
setOverride: (string, Function) => void,
|
||||||
|
|
||||||
|
// LbryFirst Methods
|
||||||
|
stop: () => Promise<string>,
|
||||||
|
status: () => Promise<StatusResponse>,
|
||||||
|
version: () => Promise<VersionResponse>,
|
||||||
|
upload: (params: {}) => Promise<UploadResponse>,
|
||||||
|
hasYTAuth: () =>Promise<HasYTAuthResponse>,
|
||||||
|
ytSignup: () =>Promise<YTSignupResponse>,
|
||||||
|
remove: () =>void,
|
||||||
|
};
|
100
flow-typed/LbryFirst.js
vendored
Normal file
100
flow-typed/LbryFirst.js
vendored
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// @flow
|
||||||
|
declare type StatusResponse = {
|
||||||
|
Version: string,
|
||||||
|
Message: string,
|
||||||
|
Running: boolean,
|
||||||
|
Commit: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type VersionResponse = {
|
||||||
|
build: string,
|
||||||
|
lbrynet_version: string,
|
||||||
|
os_release: string,
|
||||||
|
os_system: string,
|
||||||
|
platform: string,
|
||||||
|
processor: string,
|
||||||
|
python_version: string,
|
||||||
|
};
|
||||||
|
/* SAMPLE UPLOAD RESPONSE (FULL)
|
||||||
|
"Video": {
|
||||||
|
"etag": "\"Dn5xIderbhAnUk5TAW0qkFFir0M/xlGLrlTox7VFTRcR8F77RbKtaU4\"",
|
||||||
|
"id": "8InjtdvVmwE",
|
||||||
|
"kind": "youtube#video",
|
||||||
|
"snippet": {
|
||||||
|
"categoryId": "22",
|
||||||
|
"channelId": "UCXiVsGTU88fJjheB2rqF0rA",
|
||||||
|
"channelTitle": "Mark Beamer",
|
||||||
|
"liveBroadcastContent": "none",
|
||||||
|
"localized": {
|
||||||
|
"title": "my title"
|
||||||
|
},
|
||||||
|
"publishedAt": "2020-05-05T04:17:53.000Z",
|
||||||
|
"thumbnails": {
|
||||||
|
"default": {
|
||||||
|
"height": 90,
|
||||||
|
"url": "https://i9.ytimg.com/vi/8InjtdvVmwE/default.jpg?sqp=CMTQw_UF&rs=AOn4CLB6dlhZMSMrazDlWRsitPgCsn8fVw",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
"high": {
|
||||||
|
"height": 360,
|
||||||
|
"url": "https://i9.ytimg.com/vi/8InjtdvVmwE/hqdefault.jpg?sqp=CMTQw_UF&rs=AOn4CLB-Je_7l6qvASRAR_bSGWZHaXaJWQ",
|
||||||
|
"width": 480
|
||||||
|
},
|
||||||
|
"medium": {
|
||||||
|
"height": 180,
|
||||||
|
"url": "https://i9.ytimg.com/vi/8InjtdvVmwE/mqdefault.jpg?sqp=CMTQw_UF&rs=AOn4CLCvSnDLqVznRNMKuvJ_0misY_chPQ",
|
||||||
|
"width": 320
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "my title"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"embeddable": true,
|
||||||
|
"license": "youtube",
|
||||||
|
"privacyStatus": "private",
|
||||||
|
"publicStatsViewable": true,
|
||||||
|
"uploadStatus": "uploaded"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
declare type UploadResponse = {
|
||||||
|
Video: {
|
||||||
|
id: string,
|
||||||
|
snippet: {
|
||||||
|
channelId: string,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
uploadStatus: string,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type HasYTAuthResponse = {
|
||||||
|
HashAuth: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
declare type YTSignupResponse = {}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Types used in the generic LbryFirst object that is exported
|
||||||
|
//
|
||||||
|
declare type LbryFirstTypes = {
|
||||||
|
isConnected: boolean,
|
||||||
|
connectPromise: ?Promise<any>,
|
||||||
|
connect: () => void,
|
||||||
|
lbryFirstConnectionString: string,
|
||||||
|
apiRequestHeaders: { [key: string]: string },
|
||||||
|
setApiHeader: (string, string) => void,
|
||||||
|
unsetApiHeader: string => void,
|
||||||
|
overrides: { [string]: ?Function },
|
||||||
|
setOverride: (string, Function) => void,
|
||||||
|
|
||||||
|
// LbryFirst Methods
|
||||||
|
stop: () => Promise<string>,
|
||||||
|
status: () => Promise<StatusResponse>,
|
||||||
|
version: () => Promise<VersionResponse>,
|
||||||
|
upload: (params: {}) => Promise<UploadResponse>,
|
||||||
|
hasYTAuth: () =>Promise<HasYTAuthResponse>,
|
||||||
|
ytSignup: () =>Promise<YTSignupResponse>,
|
||||||
|
remove: () =>void,
|
||||||
|
};
|
|
@ -15,6 +15,7 @@ import * as SHARED_PREFERENCES from 'constants/shared_preferences';
|
||||||
import { SEARCH_TYPES, SEARCH_OPTIONS } from 'constants/search';
|
import { SEARCH_TYPES, SEARCH_OPTIONS } from 'constants/search';
|
||||||
import { DEFAULT_KNOWN_TAGS, DEFAULT_FOLLOWED_TAGS, MATURE_TAGS } from 'constants/tags';
|
import { DEFAULT_KNOWN_TAGS, DEFAULT_FOLLOWED_TAGS, MATURE_TAGS } from 'constants/tags';
|
||||||
import Lbry, { apiCall } from 'lbry';
|
import Lbry, { apiCall } from 'lbry';
|
||||||
|
import LbryFirst from 'lbry-first';
|
||||||
import { selectState as selectSearchState } from 'redux/selectors/search';
|
import { selectState as selectSearchState } from 'redux/selectors/search';
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
|
@ -42,6 +43,7 @@ export {
|
||||||
|
|
||||||
// common
|
// common
|
||||||
export { Lbry, apiCall };
|
export { Lbry, apiCall };
|
||||||
|
export { LbryFirst };
|
||||||
export {
|
export {
|
||||||
regexInvalidURI,
|
regexInvalidURI,
|
||||||
regexAddress,
|
regexAddress,
|
||||||
|
|
181
src/lbry-first.js
Normal file
181
src/lbry-first.js
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
// @flow
|
||||||
|
import 'proxy-polyfill';
|
||||||
|
|
||||||
|
const CHECK_LBRYFIRST_STARTED_TRY_NUMBER = 200;
|
||||||
|
//
|
||||||
|
// Basic LBRYFIRST connection config
|
||||||
|
// Offers a proxy to call LBRYFIRST methods
|
||||||
|
|
||||||
|
//
|
||||||
|
const LbryFirst: LbryFirstTypes = {
|
||||||
|
isConnected: false,
|
||||||
|
connectPromise: null,
|
||||||
|
lbryFirstConnectionString: 'http://localhost:1337/rpc',
|
||||||
|
apiRequestHeaders: { 'Content-Type': 'application/json' },
|
||||||
|
|
||||||
|
// Allow overriding lbryFirst connection string (e.g. to `/api/proxy` for lbryweb)
|
||||||
|
setLbryFirstConnectionString: (value: string) => {
|
||||||
|
LbryFirst.lbryFirstConnectionString = value;
|
||||||
|
},
|
||||||
|
|
||||||
|
setApiHeader: (key: string, value: string) => {
|
||||||
|
LbryFirst.apiRequestHeaders = Object.assign(LbryFirst.apiRequestHeaders, { [key]: value });
|
||||||
|
},
|
||||||
|
|
||||||
|
unsetApiHeader: key => {
|
||||||
|
Object.keys(LbryFirst.apiRequestHeaders).includes(key) && delete LbryFirst.apiRequestHeaders['key'];
|
||||||
|
},
|
||||||
|
// Allow overriding Lbry methods
|
||||||
|
overrides: {},
|
||||||
|
setOverride: (methodName, newMethod) => {
|
||||||
|
LbryFirst.overrides[methodName] = newMethod;
|
||||||
|
},
|
||||||
|
getApiRequestHeaders: () => LbryFirst.apiRequestHeaders,
|
||||||
|
|
||||||
|
//
|
||||||
|
// LbryFirst Methods
|
||||||
|
//
|
||||||
|
status: (params = {}) => lbryFirstCallWithResult('server.Status', params),
|
||||||
|
stop: () => lbryFirstCallWithResult('stop', {}),
|
||||||
|
version: () => lbryFirstCallWithResult('version', {}),
|
||||||
|
|
||||||
|
// Upload to youtube
|
||||||
|
upload: (params = {}) => {
|
||||||
|
// Only upload when originally publishing for now
|
||||||
|
if (!params.file_path) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const uploadParams = {};
|
||||||
|
uploadParams.Title = params.title;
|
||||||
|
uploadParams.Description = params.description;
|
||||||
|
uploadParams.FilePath = params.file_path;
|
||||||
|
uploadParams.Category = '';
|
||||||
|
uploadParams.ThumbnailURL = params.thumbnail_url;
|
||||||
|
uploadParams.Keywords = params.tags.join(',');
|
||||||
|
// Needs to be configurable?
|
||||||
|
uploadParams.PublishType = 'private';
|
||||||
|
uploadParams.PublishAt = ''; // Premiere Date
|
||||||
|
uploadParams.MonetizationOff = false;
|
||||||
|
uploadParams.ClaimName = params.name;
|
||||||
|
uploadParams.URI = params.permanent_url;
|
||||||
|
return lbryFirstCallWithResult('youtube.Upload', uploadParams);
|
||||||
|
},
|
||||||
|
|
||||||
|
hasYTAuth: (token: string) => {
|
||||||
|
const hasYTAuthParams = {};
|
||||||
|
hasYTAuthParams.AuthToken = token;
|
||||||
|
return lbryFirstCallWithResult('youtube.HasAuth', hasYTAuthParams);
|
||||||
|
},
|
||||||
|
|
||||||
|
ytSignup: () => {
|
||||||
|
const emptyParams = {};
|
||||||
|
return lbryFirstCallWithResult('youtube.Signup', emptyParams);
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: () => {
|
||||||
|
const emptyParams = {};
|
||||||
|
return lbryFirstCallWithResult('youtube.Remove', emptyParams);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Connect to lbry-first
|
||||||
|
connect: () => {
|
||||||
|
if (LbryFirst.connectPromise === null) {
|
||||||
|
LbryFirst.connectPromise = new Promise((resolve, reject) => {
|
||||||
|
let tryNum = 0;
|
||||||
|
// Check every half second to see if the lbryFirst is accepting connections
|
||||||
|
function checkLbryFirstStarted() {
|
||||||
|
tryNum += 1;
|
||||||
|
LbryFirst.status()
|
||||||
|
.then(resolve)
|
||||||
|
.catch(() => {
|
||||||
|
if (tryNum <= CHECK_LBRYFIRST_STARTED_TRY_NUMBER) {
|
||||||
|
setTimeout(checkLbryFirstStarted, tryNum < 50 ? 400 : 1000);
|
||||||
|
} else {
|
||||||
|
reject(new Error('Unable to connect to LBRY'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkLbryFirstStarted();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flow thinks this could be empty, but it will always return a promise
|
||||||
|
// $FlowFixMe
|
||||||
|
return LbryFirst.connectPromise;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function checkAndParse(response) {
|
||||||
|
if (response.status >= 200 && response.status < 300) {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
return response.json().then(json => {
|
||||||
|
let error;
|
||||||
|
if (json.error) {
|
||||||
|
const errorMessage = typeof json.error === 'object' ? json.error.message : json.error;
|
||||||
|
error = new Error(errorMessage);
|
||||||
|
} else {
|
||||||
|
error = new Error('Protocol error with unknown response signature');
|
||||||
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function apiCall(method: string, params: ?{}, resolve: Function, reject: Function) {
|
||||||
|
const counter = new Date().getTime();
|
||||||
|
params = [params];
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
headers: LbryFirst.apiRequestHeaders,
|
||||||
|
body: JSON.stringify({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
id: counter,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
return fetch(LbryFirst.lbryFirstConnectionString, options)
|
||||||
|
.then(checkAndParse)
|
||||||
|
.then(response => {
|
||||||
|
const error = response.error || (response.result && response.result.error);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return reject(error);
|
||||||
|
}
|
||||||
|
return resolve(response.result);
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
function lbryFirstCallWithResult(name: string, params: ?{} = {}) {
|
||||||
|
console.log(`LbryFirst: calling ${name}`);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
apiCall(
|
||||||
|
name,
|
||||||
|
params,
|
||||||
|
result => {
|
||||||
|
resolve(result);
|
||||||
|
},
|
||||||
|
reject
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is only for a fallback
|
||||||
|
// If there is a LbryFirst method that is being called by an app, it should be added to /flow-typed/LbryFirst.js
|
||||||
|
const lbryFirstProxy = new Proxy(LbryFirst, {
|
||||||
|
get(target: LbryFirstTypes, name: string) {
|
||||||
|
if (name in target) {
|
||||||
|
return target[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (params = {}) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
apiCall(name, params, resolve, reject);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default lbryFirstProxy;
|
|
@ -4,6 +4,7 @@ import { SPEECH_STATUS, SPEECH_PUBLISH } from 'constants/speech_urls';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
||||||
import Lbry from 'lbry';
|
import Lbry from 'lbry';
|
||||||
|
import LbryFirst from 'lbry-first';
|
||||||
import { batchActions } from 'util/batch-actions';
|
import { batchActions } from 'util/batch-actions';
|
||||||
import { creditsToString } from 'util/format-credits';
|
import { creditsToString } from 'util/format-credits';
|
||||||
import { doError } from 'redux/actions/notifications';
|
import { doError } from 'redux/actions/notifications';
|
||||||
|
@ -245,6 +246,7 @@ export const doPublish = (success: Function, fail: Function) => (
|
||||||
language,
|
language,
|
||||||
license,
|
license,
|
||||||
licenseUrl,
|
licenseUrl,
|
||||||
|
useLBRYUploader,
|
||||||
licenseType,
|
licenseType,
|
||||||
otherLicenseDescription,
|
otherLicenseDescription,
|
||||||
thumbnail,
|
thumbnail,
|
||||||
|
@ -350,8 +352,15 @@ export const doPublish = (success: Function, fail: Function) => (
|
||||||
// Only pass file on new uploads, not metadata only edits.
|
// Only pass file on new uploads, not metadata only edits.
|
||||||
// The sdk will figure it out
|
// The sdk will figure it out
|
||||||
if (filePath) publishPayload.file_path = filePath;
|
if (filePath) publishPayload.file_path = filePath;
|
||||||
|
// if (useLBRYUploader) return LbryFirst.upload(publishPayload);
|
||||||
return Lbry.publish(publishPayload).then(success, fail);
|
return Lbry.publish(publishPayload)
|
||||||
|
.then((response) => {
|
||||||
|
if (!useLBRYUploader) {
|
||||||
|
return success(response);
|
||||||
|
}
|
||||||
|
publishPayload.permanent_url = response.outputs[0].permanent_url;
|
||||||
|
return LbryFirst.upload(publishPayload).then(success(response), fail);
|
||||||
|
}, fail);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calls file_list until any reflecting files are done
|
// Calls file_list until any reflecting files are done
|
||||||
|
|
|
@ -33,6 +33,7 @@ type PublishState = {
|
||||||
licenseUrl: string,
|
licenseUrl: string,
|
||||||
tags: Array<string>,
|
tags: Array<string>,
|
||||||
optimize: boolean,
|
optimize: boolean,
|
||||||
|
useLBRYUploader: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultState: PublishState = {
|
const defaultState: PublishState = {
|
||||||
|
@ -68,6 +69,7 @@ const defaultState: PublishState = {
|
||||||
publishSuccess: false,
|
publishSuccess: false,
|
||||||
publishError: undefined,
|
publishError: undefined,
|
||||||
optimize: false,
|
optimize: false,
|
||||||
|
useLBRYUploader: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const publishReducer = handleActions(
|
export const publishReducer = handleActions(
|
||||||
|
|
Loading…
Reference in a new issue