This commit is contained in:
2026-08-16 20:07:53 +01:00
parent eebb6906c6
commit 58ae55e061
16 changed files with 369 additions and 171 deletions
+158 -114
View File
@@ -18,7 +18,6 @@ import (
"github.com/gen2brain/beeep"
"github.com/go-analyze/charts"
"github.com/google/uuid"
"golang.org/x/net/html/charset"
"time"
@@ -28,7 +27,6 @@ import (
_ "embed"
"encoding/xml"
"io"
"runtime"
"github.com/kr/pretty"
@@ -44,6 +42,9 @@ var connectionIcon *gtk.Image
var mStatus *gtk.Label
var mIcon *gtk.Image
var gStatus *gtk.Label
var gIcon *gtk.Image
/*
var sStatus *gtk.Label
var sIcon *gtk.Image
@@ -141,10 +142,7 @@ func main() {
config := xmpp.Config{
TransportConfiguration: xmpp.TransportConfiguration{
Address: loadedConfig.Server,
CharsetReader: func(c string, input io.Reader) (io.Reader, error) {
return charset.NewReaderLabel(c, input)
},
Address: loadedConfig.Server,
ConnectTimeout: 300,
TLSConfig: &tls.Config{InsecureSkipVerify: loadedConfig.Insecure},
},
@@ -170,15 +168,14 @@ func main() {
// All requests from either ourselves or our server will always be accepted regardless of user settings.
if !(loadedConfig.DiscoPrivacy == 0) && !((JidMustParse(iq.From).Bare() == JidMustParse(clientroot.Session.BindJid).Bare()) || (JidMustParse(iq.From).Domain == JidMustParse(clientroot.Session.BindJid).Domain)) {
if loadedConfig.DiscoPrivacy == None || (loadedConfig.DiscoPrivacy == OnlyRoster && !Roster[JidMustParse(iq.From).Bare()]) {
fmt.Println("blocking", loadedConfig.DiscoPrivacy)
if loadedConfig.IgnoreInsteadOfReturnErrorUponPrivacyViolation {
return
}
iqResp.Type = "error"
iqResp.From = clientroot.Session.BindJid
stanza_err := new(stanza.Err)
stanza_err.Type = stanza.ErrorTypeCancel
@@ -190,7 +187,6 @@ func main() {
}
}
identity := stanza.Identity{
Name: "Lambda",
Category: "client", // TODO: Allow spoofing on user request
@@ -235,12 +231,12 @@ func main() {
if !(loadedConfig.VersionPrivacy == 0) && !((JidMustParse(iq.From).Bare() == JidMustParse(clientroot.Session.BindJid).Bare()) || (JidMustParse(iq.From).Domain == JidMustParse(clientroot.Session.BindJid).Domain)) {
if loadedConfig.VersionPrivacy == None || (loadedConfig.VersionPrivacy == OnlyRoster && !Roster[JidMustParse(iq.From).Bare()]) {
fmt.Println("blocking", loadedConfig.DiscoPrivacy)
if loadedConfig.IgnoreInsteadOfReturnErrorUponPrivacyViolation {
return
}
iqResp.Type = "error"
iqResp.From = clientroot.Session.BindJid
stanza_err := new(stanza.Err)
stanza_err.Type = stanza.ErrorTypeCancel
@@ -283,6 +279,7 @@ func main() {
}
originator := JidMustParse(m.From).Bare()
glib.IdleAdd(func() {
mStatus.SetText(originator)
})
@@ -345,6 +342,28 @@ func main() {
return
}
// Handle corrections BEFORE attempting to generate a message
correction := new(Correction)
ok = m.Get(correction)
if ok {
tab, ok := tabs.Load(originator)
if ok {
typed_tab := tab.(*chatTab)
if ok {
msg, ok := typed_tab.msg_refsID[correction.ID]
if ok {
if msg.ocu_id == oi.ID && msg.ocu_id != "" {
lab := msg.label_ref
glib.IdleAdd(func() {
lab.SetMarkup(XEPToPango(m.Body, true))
})
}
return
}
}
}
}
glib.IdleAdd(func() {
b := gtk.NewBox(gtk.OrientationVertical, 0)
@@ -363,7 +382,7 @@ func main() {
fmt.Println("Got message when the tab does not exist!")
}
untyped_box, valid := generateMessageWidget(p, blocked)
untyped_box, valid := generateMessageWidget(p, blocked, originator)
ba, converted_successfully := untyped_box.(*gtk.Box)
if valid && converted_successfully {
@@ -505,11 +524,18 @@ func main() {
// client = c
// clientroot = c
// Ping
go func() {
for {
time.Sleep(5 * time.Second)
go func() {
// Goroutine counter
goroutines := runtime.NumGoroutine()
glib.IdleAdd(func() {
gStatus.SetText(fmt.Sprintf("%d goroutines", goroutines))
})
}()
go func() {
// Ping
pingStatus.AddCSSClass("pending")
before := time.Now()
iq := new(stanza.IQ)
@@ -971,10 +997,12 @@ func activate(app *gtk.Application) {
jid_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
nick_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
disco_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
bookmark_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
jid_entry := gtk.NewEntry()
nick_entry := gtk.NewEntry()
disco_check := gtk.NewCheckButton()
bookmark_check := gtk.NewCheckButton()
jid_entry.SetHAlign(gtk.AlignEnd)
jid_entry.SetHExpand(true)
@@ -1004,9 +1032,14 @@ func activate(app *gtk.Application) {
disco_box.Append(disco_check)
disco_box.SetTooltipText(loadedLocale["joinMUCDiscoCheckTooltip"])
bookmark_check.SetActive(true)
bookmark_box.Append(gtk.NewLabel(loadedLocale["joinMUCBookmarkCheck"]))
bookmark_box.Append(bookmark_check)
box.Append(jid_box)
box.Append(nick_box)
box.Append(disco_box)
box.Append(bookmark_box)
btn := gtk.NewButtonWithLabel(loadedLocale["submit"])
btn.SetVAlign(gtk.AlignBaseline)
@@ -1035,15 +1068,7 @@ func activate(app *gtk.Application) {
im.SetPixelSize(40)
go getAvatar(t, t, im)
/*
go func() {
new_im := getAvatar(t, t)
glib.IdleAdd(func() {
new_im.SetPixelSize(40)
box.Prepend(new_im)
})
}()
*/
b := gtk.NewLabel(n)
box.Append(im)
@@ -1065,6 +1090,13 @@ func activate(app *gtk.Application) {
box.AddController(gesture2)
menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
if bookmark_check.Active() {
_, err := addPEPBookmark(client, t, n, nick_entry.Text(), true, pw)
if err != nil {
panic(err)
}
}
}
if !ok {
@@ -1092,111 +1124,116 @@ func activate(app *gtk.Application) {
myIQ.Payload = &stanza.DiscoInfo{}
ctx := context.TODO()
ctx := context.Background()
mychan, err := client.SendIQ(ctx, myIQ)
if err == nil {
result := <-mychan
res, ok = result.Payload.(*stanza.DiscoInfo)
if ok {
features := res.Features
allowed = false
password_protected := false
password := ""
warning_win := gtk.NewWindow()
warning_win.SetTitle(fmt.Sprintf("%s%s", loadedLocale["joinPreviewTitle"], res.Identity[0].Name))
warning_win.SetDefaultSize(400, 1)
warning_win.SetResizable(false)
if len(res.Identity) >= 1 {
features := res.Features
allowed = false
password_protected := false
password := ""
warning_win := gtk.NewWindow()
warning_win.SetTitle(fmt.Sprintf("%s%s", loadedLocale["joinPreviewTitle"], res.Identity[0].Name))
warning_win.SetDefaultSize(400, 1)
warning_win.SetResizable(false)
buttons := gtk.NewBox(gtk.OrientationHorizontal, 10)
buttons := gtk.NewBox(gtk.OrientationHorizontal, 10)
join_button := gtk.NewButtonWithLabel("Join")
join_button.ConnectClicked(func() {
warning_win.SetVisible(false)
if password_protected {
allowed = false
join_button := gtk.NewButtonWithLabel("Join")
join_button.ConnectClicked(func() {
warning_win.SetVisible(false)
if password_protected {
allowed = false
password_win := gtk.NewWindow()
password_win.SetTitle(loadedLocale["joinPasswordRequired"])
password_win.SetDefaultSize(400, 1)
password_win.SetResizable(false)
box := gtk.NewBox(gtk.OrientationVertical, 10)
en := gtk.NewPasswordEntry()
submit := gtk.NewButtonWithLabel(loadedLocale["submit"])
submit.ConnectClicked(func() {
password = en.Text()
jm(res.Identity[0].Name, password)
password_win.SetVisible(false)
})
box.Append(en)
box.Append(submit)
password_win.SetChild(box)
password_win.SetVisible(true)
password_win := gtk.NewWindow()
password_win.SetTitle(loadedLocale["joinPasswordRequired"])
password_win.SetDefaultSize(400, 1)
password_win.SetResizable(false)
box := gtk.NewBox(gtk.OrientationVertical, 10)
en := gtk.NewPasswordEntry()
submit := gtk.NewButtonWithLabel(loadedLocale["submit"])
submit.ConnectClicked(func() {
password = en.Text()
jm(res.Identity[0].Name, password)
password_win.SetVisible(false)
})
box.Append(en)
box.Append(submit)
password_win.SetChild(box)
password_win.SetVisible(true)
}
jm(res.Identity[0].Name, password)
})
cancel_button := gtk.NewButtonWithLabel(loadedLocale["cancel"])
cancel_button.ConnectClicked(func() {
warning_win.SetVisible(false)
})
join_button.SetHExpand(true)
cancel_button.SetHExpand(true)
buttons.Append(join_button)
buttons.Append(cancel_button)
warning_box := gtk.NewBox(gtk.OrientationVertical, 10)
header := gtk.NewLabel(res.Identity[0].Name)
warning_box.Append(header)
addFeature := func(icon string, description string) {
box := gtk.NewBox(gtk.OrientationHorizontal, 10)
box.Append(gtk.NewImageFromPaintable(clientAssetsLoad(icon)))
box.Append(gtk.NewLabel(description))
warning_box.Append(box)
}
jm(res.Identity[0].Name, password)
})
cancel_button := gtk.NewButtonWithLabel(loadedLocale["cancel"])
cancel_button.ConnectClicked(func() {
warning_win.SetVisible(false)
})
join_button.SetHExpand(true)
cancel_button.SetHExpand(true)
buttons.Append(join_button)
buttons.Append(cancel_button)
warning_box := gtk.NewBox(gtk.OrientationVertical, 10)
header := gtk.NewLabel(res.Identity[0].Name)
warning_box.Append(header)
addFeature := func(icon string, description string) {
box := gtk.NewBox(gtk.OrientationHorizontal, 10)
box.Append(gtk.NewImageFromPaintable(clientAssetsLoad(icon)))
box.Append(gtk.NewLabel(description))
warning_box.Append(box)
}
for _, feature := range features {
switch feature.Var {
case "muc_passwordprotected":
password_protected = true
addFeature("muc_passwordprotected", loadedLocale["muc_passwordprotected_description"])
case "muc_unsecured":
addFeature("muc_unsecured", loadedLocale["muc_unsecured_description"])
case "muc_membersonly":
addFeature("muc_membersonly", loadedLocale["muc_membersonly_description"])
case "muc_open":
addFeature("muc_open", loadedLocale["muc_open_description"])
case "muc_moderated":
addFeature("muc_moderated", loadedLocale["muc_moderated_description"])
case "muc_unmoderated":
addFeature("muc_unmoderated", loadedLocale["muc_unmoderated_description"])
case "muc_nonanonymous":
addFeature("muc_nonanonymous", loadedLocale["muc_nonanonymous_description"])
case "muc_semianonymous":
addFeature("muc_semianonymous", loadedLocale["muc_semianonymous_description"])
case "muc_persistent":
addFeature("muc_persistent", loadedLocale["muc_persistent_description"])
case "muc_temporary":
addFeature("muc_temporary", loadedLocale["muc_temporary_description"])
case "muc_public":
addFeature("muc_public", loadedLocale["muc_public_description"])
case "muc_hidden":
addFeature("muc_hidden", loadedLocale["muc_hidden_description"])
case "urn:xmpp:mam:0":
addFeature("ok", loadedLocale["urn:xmpp:mam_description"])
case "urn:xmpp:message-moderate:0":
addFeature("moderate", loadedLocale["urn:xmpp:message-moderate_description"])
/*
default:
addFeature("comment", feature.Var)
*/
for _, feature := range features {
switch feature.Var {
case "muc_passwordprotected":
password_protected = true
addFeature("muc_passwordprotected", loadedLocale["muc_passwordprotected_description"])
case "muc_unsecured":
addFeature("muc_unsecured", loadedLocale["muc_unsecured_description"])
case "muc_membersonly":
addFeature("muc_membersonly", loadedLocale["muc_membersonly_description"])
case "muc_open":
addFeature("muc_open", loadedLocale["muc_open_description"])
case "muc_moderated":
addFeature("muc_moderated", loadedLocale["muc_moderated_description"])
case "muc_unmoderated":
addFeature("muc_unmoderated", loadedLocale["muc_unmoderated_description"])
case "muc_nonanonymous":
addFeature("muc_nonanonymous", loadedLocale["muc_nonanonymous_description"])
case "muc_semianonymous":
addFeature("muc_semianonymous", loadedLocale["muc_semianonymous_description"])
case "muc_persistent":
addFeature("muc_persistent", loadedLocale["muc_persistent_description"])
case "muc_temporary":
addFeature("muc_temporary", loadedLocale["muc_temporary_description"])
case "muc_public":
addFeature("muc_public", loadedLocale["muc_public_description"])
case "muc_hidden":
addFeature("muc_hidden", loadedLocale["muc_hidden_description"])
case "urn:xmpp:mam:0":
addFeature("ok", loadedLocale["urn:xmpp:mam_description"])
case "urn:xmpp:message-moderate:0":
addFeature("moderate", loadedLocale["urn:xmpp:message-moderate_description"])
/*
default:
addFeature("comment", feature.Var)
*/
}
}
}
warning_box.Append(buttons)
warning_win.SetChild(warning_box)
warning_win.Present()
warning_box.Append(buttons)
warning_win.SetChild(warning_box)
warning_win.Present()
} else {
allowed = false
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]), win)
}
} else {
allowed = false
if result.Error != nil {
@@ -1274,9 +1311,16 @@ func activate(app *gtk.Application) {
mStatus = gtk.NewLabel("-")
mStatus.AddController(gesture1)
gIcon = gtk.NewImageFromPaintable((clientAssetsLoad("timeline_marker")))
gIcon.AddCSSClass("icon")
gStatus = gtk.NewLabel("...")
cBox.Append(mIcon)
cBox.Append(mStatus)
cBox.Append(gIcon)
cBox.Append(gStatus)
statBar.Append(mBox)
pBox := gtk.NewBox(gtk.OrientationHorizontal, 0)