i forgor to commit sorry

This commit is contained in:
2026-04-06 11:04:53 +01:00
parent 60d6a287e5
commit ce83000e0c
12 changed files with 327 additions and 55 deletions
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 666 B

After

Width:  |  Height:  |  Size: 910 B

+9 -3
View File
@@ -4,6 +4,8 @@ go 1.25.5
require ( require (
github.com/BurntSushi/toml v1.6.0 github.com/BurntSushi/toml v1.6.0
github.com/boxes-ltd/imaging v1.7.5
github.com/crazy3lf/colorconv v1.2.0
github.com/diamondburned/gotk4/pkg v0.3.1 github.com/diamondburned/gotk4/pkg v0.3.1
github.com/gen2brain/beeep v0.11.2 github.com/gen2brain/beeep v0.11.2
github.com/go-analyze/charts v0.5.24 github.com/go-analyze/charts v0.5.24
@@ -12,6 +14,10 @@ require (
github.com/jasonlovesdoggo/gopen v0.0.0-20250130105607-39c98c645030 github.com/jasonlovesdoggo/gopen v0.0.0-20250130105607-39c98c645030
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
github.com/kr/pretty v0.2.0 github.com/kr/pretty v0.2.0
github.com/mskrha/svg2png v0.0.0-20240706085601-64fa78f4eb07
github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
golang.org/x/net v0.29.0 golang.org/x/net v0.29.0
gosrc.io/xmpp v0.5.1 gosrc.io/xmpp v0.5.1
mellium.im/xmpp v0.22.0 mellium.im/xmpp v0.22.0
@@ -33,10 +39,10 @@ require (
github.com/sergeymakinen/go-ico v1.0.0-beta.0 // indirect github.com/sergeymakinen/go-ico v1.0.0-beta.0 // indirect
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 // indirect
golang.org/x/image v0.24.0 // indirect golang.org/x/image v0.36.0 // indirect
golang.org/x/sync v0.11.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.30.0 // indirect golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.34.0 // indirect
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 // indirect golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 // indirect
mellium.im/reader v0.1.0 // indirect mellium.im/reader v0.1.0 // indirect
mellium.im/xmlstream v0.15.4 // indirect mellium.im/xmlstream v0.15.4 // indirect
+22 -10
View File
@@ -5,12 +5,16 @@ github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2
github.com/KarpelesLab/weak v0.1.1 h1:fNnlPo3aypS9tBzoEQluY13XyUfd/eWaSE/vMvo9s4g= github.com/KarpelesLab/weak v0.1.1 h1:fNnlPo3aypS9tBzoEQluY13XyUfd/eWaSE/vMvo9s4g=
github.com/KarpelesLab/weak v0.1.1/go.mod h1:pzXsWs5f2bf+fpgHayTlBE1qJpO3MpJKo5sRaLu1XNw= github.com/KarpelesLab/weak v0.1.1/go.mod h1:pzXsWs5f2bf+fpgHayTlBE1qJpO3MpJKo5sRaLu1XNw=
github.com/agnivade/wasmbrowsertest v0.3.1/go.mod h1:zQt6ZTdl338xxRaMW395qccVE2eQm0SjC/SDz0mPWQI= github.com/agnivade/wasmbrowsertest v0.3.1/go.mod h1:zQt6ZTdl338xxRaMW395qccVE2eQm0SjC/SDz0mPWQI=
github.com/boxes-ltd/imaging v1.7.5 h1:k4kYxJEhysoGhEEN1IEeKoSbnG8/8snjj7M48Ok0fnk=
github.com/boxes-ltd/imaging v1.7.5/go.mod h1:+8H+oRvis3InOFtTpcoCCB1RDXqo6p9tQBtjZfWnrC8=
github.com/chromedp/cdproto v0.0.0-20190614062957-d6d2f92b486d/go.mod h1:S8mB5wY3vV+vRIzf39xDXsw3XKYewW9X6rW2aEmkrSw= github.com/chromedp/cdproto v0.0.0-20190614062957-d6d2f92b486d/go.mod h1:S8mB5wY3vV+vRIzf39xDXsw3XKYewW9X6rW2aEmkrSw=
github.com/chromedp/cdproto v0.0.0-20190621002710-8cbd498dd7a0/go.mod h1:S8mB5wY3vV+vRIzf39xDXsw3XKYewW9X6rW2aEmkrSw= github.com/chromedp/cdproto v0.0.0-20190621002710-8cbd498dd7a0/go.mod h1:S8mB5wY3vV+vRIzf39xDXsw3XKYewW9X6rW2aEmkrSw=
github.com/chromedp/cdproto v0.0.0-20190812224334-39ef923dcb8d/go.mod h1:0YChpVzuLJC5CPr+x3xkHN6Z8KOSXjNbL7qV8Wc4GW0= github.com/chromedp/cdproto v0.0.0-20190812224334-39ef923dcb8d/go.mod h1:0YChpVzuLJC5CPr+x3xkHN6Z8KOSXjNbL7qV8Wc4GW0=
github.com/chromedp/cdproto v0.0.0-20190926234355-1b4886c6fad6/go.mod h1:0YChpVzuLJC5CPr+x3xkHN6Z8KOSXjNbL7qV8Wc4GW0= github.com/chromedp/cdproto v0.0.0-20190926234355-1b4886c6fad6/go.mod h1:0YChpVzuLJC5CPr+x3xkHN6Z8KOSXjNbL7qV8Wc4GW0=
github.com/chromedp/chromedp v0.3.1-0.20190619195644-fd957a4d2901/go.mod h1:mJdvfrVn594N9tfiPecUidF6W5jPRKHymqHfzbobPsM= github.com/chromedp/chromedp v0.3.1-0.20190619195644-fd957a4d2901/go.mod h1:mJdvfrVn594N9tfiPecUidF6W5jPRKHymqHfzbobPsM=
github.com/chromedp/chromedp v0.4.0/go.mod h1:DC3QUn4mJ24dwjcaGQLoZrhm4X/uPHZ6spDbS2uFhm4= github.com/chromedp/chromedp v0.4.0/go.mod h1:DC3QUn4mJ24dwjcaGQLoZrhm4X/uPHZ6spDbS2uFhm4=
github.com/crazy3lf/colorconv v1.2.0 h1:UM7kSZWnwFMGiC+PpYrjxQSOd6sEyWb+dRKKTd3KslA=
github.com/crazy3lf/colorconv v1.2.0/go.mod h1:2jTJ7QCWCj2sSLOhF4Gzi0J5/hoX8/VY8VzNvXAlD1I=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -80,6 +84,8 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mskrha/svg2png v0.0.0-20240706085601-64fa78f4eb07 h1:7fan6wzUXasMPMHho2ePSkB+QTEb0Rh/f6B+IkkP1Sc=
github.com/mskrha/svg2png v0.0.0-20240706085601-64fa78f4eb07/go.mod h1:KFdfdIgpr48ODxdkxKvpcYwuyLpQ6rfkAsFB2UQ6jD4=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -89,6 +95,8 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d h1:l3+2LWCbVxn5itfvXAfH9n4YL9jh8l1g5zcncbIc1cs=
github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d/go.mod h1:TbpErkob6SY7cyozRVSGoB3OlO2qOAgVN8O3KAJ4fMI=
github.com/sergeymakinen/go-bmp v1.0.0 h1:SdGTzp9WvCV0A1V0mBeaS7kQAwNLdVJbmHlqNWq0R+M= github.com/sergeymakinen/go-bmp v1.0.0 h1:SdGTzp9WvCV0A1V0mBeaS7kQAwNLdVJbmHlqNWq0R+M=
github.com/sergeymakinen/go-bmp v1.0.0/go.mod h1:/mxlAQZRLxSvJFNIEGGLBE/m40f3ZnUifpgVDlcUIEY= github.com/sergeymakinen/go-bmp v1.0.0/go.mod h1:/mxlAQZRLxSvJFNIEGGLBE/m40f3ZnUifpgVDlcUIEY=
github.com/sergeymakinen/go-ico v1.0.0-beta.0 h1:m5qKH7uPKLdrygMWxbamVn+tl2HfiA3K6MFJw4GfZvQ= github.com/sergeymakinen/go-ico v1.0.0-beta.0 h1:m5qKH7uPKLdrygMWxbamVn+tl2HfiA3K6MFJw4GfZvQ=
@@ -97,6 +105,10 @@ github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjM
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -123,11 +135,11 @@ golang.org/x/crypto v0.0.0-20180426230345-b49d69b5da94/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= golang.org/x/image v0.36.0 h1:Iknbfm1afbgtwPTmHnS2gTM/6PPZfH+z2EFuOkSbqwc=
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= golang.org/x/image v0.36.0/go.mod h1:YsWD2TyyGKiIX1kZlu9QfKIsQ4nAAK9bdgdrIsE7xy4=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -137,8 +149,8 @@ golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -152,14 +164,14 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
+72 -10
View File
@@ -1,13 +1,22 @@
package main package main
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"github.com/boxes-ltd/imaging"
"github.com/crazy3lf/colorconv"
"github.com/diamondburned/gotk4/pkg/gdk/v4" "github.com/diamondburned/gotk4/pkg/gdk/v4"
"github.com/diamondburned/gotk4/pkg/gdkpixbuf/v2"
"github.com/diamondburned/gotk4/pkg/glib/v2" "github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/diamondburned/gotk4/pkg/gtk/v4" "github.com/diamondburned/gotk4/pkg/gtk/v4"
"github.com/diamondburned/gotk4/pkg/pango" "github.com/diamondburned/gotk4/pkg/pango"
"github.com/rrivera/identicon"
"gosrc.io/xmpp/stanza" "gosrc.io/xmpp/stanza"
"image"
"image/png"
xmpp_color "mellium.im/xmpp/color"
"strconv"
) )
func scrollToBottomAfterUpdate(scrolledWindow *gtk.ScrolledWindow) { func scrollToBottomAfterUpdate(scrolledWindow *gtk.ScrolledWindow) {
@@ -62,7 +71,7 @@ func switchToTab(jid string, w *gtk.Window) {
gen := gtk.NewBox(gtk.OrientationVertical, 0) gen := gtk.NewBox(gtk.OrientationVertical, 0)
i := 0 i := 0
mm.Range(func(k, v any) bool { rangeOrdered(&mm, (func(k, v any) bool {
i++ i++
userbox := gtk.NewBox(gtk.OrientationHorizontal, 0) userbox := gtk.NewBox(gtk.OrientationHorizontal, 0)
@@ -71,6 +80,13 @@ func switchToTab(jid string, w *gtk.Window) {
var ocu OccupantID var ocu OccupantID
u.Get(&mu) u.Get(&mu)
u.Get(&ocu) u.Get(&ocu)
if mu.MucUserItem.Role == "moderator" {
gen.Prepend(userbox)
} else {
gen.Append(userbox)
}
//id := ocu.ID //id := ocu.ID
//if id == "" { //if id == "" {
id := JidMustParse(u.From).Resource id := JidMustParse(u.From).Resource
@@ -90,7 +106,29 @@ func switchToTab(jid string, w *gtk.Window) {
ok := u.Get(&hats) ok := u.Get(&hats)
if ok { if ok {
for _, hat := range hats.Hats { for _, hat := range hats.Hats {
tag := gtk.NewImageFromPaintable(clientAssets["tag"]) var val float64
if hat.Hue != "" {
tval, _ := strconv.Atoi(hat.Hue)
val = float64(tval)
} else {
xc := xmpp_color.String(hat.URI, 255, loadedConfig.CVD)
r, g, b, _ := xc.RGBA()
val, _, _ = colorconv.RGBToHSV(uint8(r), uint8(g), uint8(b))
}
tB := tagBytes
img, _, _ := image.Decode(bytes.NewReader(tB))
i_rgba := imaging.AdjustHue(img, val)
var buf bytes.Buffer
png.Encode(&buf, i_rgba)
tB = buf.Bytes()
loader := gdkpixbuf.NewPixbufLoader()
loader.Write(tB)
loader.Close()
tag := gtk.NewPictureForPaintable(gdk.NewTextureForPixbuf(loader.Pixbuf()))
tag.SetTooltipText(hat.Title) tag.SetTooltipText(hat.Title)
userbox.Prepend(tag) userbox.Prepend(tag)
} }
@@ -262,10 +300,12 @@ func switchToTab(jid string, w *gtk.Window) {
win.SetTitle(JidMustParse(u.From).Resource) win.SetTitle(JidMustParse(u.From).Resource)
nick.AddCSSClass("author") nick.AddCSSClass("author")
nick.SetSelectable(true)
profile_box.Append(nick) profile_box.Append(nick)
profile_box.Append(ver_text) profile_box.Append(ver_text)
fr := gtk.NewLabel(u.From) fr := gtk.NewLabel(u.From)
fr.AddCSSClass("jid") fr.AddCSSClass("jid")
fr.SetSelectable(true)
profile_box.Append(fr) profile_box.Append(fr)
profile_box.Append(ver_text) profile_box.Append(ver_text)
@@ -300,6 +340,7 @@ func switchToTab(jid string, w *gtk.Window) {
if mu.MucUserItem.JID != "" { if mu.MucUserItem.JID != "" {
ji := (gtk.NewLabel(mu.MucUserItem.JID)) ji := (gtk.NewLabel(mu.MucUserItem.JID))
ji.AddCSSClass("jid") ji.AddCSSClass("jid")
ji.SetSelectable(true)
profile_box.Append(ji) profile_box.Append(ji)
} }
profile_box.Append(gtk.NewLabel("Connected with role " + mu.MucUserItem.Role)) profile_box.Append(gtk.NewLabel("Connected with role " + mu.MucUserItem.Role))
@@ -397,13 +438,13 @@ func switchToTab(jid string, w *gtk.Window) {
im.AddCSSClass("author_img") im.AddCSSClass("author_img")
profile_box.Prepend(im) profile_box.Prepend(im)
} else { } else {
im := gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) im := createIdenticon(u.From)
im.SetPixelSize(80) im.SetPixelSize(80)
im.AddCSSClass("author_img") im.AddCSSClass("author_img")
profile_box.Prepend(im) profile_box.Prepend(im)
} }
} else { } else {
im := gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) im := createIdenticon(u.From)
im.SetPixelSize(80) im.SetPixelSize(80)
im.AddCSSClass("author_img") im.AddCSSClass("author_img")
profile_box.Prepend(im) profile_box.Prepend(im)
@@ -418,13 +459,8 @@ func switchToTab(jid string, w *gtk.Window) {
userbox.AddController(gesture) userbox.AddController(gesture)
userbox.AddController(mod_gesture) userbox.AddController(mod_gesture)
if mu.MucUserItem.Role == "moderator" {
gen.Prepend(userbox)
} else {
gen.Append(userbox)
}
return true return true
}) }))
headerBox := gtk.NewBox(gtk.OrientationHorizontal, 0) headerBox := gtk.NewBox(gtk.OrientationHorizontal, 0)
if i >= 500 { if i >= 500 {
@@ -450,3 +486,29 @@ func switchToTab(jid string, w *gtk.Window) {
func showErrorDialog(err error) { func showErrorDialog(err error) {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
func createIdenticon(word string) *gtk.Image { // This function generates an identicon
if !loadedConfig.Identicons {
i := gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"])
i.AddCSSClass(loadedConfig.CVD.String()+"_CVD")
return i
}
gen, _ := identicon.New("github", 5, 3)
ii, _ := gen.Draw(word)
im := ii.Image(25)
buf := new(bytes.Buffer)
err := png.Encode(buf, im)
if err != nil {
panic(err)
}
loader := gdkpixbuf.NewPixbufLoader()
loader.Write(buf.Bytes())
loader.Close()
i := gtk.NewImageFromPaintable(gdk.NewTextureForPixbuf(loader.Pixbuf()))
i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
return i
}
+25 -12
View File
@@ -16,6 +16,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
) )
func generatePresenceWidget(p stanza.Packet) gtk.Widgetter { func generatePresenceWidget(p stanza.Packet) gtk.Widgetter {
@@ -67,7 +68,7 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter {
if ok { if ok {
b := gtk.NewBox(gtk.OrientationHorizontal, 0) b := gtk.NewBox(gtk.OrientationHorizontal, 0)
b.Append(gtk.NewLabel(fmt.Sprintf("%s is typing...", JidMustParse(m.From).Resource))) b.Append(gtk.NewLabel(fmt.Sprintf("%s is typing...", JidMustParse(m.From).Resource)))
return b return b
} }
if m.Error.Type != "" { if m.Error.Type != "" {
@@ -95,7 +96,7 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter {
rc_box := gtk.NewBox(gtk.OrientationVertical, 0) rc_box := gtk.NewBox(gtk.OrientationVertical, 0)
reactions := gtk.NewBox(gtk.OrientationHorizontal, 0) reactions := gtk.NewBox(gtk.OrientationHorizontal, 0)
reaction := []string{"👍", "👎", "♥️", "🤣", "😭"} reaction := []string{"👍", "👎", "♥️", "🤣", "💀"}
for _, v := range reaction { for _, v := range reaction {
like := gtk.NewButton() like := gtk.NewButton()
like.SetLabel(v) like.SetLabel(v)
@@ -117,7 +118,15 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter {
quote := gtk.NewButtonWithLabel("Quote") quote := gtk.NewButtonWithLabel("Quote")
quote.ConnectClicked(func() { quote.ConnectClicked(func() {
message_en.SetText("> " + m.Body + "\n") lines := strings.Split(m.Body, "\n")
for i, line := range lines {
quoteline:= "> " + line
lines[i] = quoteline
}
newstr := strings.Join(lines, "\n") + "\n\n"
message_en.SetText(newstr)
}) })
rc_box.Append(quote) rc_box.Append(quote)
@@ -170,13 +179,13 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter {
im.AddCSSClass("author_img") im.AddCSSClass("author_img")
authorBox.Append(im) authorBox.Append(im)
} else { } else {
im := gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) im := createIdenticon(m.From)
im.SetPixelSize(40) im.SetPixelSize(40)
im.AddCSSClass("author_img") im.AddCSSClass("author_img")
authorBox.Append(im) authorBox.Append(im)
} }
} else { } else {
im := gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) im := createIdenticon(m.From)
im.SetPixelSize(40) im.SetPixelSize(40)
im.AddCSSClass("author_img") im.AddCSSClass("author_img")
authorBox.Append(im) authorBox.Append(im)
@@ -251,25 +260,27 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou
oghash := hash oghash := hash
p, err := ensureCache() p, err := ensureCache()
if err != nil { if err != nil {
return gtk.NewImageFromPaintable(clientAssets["FailedAvatar"]) return createIdenticon(j)
} }
if hash == "" { if hash == "" {
fmt.Println("Hash is nil!") fmt.Println("Hash is nil!")
return gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) return createIdenticon(j)
} }
_, ok := invalidImages[hash] _, ok := invalidImages[hash]
if ok { if ok {
fmt.Println("Image is invalid") fmt.Println("Image is invalid")
return gtk.NewImageFromPaintable(clientAssets["FailedAvatar"]) return createIdenticon(j)
} }
hash = filepath.Join(p, sanitizefilename.Sanitize(hash)) hash = filepath.Join(p, sanitizefilename.Sanitize(hash))
_, err = os.ReadFile(hash) _, err = os.ReadFile(hash)
if err == nil { if err == nil {
return newImageFromPath(hash) i := newImageFromPath(hash)
i.AddCSSClass(loadedConfig.CVD.String()+"_CVD")
return i
} }
iqResp, err := stanza.NewIQ(stanza.Attrs{ iqResp, err := stanza.NewIQ(stanza.Attrs{
@@ -294,14 +305,14 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou
result := <-mychan result := <-mychan
card, ok := result.Payload.(*VCard) card, ok := result.Payload.(*VCard)
if !ok { if !ok {
return gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) return createIdenticon(j)
} }
base64_data := card.Photo.Binval base64_data := card.Photo.Binval
if card.Photo.Binval == "" || ((card.Photo.Type == "image/svg+xml" || card.Photo.Type == "image/webp") && (runtime.GOOS == "windows" || runtime.GOOS == "netbsd")) { if card.Photo.Binval == "" || ((card.Photo.Type == "image/svg+xml" || card.Photo.Type == "image/webp") && (runtime.GOOS == "windows" || runtime.GOOS == "netbsd")) {
fmt.Println("Blocking image") fmt.Println("Blocking image")
invalidImages[oghash] = true invalidImages[oghash] = true
return gtk.NewImageFromPaintable(clientAssets["FailedAvatar"]) return createIdenticon(j)
} }
data, err := base64.StdEncoding.DecodeString(base64_data) data, err := base64.StdEncoding.DecodeString(base64_data)
@@ -314,5 +325,7 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou
panic(err) panic(err)
} }
return newImageFromPath(hash) i := newImageFromPath(hash)
i.AddCSSClass(loadedConfig.CVD.String()+"_CVD")
return i
} }
+26
View File
@@ -0,0 +1,26 @@
// Generic helpers
package main
import (
"sync"
"sort"
)
func rangeOrdered(m *sync.Map, fn func(k, v any) bool) {
var keys []string
m.Range(func(k, v any) bool {
keys = append(keys, k.(string))
return true
})
sort.Strings(keys)
for _, k := range keys {
v, _ := m.Load(k)
if !fn(k, v) {
break
}
}
}
+106 -11
View File
@@ -40,6 +40,8 @@ var connectionIcon *gtk.Image
var mStatus *gtk.Label var mStatus *gtk.Label
var mIcon *gtk.Image var mIcon *gtk.Image
var typingStatus *gtk.Label
var pingStatus *gtk.Label var pingStatus *gtk.Label
// var msgs *gtk.ListBox // var msgs *gtk.ListBox
@@ -225,7 +227,9 @@ func main() {
if ok { if ok {
if JidMustParse(fm.From).Bare() == JidMustParse(m.From).Bare() { if JidMustParse(fm.From).Bare() == JidMustParse(m.From).Bare() {
p = sc.Forwarded.Stanza p = sc.Forwarded.Stanza
orig := m.To
m = sc.Forwarded.Stanza.(stanza.Message) m = sc.Forwarded.Stanza.(stanza.Message)
m.To = orig
} else { } else {
panic(fmt.Sprintln("Impersonation: ", fm.From, m.From)) panic(fmt.Sprintln("Impersonation: ", fm.From, m.From))
} }
@@ -245,6 +249,19 @@ func main() {
} }
} }
} }
composing := stanza.StateComposing{}
ok = m.Get(&composing)
if ok && current == JidMustParse(m.From).Bare() {
typingStatus.SetText(fmt.Sprintf("%s is typing...", m.From))
return
}
inactive := stanza.StateInactive{}
ok = m.Get(&inactive)
if ok && current == JidMustParse(m.From).Bare() {
typingStatus.SetText("")
return
}
glib.IdleAdd(func() { glib.IdleAdd(func() {
//uiQueue <- func() { //uiQueue <- func() {
@@ -674,22 +691,97 @@ func activate(app *gtk.Application) {
btn.ConnectClicked(func() { btn.ConnectClicked(func() {
t := jid_entry.Text() t := jid_entry.Text()
_, ok := tabs.Load(t) _, ok := tabs.Load(t)
jm := func() {
err := joinMuc(client, clientroot.Session.BindJid, t, nick_entry.Text())
if err != nil {
panic(err)
}
createTab(t, true)
b := gtk.NewLabel(t)
gesture1 := gtk.NewGestureClick()
gesture1.SetButton(1)
gesture1.Connect("pressed", func() {
switchToTab(t, &window.Window)
})
b.AddController(gesture1)
menu.Append(b)
}
if !ok { if !ok {
err := joinMuc(client, clientroot.Session.BindJid, t, nick_entry.Text()) // First check the MUC's disco and see if it's semianon
allowed := true
fmt.Println("Attempting to get Disco info")
myIQ, err := stanza.NewIQ(stanza.Attrs{
Type: "get",
From: clientroot.Session.BindJid,
To: t,
Id: "dicks",
Lang: "en",
})
if err != nil { if err != nil {
panic(err) panic(err)
} }
createTab(t, true) myIQ.Payload = &stanza.DiscoInfo{}
b := gtk.NewLabel(t)
gesture1 := gtk.NewGestureClick()
gesture1.SetButton(1)
gesture1.Connect("pressed", func() {
switchToTab(t, &window.Window)
})
b.AddController(gesture1) ctx := context.TODO()
menu.Append(b) mychan, err := client.SendIQ(ctx, myIQ)
if err == nil {
result := <-mychan
res, ok := result.Payload.(*stanza.DiscoInfo)
if ok {
semianon := false
features := res.Features
for _, feature := range features {
if feature.Var == "muc_nonanonymous" {
semianon = false
break
} else if feature.Var == "muc_semianonymous" {
semianon = true
break
}
}
if !semianon {
allowed = false
warning_win := gtk.NewWindow()
warning_win.SetTitle("Warning")
warning_win.SetDefaultSize(400, 400)
warning_win.SetResizable(false)
warning_box := gtk.NewBox(gtk.OrientationVertical, 0)
warning_label := gtk.NewLabel("This muc is not semi-anonymous. Your JID will be revealed to non-moderators if you join. Continue?")
buttons := gtk.NewBox(gtk.OrientationHorizontal, 0)
join_button := gtk.NewButtonWithLabel("Join")
join_button.ConnectClicked(func() {
warning_win.SetVisible(false)
jm()
})
cancel_button := gtk.NewButtonWithLabel("Cancel")
cancel_button.ConnectClicked(func() {
warning_win.SetVisible(false)
})
buttons.Append(join_button)
buttons.Append(cancel_button)
warning_box.Append(warning_label)
warning_box.Append(buttons)
warning_win.SetChild(warning_box)
warning_win.Present()
}
}
}
if allowed {
jm()
}
} }
win.SetVisible(false) win.SetVisible(false)
}) })
@@ -884,7 +976,7 @@ func activate(app *gtk.Application) {
end := start + len("@everyone") end := start + len("@everyone")
new_mention := new(Mention) new_mention := new(Mention)
new_mention.Type = "urn:xmpp:mentions:0#channel" new_mention.Mentions = "urn:xmpp:mentions:0#channel"
new_mention.Begin = start new_mention.Begin = start
new_mention.End = end new_mention.End = end
@@ -915,6 +1007,9 @@ func activate(app *gtk.Application) {
box.Append(entry_box) box.Append(entry_box)
typingStatus = gtk.NewLabel("")
box.Append(typingStatus)
window.SetChild(box) window.SetChild(box)
window.SetVisible(true) window.SetVisible(true)
+12
View File
@@ -61,3 +61,15 @@
color: white; color: white;
background-color: red; background-color: red;
} }
.RedGreen_CVD {
filter: hue-rotate(30deg) saturate(120%) contrast(110%);
}
.Blue_CVD {
filter: hue-rotate(30deg);
}
.None_CVD {
}
+40
View File
@@ -0,0 +1,40 @@
package main
import (
"bytes"
"fmt"
"image"
"image/png"
"github.com/srwiley/oksvg"
"github.com/srwiley/rasterx"
)
func SVGToPNG(svgData []byte) ([]byte, error) {
// Parse SVG
icon, err := oksvg.ReadIconStream(bytes.NewReader(svgData))
if err != nil {
return nil, fmt.Errorf("failed to parse SVG: %w", err)
}
w := int(icon.ViewBox.W)
h := int(icon.ViewBox.H)
if w == 0 || h == 0 {
w, h = 100, 100
}
// Rasterize into an RGBA image
rgba := image.NewRGBA(image.Rect(0, 0, w, h))
scanner := rasterx.NewScannerGV(w, h, rgba, rgba.Bounds())
dasher := rasterx.NewDasher(w, h, scanner)
icon.SetTarget(0, 0, float64(w), float64(h))
icon.Draw(dasher, 1.0)
// Encode to PNG bytes
var buf bytes.Buffer
if err := png.Encode(&buf, rgba); err != nil {
return nil, fmt.Errorf("failed to encode PNG: %w", err)
}
return buf.Bytes(), nil
}
+1
View File
@@ -20,6 +20,7 @@ type lambdaConfig struct {
Nick string Nick string
JoinBookmarks bool JoinBookmarks bool
CVD color.CVD CVD color.CVD
Identicons bool
} }
type mucUnit struct { type mucUnit struct {
+1 -1
View File
@@ -1,3 +1,3 @@
package main package main
var lambda_version string = "26w11a" var lambda_version string = "26w15a"
+13 -8
View File
@@ -5,17 +5,22 @@ import (
"gosrc.io/xmpp/stanza" "gosrc.io/xmpp/stanza"
) )
// Experimental implementation of XEP-XXXX: Explicit Mentions // Implementation of XEP-0513: Explicit Mentions
// https://git.isekai.rocks/snit/protoxeps/tree/explicit-mentions.xml // https://xmpp.org/extensions/xep-0513.html
type NoPing struct{}
type Active struct{}
type Mention struct { type Mention struct {
stanza.MsgExtension stanza.MsgExtension
XMLName xml.Name `xml:"urn:xmpp:mentions:0 mention"` XMLName xml.Name `xml:"urn:xmpp:mentions:0 mention"`
URI string `xml:"uri,attr,omitempty"` URI string `xml:"uri,attr,omitempty"`
Begin int `xml:"begin,attr,omitempty"` Begin int `xml:"begin,attr,omitempty"`
End int `xml:"end,attr,omitempty"` End int `xml:"end,attr,omitempty"`
Type string `xml:"type,attr"` Mentions string `xml:"mentions,attr"`
Target string `xml:"target,attr,omitempty"` OccupantID string `xml:"occupantid,attr,omitempty"`
NoPing NoPing `xml:"noping,omitempty"`
Active Active `xml:"active,omitempty"`
} }
func init() { func init() {