2018-04-05 03:57:29 +01:00
|
|
|
// @flow
|
|
|
|
import 'proxy-polyfill';
|
2018-01-11 12:54:20 +01:00
|
|
|
|
|
|
|
const CHECK_DAEMON_STARTED_TRY_NUMBER = 200;
|
|
|
|
|
|
|
|
const Lbry = {
|
|
|
|
isConnected: false,
|
|
|
|
daemonConnectionString: 'http://localhost:5279',
|
|
|
|
pendingPublishTimeout: 20 * 60 * 1000,
|
|
|
|
};
|
|
|
|
|
2018-04-05 03:57:29 +01:00
|
|
|
function checkAndParse(response) {
|
|
|
|
if (response.status >= 200 && response.status < 300) {
|
|
|
|
return response.json();
|
|
|
|
}
|
|
|
|
return response.json().then(json => {
|
|
|
|
let error;
|
|
|
|
if (json.error) {
|
|
|
|
error = new Error(json.error);
|
|
|
|
} else {
|
|
|
|
error = new Error('Protocol error with unknown response signature');
|
|
|
|
}
|
|
|
|
return Promise.reject(error);
|
|
|
|
});
|
2018-01-11 12:54:20 +01:00
|
|
|
}
|
|
|
|
|
2018-04-05 03:57:29 +01:00
|
|
|
function apiCall(method: string, params: ?{}, resolve: Function, reject: Function) {
|
|
|
|
const counter = new Date().getTime();
|
|
|
|
const options = {
|
|
|
|
method: 'POST',
|
|
|
|
body: JSON.stringify({
|
|
|
|
jsonrpc: '2.0',
|
|
|
|
method,
|
|
|
|
params,
|
|
|
|
id: counter,
|
|
|
|
}),
|
|
|
|
};
|
2018-01-11 12:54:20 +01:00
|
|
|
|
2018-04-05 03:57:29 +01:00
|
|
|
return fetch(Lbry.daemonConnectionString, 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);
|
|
|
|
}
|
2018-01-11 12:54:20 +01:00
|
|
|
|
2018-05-02 01:09:00 +01:00
|
|
|
const daemonCallWithResult = (name, params = {}) =>
|
2018-04-05 03:57:29 +01:00
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
apiCall(
|
2018-05-02 01:09:00 +01:00
|
|
|
name,
|
2018-04-21 21:40:54 +01:00
|
|
|
params,
|
2018-05-02 01:09:00 +01:00
|
|
|
result => {
|
|
|
|
resolve(result);
|
2018-04-21 21:40:54 +01:00
|
|
|
},
|
|
|
|
reject
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2018-08-15 20:58:25 +01:00
|
|
|
// blobs
|
|
|
|
Lbry.blob_delete = (params = {}) => daemonCallWithResult('blob_delete', params);
|
|
|
|
Lbry.blob_list = (params = {}) => daemonCallWithResult('blob_list', params);
|
|
|
|
|
2018-05-02 01:09:00 +01:00
|
|
|
// core
|
|
|
|
Lbry.status = (params = {}) => daemonCallWithResult('status', params);
|
|
|
|
Lbry.version = () => daemonCallWithResult('version', {});
|
|
|
|
Lbry.file_delete = (params = {}) => daemonCallWithResult('file_delete', params);
|
|
|
|
Lbry.file_set_status = (params = {}) => daemonCallWithResult('file_set_status', params);
|
2019-02-18 09:11:32 -05:00
|
|
|
Lbry.stop = () => daemonCallWithResult('stop', {});
|
2018-05-02 01:09:00 +01:00
|
|
|
|
2018-05-25 12:34:12 +01:00
|
|
|
// claims
|
|
|
|
Lbry.claim_list_by_channel = (params = {}) => daemonCallWithResult('claim_list_by_channel', params);
|
|
|
|
|
2018-05-02 01:09:00 +01:00
|
|
|
// wallet
|
2018-10-25 12:57:55 -04:00
|
|
|
Lbry.account_balance = (params = {}) => daemonCallWithResult('account_balance', params);
|
|
|
|
Lbry.account_decrypt = () => daemonCallWithResult('account_decrypt', {});
|
|
|
|
Lbry.account_encrypt = (params = {}) => daemonCallWithResult('account_encrypt', params);
|
2019-02-22 02:02:20 -05:00
|
|
|
Lbry.account_list = (params = {}) => daemonCallWithResult('account_list', params);
|
2018-10-25 12:57:55 -04:00
|
|
|
Lbry.address_is_mine = (params = {}) => daemonCallWithResult('address_is_mine', params);
|
2018-08-24 12:22:00 +01:00
|
|
|
Lbry.wallet_lock = () => daemonCallWithResult('wallet_lock', {});
|
2018-10-25 12:57:55 -04:00
|
|
|
Lbry.address_unused = (params = {}) => daemonCallWithResult('address_unused', params);
|
2018-05-02 01:09:00 +01:00
|
|
|
Lbry.wallet_send = (params = {}) => daemonCallWithResult('wallet_send', params);
|
2018-10-25 12:57:55 -04:00
|
|
|
Lbry.account_unlock = (params = {}) => daemonCallWithResult('account_unlock', params);
|
|
|
|
Lbry.address_unused = () => daemonCallWithResult('address_unused', {});
|
|
|
|
Lbry.claim_tip = (params = {}) => daemonCallWithResult('claim_tip', params);
|
2018-01-11 12:54:20 +01:00
|
|
|
|
2018-05-02 07:34:11 +01:00
|
|
|
// transactions
|
|
|
|
Lbry.transaction_list = (params = {}) => daemonCallWithResult('transaction_list', params);
|
2019-02-18 21:50:40 +01:00
|
|
|
Lbry.utxo_release = (params = {}) => daemonCallWithResult('utxo_release', params);
|
2018-05-02 07:34:11 +01:00
|
|
|
|
2018-01-11 12:54:20 +01:00
|
|
|
Lbry.connectPromise = null;
|
|
|
|
Lbry.connect = () => {
|
|
|
|
if (Lbry.connectPromise === null) {
|
|
|
|
Lbry.connectPromise = new Promise((resolve, reject) => {
|
|
|
|
let tryNum = 0;
|
|
|
|
// Check every half second to see if the daemon is accepting connections
|
|
|
|
function checkDaemonStarted() {
|
|
|
|
tryNum += 1;
|
2018-04-05 03:57:29 +01:00
|
|
|
Lbry.status()
|
2018-01-11 12:54:20 +01:00
|
|
|
.then(resolve)
|
|
|
|
.catch(() => {
|
|
|
|
if (tryNum <= CHECK_DAEMON_STARTED_TRY_NUMBER) {
|
|
|
|
setTimeout(checkDaemonStarted, tryNum < 50 ? 400 : 1000);
|
|
|
|
} else {
|
|
|
|
reject(new Error('Unable to connect to LBRY'));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
checkDaemonStarted();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return Lbry.connectPromise;
|
|
|
|
};
|
|
|
|
|
2018-07-05 12:20:41 -06:00
|
|
|
Lbry.getMediaType = (contentType, extname) => {
|
|
|
|
if (extname) {
|
2018-04-19 17:59:24 +00:00
|
|
|
const formats = [
|
2018-07-05 12:20:41 -06:00
|
|
|
[/^(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'],
|
|
|
|
[/^(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'],
|
|
|
|
[/^(html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org)$/i, 'document'],
|
|
|
|
[/^(stl|obj|fbx|gcode)$/i, '3D-file'],
|
2018-05-02 01:09:00 +01:00
|
|
|
];
|
|
|
|
const res = formats.reduce((ret, testpair) => {
|
2018-04-19 17:59:24 +00:00
|
|
|
switch (testpair[0].test(ret)) {
|
2018-05-02 01:09:00 +01:00
|
|
|
case true:
|
|
|
|
return testpair[1];
|
|
|
|
default:
|
|
|
|
return ret;
|
|
|
|
}
|
2018-07-05 12:20:41 -06:00
|
|
|
}, extname);
|
|
|
|
return res === extname ? 'unknown' : res;
|
2018-07-04 17:06:13 -06:00
|
|
|
} else if (contentType) {
|
|
|
|
return /^[^/]+/.exec(contentType)[0];
|
2018-07-17 22:55:40 -04:00
|
|
|
}
|
2018-01-11 12:54:20 +01:00
|
|
|
return 'unknown';
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wrappers for API methods to simulate missing or future behavior. Unlike the old-style stubs,
|
|
|
|
* these are designed to be transparent wrappers around the corresponding API methods.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns results from the file_list API method, plus dummy entries for pending publishes.
|
|
|
|
* (If a real publish with the same name is found, the pending publish will be ignored and removed.)
|
|
|
|
*/
|
|
|
|
Lbry.file_list = (params = {}) =>
|
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
apiCall(
|
|
|
|
'file_list',
|
|
|
|
params,
|
|
|
|
fileInfos => {
|
2018-04-05 03:57:29 +01:00
|
|
|
resolve(fileInfos);
|
2018-01-11 12:54:20 +01:00
|
|
|
},
|
|
|
|
reject
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
Lbry.claim_list_mine = (params = {}) =>
|
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
apiCall(
|
|
|
|
'claim_list_mine',
|
|
|
|
params,
|
|
|
|
claims => {
|
2018-04-05 03:57:29 +01:00
|
|
|
resolve(claims);
|
|
|
|
},
|
|
|
|
reject
|
|
|
|
);
|
|
|
|
});
|
2018-01-11 12:54:20 +01:00
|
|
|
|
2018-04-05 03:57:29 +01:00
|
|
|
Lbry.get = (params = {}) =>
|
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
apiCall(
|
|
|
|
'get',
|
|
|
|
params,
|
|
|
|
streamInfo => {
|
|
|
|
resolve(streamInfo);
|
2018-01-11 12:54:20 +01:00
|
|
|
},
|
|
|
|
reject
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
Lbry.resolve = (params = {}) =>
|
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
apiCall(
|
|
|
|
'resolve',
|
|
|
|
params,
|
|
|
|
data => {
|
2019-02-18 09:11:32 -05:00
|
|
|
resolve(data || {});
|
2018-01-11 12:54:20 +01:00
|
|
|
},
|
|
|
|
reject
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2019-02-22 02:02:20 -05:00
|
|
|
Lbry.publish = (params = {}) =>
|
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
if (Lbry.overrides.publish) {
|
|
|
|
Lbry.overrides.publish(params).then(resolve, reject);
|
|
|
|
} else {
|
|
|
|
apiCall('publish', params, resolve, reject);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Allow overriding Lbry methods
|
|
|
|
Lbry.overrides = {};
|
|
|
|
Lbry.setOverride = (methodName, newMethod) => {
|
|
|
|
Lbry.overrides[methodName] = newMethod;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Allow overriding daemon connection string (e.g. to `/api/proxy` for lbryweb)
|
|
|
|
Lbry.setDaemonConnectionString = value => {
|
|
|
|
Lbry.daemonConnectionString = value;
|
|
|
|
};
|
|
|
|
|
2018-04-05 03:57:29 +01:00
|
|
|
const lbryProxy = new Proxy(Lbry, {
|
|
|
|
get(target, name) {
|
|
|
|
if (name in target) {
|
|
|
|
return target[name];
|
|
|
|
}
|
|
|
|
|
|
|
|
return (params = {}) =>
|
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
apiCall(name, params, resolve, reject);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2018-01-11 12:54:20 +01:00
|
|
|
export default lbryProxy;
|