lbry-desktop/ui/js/lbryio.js
2017-06-21 18:49:23 -04:00

214 lines
5.7 KiB
JavaScript

import lbry from "./lbry.js";
const querystring = require("querystring");
const keytar = require("keytar");
const lbryio = {
enabled: true,
_authenticationPromise: null,
_exchangePromise: null,
_exchangeLastFetched: null,
};
const CONNECTION_STRING = process.env.LBRY_APP_API_URL
? process.env.LBRY_APP_API_URL.replace(/\/*$/, "/") // exactly one slash at the end
: "https://api.lbry.io/";
const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000;
lbryio.getExchangeRates = function() {
if (
!lbryio._exchangeLastFetched ||
Date.now() - lbryio._exchangeLastFetched > EXCHANGE_RATE_TIMEOUT
) {
lbryio._exchangePromise = new Promise((resolve, reject) => {
lbryio
.call("lbc", "exchange_rate", {}, "get", true)
.then(({ lbc_usd, lbc_btc, btc_usd }) => {
const rates = { lbc_usd, lbc_btc, btc_usd };
resolve(rates);
})
.catch(reject);
});
lbryio._exchangeLastFetched = Date.now();
}
return lbryio._exchangePromise;
};
lbryio.call = function(resource, action, params = {}, method = "get") {
return new Promise((resolve, reject) => {
if (!lbryio.enabled && (resource != "discover" || action != "list")) {
console.log(__("Internal API disabled"));
reject(new Error(__("LBRY internal API is disabled")));
return;
}
const xhr = new XMLHttpRequest();
xhr.addEventListener("error", function(event) {
reject(
new Error(__("Something went wrong making an internal API call."))
);
});
xhr.addEventListener("timeout", function() {
reject(new Error(__("XMLHttpRequest connection timed out")));
});
xhr.addEventListener("load", function() {
const response = JSON.parse(xhr.responseText);
if (!response.success) {
if (reject) {
const error = new Error(response.error);
error.xhr = xhr;
reject(error);
} else {
document.dispatchEvent(
new CustomEvent("unhandledError", {
detail: {
connectionString: connectionString,
method: action,
params: params,
message: response.error.message,
...(response.error.data ? { data: response.error.data } : {}),
},
})
);
}
} else {
resolve(response.data);
}
});
lbryio
.getAuthToken()
.then(token => {
const fullParams = { auth_token: token, ...params };
if (method == "get") {
xhr.open(
"get",
CONNECTION_STRING +
resource +
"/" +
action +
"?" +
querystring.stringify(fullParams),
true
);
xhr.send();
} else if (method == "post") {
xhr.open("post", CONNECTION_STRING + resource + "/" + action, true);
xhr.setRequestHeader(
"Content-type",
"application/x-www-form-urlencoded"
);
xhr.send(querystring.stringify(fullParams));
} else {
reject(new Error(__("Invalid method")));
}
})
.catch(reject);
});
};
lbryio.getAuthToken = () => {
return keytar.getPassword("LBRY", "auth_token").then(token => {
return token ? token.toString().trim() : null;
});
};
lbryio.setAuthToken = token => {
return keytar.setPassword(
"LBRY",
"auth_token",
token ? token.toString().trim() : null
);
};
lbryio.getCurrentUser = () => {
return lbryio.call("user", "me");
};
lbryio.authenticate = function() {
if (!lbryio.enabled) {
return new Promise((resolve, reject) => {
resolve({
id: 1,
language: "en",
has_email: true,
has_verified_email: true,
is_reward_approved: false,
is_reward_eligible: false,
});
});
}
if (lbryio._authenticationPromise === null) {
lbryio._authenticationPromise = new Promise((resolve, reject) => {
lbryio
.getAuthToken()
.then(token => {
if (!token || token.length > 60) {
return false;
}
// check that token works
return lbryio
.getCurrentUser()
.then(() => {
return true;
})
.catch(() => {
return false;
});
})
.then(isTokenValid => {
if (isTokenValid) {
return;
}
let app_id;
return lbry
.status()
.then(status => {
// first try swapping
app_id = status.installation_id;
return lbryio.call(
"user",
"token_swap",
{ auth_token: "", app_id: app_id },
"post"
);
})
.catch(err => {
if (err.xhr.status == 403) {
// cannot swap. either app_id doesn't exist, or app_id already swapped. pretend its the former and create a new user. if we get another error, then its the latter
return lbryio.call(
"user",
"new",
{ auth_token: "", language: "en", app_id: app_id },
"post"
);
}
throw err;
})
.then(response => {
if (!response.auth_token) {
throw new Error(__("auth_token is missing from response"));
}
return lbryio.setAuthToken(response.auth_token);
});
})
.then(lbryio.getCurrentUser)
.then(resolve, reject);
});
}
return lbryio._authenticationPromise;
};
export default lbryio;