// @flow /* LBRY FIRST does not work due to api changes */ 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('status', params), stop: () => lbryFirstCallWithResult('stop', {}), version: () => lbryFirstCallWithResult('version', {}), // Upload to youtube upload: (params: { title: string, description: string, file_path: ?string } = {}) => { // Only upload when originally publishing for now if (!params.file_path) { return Promise.resolve(); } const uploadParams: { Title: string, Description: string, FilePath: string, Category: string, Keywords: string, } = { Title: params.title, Description: params.description, FilePath: params.file_path, Category: '', Keywords: '', }; 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(); const paramsArray = [params]; const options = { method: 'POST', headers: LbryFirst.apiRequestHeaders, body: JSON.stringify({ jsonrpc: '2.0', method, params: paramsArray, 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: ?{} = {}) { 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;