Rest in peace Dolly Patron

This commit is contained in:
2026-08-25 20:17:23 +01:00
parent 2717137270
commit a6e74ec808
52 changed files with 675 additions and 462 deletions
+207 -278
View File
@@ -49,11 +49,6 @@ var mIcon *gtk.Image
var gStatus *gtk.Label
var gIcon *gtk.Image
/*
var sStatus *gtk.Label
var sIcon *gtk.Image
*/
var typingStatus *gtk.Label
var pingStatus *gtk.Label
@@ -93,9 +88,6 @@ func init() {
}
func main() {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
pingTimes = append(pingTimes, []float64{})
p, err := ensureConfig()
@@ -113,6 +105,12 @@ func main() {
if err != nil {
panic(err)
}
if loadedConfig.Debug {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
log.Println("pprof debug server running at port 6060")
}
if loadedConfig.Resource == "" {
fmt.Println(loadedLocale["configResourceEmptyWarning"])
@@ -257,6 +255,31 @@ func main() {
return
}
originator := JidMustParse(m.From).Bare()
var typed_tab *chatTab
tab, ok := tabs.Load(originator)
if ok {
typed_tab = tab.(*chatTab)
} else {
if m.Type != stanza.MessageTypeGroupchat {
createTab(originator, false, originator)
tab, ok = tabs.Load(originator)
if ok {
typed_tab = tab.(*chatTab)
glib.IdleAdd(func() {
box := createTabBox(originator, originator, originator, true)
menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationVertical))
})
} else {
return
}
} else {
return
}
}
oi := new(OccupantID)
ok = m.Get(oi)
if ok {
@@ -276,12 +299,6 @@ func main() {
sid := new(StanzaID)
m.Get(sid)
originator := JidMustParse(m.From).Bare()
glib.IdleAdd(func() {
mStatus.SetText(originator)
})
at := new(Attention)
ok = m.Get(at)
if ok {
@@ -340,6 +357,41 @@ func main() {
return
}
// Handle read indicators
marker := new(Marker)
ok = m.Get(marker)
if ok {
_, ok := typed_tab.msg_refsOSID[marker.ID]
if ok {
im := gtk.NewImage()
im.SetPixelSize(20)
im.SetTooltipText(JidMustParse(m.From).Resource)
glib.IdleAdd(func() {
createIdenticon(m.From, false, im)
})
pres, err := getPresenceFromJIDMuc(JidMustParse(m.From))
if err != nil {
return
}
var vu VCardUpdate
ok = pres.Get(&vu)
if ok {
go getAvatar(m.From, vu.Photo, im)
}
ind, ok := typed_tab.msg_refsOSID[marker.ID]
if ok {
if ind.read_indicator != nil {
ind.read_indicator.Append(im)
}
}
return
}
return
}
// Handle corrections BEFORE attempting to generate a message
correction := new(Correction)
ok = m.Get(correction)
@@ -352,9 +404,11 @@ func main() {
if ok {
if msg.ocu_id == oi.ID && msg.ocu_id != "" {
lab := msg.label_ref
glib.IdleAdd(func() {
lab.SetMarkup(XEPToPango(m.Body, true))
})
if lab != nil {
glib.IdleAdd(func() {
lab.SetMarkup(XEPToPango(m.Body, true))
})
}
}
return
}
@@ -370,15 +424,15 @@ func main() {
if ok {
typed_tab := tab.(*chatTab)
/*
to_retract := ""
refs := typed_tab.msg_refsID
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 {
// If it is a DM, then we use regular message ID. If it is a MUC, we use stanza id
to_retract = sid.ID
refs = typed_tab.msg_refsOSID
}
if typed_tab.isMuc && sid != nil {
to_retract = sid.ID
refs = typed_tab.msg_refsOSID
}
*/
msg, ok := typed_tab.msg_refsOSID[retraction.ID]
@@ -387,7 +441,8 @@ func main() {
glib.IdleAdd(func() {
GenerateRetraction(lab, *retraction)
})
}
return
}
}
}
@@ -399,7 +454,10 @@ func main() {
return
}
typed_tab := tab.(*chatTab)
typed_tab, ok := tab.(*chatTab)
if !ok {
return
}
if ok {
if current == JidMustParse(m.From).Bare() {
@@ -413,6 +471,7 @@ func main() {
ba, converted_successfully := untyped_box.(*gtk.Box)
if valid && converted_successfully {
mStatus.SetText(originator)
typed_tab.msgs.Append(b)
b.Append(ba)
b.Append(gtk.NewSeparator(gtk.OrientationVertical))
@@ -439,10 +498,7 @@ func main() {
if ok { // This is a presence stanza from a user in a MUC
presence.Get(&ocu)
// id := ocu.ID
// if id == "" {
id := JidMustParse(presence.From).Resource
// }
from, _ := stanza.NewJid(presence.From)
muc := from.Bare()
_, ok = mucmembers.Load(muc)
@@ -567,7 +623,7 @@ func main() {
pingStatus.AddCSSClass("pending")
before := time.Now()
iq := new(stanza.IQ)
iq.Id = uuid.New().String()
iq.Id = uuid.NewString()
iq.From = clientroot.Session.BindJid
iq.Type = "get"
iq.Payload = &Ping{}
@@ -621,22 +677,8 @@ func main() {
name := "Note To Self"
createTab(jid, false, name)
glib.IdleAdd(func() {
box := gtk.NewBox(gtk.OrientationHorizontal, 10)
b := gtk.NewLabel(name)
gesture1 := gtk.NewGestureClick()
gesture1.SetButton(1)
gesture1.Connect("pressed", func() {
switchToTab(jid, &window.Window)
})
box.Append(b)
im := gtk.NewImage()
im.SetPixelSize(40)
go getAvatar(jid, jid, im)
box.Prepend(im)
box.AddController(gesture1)
menu.Append(box)
b := createTabBox(name, jid, jid, false)
menu.Append(b)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
})
@@ -666,30 +708,7 @@ func main() {
createTab(jid, false, name)
glib.IdleAdd(func() {
box := gtk.NewBox(gtk.OrientationHorizontal, 10)
b := gtk.NewLabel(name)
gesture1 := gtk.NewGestureClick()
gesture1.SetButton(1)
gesture1.Connect("pressed", func() {
switchToTab(jid, &window.Window)
})
gesture2 := gtk.NewGestureClick()
gesture2.SetButton(3)
gesture2.Connect("pressed", func() {
removeTab(jid, &window.Window)
box.SetVisible(false)
})
im := gtk.NewImage()
im.SetPixelSize(40)
box.Append(im)
box.Append(b)
// TODO: Use PEP avatar and do not use JID as hash
go getAvatar(jid, jid, im)
box.AddController(gesture1)
box := createTabBox(name, jid, jid, false)
menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
})
@@ -754,31 +773,7 @@ func main() {
joinMuc(client, clientroot.Session.BindJid, jid, nick, password)
createTab(jid, true, name)
glib.IdleAdd(func() {
box := gtk.NewBox(gtk.OrientationHorizontal, 10)
b := gtk.NewLabel(name)
gesture1 := gtk.NewGestureClick()
gesture1.SetButton(1)
gesture1.Connect("pressed", func() {
switchToTab(jid, &window.Window)
})
gesture2 := gtk.NewGestureClick()
gesture2.SetButton(3)
gesture2.Connect("pressed", func() {
removeTab(jid, &window.Window)
box.SetVisible(false)
})
im := gtk.NewImage()
im.SetPixelSize(40)
box.Append(b)
box.Prepend(im)
go getAvatar(jid, jid, im)
box.AddController(gesture1)
box.AddController(gesture2)
box := createTabBox(name, jid, jid, true)
menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
})
@@ -795,31 +790,7 @@ func main() {
joinMuc(client, clientroot.Session.BindJid, jid, nick, "")
createTab(jid, true, jid)
glib.IdleAdd(func() {
box := gtk.NewBox(gtk.OrientationHorizontal, 10)
b := gtk.NewLabel(jid)
gesture1 := gtk.NewGestureClick()
gesture1.SetButton(1)
gesture1.Connect("pressed", func() {
switchToTab(jid, &window.Window)
})
gesture2 := gtk.NewGestureClick()
gesture2.SetButton(3)
gesture2.Connect("pressed", func() {
removeTab(jid, &window.Window)
box.SetVisible(false)
})
im := gtk.NewImage()
im.SetPixelSize(40)
box.Append(b)
box.Prepend(im)
go getAvatar(jid, jid, im)
box.AddController(gesture1)
box.AddController(gesture2)
box := createTabBox(jid, jid, jid, true)
menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
})
@@ -891,26 +862,8 @@ func activate(app *gtk.Application) {
submit := gtk.NewButtonWithLabel(loadedLocale["submit"])
submit.ConnectClicked(func() {
t := jid_entry.Text()
n := t
createTab(t, false, n)
box := gtk.NewBox(gtk.OrientationHorizontal, 0)
b := gtk.NewLabel(n)
box.Append(b)
gesture1 := gtk.NewGestureClick()
gesture1.SetButton(1)
gesture1.Connect("pressed", func() {
switchToTab(t, &window.Window)
})
gesture2 := gtk.NewGestureClick()
gesture2.SetButton(3)
gesture2.Connect("pressed", func() {
removeTab(t, &window.Window)
box.SetVisible(false)
})
box.AddController(gesture1)
box.AddController(gesture2)
createTab(t, false, t)
box := createTabBox(t, t, t, true)
menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
dm_window.SetVisible(false)
@@ -1007,19 +960,14 @@ func activate(app *gtk.Application) {
if JidMustParse(mu.MucUserItem.JID).Bare() == JidMustParse(clientroot.Session.BindJid).Bare() {
if mu.MucUserItem.Affiliation != "owner" {
box.Append(gtk.NewLabel(loadedLocale["destroyMUCNotOwnerWarning"]))
return false
}
}
}
} else {
panic("not ok")
}
} else {
panic("not ok")
}
return true
})
} else {
panic("not ok")
}
win.SetChild(box)
@@ -1101,31 +1049,7 @@ func activate(app *gtk.Application) {
}
createTab(t, true, n)
box := gtk.NewBox(gtk.OrientationHorizontal, 10)
im := gtk.NewImage()
im.SetPixelSize(40)
go getAvatar(t, t, im)
b := gtk.NewLabel(n)
box.Append(im)
box.Append(b)
gesture1 := gtk.NewGestureClick()
gesture1.SetButton(1)
gesture1.Connect("pressed", func() {
switchToTab(t, &window.Window)
})
gesture2 := gtk.NewGestureClick()
gesture2.SetButton(3)
gesture2.Connect("pressed", func() {
removeTab(t, &window.Window)
box.SetVisible(false)
})
box.AddController(gesture1)
box.AddController(gesture2)
box := createTabBox(n, t, t, true)
menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
@@ -1137,7 +1061,6 @@ func activate(app *gtk.Application) {
}
}
if !ok {
if !disco_check.Active() {
jm(t, "")
win.SetVisible(false)
@@ -1152,7 +1075,7 @@ func activate(app *gtk.Application) {
Type: "get",
From: clientroot.Session.BindJid,
To: t,
Id: "dicks",
Id: uuid.NewString(),
Lang: "en",
})
@@ -1163,122 +1086,128 @@ func activate(app *gtk.Application) {
myIQ.Payload = &stanza.DiscoInfo{}
ctx := context.Background()
mychan, err := client.SendIQ(ctx, myIQ)
if err == nil {
result := <-mychan
res, ok = result.Payload.(*stanza.DiscoInfo)
if ok {
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)
var mychan chan stanza.IQ
//go func() {
mychan, err = client.SendIQ(ctx, myIQ)
if err != nil {
showErrorDialog(err, &window.Window)
}
//}()
join_button := gtk.NewButtonWithLabel("Join")
join_button.ConnectClicked(func() {
warning_win.SetVisible(false)
if password_protected {
allowed = false
result := <-mychan
res, ok = result.Payload.(*stanza.DiscoInfo)
if ok {
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)
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)
}
buttons := gtk.NewBox(gtk.OrientationHorizontal, 10)
jm(res.Identity[0].Name, password)
})
join_button := gtk.NewButtonWithLabel("Join")
join_button.ConnectClicked(func() {
warning_win.SetVisible(false)
if password_protected {
allowed = false
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)
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)
}
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)
*/
}
}
jm(res.Identity[0].Name, password)
})
warning_box.Append(buttons)
warning_win.SetChild(warning_box)
warning_win.Present()
} else {
allowed = false
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]), win)
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)
*/
}
}
warning_box.Append(buttons)
warning_win.SetChild(warning_box)
warning_win.Present()
} else {
allowed = false
if result.Error != nil {
showErrorDialog(fmt.Errorf("%s: %s - %s", loadedLocale["discoFail"], result.Error.Reason, result.Error.Text), win)
} else {
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]), win)
}
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]), win)
}
} else {
allowed = false
if result.Error != nil {
showErrorDialog(fmt.Errorf("%s: %s - %s", loadedLocale["discoFail"], result.Error.Reason, result.Error.Text), win)
} else {
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]), win)
}
}