slidge-whatsapp 0.3.0b0__cp311-cp311-manylinux_2_36_aarch64.whl → 0.3.1__cp311-cp311-manylinux_2_36_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of slidge-whatsapp might be problematic. Click here for more details.
- slidge_whatsapp/contact.py +2 -0
- slidge_whatsapp/event.go +72 -22
- slidge_whatsapp/generated/_whatsapp.cpython-311-aarch64-linux-gnu.h +156 -156
- slidge_whatsapp/generated/_whatsapp.cpython-311-aarch64-linux-gnu.so +0 -0
- slidge_whatsapp/generated/build.py +121 -121
- slidge_whatsapp/generated/whatsapp.c +1491 -1491
- slidge_whatsapp/generated/whatsapp.go +1244 -1244
- slidge_whatsapp/generated/whatsapp.py +1188 -1188
- slidge_whatsapp/generated/whatsapp_go.h +156 -156
- slidge_whatsapp/go.mod +5 -5
- slidge_whatsapp/go.sum +14 -14
- slidge_whatsapp/session.go +4 -4
- slidge_whatsapp/vendor/github.com/ebitengine/purego/README.md +21 -5
- slidge_whatsapp/vendor/github.com/ebitengine/purego/abi_loong64.h +60 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/cgo.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlerror.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_netbsd.go +15 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_nocgo_netbsd.go +9 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_stubs.s +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/func.go +113 -60
- slidge_whatsapp/vendor/github.com/ebitengine/purego/gen.go +6 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/go_runtime.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go +2 -2
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go +2 -2
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_loong64.h +60 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_loong64.s +40 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_loong64.go +92 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_netbsd.go +106 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go +4 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go +4 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go +4 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_netbsd.go +26 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/netbsd.go +23 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go +11 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_darwin.go +1 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go +1 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_linux.go +1 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_netbsd.go +30 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_loong64.s +71 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s +5 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/nocgo.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_amd64.go +8 -4
- slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_arm64.go +16 -6
- slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_loong64.go +190 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_other.go +6 -2
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_amd64.s +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_arm64.s +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_loong64.s +96 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_unix_arm64.s +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_unix_loong64.s +75 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall.go +6 -3
- slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go +3 -3
- slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall_sysv.go +13 -10
- slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall_windows.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/zcallback_amd64.s +2002 -2002
- slidge_whatsapp/vendor/github.com/ebitengine/purego/zcallback_arm64.s +4002 -4002
- slidge_whatsapp/vendor/github.com/ebitengine/purego/zcallback_loong64.s +4014 -0
- slidge_whatsapp/vendor/go.mau.fi/util/dbutil/log.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/util/dbutil/module.go +118 -0
- slidge_whatsapp/vendor/go.mau.fi/util/dbutil/upgradetable.go +0 -34
- slidge_whatsapp/vendor/go.mau.fi/util/exbytes/string.go +20 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exbytes/writer.go +78 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exslices/cast.go +42 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exslices/chunk.go +28 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exslices/deduplicate.go +67 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exslices/diff.go +63 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exsync/event.go +15 -1
- slidge_whatsapp/vendor/go.mau.fi/util/random/string.go +47 -7
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/decode.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/encode.go +34 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/hash.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate.go +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/armadillomessage.go +1 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/call.go +6 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/errors.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/group.go +63 -42
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/internals.go +14 -10
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/message.go +45 -18
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/msgsecret.go +23 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/notification.go +5 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair.go +3 -7
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAICommon/WAAICommon.pb.go +7747 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/{waBotMetadata/WABotMetadata.proto → waAICommon/WAAICommon.proto} +269 -9
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.pb.go +128 -14
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.proto +10 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.go +3236 -4732
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.proto +125 -273
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.pb.go +11 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.proto +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.pb.go +220 -81
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.proto +13 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.go +705 -449
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.proto +23 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.pb.go +78 -24
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.proto +6 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.go +516 -267
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.proto +22 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/receipt.go +2 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/request.go +4 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/retry.go +2 -3
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/send.go +110 -28
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/clientpayload.go +1 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/noop.go +12 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/lidmap.go +82 -4
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/store.go +112 -55
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/00-latest-schema.sql +8 -7
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/11-redacted-phone-contacts.sql +2 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/store.go +20 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/call.go +6 -5
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/message.go +7 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/user.go +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/user.go +31 -2
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/desc.go +35 -17
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go +14 -0
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go +20 -0
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/version/version.go +1 -1
- slidge_whatsapp/vendor/modules.txt +8 -6
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.1.dist-info}/METADATA +4 -3
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.1.dist-info}/RECORD +131 -107
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.1.dist-info}/WHEEL +1 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waBotMetadata/WABotMetadata.pb.go +0 -5156
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.1.dist-info}/entry_points.txt +0 -0
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.1.dist-info/licenses}/LICENSE +0 -0
|
@@ -115,6 +115,7 @@ func (z zeroLogger) QueryTiming(ctx context.Context, method, query string, args
|
|
|
115
115
|
if duration >= 1*time.Second {
|
|
116
116
|
evt := log.Warn().
|
|
117
117
|
Float64("duration_seconds", duration.Seconds()).
|
|
118
|
+
AnErr("result_error", err).
|
|
118
119
|
Str("method", method).
|
|
119
120
|
Str("query", query)
|
|
120
121
|
if z.Caller {
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Package dbutil provides a simple framework for in-process database
|
|
2
|
+
// migrations. You provide the SQL files and they are run to upgrade
|
|
3
|
+
// the database. A versions table is automatically created in the
|
|
4
|
+
// database to track which migrations have been applied. There is
|
|
5
|
+
// support for multiple migration pathways, for example v0->v2 versus
|
|
6
|
+
// v0->v1->v2, and the shorter one is prioritized if both are
|
|
7
|
+
// provided.
|
|
8
|
+
//
|
|
9
|
+
// Example usage from Go:
|
|
10
|
+
//
|
|
11
|
+
// package main
|
|
12
|
+
//
|
|
13
|
+
// import (
|
|
14
|
+
// "context"
|
|
15
|
+
// "database/sql"
|
|
16
|
+
// "embed"
|
|
17
|
+
//
|
|
18
|
+
// "go.mau.fi/util/dbutil"
|
|
19
|
+
// )
|
|
20
|
+
//
|
|
21
|
+
// //go:embed *.sql
|
|
22
|
+
// var upgrades embed.FS
|
|
23
|
+
//
|
|
24
|
+
// func mainE() error {
|
|
25
|
+
// ctx := context.Background()
|
|
26
|
+
// rawDB, err := sql.Open("sqlite3", "./hotdogs.db")
|
|
27
|
+
// if err != nil {
|
|
28
|
+
// return err
|
|
29
|
+
// }
|
|
30
|
+
// db, err := dbutil.NewWithDB(rawDB, "sqlite3")
|
|
31
|
+
// if err != nil {
|
|
32
|
+
// return err
|
|
33
|
+
// }
|
|
34
|
+
// table := dbutil.UpgradeTable{}
|
|
35
|
+
// table.RegisterFS(upgrades)
|
|
36
|
+
// err = db.Upgrade(ctx)
|
|
37
|
+
// if err != nil {
|
|
38
|
+
// return err
|
|
39
|
+
// }
|
|
40
|
+
// // db has been upgraded to latest version
|
|
41
|
+
// return nil
|
|
42
|
+
// }
|
|
43
|
+
//
|
|
44
|
+
// In dbutil, the database is understood to have a monotonic integer
|
|
45
|
+
// sequence of versions starting at v0, v1, v2, etc. By providing
|
|
46
|
+
// migrations you define a directed acyclic graph (DAG) that allows
|
|
47
|
+
// dbutil to find a path from the current recorded database version to
|
|
48
|
+
// the latest version available.
|
|
49
|
+
//
|
|
50
|
+
// Each SQL migration file has a mandatory comment header that
|
|
51
|
+
// identifies which database versions it upgrades between. For example
|
|
52
|
+
// this is a migration that upgrades from v0 to v2:
|
|
53
|
+
//
|
|
54
|
+
// -- v0 -> v2: Do some things
|
|
55
|
+
//
|
|
56
|
+
// You can omit the first version for the common case of upgrading to
|
|
57
|
+
// a version from the previous version. For example this is a
|
|
58
|
+
// migration that upgrades from v1 to v2:
|
|
59
|
+
//
|
|
60
|
+
// -- v2: Do fewer things
|
|
61
|
+
//
|
|
62
|
+
// By providing "v1" and "v2" migrations, a v0 database would be
|
|
63
|
+
// upgraded to v1 and then v2, while by providing an additional "v0 ->
|
|
64
|
+
// v2" migration a v0 database would be upgraded directly to v2 as it
|
|
65
|
+
// is a more direct path. With that migration provided the "v1"
|
|
66
|
+
// migration is no longer needed.
|
|
67
|
+
//
|
|
68
|
+
// By default, when running migrations, if a more recent database
|
|
69
|
+
// version is live than the current code knows about (for example,
|
|
70
|
+
// from running a previous version of the application), dbutil will
|
|
71
|
+
// error out. However, many database migrations are backwards
|
|
72
|
+
// compatible. You can therefore indicate this when writing a
|
|
73
|
+
// migration, and previous versions of the application will accept a
|
|
74
|
+
// database with that migration applied, even if they are unaware of
|
|
75
|
+
// its contents. For example, if the migration from v1 to v2 was
|
|
76
|
+
// backwards compatible, you could provide this migration:
|
|
77
|
+
//
|
|
78
|
+
// -- v2 (compatible with v1+): Do fewer things
|
|
79
|
+
//
|
|
80
|
+
// When applying the migration, the compatibility level (v1) is saved
|
|
81
|
+
// to the versions table in the database, so that older versions of
|
|
82
|
+
// the application which only know about v1 will see that v2 of the
|
|
83
|
+
// database is still OK to use. If the compatibility level is not set,
|
|
84
|
+
// then it defaults to the same as the target version for the
|
|
85
|
+
// migration, which achieves the default behavior described in the
|
|
86
|
+
// previous paragraph.
|
|
87
|
+
//
|
|
88
|
+
// You can provide additional flags immediately following the header
|
|
89
|
+
// line. To disable wrapping the upgrade in a single transaction, put
|
|
90
|
+
// "transaction: off" on the second line.
|
|
91
|
+
//
|
|
92
|
+
// -- v5: Upgrade without transaction
|
|
93
|
+
// -- transaction: off
|
|
94
|
+
// // do dangerous stuff
|
|
95
|
+
//
|
|
96
|
+
// Within migrations, there is special syntax that can be used to
|
|
97
|
+
// filter parts of the SQL to apply only with specific dialects. To
|
|
98
|
+
// limit the next line to one dialect:
|
|
99
|
+
//
|
|
100
|
+
// -- only: postgres
|
|
101
|
+
//
|
|
102
|
+
// To limit the next N lines:
|
|
103
|
+
//
|
|
104
|
+
// -- only: sqlite for next 123 lines
|
|
105
|
+
//
|
|
106
|
+
// To limit a block of code, fenced by another directive:
|
|
107
|
+
//
|
|
108
|
+
// -- only: sqlite until "end only"
|
|
109
|
+
// QUERY;
|
|
110
|
+
// ANOTHER QUERY;
|
|
111
|
+
// -- end only sqlite
|
|
112
|
+
//
|
|
113
|
+
// If the single-line limit is on the second line of the file, the
|
|
114
|
+
// whole file is limited to that dialect.
|
|
115
|
+
//
|
|
116
|
+
// If the filter ends with `(lines commented)`, then ALL lines chosen
|
|
117
|
+
// by the filter will be uncommented.
|
|
118
|
+
package dbutil
|
|
@@ -60,24 +60,8 @@ func (ut *UpgradeTable) Register(from, to, compat int, message string, txn TxnMo
|
|
|
60
60
|
(*ut)[from] = upg
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// Syntax is either
|
|
64
|
-
//
|
|
65
|
-
// -- v0 -> v1: Message
|
|
66
|
-
//
|
|
67
|
-
// or
|
|
68
|
-
//
|
|
69
|
-
// -- v1: Message
|
|
70
|
-
//
|
|
71
|
-
// Both syntaxes may also have a compatibility notice before the colon:
|
|
72
|
-
//
|
|
73
|
-
// -- v5 (compatible with v3+): Upgrade with backwards compatibility
|
|
74
63
|
var upgradeHeaderRegex = regexp.MustCompile(`^-- (?:v(\d+) -> )?v(\d+)(?: \(compatible with v(\d+)\+\))?: (.+)$`)
|
|
75
64
|
|
|
76
|
-
// To disable wrapping the upgrade in a single transaction, put `--transaction: off` on the second line.
|
|
77
|
-
//
|
|
78
|
-
// -- v5: Upgrade without transaction
|
|
79
|
-
// -- transaction: off
|
|
80
|
-
// // do dangerous stuff
|
|
81
65
|
var transactionDisableRegex = regexp.MustCompile(`^-- transaction: ([a-z-]*)`)
|
|
82
66
|
|
|
83
67
|
func parseFileHeader(file []byte) (from, to, compat int, message string, txn TxnMode, lines [][]byte, err error) {
|
|
@@ -123,24 +107,6 @@ func parseFileHeader(file []byte) (from, to, compat int, message string, txn Txn
|
|
|
123
107
|
return
|
|
124
108
|
}
|
|
125
109
|
|
|
126
|
-
// To limit the next line to one dialect:
|
|
127
|
-
//
|
|
128
|
-
// -- only: postgres
|
|
129
|
-
//
|
|
130
|
-
// To limit the next N lines:
|
|
131
|
-
//
|
|
132
|
-
// -- only: sqlite for next 123 lines
|
|
133
|
-
//
|
|
134
|
-
// To limit a block of code, fenced by another directive:
|
|
135
|
-
//
|
|
136
|
-
// -- only: sqlite until "end only"
|
|
137
|
-
// QUERY;
|
|
138
|
-
// ANOTHER QUERY;
|
|
139
|
-
// -- end only sqlite
|
|
140
|
-
//
|
|
141
|
-
// If the single-line limit is on the second line of the file, the whole file is limited to that dialect.
|
|
142
|
-
//
|
|
143
|
-
// If the filter ends with `(lines commented)`, then ALL lines chosen by the filter will be uncommented.
|
|
144
110
|
var dialectLineFilter = regexp.MustCompile(`^\s*-- only: (postgres|sqlite)(?: for next (\d+) lines| until "(end) only")?(?: \(lines? (commented)\))?`)
|
|
145
111
|
|
|
146
112
|
// Constants used to make parseDialectFilter clearer
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copyright (c) 2025 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exbytes
|
|
8
|
+
|
|
9
|
+
import (
|
|
10
|
+
"unsafe"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
// UnsafeString returns a string that points to the same memory as the input byte slice.
|
|
14
|
+
//
|
|
15
|
+
// The input byte slice must not be modified after this function is called.
|
|
16
|
+
//
|
|
17
|
+
// See [go.mau.fi/util/exstrings.UnsafeBytes] for the reverse operation.
|
|
18
|
+
func UnsafeString(b []byte) string {
|
|
19
|
+
return unsafe.String(unsafe.SliceData(b), len(b))
|
|
20
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Copyright (c) 2024 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exbytes
|
|
8
|
+
|
|
9
|
+
import (
|
|
10
|
+
"errors"
|
|
11
|
+
"fmt"
|
|
12
|
+
"io"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
// Writer is a simple byte writer that does not allow extending the buffer.
|
|
16
|
+
//
|
|
17
|
+
// Writes always go after the current len() and will fail if the slice capacity is too low.
|
|
18
|
+
//
|
|
19
|
+
// The correct way to use this is to create a slice with sufficient capacity and zero length:
|
|
20
|
+
//
|
|
21
|
+
// x := make([]byte, 0, 11)
|
|
22
|
+
// w := (*Writer)(&x)
|
|
23
|
+
// w.Write([]byte("hello"))
|
|
24
|
+
// w.WriteByte(' ')
|
|
25
|
+
// w.WriteString("world")
|
|
26
|
+
// fmt.Println(string(x)) // "hello world"
|
|
27
|
+
type Writer []byte
|
|
28
|
+
|
|
29
|
+
var ErrWriterBufferFull = errors.New("exbytes.Writer: buffer full")
|
|
30
|
+
|
|
31
|
+
var (
|
|
32
|
+
_ io.Writer = (*Writer)(nil)
|
|
33
|
+
_ io.StringWriter = (*Writer)(nil)
|
|
34
|
+
_ io.ByteWriter = (*Writer)(nil)
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
func (w *Writer) extendLen(n int) (int, error) {
|
|
38
|
+
ptr := len(*w)
|
|
39
|
+
if ptr+n > cap(*w) {
|
|
40
|
+
return 0, fmt.Errorf("%w (%d + %d > %d)", ErrWriterBufferFull, ptr, n, cap(*w))
|
|
41
|
+
}
|
|
42
|
+
*w = (*w)[:ptr+n]
|
|
43
|
+
return ptr, nil
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func (w *Writer) Write(b []byte) (n int, err error) {
|
|
47
|
+
ptr, err := w.extendLen(len(b))
|
|
48
|
+
if err != nil {
|
|
49
|
+
return 0, err
|
|
50
|
+
}
|
|
51
|
+
copy((*w)[ptr:], b)
|
|
52
|
+
return len(b), nil
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func (w *Writer) WriteString(s string) (n int, err error) {
|
|
56
|
+
ptr, err := w.extendLen(len(s))
|
|
57
|
+
if err != nil {
|
|
58
|
+
return 0, err
|
|
59
|
+
}
|
|
60
|
+
copy((*w)[ptr:], s)
|
|
61
|
+
return len(s), nil
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
func (w *Writer) WriteByte(r byte) error {
|
|
65
|
+
ptr, err := w.extendLen(1)
|
|
66
|
+
if err != nil {
|
|
67
|
+
return err
|
|
68
|
+
}
|
|
69
|
+
(*w)[ptr] = r
|
|
70
|
+
return nil
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
func (w *Writer) String() string {
|
|
74
|
+
if w == nil {
|
|
75
|
+
return "<nil>"
|
|
76
|
+
}
|
|
77
|
+
return string(*w)
|
|
78
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright (c) 2024 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exslices
|
|
8
|
+
|
|
9
|
+
func CastFunc[To, From any](source []From, conv func(From) To) []To {
|
|
10
|
+
result := make([]To, len(source))
|
|
11
|
+
for i, v := range source {
|
|
12
|
+
result[i] = conv(v)
|
|
13
|
+
}
|
|
14
|
+
return result
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func CastFuncFilter[To, From any](source []From, conv func(From) (To, bool)) []To {
|
|
18
|
+
result := make([]To, 0, len(source))
|
|
19
|
+
for _, v := range source {
|
|
20
|
+
res, ok := conv(v)
|
|
21
|
+
if ok {
|
|
22
|
+
result = append(result, res)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return result
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
func CastToString[To, From ~string](source []From) []To {
|
|
29
|
+
result := make([]To, len(source))
|
|
30
|
+
for i, v := range source {
|
|
31
|
+
result[i] = To(v)
|
|
32
|
+
}
|
|
33
|
+
return result
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func CastToAny[From any](source []From) []any {
|
|
37
|
+
result := make([]any, len(source))
|
|
38
|
+
for i, v := range source {
|
|
39
|
+
result[i] = v
|
|
40
|
+
}
|
|
41
|
+
return result
|
|
42
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright (c) 2024 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exslices
|
|
8
|
+
|
|
9
|
+
// Chunk splits a slice into chunks of the given size.
|
|
10
|
+
//
|
|
11
|
+
// From https://github.com/golang/go/issues/53987#issuecomment-1224367139
|
|
12
|
+
//
|
|
13
|
+
// TODO remove this after slices.Chunk can be used (it'll probably be added in Go 1.23, so it can be used after 1.22 is EOL)
|
|
14
|
+
func Chunk[T any](slice []T, size int) (chunks [][]T) {
|
|
15
|
+
if size < 1 {
|
|
16
|
+
panic("chunk size cannot be less than 1")
|
|
17
|
+
}
|
|
18
|
+
for i := 0; ; i++ {
|
|
19
|
+
next := i * size
|
|
20
|
+
if len(slice[next:]) > size {
|
|
21
|
+
end := next + size
|
|
22
|
+
chunks = append(chunks, slice[next:end:end])
|
|
23
|
+
} else {
|
|
24
|
+
chunks = append(chunks, slice[i*size:])
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Copyright (c) 2024 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exslices
|
|
8
|
+
|
|
9
|
+
// DeduplicateUnsorted removes duplicates from the given slice without requiring that the input slice is sorted.
|
|
10
|
+
// The order of the output will be the same as the input. The input slice will not be modified.
|
|
11
|
+
//
|
|
12
|
+
// If you don't care about the order of the output, it's recommended to sort the list and then use [slices.Compact].
|
|
13
|
+
func DeduplicateUnsorted[T comparable](s []T) []T {
|
|
14
|
+
return deduplicateUnsortedInto(s, make([]T, 0, len(s)))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// DeduplicateUnsortedOverwrite removes duplicates from the given slice without requiring that the input slice is sorted.
|
|
18
|
+
// The input slice will be modified and used as the output slice to avoid extra allocations.
|
|
19
|
+
//
|
|
20
|
+
// If you don't care about the order of the output, it's recommended to sort the list and then use [slices.Compact].
|
|
21
|
+
func DeduplicateUnsortedOverwrite[T comparable](s []T) []T {
|
|
22
|
+
out := deduplicateUnsortedInto(s, s[:0])
|
|
23
|
+
clear(s[len(out):])
|
|
24
|
+
return out
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func deduplicateUnsortedInto[T comparable](s, result []T) []T {
|
|
28
|
+
seen := make(map[T]struct{}, len(s))
|
|
29
|
+
for _, item := range s {
|
|
30
|
+
if _, ok := seen[item]; !ok {
|
|
31
|
+
seen[item] = struct{}{}
|
|
32
|
+
result = append(result, item)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return result
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// DeduplicateUnsortedFunc removes duplicates from the given slice using the given key function without requiring
|
|
39
|
+
// that the input slice is sorted. The order of the output will be the same as the input.
|
|
40
|
+
//
|
|
41
|
+
// If you don't care about the order of the output, it's recommended to sort the list and then use [slices.CompactFunc].
|
|
42
|
+
func DeduplicateUnsortedFunc[T any, K comparable](s []T, getKey func(T) K) []T {
|
|
43
|
+
return deduplicateUnsortedFuncInto(s, make([]T, 0, len(s)), getKey)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// DeduplicateUnsortedOverwriteFunc removes duplicates from the given slice using the given key function
|
|
47
|
+
// without requiring that the input slice is sorted. The order of the output will be the same as the input.
|
|
48
|
+
// The input slice will be modified and used as the output slice to avoid extra allocations.
|
|
49
|
+
//
|
|
50
|
+
// If you don't care about the order of the output, it's recommended to sort the list and then use [slices.CompactFunc].
|
|
51
|
+
func DeduplicateUnsortedOverwriteFunc[T any, K comparable](s []T, getKey func(T) K) []T {
|
|
52
|
+
out := deduplicateUnsortedFuncInto(s, s[:0], getKey)
|
|
53
|
+
clear(s[len(out):])
|
|
54
|
+
return out
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
func deduplicateUnsortedFuncInto[T any, K comparable](s, result []T, getKey func(T) K) []T {
|
|
58
|
+
seen := make(map[K]struct{}, len(s))
|
|
59
|
+
for _, item := range s {
|
|
60
|
+
key := getKey(item)
|
|
61
|
+
if _, ok := seen[key]; !ok {
|
|
62
|
+
seen[key] = struct{}{}
|
|
63
|
+
result = append(result, item)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return result
|
|
67
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright (c) 2023 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exslices
|
|
8
|
+
|
|
9
|
+
// SortedDiff returns the difference between two already-sorted slices, with the help of the given comparison function.
|
|
10
|
+
// The output will be in the same order as the input, which means it'll be sorted.
|
|
11
|
+
func SortedDiff[T any](a, b []T, compare func(a, b T) int) (uniqueToA, uniqueToB []T) {
|
|
12
|
+
uniqueToA = make([]T, 0, len(a))
|
|
13
|
+
uniqueToB = make([]T, 0, len(b))
|
|
14
|
+
|
|
15
|
+
var i, j int
|
|
16
|
+
for {
|
|
17
|
+
if j >= len(b) {
|
|
18
|
+
uniqueToA = append(uniqueToA, a[i:]...)
|
|
19
|
+
break
|
|
20
|
+
} else if i >= len(a) {
|
|
21
|
+
uniqueToB = append(uniqueToB, b[j:]...)
|
|
22
|
+
break
|
|
23
|
+
}
|
|
24
|
+
c := compare(a[i], b[j])
|
|
25
|
+
if c < 0 {
|
|
26
|
+
uniqueToA = append(uniqueToA, a[i])
|
|
27
|
+
i++
|
|
28
|
+
} else if c > 0 {
|
|
29
|
+
uniqueToB = append(uniqueToB, b[j])
|
|
30
|
+
j++
|
|
31
|
+
} else {
|
|
32
|
+
i++
|
|
33
|
+
j++
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Diff returns the difference between two slices. The slices may contain duplicates and don't need to be sorted.
|
|
40
|
+
// The output will not be sorted, but is guaranteed to not contain any duplicates.
|
|
41
|
+
func Diff[T comparable](a, b []T) (uniqueToA, uniqueToB []T) {
|
|
42
|
+
maxLen := len(a)
|
|
43
|
+
if len(b) > maxLen {
|
|
44
|
+
maxLen = len(b)
|
|
45
|
+
}
|
|
46
|
+
collector := make(map[T]uint8, maxLen)
|
|
47
|
+
for _, item := range a {
|
|
48
|
+
collector[item] |= 0b01
|
|
49
|
+
}
|
|
50
|
+
for _, item := range b {
|
|
51
|
+
collector[item] |= 0b10
|
|
52
|
+
}
|
|
53
|
+
uniqueToA = make([]T, 0, maxLen)
|
|
54
|
+
uniqueToB = make([]T, 0, maxLen)
|
|
55
|
+
for item, mask := range collector {
|
|
56
|
+
if mask == 0b01 {
|
|
57
|
+
uniqueToA = append(uniqueToA, item)
|
|
58
|
+
} else if mask == 0b10 {
|
|
59
|
+
uniqueToB = append(uniqueToB, item)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return
|
|
63
|
+
}
|
|
@@ -8,6 +8,7 @@ package exsync
|
|
|
8
8
|
|
|
9
9
|
import (
|
|
10
10
|
"context"
|
|
11
|
+
"fmt"
|
|
11
12
|
"sync"
|
|
12
13
|
"time"
|
|
13
14
|
)
|
|
@@ -50,7 +51,7 @@ func (e *Event) Wait(ctx context.Context) error {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
// WaitTimeout waits for
|
|
54
|
+
// WaitTimeout waits for the event to happen within the given timeout.
|
|
54
55
|
// If the timeout expires first, the return value is false, otherwise it's true.
|
|
55
56
|
func (e *Event) WaitTimeout(timeout time.Duration) bool {
|
|
56
57
|
select {
|
|
@@ -61,6 +62,19 @@ func (e *Event) WaitTimeout(timeout time.Duration) bool {
|
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
// WaitTimeoutCtx waits for the event to happen, the timeout to expire, or the given context to be done.
|
|
66
|
+
// If the context or timeout is done first, an error is returned, otherwise the return value is nil.
|
|
67
|
+
func (e *Event) WaitTimeoutCtx(ctx context.Context, timeout time.Duration) error {
|
|
68
|
+
select {
|
|
69
|
+
case <-e.GetChan():
|
|
70
|
+
return nil
|
|
71
|
+
case <-ctx.Done():
|
|
72
|
+
return ctx.Err()
|
|
73
|
+
case <-time.After(timeout):
|
|
74
|
+
return fmt.Errorf("exsync.Event: wait timeout")
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
64
78
|
// IsSet returns true if the event has been set.
|
|
65
79
|
func (e *Event) IsSet() bool {
|
|
66
80
|
e.l.RLock()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c)
|
|
1
|
+
// Copyright (c) 2025 Tulir Asokan
|
|
2
2
|
//
|
|
3
3
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
4
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
@@ -10,20 +10,52 @@ import (
|
|
|
10
10
|
"encoding/binary"
|
|
11
11
|
"hash/crc32"
|
|
12
12
|
"strings"
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
"go.mau.fi/util/exbytes"
|
|
14
15
|
)
|
|
15
16
|
|
|
16
17
|
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
17
18
|
|
|
18
19
|
// StringBytes generates a random string of the given length and returns it as a byte array.
|
|
19
20
|
func StringBytes(n int) []byte {
|
|
21
|
+
return StringBytesCharset(n, letters)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// AppendSequence generates a random sequence of the given length using the given character set
|
|
25
|
+
// and appends it to the given output slice.
|
|
26
|
+
func AppendSequence[T any](n int, charset, output []T) []T {
|
|
27
|
+
if n <= 0 {
|
|
28
|
+
return output
|
|
29
|
+
}
|
|
30
|
+
if output == nil {
|
|
31
|
+
output = make([]T, 0, n)
|
|
32
|
+
}
|
|
33
|
+
// If risk of modulo bias is too high, use 32-bit integers as source instead of 16-bit.
|
|
34
|
+
if 65536%len(charset) < 200 {
|
|
35
|
+
input := Bytes(n * 2)
|
|
36
|
+
for i := 0; i < n; i++ {
|
|
37
|
+
output = append(output, charset[binary.BigEndian.Uint16(input[i*2:])%uint16(len(charset))])
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
input := Bytes(n * 4)
|
|
41
|
+
for i := 0; i < n; i++ {
|
|
42
|
+
output = append(output, charset[binary.BigEndian.Uint32(input[i*4:])%uint32(len(charset))])
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return output
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// StringBytesCharset generates a random string of the given length using the given character set and returns it as a byte array.
|
|
49
|
+
// Note that the character set must be ASCII. For arbitrary Unicode, use [AppendSequence] with a `[]rune`.
|
|
50
|
+
func StringBytesCharset(n int, charset string) []byte {
|
|
20
51
|
if n <= 0 {
|
|
21
52
|
return []byte{}
|
|
22
53
|
}
|
|
23
54
|
input := Bytes(n * 2)
|
|
24
55
|
for i := 0; i < n; i++ {
|
|
25
|
-
//
|
|
26
|
-
|
|
56
|
+
// The risk of modulo bias is (65536 % len(charset)) / 65536.
|
|
57
|
+
// For the default charset, that's 2 in 65536 or 0.003 %.
|
|
58
|
+
input[i] = charset[binary.BigEndian.Uint16(input[i*2:])%uint16(len(charset))]
|
|
27
59
|
}
|
|
28
60
|
input = input[:n]
|
|
29
61
|
return input
|
|
@@ -34,8 +66,16 @@ func String(n int) string {
|
|
|
34
66
|
if n <= 0 {
|
|
35
67
|
return ""
|
|
36
68
|
}
|
|
37
|
-
|
|
38
|
-
|
|
69
|
+
return exbytes.UnsafeString(StringBytes(n))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// StringCharset generates a random string of the given length using the given character set.
|
|
73
|
+
// Note that the character set must be ASCII. For arbitrary Unicode, use [AppendSequence] with a `[]rune`.
|
|
74
|
+
func StringCharset(n int, charset string) string {
|
|
75
|
+
if n <= 0 {
|
|
76
|
+
return ""
|
|
77
|
+
}
|
|
78
|
+
return exbytes.UnsafeString(StringBytesCharset(n, charset))
|
|
39
79
|
}
|
|
40
80
|
|
|
41
81
|
func base62Encode(val uint32, minWidth int) []byte {
|
|
@@ -65,7 +105,7 @@ func Token(namespace string, randomLength int) string {
|
|
|
65
105
|
token[len(namespace)+randomLength+1] = '_'
|
|
66
106
|
checksum := base62Encode(crc32.ChecksumIEEE(token[:len(token)-7]), 6)
|
|
67
107
|
copy(token[len(token)-6:], checksum)
|
|
68
|
-
return
|
|
108
|
+
return exbytes.UnsafeString(token)
|
|
69
109
|
}
|
|
70
110
|
|
|
71
111
|
// GetTokenPrefix parses the given token generated with Token, validates the checksum and returns the prefix namespace.
|
|
@@ -166,6 +166,7 @@ func (proc *Processor) decodeMutations(ctx context.Context, mutations []*waServe
|
|
|
166
166
|
out.Mutations = append(out.Mutations, Mutation{
|
|
167
167
|
Operation: mutation.GetOperation(),
|
|
168
168
|
Action: syncAction.GetValue(),
|
|
169
|
+
Version: syncAction.GetVersion(),
|
|
169
170
|
Index: index,
|
|
170
171
|
IndexMAC: indexMAC,
|
|
171
172
|
ValueMAC: valueMAC,
|
|
@@ -45,7 +45,11 @@ func BuildMute(target types.JID, mute bool, muteDuration time.Duration) PatchInf
|
|
|
45
45
|
if muteDuration > 0 {
|
|
46
46
|
muteEndTimestamp = proto.Int64(time.Now().Add(muteDuration).UnixMilli())
|
|
47
47
|
}
|
|
48
|
+
return BuildMuteAbs(target, mute, muteEndTimestamp)
|
|
49
|
+
}
|
|
48
50
|
|
|
51
|
+
// BuildMuteAbs builds an app state patch for muting or unmuting a chat with an absolute timestamp.
|
|
52
|
+
func BuildMuteAbs(target types.JID, mute bool, muteEndTimestamp *int64) PatchInfo {
|
|
49
53
|
return PatchInfo{
|
|
50
54
|
Type: WAPatchRegularHigh,
|
|
51
55
|
Mutations: []MutationInfo{{
|
|
@@ -126,6 +130,36 @@ func BuildArchive(target types.JID, archive bool, lastMessageTimestamp time.Time
|
|
|
126
130
|
return result
|
|
127
131
|
}
|
|
128
132
|
|
|
133
|
+
// BuildMarkChatAsRead builds an app state patch for marking a chat as read or unread.
|
|
134
|
+
func BuildMarkChatAsRead(target types.JID, read bool, lastMessageTimestamp time.Time, lastMessageKey *waCommon.MessageKey) PatchInfo {
|
|
135
|
+
if lastMessageTimestamp.IsZero() {
|
|
136
|
+
lastMessageTimestamp = time.Now()
|
|
137
|
+
}
|
|
138
|
+
action := &waSyncAction.MarkChatAsReadAction{
|
|
139
|
+
Read: proto.Bool(read),
|
|
140
|
+
MessageRange: &waSyncAction.SyncActionMessageRange{
|
|
141
|
+
LastMessageTimestamp: proto.Int64(lastMessageTimestamp.Unix()),
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
if lastMessageKey != nil {
|
|
145
|
+
action.MessageRange.Messages = []*waSyncAction.SyncActionMessage{{
|
|
146
|
+
Key: lastMessageKey,
|
|
147
|
+
Timestamp: proto.Int64(lastMessageTimestamp.Unix()),
|
|
148
|
+
}}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return PatchInfo{
|
|
152
|
+
Type: WAPatchRegularLow,
|
|
153
|
+
Mutations: []MutationInfo{{
|
|
154
|
+
Index: []string{IndexMarkChatAsRead, target.String()},
|
|
155
|
+
Version: 3,
|
|
156
|
+
Value: &waSyncAction.SyncActionValue{
|
|
157
|
+
MarkChatAsReadAction: action,
|
|
158
|
+
},
|
|
159
|
+
}},
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
129
163
|
func newLabelChatMutation(target types.JID, labelID string, labeled bool) MutationInfo {
|
|
130
164
|
return MutationInfo{
|
|
131
165
|
Index: []string{IndexLabelAssociationChat, labelID, target.String()},
|