aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYarmo Mackenbach <yarmo@yarmo.eu>2022-04-07 10:02:30 +0200
committerYarmo Mackenbach <yarmo@yarmo.eu>2022-04-07 10:02:30 +0200
commit63ce035106841c9778fd5c5987b36549b204e5f1 (patch)
tree8a165cde838dcc74058f8f66e2dbdbb5392f9b99
parentd8d3ed7f1d5c09a0266f05e3a3c801c7175972ba (diff)
Add expense delegation, transfers
-rw-r--r--src/db.js21
-rw-r--r--src/index.js97
2 files changed, 105 insertions, 13 deletions
diff --git a/src/db.js b/src/db.js
index f97e9f0..e16c827 100644
--- a/src/db.js
+++ b/src/db.js
@@ -29,13 +29,14 @@ const write = async (obj) => {
switch (obj.type) {
case 'introduction':
case 'expense':
+ case 'transfer':
roomHash = _getHash(obj.roomId)
db.data.rooms[roomHash] ||= { events: [] }
db.data.rooms[roomHash].events.push(obj)
break
default:
- throw new Error('Invalid type for db.write()')
+ throw new Error(`Invalid type "${obj.type}" for db.write()`)
break
}
@@ -118,22 +119,30 @@ const getBalance = async (roomId) => {
data.rooms[roomHash].events.forEach((event) => {
switch (event.type) {
case 'introduction':
- balance.userIds.push(event.userId)
- balance[event.userId] = {
+ balance.userIds.push(event.data.userId)
+ balance[event.data.userId] = {
totalSpent: 0,
spentForUserId: {},
+ sentToUserId: {},
}
break
case 'expense':
- balance[event.userId].totalSpent += event.data.amount
+ balance[event.data.from].totalSpent += event.data.amount
balance.userIds.forEach((userId) => {
- balance[event.userId].spentForUserId[userId] ||= 0
- balance[event.userId].spentForUserId[userId] +=
+ balance[event.data.from].spentForUserId[userId] ||= 0
+ balance[event.data.from].spentForUserId[userId] +=
event.data.amount / balance.userIds.length
})
break
+ case 'transfer':
+ balance[event.data.from].totalSpent += event.data.amount
+ balance[event.data.from].sentToUserId[event.data.to] ||= 0
+ balance[event.data.from].sentToUserId[event.data.to] +=
+ event.data.amount
+ break
+
default:
break
}
diff --git a/src/index.js b/src/index.js
index dd92f9d..ae7cfe0 100644
--- a/src/index.js
+++ b/src/index.js
@@ -82,6 +82,11 @@ matrixClient.on('Room.timeline', async (event, room, toStartOfTimeline) => {
let users = await db.getUsers(room.roomId)
+ let from
+ let to
+ let amount
+ let description
+
switch (command) {
case 'h':
case 'help':
@@ -102,6 +107,16 @@ matrixClient.on('Room.timeline', async (event, room, toStartOfTimeline) => {
)
sendMessage(
room.roomId,
+ '!e @zaphod 42: delegate the expense',
+ '<b>!e @zaphod 42</b>: delegate the expense'
+ )
+ sendMessage(
+ room.roomId,
+ '!e 10 @trillian: transfor to a fellow user',
+ '<b>!e 10 @trillian</b>: transfor to a fellow user'
+ )
+ sendMessage(
+ room.roomId,
'!b: get the balance',
'<b>!b</b>: get the balance'
)
@@ -235,13 +250,9 @@ matrixClient.on('Room.timeline', async (event, room, toStartOfTimeline) => {
case 'e':
case 'exp':
case 'expense':
- let from
- let amount
- let description
-
if (users.includes(args[0])) {
// Use delegated sender
- from = parseFloat(args[0])
+ from = args[0]
amount = parseFloat(args[1])
description = args
.slice(2)
@@ -295,6 +306,76 @@ matrixClient.on('Room.timeline', async (event, room, toStartOfTimeline) => {
})
break
+ case 't':
+ case 'transfer':
+ if (users.includes(args[0])) {
+ // Use delegated sender
+ from = args[0]
+ amount = parseFloat(args[1])
+ to = args[2]
+ description = args
+ .slice(3)
+ .filter((a) => {
+ console.log(a, a[0])
+ return a[0] !== '?'
+ })
+ .join(' ')
+ } else {
+ // Use event sender
+ from = event.getSender()
+ amount = parseFloat(args[0])
+ to = args[1]
+ description = args
+ .slice(2)
+ .filter((a) => {
+ console.log(a, a[0])
+ return a[0] !== '?'
+ })
+ .join(' ')
+ }
+
+ // Check amount
+ if (!amount) {
+ sendMessage(
+ room.roomId,
+ '❌ That expense is invalid, need !help ?'
+ )
+ return
+ }
+
+ // Check recipient
+ if (!users.includes(to)) {
+ sendMessage(
+ room.roomId,
+ `❌ I don't know any "${to}", please try !users`
+ )
+ return
+ }
+
+ db.write({
+ type: 'transfer',
+ timestamp: event.getDate(),
+ roomId: room.roomId,
+ userId: event.getSender(),
+ data: {
+ from: from,
+ to: to,
+ amount: amount,
+ currency: 'EUR',
+ description: description,
+ },
+ })
+ .then(() => {
+ sendMessage(room.roomId, '👍 Transfer noted')
+ })
+ .catch((e) => {
+ sendMessage(
+ room.roomId,
+ `❌ Whoops, something went wrong (${e})`
+ )
+ })
+ break
+
case 'b':
case 'balance':
if (users.length === 0) {
@@ -318,12 +399,14 @@ matrixClient.on('Room.timeline', async (event, room, toStartOfTimeline) => {
const diff =
(balance[userId2].spentForUserId[userId1] || 0) -
- (balance[userId1].spentForUserId[userId2] || 0)
+ (balance[userId1].spentForUserId[userId2] || 0) +
+ (balance[userId2].sentToUserId[userId1] || 0) -
+ (balance[userId1].sentToUserId[userId2] || 0)
sendMessage(
room.roomId,
`${userId1} ${
- diff > 0 ? '→' : '←'
+ diff == 0 ? '=' : diff > 0 ? '→' : '←'
} ${userId2}: ${Math.abs(diff).toFixed(2)}`
)
}