Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update to lnbits 1.0.0 #21

Merged
merged 6 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Streamer Copilot",
"short_description": "Video tips/animations/webhooks",
"tile": "/copilot/static/bitcoin-streaming.png",
"min_lnbits_version": "0.12.6",
"min_lnbits_version": "1.0.0",
"contributors": [
{
"name": "Ben Arc",
Expand Down
88 changes: 17 additions & 71 deletions crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,89 +8,35 @@
db = Database("ext_copilot")


async def create_copilot(data: CreateCopilotData, inkey: Optional[str] = "") -> Copilot:
async def create_copilot(data: CreateCopilotData) -> Copilot:
copilot_id = urlsafe_short_hash()
await db.execute(
"""
INSERT INTO copilot.newer_copilots (
id,
"user",
lnurl_toggle,
wallet,
title,
animation1,
animation2,
animation3,
animation1threshold,
animation2threshold,
animation3threshold,
animation1webhook,
animation2webhook,
animation3webhook,
lnurl_title,
show_message,
show_ack,
show_price,
fullscreen_cam,
iframe_url,
amount_made
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
copilot_id,
data.user,
int(data.lnurl_toggle),
data.wallet,
data.title,
data.animation1,
data.animation2,
data.animation3,
data.animation1threshold,
data.animation2threshold,
data.animation3threshold,
data.animation1webhook,
data.animation2webhook,
data.animation3webhook,
data.lnurl_title,
int(data.show_message),
int(data.show_ack),
data.show_price,
0,
None,
0,
),
)
copilot = await get_copilot(copilot_id)
assert copilot, "Newly created copilot couldn't be retrieved"
copilot = Copilot(id=copilot_id, **data.dict())
await db.insert("copilot.newer_copilots", copilot)
return copilot


async def update_copilot(data: CreateCopilotData, copilot_id: str) -> Copilot:
q = ", ".join([f"{field[0]} = ?" for field in data])
items = [f"{field[1]}" for field in data]
items.append(copilot_id)
await db.execute(f"UPDATE copilot.newer_copilots SET {q} WHERE id = ?", (items,))
row = await db.fetchone(
"SELECT * FROM copilot.newer_copilots WHERE id = ?", (copilot_id,)
)
assert row, "Updated copilot couldn't be retrieved"
return Copilot(**row)
async def update_copilot(copilot: Copilot) -> Copilot:
await db.update("copilot.newer_copilots", copilot)
return copilot


async def get_copilot(copilot_id: str) -> Optional[Copilot]:
row = await db.fetchone(
"SELECT * FROM copilot.newer_copilots WHERE id = ?", (copilot_id,)
return await db.fetchone(
"SELECT * FROM copilot.newer_copilots WHERE id = :id",
{"id": copilot_id},
Copilot,
)
return Copilot(**row) if row else None


async def get_copilots(user: str) -> List[Copilot]:
rows = await db.fetchall(
'SELECT * FROM copilot.newer_copilots WHERE "user" = ?', (user,)
return await db.fetchall(
'SELECT * FROM copilot.newer_copilots WHERE "user" = :user',
{"user": user},
Copilot,
)
return [Copilot(**row) for row in rows]


async def delete_copilot(copilot_id: str) -> None:
await db.execute("DELETE FROM copilot.newer_copilots WHERE id = ?", (copilot_id,))
await db.execute(
"DELETE FROM copilot.newer_copilots WHERE id = :id", {"id": copilot_id}
)
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2,198 changes: 1,161 additions & 1,037 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = ["Alan Bits <alan@lnbits.com>"]

[tool.poetry.dependencies]
python = "^3.10 | ^3.9"
lnbits = "*"
lnbits = {version = "*", allow-prereleases = true}

[tool.poetry.group.dev.dependencies]
black = "^24.3.0"
Expand Down
260 changes: 260 additions & 0 deletions static/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
const mapCopilot = obj => {
obj._data = _.clone(obj)

obj.theTime = obj.time * 60 - (Date.now() / 1000 - obj.timestamp)
obj.time = obj.time + 'mins'

if (obj.time_elapsed) {
obj.date = 'Time elapsed'
} else {
obj.date = Quasar.date.formatDate(
new Date((obj.theTime - 3600) * 1000),
'HH:mm:ss'
)
}
obj.displayComposeUrl = ['/copilot/cp/', obj.id].join('')
obj.displayPanelUrl = ['/copilot/', obj.id].join('')
return obj
}

window.app = Vue.createApp({
el: '#vue',
mixins: [windowMixin],
data() {
return {
filter: '',
copilotLinks: [],
copilotLinksObj: [],
copilotsTable: {
columns: [
{
name: 'theId',
align: 'left',
label: 'id',
field: 'id'
},
{
name: 'lnurl_toggle',
align: 'left',
label: 'Show lnurl pay link',
field: 'lnurl_toggle'
},
{
name: 'title',
align: 'left',
label: 'title',
field: 'title'
},
{
name: 'amount_made',
align: 'left',
label: 'amount made',
field: 'amount_made'
}
],
pagination: {
rowsPerPage: 10
}
},
passedCopilot: {},
formDialog: {
show: false,
data: {}
},
formDialogCopilot: {
show: false,
data: {
lnurl_toggle: false,
show_message: false,
show_ack: false,
show_price: 'None',
title: ''
}
},
qrCodeDialog: {
show: false,
data: null
},
options: ['bitcoin', 'confetti', 'rocket', 'face', 'martijn', 'rick'],
currencyOptions: ['None', 'btcusd', 'btceur', 'btcgbp']
}
},
methods: {
cancelCopilot(data) {
this.formDialogCopilot.show = false
this.clearFormDialogCopilot()
},
closeFormDialog() {
this.clearFormDialogCopilot()
this.formDialog.data = {
lnurl_toggle: false,
show_message: false,
show_ack: false,
show_price: 'None',
title: ''
}
},
sendFormDataCopilot() {
if (this.formDialogCopilot.data.id) {
this.updateCopilot(
this.g.user.wallets[0].adminkey,
this.formDialogCopilot.data
)
} else {
this.createCopilot(
this.g.user.wallets[0].adminkey,
this.formDialogCopilot.data
)
}
},

createCopilot(wallet, data) {
const updatedData = {}
for (const property in data) {
if (data[property]) {
updatedData[property] = data[property]
}
if (property == 'animation1threshold' && data[property]) {
updatedData[property] = parseInt(data[property])
}
if (property == 'animation2threshold' && data[property]) {
updatedData[property] = parseInt(data[property])
}
if (property == 'animation3threshold' && data[property]) {
updatedData[property] = parseInt(data[property])
}
}

LNbits.api
.request('POST', '/copilot/api/v1/copilot', wallet, updatedData)
.then(response => {
this.copilotLinks.push(mapCopilot(response.data))
this.formDialogCopilot.show = false
this.clearFormDialogCopilot()
})
.catch(LNbits.utils.notifyApiError)
},
getCopilots() {
LNbits.api
.request('GET', '/copilot/api/v1/copilot', this.g.user.wallets[0].inkey)
.then(response => {
if (response.data) {
this.copilotLinks = response.data.map(mapCopilot)
}
})
.catch(LNbits.utils.notifyApiError)
},
getCopilot(copilot_id) {
LNbits.api
.request(
'GET',
'/copilot/api/v1/copilot/' + copilot_id,
this.g.user.wallets[0].inkey
)
.then(response => {
localStorage.setItem('copilot', JSON.stringify(response.data))
localStorage.setItem('inkey', this.g.user.wallets[0].inkey)
})
.catch(LNbits.utils.notifyApiError)
},
openCopilotCompose(copilot_id) {
this.getCopilot(copilot_id)
let params =
'scrollbars=no, resizable=no,status=no,location=no,toolbar=no,menubar=no,width=1200,height=644,left=410,top=100'
open('../copilot/cp/', '_blank', params)
},
openCopilotPanel(copilot_id) {
this.getCopilot(copilot_id)
let params =
'scrollbars=no, resizable=no,status=no,location=no,toolbar=no,menubar=no,width=300,height=450,left=10,top=400'
open('../copilot/pn/', '_blank', params)
},
deleteCopilotLink(copilotId) {
const link = _.findWhere(this.copilotLinks, {id: copilotId})
LNbits.utils
.confirmDialog('Are you sure you want to delete this pay link?')
.onOk(() => {
LNbits.api
.request(
'DELETE',
'/copilot/api/v1/copilot/' + copilotId,
this.g.user.wallets[0].adminkey
)
.then(response => {
this.copilotLinks = _.reject(this.copilotLinks, function (obj) {
return obj.id === copilotId
})
})
.catch(LNbits.utils.notifyApiError)
})
},
openUpdateCopilotLink(copilotId) {
const copilot = _.findWhere(this.copilotLinks, {id: copilotId})
this.formDialogCopilot.data = {...copilot._data}
this.formDialogCopilot.data.lnurl_toggle = Boolean(
this.formDialogCopilot.data.lnurl_toggle
)
this.formDialogCopilot.data.show_message = Boolean(
this.formDialogCopilot.data.show_message
)
this.formDialogCopilot.data.show_ack = Boolean(
this.formDialogCopilot.data.show_ack
)
this.formDialogCopilot.show = true
},
updateCopilot(wallet, data) {
const updatedData = {}

const updateThreshold = property => {
if (data[property] && data[property] !== 0) {
updatedData[property] = parseInt(data[property])
}
}

for (const property in data) {
if (data[property]) {
updatedData[property] = data[property]
}
switch (property) {
case 'animation1threshold':
case 'animation2threshold':
case 'animation3threshold':
updateThreshold(property)
break
}
}

LNbits.api
.request(
'PUT',
'/copilot/api/v1/copilot/' + updatedData.id,
wallet,
updatedData
)
.then(response => {
this.copilotLinks = _.reject(this.copilotLinks, function (obj) {
return obj.id === updatedData.id
})
this.copilotLinks.push(mapCopilot(response.data))
this.formDialogCopilot.show = false
this.clearFormDialogCopilot()
})
.catch(LNbits.utils.notifyApiError)
},
clearFormDialogCopilot() {
this.formDialogCopilot.data = {
lnurl_toggle: false,
show_message: false,
show_ack: false,
show_price: 'None',
title: ''
}
},
exportcopilotCSV() {
LNbits.utils.exportCSV(this.copilotsTable.columns, this.copilotLinks)
}
},
created() {
this.getCopilots()
}
})
Loading