diff --git a/go.mod b/go.mod index c85b313..170309f 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( fyne.io/x/fyne v0.0.0-20250418202416-58a230ad1acb github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d mellium.im/xmpp v0.22.0 - pain.agency/oasis-sdk v0.0.0-20250809192709-a3e5dff1aa61 + pain.agency/oasis-sdk v0.0.0-20250831105702-85385dca3a95 ) require ( diff --git a/go.sum b/go.sum index f5eff74..425745b 100644 --- a/go.sum +++ b/go.sum @@ -101,3 +101,5 @@ mellium.im/xmpp v0.22.0 h1:UthQVSwEAr7SNrmyc90c2ykGpVHxjn/3yw8Ey4+Im8s= mellium.im/xmpp v0.22.0/go.mod h1:WSjq12nhREFD88Vy/0WD6Q8inE8t6a8w7QjzwivWitw= pain.agency/oasis-sdk v0.0.0-20250809192709-a3e5dff1aa61 h1:7zb69SAfLAJhXoqXZaS0pq/p1Y9W19Pm4FjcwWjTVoE= pain.agency/oasis-sdk v0.0.0-20250809192709-a3e5dff1aa61/go.mod h1:eyvDgfpHo+9bdB/AkMEMZ3ETeoSONTULVx9X4w9kGAU= +pain.agency/oasis-sdk v0.0.0-20250831105702-85385dca3a95 h1:BcB7/hnMnQIU+pERvQRGFMt9i0/o8XCnHbK1kYG3/K4= +pain.agency/oasis-sdk v0.0.0-20250831105702-85385dca3a95/go.mod h1:eyvDgfpHo+9bdB/AkMEMZ3ETeoSONTULVx9X4w9kGAU= diff --git a/main.go b/main.go index d3b58c0..c20480a 100644 --- a/main.go +++ b/main.go @@ -202,8 +202,6 @@ func CreateUITab(chatJidStr string) ChatTabUI { return } - - if strings.HasSuffix(chatTabs[chatJidStr].Messages[i].ImageURL, "mp4") || strings.HasSuffix(chatTabs[chatJidStr].Messages[i].ImageURL, "mp3") || strings.HasSuffix(chatTabs[chatJidStr].Messages[i].ImageURL, "gif") || strings.HasSuffix(chatTabs[chatJidStr].Messages[i].ImageURL, "webp") { // FIXME: This code is fucking terrible // TODO: Could check mime? url, err := url.Parse(chatTabs[chatJidStr].Messages[i].ImageURL) if err != nil { @@ -396,91 +394,16 @@ func main() { notifications = config.Notifications client, err := oasisSdk.CreateClient( - &login, - func(client *oasisSdk.XmppClient, msg *oasisSdk.XMPPChatMessage) { - correction := false - userJidStr := msg.From.Bare().String() - tab, ok := chatTabs[userJidStr] - if ok { - str := *msg.CleanedBody - if notifications { - a.SendNotification(fyne.NewNotification(fmt.Sprintf("%s says", userJidStr), str)) - } + &login) - for _, v := range msg.Unknown { - if v.XMLName.Local == "replace" { - correction = true - break // dont need to look at more fields - } - } - - var img string = "" - if strings.Contains(str, "https://") { - lines := strings.Split(str, "\n") - for i, line := range lines { - s := strings.Split(line, " ") - for _, v := range s { - _, err := url.Parse(v) - if err == nil && strings.HasPrefix(v, "https://") { - if strings.HasSuffix(v, ".png") || strings.HasSuffix(v, ".jpg") || strings.HasSuffix(v, ".jpeg") || strings.HasSuffix(v, ".webp") || strings.HasSuffix(v, ".mp4") || strings.HasSuffix(v, ".gif") { - img = v - } - } - } - lines[i] = strings.Join(s, " ") - } - str = strings.Join(lines, " ") - } - var replyID string - if msg.Reply == nil { - replyID = "PICLIENT:UNAVAILABLE" - } else { - replyID = msg.Reply.ID - } - - if correction { - for i := len(tab.Messages) - 1; i > 0; i-- { - if tab.Messages[i].Raw.From.String() == msg.From.String() { - tab.Messages[i].Content = *msg.CleanedBody + " (edited)" - fyne.Do(func() { - UITabs[userJidStr].Scroller.Refresh() - }) - return - } - } - } - - myMessage := Message{ - Author: msg.From.Resourcepart(), - Content: str, - ID: msg.ID, - ReplyID: replyID, - Raw: *msg, - ImageURL: img, - } - - tab.Messages = append(tab.Messages, myMessage) - fyne.Do(func() { - UITabs[userJidStr].Scroller.Refresh() - if scrollDownOnNewMessage { - UITabs[userJidStr].Scroller.ScrollToBottom() - } - }) - } - }, - func(client *oasisSdk.XmppClient, muc *muc.Channel, msg *oasisSdk.XMPPChatMessage) { - // HACK: IGNORING ALL MESSAGES FROM CLASSIC MUC HISTORY IN PREPARATION OF MAM SUPPORT - ignore := false - correction := false - important := false - donotnotify := false - for _, v := range msg.Unknown { - if v.XMLName.Local == "delay" { // Classic history message - donotnotify = true - //ignore = true - //fmt.Println("ignoring!") - //return //what is blud doing - } + client.SetDmHandler(func(client *oasisSdk.XmppClient, msg *oasisSdk.XMPPChatMessage) { + correction := false + userJidStr := msg.From.Bare().String() + tab, ok := chatTabs[userJidStr] + if ok { + str := *msg.CleanedBody + if notifications { + a.SendNotification(fyne.NewNotification(fmt.Sprintf("%s says", userJidStr), str)) } for _, v := range msg.Unknown { @@ -490,105 +413,186 @@ func main() { } } - var ImageID string = "" - mucJidStr := msg.From.Bare().String() - if tab, ok := chatTabs[mucJidStr]; ok { - chatTabs[mucJidStr].Muc = muc - str := *msg.CleanedBody - if strings.Contains(str, login.DisplayName) { - fmt.Println(str) - important = true - } - if !donotnotify && !ignore && notifications { - if !correction && msg.From.String() != client.JID.String() && strings.Contains(str, login.DisplayName) || (msg.Reply != nil && strings.Contains(msg.Reply.To, login.DisplayName)) { - a.SendNotification(fyne.NewNotification(fmt.Sprintf("Mentioned in %s", mucJidStr), str)) - } - } - if strings.Contains(str, "https://") { - lines := strings.Split(str, "\n") - for i, line := range lines { - s := strings.Split(line, " ") - for _, v := range s { - _, err := url.Parse(v) - if err == nil && strings.HasPrefix(v, "https://") { - if strings.HasSuffix(v, ".png") || strings.HasSuffix(v, ".jpg") || strings.HasSuffix(v, ".jpeg") || strings.HasSuffix(v, ".webp") || strings.HasSuffix(v, ".mp4") || strings.HasSuffix(v, ".mp3") || strings.HasSuffix(v, ".gif") { - ImageID = v - } + var img string = "" + if strings.Contains(str, "https://") { + lines := strings.Split(str, "\n") + for i, line := range lines { + s := strings.Split(line, " ") + for _, v := range s { + _, err := url.Parse(v) + if err == nil && strings.HasPrefix(v, "https://") { + if strings.HasSuffix(v, ".png") || strings.HasSuffix(v, ".jpg") || strings.HasSuffix(v, ".jpeg") || strings.HasSuffix(v, ".webp") || strings.HasSuffix(v, ".mp4") || strings.HasSuffix(v, ".gif") { + img = v } } - lines[i] = strings.Join(s, " ") } - str = strings.Join(lines, " ") - fmt.Println(str) - } - fmt.Println(msg.ID) - var replyID string - if msg.Reply == nil { - replyID = "PICLIENT:UNAVAILABLE" - } else { - replyID = msg.Reply.To + lines[i] = strings.Join(s, " ") } + str = strings.Join(lines, " ") + } + var replyID string + if msg.Reply == nil { + replyID = "PICLIENT:UNAVAILABLE" + } else { + replyID = msg.Reply.ID + } - if correction { - for i := len(tab.Messages) - 1; i > 0; i-- { - if tab.Messages[i].Raw.From.String() == msg.From.String() { - tab.Messages[i].Content = *msg.CleanedBody + " (edited)" - fyne.Do(func() { - UITabs[mucJidStr].Scroller.Refresh() - }) - return + if correction { + for i := len(tab.Messages) - 1; i > 0; i-- { + if tab.Messages[i].Raw.From.String() == msg.From.String() { + tab.Messages[i].Content = *msg.CleanedBody + " (edited)" + fyne.Do(func() { + UITabs[userJidStr].Scroller.Refresh() + }) + return + } + } + } + + myMessage := Message{ + Author: msg.From.Resourcepart(), + Content: str, + ID: msg.ID, + ReplyID: replyID, + Raw: *msg, + ImageURL: img, + } + + tab.Messages = append(tab.Messages, myMessage) + fyne.Do(func() { + UITabs[userJidStr].Scroller.Refresh() + if scrollDownOnNewMessage { + UITabs[userJidStr].Scroller.ScrollToBottom() + } + }) + } + }) + + client.SetGroupChatHandler(func(client *oasisSdk.XmppClient, muc *muc.Channel, msg *oasisSdk.XMPPChatMessage) { + // HACK: IGNORING ALL MESSAGES FROM CLASSIC MUC HISTORY IN PREPARATION OF MAM SUPPORT + ignore := false + correction := false + important := false + donotnotify := false + for _, v := range msg.Unknown { + if v.XMLName.Local == "delay" { // Classic history message + donotnotify = true + //ignore = true + //fmt.Println("ignoring!") + //return //what is blud doing + } + } + + for _, v := range msg.Unknown { + if v.XMLName.Local == "replace" { + correction = true + break // dont need to look at more fields + } + } + + var ImageID string = "" + mucJidStr := msg.From.Bare().String() + if tab, ok := chatTabs[mucJidStr]; ok { + chatTabs[mucJidStr].Muc = muc + str := *msg.CleanedBody + if strings.Contains(str, login.DisplayName) { + fmt.Println(str) + important = true + } + if !donotnotify && !ignore && notifications { + if !correction && msg.From.String() != client.JID.String() && strings.Contains(str, login.DisplayName) || (msg.Reply != nil && strings.Contains(msg.Reply.To, login.DisplayName)) { + a.SendNotification(fyne.NewNotification(fmt.Sprintf("Mentioned in %s", mucJidStr), str)) + } + } + if strings.Contains(str, "https://") { + lines := strings.Split(str, "\n") + for i, line := range lines { + s := strings.Split(line, " ") + for _, v := range s { + _, err := url.Parse(v) + if err == nil && strings.HasPrefix(v, "https://") { + if strings.HasSuffix(v, ".png") || strings.HasSuffix(v, ".jpg") || strings.HasSuffix(v, ".jpeg") || strings.HasSuffix(v, ".webp") || strings.HasSuffix(v, ".mp4") || strings.HasSuffix(v, ".mp3") || strings.HasSuffix(v, ".gif") { + ImageID = v + } } } + lines[i] = strings.Join(s, " ") } + str = strings.Join(lines, " ") + fmt.Println(str) + } + fmt.Println(msg.ID) + var replyID string + if msg.Reply == nil { + replyID = "PICLIENT:UNAVAILABLE" + } else { + replyID = msg.Reply.To + } - myMessage := Message{ - Author: msg.From.Resourcepart(), - Content: str, - ID: msg.ID, - ReplyID: replyID, - Raw: *msg, - ImageURL: ImageID, - Important: important, - } - if !ignore { - tab.Messages = append(tab.Messages, myMessage) - } - fyne.Do(func() { - UITabs[mucJidStr].Scroller.Refresh() - if scrollDownOnNewMessage { - UITabs[mucJidStr].Scroller.ScrollToBottom() + if correction { + for i := len(tab.Messages) - 1; i > 0; i-- { + if tab.Messages[i].Raw.From.String() == msg.From.String() { + tab.Messages[i].Content = *msg.CleanedBody + " (edited)" + fyne.Do(func() { + UITabs[mucJidStr].Scroller.Refresh() + }) + return } - }) + } } - }, - func(_ *oasisSdk.XmppClient, from jid.JID, state oasisSdk.ChatState) { - switch state { - case oasisSdk.ChatStateComposing: - fyne.Do(func() { - statBar.SetText(fmt.Sprintf("%s is typing...", from.Resourcepart())) - }) - case oasisSdk.ChatStatePaused: - fyne.Do(func() { - statBar.SetText(fmt.Sprintf("%s has stopped typing.", from.Resourcepart())) - }) - case oasisSdk.ChatStateInactive: - fyne.Do(func() { - statBar.SetText(fmt.Sprintf("%s is idle", from.Resourcepart())) - }) - case oasisSdk.ChatStateGone: - fyne.Do(func() { - statBar.SetText(fmt.Sprintf("%s is gone", from.Resourcepart())) - }) - default: - fyne.Do(func() { - statBar.SetText("") - }) + myMessage := Message{ + Author: msg.From.Resourcepart(), + Content: str, + ID: msg.ID, + ReplyID: replyID, + Raw: *msg, + ImageURL: ImageID, + Important: important, } - }, + if !ignore { + tab.Messages = append(tab.Messages, myMessage) + } + fyne.Do(func() { + UITabs[mucJidStr].Scroller.Refresh() + if scrollDownOnNewMessage { + UITabs[mucJidStr].Scroller.ScrollToBottom() + } + }) + } + }) + + client.SetChatstateHandler(func(_ *oasisSdk.XmppClient, from jid.JID, state oasisSdk.ChatState) { + switch state { + case oasisSdk.ChatStateComposing: + fyne.Do(func() { + statBar.SetText(fmt.Sprintf("%s is typing...", from.Resourcepart())) + }) + case oasisSdk.ChatStatePaused: + + fyne.Do(func() { + statBar.SetText(fmt.Sprintf("%s has stopped typing.", from.Resourcepart())) + }) + case oasisSdk.ChatStateInactive: + fyne.Do(func() { + statBar.SetText(fmt.Sprintf("%s is idle", from.Resourcepart())) + }) + case oasisSdk.ChatStateGone: + fyne.Do(func() { + statBar.SetText(fmt.Sprintf("%s is gone", from.Resourcepart())) + }) + default: + fyne.Do(func() { + statBar.SetText("") + }) + } + }) + client.SetDeliveryReceiptHandler( func(_ *oasisSdk.XmppClient, from jid.JID, id string) { fmt.Printf("Delivered %s to %s", id, from.String()) - }, + }) + + client.SetReadReceiptHandler( func(_ *oasisSdk.XmppClient, from jid.JID, id string) { for _, tab := range chatTabs { for i := len(tab.Messages) - 1; i >= 0; i-- { @@ -603,8 +607,8 @@ func main() { } } fmt.Printf("%s has seen %s\n", from.String(), id) - }, - ) + }) + if err != nil { log.Fatalln("Could not create client - " + err.Error()) } @@ -951,55 +955,55 @@ func main() { d := dialog.NewCustom("Please wait", "Close", widget.NewLabel("..."), w) d.Show() go func() { - //search, err = jid.Parse(s) - //if err != nil { - // d.Hide() - // dialog.ShowError(err, w) - // return - //} - txt := ` ` - var stan stanza.IQ - xml.Unmarshal([]byte(txt), &stan) - if err != nil { + var stan stanza.IQ + xml.Unmarshal([]byte(txt), &stan) + if err != nil { + d.Hide() + dialog.ShowError(err, w) + return + } + r, err := client.Session.EncodeIQ(client.Ctx, stan) + if err != nil { + d.Hide() + dialog.ShowError(err, w) + return + } + ra, _ := r.Token() + t, _ := xml.MarshalIndent(ra, "", "\t") + fmt.Println(string(t)) d.Hide() - dialog.ShowError(err, w) - return - } - r, err := client.Session.EncodeIQ(client.Ctx, stan) - if err != nil { - d.Hide() - dialog.ShowError(err, w) - return - } - ra, _ := r.Token() - t, _ := xml.MarshalIndent(ra, "", "\t") - fmt.Println(string(t)) - d.Hide() - /* + /* - myBox := container.NewGridWithColumns(1, widget.NewLabel("Items")) - info, err := disco.GetInfo(client.Ctx, "", search, client.Session) - if err != nil { - d.Hide() - dialog.ShowError(err, w) - return - } - m := info.Identity - bytes, err := xml.MarshalIndent(m, "", "\t") - if err != nil { - d.Hide() - dialog.ShowError(err, w) - return - } - fyne.Do(func() {d.Hide()}) - myBox.Objects = append(myBox.Objects, widget.NewLabel(string(bytes))) - dialog.ShowCustom("Service discovery", "cancel", myBox, w) - */ + myBox := container.NewGridWithColumns(1, widget.NewLabel("Items")) + info, err := disco.GetInfo(client.Ctx, "", search, client.Session) + if err != nil { + d.Hide() + dialog.ShowError(err, w) + return + } + m := info.Identity + bytes, err := xml.MarshalIndent(m, "", "\t") + if err != nil { + d.Hide() + dialog.ShowError(err, w) + return + } + fyne.Do(func() {d.Hide()}) + myBox.Objects = append(myBox.Objects, widget.NewLabel(string(bytes))) + dialog.ShowCustom("Service discovery", "cancel", myBox, w) + */ }() }, w)