6-7
This commit is contained in:
@@ -1,6 +1,4 @@
|
|||||||
# TODO
|
# TODO
|
||||||
- XEP-0393: Message Styling 0%
|
|
||||||
- XEP-0402: PEP Native Bookmarks 50% (often lags out client if enabled)
|
|
||||||
- XEP-0461: Message Replies 0%
|
- XEP-0461: Message Replies 0%
|
||||||
- XEP-0444: Message Reactions partial
|
- XEP-0444: Message Reactions partial
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ func newImageFromPath(path string) (*gtk.Image, error) {
|
|||||||
return gtk.NewImageFromPaintable(tex), nil
|
return gtk.NewImageFromPaintable(tex), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setImageFromPath(path string, i *gtk.Image) (error) {
|
func setImageFromPath(path string, i *gtk.Image) error {
|
||||||
tex, err := getTexture(path)
|
tex, err := getTexture(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
+3
-3
@@ -718,9 +718,9 @@ func createIdenticon(word string, always_create bool, i *gtk.Image) { // This fu
|
|||||||
p := loader.Pixbuf()
|
p := loader.Pixbuf()
|
||||||
gt := gdk.NewTextureForPixbuf(p)
|
gt := gdk.NewTextureForPixbuf(p)
|
||||||
/*
|
/*
|
||||||
i := gtk.NewImageFromPaintable(gt)
|
i := gtk.NewImageFromPaintable(gt)
|
||||||
i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
|
i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
|
||||||
return i
|
return i
|
||||||
*/
|
*/
|
||||||
|
|
||||||
i.SetFromPaintable(gt)
|
i.SetFromPaintable(gt)
|
||||||
|
|||||||
+17
-15
@@ -307,9 +307,9 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
|
|||||||
} else {
|
} else {
|
||||||
createIdenticon(m.From, false, im)
|
createIdenticon(m.From, false, im)
|
||||||
/*
|
/*
|
||||||
im.SetPixelSize(40)
|
im.SetPixelSize(40)
|
||||||
im.AddCSSClass("author_img")
|
im.AddCSSClass("author_img")
|
||||||
authorBox.Append(im)
|
authorBox.Append(im)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
} else if m.Type == stanza.MessageTypeChat {
|
} else if m.Type == stanza.MessageTypeChat {
|
||||||
@@ -464,14 +464,16 @@ func getAvatar(j, hash string, i *gtk.Image) { // TODO: This function probably s
|
|||||||
_, err = os.ReadFile(hash)
|
_, err = os.ReadFile(hash)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
/*
|
/*
|
||||||
i, err = newImageFromPath(hash)
|
i, err = newImageFromPath(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
invalidImages.Store(oghash, true)
|
invalidImages.Store(oghash, true)
|
||||||
createIdenticon(j, false, i)
|
createIdenticon(j, false, i)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
setImageFromPath(hash, i)
|
glib.IdleAdd(func() {
|
||||||
|
setImageFromPath(hash, i)
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,12 +521,12 @@ func getAvatar(j, hash string, i *gtk.Image) { // TODO: This function probably s
|
|||||||
}
|
}
|
||||||
|
|
||||||
glib.IdleAdd(func() {
|
glib.IdleAdd(func() {
|
||||||
err = setImageFromPath(hash, i)
|
err = setImageFromPath(hash, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
invalidImages.Store(oghash, true)
|
invalidImages.Store(oghash, true)
|
||||||
createIdenticon(j, false, i)
|
createIdenticon(j, false, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
|
i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-2
@@ -15,15 +15,27 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func XEPToPango(text string) string {
|
func XEPToPango(text string) string {
|
||||||
format := func(s string) string {
|
formatInline := func(s string) string {
|
||||||
s = html.EscapeString(s)
|
s = html.EscapeString(s)
|
||||||
s = boldRE.ReplaceAllString(s, "<b>$1</b>")
|
s = boldRE.ReplaceAllString(s, "<b>$1</b>")
|
||||||
s = italicRE.ReplaceAllString(s, "<i>$1</i>")
|
s = italicRE.ReplaceAllString(s, "<i>$1</i>")
|
||||||
s = strikeRE.ReplaceAllString(s, "<s>$1</s>")
|
s = strikeRE.ReplaceAllString(s, "<s>$1</s>")
|
||||||
s = codeRE.ReplaceAllString(s, "<tt>$1</tt>")
|
s = codeRE.ReplaceAllString(s, `<tt>$1</tt>`)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
format := func(s string) string {
|
||||||
|
lines := strings.Split(s, "\n")
|
||||||
|
|
||||||
|
for i, line := range lines {
|
||||||
|
|
||||||
|
lines[i] = formatInline(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(lines, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
last := 0
|
last := 0
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,9 @@ var pingTimes = [][]float64{}
|
|||||||
|
|
||||||
var xmlLog *os.File
|
var xmlLog *os.File
|
||||||
|
|
||||||
|
// Basic roster
|
||||||
|
var Roster = make(map[string]bool)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
beeep.AppName = loadedLocale["appName"]
|
beeep.AppName = loadedLocale["appName"]
|
||||||
|
|
||||||
@@ -98,7 +101,6 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
pingTimes = append(pingTimes, []float64{})
|
pingTimes = append(pingTimes, []float64{})
|
||||||
p, err := ensureConfig()
|
p, err := ensureConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -132,6 +134,11 @@ func main() {
|
|||||||
xmlLog = os.Stdout
|
xmlLog = os.Stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res := "/" + loadedConfig.Resource
|
||||||
|
if loadedConfig.RandomizeResource {
|
||||||
|
res = ""
|
||||||
|
}
|
||||||
|
|
||||||
config := xmpp.Config{
|
config := xmpp.Config{
|
||||||
TransportConfiguration: xmpp.TransportConfiguration{
|
TransportConfiguration: xmpp.TransportConfiguration{
|
||||||
Address: loadedConfig.Server,
|
Address: loadedConfig.Server,
|
||||||
@@ -141,7 +148,7 @@ func main() {
|
|||||||
ConnectTimeout: 300,
|
ConnectTimeout: 300,
|
||||||
TLSConfig: &tls.Config{InsecureSkipVerify: loadedConfig.Insecure},
|
TLSConfig: &tls.Config{InsecureSkipVerify: loadedConfig.Insecure},
|
||||||
},
|
},
|
||||||
Jid: loadedConfig.Username + "/" + loadedConfig.Resource,
|
Jid: loadedConfig.Username + res,
|
||||||
Credential: xmpp.Password(loadedConfig.Password),
|
Credential: xmpp.Password(loadedConfig.Password),
|
||||||
Insecure: loadedConfig.Insecure,
|
Insecure: loadedConfig.Insecure,
|
||||||
StreamManagementEnable: true,
|
StreamManagementEnable: true,
|
||||||
@@ -161,6 +168,29 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
|
||||||
|
stanza_err := new(stanza.Err)
|
||||||
|
stanza_err.Type = stanza.ErrorTypeCancel
|
||||||
|
stanza_err.Text = "service-unavailable"
|
||||||
|
|
||||||
|
iqResp.MakeError(*stanza_err)
|
||||||
|
s.Send(iqResp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
identity := stanza.Identity{
|
identity := stanza.Identity{
|
||||||
Name: "Lambda",
|
Name: "Lambda",
|
||||||
Category: "client", // TODO: Allow spoofing on user request
|
Category: "client", // TODO: Allow spoofing on user request
|
||||||
@@ -182,6 +212,8 @@ func main() {
|
|||||||
{Var: "urn:xmpp:attention:0"},
|
{Var: "urn:xmpp:attention:0"},
|
||||||
{Var: "urn:xmpp:carbons:2"},
|
{Var: "urn:xmpp:carbons:2"},
|
||||||
{Var: "urn:xmpp:ping"},
|
{Var: "urn:xmpp:ping"},
|
||||||
|
{Var: "jabber:iq:oob"},
|
||||||
|
{Var: "jabber:x:oob"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
iqResp.Payload = &payload
|
iqResp.Payload = &payload
|
||||||
@@ -192,7 +224,6 @@ func main() {
|
|||||||
iq, ok := p.(*stanza.IQ)
|
iq, ok := p.(*stanza.IQ)
|
||||||
if !ok || iq.Type != stanza.IQTypeGet {
|
if !ok || iq.Type != stanza.IQTypeGet {
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iqResp, err := stanza.NewIQ(stanza.Attrs{Type: "result", From: iq.To, To: iq.From, Id: iq.Id})
|
iqResp, err := stanza.NewIQ(stanza.Attrs{Type: "result", From: iq.To, To: iq.From, Id: iq.Id})
|
||||||
@@ -200,6 +231,27 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All requests from either ourselves or our server will always be accepted regardless of user settings.
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
stanza_err := new(stanza.Err)
|
||||||
|
stanza_err.Type = stanza.ErrorTypeCancel
|
||||||
|
stanza_err.Text = "service-unavailable"
|
||||||
|
|
||||||
|
iqResp.MakeError(*stanza_err)
|
||||||
|
s.Send(iqResp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
v := &stanza.Version{}
|
v := &stanza.Version{}
|
||||||
v = v.SetInfo(loadedLocale["appName"], lambda_version, runtime.GOOS) // TODO: Allow spoofing on user request
|
v = v.SetInfo(loadedLocale["appName"], lambda_version, runtime.GOOS) // TODO: Allow spoofing on user request
|
||||||
|
|
||||||
@@ -484,37 +536,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Throughput
|
|
||||||
/*
|
|
||||||
var oldsize int64
|
|
||||||
var newsize int64
|
|
||||||
var diff float64
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
stat, err := xmlLog.Stat()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
newsize = stat.Size()
|
|
||||||
diff = float64(newsize-oldsize) / 1000
|
|
||||||
|
|
||||||
ic := clientAssets["car"]
|
|
||||||
if diff >= 25 {
|
|
||||||
ic = clientAssets["car_high"]
|
|
||||||
}
|
|
||||||
|
|
||||||
glib.IdleAdd(func() {
|
|
||||||
sStatus.SetText(fmt.Sprintf("%.2f%s", diff, loadedLocale["KBPerSecond"]))
|
|
||||||
sIcon.SetFromPaintable(ic)
|
|
||||||
})
|
|
||||||
|
|
||||||
oldsize = newsize
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
*/
|
|
||||||
|
|
||||||
glib.IdleAdd(func() {
|
glib.IdleAdd(func() {
|
||||||
connectionStatus.SetText(fmt.Sprintf("%s%s", loadedLocale["connectedAs"], JidMustParse(clientroot.Session.BindJid).Bare()))
|
connectionStatus.SetText(fmt.Sprintf("%s%s", loadedLocale["connectedAs"], JidMustParse(clientroot.Session.BindJid).Bare()))
|
||||||
connectionStatus.SetTooltipText(fmt.Sprintf("%s%s\n%s%t", loadedLocale["bindedJid"], clientroot.Session.BindJid, loadedLocale["usingTLS"], clientroot.Session.TlsEnabled))
|
connectionStatus.SetTooltipText(fmt.Sprintf("%s%s\n%s%t", loadedLocale["bindedJid"], clientroot.Session.BindJid, loadedLocale["usingTLS"], clientroot.Session.TlsEnabled))
|
||||||
@@ -583,6 +604,7 @@ func main() {
|
|||||||
for _, v := range items.Items {
|
for _, v := range items.Items {
|
||||||
name := v.Name
|
name := v.Name
|
||||||
jid := v.Jid
|
jid := v.Jid
|
||||||
|
Roster[jid] = true
|
||||||
|
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = jid
|
name = jid
|
||||||
@@ -613,13 +635,13 @@ func main() {
|
|||||||
go getAvatar(jid, jid, im)
|
go getAvatar(jid, jid, im)
|
||||||
/*
|
/*
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
new_im := getAvatar(jid, jid) // TODO: Use PEP avatar and do not use JID as hash
|
new_im := getAvatar(jid, jid) // TODO: Use PEP avatar and do not use JID as hash
|
||||||
glib.IdleAdd(func() {
|
glib.IdleAdd(func() {
|
||||||
new_im.SetPixelSize(40)
|
new_im.SetPixelSize(40)
|
||||||
box.Prepend(new_im)
|
box.Prepend(new_im)
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
box.AddController(gesture1)
|
box.AddController(gesture1)
|
||||||
@@ -710,13 +732,13 @@ func main() {
|
|||||||
|
|
||||||
go getAvatar(jid, jid, im)
|
go getAvatar(jid, jid, im)
|
||||||
/*
|
/*
|
||||||
go func() {
|
go func() {
|
||||||
new_im := getAvatar(jid, jid)
|
new_im := getAvatar(jid, jid)
|
||||||
glib.IdleAdd(func() {
|
glib.IdleAdd(func() {
|
||||||
new_im.SetPixelSize(40)
|
new_im.SetPixelSize(40)
|
||||||
box.Prepend(new_im)
|
box.Prepend(new_im)
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
box.AddController(gesture1)
|
box.AddController(gesture1)
|
||||||
@@ -1014,13 +1036,13 @@ func activate(app *gtk.Application) {
|
|||||||
|
|
||||||
go getAvatar(t, t, im)
|
go getAvatar(t, t, im)
|
||||||
/*
|
/*
|
||||||
go func() {
|
go func() {
|
||||||
new_im := getAvatar(t, t)
|
new_im := getAvatar(t, t)
|
||||||
glib.IdleAdd(func() {
|
glib.IdleAdd(func() {
|
||||||
new_im.SetPixelSize(40)
|
new_im.SetPixelSize(40)
|
||||||
box.Prepend(new_im)
|
box.Prepend(new_im)
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
*/
|
*/
|
||||||
b := gtk.NewLabel(n)
|
b := gtk.NewLabel(n)
|
||||||
|
|
||||||
@@ -1208,7 +1230,7 @@ func activate(app *gtk.Application) {
|
|||||||
the_menuBar := gtk.NewPopoverMenuBarFromModel(the_menu)
|
the_menuBar := gtk.NewPopoverMenuBarFromModel(the_menu)
|
||||||
app.SetMenubar(gio.NewMenu())
|
app.SetMenubar(gio.NewMenu())
|
||||||
|
|
||||||
window.SetTitle("Lambda")
|
window.SetTitle(loadedLocale["appName"])
|
||||||
window.Window.AddCSSClass("ssd")
|
window.Window.AddCSSClass("ssd")
|
||||||
window.Window.SetDefaultSize(500, 500)
|
window.Window.SetDefaultSize(500, 500)
|
||||||
menu = gtk.NewBox(gtk.OrientationVertical, 0)
|
menu = gtk.NewBox(gtk.OrientationVertical, 0)
|
||||||
|
|||||||
@@ -18,9 +18,17 @@ type chatTab struct {
|
|||||||
type BlockingMode int
|
type BlockingMode int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Drop BlockingMode = iota
|
Drop BlockingMode = iota // Do not even process if the entity is blocked
|
||||||
Hide
|
Hide // Hide the message but allow the user to expand it if they wish (discord style)
|
||||||
Highlight
|
Highlight // Just highlight the message in orange
|
||||||
|
)
|
||||||
|
|
||||||
|
type DiscoveryMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Everyone DiscoveryMode = iota // All entities can query
|
||||||
|
OnlyRoster // Only people on your roster can query
|
||||||
|
None // Nobody can query
|
||||||
)
|
)
|
||||||
|
|
||||||
type lambdaConfig struct {
|
type lambdaConfig struct {
|
||||||
@@ -48,6 +56,18 @@ type lambdaConfig struct {
|
|||||||
BlockingMode BlockingMode
|
BlockingMode BlockingMode
|
||||||
|
|
||||||
CheckUpdate string
|
CheckUpdate string
|
||||||
|
|
||||||
|
RandomizeResource bool // If this is set to true, then the resource will be completely randomized by the server on every single connect
|
||||||
|
|
||||||
|
// Privacy settings
|
||||||
|
DiscoPrivacy DiscoveryMode // Whether or not Lambda will report its service discovery features and Identity. Reccomended mode is Everyone, Default is Everyone
|
||||||
|
VersionPrivacy DiscoveryMode // Whether or not Lambda will report its version information. Reccomended mode is Roster, Default is Everyone
|
||||||
|
|
||||||
|
IgnoreInsteadOfReturnErrorUponPrivacyViolation bool // If set to true, Lambda will simply ignore Disco and Query Version requests from entities that are untrusted as per the user's discovery mode. If set to false, a service-unavailable error will be reported.
|
||||||
|
|
||||||
|
// Spoofing
|
||||||
|
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
type mucUnit struct {
|
type mucUnit struct {
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
var lambda_version string = "6"
|
var lambda_version string = "7"
|
||||||
|
|||||||
Reference in New Issue
Block a user