commit a0086b5d3130c4acc390fdb00f66d97ca2d294ef Author: dasha_uwu Date: Wed Jun 26 08:05:27 2024 +0500 1.0 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c735332 --- /dev/null +++ b/go.mod @@ -0,0 +1,20 @@ +module git.dimensionproject.net/dasha_uwu/jmap + +go 1.22.2 + +require maunium.net/go/mautrix v0.18.1 + +require ( + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/rs/zerolog v1.32.0 // indirect + github.com/tidwall/gjson v1.17.1 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + go.mau.fi/util v0.4.2 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4ed6c80 --- /dev/null +++ b/go.sum @@ -0,0 +1,43 @@ +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= +github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +go.mau.fi/util v0.4.2 h1:RR3TOcRHmCF9Bx/3YG4S65MYfa+nV6/rn8qBWW4Mi30= +go.mau.fi/util v0.4.2/go.mod h1:PlAVfUUcPyHPrwnvjkJM9UFcPE7qGPDJqk+Oufa1Gtw= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc= +golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +maunium.net/go/mautrix v0.18.1 h1:a6mUsJixegBNTXUoqC5RQ9gsumIPzKvCubKwF+zmCt4= +maunium.net/go/mautrix v0.18.1/go.mod h1:2oHaq792cSXFGvxLvYw3Gf1L4WVVP4KZcYys5HVk/h8= diff --git a/main.go b/main.go new file mode 100644 index 0000000..55a2e23 --- /dev/null +++ b/main.go @@ -0,0 +1,96 @@ +package main + +import ( + "context" + "errors" + "flag" + "fmt" + "net/http" + "strings" + + "maunium.net/go/mautrix" + "maunium.net/go/mautrix/id" +) + +func main() { + address := flag.String("address", "127.0.0.1:8080", "address:port to listen on") + username := flag.String("username", "", "matrix username") + password := flag.String("password", "", "matrix password") + homeserver := flag.String("homeserver", "", "matrix homeserver URL") + flag.Parse() + + if *username == "" { + fmt.Println("empty username") + return + } + + if *password == "" { + fmt.Println("empty password") + return + } + + if *homeserver == "" { + fmt.Println("empty homeserver") + return + } + + fmt.Printf("logging in as %s on %s\n", *username, *homeserver) + client, err := loginMatrix(*username, *password, *homeserver) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("starting jmap on %s\n", *address) + + http.HandleFunc("/avatar/{mxId}", func(w http.ResponseWriter, r *http.Request) { + mxId := r.PathValue("mxId") + if !strings.HasPrefix(mxId, "@") { + mxId = "@" + mxId + } + avatar, err := getMatrixUserAvatar(r.Context(), client, mxId) + if err != nil { + fmt.Printf("bad request for %s error %s\n", mxId, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + fmt.Printf("ok request for %s\n", mxId) + w.Write(avatar) + }) + http.ListenAndServe(*address, nil) +} + +func loginMatrix(mxId string, password string, homeserverURL string) (client *mautrix.Client, err error) { + client, err = mautrix.NewClient(homeserverURL, id.UserID(mxId), "") + if err != nil { + return nil, err + } + _, err = client.Login(context.Background(), &mautrix.ReqLogin{ + Type: mautrix.AuthTypePassword, + Identifier: mautrix.UserIdentifier{ + Type: mautrix.IdentifierTypeUser, + User: mxId, + }, + Password: password, + StoreCredentials: true, + }) + if err != nil { + return nil, err + } + return client, nil +} + +func getMatrixUserAvatar(ctx context.Context, client *mautrix.Client, mxId string) (avatar []byte, err error) { + profile, err := client.GetProfile(ctx, id.UserID(mxId)) + if err != nil { + return nil, err + } + if profile.AvatarURL.IsEmpty() { + return nil, errors.New("no avatar") + } + avatar, err = client.DownloadBytes(ctx, profile.AvatarURL) + if err != nil { + return nil, err + } + return avatar, nil +} diff --git a/openrc/jmap.conf.d b/openrc/jmap.conf.d new file mode 100644 index 0000000..fb0cfd4 --- /dev/null +++ b/openrc/jmap.conf.d @@ -0,0 +1,4 @@ +username="" +password="" +homeserver="" +address="127.0.0.1:8080" diff --git a/openrc/jmap.init.d b/openrc/jmap.init.d new file mode 100755 index 0000000..202e148 --- /dev/null +++ b/openrc/jmap.init.d @@ -0,0 +1,12 @@ +#!/sbin/openrc-run + +command="/usr/local/bin/jmap" +command_args="-username $username -password $password -homeserver $homeserver -address $address" +command_user="jmap:jmap" +command_background=1 +pidfile="/run/${RC_SVCNAME}.pid" +output_log="/var/log/jmap/jmap.log" + +depend() { + use net +}