diff --git a/src/backend/database.cjs b/src/backend/database.cjs index c8c0b5a0..2591e192 100644 --- a/src/backend/database.cjs +++ b/src/backend/database.cjs @@ -181,6 +181,12 @@ const groupMessageTable = () => { hash TEXT UNIQUE, sent BOOLEAN )` + + try { + const update = `ALTER TABLE groupmessages ADD tip TEXT` + database.prepare(update).run() + } catch(e) { + } return new Promise( (resolve, reject) => { database.prepare(groupTable).run() @@ -423,6 +429,12 @@ const saveGroupMsg = async (msg, offchain, channels = false) => { msg.name = 'Anonymous' } + let tip = "" + + if (msg.tip) { + tip = JSON.stringify(msg.tip) + } + msg.sent = changeBool(msg.sent) try { @@ -436,17 +448,18 @@ const saveGroupMsg = async (msg, offchain, channels = false) => { name, reply, hash, - sent + sent, + tip ) VALUES - (? ,?, ?, ?, ?, ?, ?, ?, ?)` + (? ,?, ?, ?, ?, ?, ?, ?, ?, ?)` - ).run(msg.message, msg.address, '', msg.group, msg.time, msg.name, msg.reply, msg.hash, msg.sent) + ).run(msg.message, msg.address, '', msg.group, msg.time, msg.name, msg.reply, msg.hash, msg.sent, tip) } catch(a) { console.log("Sql lite", a) } - + return msg } @@ -724,7 +737,8 @@ const printGroup = async (group, page) => { name, reply, hash, - sent + sent, + tip FROM groupmessages WHERE grp = ? diff --git a/src/backend/preload.cjs b/src/backend/preload.cjs index e36628e3..b8163cab 100644 --- a/src/backend/preload.cjs +++ b/src/backend/preload.cjs @@ -169,7 +169,7 @@ const WINDOW_API = { }, sendTransaction: async (tx) => { - ipcRenderer.send('send-tx', tx) + return await ipcRenderer.invoke('send-tx', tx) }, addGroup: async (grp) => { diff --git a/src/backend/swarm.cjs b/src/backend/swarm.cjs index 490dacdd..884653b1 100644 --- a/src/backend/swarm.cjs +++ b/src/backend/swarm.cjs @@ -449,6 +449,7 @@ const check_data_message = async (data, connection, topic, peer) => { return true } if (INC_PEERS && active.peers.toString() !== data?.peers.toString()) { + if (data.peers?.length > 100) return "Ban" find_missing_peers(active, data?.peers); } const missing = await check_missed_messages(data.hashes, con.address, topic) @@ -562,7 +563,8 @@ const process_request = async (messages, key, live = false) => { g: m?.grp ? m?.grp : m?.room, r: m?.reply, n: m?.name ? m?.name : m?.nickname, - hash: m?.hash + hash: m?.hash, + tip: m?.tip } if (await roomMessageExists(inc.hash)) continue const message = sanitize_group_message(inc, false) diff --git a/src/backend/utils.cjs b/src/backend/utils.cjs index cc458ff7..4eef414d 100644 --- a/src/backend/utils.cjs +++ b/src/backend/utils.cjs @@ -204,7 +204,7 @@ const sanitize_join_swarm_data = (data) => { if (typeof screenshare !== 'boolean') return false; // if (typeof data?.avatar !== 'string') return false let avatar = "" - if (data.avatar !== undefined) { + if (data.avatar !== undefined || data.avatar?.length > 0) { avatar = Buffer.from(data.avatar, 'base64') if (avatar.length > 200000) { console.log("Avatar too big") @@ -256,6 +256,13 @@ const sanitize_join_swarm_data = (data) => { if (nick?.length > 50 || data.n === undefined) return false; let txHash = sanitizeHtml(data.hash); if (txHash?.length > 128 || data.hash === undefined) return false; + + let tip = false; + if (data.tip) { + if (typeof data.tip.amount !== 'number' || data.tip.amount?.length > 100) return false; + if (typeof data.tip.receiver !== 'string' || data.tip.receiver?.length > 100) return false; + tip = {amount: data.tip.amount, receiver: sanitizeHtml(data.tip.receiver)} + } const clean_object = { message: text, @@ -269,6 +276,7 @@ const sanitize_join_swarm_data = (data) => { sent: sent, channel: 'channel', hash: txHash, + tip }; return clean_object; @@ -298,7 +306,7 @@ const sanitize_join_swarm_data = (data) => { if (typeof screenshare !== 'boolean') return false; let avatar = "" - if (data.avatar !== undefined) { + if (data.avatar !== undefined || data.avatar?.length > 0) { const base64 = /^[A-Za-z0-9+/]+={0,2}$/; if (!base64.test(data.avatar)) { return false diff --git a/src/backend/wallet.cjs b/src/backend/wallet.cjs index ff3d2e7d..be11d643 100644 --- a/src/backend/wallet.cjs +++ b/src/backend/wallet.cjs @@ -35,8 +35,8 @@ ipcMain.on('switch-node', (e, node) => { pickNode(node) }) -ipcMain.on('send-tx', (e, tx) => { - sendTx(tx) +ipcMain.handle('send-tx', async (e, tx) => { + return await sendTx(tx) }) ipcMain.handle('verify-pass', async (e, pass) => { @@ -459,6 +459,7 @@ async function sendTx(tx) { key: tx.to, } sender('sent_tx', sent) + return true } else { console.log(`Failed to send transaction: ${result.error.toString()}`) let error = { @@ -467,6 +468,7 @@ async function sendTx(tx) { hash: Date.now(), } sender('error_msg', error) + return false } } diff --git a/src/lib/components/chat/GroupMessage.svelte b/src/lib/components/chat/GroupMessage.svelte index 44a7edf5..d8a0edda 100644 --- a/src/lib/components/chat/GroupMessage.svelte +++ b/src/lib/components/chat/GroupMessage.svelte @@ -21,6 +21,7 @@ import { roomMessages } from '$lib/stores/roommsgs' import { groupMessages } from '$lib/stores/groupmsgs' import UserOptions from '/src/routes/rooms/components/UserOptions.svelte' import PayIcon from '../icons/PayIcon.svelte' +import Tip from './Tip.svelte' export let msg export let msgFrom @@ -37,6 +38,16 @@ export let joined = false export let file = false export let room = false export let admin = false +export let tip = false + +$: tipMessage = "" +$: if (tip !== "") { + try { + tipMessage = JSON.parse(tip) + } catch(e) { + tipMessage = tip + } +} $: positionEmojiContainer(openEmoji); @@ -278,6 +289,7 @@ const check_avatar = (address) => { } const sendMoney = () => { + $rooms.replyTo.reply = false $transactions.tip = true $transactions.send = { to: msgFrom, @@ -325,7 +337,7 @@ const sendMoney = () => {
{#await check_avatar(msgFrom)} {:then avatar} - {#if avatar} + {#if avatar && room} { {:else if file && myMsg} + {:else if tip && tipMessage} + {:else}

{msg}

{/if} diff --git a/src/lib/components/chat/Tip.svelte b/src/lib/components/chat/Tip.svelte new file mode 100644 index 00000000..020530cd --- /dev/null +++ b/src/lib/components/chat/Tip.svelte @@ -0,0 +1,65 @@ + + + + +
+
+

+ Sent {prettyNumbers(tip.amount)} to {tip.receiver}! 💸 +

+
+
\ No newline at end of file diff --git a/src/routes/rooms/+page.svelte b/src/routes/rooms/+page.svelte index 28186d2b..dbfb034c 100644 --- a/src/routes/rooms/+page.svelte +++ b/src/routes/rooms/+page.svelte @@ -124,9 +124,9 @@ window.api.receive('set-channels', async () => { }) //Check for possible errors -const checkErr = (e) => { +const checkErr = (e, tip = false) => { let error = false - if (e.detail.text.length === 0) return true + if (e.detail.text.length === 0 && !tip) return true if (e.detail.text.length > 777) error = "Message is too long" if ($user.wait) error = 'Please wait a couple of minutes before sending a message.' if (!error) return false @@ -136,8 +136,8 @@ const checkErr = (e) => { } //Send message to store and DB -const sendRoomMsg = async (e) => { - const error = checkErr(e) +const sendRoomMsg = async (e, tipping = false) => { + const error = checkErr(e, tipping) if (error) return let msg = e.detail.text let myaddr = $user.myAddress @@ -147,10 +147,15 @@ const sendRoomMsg = async (e) => { let room = $swarm.activeSwarm?.key let in_swarm = true let in_channel = $swarm.activeChannel.name + let tip = false //Reaction switch if (e.detail.reply) { replyto = e.detail.reply } + + if (e.detail.tip) { + tip = e.detail.tip + } //Construct a new json object (myGroupMessage) to be able to print our message instant. let myRoomMessage = { @@ -161,7 +166,8 @@ const sendRoomMsg = async (e) => { time: time, name: myName, hash: hash, - sent: true + sent: true, + tip: tip } let sendMsg = { m: msg, @@ -172,13 +178,15 @@ const sendRoomMsg = async (e) => { n: myName, hash: hash, swarm: in_swarm, - sent: true + sent: true, + tip: tip } if (in_channel) { sendMsg.c = in_channel } - + + $transactions.pending = false window.api.sendRoomMessage(sendMsg) printRoomMessage(myRoomMessage) replyExit() @@ -314,7 +322,7 @@ async function printRoom(room, create = false) { function addFileMessage(array) { for (const msg of array) { const i = array.indexOf(msg) - if (!msg.message) { + if (!msg.message && msg.tip === "") { array[i].message = "" continue } @@ -340,7 +348,7 @@ function checkReactions(array, scroll) { //All group messages all messages except reactions filterRooms = array.filter( - (m) => m.message.length > 0 && !(m.reply.length === 64 && filterEmojis.includes(m)) + (m) => !(m.reply.length === 64 && filterEmojis.includes(m)) ) if (filterEmojis.length) { @@ -415,7 +423,7 @@ async function getMessages(group) { } async function getMoreMessages() { - return await window.api.printRoom($rooms.thisRoom?.key, pageNum) + return await window.api.printRoom($swarm.activeSwarm?.key, pageNum) } let dragover = false @@ -446,7 +454,7 @@ async function dropFile(e) { const hash = await window.api.createGroup() const message = { message: 'File shared', - grp: $rooms.thisRoom?.key, + grp: $swarm.activeSwarm?.key, name: $user.username, address: $user.myAddress, reply: "", @@ -460,7 +468,7 @@ async function dropFile(e) { } $localFiles.push(acceptedFiles[0]) printRoomMessage(message) - window.api.groupUpload(filename, path, $rooms.thisRoom?.key, size, time, hash) + window.api.groupUpload(filename, path, $swarm.activeSwarm?.key, size, time, hash) } // function setChannels() { @@ -487,11 +495,26 @@ async function dropFile(e) { // } -const sendTransaction = (e) => { +const sendTransaction = async (e) => { $transactions.tip = false $transactions.send = false let tx = e.detail - window.api.sendTransaction(tx) + $transactions.pending = tx + const sent = await window.api.sendTransaction(tx) + if (sent) { + const e = { + detail: { + text: "", + tip: { + amount: $transactions.pending.amount, + receiver: fixedRooms.find(a => a.address === $transactions.pending.to).name + } + } + } + sendRoomMsg(e, true) + } else { + $transactions.pending = false + } } const hideModal = () => { @@ -562,6 +585,7 @@ const hideModal = () => { file="{message?.file}" room="{true}" admin="{admin}" + tip="{message.tip}" /> {/each} {#if (fixedRooms.length + filterEmojis.length) > 49 && loadMore }