Skip to content
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
twilio-join-sandbox.txt
config.ini.local
.env.local
devicestore.db
12 changes: 7 additions & 5 deletions Dockerfile.backend
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
FROM golang:1.24.6 AS builder
FROM golang:1.24-alpine AS builder
Comment thread
ashiven marked this conversation as resolved.
ENV CGO_ENABLED=1
RUN apk add --no-cache gcc musl-dev sqlite-dev
WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o backend main.go
RUN go build -o backend main.go

FROM gcr.io/distroless/static-debian12
FROM alpine:3.21
RUN apk add --no-cache sqlite-libs
WORKDIR /app
COPY --from=builder /app/backend .
COPY .env .
COPY config.ini .

EXPOSE 8080
CMD ["./backend"]
CMD ["./backend", "-w"]
22 changes: 12 additions & 10 deletions frontend/src/components/memberTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@ const API_BASE = import.meta.env.VITE_API_BASE || "http://localhost:8080";

interface Member {
Name: string;
Phonenumber: string;
PhoneNumber: string;
}

export default function MembersTable({ members }: { members: Member[] }) {
const [tableData, setTableData] = React.useState<Member[]>(members);
export default function MembersTable({ members = []}: { members?: Member[] }) {
const [tableData, setTableData] = React.useState<Member[]>(members ?? []);
const [open, setOpen] = React.useState(false);
const [editIndex, setEditIndex] = React.useState<number | null>(null);
const [formData, setFormData] = React.useState<Member>({
Name: "",
Phonenumber: "",
PhoneNumber: "",
});
const [nameDisabled, setNameDisabled] = React.useState(false);

React.useEffect(() => {
setTableData(members);
if (Array.isArray(members)) {
setTableData(members);
}
}, [members]);

React.useEffect(() => {
Expand Down Expand Up @@ -82,7 +84,7 @@ export default function MembersTable({ members }: { members: Member[] }) {

const startAdd = () => {
setEditIndex(null);
setFormData({ Name: "", Phonenumber: "" });
setFormData({ Name: "", PhoneNumber: "" });
setOpen(true);
setNameDisabled(false);
};
Expand Down Expand Up @@ -115,10 +117,10 @@ export default function MembersTable({ members }: { members: Member[] }) {
</tr>
</thead>
<tbody>
{tableData.map((member, index) => (
{tableData.length > 0 && tableData.map((member, index) => (
<tr key={index}>
<td>{member.Name}</td>
<td>{member.Phonenumber.slice(0, 9) + "..."}</td>
<td>{member.PhoneNumber.slice(0, 9) + "..."}</td>
<td>
<Box sx={{ display: "flex", gap: 2, flexWrap: "wrap" }}>
<Button
Expand Down Expand Up @@ -164,9 +166,9 @@ export default function MembersTable({ members }: { members: Member[] }) {
/>
<Input
placeholder="Telefonnummer"
value={formData.Phonenumber}
value={formData.PhoneNumber}
onChange={(e) =>
setFormData({ ...formData, Phonenumber: e.target.value })
setFormData({ ...formData, PhoneNumber: e.target.value })
}
/>
<Button color="success" onClick={saveEdit}>
Expand Down
14 changes: 8 additions & 6 deletions frontend/src/components/taskTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const API_BASE = import.meta.env.VITE_API_BASE || "http://localhost:8080";

interface Member {
Name: string;
Phonenumber: string;
PhoneNumber: string;
}

interface Task {
Expand All @@ -22,12 +22,12 @@ interface Task {

export default function TaskTable({
id,
tasks,
tasks = [],
}: {
id: string;
tasks: Task[];
tasks?: Task[];
}) {
const [tableData, setTableData] = React.useState<Task[]>(tasks);
const [tableData, setTableData] = React.useState<Task[]>(tasks ?? []);
const [open, setOpen] = React.useState(false);
const [editIndex, setEditIndex] = React.useState<number | null>(null);
const [formData, setFormData] = React.useState<Task>({
Expand All @@ -36,7 +36,9 @@ export default function TaskTable({
});

React.useEffect(() => {
setTableData(tasks);
if (Array.isArray(tasks)) {
setTableData(tasks);
}
}, [tasks]);

React.useEffect(() => {
Expand Down Expand Up @@ -124,7 +126,7 @@ export default function TaskTable({
</tr>
</thead>
<tbody>
{tableData.map((task, index) => (
{tableData.length > 0 && tableData.map((task, index) => (
<tr key={index}>
<td>{task.Name}</td>
<td>{task.Assignee?.Name ?? ""}</td>
Expand Down
23 changes: 23 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,37 @@ module household-planner
go 1.24.6

require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/beeper/argo-go v1.1.2 // indirect
github.com/bigkevmcd/go-configparser v0.0.0-20250311182818-a679eef33309 // indirect
github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.32 // indirect
github.com/mdp/qrterminal/v3 v3.2.1 // indirect
github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/rs/zerolog v1.34.0 // indirect
github.com/twilio/twilio-go v1.27.0 // indirect
github.com/vektah/gqlparser/v2 v2.5.30 // indirect
go.mau.fi/libsignal v0.2.0 // indirect
go.mau.fi/util v0.9.0 // indirect
go.mau.fi/whatsmeow v0.0.0-20250905121447-8d6da61ecbfa // indirect
golang.org/x/crypto v0.42.0 // indirect
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/term v0.35.0 // indirect
golang.org/x/text v0.29.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
rsc.io/qr v0.2.0 // indirect
)
53 changes: 53 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/beeper/argo-go v1.1.2 h1:UQI2G8F+NLfGTOmTUI0254pGKx/HUU/etbUGTJv91Fs=
github.com/beeper/argo-go v1.1.2/go.mod h1:M+LJAnyowKVQ6Rdj6XYGEn+qcVFkb3R/MUpqkGR0hM4=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/bigkevmcd/go-configparser v0.0.0-20250311182818-a679eef33309 h1:h2H7P1M0rXm8LTJMhZWr3SAleTmR6vg+7PM1BkTumaw=
github.com/bigkevmcd/go-configparser v0.0.0-20250311182818-a679eef33309/go.mod h1:vzEQfW+A1T+AMJmTIX+SXNLNECHOM7GEinHhw0IjykI=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg=
github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
Expand All @@ -19,23 +31,51 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275/go.mod h1:zt6UU74K6Z6oMOYJbJzYpYucqdcQwSMPBEdSvGiaUMw=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4=
github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 h1:QTvNkZ5ylY0PGgA+Lih+GdboMLY/G9SEGLMEGVjTVA4=
github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/twilio/twilio-go v1.27.0 h1:XmxS8jrNbTj4dKsgkpCFKKr0AvQt7FMix2AA0mXWa1s=
github.com/twilio/twilio-go v1.27.0/go.mod h1:FpgNWMoD8CFnmukpKq9RNpUSGXC0BwnbeKZj2YHlIkw=
github.com/vektah/gqlparser/v2 v2.5.30 h1:EqLwGAFLIzt1wpx1IPpY67DwUujF1OfzgEyDsLrN6kE=
github.com/vektah/gqlparser/v2 v2.5.30/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
go.mau.fi/libsignal v0.2.0 h1:oRXj3OHhEJq51BFEM8/50UZblmWiTYH93hsNTPcbk90=
go.mau.fi/libsignal v0.2.0/go.mod h1:tvjoDsMejgT38CXTXwqaYu8itBiY8O2Mb6biWvZBb9k=
go.mau.fi/util v0.9.0 h1:ya3s3pX+Y8R2fgp0DbE7a0o3FwncoelDX5iyaeVE8ls=
go.mau.fi/util v0.9.0/go.mod h1:pdL3lg2aaeeHIreGXNnPwhJPXkXdc3ZxsI6le8hOWEA=
go.mau.fi/whatsmeow v0.0.0-20250905121447-8d6da61ecbfa h1:+77BnZUz3DVMHPUil1YFc2spz7dtuqHaEt2nzWVgX0s=
go.mau.fi/whatsmeow v0.0.0-20250905121447-8d6da61ecbfa/go.mod h1:Xn2RtGFtEJPCAr56wsWpauBIQAC0S0+v81iyKmrd708=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
Expand All @@ -53,13 +93,22 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 h1:3doPGa+Gg4snce233aCWnbZVFsyFMo/dR40KK/6skyE=
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
Expand All @@ -68,6 +117,10 @@ golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=
52 changes: 46 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package main

import (
"context"
"fmt"
"household-planner/pkg/backend"
"household-planner/pkg/planner"
"os"
"slices"
"time"

"github.com/kr/pretty"
"go.mau.fi/whatsmeow/proto/waE2E"
"google.golang.org/protobuf/proto"
)

func main() {
fmt.Println("[INFO] Starting Household Planner...")
debug := len(os.Args) > 1 && os.Args[1] == "-d"
debug := len(os.Args) > 1 && slices.Contains(os.Args, "-d")
useWhatsApp := len(os.Args) > 1 && slices.Contains(os.Args, "-w")

myHousehold, err := planner.NewHousehold()
if err != nil {
Expand All @@ -24,7 +31,6 @@ func main() {
for {
if debug {
fmt.Println("[DEBUG] Starting next day in one minute...: ")
// fmt.Printf("%# v\n", pretty.Formatter(myHousehold))
time.Sleep(1 * time.Minute)
} else {
planner.WaitUntilNoon()
Expand All @@ -38,10 +44,44 @@ func main() {
myHousehold.AssignWeeklyTasks()
myHousehold.AssignMonthlyTasks()

client := planner.InitializeTwilioClient()
for _, member := range myHousehold.Members {
assignedTasks := myHousehold.GetAssignedTasks(member)
planner.SendMessageSms(client, member, assignedTasks, debug)
// Send messages via whatsmeow
if useWhatsApp {
client := planner.NewWhatsmeowClient()

// NOTE: Needs QR Login via terminal on first startup
planner.Login(client)
time.Sleep(time.Second * 30)
Comment thread
ashiven marked this conversation as resolved.

phoneNumbers := myHousehold.PhoneNumbers()
JIDs := planner.PhoneNumbersToJIDs(client, phoneNumbers)
Comment on lines +49 to +56
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error handling from NewWhatsmeowClient(), Login(), and PhoneNumbersToJIDs() is absent. Since these functions don't return errors (though they should), the code continues execution even if initialization fails. This could lead to nil pointer dereferences or unexpected behavior when trying to send messages.

Copilot uses AI. Check for mistakes.
Comment on lines +49 to +56
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The WhatsApp client is being created, authenticated, and phone numbers are being checked on every iteration of the infinite loop (daily). This is inefficient and wasteful - client initialization, login, and phone number verification should be performed once before entering the loop, not on every day's task assignment. Consider moving lines 49-56 outside the loop.

Copilot uses AI. Check for mistakes.

for _, member := range myHousehold.Members {
assignedTasks := myHousehold.GetAssignedTasks(member)
message := planner.CreateDailyTaskMessage(assignedTasks, member)

if debug {
pretty.Println("[DEBUG] member: ", member)
pretty.Println("[DEBUG] phoneNumber: ", member.PhoneNumber)
pretty.Println("[DEBUG] JID: ", JIDs[member.PhoneNumber])
pretty.Println("[DEBUG] message: ", message)

} else {
JID := JIDs[member.PhoneNumber]
waMessage := &waE2E.Message{Conversation: proto.String(message)}
_, err := client.SendMessage(context.Background(), JID, waMessage)
if err != nil {
fmt.Printf("[ERROR] Failed to deliver message to %s.\n", member.Name)
}
}
Comment on lines +69 to +75
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a phone number is not on WhatsApp, an empty JID (types.JID{}) is stored in the map (line 82 in whatsmeow.go). In the message sending loop, this empty JID is then used to attempt sending a message without any validation. This will likely cause SendMessage to fail. Consider checking if the JID is valid before attempting to send, or filtering out members without valid JIDs.

Copilot uses AI. Check for mistakes.
}

// Send messages via twilio sms
} else {
client := planner.InitializeTwilioClient()
for _, member := range myHousehold.Members {
assignedTasks := myHousehold.GetAssignedTasks(member)
planner.SendMessageSms(client, member, assignedTasks, debug)
}
}
}
}
2 changes: 1 addition & 1 deletion pkg/backend/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func getMembers(w http.ResponseWriter, r *http.Request) {

func updateMembers(w http.ResponseWriter, r *http.Request) {
handleUpdate(w, r, "Members", func(member *planner.Member) {
household.Config.Set("Members", member.Name, member.Phonenumber)
household.Config.Set("Members", member.Name, member.PhoneNumber)
}, func(updatedMembers []*planner.Member) {
household.Members = updatedMembers
})
Expand Down
Loading