Add rendering forms to messages, add configuring mucs, add getting muc affiliations, add a bunch of other stuff idk man check the diff

This commit is contained in:
Sunglocto committed 2026-10-11 12:08:38 +01:00
1 parent 7a875f84a5
commit 34b885a770
19 files changed
+669 -64

No files matched your search

+4
View File
@@ -208,6 +208,9 @@ var yaximCapBytes []byte
//go:embed assets/client_icons/psi.png
var psiCapBytes []byte
//go:embed assets/client_icons/spark.png
var sparkCapBytes []byte
var clientAssets sync.Map
func loadAsset(key string, data []byte) {
@@ -299,6 +302,7 @@ func init() {
"https://movim.eu/": movimCapBytes,
"https://yaxim.org/": yaximCapBytes,
"https://psi-im.org": psiCapBytes,
"https://igniterealtime.org/projects/smack": sparkCapBytes,
} {
loadAsset(key, data)
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

+5
View File
@@ -14,6 +14,7 @@ const (
// See XEP-0004 and XEP-0068
// Pointer semantics
type Form struct {
MsgExtension
XMLName xml.Name `xml:"jabber:x:data x"`
Instructions []string `xml:"instructions"`
Title string `xml:"title,omitempty"`
@@ -66,3 +67,7 @@ type Option struct {
Label string `xml:"label,attr,omitempty"`
ValuesList []string `xml:"value"`
}
func init() {
TypeRegistry.MapExtension(PKTMessage, xml.Name{Space: "jabber:x:data", Local: "x"}, Form{})
}
+1 -1
View File
@@ -10,7 +10,7 @@ type Attrs struct {
Id string `xml:"id,attr,omitempty"`
From string `xml:"from,attr,omitempty"`
To string `xml:"to,attr,omitempty"`
Lang string `xml:"lang,attr,omitempty"`
Lang string `xml:"xml:lang,attr,omitempty"`
}
type packetFormatter interface {
+22 -2
View File
@@ -1,6 +1,6 @@
module lambda-im
go 1.25.5
go 1.26.0
require (
github.com/BurntSushi/toml v1.6.0
@@ -16,16 +16,28 @@ require (
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
github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c
gosrc.io/xmpp v0.5.1
mellium.im/xmpp v0.23.0
)
require (
codeberg.org/go-pdf/fpdf v0.12.0 // indirect
git.sr.ht/~jackmordaunt/go-toast v1.1.2 // indirect
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 // indirect
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 // indirect
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc // indirect
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 // indirect
github.com/ByteArena/poly2tri-go v0.0.0-20170716161910-d102ad91854f // indirect
github.com/andybalholm/brotli v1.2.2 // indirect
github.com/benoitkugler/textlayout v0.3.2 // indirect
github.com/benoitkugler/textprocessing v0.0.6 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/esiqveland/notify v0.14.0 // indirect
github.com/go-analyze/bulk v0.1.5 // indirect
github.com/go-fonts/latin-modern v0.3.3 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-text/typesetting v0.3.4 // indirect
github.com/godbus/dbus/v5 v5.2.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/jackmordaunt/icns/v3 v3.0.1 // indirect
@@ -34,16 +46,24 @@ require (
github.com/rogpeppe/go-internal v1.16.0 // indirect
github.com/sergeymakinen/go-bmp v1.0.0 // indirect
github.com/sergeymakinen/go-ico v1.0.0 // indirect
github.com/srwiley/scanx v0.0.0-20190309010443-e94503791388 // indirect
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect
github.com/tdewolff/font v0.0.0-20260822205238-d0d2f004b117 // indirect
github.com/tdewolff/minify/v2 v2.24.17 // indirect
github.com/tdewolff/parse/v2 v2.8.16 // indirect
github.com/yuin/goldmark v1.8.5 // indirect
golang.org/x/image v0.45.0 // indirect
golang.org/x/net v0.57.0 // indirect
golang.org/x/net v0.58.0 // indirect
golang.org/x/sync v0.22.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/text v0.41.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
mellium.im/reader v0.1.0 // indirect
mellium.im/xmlstream v0.15.4 // indirect
modernc.org/knuth v0.6.0 // indirect
modernc.org/token v1.1.0 // indirect
nhooyr.io/websocket v1.8.17 // indirect
star-tex.org/x/tex v0.7.1 // indirect
)
replace gosrc.io/xmpp => ./go-xmpp/
+83 -9
View File
@@ -1,14 +1,43 @@
codeberg.org/go-fonts/liberation v0.6.0 h1:15Gh6SdwYve22CWCm9jYpVpRuaTh726av2TgHTHvAtQ=
codeberg.org/go-fonts/liberation v0.6.0/go.mod h1:J15VAa+lyxdcI/Je7lDDDl6QOhLk9feNBnnwXqEHXOk=
codeberg.org/go-latex/latex v0.3.0 h1:LKTaDHFbEC2PH1sh0sYv6PZ1pzs/g2aoeV1HItWj/bg=
codeberg.org/go-latex/latex v0.3.0/go.mod h1:8ETijTpK2bFtwRAXLXe1RZJrYxnc5pibibZfQBj+Lk4=
codeberg.org/go-pdf/fpdf v0.12.0 h1:g8E/1VqGqB2lZUUaqQrrTnA0IEJLPTTX1DZ0qS/ZmhU=
codeberg.org/go-pdf/fpdf v0.12.0/go.mod h1:WJNJ2bvCj81rZBdhOf7lKOGoSl+OKMXcIcXqDcP8r5Y=
git.sr.ht/~jackmordaunt/go-toast v1.1.2 h1:/yrfI55LRt1M7H1vkaw+NaH1+L1CDxrqDltwm5euVuE=
git.sr.ht/~jackmordaunt/go-toast v1.1.2/go.mod h1:jA4OqHKTQ4AFBdwrSnwnskUIIS3HYzlJSgdzCKqfavo=
git.sr.ht/~sbinet/cmpimg v0.1.0 h1:E0zPRk2muWuCqSKSVZIWsgtU9pjsw3eKHi8VmQeScxo=
git.sr.ht/~sbinet/cmpimg v0.1.0/go.mod h1:FU12psLbF4TfNXkKH2ZZQ29crIqoiqTZmeQ7dkp/pxE=
git.sr.ht/~sbinet/gg v0.8.0 h1:PjQ4AgUWRz7Dy6PVBKMLLg96eRCos1U+H6F3FJuKWHo=
git.sr.ht/~sbinet/gg v0.8.0/go.mod h1:XhlGCvSXts+BaZ1XMZLxLSFUDvwsJ/2El5F6XzPep6o=
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 h1:1qlsVAQJXZHsaM8b6OLVo6muQUQd4CwkH/D3fnnbHXA=
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ=
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 h1:lTG4HQym5oPKjL7nGs+csTgiDna685ZXjxijkne828g=
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0=
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc h1:7D+Bh06CRPCJO3gr2F7h1sriovOZ8BMhca2Rg85c2nk=
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 h1:O/r2Sj+8QcMF7V5IcmiE2sMFV2q3J47BEirxbXJAdzA=
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k=
github.com/ByteArena/poly2tri-go v0.0.0-20170716161910-d102ad91854f h1:l7moT9o/v/9acCWA64Yz/HDLqjcRTvc0noQACi4MsJw=
github.com/ByteArena/poly2tri-go v0.0.0-20170716161910-d102ad91854f/go.mod h1:vIOkSdX3NDCPwgu8FIuTat2zDF0FPXXQ0RYFRy+oQic=
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw=
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
github.com/andybalholm/brotli v1.2.2 h1:HzTuoo2ErYQqf5qvcJInB8uvqSVxRttzkFexPWtnceM=
github.com/andybalholm/brotli v1.2.2/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/benoitkugler/pstokenizer v1.0.0/go.mod h1:l1G2Voirz0q/jj0TQfabNxVsa8HZXh/VMxFSRALWTiE=
github.com/benoitkugler/textlayout v0.3.2 h1:Y/LTkwpQ9G0Fia9yhPmZA9IR5AnE8Cq30j3C+Gx5/IE=
github.com/benoitkugler/textlayout v0.3.2/go.mod h1:o+1hFV+JSHBC9qNLIuwVoLedERU7sBPgEFcuSgfvi/w=
github.com/benoitkugler/textlayout-testdata v0.1.1/go.mod h1:i/qZl09BbUOtd7Bu/W1CAubRwTWrEXWq6JwMkw8wYxo=
github.com/benoitkugler/textprocessing v0.0.6 h1:obkMyj62GEPg3xUVYqROlCN22z1OleuZm6ULqX9Om1g=
github.com/benoitkugler/textprocessing v0.0.6/go.mod h1:Io0gN08/PXEzrSOWFa88xHx2Xv3VjvLMY7H76YoI23A=
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/crazy3lf/colorconv v1.2.0 h1:UM7kSZWnwFMGiC+PpYrjxQSOd6sEyWb+dRKKTd3KslA=
github.com/crazy3lf/colorconv v1.2.0/go.mod h1:2jTJ7QCWCj2sSLOhF4Gzi0J5/hoX8/VY8VzNvXAlD1I=
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/diamondburned/gotk4/pkg v0.4.1 h1:w4BwVUUBkKyNLz5HKHN2Oz3kZCTLHfpfKgB/su1p6uo=
github.com/diamondburned/gotk4/pkg v0.4.1/go.mod h1:BAEEDXtj5srQ1S2++5HX2K1s9c6CtuWSa60dAywrkRM=
@@ -22,8 +51,14 @@ github.com/go-analyze/bulk v0.1.5 h1:Zj8w3gEOhEnp8aRZ7DHMDqaG3/Bp7CvQ7pu6Mw9YhFc
github.com/go-analyze/bulk v0.1.5/go.mod h1:afon/KtFJYnekIyN20H/+XUvcLFjE8sKR1CfpqfClgM=
github.com/go-analyze/charts v0.6.0 h1:aBE2cbdr58faYGwPk3RUzGQMyg5fGsSAxepwYTYmvhg=
github.com/go-analyze/charts v0.6.0/go.mod h1:m8hqGNSpYYdMMc0Im/RCowY9CIA7705jiltuOVQZWuI=
github.com/go-fonts/latin-modern v0.3.3 h1:g2xNgI8yzdNzIVm+qvbMryB6yGPe0pSMss8QT3QwlJ0=
github.com/go-fonts/latin-modern v0.3.3/go.mod h1:tHaiWDGze4EPB0Go4cLT5M3QzRY3peya09Z/8KSCrpY=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-text/typesetting v0.3.4 h1:YYurUOtEb9kGSOz4uE3k4OpBGsp1dDL8+fjCeaFamAU=
github.com/go-text/typesetting v0.3.4/go.mod h1:4qZCQphq4KSgGTAeI0uMEkVbROgfah8BuyF5LRYr7XY=
github.com/go-text/typesetting-utils v0.0.0-20260223113751-2d88ac90dae3 h1:drBZzMgdYPbmyXqOto4YhhJGrFIQCX94FpR4MzTCsos=
github.com/go-text/typesetting-utils v0.0.0-20260223113751-2d88ac90dae3/go.mod h1:3/62I4La/HBRX9TcTpBj4eipLiwzf+vhI+7whTc9V7o=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
@@ -46,8 +81,9 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
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/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
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.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/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.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g=
github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
@@ -61,38 +97,68 @@ github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiY
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/srwiley/scanFT v0.0.0-20220128184157-0d1ee492111f h1:uLR2GaV0kWYZ3Ns3l3sjtiN+mOWAQadvrL8HXcyKjl0=
github.com/srwiley/scanFT v0.0.0-20220128184157-0d1ee492111f/go.mod h1:LZwgIPG9X6nH6j5Ef+xMFspl6Hru4b5EJxzMfeqHYJY=
github.com/srwiley/scanx v0.0.0-20190309010443-e94503791388 h1:ZdkidVdpLW13BQ9a+/3uerT2ezy9J7KQWH18JCfhDmI=
github.com/srwiley/scanx v0.0.0-20190309010443-e94503791388/go.mod h1:C/WY5lmWfMtPFYYBTd3Lzdn4FTLr+RxlIeiBNye+/os=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c h1:eXJXpQAo8l0AdVnsjJctG38GlBnHnwHfhLOTLYxZYNE=
github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c/go.mod h1:K9Ux3cwFtyAFRITZ46g7v+ORXgI3ENtQa5rL9yjNz5Y=
github.com/tdewolff/font v0.0.0-20260822205238-d0d2f004b117 h1:5vSJjsbV9AH0U+Ex0uej8ROrpOBlOVBrw0mGlVef7oo=
github.com/tdewolff/font v0.0.0-20260822205238-d0d2f004b117/go.mod h1:ipESUihcEdgRBhIwTRHmBTOMamccMQrp4iCxfa1aFws=
github.com/tdewolff/minify/v2 v2.24.17 h1:6AbitfVyq0M7aW6i+XL7+49DeTQZwloOMs9O574arBg=
github.com/tdewolff/minify/v2 v2.24.17/go.mod h1:kVqn9vxXUKtlHexSNrWbYePqioOT5mc4ou/KVSMpfCM=
github.com/tdewolff/parse/v2 v2.8.16 h1:bLk5svUOQRkW/Y2SJ+DeENSIkZBcTIkq+Atyv5D8feI=
github.com/tdewolff/parse/v2 v2.8.16/go.mod h1:XdsoSFThlVIRIajAuqz1evNY7bagZS8LBOPA3aVopwQ=
github.com/tdewolff/test v1.0.12 h1:7F21DqIajswxuche0geHdrUZRCWE4oko4b7bcmkkrxk=
github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA=
github.com/yuin/goldmark v1.8.5/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.45.0 h1:FMb1nTbH5H9vF55SriQHgFw5GnNL9Jg6L25BwXKzhB0=
golang.org/x/image v0.45.0/go.mod h1:n62x/7RqlwXDvGsSU4u6IUTUf6KghUZ9Bt7cG/T9Fx4=
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
gonum.org/v1/plot v0.17.0 h1:d0DwPVBe9jnEGqQBoZGl/P2M9WciJbG2CnV59C9QBT4=
gonum.org/v1/plot v0.17.0/go.mod h1:ipt2GUN1oqzr2O7wCjLDtw1ShfIYYNBp4o0O1Ez5B3Y=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mellium.im/reader v0.1.0 h1:UUEMev16gdvaxxZC7fC08j7IzuDKh310nB6BlwnxTww=
mellium.im/reader v0.1.0/go.mod h1:F+X5HXpkIfJ9EE1zHQG9lM/hO946iYAmU7xjg5dsQHI=
@@ -102,5 +168,13 @@ mellium.im/xmlstream v0.15.4 h1:gLKxcWl4rLMUpKgtzrTBvr4OexPeO/edYus+uK3F6ZI=
mellium.im/xmlstream v0.15.4/go.mod h1:yXaCW2++fmVO4L9piKVkyLDqnCmictVYF7FDQW8prb4=
mellium.im/xmpp v0.23.0 h1:rvKvOvMdIURCLaAWEJN8J0QpO3AJYCDKjxLsqtTPSjY=
mellium.im/xmpp v0.23.0/go.mod h1:GHDKlKKQe0LNmD9YqExyxnFEEBiz84KGqnfiA2VNzb8=
modernc.org/knuth v0.6.0 h1:zLv0hzgdcpcCUB/iMwpQvn9m/iciqO/hyNXlpWymMKU=
modernc.org/knuth v0.6.0/go.mod h1:ISAZV+URZIlE8h1BwNVg1NzpwHKndV5lQ13NPPj3tds=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y=
nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
star-tex.org/x/tex v0.7.1 h1:4qGAByRyY0WQsOjtcHlxz+FgrYxz8fzxIds2Gjepp5U=
star-tex.org/x/tex v0.7.1/go.mod h1:Y3y0U7sZTltTh/CDZIx0oAtMjG7eMaTuTtvDZGdyhJo=
+222 -5
View File
@@ -7,7 +7,10 @@ import (
"image"
"image/color"
"image/png"
"slices"
"strconv"
"strings"
_ "sync"
"github.com/boxes-ltd/imaging"
"github.com/crazy3lf/colorconv"
@@ -77,7 +80,11 @@ func showUserWindow(u stanza.Presence, custom_nick string) {
win.SetTitle(JidMustParse(u.From).Resource)
nick.AddCSSClass("author")
nick.SetSelectable(true)
profile_box.Append(nick)
nbox := gtk.NewBox(gtk.OrientationHorizontal, 5)
nbox.SetHAlign(gtk.AlignCenter)
nbox.Append(nick)
profile_box.Append(nbox)
if u.Status != "" {
status_message := gtk.NewLabel(u.Status)
status_message.AddCSSClass("status")
@@ -128,6 +135,7 @@ func showUserWindow(u stanza.Presence, custom_nick string) {
if ok {
for _, hat := range hats.Hats {
l := gtk.NewLabel(hat.Title)
l.SetSelectable(true)
l.AddCSSClass("hat")
profile_box.Append(l)
}
@@ -141,6 +149,11 @@ func showUserWindow(u stanza.Presence, custom_nick string) {
ji.AddCSSClass("jid")
ji.SetSelectable(true)
profile_box.Append(ji)
if JidMustParse(mu.MucUserItem.JID).Bare() == JidMustParse(clientroot.Session.BindJid).Bare() {
you_label := gtk.NewLabel("(You)")
you_label.AddCSSClass("you")
nbox.Append(you_label)
}
}
profile_box.Append(gtk.NewLabel(loadedLocale["connectedWithRole"] + mu.MucUserItem.Role))
var affil string
@@ -308,7 +321,7 @@ func createTab(jid string, isMuc bool, name string) bool {
})
newTab.name = name
newTab.msg_refsID = make(map[string]*abMessage)
newTab.msg_refsOSID = make(map[string]*abMessage)
//newTab.msg_refsOSID = make(map[string]*abMessage)
tabs.Store(jid, newTab)
return true
}
@@ -785,11 +798,215 @@ func showErrorDialog(err error, w *gtk.Window) {
err_win.Present()
}
func showDialog(s string, w *gtk.Window) {
err_win := gtk.NewWindow()
err_win.SetTitle("Information")
err_win.SetDefaultSize(400, 200)
err_win.SetResizable(false)
box := gtk.NewBox(gtk.OrientationVertical, 0)
err_label := gtk.NewLabel(s)
err_label.SetSelectable(true)
box.Append(err_label)
close_btn := gtk.NewButtonWithLabel(loadedLocale["close"])
close_btn.ConnectClicked(func() {
err_win.Destroy()
})
box.Append(close_btn)
err_win.SetChild(box)
err_win.SetTransientFor(w)
err_win.Present()
}
func showFormDialog(f stanza.Form) (*stanza.Form, gtk.Window, string) {
form_type := ""
var ret *stanza.Form = &f
form_win := gtk.NewWindow()
form_win.SetTitle(f.Title)
form_win.SetDefaultSize(400, 400)
form_win.SetResizable(false)
form_box := gtk.NewBox(gtk.OrientationVertical, 2)
for _, instruction := range f.Instructions {
form_box.Append(gtk.NewLabel(instruction))
}
// for x, item := range f.Items {
for y, field := range f.Fields {
if field.Var == "FORM_TYPE" {
form_type = field.ValuesList[0]
}
field_box := gtk.NewBox(gtk.OrientationHorizontal, 2)
field_label := gtk.NewLabel(field.Label)
field_label.SetTooltipText(field.Description)
btn_box := gtk.NewBox(gtk.OrientationVertical, 0)
btn_box.SetHAlign(gtk.AlignEnd)
btn_box.SetHExpand(true)
switch field.Type {
case "boolean":
if len(field.ValuesList) == 0 {
field.ValuesList = append(field.ValuesList, "0")
f.Fields[y].ValuesList = append(f.Fields[y].ValuesList, "0")
}
tick := gtk.NewCheckButton()
if field.ValuesList[0] == "1" {
tick.SetActive(true)
} else {
tick.SetActive(false)
}
tick.ConnectToggled(func() {
str := ""
if tick.Active() {
str = "1"
} else {
str = "0"
}
f.Fields[y].ValuesList[0] = str
})
btn_box.Append(tick)
case "fixed":
for _, v := range field.ValuesList {
label := gtk.NewLabel(v)
label.AddCSSClass("visitor")
btn_box.SetHAlign(gtk.AlignCenter)
btn_box.Append(label)
}
case "hidden":
// do nothing
case "jid-multi":
// TODO
case "jid-single":
e_box := gtk.NewBox(gtk.OrientationHorizontal, 0)
jid_entry := gtk.NewEntry()
jid_entry.SetText(field.ValuesList[0])
buildAJIDButton := gtk.NewImageFromPaintable(clientAssetsLoad("jabber"))
buildAJIDButton.Connect("pressed", func() {
jidBuilder(jid_entry)
})
jid_entry.ConnectChanged(func() {
f.Fields[y].ValuesList[0] = jid_entry.Text()
})
e_box.Append(buildAJIDButton)
e_box.Append(jid_entry)
btn_box.Append(e_box)
case "list-multi":
// TODO
case "list-single":
var selected uint
str := []string{}
for i, option := range field.Options {
if slices.Equal(option.ValuesList, field.ValuesList) {
selected = uint(i)
}
str = append(str, option.ValuesList[0])
}
dropdown := gtk.NewDropDownFromStrings(str)
dropdown.SetSelected(selected)
dropdown.ConnectActivate(func() {
f.Fields[y].ValuesList[0] = field.Options[dropdown.Selected()].ValuesList[0]
})
btn_box.Append(dropdown)
case "text-private":
p_entry := gtk.NewPasswordEntry()
p_entry.SetText(field.ValuesList[0])
p_entry.ConnectChanged(func() {
f.Fields[y].ValuesList[0] = p_entry.Text()
})
btn_box.Append(p_entry)
case "text-multi":
textView := gtk.NewTextView()
textView.SetWrapMode(gtk.WrapWordChar)
txt := ""
for i, line := range field.ValuesList {
txt = txt + line
if i != len(field.ValuesList)-1 {
txt = txt + "\n"
}
}
textView.Buffer().SetText(txt)
textView.Buffer().ConnectChanged(func() {
txt := textView.Buffer().Text(textView.Buffer().StartIter(), textView.Buffer().EndIter(), false)
f.Fields[y].ValuesList = strings.Split(txt, "\n")
})
scroll := gtk.NewScrolledWindow()
scroll.SetChild(textView)
scroll.SetMinContentHeight(150)
btn_box.Append(scroll)
default: // includes text-single
en := gtk.NewEntry()
txt := ""
if len(field.ValuesList) != 0 {
txt = field.ValuesList[0]
}
en.SetText(txt)
en.ConnectChanged(func() {
if len(field.ValuesList) == 0 {
f.Fields[y].ValuesList = append(f.Fields[y].ValuesList, en.Text())
} else {
f.Fields[y].ValuesList[0] = en.Text()
}
})
btn_box.Append(en)
}
field_box.Append(field_label)
field_box.Append(btn_box)
form_box.Append(field_box)
}
form_box.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
btn_box := gtk.NewBox(gtk.OrientationHorizontal, 0)
btn_box.SetHAlign(gtk.AlignCenter)
cancelbtn := gtk.NewButtonWithLabel("Cancel")
cancelbtn.ConnectClicked(func() {
form_win.Close()
})
okbtn := gtk.NewButtonWithLabel(loadedLocale["submit"])
okbtn.ConnectClicked(func() {
ret = &f
form_win.Close()
})
btn_box.Append(okbtn)
btn_box.Append(cancelbtn)
form_box.Append(btn_box)
form_win.SetChild(form_box)
form_win.SetVisible(true)
return ret, *form_win, form_type
}
func createIdenticon(word string, always_create bool, i *gtk.Image) { // This function generates an identicon
if !loadedConfig.Identicons && !always_create {
// return gtk.NewImageFromPaintable(clientAssetsLoad("DefaultAvatar"))
glib.IdleAdd(func() {
i.SetFromPaintable(clientAssetsLoad("DefaultAvatar"))
p := clientAssetsLoad("DefaultAvatar")
glib.IdleAddPriority(glib.PriorityLow, func() {
i.SetFromPaintable(p)
})
return
}
@@ -814,7 +1031,7 @@ func createIdenticon(word string, always_create bool, i *gtk.Image) { // This fu
p := loader.Pixbuf()
gt := gdk.NewTextureForPixbuf(p)
glib.IdleAdd(func() {
glib.IdleAddPriority(glib.PriorityLow, func() {
i.SetFromPaintable(gt)
})
}
+56 -15
View File
@@ -6,19 +6,21 @@ import (
"context"
"encoding/base64"
"fmt"
"github.com/diamondburned/gotk4/pkg/gdk/v4"
"github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/diamondburned/gotk4/pkg/gtk/v4"
"github.com/google/uuid"
"github.com/jasonlovesdoggo/gopen"
"gosrc.io/xmpp/stanza"
xmpp_color "mellium.im/xmpp/color"
"mellium.im/xmpp/jid"
"os"
"path/filepath"
"runtime"
"strings"
"time"
"github.com/diamondburned/gotk4/pkg/gdk/v4"
"github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/diamondburned/gotk4/pkg/gtk/v4"
"github.com/google/uuid"
"github.com/jasonlovesdoggo/gopen"
"gosrc.io/xmpp/stanza"
xmpp_color "mellium.im/xmpp/color"
"mellium.im/xmpp/jid"
)
func generatePresenceWidget(p stanza.Packet) gtk.Widgetter {
@@ -102,7 +104,8 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
msg.ocu_id = ocu.ID
if sid.ID != "" {
typed_tab.msg_refsOSID[sid.ID] = msg
// typed_tab.msg_refsOSID[sid.ID] = msg
typed_tab.msg_refsOSID.Store(sid.ID, msg)
}
}
@@ -241,6 +244,7 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
live_edit := gtk.NewButtonWithLabel("Live edit")
live_edit.ConnectClicked(func() {
en := gtk.NewEntry()
en.SetText(m.Body)
en.ConnectChanged(func() {
client.SendRaw(fmt.Sprintf("<message id='%s' to='%s' type='%s'><body>%s</body><replace id='%s' xmlns='urn:xmpp:message-correct:0'/></message>",
uuid.NewString(),
@@ -277,7 +281,13 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
al := gtk.NewLabel(name)
ycbcr := xmpp_color.String(id, 255, loadedConfig.CVD)
r, g, b, _ := ycbcr.RGBA()
hexcolor := fmt.Sprintf("#%02x%02x%02x", r, g, b)
r = uint32((float32(r) / 65536) * 255)
g = uint32((float32(g) / 65536) * 255)
b = uint32((float32(b) / 65536) * 255)
hexcolor := fmt.Sprintf("#%x%x%x", r, g, b)
fmt.Println(hexcolor)
al.SetMarkup(fmt.Sprintf("<span foreground='%s'>%s</span>", hexcolor, name))
al.SetSelectable(true)
@@ -416,10 +426,19 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
body = XEPToPango(body, false)
mlabel := gtk.NewLabel("")
if m.Body == "" {
form := new(stanza.Form)
contains_form := m.Get(form)
if m.Body == "" && m.Subject == "" && !contains_form {
return nil, false
}
if m.Body == "" {
mlabel.SetText("No body set")
mlabel.AddCSSClass("visitor")
}
mlabel.SetMarkup(body)
mlabel.SetWrap(true)
mlabel.SetSelectable(true)
@@ -469,13 +488,34 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
mainBox.Append(lp_box)
}
if contains_form {
btn := gtk.NewButtonWithLabel(fmt.Sprintf("Open attached form - %s", form.Title))
btn.ConnectClicked(func() {
f, w, _ := showFormDialog(*form)
w.ConnectCloseRequest(func() (ok bool) {
go func() {
form_reply := stanza.NewMessage(stanza.Attrs{
Type: m.Type,
Id: m.Id,
To: m.From,
})
form_reply.Extensions = []stanza.MsgExtension{f}
client.Send(form_reply)
}()
return false
})
})
mainBox.Append(btn)
}
if loadedConfig.BlockingMode == Highlight && blocked {
}
if blocked {
switch loadedConfig.BlockingMode {
case Highlight:
mainBox.AddCSSClass("blocked")
}
if loadedConfig.BlockingMode == Hide && blocked {
case Hide:
mainBox.SetVisible(false)
blocked_box := gtk.NewBox(gtk.OrientationVertical, 0)
blocked_part := gtk.NewBox(gtk.OrientationHorizontal, 0)
@@ -491,6 +531,7 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
blocked_box.Append(mainBox)
return blocked_box, true
}
}
return mainBox, true
}
+1 -1
View File
@@ -103,7 +103,7 @@ func dropToSignInPage(err error) {
if err != nil {
panic(err)
}
os.WriteFile(filepath.Join(p, "lambda.toml"), b.Bytes(), 0644)
os.WriteFile(filepath.Join(p, config_filename), b.Bytes(), 0644)
window.SetVisible(false)
main()
+1 -1
View File
@@ -121,7 +121,7 @@ func save(choice string) {
if err != nil {
panic(err)
}
os.WriteFile(filepath.Join(p, "lambda.toml"), b.Bytes(), 0644)
os.WriteFile(filepath.Join(p, config_filename), b.Bytes(), 0644)
fmt.Println("a")
// Please add tenary operators to go istg this is painful
+195 -28
View File
@@ -19,6 +19,7 @@ import (
"github.com/diamondburned/gotk4/pkg/gio/v2"
"github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/diamondburned/gotk4/pkg/gtk/v4"
"github.com/diamondburned/gotk4/pkg/pango"
"github.com/gen2brain/beeep"
"github.com/go-analyze/charts"
"github.com/google/uuid"
@@ -83,11 +84,18 @@ var xmlLog *os.File
// Basic roster
var Roster = make(map[string]bool)
var config_filename = "lambda.toml"
var app_id = "net.sunglocto.lambda"
func init() {
beeep.AppName = loadedLocale["appName"]
}
func main() {
if os.Getenv("PROFILE") != "" {
config_filename = fmt.Sprintf("lambda_%s.toml", os.Getenv("PROFILE"))
app_id = "net.sunglocto.lambda." + os.Getenv("PROFILE")
}
pingTimes = append(pingTimes, []float64{})
p, err := ensureConfig()
@@ -95,7 +103,7 @@ func main() {
panic(err)
}
b, err := os.ReadFile(filepath.Join(p, "lambda.toml"))
b, err := os.ReadFile(filepath.Join(p, config_filename))
if err != nil {
dropToSignInPage(err)
return
@@ -169,6 +177,7 @@ func main() {
iqResp.Type = "error"
iqResp.From = clientroot.Session.BindJid
iqResp.Id = iq.Id
stanza_err := new(stanza.Err)
stanza_err.Type = stanza.ErrorTypeCancel
@@ -203,6 +212,7 @@ func main() {
{Var: "urn:xmpp:ping"},
{Var: "jabber:iq:oob"},
{Var: "jabber:x:oob"},
{Var: "jabber:x:data"},
},
}
iqResp.Payload = &payload
@@ -230,6 +240,7 @@ func main() {
iqResp.Type = "error"
iqResp.From = clientroot.Session.BindJid
iqResp.Id = iq.Id
stanza_err := new(stanza.Err)
stanza_err.Type = stanza.ErrorTypeCancel
@@ -360,8 +371,8 @@ func main() {
// Handle read indicators
marker := new(Marker)
ok = m.Get(marker)
if ok {
_, ok := typed_tab.msg_refsOSID[marker.ID]
if ok && !loadedConfig.CompactMode {
_, ok := typed_tab.msg_refsOSID.Load(marker.ID)
if ok {
im := gtk.NewImage()
im.SetPixelSize(20)
@@ -381,12 +392,15 @@ func main() {
go getAvatar(m.From, vu.Photo, im)
}
ind, ok := typed_tab.msg_refsOSID[marker.ID]
uind, loaded := typed_tab.msg_refsOSID.Load(marker.ID)
if loaded {
ind, ok := uind.(*abMessage)
if ok {
if ind.read_indicator != nil {
ind.read_indicator.Append(im)
}
}
}
return
}
return
@@ -423,19 +437,9 @@ func main() {
tab, ok := tabs.Load(originator)
if ok {
typed_tab := tab.(*chatTab)
/*
to_retract := ""
refs := typed_tab.msg_refsID
// If it is a DM, then we use regular message ID. If it is a MUC, we use stanza id
to_retract = sid.ID
if typed_tab.isMuc && sid != nil {
to_retract = sid.ID
refs = typed_tab.msg_refsOSID
}
*/
msg, ok := typed_tab.msg_refsOSID[retraction.ID]
umsg, ok := typed_tab.msg_refsOSID.Load(retraction.ID)
if ok {
msg, ok := umsg.(*abMessage)
if ok {
lab := msg.label_ref
glib.IdleAdd(func() {
@@ -445,8 +449,9 @@ func main() {
}
}
}
}
glib.IdleAdd(func() {
glib.IdleAddPriority(glib.PriorityLow, func() {
b := gtk.NewBox(gtk.OrientationVertical, 0)
tab, ok := tabs.Load(originator)
@@ -472,10 +477,12 @@ func main() {
if valid && converted_successfully {
mStatus.SetText(originator)
if typed_tab.msgs != nil {
typed_tab.msgs.Append(b)
b.Append(ba)
b.Append(gtk.NewSeparator(gtk.OrientationVertical))
}
}
})
})
@@ -496,6 +503,20 @@ func main() {
ok = presence.Get(&mu)
if ok { // This is a presence stanza from a user in a MUC
from_self, created := false, false
for _, status := range mu.StatusCodes {
if status.Code == "110" {
from_self = true
}
if status.Code == "201" {
created = true
}
}
if from_self && created {
showDialog("You have created a new MUC. In order for people to be able to join this MUC, you must first configure it. You can configure this MUC by clicking on the MUC button in the top right and then clicking 'Configre MUC'.", &window.Window)
}
presence.Get(&ocu)
id := JidMustParse(presence.From).Resource
@@ -524,7 +545,7 @@ func main() {
if presence.Type != "unavailable" {
_, ok := typed_unit.Members.Load(id)
if !ok && loadedConfig.ShowPresenceUpdates {
glib.IdleAdd(func() {
glib.IdleAddPriority(glib.PriorityLow, func() {
b := gtk.NewBox(gtk.OrientationVertical, 0)
ba, ok := generatePresenceWidget(p).(*gtk.Box)
if ok {
@@ -548,7 +569,7 @@ func main() {
} else {
typed_unit.Members.Delete(id)
if loadedConfig.ShowPresenceUpdates {
glib.IdleAdd(func() {
glib.IdleAddPriority(glib.PriorityLow, func() {
b := gtk.NewBox(gtk.OrientationVertical, 0)
ba, ok := generatePresenceWidget(p).(*gtk.Box)
if ok {
@@ -604,7 +625,7 @@ func main() {
cm := xmpp.NewStreamManager(c, func(c xmpp.Sender) {
fmt.Println("XMPP client connected")
// client = c
client = c
// clientroot = c
go func() {
@@ -810,7 +831,7 @@ func main() {
}
}
app := gtk.NewApplication("net.sunglocto.lambda", gio.ApplicationDefaultFlags)
app := gtk.NewApplication(app_id, gio.ApplicationDefaultFlags)
app.ConnectActivate(func() {
activate(app)
go conc()
@@ -834,6 +855,86 @@ func activate(app *gtk.Application) {
fileMenu := gio.NewMenu()
fileMenu.Append(loadedLocale["joinMUCMenu"], "app.join")
fileMenu.Append(loadedLocale["destroyMUCMenu"], "app.destroymuc")
fileMenu.Append("MUC Affiliations", "app.mucaffils")
fileMenu.Append("Configure MUC", "app.configuremuc")
viewAffilsMucAction := gio.NewSimpleAction("mucaffils", nil)
viewAffilsMucAction.ConnectActivate(func(p *glib.Variant) {
go func() {
cur, ok := tabs.Load(current)
if ok {
cur := cur.(*chatTab)
if cur.isMuc {
affils := []string{"owner", "admin", "member", "outcast"}
items := []MucAdminItem{}
for _, affil := range affils {
iq, err := stanza.NewIQ(stanza.Attrs{Type: stanza.IQTypeGet, To: current, Id: uuid.NewString(), From: clientroot.Session.BindJid})
if err != nil {
return
}
q := new(MucAdminQuery)
q.MucAdminItems = append(q.MucAdminItems, MucAdminItem{Affiliation: affil})
iq.Payload = q
ctx := context.TODO()
mychan, err := client.SendIQ(ctx, iq)
result := <-mychan
res, ok := result.Payload.(*MucAdminQuery)
if ok {
for _, item := range res.MucAdminItems {
items = append(items, item)
}
}
}
glib.IdleAdd(func() {
affil_win := gtk.NewWindow()
affil_box := gtk.NewBox(gtk.OrientationVertical, 2)
affil_box.Append(gtk.NewLabel("Affiliations"))
scroller := gtk.NewScrolledWindow()
scroller_grid := gtk.NewGrid()
scroller_grid.SetVExpand(true)
scroller.SetChild(scroller_grid)
scroller.SetVExpand(true)
affil_box.Append(scroller)
affil_win.SetChild(affil_box)
scroller_grid.Attach(gtk.NewLabel("Affiliation"), 0, 0, 1, 1)
scroller_grid.Attach(gtk.NewLabel("JID"), 1, 0, 1, 1)
scroller_grid.Attach(gtk.NewLabel("Nick"), 2, 0, 1, 1)
scroller_grid.Attach(gtk.NewLabel("Reason"), 3, 0, 1, 1)
for i, v := range items {
medal_box := gtk.NewBox(gtk.OrientationHorizontal, 0)
medal_box.Append(gtk.NewImageFromPaintable(clientAssetsLoad(v.Affiliation)))
medal_box.Append(gtk.NewLabel(v.Affiliation))
scroller_grid.Attach(medal_box, 0, i+1, 1, 1)
jid := gtk.NewLabel(v.JID)
jid.AddCSSClass("jid")
jid.SetSelectable(true)
scroller_grid.Attach(jid, 1, i+1, 1, 1)
nick := gtk.NewLabel(v.Nick)
nick.SetSelectable(true)
scroller_grid.Attach(nick, 2, i+1, 1, 1)
reason := gtk.NewLabel(v.Reason)
reason.SetSelectable(true)
reason.SetEllipsize(pango.EllipsizeEnd)
scroller_grid.Attach(reason, 3, i+1, 1, 1)
}
affil_win.SetVisible(true)
})
}
}
}()
})
dmMenu := gio.NewMenu()
dmMenu.Append(loadedLocale["startDMMenu"], "app.dm")
@@ -890,12 +991,81 @@ func activate(app *gtk.Application) {
a.SetAuthors([]string{"Sunglocto", "Hydrogen", "Kuyuhi"})
a.SetLicenseType(gtk.LicenseGPL30)
a.SetLogo(clientAssetsLoad("logo"))
a.SetWebsite("https://forge.sunglocto.net/sunglocto/lambda")
a.SetWebsite("https://sunglocto.net/lambda")
a.SetWebsiteLabel("Website")
a.SetVisible(true)
})
configureMucAction := gio.NewSimpleAction("configuremuc", nil)
configureMucAction.ConnectActivate(func(p *glib.Variant) {
go func() {
cur, ok := tabs.Load(current)
if ok {
cur := cur.(*chatTab)
if cur.isMuc {
iq, err := stanza.NewIQ(stanza.Attrs{
Type: stanza.IQTypeGet,
Id: uuid.NewString(),
To: current,
})
if err != nil {
glib.IdleAdd(func() { showErrorDialog(err, &window.Window) })
return
}
iq.Payload = &MucOwnerQuery{}
ctx := context.TODO()
mychan, err := client.SendIQ(ctx, iq)
if err != nil {
glib.IdleAdd(func() { showErrorDialog(err, &window.Window) })
return
}
result := <-mychan
res, ok := result.Payload.(*MucOwnerQuery)
if !ok {
return
}
glib.IdleAdd(func() {
f, win, _ := showFormDialog(res.Form)
win.ConnectCloseRequest(func() (ok bool) {
go func() {
iq, err := stanza.NewIQ(stanza.Attrs{
Id: result.Id,
To: result.From,
Type: stanza.IQTypeSet,
})
if err != nil {
glib.IdleAdd(func() { showErrorDialog(err, &window.Window) })
return
}
f.Type = "submit"
mo := new(MucOwnerQuery)
mo.Form = *f
iq.Payload = mo
ctx := context.TODO()
_, err = client.SendIQ(ctx, iq)
if err != nil {
glib.IdleAdd(func() { showErrorDialog(err, &window.Window) })
return
}
}()
return false
})
})
}
}
}()
})
destroymucAction := gio.NewSimpleAction("destroymuc", nil)
destroymucAction.ConnectActivate(func(p *glib.Variant) {
cur, ok := tabs.Load(current)
@@ -919,7 +1089,6 @@ func activate(app *gtk.Application) {
submit := gtk.NewButtonWithLabel(loadedLocale["destroyMUCActionButton"])
submit.ConnectClicked(func() {
fmt.Println(en.Text())
if en.Text() == loadedLocale["destroyMUCPassword"] {
cur, ok := tabs.Load(current)
if ok {
@@ -1069,7 +1238,6 @@ func activate(app *gtk.Application) {
var res *stanza.DiscoInfo
allowed := true
fmt.Println("Attempting to get Disco info")
myIQ, err := stanza.NewIQ(stanza.Attrs{
Type: "get",
@@ -1225,7 +1393,9 @@ func activate(app *gtk.Application) {
app.AddAction(joinAction)
app.AddAction(aboutAction)
app.AddAction(destroymucAction)
app.AddAction(configureMucAction)
app.AddAction(startDmAction)
app.AddAction(viewAffilsMucAction)
the_menu.AppendSubmenu("MUC", fileMenu)
the_menu.AppendSubmenu("DM", dmMenu)
@@ -1350,16 +1520,13 @@ func activate(app *gtk.Application) {
scrollerStatBar.SetChild(statBar)
box.Append(scrollerStatBar)
// scroller.SetChild(empty_dialog)
scroller.SetChild(empty_dialog)
menu_scroll := gtk.NewScrolledWindow()
menu_scroll.SetHExpand(true)
menu_scroll.SetChild(menu)
// box.Append(menu_scroll)
chatbox := gtk.NewBox(gtk.OrientationHorizontal, 0)
// chatbox.Append(menu_scroll)
chat_pane := gtk.NewPaned(gtk.OrientationHorizontal)
chat_pane.SetStartChild(scroller)
chat_pane.SetEndChild(memberList)
+5
View File
@@ -139,3 +139,8 @@
color: black;
}
.you {
color: red;
text-decoration: underline;
}
+2 -1
View File
@@ -17,7 +17,8 @@ type chatTab struct {
isMuc bool
msgs *gtk.ListBox
msg_refsID map[string]*abMessage
msg_refsOSID map[string]*abMessage
// msg_refsOSID map[string]*abMessage
msg_refsOSID sync.Map
name string
current_nick string
muc_presence *stanza.Presence
+1 -1
View File
@@ -1,3 +1,3 @@
package main
var lambda_version string = "10"
var lambda_version string = "11"
+4
View File
@@ -37,6 +37,7 @@ func joinMuc(c xmpp.Sender, jid string, muc string, nick string, password string
Attrs: stanza.Attrs{
From: jid,
To: addr,
Lang: "en",
},
Extensions: []stanza.PresExtension{
&stanza.MucPresence{},
@@ -47,6 +48,7 @@ func joinMuc(c xmpp.Sender, jid string, muc string, nick string, password string
Attrs: stanza.Attrs{
From: jid,
To: addr,
Lang: "en",
},
Extensions: []stanza.PresExtension{
&stanza.MucPresence{
@@ -162,11 +164,13 @@ func addPEPBookmark(c xmpp.Sender, jid string, name string, nick string, autojoi
persist.ValuesList = []string{"true"}
options_form.Fields = append(options_form.Fields, persist)
/*
max_items := new(stanza.Field)
max_items.Type = "text-single"
max_items.Var = "pubsub#max_items"
max_items.ValuesList = []string{"max"}
options_form.Fields = append(options_form.Fields, max_items)
*/
send_last_published_item := new(stanza.Field)
send_last_published_item.Type = "text-single"
+35
View File
@@ -0,0 +1,35 @@
package main
// Implementation of XEP-0045 admin
// https://xmpp.org/extensions/xep-0045.html
import (
"encoding/xml"
"gosrc.io/xmpp/stanza"
)
type MucAdminQuery struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/muc#admin query"`
MucAdminItems []MucAdminItem `xml:"http://jabber.org/protocol/muc#admin item"`
ResultSet *stanza.ResultSet `xml:"set,omitempty"`
}
type MucAdminItem struct {
Affiliation string `xml:"affiliation,attr,omitempty"`
JID string `xml:"jid,attr,omitempty"`
Nick string `xml:"nick,attr,omitempty"`
Role string `xml:"role,attr,omitempty"`
Reason string `xml:"reason,omitempty"`
}
func (v *MucAdminQuery) Namespace() string {
return v.XMLName.Space
}
func (v *MucAdminQuery) GetSet() *stanza.ResultSet {
return v.ResultSet
}
func init() {
stanza.TypeRegistry.MapExtension(stanza.PKTIQ, xml.Name{Space: "http://jabber.org/protocol/muc#admin", Local: "query"}, MucAdminQuery{})
}
+27
View File
@@ -0,0 +1,27 @@
package main
// Implementation of XEP-0045 admin
// https://xmpp.org/extensions/xep-0045.html
import (
"encoding/xml"
"gosrc.io/xmpp/stanza"
)
type MucOwnerQuery struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/muc#owner query"`
ResultSet *stanza.ResultSet `xml:"set,omitempty"`
Form stanza.Form `xml:"jabber:x:data x,omitempty"`
}
func (v *MucOwnerQuery) Namespace() string {
return v.XMLName.Space
}
func (v *MucOwnerQuery) GetSet() *stanza.ResultSet {
return v.ResultSet
}
func init() {
stanza.TypeRegistry.MapExtension(stanza.PKTIQ, xml.Name{Space: "http://jabber.org/protocol/muc#owner", Local: "query"}, MucOwnerQuery{})
}
+5
View File
@@ -12,6 +12,7 @@ type MucUser struct {
stanza.PresExtension
stanza.MsgExtension
XMLName xml.Name `xml:"http://jabber.org/protocol/muc#user x"`
StatusCodes []MucUserStatusCode `xml:"status,omitempty"`
MucUserItem MucUserItem `xml:"item,omitempty"`
}
@@ -29,6 +30,10 @@ type Actor struct {
Nick string `xml:"nick,attr"`
}
type MucUserStatusCode struct {
Code string `xml:"code,attr"`
}
func init() {
stanza.TypeRegistry.MapExtension(stanza.PKTPresence, xml.Name{Space: "http://jabber.org/protocol/muc#user", Local: "x"}, MucUser{})
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{Space: "http://jabber.org/protocol/muc#user", Local: "x"}, MucUser{})