mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-25 07:07:48 +01:00
650 lines
19 KiB
JavaScript
650 lines
19 KiB
JavaScript
window.ExtensionsPageLogic = {
|
|
data: function () {
|
|
return {
|
|
slide: 0,
|
|
fullscreen: false,
|
|
autoplay: true,
|
|
searchTerm: '',
|
|
tab: 'all',
|
|
manageExtensionTab: 'releases',
|
|
filteredExtensions: null,
|
|
updatableExtensions: [],
|
|
showUninstallDialog: false,
|
|
showManageExtensionDialog: false,
|
|
showExtensionDetailsDialog: false,
|
|
showDropDbDialog: false,
|
|
showPayToEnableDialog: false,
|
|
showUpdateAllDialog: false,
|
|
dropDbExtensionId: '',
|
|
selectedExtension: null,
|
|
selectedImage: null,
|
|
selectedExtensionDetails: null,
|
|
selectedExtensionRepos: null,
|
|
selectedRelease: null,
|
|
uninstallAndDropDb: false,
|
|
maxStars: 5,
|
|
paylinkWebsocket: null,
|
|
user: null
|
|
}
|
|
},
|
|
watch: {
|
|
searchTerm(term) {
|
|
this.filterExtensions(term, this.tab)
|
|
}
|
|
},
|
|
methods: {
|
|
handleTabChanged: function (tab) {
|
|
this.filterExtensions(this.searchTerm, tab)
|
|
},
|
|
filterExtensions: function (term, tab) {
|
|
// Filter the extensions list
|
|
function extensionNameContains(searchTerm) {
|
|
return function (extension) {
|
|
return (
|
|
extension.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
extension.shortDescription
|
|
?.toLowerCase()
|
|
.includes(searchTerm.toLowerCase())
|
|
)
|
|
}
|
|
}
|
|
|
|
this.filteredExtensions = this.extensions
|
|
.filter(e => (tab === 'all' ? !e.isInstalled : true))
|
|
.filter(e => (tab === 'installed' ? e.isInstalled : true))
|
|
.filter(e =>
|
|
tab === 'installed' ? (e.isActive ? true : !!this.g.user.admin) : true
|
|
)
|
|
.filter(e => (tab === 'featured' ? e.isFeatured : true))
|
|
.filter(extensionNameContains(term))
|
|
.map(e => ({
|
|
...e,
|
|
details_link:
|
|
e.installedRelease?.details_link || e.latestRelease?.details_link
|
|
}))
|
|
this.tab = tab
|
|
},
|
|
|
|
installExtension: async function (release) {
|
|
// no longer required to check if the invoice was paid
|
|
// the install logic has been triggered one way or another
|
|
this.unsubscribeFromPaylinkWs()
|
|
|
|
const extension = this.selectedExtension
|
|
extension.inProgress = true
|
|
this.showManageExtensionDialog = false
|
|
release.payment_hash =
|
|
release.payment_hash || this.getPaylinkHash(release.pay_link)
|
|
|
|
LNbits.api
|
|
.request('POST', `/api/v1/extension`, this.g.user.wallets[0].adminkey, {
|
|
ext_id: extension.id,
|
|
archive: release.archive,
|
|
source_repo: release.source_repo,
|
|
payment_hash: release.payment_hash,
|
|
version: release.version
|
|
})
|
|
.then(response => {
|
|
extension.isAvailable = true
|
|
extension.isInstalled = true
|
|
extension.installedRelease = release
|
|
this.toggleExtension(extension)
|
|
extension.inProgress = false
|
|
this.filteredExtensions = this.extensions.concat([])
|
|
this.handleTabChanged('installed')
|
|
this.tab = 'installed'
|
|
this.refreshRoute()
|
|
})
|
|
.catch(err => {
|
|
console.warn(err)
|
|
extension.inProgress = false
|
|
LNbits.utils.notifyApiError(err)
|
|
})
|
|
},
|
|
uninstallExtension: async function () {
|
|
const extension = this.selectedExtension
|
|
this.showManageExtensionDialog = false
|
|
this.showUninstallDialog = false
|
|
extension.inProgress = true
|
|
LNbits.api
|
|
.request(
|
|
'DELETE',
|
|
`/api/v1/extension/${extension.id}`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
extension.isAvailable = false
|
|
extension.isInstalled = false
|
|
extension.inProgress = false
|
|
extension.installedRelease = null
|
|
this.filteredExtensions = this.extensions.concat([])
|
|
this.handleTabChanged('installed')
|
|
this.tab = 'installed'
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Extension uninstalled!'
|
|
})
|
|
if (this.uninstallAndDropDb) {
|
|
this.showDropDb()
|
|
} else {
|
|
setTimeout(() => {
|
|
this.refreshRoute()
|
|
}, 300)
|
|
}
|
|
})
|
|
.catch(err => {
|
|
LNbits.utils.notifyApiError(err)
|
|
extension.inProgress = false
|
|
})
|
|
},
|
|
dropExtensionDb: async function () {
|
|
const extension = this.selectedExtension
|
|
this.showManageExtensionDialog = false
|
|
this.showDropDbDialog = false
|
|
this.dropDbExtensionId = ''
|
|
extension.inProgress = true
|
|
LNbits.api
|
|
.request(
|
|
'DELETE',
|
|
`/api/v1/extension/${extension.id}/db`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
extension.installedRelease = null
|
|
extension.inProgress = false
|
|
extension.hasDatabaseTables = false
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Extension DB deleted!'
|
|
})
|
|
setTimeout(() => {
|
|
this.refreshRoute()
|
|
}, 300)
|
|
})
|
|
.catch(err => {
|
|
LNbits.utils.notifyApiError(err)
|
|
extension.inProgress = false
|
|
})
|
|
},
|
|
toggleExtension(extension) {
|
|
const action = extension.isActive ? 'activate' : 'deactivate'
|
|
LNbits.api
|
|
.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extension.id}/${action}`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
Quasar.Notify.create({
|
|
timeout: 2000,
|
|
type: 'positive',
|
|
message: `Extension '${extension.id}' ${action}d!`
|
|
})
|
|
})
|
|
.catch(err => {
|
|
LNbits.utils.notifyApiError(err)
|
|
extension.isActive = false
|
|
extension.inProgress = false
|
|
})
|
|
},
|
|
enableExtensionForUser: function (extension) {
|
|
if (extension.isPaymentRequired) {
|
|
this.showPayToEnable(extension)
|
|
return
|
|
}
|
|
this.enableExtension(extension)
|
|
},
|
|
enableExtension: function (extension) {
|
|
LNbits.api
|
|
.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extension.id}/enable`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Extension enabled!'
|
|
})
|
|
setTimeout(() => {
|
|
this.refreshRoute()
|
|
}, 300)
|
|
})
|
|
.catch(err => {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
})
|
|
},
|
|
disableExtension: function (extension) {
|
|
LNbits.api
|
|
.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extension.id}/disable`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Extension disabled!'
|
|
})
|
|
setTimeout(() => {
|
|
this.refreshRoute()
|
|
}, 300)
|
|
})
|
|
.catch(err => {
|
|
console.warn(error)
|
|
LNbits.utils.notifyApiError(err)
|
|
})
|
|
},
|
|
showPayToEnable: function (extension) {
|
|
this.selectedExtension = extension
|
|
this.selectedExtension.payToEnable.paidAmount =
|
|
extension.payToEnable.amount
|
|
this.selectedExtension.payToEnable.showQRCode = false
|
|
this.showPayToEnableDialog = true
|
|
},
|
|
updatePayToInstallData: function (extension) {
|
|
LNbits.api
|
|
.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extension.id}/sell`,
|
|
this.g.user.wallets[0].adminkey,
|
|
{
|
|
required: extension.payToEnable.required,
|
|
amount: extension.payToEnable.amount,
|
|
wallet: extension.payToEnable.wallet
|
|
}
|
|
)
|
|
.then(response => {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Payment info updated!'
|
|
})
|
|
this.showManageExtensionDialog = false
|
|
})
|
|
.catch(err => {
|
|
LNbits.utils.notifyApiError(err)
|
|
extension.inProgress = false
|
|
})
|
|
},
|
|
|
|
showUninstall: function () {
|
|
this.showManageExtensionDialog = false
|
|
this.showUninstallDialog = true
|
|
this.uninstallAndDropDb = false
|
|
},
|
|
|
|
showDropDb: function () {
|
|
this.showDropDbDialog = true
|
|
},
|
|
|
|
showManageExtension: async function (extension) {
|
|
this.selectedExtension = extension
|
|
this.selectedRelease = null
|
|
this.selectedExtensionRepos = null
|
|
this.manageExtensionTab = 'releases'
|
|
this.showManageExtensionDialog = true
|
|
|
|
try {
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
`/api/v1/extension/${extension.id}/releases`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
|
|
this.selectedExtensionRepos = data.reduce((repos, release) => {
|
|
repos[release.source_repo] = repos[release.source_repo] || {
|
|
releases: [],
|
|
isInstalled: false,
|
|
repo: release.repo
|
|
}
|
|
release.inProgress = false
|
|
release.error = null
|
|
release.loaded = false
|
|
release.isInstalled = this.isInstalledVersion(
|
|
this.selectedExtension,
|
|
release
|
|
)
|
|
if (release.isInstalled) {
|
|
repos[release.source_repo].isInstalled = true
|
|
}
|
|
if (release.pay_link) {
|
|
release.requiresPayment = true
|
|
release.paidAmount = release.cost_sats
|
|
release.payment_hash = this.getPaylinkHash(release.pay_link)
|
|
}
|
|
|
|
repos[release.source_repo].releases.push(release)
|
|
return repos
|
|
}, {})
|
|
} catch (error) {
|
|
LNbits.utils.notifyApiError(error)
|
|
extension.inProgress = false
|
|
}
|
|
},
|
|
|
|
showExtensionDetails: async function (extId, detailsLink) {
|
|
if (!detailsLink) {
|
|
return
|
|
}
|
|
this.selectedExtensionDetails = null
|
|
this.showExtensionDetailsDialog = true
|
|
this.slide = 0
|
|
this.fullscreen = false
|
|
|
|
try {
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
`/api/v1/extension/${extId}/details?details_link=${detailsLink}`,
|
|
this.g.user.wallets[0].inkey
|
|
)
|
|
|
|
this.selectedExtensionDetails = data
|
|
this.selectedExtensionDetails.description_md =
|
|
LNbits.utils.convertMarkdown(data.description_md)
|
|
} catch (error) {
|
|
console.warn(error)
|
|
}
|
|
},
|
|
async payAndInstall(release) {
|
|
try {
|
|
this.selectedExtension.inProgress = true
|
|
this.showManageExtensionDialog = false
|
|
const paymentInfo = await this.requestPaymentForInstall(
|
|
this.selectedExtension.id,
|
|
release
|
|
)
|
|
this.rememberPaylinkHash(release.pay_link, paymentInfo.payment_hash)
|
|
const wallet = this.g.user.wallets.find(w => w.id === release.wallet)
|
|
const {data} = await LNbits.api.payInvoice(
|
|
wallet,
|
|
paymentInfo.payment_request
|
|
)
|
|
|
|
release.payment_hash = data.payment_hash
|
|
|
|
await this.installExtension(release)
|
|
} catch (err) {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
} finally {
|
|
this.selectedExtension.inProgress = false
|
|
}
|
|
},
|
|
async payAndEnable(extension) {
|
|
try {
|
|
const paymentInfo = await this.requestPaymentForEnable(
|
|
extension.id,
|
|
extension.payToEnable.paidAmount
|
|
)
|
|
|
|
const wallet = this.g.user.wallets.find(
|
|
w => w.id === extension.payToEnable.paymentWallet
|
|
)
|
|
const {data} = await LNbits.api.payInvoice(
|
|
wallet,
|
|
paymentInfo.payment_request
|
|
)
|
|
this.enableExtension(extension)
|
|
this.showPayToEnableDialog = false
|
|
} catch (err) {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
}
|
|
},
|
|
async showInstallQRCode(release) {
|
|
this.selectedRelease = release
|
|
|
|
try {
|
|
const data = await this.requestPaymentForInstall(
|
|
this.selectedExtension.id,
|
|
release
|
|
)
|
|
|
|
this.selectedRelease.paymentRequest = data.payment_request
|
|
this.selectedRelease.payment_hash = data.payment_hash
|
|
this.selectedRelease = _.clone(this.selectedRelease)
|
|
this.rememberPaylinkHash(
|
|
this.selectedRelease.pay_link,
|
|
this.selectedRelease.payment_hash
|
|
)
|
|
|
|
this.subscribeToPaylinkWs(
|
|
this.selectedRelease.pay_link,
|
|
data.payment_hash
|
|
)
|
|
} catch (err) {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
}
|
|
},
|
|
|
|
async showEnableQRCode(extension) {
|
|
try {
|
|
extension.payToEnable.showQRCode = true
|
|
this.selectedExtension = _.clone(extension)
|
|
|
|
const data = await this.requestPaymentForEnable(
|
|
extension.id,
|
|
extension.payToEnable.paidAmount
|
|
)
|
|
extension.payToEnable.paymentRequest = data.payment_request
|
|
this.selectedExtension = _.clone(extension)
|
|
|
|
const url = new URL(window.location)
|
|
url.protocol = url.protocol === 'https:' ? 'wss' : 'ws'
|
|
url.pathname = `/api/v1/ws/${data.payment_hash}`
|
|
const ws = new WebSocket(url)
|
|
ws.addEventListener('message', async ({data}) => {
|
|
const payment = JSON.parse(data)
|
|
if (payment.pending === false) {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Invoice Paid!'
|
|
})
|
|
|
|
this.enableExtension(extension)
|
|
ws.close()
|
|
}
|
|
})
|
|
} catch (err) {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
}
|
|
},
|
|
|
|
async requestPaymentForInstall(extId, release) {
|
|
const {data} = await LNbits.api.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extId}/invoice/install`,
|
|
this.g.user.wallets[0].adminkey,
|
|
{
|
|
ext_id: extId,
|
|
archive: release.archive,
|
|
source_repo: release.source_repo,
|
|
cost_sats: release.paidAmount,
|
|
version: release.version
|
|
}
|
|
)
|
|
return data
|
|
},
|
|
|
|
async requestPaymentForEnable(extId, amount) {
|
|
const {data} = await LNbits.api.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extId}/invoice/enable`,
|
|
this.g.user.wallets[0].adminkey,
|
|
{
|
|
amount
|
|
}
|
|
)
|
|
return data
|
|
},
|
|
|
|
clearHangingInvoice(release) {
|
|
this.forgetPaylinkHash(release.pay_link)
|
|
release.payment_hash = null
|
|
},
|
|
|
|
rememberPaylinkHash(pay_link, payment_hash) {
|
|
this.$q.localStorage.set(
|
|
`lnbits.extensions.paylink.${pay_link}`,
|
|
payment_hash
|
|
)
|
|
},
|
|
getPaylinkHash(pay_link) {
|
|
return this.$q.localStorage.getItem(
|
|
`lnbits.extensions.paylink.${pay_link}`
|
|
)
|
|
},
|
|
forgetPaylinkHash(pay_link) {
|
|
this.$q.localStorage.remove(`lnbits.extensions.paylink.${pay_link}`)
|
|
},
|
|
subscribeToPaylinkWs(pay_link, payment_hash) {
|
|
const url = new URL(`${pay_link}/${payment_hash}`)
|
|
url.protocol = url.protocol === 'https:' ? 'wss' : 'ws'
|
|
this.paylinkWebsocket = new WebSocket(url)
|
|
this.paylinkWebsocket.addEventListener('message', async ({data}) => {
|
|
const resp = JSON.parse(data)
|
|
if (resp.paid) {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Invoice Paid!'
|
|
})
|
|
this.installExtension(this.selectedRelease)
|
|
} else {
|
|
Quasar.Notify.create({
|
|
type: 'warning',
|
|
message: 'Invoice tracking lost!'
|
|
})
|
|
}
|
|
})
|
|
},
|
|
unsubscribeFromPaylinkWs() {
|
|
try {
|
|
this.paylinkWebsocket && this.paylinkWebsocket.close()
|
|
} catch (error) {
|
|
console.warn(error)
|
|
}
|
|
},
|
|
|
|
hasNewVersion: function (extension) {
|
|
if (extension.installedRelease && extension.latestRelease) {
|
|
return (
|
|
extension.installedRelease.version !== extension.latestRelease.version
|
|
)
|
|
}
|
|
},
|
|
isInstalledVersion: function (extension, release) {
|
|
if (extension.installedRelease) {
|
|
return (
|
|
extension.installedRelease.source_repo === release.source_repo &&
|
|
extension.installedRelease.version === release.version
|
|
)
|
|
}
|
|
},
|
|
getReleaseIcon: function (release) {
|
|
if (!release.is_version_compatible) return 'block'
|
|
if (release.isInstalled) return 'download_done'
|
|
|
|
return 'download'
|
|
},
|
|
getReleaseIconColor: function (release) {
|
|
if (!release.is_version_compatible) return 'text-red'
|
|
if (release.isInstalled) return 'text-green'
|
|
|
|
return ''
|
|
},
|
|
getGitHubReleaseDetails: async function (release) {
|
|
if (!release.is_github_release || release.loaded) {
|
|
return
|
|
}
|
|
const [org, repo] = release.source_repo.split('/')
|
|
release.inProgress = true
|
|
try {
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
`/api/v1/extension/release/${org}/${repo}/${release.version}`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
release.loaded = true
|
|
release.is_version_compatible = data.is_version_compatible
|
|
release.min_lnbits_version = data.min_lnbits_version
|
|
release.warning = data.warning
|
|
} catch (error) {
|
|
console.warn(error)
|
|
release.error = error
|
|
LNbits.utils.notifyApiError(error)
|
|
} finally {
|
|
release.inProgress = false
|
|
}
|
|
},
|
|
selectAllUpdatableExtensionss: async function () {
|
|
this.updatableExtensions.forEach(e => (e.selectedForUpdate = true))
|
|
},
|
|
updateSelectedExtensions: async function () {
|
|
let count = 0
|
|
for (const ext of this.updatableExtensions) {
|
|
try {
|
|
if (!ext.selectedForUpdate) {
|
|
continue
|
|
}
|
|
ext.inProgress = true
|
|
await LNbits.api.request(
|
|
'POST',
|
|
`/api/v1/extension`,
|
|
this.g.user.wallets[0].adminkey,
|
|
{
|
|
ext_id: ext.id,
|
|
archive: ext.latestRelease.archive,
|
|
source_repo: ext.latestRelease.source_repo,
|
|
payment_hash: ext.latestRelease.payment_hash,
|
|
version: ext.latestRelease.version
|
|
}
|
|
)
|
|
count++
|
|
ext.isAvailable = true
|
|
ext.isInstalled = true
|
|
ext.isUpgraded = true
|
|
ext.inProgress = false
|
|
ext.installedRelease = ext.latestRelease
|
|
this.toggleExtension(ext)
|
|
} catch (err) {
|
|
console.warn(err)
|
|
Quasar.Notify.create({
|
|
type: 'negative',
|
|
message: `Failed to update ${ext.code}!`
|
|
})
|
|
} finally {
|
|
ext.inProgress = false
|
|
}
|
|
}
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: `${count} extensions updated!`
|
|
})
|
|
this.showUpdateAllDialog = false
|
|
setTimeout(() => {
|
|
this.refreshRoute()
|
|
}, 2000)
|
|
}
|
|
},
|
|
created: function () {
|
|
this.extensions = window.extension_data.map(e => ({
|
|
...e,
|
|
inProgress: false,
|
|
selectedForUpdate: false
|
|
}))
|
|
this.filteredExtensions = this.extensions.concat([])
|
|
for (let i = 0; i < this.filteredExtensions.length; i++) {
|
|
if (this.filteredExtensions[i].isInstalled != false) {
|
|
this.handleTabChanged('installed')
|
|
this.tab = 'installed'
|
|
}
|
|
}
|
|
this.updatableExtensions = this.extensions.filter(ext =>
|
|
this.hasNewVersion(ext)
|
|
)
|
|
},
|
|
mixins: [windowMixin]
|
|
}
|