1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-07 21:37:04 +09:00

Merge branch 'main' of github.com:anyproto/anytype-heart into go-4144-refactor-internal-details-structure

# Conflicts:
#	core/block/editor/profile.go
#	core/block/editor/smartblock/smartblock.go
#	core/block/editor/state/event.go
#	core/block/editor/state/state.go
#	core/block/editor/state/state_test.go
#	core/block/import/common/objectid/fileobject.go
#	core/block/import/common/objectid/oldfile.go
#	core/block/simple/link/link.go
#	core/block/simple/text/details.go
#	core/subscription/context.go
#	core/subscription/crossspacesub/service_test.go
#	core/subscription/internalsub_test.go
#	core/subscription/objectsubscription/objsubscription_test.go
This commit is contained in:
Sergey 2024-12-18 13:30:46 +01:00
commit ad02ae4bd1
No known key found for this signature in database
GPG key ID: 3B6BEF79160221C6
86 changed files with 1593 additions and 1430 deletions

View file

@ -2,10 +2,14 @@
on:
workflow_dispatch:
inputs:
run-on-runner:
description: 'Specify the runner to use'
run-on-runner-mac:
description: 'Specify the runner to use on MacOS'
required: true
default: 'ARM64'
run-on-runner-win:
description: 'Specify the runner to use on Windows'
required: true
default: 'windows-perftests'
perf-test:
description: 'Run perf test times'
required: true
@ -17,7 +21,6 @@ on:
include:
- 'main'
permissions:
actions: 'write'
contents: 'write'
@ -25,7 +28,7 @@ permissions:
name: Perf tests
jobs:
build:
perftests-macos:
timeout-minutes: 60
runs-on: 'ARM64'
steps:
@ -76,7 +79,7 @@ jobs:
RUN_COUNT=${{ github.event.inputs.perf-test }}
if [[ "${{ github.event_name }}" == "schedule" ]]; then
RUN_COUNT=10
fi
fi
echo $PERF_CONFIG_STAGING > config.json
mv .github/staging_fake.yml staging_fake.yml
PERF_CONFIG=$PWD/config.json
@ -97,6 +100,165 @@ jobs:
- name: Archive perf tests results
uses: actions/upload-artifact@v4
with:
name: traces
name: traces-macos
path: |
*.log
*.log
perftests-windows:
timeout-minutes: 60
runs-on: 'windows-perftests'
steps:
- name: Install windows utils
run: C:\ProgramData\chocolatey\bin\choco install gzip mingw git -y
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: false
- name: Setup Go env
run: |
go version
echo GOPATH=$(go env GOPATH) >> $env:GITHUB_ENV
echo GOBIN=$(go env GOPATH)\bin >> $env:GITHUB_ENV
echo $(go env GOPATH)\bin >> $env:GITHUB_PATH
- name: Checkout
uses: actions/checkout@v4.2.2
- name: Set env vars
env:
UNSPLASH_KEY: ${{ secrets.UNSPLASH_KEY }}
INHOUSE_KEY: ${{ secrets.INHOUSE_KEY }}
run: |
$GIT_SUMMARY = git describe --tags --always
echo "FLAGS=-X github.com/anyproto/anytype-heart/util/vcs.GitSummary=$GIT_SUMMARY -X github.com/anyproto/anytype-heart/metrics.DefaultInHouseKey=$env:INHOUSE_KEY -X github.com/anyproto/anytype-heart/util/unsplash.DefaultToken=$env:UNSPLASH_KEY" >> $env:GITHUB_ENV
if ($env:GITHUB_EVENT_NAME -eq "workflow_dispatch") {
$VERSION = ${{ github.event.inputs.alpha_version }}
if (-not $VERSION) {
$VERSION = git rev-parse --short HEAD
}
}
if (-not $VERSION) {
$VERSION = ($env:GITHUB_REF -split "/")[-1]
}
echo "VERSION=$VERSION" >> $env:GITHUB_ENV
echo "MAVEN_ARTIFACT_VERSION=$VERSION" >> $env:GITHUB_ENV
echo "GOPRIVATE=github.com/anyproto" >> $env:GITHUB_ENV
echo "$(Get-Location)\deps" >> $env:GITHUB_PATH
echo "$env:GOBIN" >> $env:GITHUB_PATH
git config --global url."https://${{ secrets.ANYTYPE_PAT }}@github.com/".insteadOf "https://github.com/"
- name: Go mod download
run: |
go mod download
- name: Setup network config
env:
CUSTOM_NETWORK_FILE: ./core/anytype/config/nodes/custom.yml
run: |
if (-not $env:ANY_SYNC_NETWORK) {
echo "Using the default production Any Sync Network"
} elseif (-not (Test-Path $env:ANY_SYNC_NETWORK)) {
echo "Network configuration file not found at $env:ANY_SYNC_NETWORK"
exit 1
} else {
echo "Using Any Sync Network configuration at $env:ANY_SYNC_NETWORK"
Copy-Item -Path $env:ANY_SYNC_NETWORK -Destination $CUSTOM_NETWORK_FILE -Force
}
- name: Check and download tantivy
env:
TANTIVY_GO_PATH: ../tantivy-go
OUTPUT_DIR: deps/libs
REPO: anyproto/tantivy-go
run: |
$TANTIVY_VERSION = (Get-Content go.mod | Select-String "github.com/anyproto/tantivy-go" | ForEach-Object { ($_ -split " ")[1] }).Trim()
$TANTIVY_LIBS = @(
"windows-amd64.tar.gz"
)
if (-not (Test-Path "$env:OUTPUT_DIR/.verified") -or (Get-Content "$env:OUTPUT_DIR/.verified").Trim() -ne $TANTIVY_VERSION) {
if (Test-Path "$env:OUTPUT_DIR") {
Remove-Item -Recurse -Force "$env:OUTPUT_DIR/*"
}
if (-not (Test-Path "$env:OUTPUT_DIR")) {
New-Item -ItemType Directory -Path "$env:OUTPUT_DIR" | Out-Null
}
foreach ($lib in $TANTIVY_LIBS) {
$downloadUrl = "https://github.com/$env:REPO/releases/download/$TANTIVY_VERSION/$lib"
$localFilePath = "$env:OUTPUT_DIR/$lib"
Invoke-WebRequest -Uri $downloadUrl -OutFile $localFilePath
$extractDir = "$env:OUTPUT_DIR/$($lib -replace '.tar.gz', '')"
if (-not (Test-Path $extractDir)) {
New-Item -ItemType Directory -Path $extractDir | Out-Null
}
tar -C $extractDir -xvzf $localFilePath
}
Get-ChildItem -Path "$env:OUTPUT_DIR" -Filter "*.tar.gz" | Remove-Item -Force
Set-Content -Path "$env:OUTPUT_DIR/.verified" -Value $TANTIVY_VERSION
echo "Tantivy libraries updated successfully."
} else {
echo "Tantivy libraries are up to date."
}
- name: Install grpcurl and govvv
run: |
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
go install github.com/ahmetb/govvv@v0.2.0
- name: Run perf tests
run: |
echo "Running perf tests in staging mode..."
if ($env:GITHUB_EVENT_NAME -eq "schedule") {
$RUN_COUNT = 10
} elseif ("${{ github.event.inputs.perf-test }}" -ne "") {
$RUN_COUNT = "${{ github.event.inputs.perf-test }}"
} else {
$RUN_COUNT = 10 # default value
}
echo "Current RUN_COUNT: $RUN_COUNT"
echo "Current Github event name: $env:GITHUB_EVENT_NAME"
Set-Content -Path config.json -Value $env:PERF_CONFIG_STAGING
(Get-Content config.json).Replace('"/Users/user1/account30000"', '"C:/Users/' + $env:USERNAME + '"') | Set-Content -Path config.json
Move-Item -Path .\.github\staging_fake.yml -Destination .\staging_fake.yml -Force
$PERF_CONFIG = ((Get-Location).Path -replace '\\', '/') + "/config.json"
Set-Location cmd\perfstand\account_create
$env:CGO_ENABLED = "1"
go run main.go $PERF_CONFIG $RUN_COUNT
Set-Location ..\account_select
go run main.go $PERF_CONFIG $RUN_COUNT
echo "Perf test with staging - done"
echo "Running perf tests in local mode..."
Set-Location (Resolve-Path "../../..")
Set-Content -Path config.json -Value $env:PERF_CONFIG_LOCAL
(Get-Content config.json).Replace('"/Users/user1/account30000"', '"C:/Users/' + $env:USERNAME + '"') | Set-Content -Path config.json
Set-Location cmd\perfstand\account_create
$env:CGO_ENABLED = "1"
go run main.go $PERF_CONFIG $RUN_COUNT
Set-Location ..\account_select
go run main.go $PERF_CONFIG $RUN_COUNT
echo "Perf test in local mode - done"
env:
PERF_CONFIG_STAGING: ${{ secrets.PERF_CONFIG_STAGING }}
PERF_CONFIG_LOCAL: ${{ secrets.PERF_CONFIG_LOCAL }}
CH_API_KEY: ${{ secrets.CH_PERF_API_KEY }}
- name: Clean /tmp
run: |
echo "Clean workspaces in /Temp"
Get-ChildItem "C:/Users/$env:USERNAME/AppData/Local/Temp/" -Directory -Force | Where-Object { $_.Name -like "workspace*" } | ForEach-Object { Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
- name: Archive perf tests results
uses: actions/upload-artifact@v4
with:
name: traces-win
path: |
*.log

View file

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/exec"
"runtime"
"go.uber.org/atomic"
@ -58,10 +59,18 @@ func main() {
func iterate(prep *input, result internal.PerfResult) error {
workspace, err := os.MkdirTemp("", "workspace")
prep.Workspace = workspace
if err != nil {
return err
}
if runtime.GOOS == "windows" {
workspace, err = internal.WinFixPath(workspace)
if err != nil {
return err
}
}
prep.Workspace = workspace
defer os.RemoveAll(workspace)
fmt.Println("Created temporary directory:", workspace)
@ -79,7 +88,13 @@ func iterate(prep *input, result internal.PerfResult) error {
return err
}
walletStr, err := exec.Command("bash", "-c", internal.GrpcWalletCreate(workspace)).Output()
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("powershell", "-Command", internal.GrpcWalletCreate(workspace))
} else {
cmd = exec.Command("bash", "-c", internal.GrpcWalletCreate(workspace))
}
walletStr, err := cmd.Output()
if err != nil {
return err
}

View file

@ -80,12 +80,23 @@ func SendResultsToHttp(apiKey string, events []Event) error {
}
func KillServer() error {
return ExecuteCommand("kill -9 $(lsof -i :31007 -t) ; echo \"Server killed\"")
var cmd string
if runtime.GOOS == "windows" {
cmd = `(Get-NetTCPConnection -LocalPort 31007 -State Listen | Select-Object -ExpandProperty OwningProcess | ForEach-Object { Stop-Process -Id $_ -Force -ErrorAction SilentlyContinue }) ; Write-Host "Server killed"`
} else {
cmd = "kill -9 $(lsof -i :31007 -t) ; echo \"Server killed\""
}
return ExecuteCommand(cmd)
}
func ExecuteCommand(command string) error {
fmt.Println(command)
cmd := exec.Command("bash", "-c", command)
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("powershell", "-Command", command)
} else {
cmd = exec.Command("bash", "-c", command)
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
@ -96,7 +107,10 @@ func ExecuteCommand(command string) error {
}
func UnpackZip(path string, workspace string) error {
return ExecuteCommand("unzip -o " + path + " -d " + workspace)
if runtime.GOOS == "windows" {
return ExecuteCommand("Expand-Archive -Path " + path + " -DestinationPath " + workspace + " -Force")
}
return ExecuteCommand("unzip -qq -o " + path + " -d " + workspace)
}
func BuildAnytype(err error) error {
@ -117,6 +131,10 @@ func LoadEnv(env string) (string, error) {
return res, nil
}
func WinFixPath(winPath string) (string, error) {
return strings.ReplaceAll(winPath, "\\", "/"), nil
}
func SetupWd() (string, error) {
err := os.Chdir("../../..")
if err != nil {
@ -128,22 +146,42 @@ func SetupWd() (string, error) {
return "", err
}
if runtime.GOOS == "windows" {
getwd, err = WinFixPath(getwd)
if err != nil {
return "", err
}
}
fmt.Println("Current working directory:", getwd)
return getwd, nil
}
func GrpcWorkspaceOpen(workspace string) string {
if runtime.GOOS == "windows" {
return `cmd.exe /c 'grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d "{\"spaceId\":\"` + workspace + `\"}" localhost:31007 anytype.ClientCommands.WorkspaceOpen'`
}
return `grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{
"spaceId": "` + workspace + `"
}' localhost:31007 anytype.ClientCommands.WorkspaceOpen`
}
func GrpcWorkspaceCreate() string {
if runtime.GOOS == "windows" {
return `cmd.exe /c 'grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d "{}" localhost:31007 anytype.ClientCommands.WorkspaceCreate'`
}
return `grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{
}' localhost:31007 anytype.ClientCommands.WorkspaceCreate`
}
func GrpcAccountSelect(accHash, workspace, networkMode, staging string) string {
if runtime.GOOS == "windows" {
staging, err := WinFixPath(staging)
if err != nil {
return "Error: " + err.Error()
}
return `cmd.exe /c 'grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d "{\"id\":\"` + accHash + `\",\"rootPath\":\"` + workspace + `\",\"disableLocalNetworkSync\":false,\"networkMode\":` + networkMode + `,\"networkCustomConfigFilePath\":\"` + staging + `\"}" localhost:31007 anytype.ClientCommands.AccountSelect'`
}
return `grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{
"id": "` + accHash + `",
"rootPath": "` + workspace + `",
@ -154,12 +192,18 @@ func GrpcAccountSelect(accHash, workspace, networkMode, staging string) string {
}
func GrpcWalletCreateSession(mnemonic string) string {
if runtime.GOOS == "windows" {
return `cmd.exe /c 'grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d "{\"mnemonic\":\"` + mnemonic + `\"}" localhost:31007 anytype.ClientCommands.WalletCreateSession'`
}
return `grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{
"mnemonic": "` + mnemonic + `"
}' localhost:31007 anytype.ClientCommands.WalletCreateSession`
}
func GrpcWalletRecover(workspace, mnemonic string) string {
if runtime.GOOS == "windows" {
return `cmd.exe /c 'grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d "{\"rootPath\":\"` + workspace + `\",\"mnemonic\":\"` + mnemonic + `\"}" localhost:31007 anytype.ClientCommands.WalletRecover'`
}
return `grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{
"rootPath": "` + workspace + `",
"mnemonic": "` + mnemonic + `"
@ -167,12 +211,22 @@ func GrpcWalletRecover(workspace, mnemonic string) string {
}
func GrpcWalletCreate(workspace string) string {
if runtime.GOOS == "windows" {
return `cmd.exe /c 'grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d "{\"rootPath\":\"` + workspace + `\"}" localhost:31007 anytype.ClientCommands.WalletCreate'`
}
return `grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{
"rootPath": "` + workspace + `"
}' localhost:31007 anytype.ClientCommands.WalletCreate`
}
func GrpcAccountCreate(workspace, networkMode, staging string) string {
if runtime.GOOS == "windows" {
staging, err := WinFixPath(staging)
if err != nil {
return "Error: " + err.Error()
}
return `cmd.exe /c 'grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d "{\"icon\":13,\"networkMode\":` + networkMode + `,\"storePath\":\"` + workspace + `\",\"networkCustomConfigFilePath\":\"` + staging + `\"}" localhost:31007 anytype.ClientCommands.AccountCreate'`
}
return `grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{
"icon": 13,
"networkMode": ` + networkMode + `,
@ -182,6 +236,9 @@ func GrpcAccountCreate(workspace, networkMode, staging string) string {
}
func GrpcInitialSetParameters() string {
if runtime.GOOS == "windows" {
return `cmd.exe /c 'grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d "{\"platform\":\"test\",\"version\":\"0.0.0-test\"}" localhost:31007 anytype.ClientCommands.InitialSetParameters'`
}
return `grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{
"platform": "test",
"version": "0.0.0-test"
@ -189,7 +246,12 @@ func GrpcInitialSetParameters() string {
}
func StartAnytypeBackground() error {
runServer := exec.Command("./dist/server")
var runServer *exec.Cmd
if runtime.GOOS == "windows" {
runServer = exec.Command("./dist/server.exe")
} else {
runServer = exec.Command("./dist/server")
}
runServer.Stdout = os.Stdout
runServer.Stderr = os.Stderr
runServer.Env = append(os.Environ(), `ANYPROF=:6060`)
@ -200,7 +262,15 @@ func StartAnytypeBackground() error {
// Wait for the server to start
for {
err = ExecuteCommand(`pids=$(lsof -i :31007 -t) && [ -n "$pids" ] && echo "Found process: $pids" || { echo "No process found"; exit 1; }`)
var cmd string
if runtime.GOOS == "windows" {
cmd = `$pids = (Get-NetTCPConnection -LocalPort 31007 -State Listen -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess); if ($pids) { Write-Output "Found process: $pids" } else { Write-Output "No process found"; exit 1 }`
} else {
cmd = `pids=$(lsof -i :31007 -t) && [ -n "$pids" ] && echo "Found process: $pids" || { echo "No process found"; exit 1; }`
}
err = ExecuteCommand(cmd)
if err == nil {
break
} else {
@ -466,8 +536,18 @@ func Prepare[T BasicInputtable](prep T, f func(T) error) error {
if err != nil {
return err
}
fmt.Println("Created temporary directory:", workspace)
prep.SetWorkspace(workspace)
if runtime.GOOS == "windows" {
winWorkspace, err := WinFixPath(workspace)
if err != nil {
return err
}
fmt.Println("Created temporary directory:", winWorkspace)
prep.SetWorkspace(winWorkspace)
} else {
fmt.Println("Created temporary directory:", workspace)
prep.SetWorkspace(workspace)
}
_, err = SetupWd()
if err != nil {
@ -486,10 +566,29 @@ func Prepare[T BasicInputtable](prep T, f func(T) error) error {
}
}
err = BuildAnytype(err)
if err != nil {
return err
if runtime.GOOS == "windows" {
fmt.Printf("Build GRPC server on Windows...")
command := `
$Env:GOOS="windows";
$Env:GOARCH="amd64";
$Env:CGO_ENABLED="1";
$Env:CC="x86_64-w64-mingw32-gcc";
$Env:CXX="x86_64-w64-mingw32-g++";
go build -o dist/server.exe -ldflags "$env:FLAGS -linkmode external -extldflags=-static" --tags "noauth nosigar nowatchdog" $env:BUILD_FLAGS github.com/anyproto/anytype-heart/cmd/grpcserver
`
err := ExecuteCommand(command)
if err != nil {
fmt.Printf("Error on building: %v\n", err)
} else {
fmt.Println("Build completed successfully")
}
} else {
err = BuildAnytype(err)
if err != nil {
return err
}
}
return nil
}

View file

@ -3,6 +3,7 @@ package application
import (
"errors"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/core"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
@ -18,20 +19,13 @@ func (s *Service) AccountRecover() error {
return errors.Join(ErrBadInput, err)
}
event := &pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfAccountShow{
AccountShow: &pb.EventAccountShow{
Account: &model.Account{
Id: res.Identity.GetPublic().Account(),
},
},
},
s.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfAccountShow{
AccountShow: &pb.EventAccountShow{
Account: &model.Account{
Id: res.Identity.GetPublic().Account(),
},
},
}
s.eventSender.Broadcast(event)
}))
return nil
}

View file

@ -5,6 +5,7 @@ import (
"fmt"
"time"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/session"
walletComp "github.com/anyproto/anytype-heart/core/wallet"
"github.com/anyproto/anytype-heart/pb"
@ -73,18 +74,12 @@ func (s *Service) LinkLocalStartNewChallenge(clientInfo *pb.EventAccountLinkChal
if err != nil {
return "", err
}
s.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfAccountLinkChallenge{
AccountLinkChallenge: &pb.EventAccountLinkChallenge{
Challenge: value,
ClientInfo: clientInfo,
},
},
},
s.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfAccountLinkChallenge{
AccountLinkChallenge: &pb.EventAccountLinkChallenge{
Challenge: value,
ClientInfo: clientInfo,
},
})
}))
return id, nil
}

View file

@ -55,7 +55,7 @@ func (s *Service) DeleteObjectByFullID(id domain.FullID) error {
if err != nil {
return err
}
sendOnRemoveEvent(s.eventSender, id.ObjectID)
s.sendOnRemoveEvent(id.SpaceID, id.ObjectID)
// Remove from cache
err = spc.Remove(context.Background(), id.ObjectID)
if err != nil {
@ -152,16 +152,10 @@ func (s *Service) OnDelete(id domain.FullID, workspaceRemove func() error) error
return nil
}
func sendOnRemoveEvent(eventSender event.Sender, ids ...string) {
eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfObjectRemove{
ObjectRemove: &pb.EventObjectRemove{
Ids: ids,
},
},
},
func (s *Service) sendOnRemoveEvent(spaceId string, id string) {
s.eventSender.Broadcast(event.NewEventSingleMessage(spaceId, &pb.EventMessageValueOfObjectRemove{
ObjectRemove: &pb.EventObjectRemove{
Ids: []string{id},
},
})
}))
}

View file

@ -83,7 +83,7 @@ func (s *storeObject) Init(ctx *smartblock.InitContext) error {
if err != nil {
return err
}
s.subscription = newSubscription(s.Id(), s.eventSender)
s.subscription = newSubscription(s.SpaceID(), s.Id(), s.eventSender)
stateStore, err := storestate.New(ctx.Ctx, s.Id(), s.crdtDb, ChatHandler{
subscription: s.subscription,
@ -322,11 +322,7 @@ func (s *storeObject) SubscribeLastMessages(ctx context.Context, limit int) ([]*
return messages[i].OrderId < messages[j].OrderId
})
var firstOrderId string
if len(messages) > 0 {
firstOrderId = messages[0].OrderId
}
s.subscription.subscribe(firstOrderId)
s.subscription.enable()
return messages, 0, nil
}

View file

@ -10,6 +10,7 @@ import (
)
type subscription struct {
spaceId string
chatId string
eventSender event.Sender
@ -17,19 +18,18 @@ type subscription struct {
eventsBuffer []*pb.EventMessage
firstOrderId string
enabled bool
enabled bool
}
func newSubscription(chatId string, eventSender event.Sender) *subscription {
func newSubscription(spaceId string, chatId string, eventSender event.Sender) *subscription {
return &subscription{
spaceId: spaceId,
chatId: chatId,
eventSender: eventSender,
}
}
func (s *subscription) subscribe(firstOrderId string) {
s.firstOrderId = firstOrderId
func (s *subscription) enable() {
s.enabled = true
}
@ -63,7 +63,7 @@ func (s *subscription) flush() {
}
func (s *subscription) add(message *model.ChatMessage) {
if !s.canSend(message) {
if !s.canSend() {
return
}
ev := &pb.EventChatAdd{
@ -71,63 +71,52 @@ func (s *subscription) add(message *model.ChatMessage) {
Message: message,
OrderId: message.OrderId,
}
s.eventsBuffer = append(s.eventsBuffer, &pb.EventMessage{
Value: &pb.EventMessageValueOfChatAdd{
ChatAdd: ev,
},
})
s.eventsBuffer = append(s.eventsBuffer, event.NewMessage(s.spaceId, &pb.EventMessageValueOfChatAdd{
ChatAdd: ev,
}))
}
func (s *subscription) delete(messageId string) {
ev := &pb.EventChatDelete{
Id: messageId,
}
s.eventsBuffer = append(s.eventsBuffer, &pb.EventMessage{
Value: &pb.EventMessageValueOfChatDelete{
ChatDelete: ev,
},
})
s.eventsBuffer = append(s.eventsBuffer, event.NewMessage(s.spaceId, &pb.EventMessageValueOfChatDelete{
ChatDelete: ev,
}))
}
func (s *subscription) updateFull(message *model.ChatMessage) {
if !s.canSend(message) {
if !s.canSend() {
return
}
ev := &pb.EventChatUpdate{
Id: message.Id,
Message: message,
}
s.eventsBuffer = append(s.eventsBuffer, &pb.EventMessage{
Value: &pb.EventMessageValueOfChatUpdate{
ChatUpdate: ev,
},
})
s.eventsBuffer = append(s.eventsBuffer, event.NewMessage(s.spaceId, &pb.EventMessageValueOfChatUpdate{
ChatUpdate: ev,
}))
}
func (s *subscription) updateReactions(message *model.ChatMessage) {
if !s.canSend(message) {
if !s.canSend() {
return
}
ev := &pb.EventChatUpdateReactions{
Id: message.Id,
Reactions: message.Reactions,
}
s.eventsBuffer = append(s.eventsBuffer, &pb.EventMessage{
Value: &pb.EventMessageValueOfChatUpdateReactions{
ChatUpdateReactions: ev,
},
})
s.eventsBuffer = append(s.eventsBuffer, event.NewMessage(s.spaceId, &pb.EventMessageValueOfChatUpdateReactions{
ChatUpdateReactions: ev,
}))
}
func (s *subscription) canSend(message *model.ChatMessage) bool {
func (s *subscription) canSend() bool {
if s.sessionContext != nil {
return true
}
if !s.enabled {
return false
}
if s.firstOrderId > message.OrderId {
return false
}
return true
}

View file

@ -547,7 +547,7 @@ func TestClipboard_TitleOps(t *testing.T) {
s.Add(tb)
s.InsertTo("", 0, tb.Model().Id)
}
_, _, err := state.ApplyState(s, false)
_, _, err := state.ApplyState("", s, false)
require.NoError(t, err)
return sb
}
@ -572,7 +572,7 @@ func TestClipboard_TitleOps(t *testing.T) {
bm.Model().Id = "bookmarkId"
s.Add(bm)
s.InsertTo("", 0, bm.Model().Id)
_, _, err := state.ApplyState(s, false)
_, _, err := state.ApplyState("", s, false)
require.NoError(t, err)
return sb
}
@ -1103,7 +1103,7 @@ func addDescription(st *smarttest.SmartTest, description string) {
newState := st.Doc.NewState()
template.InitTemplate(newState, template.WithForcedDescription)
newState.Get(template.DescriptionBlockId).(text.Block).SetText(description, nil)
state.ApplyState(newState, false)
state.ApplyState("", newState, false)
}
func addRelations(st *smarttest.SmartTest) {
@ -1111,7 +1111,7 @@ func addRelations(st *smarttest.SmartTest) {
template.InitTemplate(newState, template.RequireHeader)
template.InitTemplate(newState, template.WithFeaturedRelations)
template.InitTemplate(newState, template.WithForcedDescription)
state.ApplyState(newState, false)
state.ApplyState("", newState, false)
}
func TestClipboard_PasteToCodeBlock(t *testing.T) {

View file

@ -135,17 +135,11 @@ func (p *Profile) SetDetails(ctx session.Context, details []domain.Detail, showE
return
}
p.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfAccountDetails{
AccountDetails: &pb.EventAccountDetails{
ProfileId: p.Id(),
Details: p.Details().ToProto(),
},
},
},
p.eventSender.Broadcast(event.NewEventSingleMessage(p.SpaceID(), &pb.EventMessageValueOfAccountDetails{
AccountDetails: &pb.EventAccountDetails{
ProfileId: p.Id(),
Details: p.Details().ToProto(),
},
})
}))
return
}

View file

@ -378,14 +378,12 @@ func (sb *smartBlock) Init(ctx *InitContext) (err error) {
func (sb *smartBlock) sendObjectCloseEvent(_ ApplyInfo) error {
sb.sendEvent(&pb.Event{
ContextId: sb.Id(),
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfObjectClose{
Messages: []*pb.EventMessage{
event.NewMessage(sb.SpaceID(), &pb.EventMessageValueOfObjectClose{
ObjectClose: &pb.EventObjectClose{
Id: sb.Id(),
},
},
}},
})
}}),
}})
return nil
}
@ -396,7 +394,11 @@ func (sb *smartBlock) updateRestrictions() {
return
}
sb.restrictions = r
sb.SendEvent([]*pb.EventMessage{{Value: &pb.EventMessageValueOfObjectRestrictionsSet{ObjectRestrictionsSet: &pb.EventObjectRestrictionsSet{Id: sb.Id(), Restrictions: r.Proto()}}}})
sb.SendEvent([]*pb.EventMessage{
event.NewMessage(sb.SpaceID(), &pb.EventMessageValueOfObjectRestrictionsSet{
ObjectRestrictionsSet: &pb.EventObjectRestrictionsSet{Id: sb.Id(), Restrictions: r.Proto()},
}),
})
}
func (sb *smartBlock) SetIsDeleted() {
@ -561,7 +563,7 @@ func (sb *smartBlock) onMetaChange(details *domain.Details) {
return
}
id := details.GetString(bundle.RelationKeyId)
msgs := []*pb.EventMessage{}
var msgs []*pb.EventMessage
if v, exists := sb.lastDepDetails[id]; exists {
diff := domain.StructDiff(v, details)
if id == sb.Id() {
@ -569,16 +571,18 @@ func (sb *smartBlock) onMetaChange(details *domain.Details) {
diff = diff.CopyOnlyKeys(bundle.LocalRelationsKeys...)
}
msgs = append(msgs, state.StructDiffIntoEvents(id, diff)...)
msgs = append(msgs, state.StructDiffIntoEvents(sb.SpaceID(), id, diff)...)
} else {
msgs = append(msgs, &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: id,
Details: details.ToProto(),
},
msgs = append(msgs, event.NewMessage(sb.SpaceID(), &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: id,
Details: details.ToProto(),
},
})
}))
}
sb.lastDepDetails[id] = &pb.EventObjectDetailsSet{
Id: id,
Details: details,
}
sb.lastDepDetails[id] = details
@ -705,7 +709,7 @@ func (sb *smartBlock) Apply(s *state.State, flags ...ApplyFlag) (err error) {
migrationVersionUpdated = s.MigrationVersion() != parent.MigrationVersion()
}
msgs, act, err := state.ApplyState(s, !sb.disableLayouts)
msgs, act, err := state.ApplyState(sb.SpaceID(), s, !sb.disableLayouts)
if err != nil {
return
}
@ -1067,7 +1071,7 @@ func (sb *smartBlock) StateAppend(f func(d state.Doc) (s *state.State, changes [
sb.updateRestrictions()
sb.injectDerivedDetails(s, sb.SpaceID(), sb.Type())
sb.execHooks(HookBeforeApply, ApplyInfo{State: s})
msgs, act, err := state.ApplyState(s, !sb.disableLayouts)
msgs, act, err := state.ApplyState(sb.SpaceID(), s, !sb.disableLayouts)
if err != nil {
return err
}
@ -1102,7 +1106,7 @@ func (sb *smartBlock) StateRebuild(d state.Doc) (err error) {
d.(*state.State).SetParent(sb.Doc.(*state.State))
// todo: make store diff
sb.execHooks(HookBeforeApply, ApplyInfo{State: d.(*state.State)})
msgs, _, err := state.ApplyState(d.(*state.State), !sb.disableLayouts)
msgs, _, err := state.ApplyState(sb.SpaceID(), d.(*state.State), !sb.disableLayouts)
log.Infof("changes: stateRebuild: %d events", len(msgs))
if err != nil {
// can't make diff - reopen doc

View file

@ -361,7 +361,7 @@ func (st *SmartTest) Apply(s *state.State, flags ...smartblock.ApplyFlag) (err e
s.RemoveDetail(bundle.RelationKeyInternalFlags)
}
msgs, act, err := state.ApplyState(s, true)
msgs, act, err := state.ApplyState(st.SpaceID(), s, true)
if err != nil {
return
}
@ -390,7 +390,7 @@ func (st *SmartTest) History() undo.History {
func (st *SmartTest) StateRebuild(d state.Doc) (err error) {
d.(*state.State).SetParent(st.Doc.(*state.State))
_, _, err = state.ApplyState(d.(*state.State), false)
_, _, err = state.ApplyState(st.SpaceID(), d.(*state.State), false)
return err
}

View file

@ -46,7 +46,7 @@ func TestState_ChangesCreate_MoveAdd(t *testing.T) {
require.NoError(t, s.InsertTo("b", model.Block_Inner, "1", "2", "4", "5"))
s.Add(simple.New(&model.Block{Id: "3.1"}))
require.NoError(t, s.InsertTo("2", model.Block_Bottom, "3.1"))
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
changes := d.(*State).GetChanges()
require.Len(t, changes, 4)
@ -62,7 +62,7 @@ func TestState_ChangesCreate_Collection_Set(t *testing.T) {
d := NewDoc("root", nil)
s := d.NewState()
s.SetInStore([]string{"coll1", "key1"}, pbtypes.String("1"))
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
changes := d.(*State).GetChanges()
require.Len(t, changes, 1)
@ -81,7 +81,7 @@ func TestState_ChangesCreate_Collection_Unset(t *testing.T) {
d.(*State).store = makeStoreWithTwoKeysAndValue("coll1", "key1", "1")
s := d.NewState()
s.RemoveFromStore([]string{"coll1", "key1"})
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
changes := d.(*State).GetChanges()
require.Len(t, changes, 1)
@ -197,7 +197,7 @@ func TestState_ChangesCreate_StoreSlice(t *testing.T) {
newState := doc.NewState()
newState.UpdateStoreSlice(key, tc.after)
_, _, err := ApplyState(newState, false)
_, _, err := ApplyState("", newState, false)
require.NoError(t, err)
got := doc.(*State).GetChanges()
@ -232,12 +232,12 @@ func TestState_ChangesCreate_MoveAdd_Wrap(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "div", ChildrenIds: []string{"a", "b"}}))
s.Get("root").Model().ChildrenIds = []string{"div"}
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
changes := d.(*State).GetChanges()
s2 := dc.NewState()
require.NoError(t, s2.ApplyChange(changes...))
_, _, err = ApplyState(s2, true)
_, _, err = ApplyState("", s2, true)
require.NoError(t, err)
assert.Equal(t, d.(*State).String(), dc.(*State).String())
}
@ -264,12 +264,12 @@ func TestState_ChangesCreate_MoveAdd_Side(t *testing.T) {
s.Unlink("5")
s.InsertTo("1", model.Block_Left, "4", "5")
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
changes := d.(*State).GetChanges()
s2 := dc.NewState()
require.NoError(t, s2.ApplyChange(changes...))
_, _, err = ApplyState(s2, true)
_, _, err = ApplyState("", s2, true)
require.NoError(t, err)
assert.Equal(t, d.(*State).String(), dc.(*State).String())
}
@ -290,7 +290,7 @@ func TestState_ChangesCreate_MoveAdd_Side_NewBlock(t *testing.T) {
assertApplyingChanges := func(t *testing.T, state *State, wantState *State, originalState *State) {
AssertTreesEqual(t, wantState.Blocks(), state.Blocks())
_, _, err := ApplyState(state, true)
_, _, err := ApplyState("", state, true)
require.NoError(t, err)
changes := state.GetChanges()
err = originalState.ApplyChange(changes...)
@ -368,7 +368,7 @@ func TestState_SetParent(t *testing.T) {
ns.SetRootId(st.RootId())
ns.SetParent(st)
_, _, err := ApplyState(ns, false)
_, _, err := ApplyState("", ns, false)
require.NoError(t, err)
st2 := orig.Copy()
@ -392,7 +392,7 @@ func TestStateNormalizeMerge(t *testing.T) {
s.InsertTo(fmt.Sprintf("common%d", i-1), model.Block_Bottom, id)
}
}
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
t.Run("parallel normalize", func(t *testing.T) {
@ -403,7 +403,7 @@ func TestStateNormalizeMerge(t *testing.T) {
stateA.Add(simple.New(&model.Block{Id: "a1"}))
stateA.Add(simple.New(&model.Block{Id: "a2"}))
stateA.InsertTo("common39", model.Block_Bottom, "a1", "a2")
_, _, err = ApplyState(stateA, true)
_, _, err = ApplyState("", stateA, true)
require.NoError(t, err)
// t.Log(docA.String())
changesA := stateA.GetChanges()
@ -412,18 +412,18 @@ func TestStateNormalizeMerge(t *testing.T) {
stateB := docB.NewState()
stateB.Add(simple.New(&model.Block{Id: "b1"}))
stateB.InsertTo("common39", model.Block_Bottom, "b1")
_, _, err = ApplyState(stateB, true)
_, _, err = ApplyState("", stateB, true)
require.NoError(t, err)
// t.Log(docB.String())
changesB := stateB.GetChanges()
s = d.NewState()
require.NoError(t, s.ApplyChange(changesB...))
_, _, err = ApplyStateFastOne(s)
_, _, err = ApplyStateFastOne("", s)
require.NoError(t, err)
s = d.NewState()
require.NoError(t, s.ApplyChange(changesA...))
_, _, err = ApplyState(s, true)
_, _, err = ApplyState("", s, true)
require.NoError(t, err)
s = d.NewState()
@ -439,7 +439,7 @@ func TestStateNormalizeMerge(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "common40"}))
s.InsertTo("common39", model.Block_Bottom, "common40")
ids = append(ids, "common40")
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
aIds := []string{}
@ -451,7 +451,7 @@ func TestStateNormalizeMerge(t *testing.T) {
stateA.Add(simple.New(&model.Block{Id: id}))
}
stateA.InsertTo("common0", model.Block_Top, aIds...)
_, _, err = ApplyState(stateA, true)
_, _, err = ApplyState("", stateA, true)
require.NoError(t, err)
changesA := stateA.GetChanges()
@ -464,17 +464,17 @@ func TestStateNormalizeMerge(t *testing.T) {
stateB.Add(simple.New(&model.Block{Id: id}))
}
stateB.InsertTo("common40", model.Block_Bottom, bIds...)
_, _, err = ApplyState(stateB, true)
_, _, err = ApplyState("", stateB, true)
require.NoError(t, err)
changesB := stateB.GetChanges()
s = d.NewState()
require.NoError(t, s.ApplyChange(changesB...))
_, _, err = ApplyStateFastOne(s)
_, _, err = ApplyStateFastOne("", s)
require.NoError(t, err)
s = d.NewState()
require.NoError(t, s.ApplyChange(changesA...))
_, _, err = ApplyState(s, true)
_, _, err = ApplyState("", s, true)
require.NoError(t, err)
s = d.NewState()
@ -506,12 +506,12 @@ func TestState_ChangeDataviewOrder(t *testing.T) {
s := d.NewState()
s.Get("dv").(dataview.Block).SetViewOrder([]string{"3", "1", "2"})
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
changes := d.(*State).GetChanges()
s2 := dc.NewState()
require.NoError(t, s2.ApplyChange(changes...))
_, _, err = ApplyState(s2, true)
_, _, err = ApplyState("", s2, true)
require.NoError(t, err)
assert.Equal(t, d.(*State).Pick("dv").Model().String(), dc.(*State).Pick("dv").Model().String())
}
@ -534,11 +534,11 @@ func TestState_ChangeDataviewUnlink(t *testing.T) {
},
}}))
s.InsertTo("root", model.Block_Inner, "dv")
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
changes := d.(*State).GetChanges()
s = d.NewState()
s.Unlink("dv")
_, _, err = ApplyState(s, true)
_, _, err = ApplyState("", s, true)
require.NoError(t, err)
changes = append(changes, d.(*State).GetChanges()...)
@ -547,7 +547,7 @@ func TestState_ChangeDataviewUnlink(t *testing.T) {
require.Nil(t, s2.Get("dv"))
require.Nil(t, s2.Pick("dv"))
_, _, err = ApplyState(s2, true)
_, _, err = ApplyState("", s2, true)
require.NoError(t, err)
require.Nil(t, dc.(*State).Get("dv"))
require.Nil(t, dc.(*State).Pick("dv"))
@ -571,11 +571,11 @@ func TestState_ChangeDataviewRemoveAdd(t *testing.T) {
},
}}))
s.InsertTo("root", model.Block_Inner, "dv")
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
changes := d.(*State).GetChanges()
s = d.NewState()
s.Unlink("dv")
_, _, err = ApplyState(s, true)
_, _, err = ApplyState("", s, true)
require.NoError(t, err)
changes = append(changes, d.(*State).GetChanges()...)
s = d.NewState()
@ -587,7 +587,7 @@ func TestState_ChangeDataviewRemoveAdd(t *testing.T) {
},
}}))
s.InsertTo("root", model.Block_Inner, "dv")
_, _, err = ApplyState(s, true)
_, _, err = ApplyState("", s, true)
require.NoError(t, err)
changes = append(changes, d.(*State).GetChanges()...)
@ -597,7 +597,7 @@ func TestState_ChangeDataviewRemoveAdd(t *testing.T) {
require.Len(t, s2.Get("dv").Model().GetDataview().Views, 1)
require.Equal(t, "2", s2.Get("dv").Model().GetDataview().Views[0].Id)
_, _, err = ApplyState(s2, true)
_, _, err = ApplyState("", s2, true)
require.NoError(t, err)
require.NotNil(t, dc.(*State).Get("dv"))
require.Len(t, dc.(*State).Get("dv").Model().GetDataview().Views, 1)
@ -624,7 +624,7 @@ func TestState_ChangeDataviewRemoveMove(t *testing.T) {
s := d1.NewState()
require.NoError(t, s.ApplyChange(changes...))
ApplyState(s, true)
ApplyState("", s, true)
require.Nil(t, d1.(*State).blocks["b"])
require.NotContains(t, d1.(*State).Pick("s").Model().ChildrenIds, "b")
require.NotContains(t, d1.(*State).Pick("root").Model().ChildrenIds, "b")
@ -693,7 +693,7 @@ func TestRelationChanges(t *testing.T) {
ac := a.Copy()
b := a.NewState()
b.relationLinks = []*model.RelationLink{{Key: "3"}, {Key: "4"}, {Key: "5"}}
_, _, err := ApplyState(b, false)
_, _, err := ApplyState("", b, false)
require.NoError(t, err)
chs := a.GetChanges()
require.NoError(t, ac.ApplyChange(chs...))
@ -709,7 +709,7 @@ func TestLocalRelationChanges(t *testing.T) {
b.relationLinks = []*model.RelationLink{{Key: bundle.RelationKeySyncStatus.String(), Format: model.RelationFormat_number}}
// when
_, _, err := ApplyState(b, false)
_, _, err := ApplyState("", b, false)
require.NoError(t, err)
chs := a.GetChanges()
@ -724,7 +724,7 @@ func TestLocalRelationChanges(t *testing.T) {
b.relationLinks = []*model.RelationLink{}
// when
_, _, err := ApplyState(b, false)
_, _, err := ApplyState("", b, false)
require.NoError(t, err)
chs := a.GetChanges()
@ -739,7 +739,7 @@ func TestLocalRelationChanges(t *testing.T) {
b.relationLinks = []*model.RelationLink{{Key: bundle.RelationKeySpaceId.String(), Format: model.RelationFormat_longtext}}
// when
_, _, err := ApplyState(b, false)
_, _, err := ApplyState("", b, false)
require.NoError(t, err)
chs := a.GetChanges()
@ -754,7 +754,7 @@ func TestLocalRelationChanges(t *testing.T) {
b.relationLinks = []*model.RelationLink{}
// when
_, _, err := ApplyState(b, false)
_, _, err := ApplyState("", b, false)
require.NoError(t, err)
chs := a.GetChanges()
@ -770,7 +770,7 @@ func TestRootBlockChanges(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "new"}))
require.NoError(t, s.InsertTo("root", model.Block_Inner, "new"))
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
changes := s.GetChanges()
@ -826,7 +826,7 @@ func buildStateFromAST(root *Block) *State {
Blocks: root.Build(),
},
}).(*State)
ApplyState(st, true)
ApplyState("", st, true)
return st.NewState()
}
@ -880,7 +880,7 @@ func TestRootDeviceChanges(t *testing.T) {
s := a.NewState()
// when
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
// then
assert.Nil(t, err)
@ -898,7 +898,7 @@ func TestRootDeviceChanges(t *testing.T) {
s.AddDevice(device)
// when
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
// then
assert.Nil(t, err)
@ -917,7 +917,7 @@ func TestRootDeviceChanges(t *testing.T) {
s := a.NewState()
s.SetDeviceName("id", "test1")
// when
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
// then
assert.Nil(t, err)
@ -936,7 +936,7 @@ func TestRootDeviceChanges(t *testing.T) {
s.AddDevice(device)
s.parent = nil
// when
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
// then
assert.Nil(t, err)
@ -981,7 +981,7 @@ func TestTableChanges(t *testing.T) {
},
}}))
msgs, _, err := ApplyState(s, true)
msgs, _, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 1)
@ -989,7 +989,7 @@ func TestTableChanges(t *testing.T) {
rows := s.Get("tableRow1")
require.NotNil(t, rows)
rows.Model().GetTableRow().IsHeader = true
msgs, _, err = ApplyState(s, true)
msgs, _, err = ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 1)

View file

@ -15,6 +15,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple/table"
"github.com/anyproto/anytype-heart/core/block/simple/text"
"github.com/anyproto/anytype-heart/core/block/simple/widget"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
@ -313,12 +314,12 @@ func WrapEventMessages(virtual bool, msgs []*pb.EventMessage) []simple.EventMess
return wmsgs
}
func StructDiffIntoEvents(contextId string, diff *domain.Details) (msgs []*pb.EventMessage) {
return StructDiffIntoEventsWithSubIds(contextId, diff, nil, nil)
func StructDiffIntoEvents(spaceId string, contextId string, diff *domain.Details) (msgs []*pb.EventMessage) {
return StructDiffIntoEventsWithSubIds(spaceId, contextId, diff, nil, nil)
}
// StructDiffIntoEvents converts map into events. nil map value converts to Remove event
func StructDiffIntoEventsWithSubIds(contextId string, diff *domain.Details, keys []domain.RelationKey, subIds []string) (msgs []*pb.EventMessage) {
func StructDiffIntoEventsWithSubIds(spaceId string, contextId string, diff *domain.Details, keys []domain.RelationKey, subIds []string) (msgs []*pb.EventMessage) {
if diff.Len() == 0 {
return nil
}
@ -341,28 +342,23 @@ func StructDiffIntoEventsWithSubIds(contextId string, diff *domain.Details, keys
}
if len(details) > 0 {
msgs = append(msgs, &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: contextId,
Details: details,
SubIds: subIds,
},
msgs = append(msgs, event.NewMessage(spaceId, &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: contextId,
Details: details,
SubIds: subIds,
},
})
}))
}
if len(removed) > 0 {
msgs = append(msgs, &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsUnset{
ObjectDetailsUnset: &pb.EventObjectDetailsUnset{
Id: contextId,
Keys: removed,
SubIds: subIds,
},
msgs = append(msgs, event.NewMessage(spaceId, &pb.EventMessageValueOfObjectDetailsUnset{
ObjectDetailsUnset: &pb.EventObjectDetailsUnset{
Id: contextId,
Keys: removed,
SubIds: subIds,
},
})
}))
}
return
}

View file

@ -50,7 +50,7 @@ func TestState_Normalize(t *testing.T) {
r := NewDoc("1", nil)
r.(*State).Add(simple.New(&model.Block{Id: "1"}))
s := r.NewState()
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 0)
assert.Empty(t, hist)
@ -63,7 +63,7 @@ func TestState_Normalize(t *testing.T) {
}).(*State)
s := r.NewState()
s.Get("one")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 1)
assert.Len(t, hist.Change, 1)
@ -97,7 +97,7 @@ func TestState_Normalize(t *testing.T) {
s.Get("tableRows")
s.Get("tableColumns")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2) // 1 remove + 1 change
assert.Len(t, hist.Change, 1)
@ -122,7 +122,7 @@ func TestState_Normalize(t *testing.T) {
s := r.NewState()
s.Get("c1")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2) // 1 remove + 1 change
assert.Len(t, hist.Change, 1)
@ -146,7 +146,7 @@ func TestState_Normalize(t *testing.T) {
s := r.NewState()
s.Unlink("c2")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 4) // 1 row change + 1 remove + 2 width reset
assert.Len(t, hist.Remove, 2)
@ -168,7 +168,7 @@ func TestState_Normalize(t *testing.T) {
s := r.NewState()
s.normalizeTree()
ApplyState(s, true)
ApplyState("", s, true)
blocks := r.Blocks()
result := []string{}
divs := []string{}
@ -207,7 +207,7 @@ func TestState_Normalize(t *testing.T) {
r.Add(simple.New(&model.Block{Id: "root", ChildrenIds: rootIds}))
s := r.NewState()
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
require.NoError(t, err)
})
@ -221,7 +221,7 @@ func TestState_Normalize(t *testing.T) {
id := fmt.Sprint(i)
s.Add(simple.New(&model.Block{Id: id}))
s.InsertTo(targetId, targetPos, id)
msgs, _, err := ApplyState(s, true)
msgs, _, err := ApplyState("", s, true)
require.NoError(t, err)
for _, msg := range msgs {
if add := msg.Msg.GetBlockAdd(); add != nil {
@ -262,7 +262,7 @@ func TestState_Normalize(t *testing.T) {
for _, b := range ev.Blocks {
r.Add(simple.New(b))
}
_, _, err = ApplyState(r.NewState(), true)
_, _, err = ApplyState("", r.NewState(), true)
require.NoError(t, err)
// t.Log(r.String())
@ -283,7 +283,7 @@ func TestState_Normalize(t *testing.T) {
r.Add(simple.New(&model.Block{Id: "e"}))
s := r.NewState()
require.NoError(t, s.Normalize(false))
_, _, err := ApplyState(s, false)
_, _, err := ApplyState("", s, false)
require.NoError(t, err)
assert.Equal(t, []string{"a", "b", "c"}, r.Pick("root").Model().ChildrenIds)
assert.Equal(t, []string{"d"}, r.Pick("a").Model().ChildrenIds)
@ -305,7 +305,7 @@ func TestState_Normalize(t *testing.T) {
s := r.NewState()
s.normalizeTree()
ApplyState(s, true)
ApplyState("", s, true)
assert.Equal(t, "header", s.Pick(s.RootId()).Model().ChildrenIds[0])
})
@ -336,7 +336,7 @@ func TestState_Normalize(t *testing.T) {
// when
require.NoError(t, s.Normalize(false))
_, msg, err := ApplyState(s, false)
_, msg, err := ApplyState("", s, false)
// then
require.NoError(t, err)
@ -463,7 +463,7 @@ func BenchmarkNormalize(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
ApplyState(r.NewState(), true)
ApplyState("", r.NewState(), true)
}
}

View file

@ -23,7 +23,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "second"}))
s.InsertTo("", 0, "first", "second")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
assert.Len(t, hist.Add, 2)
@ -42,7 +42,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "second"}))
s.InsertTo("target", model.Block_Bottom, "first", "second")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
assert.Len(t, hist.Add, 2)
@ -59,7 +59,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "second"}))
s.InsertTo("target", model.Block_Top, "first", "second")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
assert.Len(t, hist.Add, 2)
@ -76,7 +76,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "second"}))
s.InsertTo("target", model.Block_Inner, "first", "second")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
assert.Len(t, hist.Add, 2)
@ -95,7 +95,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "second"}))
s.InsertTo("target", model.Block_Replace, "first", "second")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 3)
assert.Len(t, hist.Remove, 1)
@ -106,7 +106,7 @@ func TestState_InsertTo(t *testing.T) {
s = r.NewState()
require.NoError(t, r.InsertTo("first", model.Block_Replace, "child"))
_, _, err = ApplyState(s, true)
_, _, err = ApplyState("", s, true)
require.NoError(t, err)
assert.Equal(t, []string{"child", "second"}, r.Pick("root").Model().ChildrenIds)
})
@ -123,7 +123,7 @@ func TestState_InsertTo(t *testing.T) {
// when
err := s.InsertTo("target", model.Block_Replace, "link")
_, _, err2 := ApplyState(s, true)
_, _, err2 := ApplyState("", s, true)
// then
assert.NoError(t, err)
@ -142,7 +142,7 @@ func TestState_InsertTo(t *testing.T) {
// when
err := s.InsertTo("target", model.Block_Replace, "link")
_, _, err2 := ApplyState(s, true)
_, _, err2 := ApplyState("", s, true)
// then
assert.NoError(t, err)
@ -174,7 +174,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "second"}))
s.InsertTo("target", pos, "first", "second")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.NotEmpty(t, msgs)
assert.Len(t, hist.Remove, 0)
@ -207,7 +207,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "third"}))
s.InsertTo(c1.Model().Id, model.Block_Left, "third")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
assert.Len(t, hist.Remove, 0)
@ -220,7 +220,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "third"}))
s.InsertTo(c2.Model().Id, model.Block_Left, "third")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
assert.Len(t, hist.Remove, 0)
@ -233,7 +233,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "third"}))
s.InsertTo(c2.Model().Id, model.Block_Right, "third")
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
assert.Len(t, hist.Remove, 0)
@ -250,7 +250,7 @@ func TestState_InsertTo(t *testing.T) {
s.Add(simple.New(&model.Block{Id: "2", ChildrenIds: []string{"1"}}))
s.Get("root").Model().ChildrenIds = []string{"1"}
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
assert.Error(t, err)
})

View file

@ -14,6 +14,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/block/undo"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/session"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
@ -413,25 +414,25 @@ func (s *State) SearchText() string {
return builder.String()
}
func ApplyState(s *State, withLayouts bool) (msgs []simple.EventMessage, action undo.Action, err error) {
return s.apply(false, false, withLayouts)
func ApplyState(spaceId string, s *State, withLayouts bool) (msgs []simple.EventMessage, action undo.Action, err error) {
return s.apply(spaceId, false, false, withLayouts)
}
func ApplyStateFast(s *State) (msgs []simple.EventMessage, action undo.Action, err error) {
return s.apply(true, false, false)
func ApplyStateFast(spaceId string, s *State) (msgs []simple.EventMessage, action undo.Action, err error) {
return s.apply(spaceId, true, false, false)
}
func ApplyStateFastOne(s *State) (msgs []simple.EventMessage, action undo.Action, err error) {
return s.apply(true, true, false)
func ApplyStateFastOne(spaceId string, s *State) (msgs []simple.EventMessage, action undo.Action, err error) {
return s.apply(spaceId, true, true, false)
}
func (s *State) apply(fast, one, withLayouts bool) (msgs []simple.EventMessage, action undo.Action, err error) {
func (s *State) apply(spaceId string, fast, one, withLayouts bool) (msgs []simple.EventMessage, action undo.Action, err error) {
if s.parent != nil && (s.parent.parent != nil || fast) {
s.intermediateApply()
if one {
return
}
return s.parent.apply(fast, one, withLayouts)
return s.parent.apply("", fast, one, withLayouts)
}
if fast {
return
@ -487,13 +488,13 @@ func (s *State) apply(fast, one, withLayouts bool) (msgs []simple.EventMessage,
}
flushNewBlocks := func() {
if len(newBlocks) > 0 {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{
Value: &pb.EventMessageValueOfBlockAdd{
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId,
&pb.EventMessageValueOfBlockAdd{
BlockAdd: &pb.EventBlockAdd{
Blocks: newBlocks,
},
},
}})
}),
})
}
newBlocks = nil
}
@ -517,7 +518,7 @@ func (s *State) apply(fast, one, withLayouts bool) (msgs []simple.EventMessage,
db.DetailsInit(s)
}
}
diff, err := orig.Diff(b)
diff, err := orig.Diff(spaceId, b)
if err != nil {
return nil, undo.Action{}, err
}
@ -553,11 +554,9 @@ func (s *State) apply(fast, one, withLayouts bool) (msgs []simple.EventMessage,
}
}
if len(toRemove) > 0 {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{
Value: &pb.EventMessageValueOfBlockDelete{
BlockDelete: &pb.EventBlockDelete{BlockIds: toRemove},
},
}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(s.SpaceID(), &pb.EventMessageValueOfBlockDelete{
BlockDelete: &pb.EventBlockDelete{BlockIds: toRemove},
})})
}
if s.parent != nil && s.relationLinks != nil {
@ -572,26 +571,24 @@ func (s *State) apply(fast, one, withLayouts bool) (msgs []simple.EventMessage,
if len(removed) > 0 {
msgs = append(msgs, WrapEventMessages(false, []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfObjectRelationsRemove{
ObjectRelationsRemove: &pb.EventObjectRelationsRemove{
Id: s.RootId(),
RelationKeys: removed,
},
event.NewMessage(s.SpaceID(), &pb.EventMessageValueOfObjectRelationsRemove{
ObjectRelationsRemove: &pb.EventObjectRelationsRemove{
Id: s.RootId(),
RelationKeys: removed,
},
},
),
})...)
}
if len(added) > 0 {
msgs = append(msgs, WrapEventMessages(false, []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfObjectRelationsAmend{
ObjectRelationsAmend: &pb.EventObjectRelationsAmend{
Id: s.RootId(),
RelationLinks: added,
},
event.NewMessage(s.SpaceID(), &pb.EventMessageValueOfObjectRelationsAmend{
ObjectRelationsAmend: &pb.EventObjectRelationsAmend{
Id: s.RootId(),
RelationLinks: added,
},
},
),
})...)
}
}
@ -625,7 +622,7 @@ func (s *State) apply(fast, one, withLayouts bool) (msgs []simple.EventMessage,
prev := s.parent.Details()
if diff := domain.StructDiff(prev, s.details); diff != nil {
action.Details = &undo.Details{Before: prev.Copy(), After: s.details.Copy()}
msgs = append(msgs, WrapEventMessages(false, StructDiffIntoEvents(s.RootId(), diff))...)
msgs = append(msgs, WrapEventMessages(false, StructDiffIntoEvents(s.SpaceID(), s.RootId(), diff))...)
s.parent.details = s.details
} else if !s.details.Equal(s.parent.details) {
s.parent.details = s.details
@ -655,7 +652,7 @@ func (s *State) apply(fast, one, withLayouts bool) (msgs []simple.EventMessage,
if s.parent != nil && s.localDetails != nil {
prev := s.parent.LocalDetails()
if diff := domain.StructDiff(prev, s.localDetails); diff != nil {
msgs = append(msgs, WrapEventMessages(true, StructDiffIntoEvents(s.RootId(), diff))...)
msgs = append(msgs, WrapEventMessages(true, StructDiffIntoEvents(spaceId, s.RootId(), diff))...)
s.parent.localDetails = s.localDetails
} else if !s.localDetails.Equal(s.parent.localDetails) {
s.parent.localDetails = s.localDetails
@ -1188,7 +1185,8 @@ func (s *State) CheckRestrictions() (err error) {
}
if rest.Edit {
if ob := s.parent.Pick(id); ob != nil {
if msgs, _ := ob.Diff(b); len(msgs) > 0 {
// SpaceId is empty because only the fact that there is any diff matters here
if msgs, _ := ob.Diff("", b); len(msgs) > 0 {
return ErrRestricted
}
}

View file

@ -192,7 +192,7 @@ func TestApplyState(t *testing.T) {
s.InsertTo("4", model.Block_Bottom, "5")
s.changeId = "4"
msgs, hist, err := ApplyState(s, true)
msgs, hist, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, hist.Add, 2)
assert.Len(t, hist.Change, 1)
@ -223,7 +223,7 @@ func TestApplyState(t *testing.T) {
Text: "name",
Checked: "done",
}))
_, _, err := ApplyState(s, true)
_, _, err := ApplyState("", s, true)
assert.Equal(t, "new name", s.Pick("title").Model().GetText().Text)
require.NoError(t, err)
})
@ -249,7 +249,7 @@ func TestApplyState(t *testing.T) {
s.SetDetails(domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
"name": domain.String("new name"),
}))
msgs, _, err := ApplyState(s, true)
msgs, _, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
})
@ -276,7 +276,7 @@ func TestApplyState(t *testing.T) {
s.SetDetails(domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
"done": domain.Bool(false),
}))
msgs, _, err := ApplyState(s, true)
msgs, _, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
})
@ -301,7 +301,7 @@ func TestApplyState(t *testing.T) {
d.BlocksInit(d.(simple.DetailsService))
s := d.NewState()
s.Get("2").(text.Block).SetChecked(false)
msgs, _, err := ApplyState(s, true)
msgs, _, err := ApplyState("", s, true)
require.NoError(t, err)
assert.Len(t, msgs, 2)
})

View file

@ -479,7 +479,7 @@ func (t *textImpl) isLastTextBlockChanged() (bool, error) {
return true, err
}
oldTextBlock := t.lastSetTextState.PickOrigin(t.lastSetTextId)
messages, err := oldTextBlock.Diff(newTextBlock)
messages, err := oldTextBlock.Diff(t.SpaceID(), newTextBlock)
return len(messages) != 0, err
}

View file

@ -1064,7 +1064,7 @@ func objectValid(sbType smartblock.SmartBlockType, info *database.ObjectInfo, in
if info.Id == addr.AnytypeProfileId {
return false
}
if !isProtobuf && !validTypeForNonProtobuf(sbType) && !validLayoutForNonProtobuf(info.Details) {
if !isProtobuf && (!validTypeForNonProtobuf(sbType) || !validLayoutForNonProtobuf(info.Details)) {
return false
}
if isProtobuf && !validType(sbType) {
@ -1120,10 +1120,8 @@ func (fn *namer) Get(path, hash, title, ext string) (name string) {
}
func validType(sbType smartblock.SmartBlockType) bool {
return sbType == smartblock.SmartBlockTypeHome ||
sbType == smartblock.SmartBlockTypeProfilePage ||
return sbType == smartblock.SmartBlockTypeProfilePage ||
sbType == smartblock.SmartBlockTypePage ||
sbType == smartblock.SmartBlockTypeSubObject ||
sbType == smartblock.SmartBlockTypeTemplate ||
sbType == smartblock.SmartBlockTypeWorkspace ||
sbType == smartblock.SmartBlockTypeWidget ||

View file

@ -34,8 +34,7 @@ func (o *fileObject) GetIDAndPayload(ctx context.Context, spaceId string, sn *co
encryptionKeys[key.Path] = key.Key
}
}
name := sn.Snapshot.Data.Details.GetString(bundle.RelationKeyName)
fileObjectId, err := uploadFile(ctx, o.blockService, spaceId, name, filePath, origin, encryptionKeys)
fileObjectId, err := uploadFile(ctx, o.blockService, spaceId, filePath, origin, encryptionKeys, sn.Snapshot.Data.Details)
if err != nil {
log.Error("handling file object: upload file", zap.Error(err))
return id, payload, nil

View file

@ -40,8 +40,7 @@ func (f *oldFile) GetIDAndPayload(ctx context.Context, spaceId string, sn *commo
filePath := sn.Snapshot.Data.Details.GetString(bundle.RelationKeySource)
if filePath != "" {
name := sn.Snapshot.Data.Details.GetString(bundle.RelationKeyName)
fileObjectId, err := uploadFile(ctx, f.blockService, spaceId, name, filePath, origin, filesKeys)
fileObjectId, err := uploadFile(ctx, f.blockService, spaceId, filePath, origin, filesKeys, sn.Snapshot.Data.Details)
if err != nil {
log.Error("handling old file object: upload file", zap.Error(err))
}
@ -64,14 +63,17 @@ func (f *oldFile) GetIDAndPayload(ctx context.Context, spaceId string, sn *commo
return objectId, treestorage.TreeStorageCreatePayload{}, nil
}
func uploadFile(ctx context.Context, blockService *block.Service, spaceId string, name string, filePath string, origin objectorigin.ObjectOrigin, encryptionKeys map[string]string) (string, error) {
func uploadFile(
ctx context.Context,
blockService *block.Service,
spaceId, filePath string,
origin objectorigin.ObjectOrigin,
encryptionKeys map[string]string,
details *types.Struct,
) (string, error) {
params := pb.RpcFileUploadRequest{
SpaceId: spaceId,
Details: &types.Struct{
Fields: map[string]*types.Value{
bundle.RelationKeyName.String(): pbtypes.String(name),
},
},
Details: pbtypes.StructFilterKeys(details, []string{bundle.RelationKeyName.String(), bundle.RelationKeyIsHiddenDiscovery.String()}),
}
if strings.HasPrefix(filePath, "http://") || strings.HasPrefix(filePath, "https://") {

View file

@ -533,19 +533,13 @@ func (i *Import) sendImportFinishEventToClient(rootCollectionID string, isSync b
if isSync {
return
}
i.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfImportFinish{
ImportFinish: &pb.EventImportFinish{
RootCollectionID: rootCollectionID,
ObjectsCount: objectsCount,
ImportType: importType,
},
},
},
i.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfImportFinish{
ImportFinish: &pb.EventImportFinish{
RootCollectionID: rootCollectionID,
ObjectsCount: objectsCount,
ImportType: importType,
},
})
}))
}
func convertType(cType string) pb.RpcObjectImportListImportResponseType {

View file

@ -119,21 +119,15 @@ func (m *treeManager) DeleteTree(ctx context.Context, spaceId, treeId string) (e
return
}
m.sendOnRemoveEvent(treeId)
m.sendOnRemoveEvent(spaceId, []string{treeId})
err = spc.Remove(ctx, treeId)
return
}
func (m *treeManager) sendOnRemoveEvent(ids ...string) {
m.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfObjectRemove{
ObjectRemove: &pb.EventObjectRemove{
Ids: ids,
},
},
},
func (m *treeManager) sendOnRemoveEvent(spaceId string, ids []string) {
m.eventSender.Broadcast(event.NewEventSingleMessage(spaceId, &pb.EventMessageValueOfObjectRemove{
ObjectRemove: &pb.EventObjectRemove{
Ids: ids,
},
})
}))
}

View file

@ -8,6 +8,7 @@ import (
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/app/logger"
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
"github.com/anyproto/any-sync/commonspace/object/tree/synctree"
"github.com/anyproto/any-sync/commonspace/object/treemanager"
"github.com/anyproto/any-sync/commonspace/object/treesyncer"
@ -193,7 +194,7 @@ func (t *treeSyncer) SyncAll(ctx context.Context, p peer.Peer, existing, missing
for _, id := range missing {
idCopy := id
err = reqExec.tryAdd(idCopy, func() {
t.requestTree(peerId, idCopy)
t.requestTree(p, idCopy)
})
if err != nil {
log.Error("failed to add to request queue", zap.Error(err))
@ -214,17 +215,22 @@ func (t *treeSyncer) sendDetailsUpdates(existing, missing []string) {
t.syncDetailsUpdater.UpdateSpaceDetails(existing, missing, t.spaceId)
}
func (t *treeSyncer) requestTree(peerId, id string) {
func (t *treeSyncer) requestTree(p peer.Peer, id string) {
log := log.With(zap.String("treeId", id))
peerId := p.Id()
ctx := peer.CtxWithPeerId(t.mainCtx, peerId)
ctx, cancel := context.WithTimeout(ctx, t.timeout)
defer cancel()
_, err := t.treeManager.GetTree(ctx, t.spaceId, id)
tr, err := t.treeManager.GetTree(ctx, t.spaceId, id)
if err != nil {
log.Warn("can't load missing tree", zap.Error(err))
return
} else {
log.Debug("loaded missing tree")
}
if objecttree.IsEmptyDerivedTree(tr) {
t.pingTree(p, tr)
}
}
func (t *treeSyncer) updateTree(p peer.Peer, id string) {
@ -236,12 +242,16 @@ func (t *treeSyncer) updateTree(p peer.Peer, id string) {
log.Warn("can't load existing tree", zap.Error(err))
return
}
t.pingTree(p, tr)
}
func (t *treeSyncer) pingTree(p peer.Peer, tr objecttree.ObjectTree) {
syncTree, ok := tr.(synctree.SyncTree)
if !ok {
log.Warn("not a sync tree")
return
}
if err = syncTree.SyncWithPeer(ctx, p); err != nil {
if err := syncTree.SyncWithPeer(p.Context(), p); err != nil {
log.Warn("synctree.SyncWithPeer error", zap.Error(err))
} else {
log.Debug("success synctree.SyncWithPeer")

View file

@ -2,13 +2,13 @@ package treesyncer
import (
"context"
"fmt"
"sync"
"testing"
"time"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree/mock_objecttree"
"github.com/anyproto/any-sync/commonspace/object/tree/synctree/mock_synctree"
"github.com/anyproto/any-sync/commonspace/object/treemanager/mock_treemanager"
"github.com/anyproto/any-sync/commonspace/spacestorage/mock_spacestorage"
@ -26,7 +26,7 @@ import (
type fixture struct {
*treeSyncer
missingMock *mock_objecttree.MockObjectTree
missingMock *mock_synctree.MockSyncTree
existingMock *mock_synctree.MockSyncTree
treeManager *mock_treemanager.MockTreeManager
nodeConf *mock_nodeconf.MockService
@ -37,7 +37,7 @@ type fixture struct {
func newFixture(t *testing.T, spaceId string) *fixture {
ctrl := gomock.NewController(t)
treeManager := mock_treemanager.NewMockTreeManager(ctrl)
missingMock := mock_objecttree.NewMockObjectTree(ctrl)
missingMock := mock_synctree.NewMockSyncTree(ctrl)
existingMock := mock_synctree.NewMockSyncTree(ctrl)
nodeConf := mock_nodeconf.NewMockService(ctrl)
nodeConf.EXPECT().Name().Return("nodeConf").AnyTimes()
@ -75,11 +75,34 @@ func TestTreeSyncer(t *testing.T) {
pr := rpctest.MockPeer{}
t.Run("delayed sync", func(t *testing.T) {
ctx := context.Background()
fx := newFixture(t, spaceId)
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(fx.existingMock, nil)
fx.existingMock.EXPECT().SyncWithPeer(gomock.Any(), pr).Return(nil)
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(nil, fmt.Errorf("not found"))
fx.nodeConf.EXPECT().NodeIds(spaceId).Return([]string{})
fx.syncStatus.EXPECT().RemoveAllExcept(peerId, []string{existingId}).Return()
err := fx.SyncAll(context.Background(), pr, []string{existingId}, []string{missingId})
require.NoError(t, err)
require.NotNil(t, fx.requestPools[peerId])
require.NotNil(t, fx.headPools[peerId])
fx.StartSync()
time.Sleep(100 * time.Millisecond)
fx.Close(ctx)
})
t.Run("delayed sync empty derived", func(t *testing.T) {
ctx := context.Background()
fx := newFixture(t, spaceId)
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(fx.existingMock, nil)
fx.existingMock.EXPECT().SyncWithPeer(gomock.Any(), pr).Return(nil)
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(fx.missingMock, nil)
fx.missingMock.EXPECT().IsDerived().Return(true)
fx.missingMock.EXPECT().Len().Return(1)
fx.missingMock.EXPECT().Root().Return(&objecttree.Change{Id: "id"})
fx.missingMock.EXPECT().Id().Return("id")
fx.missingMock.EXPECT().SyncWithPeer(gomock.Any(), pr).Return(nil)
fx.nodeConf.EXPECT().NodeIds(spaceId).Return([]string{})
fx.syncStatus.EXPECT().RemoveAllExcept(peerId, []string{existingId}).Return()
err := fx.SyncAll(context.Background(), pr, []string{existingId}, []string{missingId})
@ -99,6 +122,7 @@ func TestTreeSyncer(t *testing.T) {
fx.existingMock.EXPECT().SyncWithPeer(gomock.Any(), pr).Return(nil)
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(fx.missingMock, nil)
fx.nodeConf.EXPECT().NodeIds(spaceId).Return([]string{peerId})
fx.missingMock.EXPECT().IsDerived().Return(false)
fx.syncDetailsUpdater.EXPECT().UpdateSpaceDetails([]string{existingId}, []string{missingId}, spaceId)
fx.syncStatus.EXPECT().RemoveAllExcept(peerId, []string{existingId}).Return()
err := fx.SyncAll(context.Background(), pr, []string{existingId}, []string{missingId})
@ -117,6 +141,7 @@ func TestTreeSyncer(t *testing.T) {
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(fx.existingMock, nil)
fx.existingMock.EXPECT().SyncWithPeer(gomock.Any(), pr).Return(nil)
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(fx.missingMock, nil)
fx.missingMock.EXPECT().IsDerived().Return(false)
fx.nodeConf.EXPECT().NodeIds(spaceId).Return([]string{})
fx.syncStatus.EXPECT().RemoveAllExcept(peerId, []string{existingId}).Return()
@ -136,6 +161,7 @@ func TestTreeSyncer(t *testing.T) {
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(fx.existingMock, nil)
fx.existingMock.EXPECT().SyncWithPeer(gomock.Any(), pr).Return(nil)
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(fx.missingMock, nil)
fx.missingMock.EXPECT().IsDerived().Return(false)
fx.nodeConf.EXPECT().NodeIds(spaceId).Return([]string{})
fx.syncStatus.EXPECT().RemoveAllExcept(peerId, []string{existingId, existingId}).Return()
@ -184,6 +210,7 @@ func TestTreeSyncer(t *testing.T) {
<-ch
return fx.missingMock, nil
})
fx.missingMock.EXPECT().IsDerived().AnyTimes().Return(false)
fx.nodeConf.EXPECT().NodeIds(spaceId).Return([]string{})
fx.syncStatus.EXPECT().RemoveAllExcept(peerId, []string{existingId}).Return()
@ -211,6 +238,7 @@ func TestTreeSyncer(t *testing.T) {
mutex.Unlock()
return fx.missingMock, nil
})
fx.missingMock.EXPECT().IsDerived().Return(false)
fx.nodeConf.EXPECT().NodeIds(spaceId).Return(nil)
var existing []string
fx.syncStatus.EXPECT().RemoveAllExcept(peerId, mock.Anything).RunAndReturn(func(s string, strings []string) {

View file

@ -81,49 +81,31 @@ func (s *service) monitor(p Process) {
s.m.Unlock()
}()
info := p.Info()
s.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfProcessNew{
ProcessNew: &pb.EventProcessNew{
Process: &info,
},
},
},
s.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfProcessNew{
ProcessNew: &pb.EventProcessNew{
Process: &info,
},
})
}))
var prevInfo = info
for {
select {
case <-ticker.C:
info := p.Info()
if !infoEquals(info, prevInfo) {
s.eventSender.BroadcastExceptSessions(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfProcessUpdate{
ProcessUpdate: &pb.EventProcessUpdate{
Process: &info,
},
},
},
s.eventSender.BroadcastExceptSessions(event.NewEventSingleMessage("", &pb.EventMessageValueOfProcessUpdate{
ProcessUpdate: &pb.EventProcessUpdate{
Process: &info,
},
}, s.getExcludedSessions())
}), s.getExcludedSessions())
prevInfo = info
}
case <-p.Done():
info := p.Info()
s.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfProcessDone{
ProcessDone: &pb.EventProcessDone{
Process: &info,
},
},
},
s.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfProcessDone{
ProcessDone: &pb.EventProcessDone{
Process: &info,
},
})
}))
if notificationSender, ok := p.(NotificationSender); ok {
notificationSender.SendNotification()
}

View file

@ -277,7 +277,7 @@ func (s *Service) CloseBlock(ctx session.Context, id domain.FullID) error {
if err = s.DeleteObjectByFullID(id); err != nil {
log.Errorf("error while block delete: %v", err)
} else {
sendOnRemoveEvent(s.eventSender, id.ObjectID)
s.sendOnRemoveEvent(id.SpaceID, id.ObjectID)
}
}
mutex.WithLock(s.openedObjs.lock, func() any { delete(s.openedObjs.objects, id.ObjectID); return nil })

View file

@ -6,6 +6,7 @@ import (
"github.com/gogo/protobuf/types"
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
@ -39,13 +40,13 @@ func (s *Base) ModelToSave() *model.Block {
return s.Block
}
func (s *Base) Diff(block simple.Block) (msgs []simple.EventMessage, err error) {
func (s *Base) Diff(spaceId string, block simple.Block) (msgs []simple.EventMessage, err error) {
m := block.Model()
if !stringSlicesEq(m.ChildrenIds, s.ChildrenIds) {
m := &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetChildrenIds{BlockSetChildrenIds: &pb.EventBlockSetChildrenIds{
m := event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetChildrenIds{BlockSetChildrenIds: &pb.EventBlockSetChildrenIds{
Id: s.Id,
ChildrenIds: m.ChildrenIds,
}}}
}})
msgs = append(msgs, simple.EventMessage{Msg: m})
}
@ -56,38 +57,38 @@ func (s *Base) Diff(block simple.Block) (msgs []simple.EventMessage, err error)
m.Restrictions = &model.BlockRestrictions{}
}
if *s.Restrictions != *m.Restrictions {
m := &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetRestrictions{BlockSetRestrictions: &pb.EventBlockSetRestrictions{
m := event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetRestrictions{BlockSetRestrictions: &pb.EventBlockSetRestrictions{
Id: s.Id,
Restrictions: m.Restrictions,
}}}
}})
msgs = append(msgs, simple.EventMessage{Msg: m})
}
if !fieldsEq(s.Fields, m.Fields) {
m := &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetFields{BlockSetFields: &pb.EventBlockSetFields{
m := event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetFields{BlockSetFields: &pb.EventBlockSetFields{
Id: s.Id,
Fields: m.Fields,
}}}
}})
msgs = append(msgs, simple.EventMessage{Msg: m})
}
if s.BackgroundColor != m.BackgroundColor {
m := &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetBackgroundColor{BlockSetBackgroundColor: &pb.EventBlockSetBackgroundColor{
m := event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetBackgroundColor{BlockSetBackgroundColor: &pb.EventBlockSetBackgroundColor{
Id: s.Id,
BackgroundColor: m.BackgroundColor,
}}}
}})
msgs = append(msgs, simple.EventMessage{Msg: m})
}
if s.Align != m.Align {
m := &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetAlign{BlockSetAlign: &pb.EventBlockSetAlign{
m := event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetAlign{BlockSetAlign: &pb.EventBlockSetAlign{
Id: s.Id,
Align: m.Align,
}}}
}})
msgs = append(msgs, simple.EventMessage{Msg: m})
}
if s.VerticalAlign != m.VerticalAlign {
m := &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetVerticalAlign{BlockSetVerticalAlign: &pb.EventBlockSetVerticalAlign{
m := event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetVerticalAlign{BlockSetVerticalAlign: &pb.EventBlockSetVerticalAlign{
Id: s.Id,
VerticalAlign: m.VerticalAlign,
}}}
}})
msgs = append(msgs, simple.EventMessage{Msg: m})
}

View file

@ -35,7 +35,7 @@ func TestBase_Diff(t *testing.T) {
t.Run("equals", func(t *testing.T) {
b1 := testBlock()
b2 := testBlock()
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, diff, 0)
})
@ -43,7 +43,7 @@ func TestBase_Diff(t *testing.T) {
b1 := testBlock()
b2 := testBlock()
b2.ChildrenIds[0], b2.ChildrenIds[1] = b2.ChildrenIds[1], b2.ChildrenIds[2]
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
assert.Equal(t, test.MakeEvent(&pb.EventMessageValueOfBlockSetChildrenIds{
@ -57,7 +57,7 @@ func TestBase_Diff(t *testing.T) {
b1 := testBlock()
b2 := testBlock()
b2.Restrictions.Read = !b1.Restrictions.Read
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
assert.Equal(t, test.MakeEvent(&pb.EventMessageValueOfBlockSetRestrictions{
@ -75,7 +75,7 @@ func TestBase_Diff(t *testing.T) {
b2.Fields.Fields["diff"] = &types.Value{
Kind: &types.Value_StringValue{StringValue: "value"},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
assert.Equal(t, test.MakeEvent(&pb.EventMessageValueOfBlockSetFields{
@ -98,7 +98,7 @@ func TestBase_Diff(t *testing.T) {
// when
b1.BackgroundColor = "yellow"
b2.BackgroundColor = "red"
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -118,7 +118,7 @@ func TestBase_Diff(t *testing.T) {
// when
b1.VerticalAlign = model.Block_VerticalAlignTop
b2.VerticalAlign = model.Block_VerticalAlignMiddle
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -139,7 +139,7 @@ func TestBase_Diff(t *testing.T) {
// when
b1.Align = model.Block_AlignLeft
b2.Align = model.Block_AlignCenter
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)

View file

@ -4,6 +4,7 @@ import (
"fmt"
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
@ -27,12 +28,12 @@ type Div struct {
content *model.BlockContentDiv
}
func (b *Div) Diff(block simple.Block) (msgs []simple.EventMessage, err error) {
func (b *Div) Diff(spaceId string, block simple.Block) (msgs []simple.EventMessage, err error) {
div, ok := block.(*Div)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = b.Base.Diff(div); err != nil {
if msgs, err = b.Base.Diff(spaceId, div); err != nil {
return
}
changes := &pb.EventBlockSetDiv{
@ -45,7 +46,7 @@ func (b *Div) Diff(block simple.Block) (msgs []simple.EventMessage, err error) {
changes.Style = &pb.EventBlockSetDivStyle{Value: div.content.Style}
}
if hasChanges {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetDiv{BlockSetDiv: changes}}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetDiv{BlockSetDiv: changes})})
}
return
}

View file

@ -21,7 +21,7 @@ func TestDiv_Diff(t *testing.T) {
t.Run("type error", func(t *testing.T) {
b1 := testBlock()
b2 := NewBase(&model.Block{})
_, err := b1.Diff(b2)
_, err := b1.Diff("", b2)
assert.Error(t, err)
})
t.Run("no diff", func(t *testing.T) {
@ -29,7 +29,7 @@ func TestDiv_Diff(t *testing.T) {
b2 := testBlock()
b1.content.Style = model.BlockContentDiv_Dots
b2.content.Style = model.BlockContentDiv_Dots
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 0)
})
@ -37,7 +37,7 @@ func TestDiv_Diff(t *testing.T) {
b1 := testBlock()
b2 := testBlock()
b2.Restrictions.Read = true
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 1)
})
@ -46,7 +46,7 @@ func TestDiv_Diff(t *testing.T) {
b2 := testBlock()
b2.SetStyle(model.BlockContentDiv_Dots)
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
assert.Equal(t, test.MakeEvent(&pb.EventMessageValueOfBlockSetDiv{

View file

@ -7,6 +7,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple/base"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/core/domain/objectorigin"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
@ -88,12 +89,12 @@ func (b *Bookmark) Validate() error {
return nil
}
func (b *Bookmark) Diff(other simple.Block) (msgs []simple.EventMessage, err error) {
func (b *Bookmark) Diff(spaceId string, other simple.Block) (msgs []simple.EventMessage, err error) {
bookmark, ok := other.(*Bookmark)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = b.Base.Diff(bookmark); err != nil {
if msgs, err = b.Base.Diff(spaceId, bookmark); err != nil {
return
}
changes := &pb.EventBlockSetBookmark{
@ -135,7 +136,7 @@ func (b *Bookmark) Diff(other simple.Block) (msgs []simple.EventMessage, err err
}
if hasChanges {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetBookmark{BlockSetBookmark: changes}}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetBookmark{BlockSetBookmark: changes})})
}
return
}

View file

@ -39,7 +39,7 @@ func TestBookmark_Diff(t *testing.T) {
t.Run("type error", func(t *testing.T) {
b1 := testBlock()
b2 := base.NewBase(&model.Block{})
_, err := b1.Diff(b2)
_, err := b1.Diff("", b2)
assert.Error(t, err)
})
t.Run("no diff", func(t *testing.T) {
@ -47,7 +47,7 @@ func TestBookmark_Diff(t *testing.T) {
b2 := testBlock()
setLinkPreview(b1, lp)
setLinkPreview(b2, lp)
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 0)
})
@ -55,7 +55,7 @@ func TestBookmark_Diff(t *testing.T) {
b1 := testBlock()
b2 := testBlock()
b2.Restrictions.Read = true
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 1)
})
@ -70,7 +70,7 @@ func TestBookmark_Diff(t *testing.T) {
c.BookmarkContent.TargetObjectId = "newobject"
})
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
assert.Equal(t, test.MakeEvent(&pb.EventMessageValueOfBlockSetBookmark{

View file

@ -6,71 +6,72 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/util/pbtypes"
"github.com/anyproto/anytype-heart/util/slice"
)
func (d *Dataview) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
func (d *Dataview) Diff(spaceId string, b simple.Block) (msgs []simple.EventMessage, err error) {
other, ok := b.(*Dataview)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = d.Base.Diff(other); err != nil {
if msgs, err = d.Base.Diff(spaceId, other); err != nil {
return
}
msgs = d.diffGroupOrders(other, msgs)
msgs = d.diffObjectOrders(other, msgs)
msgs = d.diffViews(other, msgs)
msgs = d.diffRelationLinks(other, msgs)
msgs = d.diffSources(other, msgs)
msgs = d.diffOrderOfViews(other, msgs)
msgs = d.diffTargetObjectIDs(other, msgs)
msgs = d.diffIsCollections(other, msgs)
msgs = d.diffGroupOrders(spaceId, other, msgs)
msgs = d.diffObjectOrders(spaceId, other, msgs)
msgs = d.diffViews(spaceId, other, msgs)
msgs = d.diffRelationLinks(spaceId, other, msgs)
msgs = d.diffSources(spaceId, other, msgs)
msgs = d.diffOrderOfViews(spaceId, other, msgs)
msgs = d.diffTargetObjectIDs(spaceId, other, msgs)
msgs = d.diffIsCollections(spaceId, other, msgs)
return
}
func (d *Dataview) diffIsCollections(other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
func (d *Dataview) diffIsCollections(spaceId string, other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
if other.content.IsCollection != d.content.IsCollection {
msgs = append(msgs,
simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewIsCollectionSet{
simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataviewIsCollectionSet{
BlockDataviewIsCollectionSet: &pb.EventBlockDataviewIsCollectionSet{
Id: other.Id,
Value: other.content.IsCollection,
}},
}})
)})
}
return msgs
}
func (d *Dataview) diffTargetObjectIDs(other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
func (d *Dataview) diffTargetObjectIDs(spaceId string, other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
if other.content.TargetObjectId != d.content.TargetObjectId {
msgs = append(msgs,
simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewTargetObjectIdSet{
simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataviewTargetObjectIdSet{
BlockDataviewTargetObjectIdSet: &pb.EventBlockDataviewTargetObjectIdSet{
Id: other.Id,
TargetObjectId: other.content.TargetObjectId,
}},
}})
)})
}
return msgs
}
func (d *Dataview) diffSources(other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
func (d *Dataview) diffSources(spaceId string, other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
if !slice.UnsortedEqual(other.content.Source, d.content.Source) {
msgs = append(msgs,
simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewSourceSet{
simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataviewSourceSet{
&pb.EventBlockDataviewSourceSet{
Id: other.Id,
Source: other.content.Source,
}}}})
}})})
}
return msgs
}
func (d *Dataview) diffViews(other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
func (d *Dataview) diffViews(spaceId string, other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
// @TODO: rewrite for optimised compare
for _, view2 := range other.content.Views {
var found bool
@ -97,7 +98,7 @@ func (d *Dataview) diffViews(other *Dataview, msgs []simple.EventMessage) []simp
if len(viewFilterChanges) > 0 || len(viewRelationChanges) > 0 || len(viewSortChanges) > 0 || viewFieldsChange != nil {
msgs = append(msgs,
simple.EventMessage{
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewViewUpdate{
Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataviewViewUpdate{
BlockDataviewViewUpdate: &pb.EventBlockDataviewViewUpdate{
Id: other.Id,
ViewId: view2.Id,
@ -106,18 +107,18 @@ func (d *Dataview) diffViews(other *Dataview, msgs []simple.EventMessage) []simp
Relation: viewRelationChanges,
Sort: viewSortChanges,
},
}}})
})})
}
if !found {
msgs = append(msgs,
simple.EventMessage{
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewViewSet{
Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataviewViewSet{
&pb.EventBlockDataviewViewSet{
Id: other.Id,
ViewId: view2.Id,
View: view2,
}}}})
}})})
}
}
@ -132,42 +133,42 @@ func (d *Dataview) diffViews(other *Dataview, msgs []simple.EventMessage) []simp
if !found {
msgs = append(msgs,
simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewViewDelete{
simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataviewViewDelete{
&pb.EventBlockDataviewViewDelete{
Id: other.Id,
ViewId: view1.Id,
}}}})
}})})
}
}
return msgs
}
func (d *Dataview) diffRelationLinks(other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
func (d *Dataview) diffRelationLinks(spaceId string, other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
added, removed := pbtypes.RelationLinks(other.content.RelationLinks).Diff(d.content.RelationLinks)
if len(removed) > 0 {
msgs = append(msgs, simple.EventMessage{
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewRelationDelete{
Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataviewRelationDelete{
BlockDataviewRelationDelete: &pb.EventBlockDataviewRelationDelete{
Id: other.Id,
RelationKeys: removed,
},
}},
}),
})
}
if len(added) > 0 {
msgs = append(msgs, simple.EventMessage{
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewRelationSet{
Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataviewRelationSet{
BlockDataviewRelationSet: &pb.EventBlockDataviewRelationSet{
Id: other.Id,
RelationLinks: added,
},
}},
}),
})
}
return msgs
}
func (d *Dataview) diffOrderOfViews(other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
func (d *Dataview) diffOrderOfViews(spaceId string, other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
var viewIds1, viewIds2 []string
for _, v := range d.content.Views {
viewIds1 = append(viewIds1, v.Id)
@ -177,16 +178,16 @@ func (d *Dataview) diffOrderOfViews(other *Dataview, msgs []simple.EventMessage)
}
if !slice.SortedEquals(viewIds1, viewIds2) {
msgs = append(msgs,
simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewViewOrder{
simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataviewViewOrder{
&pb.EventBlockDataviewViewOrder{
Id: other.Id,
ViewIds: viewIds2,
}}}})
}})})
}
return msgs
}
func (d *Dataview) diffObjectOrders(other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
func (d *Dataview) diffObjectOrders(spaceId string, other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
for _, order2 := range other.content.ObjectOrders {
var found bool
var changes []*pb.EventBlockDataviewSliceChange
@ -201,31 +202,31 @@ func (d *Dataview) diffObjectOrders(other *Dataview, msgs []simple.EventMessage)
if !found {
msgs = append(msgs,
simple.EventMessage{
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataViewObjectOrderUpdate{
Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataViewObjectOrderUpdate{
&pb.EventBlockDataviewObjectOrderUpdate{
Id: other.Id,
ViewId: order2.ViewId,
GroupId: order2.GroupId,
SliceChanges: []*pb.EventBlockDataviewSliceChange{{Op: pb.EventBlockDataview_SliceOperationAdd, Ids: order2.ObjectIds}},
}}}})
}})})
}
if len(changes) > 0 {
msgs = append(msgs,
simple.EventMessage{
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataViewObjectOrderUpdate{
Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataViewObjectOrderUpdate{
&pb.EventBlockDataviewObjectOrderUpdate{
Id: other.Id,
ViewId: order2.ViewId,
GroupId: order2.GroupId,
SliceChanges: changes,
}}}})
}})})
}
}
return msgs
}
func (d *Dataview) diffGroupOrders(other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
func (d *Dataview) diffGroupOrders(spaceId string, other *Dataview, msgs []simple.EventMessage) []simple.EventMessage {
for _, order2 := range other.content.GroupOrders {
var found, changed bool
for _, order1 := range d.content.GroupOrders {
@ -239,11 +240,11 @@ func (d *Dataview) diffGroupOrders(other *Dataview, msgs []simple.EventMessage)
if !found || changed {
msgs = append(msgs,
simple.EventMessage{
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataViewGroupOrderUpdate{
Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockDataViewGroupOrderUpdate{
&pb.EventBlockDataviewGroupOrderUpdate{
Id: other.Id,
GroupOrder: order2,
}}}})
}})})
}
}
return msgs

View file

@ -26,7 +26,7 @@ func TestDiff(t *testing.T) {
// when
b2.content.IsCollection = true
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -46,7 +46,7 @@ func TestDiff(t *testing.T) {
// when
b1.content.TargetObjectId = "1"
b2.content.TargetObjectId = "2"
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -65,7 +65,7 @@ func TestDiff(t *testing.T) {
// when
b2.content.Source = []string{"1"}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -87,7 +87,7 @@ func TestDiff(t *testing.T) {
// when
b2.content.Source = nil
b1.content.Source = []string{"1"}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -107,7 +107,7 @@ func TestDiff(t *testing.T) {
// when
b1.content.Views = []*model.BlockContentDataviewView{{Id: "1"}, {Id: "2"}}
b2.content.Views = []*model.BlockContentDataviewView{{Id: "2"}, {Id: "1"}}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -186,7 +186,7 @@ func TestDiff(t *testing.T) {
ViewGroups: view2Groups,
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -233,7 +233,7 @@ func TestDiff(t *testing.T) {
ObjectIds: []string{"object1", "object3"},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -281,7 +281,7 @@ func TestDiff(t *testing.T) {
ObjectIds: []string{"object1"},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -338,7 +338,7 @@ func TestDiff(t *testing.T) {
ObjectIds: []string{"object1", "object3", "object2"},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -383,7 +383,7 @@ func TestDiff(t *testing.T) {
Format: model.RelationFormat_longtext,
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -424,7 +424,7 @@ func TestDiff(t *testing.T) {
Format: model.RelationFormat_longtext,
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -472,7 +472,7 @@ func TestDiff(t *testing.T) {
PageLimit: 11,
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -517,7 +517,7 @@ func TestDiff(t *testing.T) {
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -561,7 +561,7 @@ func TestDiff(t *testing.T) {
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -618,7 +618,7 @@ func TestDiff(t *testing.T) {
Sorts: []*model.BlockContentDataviewSort{newSort},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -685,7 +685,7 @@ func TestDiff(t *testing.T) {
},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -735,7 +735,7 @@ func TestDiff(t *testing.T) {
Id: "1",
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -793,7 +793,7 @@ func TestDiff(t *testing.T) {
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -846,7 +846,7 @@ func TestDiff(t *testing.T) {
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -912,7 +912,7 @@ func TestDiff(t *testing.T) {
},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -985,7 +985,7 @@ func TestDiff(t *testing.T) {
},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -1039,7 +1039,7 @@ func TestDiff(t *testing.T) {
},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -1105,7 +1105,7 @@ func TestDiff(t *testing.T) {
},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -1154,7 +1154,7 @@ func TestDiff(t *testing.T) {
Relations: []*model.BlockContentDataviewRelation{},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -1218,7 +1218,7 @@ func TestDiff(t *testing.T) {
},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -1363,7 +1363,7 @@ func TestDiff(t *testing.T) {
ObjectIds: []string{"object1", "object2", "object3"},
},
}
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)

View file

@ -5,6 +5,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/block/simple/base"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
@ -50,12 +51,12 @@ func (l *Latex) Validate() error {
return nil
}
func (l *Latex) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
func (l *Latex) Diff(spaceId string, b simple.Block) (msgs []simple.EventMessage, err error) {
embed, ok := b.(*Latex)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = l.Base.Diff(embed); err != nil {
if msgs, err = l.Base.Diff(spaceId, embed); err != nil {
return
}
changes := &pb.EventBlockSetLatex{
@ -74,7 +75,7 @@ func (l *Latex) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
}
if hasChanges {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetLatex{BlockSetLatex: changes}}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetLatex{BlockSetLatex: changes})})
}
return
}

View file

@ -22,7 +22,7 @@ func TestLatex_Diff(t *testing.T) {
t.Run("type error", func(t *testing.T) {
b1 := testBlock()
b2 := base.NewBase(&model.Block{})
_, err := b1.Diff(b2)
_, err := b1.Diff("", b2)
assert.Error(t, err)
})
t.Run("no diff", func(t *testing.T) {
@ -30,7 +30,7 @@ func TestLatex_Diff(t *testing.T) {
b2 := testBlock()
b1.content.Text = "1"
b2.content.Text = "1"
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 0)
})
@ -38,7 +38,7 @@ func TestLatex_Diff(t *testing.T) {
b1 := testBlock()
b2 := testBlock()
b2.Restrictions.Read = true
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 1)
})
@ -47,7 +47,7 @@ func TestLatex_Diff(t *testing.T) {
b2 := testBlock()
b2.content.Text = "42"
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
assert.Equal(t, test.MakeEvent(&pb.EventMessageValueOfBlockSetLatex{
@ -62,7 +62,7 @@ func TestLatex_Diff(t *testing.T) {
b2 := testBlock()
b2.content.Processor = model.BlockContentLatex_Mermaid
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
assert.Equal(t, test.MakeEvent(&pb.EventMessageValueOfBlockSetLatex{

View file

@ -8,6 +8,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/block/simple/base"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/mill"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
@ -129,12 +130,12 @@ func (f *File) Validate() error {
return nil
}
func (f *File) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
func (f *File) Diff(spaceId string, b simple.Block) (msgs []simple.EventMessage, err error) {
file, ok := b.(*File)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = f.Base.Diff(file); err != nil {
if msgs, err = f.Base.Diff(spaceId, file); err != nil {
return
}
changes := &pb.EventBlockSetFile{
@ -176,7 +177,7 @@ func (f *File) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
}
if hasChanges {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetFile{BlockSetFile: changes}}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetFile{BlockSetFile: changes})})
}
return
}

View file

@ -29,7 +29,7 @@ func TestFile_Diff(t *testing.T) {
t.Run("type error", func(t *testing.T) {
b1 := testBlock()
b2 := base.NewBase(&model.Block{})
_, err := b1.Diff(b2)
_, err := b1.Diff("", b2)
assert.Error(t, err)
})
t.Run("no diff", func(t *testing.T) {
@ -38,7 +38,7 @@ func TestFile_Diff(t *testing.T) {
tm := time.Now()
b1.SetHash("1").SetMIME("2").SetName("3").SetSize(4).SetTime(tm)
b2.SetHash("1").SetMIME("2").SetName("3").SetSize(4).SetTime(tm)
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 0)
})
@ -46,7 +46,7 @@ func TestFile_Diff(t *testing.T) {
b1 := testBlockPdf()
b2 := testBlockPdf()
b2.Restrictions.Read = true
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 1)
})
@ -57,7 +57,7 @@ func TestFile_Diff(t *testing.T) {
b2.SetState(model.BlockContentFile_Done)
b2.SetHash("hash").SetMIME("video/mpeg").SetName("image.mpg").SetSize(3).SetTime(time.Now()).SetType(model.BlockContentFile_Video)
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
assert.Equal(t, test.MakeEvent(&pb.EventMessageValueOfBlockSetFile{

View file

@ -5,6 +5,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/block/simple/base"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
@ -65,12 +66,12 @@ func (l *Link) SetAppearance(content *model.BlockContentLink) error {
return nil
}
func (l *Link) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
func (l *Link) Diff(spaceId string, b simple.Block) (msgs []simple.EventMessage, err error) {
link, ok := b.(*Link)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = l.Base.Diff(link); err != nil {
if msgs, err = l.Base.Diff(spaceId, link); err != nil {
return
}
changes := &pb.EventBlockSetLink{
@ -108,7 +109,7 @@ func (l *Link) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
}
if hasChanges {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetLink{BlockSetLink: changes}}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetLink{BlockSetLink: changes})})
}
return
}

View file

@ -23,7 +23,7 @@ func TestLink_Diff(t *testing.T) {
t.Run("type error", func(t *testing.T) {
b1 := testBlock()
b2 := base.NewBase(&model.Block{})
_, err := b1.Diff(b2)
_, err := b1.Diff("", b2)
assert.Error(t, err)
})
t.Run("no diff", func(t *testing.T) {
@ -31,7 +31,7 @@ func TestLink_Diff(t *testing.T) {
b2 := testBlock()
b1.content.TargetBlockId = "1"
b2.content.TargetBlockId = "1"
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 0)
})
@ -39,7 +39,7 @@ func TestLink_Diff(t *testing.T) {
b1 := testBlock()
b2 := testBlock()
b2.Restrictions.Read = true
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 1)
})
@ -55,7 +55,7 @@ func TestLink_Diff(t *testing.T) {
b2.content.IconSize = model.BlockContentLink_SizeMedium
b2.content.Description = model.BlockContentLink_Content
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -78,7 +78,7 @@ func TestLink_Diff(t *testing.T) {
// when
b2.content.Relations = append(b2.content.Relations, "cover")
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)

View file

@ -5,6 +5,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/block/simple/base"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
@ -48,12 +49,12 @@ func (l *Relation) Validate() error {
return nil
}
func (l *Relation) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
func (l *Relation) Diff(spaceId string, b simple.Block) (msgs []simple.EventMessage, err error) {
relation, ok := b.(*Relation)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = l.Base.Diff(relation); err != nil {
if msgs, err = l.Base.Diff(spaceId, relation); err != nil {
return
}
changes := &pb.EventBlockSetRelation{
@ -67,7 +68,7 @@ func (l *Relation) Diff(b simple.Block) (msgs []simple.EventMessage, err error)
}
if hasChanges {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetRelation{BlockSetRelation: changes}}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetRelation{BlockSetRelation: changes})})
}
return
}

View file

@ -22,7 +22,7 @@ func TestRelation_Diff(t *testing.T) {
t.Run("type error", func(t *testing.T) {
b1 := testBlock()
b2 := base.NewBase(&model.Block{})
_, err := b1.Diff(b2)
_, err := b1.Diff("", b2)
assert.Error(t, err)
})
t.Run("no diff", func(t *testing.T) {
@ -30,7 +30,7 @@ func TestRelation_Diff(t *testing.T) {
b2 := testBlock()
b1.content.Key = "1"
b2.content.Key = "1"
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 0)
})
@ -38,7 +38,7 @@ func TestRelation_Diff(t *testing.T) {
b1 := testBlock()
b2 := testBlock()
b2.Restrictions.Read = true
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 1)
})
@ -47,7 +47,7 @@ func TestRelation_Diff(t *testing.T) {
b2 := testBlock()
b2.content.Key = "42"
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
assert.Equal(t, test.MakeEvent(&pb.EventMessageValueOfBlockSetRelation{

View file

@ -26,7 +26,7 @@ func RegisterFallback(c BlockCreator) {
type Block interface {
Model() *model.Block
ModelToSave() *model.Block
Diff(block Block) (msgs []EventMessage, err error)
Diff(spaceId string, block Block) (msgs []EventMessage, err error)
String() string
Copy() Block
Validate() error

View file

@ -5,6 +5,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/block/simple/base"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
@ -43,12 +44,12 @@ func (b *rowBlock) SetIsHeader(v bool) {
b.content.IsHeader = v
}
func (b *rowBlock) Diff(sb simple.Block) (msgs []simple.EventMessage, err error) {
func (b *rowBlock) Diff(spaceId string, sb simple.Block) (msgs []simple.EventMessage, err error) {
other, ok := sb.(*rowBlock)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = b.Base.Diff(other); err != nil {
if msgs, err = b.Base.Diff(spaceId, other); err != nil {
return
}
changes := &pb.EventBlockSetTableRow{
@ -62,7 +63,7 @@ func (b *rowBlock) Diff(sb simple.Block) (msgs []simple.EventMessage, err error)
}
if hasChanges {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetTableRow{BlockSetTableRow: changes}}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetTableRow{BlockSetTableRow: changes})})
}
return
}

View file

@ -25,7 +25,7 @@ func TestDiff(t *testing.T) {
// when
b2.content.IsHeader = true
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)

View file

@ -5,6 +5,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
@ -92,23 +93,21 @@ func (td *textDetails) Validate() error {
return nil
}
func (td *textDetails) Diff(s simple.Block) (msgs []simple.EventMessage, err error) {
func (td *textDetails) Diff(spaceId string, s simple.Block) (msgs []simple.EventMessage, err error) {
sd, ok := s.(*textDetails)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = td.Text.Diff(sd.Text); err != nil {
if msgs, err = td.Text.Diff(spaceId, sd.Text); err != nil {
return
}
var virtEvent = simple.EventMessage{
virtEvent := simple.EventMessage{
Virtual: true,
Msg: &pb.EventMessage{
Value: &pb.EventMessageValueOfBlockSetText{
BlockSetText: &pb.EventBlockSetText{
Id: td.Id,
},
Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetText{
BlockSetText: &pb.EventBlockSetText{
Id: td.Id,
},
},
}),
}
var (
toRemove = -1

View file

@ -90,7 +90,7 @@ func TestTextDetails_Diff(t *testing.T) {
assert.Equal(t, "changed", ds.details.GetString("title"))
assert.Equal(t, true, ds.details.GetBool("checked"))
msgs, err := orig.Diff(db)
msgs, err := orig.Diff("", db)
require.NoError(t, err)
require.Len(t, msgs, 1)
assert.True(t, msgs[0].Virtual)
@ -116,7 +116,7 @@ func TestTextDetails_Diff(t *testing.T) {
"keys": pbtypes.String("value"),
},
}
msgs, err := orig.Diff(db)
msgs, err := orig.Diff("", db)
require.NoError(t, err)
require.Len(t, msgs, 1)
assert.False(t, msgs[0].Virtual)

View file

@ -6,6 +6,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/block/simple/base"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/logging"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
@ -98,12 +99,12 @@ func (t *Text) Validate() error {
return nil
}
func (t *Text) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
func (t *Text) Diff(spaceId string, b simple.Block) (msgs []simple.EventMessage, err error) {
text, ok := b.(*Text)
if !ok {
return nil, fmt.Errorf("can't make diff with different block type")
}
if msgs, err = t.Base.Diff(text); err != nil {
if msgs, err = t.Base.Diff(spaceId, text); err != nil {
return
}
changes := &pb.EventBlockSetText{
@ -140,7 +141,7 @@ func (t *Text) Diff(b simple.Block) (msgs []simple.EventMessage, err error) {
changes.IconEmoji = &pb.EventBlockSetTextIconEmoji{Value: text.content.IconEmoji}
}
if hasChanges {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetText{BlockSetText: changes}}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetText{BlockSetText: changes})})
}
return
}

View file

@ -22,7 +22,7 @@ func TestText_Diff(t *testing.T) {
t.Run("type error", func(t *testing.T) {
b1 := testBlock()
b2 := base.NewBase(&model.Block{})
_, err := b1.Diff(b2)
_, err := b1.Diff("", b2)
assert.Error(t, err)
})
t.Run("no diff", func(t *testing.T) {
@ -30,7 +30,7 @@ func TestText_Diff(t *testing.T) {
b2 := testBlock()
b1.SetText("same text", &model.BlockContentTextMarks{})
b2.SetText("same text", &model.BlockContentTextMarks{})
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 0)
})
@ -38,7 +38,7 @@ func TestText_Diff(t *testing.T) {
b1 := testBlock()
b2 := testBlock()
b2.Restrictions.Read = true
d, err := b1.Diff(b2)
d, err := b1.Diff("", b2)
require.NoError(t, err)
assert.Len(t, d, 1)
})
@ -55,7 +55,7 @@ func TestText_Diff(t *testing.T) {
})
b2.SetStyle(model.BlockContentText_Header2)
b2.SetChecked(true)
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
require.NoError(t, err)
require.Len(t, diff, 1)
textChange := diff[0].Msg.Value.(*pb.EventMessageValueOfBlockSetText).BlockSetText

View file

@ -5,6 +5,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/simple"
"github.com/anyproto/anytype-heart/core/block/simple/base"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
@ -38,12 +39,12 @@ func (b *block) Copy() simple.Block {
return NewBlock(pbtypes.CopyBlock(b.Model()))
}
func (b *block) Diff(ob simple.Block) (msgs []simple.EventMessage, err error) {
func (b *block) Diff(spaceId string, ob simple.Block) (msgs []simple.EventMessage, err error) {
other, ok := ob.(*block)
if !ok {
return nil, fmt.Errorf("can't make diff with incompatible block")
}
if msgs, err = b.Base.Diff(other); err != nil {
if msgs, err = b.Base.Diff(spaceId, other); err != nil {
return
}
@ -68,7 +69,7 @@ func (b *block) Diff(ob simple.Block) (msgs []simple.EventMessage, err error) {
}
if hasChanges {
msgs = append(msgs, simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockSetWidget{BlockSetWidget: changes}}})
msgs = append(msgs, simple.EventMessage{Msg: event.NewMessage(spaceId, &pb.EventMessageValueOfBlockSetWidget{BlockSetWidget: changes})})
}
return
}

View file

@ -25,7 +25,7 @@ func TestDiff(t *testing.T) {
// when
b2.content.Layout = model.BlockContentWidget_Tree
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -47,7 +47,7 @@ func TestDiff(t *testing.T) {
// when
b2.content.ViewId = "viewID"
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)
@ -69,7 +69,7 @@ func TestDiff(t *testing.T) {
// when
b2.content.Limit = 10
diff, err := b1.Diff(b2)
diff, err := b1.Diff("", b2)
// then
require.NoError(t, err)

View file

@ -348,7 +348,7 @@ func (s *source) buildState() (doc state.Doc, err error) {
}
// TODO: check if we can use apply fast one
if _, _, err = state.ApplyState(st, false); err != nil {
if _, _, err = state.ApplyState(s.spaceID, st, false); err != nil {
return
}
return st, nil
@ -622,7 +622,7 @@ func BuildState(spaceId string, initState *state.State, ot objecttree.ReadableOb
return
}
if applyState {
_, _, err = state.ApplyStateFastOne(st)
_, _, err = state.ApplyStateFastOne(spaceId, st)
if err != nil {
return
}

View file

@ -9,11 +9,9 @@ import (
func (mw *Middleware) BroadcastPayloadEvent(cctx context.Context, req *pb.RpcBroadcastPayloadEventRequest) *pb.RpcBroadcastPayloadEventResponse {
messages := []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfPayloadBroadcast{
PayloadBroadcast: &pb.EventPayloadBroadcast{Payload: req.Payload},
},
},
event.NewMessage("", &pb.EventMessageValueOfPayloadBroadcast{
PayloadBroadcast: &pb.EventPayloadBroadcast{Payload: req.Payload},
}),
}
mustService[event.Sender](mw).Broadcast(&pb.Event{
Messages: messages,

View file

@ -14,7 +14,7 @@ import (
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/wallet"
pbMiddle "github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/logging"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/space/clientspace"
@ -130,17 +130,11 @@ func (c *configFetcher) notifyClientApp(status *coordinatorproto.SpaceStatusPayl
}
c.lastStatus = s.StatusType
ev := &pbMiddle.Event{
Messages: []*pbMiddle.EventMessage{
{
Value: &pbMiddle.EventMessageValueOfAccountUpdate{
AccountUpdate: &pbMiddle.EventAccountUpdate{
Status: s,
},
},
},
ev := event.NewEventSingleMessage("", &pb.EventMessageValueOfAccountUpdate{
AccountUpdate: &pb.EventAccountUpdate{
Status: s,
},
}
})
if c.eventSender != nil {
c.eventSender.Broadcast(ev)
}

View file

@ -77,7 +77,7 @@ func (t *treeImporter) State() (*state.State, error) {
return nil, err
}
if _, _, err = state.ApplyStateFast(st); err != nil {
if _, _, err = state.ApplyStateFast("", st); err != nil {
return nil, err
}
return st, nil

View file

@ -55,3 +55,16 @@ func (es *CallbackSender) Broadcast(event *pb.Event) {
func (es *CallbackSender) BroadcastExceptSessions(event *pb.Event, exceptTokens []string) {
es.callback(event)
}
func NewMessage(spaceId string, value pb.IsEventMessageValue) *pb.EventMessage {
return &pb.EventMessage{
SpaceId: spaceId,
Value: value,
}
}
func NewEventSingleMessage(spaceId string, value pb.IsEventMessageValue) *pb.Event {
return &pb.Event{
Messages: []*pb.EventMessage{NewMessage(spaceId, value)},
}
}

View file

@ -15,6 +15,7 @@ import (
"go.uber.org/zap"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/util/conc"
)
@ -229,18 +230,12 @@ func (s *fileSync) sendSpaceUsageEvent(spaceId string, bytesUsage uint64) {
}
func makeSpaceUsageEvent(spaceId string, bytesUsage uint64) *pb.Event {
return &pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfFileSpaceUsage{
FileSpaceUsage: &pb.EventFileSpaceUsage{
BytesUsage: bytesUsage,
SpaceId: spaceId,
},
},
},
return event.NewEventSingleMessage("", &pb.EventMessageValueOfFileSpaceUsage{
FileSpaceUsage: &pb.EventFileSpaceUsage{
BytesUsage: bytesUsage,
SpaceId: spaceId,
},
}
})
}
func (s *fileSync) sendLimitUpdatedEvent(limit uint64) {
@ -248,17 +243,11 @@ func (s *fileSync) sendLimitUpdatedEvent(limit uint64) {
}
func makeLimitUpdatedEvent(limit uint64) *pb.Event {
return &pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfFileLimitUpdated{
FileLimitUpdated: &pb.EventFileLimitUpdated{
BytesLimit: limit,
},
},
},
return event.NewEventSingleMessage("", &pb.EventMessageValueOfFileLimitUpdated{
FileLimitUpdated: &pb.EventFileLimitUpdated{
BytesLimit: limit,
},
}
})
}
func (s *fileSync) FileListStats(ctx context.Context, spaceID string, hashes []domain.FileId) ([]FileStat, error) {

View file

@ -19,6 +19,7 @@ import (
"go.uber.org/zap"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/filestorage"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/util/persistentqueue"
@ -354,33 +355,20 @@ func (s *fileSync) uploadFile(ctx context.Context, spaceID string, fileId domain
}
func (s *fileSync) sendLimitReachedEvent(spaceID string) {
s.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfFileLimitReached{
FileLimitReached: &pb.EventFileLimitReached{
SpaceId: spaceID,
},
},
},
s.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfFileLimitReached{
FileLimitReached: &pb.EventFileLimitReached{
SpaceId: spaceID,
},
})
}))
}
func (s *fileSync) addImportEvent(spaceID string) {
s.importEventsMutex.Lock()
defer s.importEventsMutex.Unlock()
s.importEvents = append(s.importEvents, &pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfFileLimitReached{
FileLimitReached: &pb.EventFileLimitReached{
SpaceId: spaceID,
},
},
},
},
})
s.importEvents = append(s.importEvents, event.NewEventSingleMessage("", &pb.EventMessageValueOfFileLimitReached{
FileLimitReached: &pb.EventFileLimitReached{
SpaceId: spaceID,
}}))
}
type blocksAvailabilityResponse struct {

View file

@ -190,17 +190,11 @@ func (d *localBytesUsageEventSender) sendLocalBytesUsageEvent(localBytesUsage ui
}
func (d *localBytesUsageEventSender) send(usage uint64) {
d.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfFileLocalUsage{
FileLocalUsage: &pb.EventFileLocalUsage{
LocalBytesUsage: usage,
},
},
},
d.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfFileLocalUsage{
FileLocalUsage: &pb.EventFileLocalUsage{
LocalBytesUsage: usage,
},
})
}))
}
type LocalStoreGarbageCollector interface {

View file

@ -241,7 +241,7 @@ func (h *history) DiffVersions(req *pb.RpcHistoryDiffVersionsRequest) ([]*pb.Eve
}
currState.SetParent(previousState)
msg, _, err := state.ApplyState(currState, false)
msg, _, err := state.ApplyState(req.SpaceId, currState, false)
if err != nil {
return nil, nil, fmt.Errorf("failed to get history events for versions %s, %s: %w", req.CurrentVersion, req.PreviousVersion, err)
}
@ -560,7 +560,7 @@ func (h *history) buildState(id domain.FullID, versionId string) (st *state.Stat
if err != nil {
return
}
if _, _, err = state.ApplyStateFast(st); err != nil {
if _, _, err = state.ApplyStateFast(id.SpaceID, st); err != nil {
return
}

View file

@ -161,17 +161,11 @@ func (n *notificationService) CreateAndSend(notification *model.Notification) er
return nil
}
}
n.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfNotificationSend{
NotificationSend: &pb.EventNotificationSend{
Notification: notification,
},
},
},
n.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfNotificationSend{
NotificationSend: &pb.EventNotificationSend{
Notification: notification,
},
})
}))
err := n.notificationStore.SaveNotification(notification)
if err != nil {
return fmt.Errorf("failed to add notification %s to cache: %w", notification.Id, err)
@ -180,17 +174,11 @@ func (n *notificationService) CreateAndSend(notification *model.Notification) er
}
func (n *notificationService) UpdateAndSend(notification *model.Notification) error {
n.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfNotificationUpdate{
NotificationUpdate: &pb.EventNotificationUpdate{
Notification: notification,
},
},
},
n.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfNotificationUpdate{
NotificationUpdate: &pb.EventNotificationUpdate{
Notification: notification,
},
})
}))
err := n.notificationStore.SaveNotification(notification)
if err != nil {
return fmt.Errorf("failed to update notification %s: %w", notification.Id, err)

View file

@ -189,17 +189,11 @@ func (s *service) getPeriodicStatus(ctx context.Context) error {
}
func (s *service) sendMembershipUpdateEvent(status *pb.RpcMembershipGetStatusResponse) {
s.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfMembershipUpdate{
MembershipUpdate: &pb.EventMembershipUpdate{
Data: status.Data,
},
},
},
s.eventSender.Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfMembershipUpdate{
MembershipUpdate: &pb.EventMembershipUpdate{
Data: status.Data,
},
})
}))
}
// GetSubscriptionStatus Logic:

View file

@ -254,22 +254,16 @@ func (p *p2pStatus) countOpenConnections(spaceId string) int64 {
// sendEvent sends event to session with sessionToken or broadcast to all sessions if sessionToken is empty
func (p *p2pStatus) sendEvent(sessionToken string, spaceId string, status pb.EventP2PStatusStatus, count int64) {
event := &pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: spaceId,
Status: status,
DevicesCounter: count,
},
},
},
ev := event.NewEventSingleMessage("", &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: spaceId,
Status: status,
DevicesCounter: count,
},
}
})
if sessionToken != "" {
p.eventSender.SendToSession(sessionToken, event)
p.eventSender.SendToSession(sessionToken, ev)
return
}
p.eventSender.Broadcast(event)
p.eventSender.Broadcast(ev)
}

View file

@ -5,6 +5,7 @@ import (
"fmt"
"time"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
)
@ -33,14 +34,9 @@ func (mw *Middleware) DebugPing(cctx context.Context, req *pb.RpcDebugPingReques
n = time.Now()
fmt.Printf("%d.%d go send ping event %d\n", n.Unix(), nsToMs(n.UnixNano()), i)
mw.applicationService.GetEventSender().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
&pb.EventMessage{
Value: &pb.EventMessageValueOfPing{
Ping: &pb.EventPing{Index: int32(i)},
},
}},
})
mw.applicationService.GetEventSender().Broadcast(event.NewEventSingleMessage("", &pb.EventMessageValueOfPing{
Ping: &pb.EventPing{Index: int32(i)},
}))
}
return response(req.Index, pb.RpcDebugPingResponseError_NULL, nil)

View file

@ -4,6 +4,7 @@ import (
"github.com/samber/lo"
"github.com/anyproto/anytype-heart/core/block/editor/state"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
@ -43,6 +44,7 @@ type opGroup struct {
}
type opCtx struct {
spaceId string
outputs map[string][]*pb.EventMessage
// subIds for remove
@ -86,52 +88,48 @@ func (ctx *opCtx) apply() {
for _, pos := range ctx.position {
if pos.isAdd {
ctx.collectKeys(pos.id, pos.subId, pos.keys)
addEvent(pos.subId, &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionAdd{
SubscriptionAdd: &pb.EventObjectSubscriptionAdd{
Id: pos.id,
AfterId: pos.afterId,
SubId: pos.subId,
},
addEvent(pos.subId, event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfSubscriptionAdd{
SubscriptionAdd: &pb.EventObjectSubscriptionAdd{
Id: pos.id,
AfterId: pos.afterId,
SubId: pos.subId,
},
})
},
))
} else {
addEvent(pos.subId, &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionPosition{
SubscriptionPosition: &pb.EventObjectSubscriptionPosition{
Id: pos.id,
AfterId: pos.afterId,
SubId: pos.subId,
},
addEvent(pos.subId, event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfSubscriptionPosition{
SubscriptionPosition: &pb.EventObjectSubscriptionPosition{
Id: pos.id,
AfterId: pos.afterId,
SubId: pos.subId,
},
})
},
))
}
}
// removes
for _, rem := range ctx.remove {
addEvent(rem.subId, &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionRemove{
SubscriptionRemove: &pb.EventObjectSubscriptionRemove{
Id: rem.id,
SubId: rem.subId,
},
addEvent(rem.subId, event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfSubscriptionRemove{
SubscriptionRemove: &pb.EventObjectSubscriptionRemove{
Id: rem.id,
SubId: rem.subId,
},
})
},
))
}
// counters
for _, count := range ctx.counters {
addEvent(count.subId, &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionCounters{
SubscriptionCounters: &pb.EventObjectSubscriptionCounters{
Total: int64(count.total),
NextCount: int64(count.nextCount),
PrevCount: int64(count.prevCount),
SubId: count.subId,
},
addEvent(count.subId, event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfSubscriptionCounters{
SubscriptionCounters: &pb.EventObjectSubscriptionCounters{
Total: int64(count.total),
NextCount: int64(count.nextCount),
PrevCount: int64(count.prevCount),
SubId: count.subId,
},
})
},
))
}
// apply to cache
@ -144,15 +142,15 @@ func (ctx *opCtx) apply() {
}
for _, opGroup := range ctx.groups {
addEvent(opGroup.subId, &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionGroups{
addEvent(opGroup.subId, event.NewMessage(ctx.spaceId,
&pb.EventMessageValueOfSubscriptionGroups{
SubscriptionGroups: &pb.EventObjectSubscriptionGroups{
SubId: opGroup.subId,
Group: opGroup.group,
Remove: opGroup.remove,
},
},
})
))
}
}
@ -201,7 +199,7 @@ func (ctx *opCtx) addDetailsEvents(prev, curr *entry, info struct {
subIdsToSendSetDetails = slice.Difference(info.subIds, subIdsToSendAmendDetails)
if len(subIdsToSendAmendDetails) != 0 {
diff := domain.StructDiff(prev.data, curr.data)
msgs = append(msgs, state.StructDiffIntoEventsWithSubIds(info.id, diff, info.keys, subIdsToSendAmendDetails)...)
msgs = append(msgs, state.StructDiffIntoEventsWithSubIds(ctx.spaceId, info.id, diff, info.keys, subIdsToSendAmendDetails)...)
}
if len(subIdsToSendSetDetails) != 0 {
msgs = ctx.appendObjectDetailsSetMessage(msgs, curr, subIdsToSendSetDetails, info.keys)
@ -213,15 +211,14 @@ func (ctx *opCtx) addDetailsEvents(prev, curr *entry, info struct {
}
func (ctx *opCtx) appendObjectDetailsSetMessage(msgs []*pb.EventMessage, curr *entry, subIds []string, keys []domain.RelationKey) []*pb.EventMessage {
msgs = append(msgs, &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: curr.id,
Details: curr.data.CopyOnlyKeys(keys...).ToProto(),
SubIds: subIds,
},
msgs = append(msgs, event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: curr.id,
Details: curr.data.CopyOnlyKeys(keys...).ToProto(),
SubIds: subIds,
},
})
},
))
return msgs
}
@ -241,29 +238,27 @@ func (ctx *opCtx) groupEventsDetailsSet(v *pb.EventObjectDetailsSet) {
defaultSubIds := v.SubIds[:0]
for _, subId := range v.SubIds {
if _, ok := ctx.outputs[subId]; ok {
ctx.outputs[subId] = append(ctx.outputs[subId], &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: v.Id,
Details: v.Details,
SubIds: []string{subId},
},
ctx.outputs[subId] = append(ctx.outputs[subId], event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: v.Id,
Details: v.Details,
SubIds: []string{subId},
},
})
},
))
} else {
defaultSubIds = append(defaultSubIds, subId)
}
}
if len(defaultSubIds) > 0 {
ctx.outputs[defaultOutput] = append(ctx.outputs[defaultOutput], &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: v.Id,
Details: v.Details,
SubIds: defaultSubIds,
},
ctx.outputs[defaultOutput] = append(ctx.outputs[defaultOutput], event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: v.Id,
Details: v.Details,
SubIds: defaultSubIds,
},
})
},
))
}
}
@ -271,29 +266,27 @@ func (ctx *opCtx) groupEventsDetailsUnset(v *pb.EventObjectDetailsUnset) {
defaultSubIds := v.SubIds[:0]
for _, subId := range v.SubIds {
if _, ok := ctx.outputs[subId]; ok {
ctx.outputs[subId] = append(ctx.outputs[subId], &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsUnset{
ObjectDetailsUnset: &pb.EventObjectDetailsUnset{
Id: v.Id,
Keys: v.Keys,
SubIds: []string{subId},
},
ctx.outputs[subId] = append(ctx.outputs[subId], event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfObjectDetailsUnset{
ObjectDetailsUnset: &pb.EventObjectDetailsUnset{
Id: v.Id,
Keys: v.Keys,
SubIds: []string{subId},
},
})
},
))
} else {
defaultSubIds = append(defaultSubIds, subId)
}
}
if len(defaultSubIds) > 0 {
ctx.outputs[defaultOutput] = append(ctx.outputs[defaultOutput], &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsUnset{
ObjectDetailsUnset: &pb.EventObjectDetailsUnset{
Id: v.Id,
Keys: v.Keys,
SubIds: defaultSubIds,
},
ctx.outputs[defaultOutput] = append(ctx.outputs[defaultOutput], event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfObjectDetailsUnset{
ObjectDetailsUnset: &pb.EventObjectDetailsUnset{
Id: v.Id,
Keys: v.Keys,
SubIds: defaultSubIds,
},
})
},
))
}
}
@ -301,29 +294,27 @@ func (ctx *opCtx) groupEventsDetailsAmend(v *pb.EventObjectDetailsAmend) {
defaultSubIds := v.SubIds[:0]
for _, subId := range v.SubIds {
if _, ok := ctx.outputs[subId]; ok {
ctx.outputs[subId] = append(ctx.outputs[subId], &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: v.Id,
Details: v.Details,
SubIds: []string{subId},
},
ctx.outputs[subId] = append(ctx.outputs[subId], event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: v.Id,
Details: v.Details,
SubIds: []string{subId},
},
})
},
))
} else {
defaultSubIds = append(defaultSubIds, subId)
}
}
if len(defaultSubIds) > 0 {
ctx.outputs[defaultOutput] = append(ctx.outputs[defaultOutput], &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: v.Id,
Details: v.Details,
SubIds: defaultSubIds,
},
ctx.outputs[defaultOutput] = append(ctx.outputs[defaultOutput], event.NewMessage(ctx.spaceId, &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: v.Id,
Details: v.Details,
SubIds: defaultSubIds,
},
})
},
))
}
}

View file

@ -84,6 +84,9 @@ func (s *crossSpaceSubscription) run() {
}
func (s *crossSpaceSubscription) patchEvent(msg *pb.EventMessage) {
// Remove spaceId as it's the cross space subscription
msg.SpaceId = ""
matcher := subscriptionservice.EventMatcher{
OnAdd: func(add *pb.EventObjectSubscriptionAdd) {
add.SubId = s.subId
@ -171,28 +174,26 @@ func (s *crossSpaceSubscription) removeSpace(spaceId string) error {
return err
}
for _, id := range ids {
err = s.queue.Add(s.ctx, &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionRemove{
SubscriptionRemove: &pb.EventObjectSubscriptionRemove{
SubId: s.subId,
Id: id,
},
err = s.queue.Add(s.ctx, event.NewMessage("", &pb.EventMessageValueOfSubscriptionRemove{
SubscriptionRemove: &pb.EventObjectSubscriptionRemove{
SubId: s.subId,
Id: id,
},
})
},
))
if err != nil {
return fmt.Errorf("send remove event to queue: %w", err)
}
}
total := s.removeTotalCount(subId)
err = s.queue.Add(s.ctx, &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionCounters{
SubscriptionCounters: &pb.EventObjectSubscriptionCounters{
SubId: subId,
Total: total,
},
err = s.queue.Add(s.ctx, event.NewMessage("", &pb.EventMessageValueOfSubscriptionCounters{
SubscriptionCounters: &pb.EventObjectSubscriptionCounters{
SubId: subId,
Total: total,
},
})
},
))
if err != nil {
return fmt.Errorf("send counters event to queue: %w", err)
}

View file

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/core/event/mock_event"
"github.com/anyproto/anytype-heart/core/kanban/mock_kanban"
@ -331,65 +332,55 @@ func TestUnsubscribe(t *testing.T) {
}
func makeDetailsSetEvent(subId string, details *types.Struct) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: pbtypes.GetString(details, bundle.RelationKeyId.String()),
SubIds: []string{
subId,
},
Details: details,
return event.NewMessage("", &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: pbtypes.GetString(details, bundle.RelationKeyId.String()),
SubIds: []string{
subId,
},
Details: details,
},
}
})
}
func makeDetailsAmendEvent(subId string, id string, details []*pb.EventObjectDetailsAmendKeyValue) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: id,
SubIds: []string{
subId,
},
Details: details,
return event.NewMessage("", &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: id,
SubIds: []string{
subId,
},
Details: details,
},
}
})
}
func makeAddEvent(subId string, id string) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionAdd{
SubscriptionAdd: &pb.EventObjectSubscriptionAdd{
SubId: subId,
Id: id,
AfterId: "",
},
return event.NewMessage("", &pb.EventMessageValueOfSubscriptionAdd{
SubscriptionAdd: &pb.EventObjectSubscriptionAdd{
SubId: subId,
Id: id,
AfterId: "",
},
}
})
}
func makeCountersEvent(subId string, total int) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionCounters{
SubscriptionCounters: &pb.EventObjectSubscriptionCounters{
SubId: subId,
Total: int64(total),
},
return event.NewMessage("", &pb.EventMessageValueOfSubscriptionCounters{
SubscriptionCounters: &pb.EventObjectSubscriptionCounters{
SubId: subId,
Total: int64(total),
},
}
})
}
func makeRemoveEvent(subId string, id string) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionRemove{
SubscriptionRemove: &pb.EventObjectSubscriptionRemove{
SubId: subId,
Id: id,
},
return event.NewMessage("", &pb.EventMessageValueOfSubscriptionRemove{
SubscriptionRemove: &pb.EventObjectSubscriptionRemove{
SubId: subId,
Id: id,
},
}
})
}
type dummyCollectionService struct{}

View file

@ -25,7 +25,7 @@ type dependencyService struct {
func (ds *dependencyService) makeSubscriptionByEntries(subId string, spaceId string, allEntries, activeEntries []*entry, keys, depKeys []domain.RelationKey, filterDepIds []string) *simpleSub {
depSub := ds.s.newSimpleSub(subId, spaceId, keys, true)
depSub.forceIds = filterDepIds
depEntries := ds.depEntriesByEntries(&opCtx{entries: allEntries}, ds.depIdsByEntries(activeEntries, depKeys, depSub.forceIds))
depEntries := ds.depEntriesByEntries(&opCtx{entries: allEntries, spaceId: spaceId}, ds.depIdsByEntries(activeEntries, depKeys, depSub.forceIds))
depSub.init(depEntries)
return depSub
}

View file

@ -9,6 +9,7 @@ import (
mb2 "github.com/cheggaaa/mb/v3"
"github.com/stretchr/testify/require"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
@ -17,10 +18,10 @@ import (
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
)
func wrapToEventMessages(vals []pb.IsEventMessageValue) []*pb.EventMessage {
func wrapToEventMessages(spaceId string, vals []pb.IsEventMessageValue) []*pb.EventMessage {
msgs := make([]*pb.EventMessage, len(vals))
for i, v := range vals {
msgs[i] = &pb.EventMessage{Value: v}
msgs[i] = &pb.EventMessage{SpaceId: spaceId, Value: v}
}
return msgs
}
@ -71,7 +72,7 @@ func TestInternalSubscriptionSingle(t *testing.T) {
msgs, err := resp.Output.NewCond().WithMin(len(want)).Wait(ctx)
require.NoError(t, err)
require.Equal(t, wrapToEventMessages(want), msgs)
require.Equal(t, wrapToEventMessages(testSpaceId, want), msgs)
})
t.Run("amend details related to filter -- remove from subscription", func(t *testing.T) {
@ -100,14 +101,14 @@ func TestInternalSubscriptionSingle(t *testing.T) {
msgs, err := resp.Output.NewCond().WithMin(len(want)).Wait(ctx)
require.NoError(t, err)
require.Equal(t, wrapToEventMessages(want), msgs)
require.Equal(t, wrapToEventMessages(testSpaceId, want), msgs)
})
t.Run("unsubscribe", func(t *testing.T) {
err = fx.Unsubscribe("test")
require.NoError(t, err)
err = resp.Output.Add(context.Background(), &pb.EventMessage{})
err = resp.Output.Add(context.Background(), event.NewMessage("", nil))
require.True(t, errors.Is(err, mb2.ErrClosed))
})
@ -206,7 +207,7 @@ func TestInternalSubscriptionMultiple(t *testing.T) {
msgs, err := resp1.Output.NewCond().WithMin(len(want)).Wait(ctx)
require.NoError(t, err)
require.Equal(t, wrapToEventMessages(want), msgs)
require.Equal(t, wrapToEventMessages(testSpaceId, want), msgs)
want = givenMessagesForFirstObject("client1", "client2")
fx.waitEvents(t, want...)
@ -238,7 +239,7 @@ func TestInternalSubscriptionMultiple(t *testing.T) {
msgs, err := resp1.Output.NewCond().WithMin(len(want)).Wait(ctx)
require.NoError(t, err)
require.Equal(t, wrapToEventMessages(want), msgs)
require.Equal(t, wrapToEventMessages(testSpaceId, want), msgs)
want = givenMessagesForSecondObject("client1", "client2")
fx.waitEvents(t, want...)
@ -260,12 +261,12 @@ func TestInternalSubscriptionMultiple(t *testing.T) {
want := givenMessagesForThirdObject(2, "id1", "internal1")
msgs, err := resp1.Output.NewCond().WithMin(len(want)).Wait(ctx)
require.NoError(t, err)
require.Equal(t, wrapToEventMessages(want), msgs)
require.Equal(t, wrapToEventMessages(testSpaceId, want), msgs)
want = givenMessagesForThirdObject(1, "", "internal2")
msgs, err = resp4.Output.NewCond().WithMin(len(want)).Wait(ctx)
require.NoError(t, err)
require.Equal(t, wrapToEventMessages(want), msgs)
require.Equal(t, wrapToEventMessages(testSpaceId, want), msgs)
want = givenMessagesForThirdObject(2, "id1", "client1", "client2")
fx.waitEvents(t, want...)
@ -329,7 +330,7 @@ func TestInternalSubCustomQueue(t *testing.T) {
msgs, err := queue.NewCond().WithMin(len(want)).Wait(ctx)
require.NoError(t, err)
require.Equal(t, wrapToEventMessages(want), msgs)
require.Equal(t, wrapToEventMessages(testSpaceId, want), msgs)
}
func TestInternalSubAsyncInit(t *testing.T) {
@ -388,7 +389,7 @@ func TestInternalSubAsyncInit(t *testing.T) {
msgs, err := resp.Output.NewCond().WithMin(len(want)).Wait(ctx)
require.NoError(t, err)
require.Equal(t, wrapToEventMessages(want), msgs)
require.Equal(t, wrapToEventMessages(testSpaceId, want), msgs)
}
func givenMessagesForFirstObject(subIds ...string) []pb.IsEventMessageValue {

View file

@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/core/subscription"
"github.com/anyproto/anytype-heart/core/subscription/mock_subscription"
"github.com/anyproto/anytype-heart/pb"
@ -18,63 +19,53 @@ import (
)
func makeSubscriptionAdd(id string) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionAdd{
SubscriptionAdd: &pb.EventObjectSubscriptionAdd{
Id: id,
},
return event.NewMessage("", &pb.EventMessageValueOfSubscriptionAdd{
SubscriptionAdd: &pb.EventObjectSubscriptionAdd{
Id: id,
},
}
})
}
func makeSubscriptionRemove(id string) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfSubscriptionRemove{
SubscriptionRemove: &pb.EventObjectSubscriptionRemove{
Id: id,
},
return event.NewMessage("", &pb.EventMessageValueOfSubscriptionRemove{
SubscriptionRemove: &pb.EventObjectSubscriptionRemove{
Id: id,
},
}
})
}
func makeDetailsSet(id string) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: id,
Details: domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
"key1": domain.String("value1"),
}).ToProto(),
},
return event.NewMessage("", &pb.EventMessageValueOfObjectDetailsSet{
ObjectDetailsSet: &pb.EventObjectDetailsSet{
Id: id,
Details: domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
"key1": domain.String("value1"),
}).ToProto(),
},
}
})
}
func makeDetailsUnset(id string) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsUnset{
ObjectDetailsUnset: &pb.EventObjectDetailsUnset{
Id: id,
Keys: []string{"key1", "key2"},
},
return event.NewMessage("", &pb.EventMessageValueOfObjectDetailsUnset{
ObjectDetailsUnset: &pb.EventObjectDetailsUnset{
Id: id,
Keys: []string{"key1", "key2"},
},
}
})
}
func makeDetailsAmend(id string) *pb.EventMessage {
return &pb.EventMessage{
Value: &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: id,
Details: []*pb.EventObjectDetailsAmendKeyValue{
{
Key: "key3",
Value: pbtypes.String("value3"),
},
return event.NewMessage("", &pb.EventMessageValueOfObjectDetailsAmend{
ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
Id: id,
Details: []*pb.EventObjectDetailsAmendKeyValue{
{
Key: "key3",
Value: pbtypes.String("value3"),
},
},
},
}
})
}
func makeStructs(ids []string) []*domain.Details {

View file

@ -275,7 +275,7 @@ func (s *service) getSpaceSubscriptions(spaceId string) (*spaceSubscriptions, er
kanban: s.kanban,
collectionService: s.collectionService,
eventSender: s.eventSender,
ctxBuf: &opCtx{c: cache},
ctxBuf: &opCtx{spaceId: spaceId, c: cache},
arenaPool: s.arenaPool,
}
spaceSubs.ds = newDependencyService(spaceSubs)

View file

@ -145,13 +145,9 @@ func (s *spaceSyncStatus) sendEventToSession(spaceId, token string) {
compatibility: s.nodeConf.NetworkCompatibilityStatus(),
objectsSyncingCount: s.getObjectSyncingObjectsCount(spaceId, s.getMissingIds(spaceId)),
}
s.eventSender.SendToSession(token, &pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: s.makeSyncEvent(spaceId, params),
},
}},
})
s.eventSender.SendToSession(token, event.NewEventSingleMessage(spaceId, &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: s.makeSyncEvent(spaceId, params),
}))
}
func (s *spaceSyncStatus) sendStartEvent(spaceIds []string) {
@ -161,17 +157,13 @@ func (s *spaceSyncStatus) sendStartEvent(spaceIds []string) {
}
func (s *spaceSyncStatus) sendLocalOnlyEvent(spaceId string) {
s.broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: spaceId,
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
},
}},
})
s.broadcast(event.NewEventSingleMessage(spaceId, &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: spaceId,
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
}))
}
func eventsEqual(a, b pb.EventSpaceSyncStatusUpdate) bool {
@ -195,17 +187,13 @@ func (s *spaceSyncStatus) broadcast(event *pb.Event) {
}
func (s *spaceSyncStatus) sendLocalOnlyEventToSession(spaceId, token string) {
s.eventSender.SendToSession(token, &pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: spaceId,
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
},
}},
})
s.eventSender.SendToSession(token, event.NewEventSingleMessage(spaceId, &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: spaceId,
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
}))
}
func (s *spaceSyncStatus) Refresh(spaceId string) {
@ -244,13 +232,9 @@ func (s *spaceSyncStatus) updateSpaceSyncStatus(spaceId string) {
compatibility: s.nodeConf.NetworkCompatibilityStatus(),
objectsSyncingCount: s.getObjectSyncingObjectsCount(spaceId, missingObjects),
}
s.broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: s.makeSyncEvent(spaceId, params),
},
}},
})
s.broadcast(event.NewEventSingleMessage(spaceId, &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: s.makeSyncEvent(spaceId, params),
}))
}
func (s *spaceSyncStatus) Close(ctx context.Context) (err error) {

View file

@ -147,17 +147,13 @@ func Test(t *testing.T) {
LocalUsageBytes: 0,
}, nil)
fx.nodeConf.EXPECT().NetworkCompatibilityStatus().Return(nodeconf.NetworkCompatibilityStatusOk)
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_Synced,
Network: pb.EventSpace_Anytype,
},
},
}},
})
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_Synced,
Network: pb.EventSpace_Anytype,
},
}))
})
defer fx.ctrl.Finish()
})
@ -176,18 +172,14 @@ func Test(t *testing.T) {
LocalUsageBytes: 0,
}, nil)
fx.nodeConf.EXPECT().NetworkCompatibilityStatus().Return(nodeconf.NetworkCompatibilityStatusOk)
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Syncing,
Network: pb.EventSpace_Anytype,
},
},
}},
})
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Syncing,
Network: pb.EventSpace_Anytype,
},
}))
})
defer fx.ctrl.Finish()
})
@ -207,18 +199,14 @@ func Test(t *testing.T) {
LocalUsageBytes: 0,
}, nil)
fx.nodeConf.EXPECT().NetworkCompatibilityStatus().AnyTimes().Return(nodeconf.NetworkCompatibilityStatusOk)
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Syncing,
Network: pb.EventSpace_Anytype,
},
},
}},
}).Times(1)
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Syncing,
Network: pb.EventSpace_Anytype,
},
})).Times(1)
})
fx.Refresh("spaceId")
time.Sleep(100 * time.Millisecond)
@ -230,17 +218,13 @@ func Test(t *testing.T) {
fx.objectStore.AddObjects(t, "spaceId", objs)
fx.networkConfig.EXPECT().GetNetworkMode().Return(pb.RpcAccount_LocalOnly)
fx.spaceIdGetter.EXPECT().AllSpaceIds().Return([]string{"spaceId"})
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
},
}},
})
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
}))
})
defer fx.ctrl.Finish()
})
@ -259,19 +243,15 @@ func Test(t *testing.T) {
LocalUsageBytes: 0,
}, nil)
fx.nodeConf.EXPECT().NetworkCompatibilityStatus().Return(nodeconf.NetworkCompatibilityStatusOk)
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Error,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_StorageLimitExceed,
},
},
}},
})
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Error,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_StorageLimitExceed,
},
}))
})
defer fx.ctrl.Finish()
})
@ -290,19 +270,15 @@ func Test(t *testing.T) {
LocalUsageBytes: 0,
}, nil)
fx.nodeConf.EXPECT().NetworkCompatibilityStatus().Return(nodeconf.NetworkCompatibilityStatusOk)
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_NetworkError,
},
},
}},
})
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_NetworkError,
},
}))
})
defer fx.ctrl.Finish()
})
@ -321,19 +297,15 @@ func Test(t *testing.T) {
LocalUsageBytes: 0,
}, nil)
fx.nodeConf.EXPECT().NetworkCompatibilityStatus().Return(nodeconf.NetworkCompatibilityStatusIncompatible)
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Error,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_IncompatibleVersion,
},
},
}},
})
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Error,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_IncompatibleVersion,
},
}))
})
defer fx.ctrl.Finish()
})
@ -353,33 +325,25 @@ func Test(t *testing.T) {
LocalUsageBytes: 0,
}, nil)
fx.nodeConf.EXPECT().NetworkCompatibilityStatus().AnyTimes().Return(nodeconf.NetworkCompatibilityStatusOk)
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Syncing,
Network: pb.EventSpace_Anytype,
},
},
}},
})
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Syncing,
Network: pb.EventSpace_Anytype,
},
}))
})
fx.UpdateMissingIds("spaceId", []string{"missingId"})
fx.Refresh("spaceId")
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 111,
Status: pb.EventSpace_Syncing,
Network: pb.EventSpace_Anytype,
},
},
}},
}).Times(1)
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 111,
Status: pb.EventSpace_Syncing,
Network: pb.EventSpace_Anytype,
},
})).Times(1)
time.Sleep(100 * time.Millisecond)
defer fx.ctrl.Finish()
})
@ -396,17 +360,13 @@ func Test(t *testing.T) {
LocalUsageBytes: 0,
}, nil)
fx.nodeConf.EXPECT().NetworkCompatibilityStatus().Return(nodeconf.NetworkCompatibilityStatusNeedsUpdate)
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_NetworkNeedsUpdate,
Network: pb.EventSpace_Anytype,
},
},
}},
})
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_NetworkNeedsUpdate,
Network: pb.EventSpace_Anytype,
},
}))
})
defer fx.ctrl.Finish()
})
@ -425,33 +385,25 @@ func Test(t *testing.T) {
LocalUsageBytes: 0,
}, nil)
fx.nodeConf.EXPECT().NetworkCompatibilityStatus().AnyTimes().Return(nodeconf.NetworkCompatibilityStatusIncompatible)
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Error,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_IncompatibleVersion,
},
},
}},
})
})
fx.eventSender.EXPECT().SendToSession("sessionId", &pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Error,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_IncompatibleVersion,
},
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Error,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_IncompatibleVersion,
},
}},
}))
})
fx.eventSender.EXPECT().SendToSession("sessionId", event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
SyncingObjectsCounter: 110,
Status: pb.EventSpace_Error,
Network: pb.EventSpace_Anytype,
Error: pb.EventSpace_IncompatibleVersion,
},
}))
fx.session.RunHooks(mockSessionContext{"sessionId"})
defer fx.ctrl.Finish()
})
@ -461,29 +413,21 @@ func Test(t *testing.T) {
fx.objectStore.AddObjects(t, "spaceId", objs)
fx.networkConfig.EXPECT().GetNetworkMode().Return(pb.RpcAccount_LocalOnly)
fx.spaceIdGetter.EXPECT().AllSpaceIds().Return([]string{"spaceId"})
fx.eventSender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
},
}},
})
})
fx.eventSender.EXPECT().SendToSession("sessionId", &pb.Event{
Messages: []*pb.EventMessage{{
Value: &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
fx.eventSender.EXPECT().Broadcast(event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
}},
}))
})
fx.eventSender.EXPECT().SendToSession("sessionId", event.NewEventSingleMessage("spaceId", &pb.EventMessageValueOfSpaceSyncStatusUpdate{
SpaceSyncStatusUpdate: &pb.EventSpaceSyncStatusUpdate{
Id: "spaceId",
Status: pb.EventSpace_Offline,
Network: pb.EventSpace_LocalOnly,
},
}))
fx.session.RunHooks(mockSessionContext{"sessionId"})
defer fx.ctrl.Finish()
})

View file

@ -26805,6 +26805,7 @@ Precondition: user A opened a block
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| spaceId | [string](#string) | | |
| accountShow | [Event.Account.Show](#anytype-Event-Account-Show) | | |
| accountDetails | [Event.Account.Details](#anytype-Event-Account-Details) | | |
| accountConfigUpdate | [Event.Account.Config.Update](#anytype-Event-Account-Config-Update) | | |

8
go.mod
View file

@ -8,7 +8,7 @@ require (
github.com/VividCortex/ewma v1.2.0
github.com/adrium/goheif v0.0.0-20230113233934-ca402e77a786
github.com/anyproto/any-store v0.1.3
github.com/anyproto/any-sync v0.5.22
github.com/anyproto/any-sync v0.5.23
github.com/anyproto/go-chash v0.1.0
github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438
github.com/anyproto/go-slip10 v1.0.0
@ -29,7 +29,7 @@ require (
github.com/dsoprea/go-jpeg-image-structure/v2 v2.0.0-20221012074422-4f3f7e934102
github.com/ethereum/go-ethereum v1.13.15
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8
github.com/go-chi/chi/v5 v5.1.0
github.com/go-chi/chi/v5 v5.2.0
github.com/go-shiori/go-readability v0.0.0-20241012063810-92284fa8a71f
github.com/goccy/go-graphviz v0.2.9
github.com/gogo/protobuf v1.3.2
@ -105,7 +105,7 @@ require (
golang.org/x/net v0.32.0
golang.org/x/oauth2 v0.24.0
golang.org/x/text v0.21.0
google.golang.org/grpc v1.68.1
google.golang.org/grpc v1.69.0
gopkg.in/Graylog2/go-gelf.v2 v2.0.0-20180125164251-1832d8546a9f
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
@ -246,7 +246,7 @@ require (
go.opentelemetry.io/otel v1.32.0 // indirect
go.opentelemetry.io/otel/metric v1.32.0 // indirect
go.opentelemetry.io/otel/trace v1.32.0 // indirect
golang.org/x/crypto v0.30.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect

20
go.sum
View file

@ -78,8 +78,8 @@ github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsVi
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/anyproto/any-store v0.1.3 h1:onWLP8tuWiUvYOyV3DoRODscTxAiGEjwQPm+NMxeq3M=
github.com/anyproto/any-store v0.1.3/go.mod h1:6/0OUKgSMWF/vYGoGYzQOl2CII5OdiuXbQlGDXYcNYc=
github.com/anyproto/any-sync v0.5.22 h1:mfAVfmcP8o/9ZIGS59YECiVCi9UZI9u3W0hK+vH7/z8=
github.com/anyproto/any-sync v0.5.22/go.mod h1:ANfWnDHP9t4RHelUhX99YmaDvmzcaeIwR9grkKIkfeM=
github.com/anyproto/any-sync v0.5.23 h1:NEWFKz35KgixIq8HsAqXIIFS0Yz+1VjSDimVg8xaqPA=
github.com/anyproto/any-sync v0.5.23/go.mod h1:ANfWnDHP9t4RHelUhX99YmaDvmzcaeIwR9grkKIkfeM=
github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580 h1:Ba80IlCCxkZ9H1GF+7vFu/TSpPvbpDCxXJ5ogc4euYc=
github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580/go.mod h1:T/uWAYxrXdaXw64ihI++9RMbKTCpKd/yE9+saARew7k=
github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY=
@ -280,8 +280,8 @@ github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.2.0 h1:Aj1EtB0qR2Rdo2dG4O94RIU35w2lvQSj6BRA4+qwFL0=
github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
@ -1047,6 +1047,10 @@ go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@ -1091,8 +1095,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -1496,8 +1500,8 @@ google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
google.golang.org/grpc v1.69.0 h1:quSiOM1GJPmPH5XtU+BCoVXcDVJJAzNcoyfC2cCjGkI=
google.golang.org/grpc v1.69.0/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

View file

@ -326,6 +326,7 @@ func (m *Event) GetTraceId() string {
}
type EventMessage struct {
SpaceId string `protobuf:"bytes,132,opt,name=spaceId,proto3" json:"spaceId,omitempty"`
// Types that are valid to be assigned to Value:
// *EventMessageValueOfAccountShow
// *EventMessageValueOfAccountDetails
@ -748,6 +749,13 @@ func (m *EventMessage) GetValue() IsEventMessageValue {
return nil
}
func (m *EventMessage) GetSpaceId() string {
if m != nil {
return m.SpaceId
}
return ""
}
func (m *EventMessage) GetAccountShow() *EventAccountShow {
if x, ok := m.GetValue().(*EventMessageValueOfAccountShow); ok {
return x.AccountShow
@ -12260,391 +12268,392 @@ func init() {
func init() { proto.RegisterFile("pb/protos/events.proto", fileDescriptor_a966342d378ae5f5) }
var fileDescriptor_a966342d378ae5f5 = []byte{
// 6140 bytes of a gzipped FileDescriptorProto
// 6151 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5c, 0x4b, 0x8c, 0x1c, 0xc7,
0x79, 0x9e, 0xf7, 0xe3, 0x5f, 0x72, 0x39, 0x2c, 0x52, 0x54, 0xab, 0x45, 0x51, 0xd4, 0x8a, 0xa4,
0x68, 0x89, 0x1a, 0x52, 0x24, 0x45, 0xca, 0xb4, 0xf8, 0xd8, 0x17, 0x35, 0xc3, 0xc7, 0x72, 0x5d,
0x4b, 0xd2, 0xb2, 0x6c, 0x04, 0xee, 0x9d, 0xae, 0x9d, 0x6d, 0x73, 0xb6, 0x7b, 0xdc, 0xdd, 0xbb,
0xe4, 0xda, 0x8e, 0xe3, 0xd8, 0x09, 0x82, 0x00, 0x09, 0x92, 0x43, 0x90, 0x04, 0xb9, 0x04, 0x30,
0x12, 0x20, 0x87, 0x20, 0x48, 0x90, 0x4b, 0x72, 0x31, 0x02, 0x04, 0x46, 0x9e, 0x07, 0xfb, 0x96,
0x4b, 0x60, 0x43, 0xbe, 0xe4, 0x90, 0x1c, 0x9c, 0x00, 0x41, 0x4e, 0x41, 0x50, 0x8f, 0xae, 0xae,
0xea, 0xc7, 0xf4, 0x8c, 0x25, 0xe7, 0x81, 0xf8, 0x34, 0x53, 0x55, 0xff, 0xff, 0xd5, 0xe3, 0x7f,
0x54, 0xd5, 0x5f, 0xd5, 0x05, 0xc7, 0xc6, 0x9b, 0xe7, 0xc7, 0xbe, 0x17, 0x7a, 0xc1, 0x79, 0xb2,
0x47, 0xdc, 0x30, 0xe8, 0xb2, 0x14, 0x6a, 0x5a, 0xee, 0x7e, 0xb8, 0x3f, 0x26, 0xe6, 0xa9, 0xf1,
0x93, 0xe1, 0xf9, 0x91, 0xb3, 0x79, 0x7e, 0xbc, 0x79, 0x7e, 0xc7, 0xb3, 0xc9, 0x28, 0x22, 0x67,
0x09, 0x41, 0x6e, 0x1e, 0x1f, 0x7a, 0xde, 0x70, 0x44, 0x78, 0xd9, 0xe6, 0xee, 0xd6, 0xf9, 0x20,
0xf4, 0x77, 0x07, 0x21, 0x2f, 0x5d, 0xf8, 0xd6, 0xb7, 0xcb, 0x50, 0x5f, 0xa5, 0xf0, 0xe8, 0x22,
0xb4, 0x76, 0x48, 0x10, 0x58, 0x43, 0x12, 0x18, 0xe5, 0x93, 0xd5, 0xb3, 0x73, 0x17, 0x8f, 0x75,
0x45, 0x55, 0x5d, 0x46, 0xd1, 0xbd, 0xcf, 0x8b, 0xb1, 0xa4, 0x43, 0xc7, 0xa1, 0x3d, 0xf0, 0xdc,
0x90, 0x3c, 0x0b, 0xfb, 0xb6, 0x51, 0x39, 0x59, 0x3e, 0xdb, 0xc6, 0x71, 0x06, 0xba, 0x0c, 0x6d,
0xc7, 0x75, 0x42, 0xc7, 0x0a, 0x3d, 0xdf, 0xa8, 0x9e, 0x2c, 0x6b, 0x90, 0xac, 0x91, 0xdd, 0xc5,
0xc1, 0xc0, 0xdb, 0x75, 0x43, 0x1c, 0x13, 0x22, 0x03, 0x9a, 0xa1, 0x6f, 0x0d, 0x48, 0xdf, 0x36,
0x6a, 0x0c, 0x31, 0x4a, 0x9a, 0xdf, 0xb9, 0x00, 0x4d, 0xd1, 0x06, 0x74, 0x13, 0xe6, 0x2c, 0xce,
0xbb, 0xb1, 0xed, 0x3d, 0x35, 0xca, 0x0c, 0xfd, 0xc5, 0x44, 0x83, 0x05, 0x7a, 0x97, 0x92, 0xf4,
0x4a, 0x58, 0xe5, 0x40, 0x7d, 0x98, 0x17, 0xc9, 0x15, 0x12, 0x5a, 0xce, 0x28, 0x30, 0xfe, 0x86,
0x83, 0x9c, 0xc8, 0x01, 0x11, 0x64, 0xbd, 0x12, 0x4e, 0x30, 0xa2, 0xcf, 0xc2, 0x11, 0x91, 0xb3,
0xec, 0xb9, 0x5b, 0xce, 0xf0, 0xd1, 0xd8, 0xb6, 0x42, 0x62, 0xfc, 0x2d, 0xc7, 0x3b, 0x95, 0x83,
0xc7, 0x69, 0xbb, 0x9c, 0xb8, 0x57, 0xc2, 0x59, 0x18, 0xe8, 0x36, 0x1c, 0x14, 0xd9, 0x02, 0xf4,
0xef, 0x38, 0xe8, 0x4b, 0x39, 0xa0, 0x12, 0x4d, 0x67, 0x43, 0x9f, 0x83, 0xa3, 0x22, 0xe3, 0x9e,
0xe3, 0x3e, 0x59, 0xde, 0xb6, 0x46, 0x23, 0xe2, 0x0e, 0x89, 0xf1, 0xf7, 0x93, 0xdb, 0xa8, 0x11,
0xf7, 0x4a, 0x38, 0x13, 0x04, 0x3d, 0x80, 0x8e, 0xb7, 0xf9, 0x45, 0x32, 0x88, 0x06, 0x64, 0x83,
0x84, 0x46, 0x87, 0xe1, 0xbe, 0x92, 0xc0, 0x7d, 0xc0, 0xc8, 0xa2, 0xa1, 0xec, 0x6e, 0x90, 0xb0,
0x57, 0xc2, 0x29, 0x66, 0xf4, 0x08, 0x90, 0x96, 0xb7, 0xb8, 0x43, 0x5c, 0xdb, 0xb8, 0xc8, 0x20,
0x5f, 0x9d, 0x0c, 0xc9, 0x48, 0x7b, 0x25, 0x9c, 0x01, 0x90, 0x82, 0x7d, 0xe4, 0x06, 0x24, 0x34,
0x2e, 0x4d, 0x03, 0xcb, 0x48, 0x53, 0xb0, 0x2c, 0x97, 0x8e, 0x2d, 0xcf, 0xc5, 0x64, 0x64, 0x85,
0x8e, 0xe7, 0x8a, 0xf6, 0x5e, 0x66, 0xc0, 0xa7, 0xb3, 0x81, 0x25, 0xad, 0x6c, 0x71, 0x26, 0x08,
0xfa, 0x19, 0x78, 0x2e, 0x91, 0x8f, 0xc9, 0x8e, 0xb7, 0x47, 0x8c, 0xb7, 0x19, 0xfa, 0x99, 0x22,
0x74, 0x4e, 0xdd, 0x2b, 0xe1, 0x6c, 0x18, 0xb4, 0x04, 0x07, 0xa2, 0x02, 0x06, 0x7b, 0x85, 0xc1,
0x1e, 0xcf, 0x83, 0x15, 0x60, 0x1a, 0x0f, 0xb5, 0x45, 0x9e, 0x5e, 0x1e, 0x79, 0x01, 0x31, 0x16,
0x33, 0x6d, 0x51, 0x40, 0x30, 0x12, 0x6a, 0x8b, 0x0a, 0x87, 0xda, 0xc9, 0x20, 0xf4, 0x9d, 0x01,
0x6b, 0x20, 0xd5, 0xa2, 0xab, 0x93, 0x3b, 0x19, 0x13, 0x0b, 0x55, 0xca, 0x86, 0x41, 0x18, 0x0e,
0x05, 0xbb, 0x9b, 0xc1, 0xc0, 0x77, 0xc6, 0x34, 0x6f, 0xd1, 0xb6, 0x8d, 0x77, 0x27, 0x21, 0x6f,
0x28, 0xc4, 0xdd, 0x45, 0x9b, 0x4a, 0x27, 0x09, 0x80, 0x3e, 0x07, 0x48, 0xcd, 0x12, 0xc3, 0x77,
0x9d, 0xc1, 0x7e, 0x62, 0x0a, 0x58, 0x39, 0x96, 0x19, 0x30, 0xc8, 0x82, 0xa3, 0x6a, 0xee, 0xba,
0x17, 0x38, 0xf4, 0xd7, 0xb8, 0xc1, 0xe0, 0xdf, 0x98, 0x02, 0x3e, 0x62, 0xa1, 0x8a, 0x95, 0x05,
0x95, 0xac, 0x62, 0x99, 0x9a, 0x35, 0xf1, 0x03, 0xe3, 0xe6, 0xd4, 0x55, 0x44, 0x2c, 0xc9, 0x2a,
0xa2, 0xfc, 0xe4, 0x10, 0xbd, 0xe7, 0x7b, 0xbb, 0xe3, 0xc0, 0xb8, 0x35, 0xf5, 0x10, 0x71, 0x86,
0xe4, 0x10, 0xf1, 0x5c, 0x74, 0x05, 0x5a, 0x9b, 0x23, 0x6f, 0xf0, 0x84, 0x0a, 0xb3, 0xc2, 0x20,
0x8d, 0x04, 0xe4, 0x12, 0x2d, 0x16, 0xe2, 0x93, 0xb4, 0x54, 0x59, 0xd9, 0xff, 0x15, 0x32, 0x22,
0x21, 0x11, 0xd3, 0xd2, 0x8b, 0x99, 0xac, 0x9c, 0x84, 0x2a, 0xab, 0xc2, 0x81, 0x56, 0x60, 0x6e,
0xcb, 0x19, 0x91, 0xe0, 0xd1, 0x78, 0xe4, 0x59, 0x7c, 0x8e, 0x9a, 0xbb, 0x78, 0x32, 0x13, 0xe0,
0x76, 0x4c, 0x47, 0x51, 0x14, 0x36, 0x74, 0x03, 0xda, 0x3b, 0x96, 0xff, 0x24, 0xe8, 0xbb, 0x5b,
0x9e, 0x51, 0xcf, 0x9c, 0x78, 0x38, 0xc6, 0xfd, 0x88, 0xaa, 0x57, 0xc2, 0x31, 0x0b, 0x9d, 0xbe,
0x58, 0xa3, 0x36, 0x48, 0x78, 0xdb, 0x21, 0x23, 0x3b, 0x30, 0x1a, 0x0c, 0xe4, 0xe5, 0x4c, 0x90,
0x0d, 0x12, 0x76, 0x39, 0x19, 0x9d, 0xbe, 0x74, 0x46, 0xf4, 0x3e, 0x1c, 0x89, 0x72, 0x96, 0xb7,
0x9d, 0x91, 0xed, 0x13, 0xb7, 0x6f, 0x07, 0x46, 0x33, 0x73, 0x66, 0x88, 0xf1, 0x14, 0x5a, 0x3a,
0x7b, 0x65, 0x40, 0x50, 0xcf, 0x18, 0x65, 0xab, 0x26, 0x69, 0xb4, 0x32, 0x3d, 0x63, 0x0c, 0xad,
0x12, 0x53, 0xed, 0xca, 0x02, 0x41, 0x36, 0x3c, 0x1f, 0xe5, 0x2f, 0x59, 0x83, 0x27, 0x43, 0xdf,
0xdb, 0x75, 0xed, 0x65, 0x6f, 0xe4, 0xf9, 0x46, 0x9b, 0xe1, 0x9f, 0xcd, 0xc5, 0x4f, 0xd0, 0xf7,
0x4a, 0x38, 0x0f, 0x0a, 0x2d, 0xc3, 0x81, 0xa8, 0xe8, 0x21, 0x79, 0x16, 0x1a, 0x90, 0x39, 0xfd,
0xc6, 0xd0, 0x94, 0x88, 0x3a, 0x48, 0x95, 0x49, 0x05, 0xa1, 0x2a, 0x61, 0xcc, 0x15, 0x80, 0x50,
0x22, 0x15, 0x84, 0xa6, 0x55, 0x10, 0x3a, 0xfd, 0x1a, 0x07, 0x0b, 0x40, 0x28, 0x91, 0x0a, 0x42,
0xd3, 0x74, 0xaa, 0x96, 0x3d, 0xf5, 0xbc, 0x27, 0x54, 0x9f, 0x8c, 0xf9, 0xcc, 0xa9, 0x5a, 0x19,
0x2d, 0x41, 0x48, 0xa7, 0xea, 0x24, 0x33, 0x5d, 0xa0, 0x44, 0x79, 0x8b, 0x23, 0x67, 0xe8, 0x1a,
0x87, 0x26, 0xe8, 0x32, 0x45, 0x63, 0x54, 0x74, 0x81, 0xa2, 0xb1, 0xa1, 0x5b, 0xc2, 0x2c, 0x37,
0x48, 0xb8, 0xe2, 0xec, 0x19, 0x87, 0x33, 0xa7, 0xa1, 0x18, 0x65, 0xc5, 0xd9, 0x93, 0x76, 0xc9,
0x59, 0xd4, 0xae, 0x45, 0x93, 0x9c, 0xf1, 0x5c, 0x41, 0xd7, 0x22, 0x42, 0xb5, 0x6b, 0x51, 0x9e,
0xda, 0xb5, 0x7b, 0x56, 0x48, 0x9e, 0x19, 0x2f, 0x14, 0x74, 0x8d, 0x51, 0xa9, 0x5d, 0x63, 0x19,
0x74, 0x76, 0x8b, 0x32, 0x1e, 0x13, 0x3f, 0x74, 0x06, 0xd6, 0x88, 0x0f, 0xd5, 0xa9, 0xcc, 0x39,
0x28, 0xc6, 0xd3, 0xa8, 0xe9, 0xec, 0x96, 0x09, 0xa3, 0x76, 0xfc, 0xa1, 0xb5, 0x39, 0x22, 0xd8,
0x7b, 0x6a, 0x9c, 0x2e, 0xe8, 0x78, 0x44, 0xa8, 0x76, 0x3c, 0xca, 0x53, 0x7d, 0xcb, 0x67, 0x1c,
0x7b, 0x48, 0x42, 0xe3, 0x6c, 0x81, 0x6f, 0xe1, 0x64, 0xaa, 0x6f, 0xe1, 0x39, 0xd2, 0x03, 0xac,
0x58, 0xa1, 0xb5, 0xe7, 0x90, 0xa7, 0x8f, 0x1d, 0xf2, 0x94, 0x4e, 0xec, 0x47, 0x26, 0x78, 0x80,
0x88, 0xb6, 0x2b, 0x88, 0xa5, 0x07, 0x48, 0x80, 0x48, 0x0f, 0xa0, 0xe6, 0x0b, 0xb7, 0x7e, 0x74,
0x82, 0x07, 0xd0, 0xf0, 0xa5, 0x8f, 0xcf, 0x83, 0x42, 0x16, 0x1c, 0x4b, 0x15, 0x3d, 0xf0, 0x6d,
0xe2, 0x1b, 0x2f, 0xb1, 0x4a, 0x5e, 0x2b, 0xae, 0x84, 0x91, 0xf7, 0x4a, 0x38, 0x07, 0x28, 0x55,
0xc5, 0x86, 0xb7, 0xeb, 0x0f, 0x08, 0x1d, 0xa7, 0x57, 0xa7, 0xa9, 0x42, 0x92, 0xa7, 0xaa, 0x90,
0x25, 0x68, 0x0f, 0x5e, 0x92, 0x25, 0xb4, 0x62, 0x36, 0x8b, 0xb2, 0xda, 0xc5, 0xc6, 0xe2, 0x0c,
0xab, 0xa9, 0x3b, 0xb9, 0xa6, 0x24, 0x57, 0xaf, 0x84, 0x27, 0xc3, 0xa2, 0x7d, 0x38, 0xa1, 0x11,
0xf0, 0x79, 0x5e, 0xad, 0xf8, 0x35, 0x56, 0xf1, 0xf9, 0xc9, 0x15, 0xa7, 0xd8, 0x7a, 0x25, 0x5c,
0x00, 0x8c, 0xc6, 0xf0, 0xa2, 0x36, 0x18, 0x91, 0x61, 0x0b, 0x15, 0xf9, 0x2a, 0xab, 0xf7, 0xdc,
0xe4, 0x7a, 0x75, 0x9e, 0x5e, 0x09, 0x4f, 0x82, 0x44, 0x43, 0x30, 0x32, 0x8b, 0xa9, 0x24, 0xbf,
0x92, 0xb9, 0xec, 0xc9, 0xa9, 0x8e, 0xcb, 0x32, 0x17, 0x2c, 0x53, 0xf3, 0xc5, 0x70, 0xfe, 0xec,
0xb4, 0x9a, 0x2f, 0xc7, 0x31, 0x0f, 0x4a, 0x93, 0x1d, 0x2d, 0x7a, 0x68, 0xf9, 0x43, 0x12, 0xf2,
0x81, 0xee, 0xdb, 0xb4, 0x53, 0x5f, 0x9b, 0x46, 0x76, 0x29, 0x36, 0x4d, 0x76, 0x99, 0xc0, 0x28,
0x80, 0xe3, 0x1a, 0x45, 0x3f, 0x58, 0xf6, 0x46, 0x23, 0x32, 0x88, 0x46, 0xf3, 0xe7, 0x58, 0xc5,
0x6f, 0x4e, 0xae, 0x38, 0xc1, 0xd4, 0x2b, 0xe1, 0x89, 0xa0, 0xa9, 0xfe, 0x3e, 0x18, 0xd9, 0x09,
0x9d, 0x31, 0xa6, 0xd2, 0xd5, 0x24, 0x5b, 0xaa, 0xbf, 0x29, 0x8a, 0x94, 0xae, 0x2a, 0x14, 0xb4,
0xbb, 0xcf, 0x4f, 0xa3, 0xab, 0x3a, 0x4f, 0x4a, 0x57, 0xf5, 0x62, 0x3a, 0xbb, 0xed, 0x06, 0xc4,
0x67, 0x18, 0x77, 0x3c, 0xc7, 0x35, 0x5e, 0xce, 0x9c, 0xdd, 0x1e, 0x05, 0xc4, 0x17, 0x15, 0x51,
0x2a, 0x3a, 0xbb, 0x69, 0x6c, 0x1a, 0xce, 0x3d, 0xb2, 0x15, 0x1a, 0x27, 0x8b, 0x70, 0x28, 0x95,
0x86, 0x43, 0x33, 0xe8, 0x4c, 0x21, 0x33, 0x36, 0x08, 0x95, 0x0a, 0xb6, 0xdc, 0x21, 0x31, 0x5e,
0xc9, 0x9c, 0x29, 0x14, 0x38, 0x85, 0x98, 0xce, 0x14, 0x59, 0x20, 0x74, 0xe7, 0x2f, 0xf3, 0xe9,
0x8a, 0x8c, 0x43, 0x2f, 0x64, 0xee, 0xfc, 0x15, 0x68, 0x49, 0x4a, 0xf7, 0x20, 0x69, 0x00, 0xf4,
0x09, 0xa8, 0x8d, 0x1d, 0x77, 0x68, 0xd8, 0x0c, 0xe8, 0x48, 0x02, 0x68, 0xdd, 0x71, 0x87, 0xbd,
0x12, 0x66, 0x24, 0xe8, 0x5d, 0x80, 0xb1, 0xef, 0x0d, 0x48, 0x10, 0xac, 0x91, 0xa7, 0x06, 0x61,
0x0c, 0x66, 0x92, 0x81, 0x13, 0x74, 0xd7, 0x08, 0x9d, 0x97, 0x15, 0x7a, 0xb4, 0x0a, 0x07, 0x45,
0x4a, 0x58, 0xf9, 0x56, 0xe6, 0xe2, 0x2f, 0x02, 0x88, 0xa3, 0x40, 0x1a, 0x17, 0xdd, 0xfb, 0x88,
0x8c, 0x15, 0xcf, 0x25, 0xc6, 0x30, 0x73, 0xef, 0x13, 0x81, 0x50, 0x12, 0xba, 0xc6, 0x52, 0x38,
0xd0, 0x12, 0x1c, 0x08, 0xb7, 0x7d, 0x62, 0xd9, 0x1b, 0xa1, 0x15, 0xee, 0x06, 0x86, 0x9b, 0xb9,
0x4c, 0xe3, 0x85, 0xdd, 0x87, 0x8c, 0x92, 0x2e, 0x41, 0x55, 0x1e, 0xb4, 0x06, 0x1d, 0xba, 0x11,
0xba, 0xe7, 0xec, 0x38, 0x21, 0x26, 0xd6, 0x60, 0x9b, 0xd8, 0x86, 0x97, 0xb9, 0x89, 0xa2, 0xcb,
0xde, 0xae, 0x4a, 0x47, 0x57, 0x2b, 0x49, 0x5e, 0xd4, 0x83, 0x79, 0x9a, 0xb7, 0x31, 0xb6, 0x06,
0xe4, 0x51, 0x60, 0x0d, 0x89, 0x31, 0xce, 0xd4, 0x40, 0x86, 0x16, 0x53, 0xd1, 0xc5, 0x8a, 0xce,
0x17, 0x21, 0xdd, 0xf3, 0x06, 0xd6, 0x88, 0x23, 0x7d, 0x29, 0x1f, 0x29, 0xa6, 0x8a, 0x90, 0xe2,
0x1c, 0xad, 0x8f, 0x7c, 0xec, 0x6d, 0x63, 0xaf, 0xa0, 0x8f, 0x82, 0x4e, 0xeb, 0xa3, 0xc8, 0xa3,
0x78, 0xae, 0x17, 0x3a, 0x5b, 0xce, 0x40, 0xd8, 0xaf, 0x6b, 0x1b, 0x7e, 0x26, 0xde, 0x9a, 0x42,
0xd6, 0xdd, 0xe0, 0x91, 0xa5, 0x14, 0x2f, 0x7a, 0x08, 0x48, 0xcd, 0x13, 0x4a, 0x15, 0x30, 0xc4,
0x85, 0x49, 0x88, 0x52, 0xb3, 0x32, 0xf8, 0x69, 0x2b, 0xc7, 0xd6, 0x3e, 0xdd, 0xde, 0x2e, 0xf9,
0x9e, 0x65, 0x0f, 0xac, 0x20, 0x34, 0xc2, 0xcc, 0x56, 0xae, 0x73, 0xb2, 0xae, 0xa4, 0xa3, 0xad,
0x4c, 0xf2, 0x52, 0xbc, 0x1d, 0xb2, 0xb3, 0x49, 0xfc, 0x60, 0xdb, 0x19, 0x8b, 0x36, 0xee, 0x66,
0xe2, 0xdd, 0x97, 0x64, 0x71, 0x0b, 0x53, 0xbc, 0x74, 0x21, 0x1e, 0x50, 0x69, 0x6f, 0xec, 0xbb,
0x03, 0xae, 0x8c, 0x02, 0xf4, 0x69, 0xe6, 0x42, 0x9c, 0x69, 0x46, 0x37, 0x26, 0x8e, 0xa1, 0xb3,
0x61, 0xd0, 0x5d, 0x38, 0x34, 0xbe, 0x38, 0xd6, 0x90, 0x9f, 0x65, 0x2e, 0x9c, 0xd7, 0x2f, 0xae,
0x27, 0x21, 0x93, 0x9c, 0xd4, 0xd4, 0x9c, 0x9d, 0xb1, 0xe7, 0x87, 0xb7, 0x1d, 0xd7, 0x09, 0xb6,
0x8d, 0xfd, 0x4c, 0x53, 0xeb, 0x33, 0x92, 0x2e, 0xa7, 0xa1, 0xa6, 0xa6, 0xf2, 0xa0, 0xcb, 0xd0,
0x1c, 0x6c, 0x5b, 0xe1, 0xa2, 0x6d, 0x1b, 0x5f, 0xe7, 0x81, 0xde, 0xe7, 0x13, 0xfc, 0xcb, 0xdb,
0x56, 0x28, 0x42, 0x24, 0x11, 0x29, 0xba, 0x0e, 0x40, 0xff, 0x8a, 0x1e, 0xfc, 0x7c, 0x39, 0xd3,
0x57, 0x31, 0x46, 0xd9, 0x7a, 0x85, 0x01, 0xbd, 0x0f, 0x47, 0xe2, 0x14, 0x35, 0x52, 0xbe, 0xe7,
0xff, 0x46, 0x39, 0xd3, 0xdb, 0x2a, 0x38, 0x92, 0xb6, 0x57, 0xc2, 0x59, 0x10, 0x51, 0xc3, 0xc4,
0x5c, 0xfc, 0xcd, 0x09, 0x0d, 0x93, 0xf3, 0xae, 0xc2, 0xb0, 0xd4, 0x84, 0xfa, 0x9e, 0x35, 0xda,
0x25, 0xe6, 0xb7, 0x2b, 0x50, 0xa3, 0x64, 0x26, 0x81, 0x2a, 0xed, 0xf0, 0x3c, 0x54, 0x1c, 0x9b,
0x1d, 0x21, 0xb4, 0x71, 0xc5, 0xb1, 0x91, 0x01, 0x4d, 0x8f, 0xae, 0x23, 0xe5, 0x99, 0x46, 0x94,
0xa4, 0x03, 0x2a, 0xce, 0x3e, 0x44, 0xe0, 0xc8, 0x4c, 0x9c, 0x67, 0x50, 0xd8, 0xe8, 0x98, 0x24,
0x22, 0x35, 0x0d, 0x68, 0x88, 0x69, 0x3e, 0x51, 0x93, 0xb9, 0x06, 0x0d, 0x31, 0x6a, 0xc9, 0x36,
0x28, 0x35, 0x55, 0xa6, 0xaf, 0x89, 0xc0, 0xa1, 0xe4, 0xa0, 0x25, 0x81, 0x97, 0xa0, 0xed, 0x4b,
0xa1, 0x54, 0x12, 0x31, 0x9e, 0x14, 0x74, 0x57, 0x02, 0xe1, 0x98, 0xcd, 0xfc, 0x93, 0x3a, 0x34,
0xc5, 0x11, 0x81, 0xb9, 0x06, 0x35, 0x76, 0x9e, 0x72, 0x14, 0xea, 0x8e, 0x6b, 0x93, 0x67, 0xac,
0xaa, 0x3a, 0xe6, 0x09, 0x74, 0x01, 0x9a, 0xe2, 0xc8, 0x40, 0xd4, 0x95, 0x77, 0x00, 0x14, 0x91,
0x99, 0x1f, 0x40, 0x33, 0x3a, 0x57, 0x39, 0x0e, 0xed, 0xb1, 0xef, 0x51, 0x67, 0xd8, 0x8f, 0x7a,
0x10, 0x67, 0xa0, 0xb7, 0xa0, 0x69, 0x8b, 0x93, 0x9b, 0x8a, 0xd0, 0x6d, 0x7e, 0xd4, 0xd5, 0x8d,
0x8e, 0xba, 0xba, 0x1b, 0xec, 0xa8, 0x0b, 0x47, 0x74, 0xe6, 0xd7, 0xcb, 0xd0, 0xe0, 0xc7, 0x2b,
0xe6, 0x9e, 0x1c, 0xf9, 0xb7, 0xa1, 0x31, 0x60, 0x79, 0x46, 0xf2, 0x68, 0x45, 0x6b, 0xa1, 0x38,
0xaf, 0xc1, 0x82, 0x98, 0xb2, 0x05, 0x7c, 0x12, 0xac, 0x4c, 0x64, 0xe3, 0x46, 0x8d, 0x05, 0xf1,
0xff, 0x58, 0xbd, 0xff, 0x59, 0x86, 0x83, 0xfa, 0xa9, 0xcd, 0x71, 0x68, 0x0f, 0xe4, 0x39, 0x90,
0x18, 0xdd, 0x81, 0x72, 0xa6, 0x03, 0x83, 0x91, 0x43, 0xdc, 0x90, 0x05, 0x28, 0x2b, 0x99, 0xeb,
0xde, 0xcc, 0x53, 0xa2, 0xee, 0xb2, 0x64, 0xc3, 0x0a, 0x84, 0xf9, 0x35, 0x80, 0xb8, 0x04, 0x9d,
0x94, 0x2b, 0x91, 0x35, 0x6b, 0x27, 0xaa, 0x5e, 0xcd, 0x52, 0x28, 0xd6, 0xad, 0x70, 0x5b, 0x18,
0xa2, 0x9a, 0x85, 0xce, 0xc1, 0xe1, 0xc0, 0x19, 0xba, 0x56, 0xb8, 0xeb, 0x93, 0xc7, 0xc4, 0x77,
0xb6, 0x1c, 0x62, 0x33, 0xb3, 0x6c, 0xe1, 0x74, 0x81, 0xf9, 0xcb, 0x6d, 0x68, 0xf0, 0x1d, 0x86,
0xf9, 0xef, 0x15, 0xa9, 0x63, 0xe6, 0x5f, 0x96, 0xa1, 0xce, 0x4f, 0x5a, 0x92, 0x86, 0x72, 0x5b,
0xd5, 0xaf, 0x6a, 0xc6, 0xf2, 0x3b, 0xeb, 0xe4, 0xa9, 0x7b, 0x97, 0xec, 0x3f, 0xa6, 0x4e, 0x46,
0x2a, 0x1d, 0x3a, 0x06, 0x8d, 0x60, 0x77, 0xb3, 0x6f, 0x07, 0x46, 0xf5, 0x64, 0xf5, 0x6c, 0x1b,
0x8b, 0x94, 0x79, 0x07, 0x5a, 0x11, 0x31, 0xea, 0x40, 0xf5, 0x09, 0xd9, 0x17, 0x95, 0xd3, 0xbf,
0xe8, 0x9c, 0x70, 0x56, 0xd2, 0x6c, 0x92, 0xba, 0xcd, 0x6b, 0x11, 0x1e, 0xed, 0x0b, 0x50, 0xa5,
0x6b, 0xfa, 0x64, 0x17, 0x66, 0x37, 0x91, 0xdc, 0xd6, 0x2e, 0x43, 0x9d, 0x9f, 0x76, 0x25, 0xeb,
0x40, 0x50, 0x7b, 0x42, 0xf6, 0xf9, 0x18, 0xb5, 0x31, 0xfb, 0x9f, 0x0b, 0xf2, 0x17, 0x55, 0x38,
0xa0, 0x46, 0xf8, 0xcd, 0xd5, 0x5c, 0x07, 0x6c, 0x6d, 0x85, 0xaa, 0x03, 0x16, 0x49, 0xea, 0x65,
0x18, 0x16, 0x93, 0x73, 0x1b, 0xf3, 0x84, 0xd9, 0x85, 0x86, 0x38, 0x38, 0x49, 0x22, 0x49, 0xfa,
0x8a, 0x4a, 0x7f, 0x07, 0x5a, 0xf2, 0x1c, 0xe4, 0xa3, 0xd6, 0xed, 0x43, 0x4b, 0x1e, 0x78, 0x1c,
0x85, 0x7a, 0xe8, 0x85, 0xd6, 0x88, 0xc1, 0x55, 0x31, 0x4f, 0x50, 0x43, 0x73, 0xc9, 0xb3, 0x70,
0x59, 0x7a, 0xc1, 0x2a, 0x8e, 0x33, 0xb8, 0x93, 0x23, 0x7b, 0xbc, 0xb4, 0xca, 0x4b, 0x65, 0x46,
0x5c, 0x67, 0x4d, 0xad, 0x73, 0x1f, 0x1a, 0xe2, 0x14, 0x44, 0x96, 0x97, 0x95, 0x72, 0xb4, 0x08,
0xf5, 0x21, 0x2d, 0x17, 0x52, 0x7f, 0x23, 0xe1, 0x22, 0xf8, 0xe6, 0x66, 0xd9, 0x73, 0x43, 0xaa,
0xc6, 0x7a, 0x70, 0x07, 0x73, 0x4e, 0x2a, 0x42, 0x9f, 0x1f, 0x69, 0x71, 0x8b, 0x12, 0x29, 0xf3,
0xf7, 0xcb, 0xd0, 0x96, 0x67, 0x88, 0xe6, 0x07, 0x79, 0xc6, 0xb3, 0x08, 0x07, 0x7d, 0x41, 0x45,
0xbd, 0x43, 0x64, 0x42, 0x2f, 0x26, 0x5a, 0x82, 0x15, 0x1a, 0xac, 0x73, 0x98, 0xef, 0xe6, 0x0a,
0x75, 0x01, 0x0e, 0x44, 0xa4, 0x77, 0x63, 0xd5, 0xd3, 0xf2, 0x4c, 0x53, 0x72, 0x77, 0xa0, 0xea,
0xd8, 0xfc, 0x4a, 0x43, 0x1b, 0xd3, 0xbf, 0xe6, 0x16, 0x1c, 0x50, 0x4f, 0x12, 0xcc, 0xc7, 0xd9,
0xd6, 0x73, 0x93, 0x56, 0xa3, 0x9c, 0x5a, 0x54, 0x12, 0xdb, 0xa5, 0xa8, 0x0b, 0x31, 0x09, 0xd6,
0x18, 0xcc, 0xe7, 0xa1, 0xce, 0xcf, 0x37, 0x93, 0xd3, 0xfe, 0xef, 0x0c, 0xa0, 0xce, 0x84, 0x60,
0x5e, 0xe2, 0x06, 0x70, 0x0e, 0x1a, 0x6c, 0xaf, 0x1e, 0xdd, 0xbc, 0x38, 0x9a, 0x25, 0x31, 0x2c,
0x68, 0xcc, 0x65, 0x98, 0x53, 0x4e, 0x96, 0xa8, 0xc6, 0xb2, 0x02, 0xa9, 0x05, 0x51, 0x12, 0x99,
0xd0, 0xa2, 0x93, 0xa5, 0x70, 0xa0, 0xb4, 0xff, 0x32, 0x6d, 0x9e, 0x92, 0x8b, 0x12, 0x53, 0x9c,
0xa4, 0xf5, 0xe5, 0x28, 0xc9, 0xb4, 0xf9, 0x79, 0x68, 0xcb, 0x03, 0x28, 0xf4, 0x00, 0x0e, 0x88,
0x03, 0x28, 0xbe, 0x7f, 0xa6, 0xc4, 0xf3, 0x05, 0xda, 0x45, 0x37, 0xcb, 0xec, 0x0c, 0xab, 0xfb,
0x70, 0x7f, 0x4c, 0xb0, 0x06, 0x60, 0xfe, 0xe2, 0x59, 0x36, 0xf2, 0xe6, 0x18, 0x5a, 0x32, 0xea,
0x9e, 0x94, 0xc2, 0x55, 0xee, 0x1a, 0x2b, 0x85, 0x47, 0x46, 0x9c, 0x9f, 0x3a, 0x60, 0xe6, 0x41,
0xcd, 0x17, 0xa1, 0x7a, 0x97, 0xec, 0x53, 0x0b, 0xe1, 0x8e, 0x54, 0x58, 0x08, 0x77, 0x98, 0x7d,
0x68, 0x88, 0xd3, 0xaf, 0x64, 0x7d, 0xe7, 0xa1, 0xb1, 0xc5, 0x0f, 0xd4, 0x0a, 0x5c, 0xa6, 0x20,
0x33, 0x6f, 0xc2, 0x9c, 0x7a, 0xe6, 0x95, 0xc4, 0x3b, 0x09, 0x73, 0x03, 0xe5, 0x54, 0x8d, 0x8b,
0x41, 0xcd, 0x32, 0x89, 0xae, 0x8e, 0x29, 0x84, 0xd5, 0x4c, 0x3d, 0x7c, 0x25, 0x73, 0xd8, 0x27,
0x68, 0xe3, 0x5d, 0x38, 0x94, 0x3c, 0xdc, 0x4a, 0xd6, 0x74, 0x16, 0x0e, 0x6d, 0x26, 0x8e, 0xd2,
0xb8, 0x0f, 0x4c, 0x66, 0x9b, 0x7d, 0xa8, 0xf3, 0xc3, 0x87, 0x24, 0xc4, 0x05, 0xa8, 0x5b, 0xec,
0x70, 0x83, 0x32, 0xce, 0xa7, 0x56, 0xad, 0xe2, 0x4c, 0x96, 0x52, 0x60, 0x4e, 0x68, 0x3a, 0x70,
0x50, 0x3f, 0xcf, 0x48, 0x42, 0xf6, 0xe0, 0xe0, 0x9e, 0x76, 0x6e, 0xc2, 0xa1, 0x17, 0x32, 0xa1,
0x35, 0x28, 0xac, 0x33, 0x9a, 0xdf, 0x68, 0x40, 0x8d, 0x1d, 0xc8, 0x25, 0xab, 0xb8, 0x02, 0xb5,
0x90, 0x3c, 0x8b, 0xd6, 0xa8, 0x0b, 0x13, 0x4f, 0xf7, 0x78, 0x54, 0x88, 0xd1, 0xa3, 0x4f, 0x42,
0x3d, 0x08, 0xf7, 0x47, 0xd1, 0x6e, 0xe0, 0xd5, 0xc9, 0x8c, 0x1b, 0x94, 0x14, 0x73, 0x0e, 0xca,
0xca, 0x6c, 0x41, 0x1c, 0x20, 0x17, 0xb0, 0x32, 0x23, 0xc4, 0x9c, 0x03, 0xdd, 0xa4, 0xdb, 0x3a,
0x32, 0x78, 0x42, 0x6c, 0x71, 0x72, 0x7c, 0x7a, 0x32, 0xf3, 0x32, 0x27, 0xc6, 0x11, 0x17, 0xad,
0x7b, 0xc0, 0xa4, 0xdb, 0x98, 0xa6, 0x6e, 0x26, 0x71, 0xcc, 0x39, 0xd0, 0x2a, 0xb4, 0x9d, 0x81,
0xe7, 0xae, 0xee, 0x78, 0x5f, 0x74, 0xc4, 0x11, 0xf1, 0x6b, 0x93, 0xd9, 0xfb, 0x11, 0x39, 0x8e,
0x39, 0x23, 0x98, 0xfe, 0x0e, 0xdd, 0xe0, 0xb4, 0xa6, 0x85, 0x61, 0xe4, 0x38, 0xe6, 0x34, 0x8f,
0x0b, 0x79, 0x66, 0x1b, 0xf9, 0x6d, 0xa8, 0xb3, 0x21, 0x47, 0xd7, 0xd5, 0xe2, 0x79, 0xa5, 0xa6,
0x5c, 0x8f, 0x25, 0x44, 0x25, 0x71, 0xd8, 0xf8, 0xeb, 0x38, 0x73, 0xd3, 0xe0, 0x08, 0xb9, 0x71,
0x9c, 0x97, 0xa1, 0x29, 0x44, 0xa1, 0x37, 0xb8, 0x15, 0x11, 0xbc, 0x04, 0x75, 0x6e, 0x98, 0xd9,
0xfd, 0x79, 0x05, 0xda, 0x72, 0x30, 0x27, 0x93, 0xb0, 0xd1, 0xc9, 0x21, 0xf9, 0xa5, 0x0a, 0xd4,
0xf9, 0xc1, 0x64, 0xda, 0xd5, 0xaa, 0x56, 0xf0, 0xea, 0xe4, 0x73, 0x4e, 0xd5, 0x0c, 0x6e, 0xb3,
0x8d, 0x1a, 0x5d, 0x98, 0xcb, 0x8b, 0x7e, 0x67, 0x0b, 0xb8, 0xd7, 0x23, 0x7a, 0x1c, 0xb3, 0x16,
0x88, 0xf3, 0x01, 0xb4, 0x25, 0x17, 0x5a, 0xd2, 0x45, 0x7a, 0x6e, 0xa2, 0x28, 0x92, 0x55, 0x0a,
0xc0, 0xdf, 0x2c, 0x43, 0x75, 0xc5, 0xd9, 0x4b, 0x8d, 0xc3, 0x3b, 0x91, 0x55, 0x17, 0xb9, 0x83,
0x15, 0x67, 0x4f, 0x33, 0x6a, 0x73, 0x35, 0xd2, 0xb8, 0x77, 0xf5, 0xe6, 0x9d, 0x99, 0xbc, 0x02,
0x8b, 0x61, 0x78, 0xc3, 0x7e, 0xad, 0x09, 0x35, 0x76, 0xe6, 0x9f, 0xe5, 0xa7, 0xf6, 0xc7, 0xc5,
0x0d, 0x63, 0x51, 0x45, 0x36, 0xe1, 0x32, 0x7a, 0xee, 0xa7, 0xac, 0xb0, 0xd8, 0x4f, 0xf1, 0x20,
0x29, 0x25, 0xc5, 0x9c, 0x83, 0x56, 0xb9, 0xe3, 0xec, 0x10, 0xe1, 0xa6, 0x0a, 0xaa, 0xbc, 0xef,
0xec, 0x10, 0xcc, 0xe8, 0x29, 0xdf, 0xb6, 0x15, 0x6c, 0x0b, 0x0f, 0x55, 0xc0, 0xd7, 0xb3, 0x82,
0x6d, 0xcc, 0xe8, 0x29, 0x9f, 0x4b, 0xb7, 0x84, 0x8d, 0x69, 0xf8, 0xe8, 0x4e, 0x11, 0x33, 0x7a,
0xca, 0x17, 0x38, 0x5f, 0x26, 0xc2, 0x27, 0x15, 0xf0, 0x6d, 0x38, 0x5f, 0x26, 0x98, 0xd1, 0xc7,
0x2e, 0xbc, 0x35, 0xdd, 0xd0, 0x28, 0x2e, 0xfc, 0x21, 0xcc, 0x87, 0xda, 0xc9, 0x95, 0xb8, 0x78,
0x72, 0xae, 0x40, 0x2e, 0x1a, 0x0f, 0x4e, 0x60, 0x50, 0x23, 0x60, 0x1b, 0xe0, 0x6c, 0x23, 0x78,
0x09, 0xea, 0x9f, 0x71, 0xec, 0x70, 0x5b, 0x2f, 0xae, 0x6b, 0x2e, 0x8f, 0x8a, 0x6d, 0x26, 0x97,
0xa7, 0x4a, 0x9d, 0xe3, 0xac, 0x40, 0x8d, 0xaa, 0xcf, 0x6c, 0x7a, 0x1c, 0x6b, 0xdd, 0x47, 0x72,
0xc0, 0xea, 0x40, 0x73, 0x9c, 0xe3, 0x50, 0xa3, 0x1a, 0x92, 0x33, 0x24, 0xc7, 0xa1, 0x46, 0xf5,
0x2e, 0xbf, 0x94, 0x4a, 0x5b, 0x2f, 0xad, 0x46, 0xa5, 0x67, 0x60, 0x5e, 0x17, 0x47, 0x0e, 0xca,
0xb7, 0x9b, 0x50, 0x63, 0x17, 0x68, 0x92, 0x16, 0xf9, 0x69, 0x38, 0xc8, 0xe5, 0xb7, 0x24, 0x96,
0xe0, 0x95, 0xcc, 0xfb, 0x73, 0xfa, 0xb5, 0x1c, 0xa1, 0x02, 0x82, 0x05, 0xeb, 0x08, 0xd3, 0x2f,
0x2a, 0x18, 0x94, 0xa6, 0x91, 0xef, 0xca, 0xc5, 0x6b, 0xad, 0xe0, 0xf6, 0x16, 0xe3, 0xe5, 0x4b,
0xe0, 0x68, 0x25, 0x8b, 0x96, 0xa0, 0x45, 0xa7, 0x56, 0x3a, 0x5c, 0xc2, 0x6c, 0xcf, 0x4c, 0xe6,
0xef, 0x0b, 0x6a, 0x2c, 0xf9, 0xe8, 0xc4, 0x3e, 0xb0, 0x7c, 0x9b, 0xb5, 0x4a, 0xd8, 0xf0, 0x6b,
0x93, 0x41, 0x96, 0x23, 0x72, 0x1c, 0x73, 0xa2, 0xbb, 0x30, 0x67, 0x13, 0x19, 0x27, 0x10, 0x46,
0xfd, 0x89, 0xc9, 0x40, 0x2b, 0x31, 0x03, 0x56, 0xb9, 0x69, 0x9b, 0xa2, 0xbd, 0x61, 0x50, 0xb8,
0xd8, 0x60, 0x50, 0xf1, 0x2d, 0xd9, 0x98, 0xd3, 0x3c, 0x0d, 0x07, 0x35, 0xb9, 0x7d, 0xac, 0xab,
0x0e, 0x55, 0x96, 0x1c, 0xe7, 0xaa, 0xdc, 0xa2, 0xbc, 0xa9, 0x2f, 0x3b, 0x72, 0x77, 0x24, 0x82,
0xf1, 0x1e, 0xb4, 0x22, 0xc1, 0xa0, 0x5b, 0x7a, 0x1b, 0x5e, 0x2f, 0x6e, 0x83, 0x94, 0xa9, 0x40,
0x5b, 0x83, 0xb6, 0x94, 0x10, 0x5a, 0xd4, 0xe1, 0xde, 0x28, 0x86, 0x8b, 0xa5, 0x2b, 0xf0, 0x30,
0xcc, 0x29, 0x82, 0x42, 0xcb, 0x3a, 0xe2, 0x9b, 0xc5, 0x88, 0xaa, 0x98, 0xe3, 0x55, 0x8f, 0x94,
0x98, 0x2a, 0x95, 0x6a, 0x2c, 0x95, 0x3f, 0x6e, 0x42, 0x4b, 0x5e, 0x5a, 0xcb, 0xd8, 0x63, 0xee,
0xfa, 0xa3, 0xc2, 0x3d, 0x66, 0xc4, 0xdf, 0x7d, 0xe4, 0x8f, 0x30, 0xe5, 0xa0, 0x22, 0x0e, 0x9d,
0x50, 0x9a, 0xea, 0x6b, 0xc5, 0xac, 0x0f, 0x29, 0x39, 0xe6, 0x5c, 0xe8, 0x81, 0xae, 0xe5, 0xb5,
0x09, 0x97, 0x1a, 0x34, 0x90, 0x5c, 0x4d, 0xef, 0x43, 0xdb, 0xa1, 0x4b, 0xbf, 0x5e, 0x3c, 0xf3,
0xbe, 0x51, 0x0c, 0xd7, 0x8f, 0x58, 0x70, 0xcc, 0x4d, 0xdb, 0xb6, 0x65, 0xed, 0x51, 0xbb, 0x66,
0x60, 0x8d, 0x69, 0xdb, 0x76, 0x3b, 0x66, 0xc2, 0x2a, 0x02, 0xba, 0x26, 0xd6, 0x2e, 0xcd, 0x02,
0xcf, 0x12, 0x0f, 0x55, 0xbc, 0x7e, 0x79, 0x3f, 0x35, 0xd3, 0x72, 0x33, 0xbe, 0x30, 0x05, 0xca,
0xc4, 0xd9, 0x96, 0x4a, 0x90, 0xaf, 0x8c, 0xda, 0xd3, 0x4a, 0x50, 0x5d, 0x1d, 0x99, 0x2f, 0x42,
0xf5, 0x91, 0x3f, 0xca, 0x9f, 0xab, 0x99, 0xb8, 0x73, 0x8a, 0x5f, 0xd5, 0x2d, 0x21, 0x7f, 0x41,
0x2f, 0x65, 0x92, 0x8b, 0xa3, 0x0c, 0x7a, 0x0e, 0xd1, 0x75, 0x31, 0xa1, 0xbf, 0xad, 0xdb, 0xdb,
0xcb, 0x09, 0x7b, 0xa3, 0x16, 0xb6, 0xee, 0x13, 0x7e, 0x6f, 0x47, 0x99, 0xc9, 0xa7, 0x9d, 0x27,
0xef, 0x44, 0xeb, 0x8f, 0x99, 0x3c, 0x45, 0x72, 0x6c, 0x39, 0xd6, 0x2f, 0x94, 0xa1, 0x25, 0xef,
0x24, 0xa6, 0xa3, 0xf3, 0x2d, 0x27, 0xe8, 0x11, 0xcb, 0x26, 0xbe, 0xb0, 0xdb, 0xd7, 0x0b, 0x2f,
0x3b, 0x76, 0xfb, 0x82, 0x03, 0x4b, 0x5e, 0xf3, 0x24, 0xb4, 0xa2, 0xdc, 0x9c, 0x4d, 0xd9, 0x0f,
0x2a, 0xd0, 0x10, 0xb7, 0x19, 0x93, 0x8d, 0xb8, 0x01, 0x8d, 0x91, 0xb5, 0xef, 0xed, 0x46, 0x5b,
0xa6, 0x33, 0x05, 0x17, 0x24, 0xbb, 0xf7, 0x18, 0x35, 0x16, 0x5c, 0xe8, 0x53, 0x50, 0x1f, 0x39,
0x3b, 0x4e, 0x28, 0xdc, 0xc7, 0xe9, 0x42, 0x76, 0x76, 0xef, 0x81, 0xf3, 0xd0, 0xca, 0xd9, 0x25,
0xa6, 0xe8, 0x0a, 0x7a, 0x61, 0xe5, 0x8f, 0x19, 0x35, 0x16, 0x5c, 0xe6, 0x1d, 0x68, 0xf0, 0xe6,
0xcc, 0x36, 0x49, 0xe8, 0x3d, 0x89, 0x35, 0x9d, 0xb5, 0x2d, 0x67, 0x55, 0x7a, 0x02, 0x1a, 0xbc,
0xf2, 0x1c, 0xad, 0xf9, 0xfe, 0x0b, 0x6c, 0xbf, 0x33, 0x32, 0xef, 0xc5, 0x87, 0x7f, 0x1f, 0xfd,
0x2c, 0xc3, 0x7c, 0x08, 0x87, 0x56, 0xac, 0xd0, 0xda, 0xb4, 0x02, 0x82, 0xc9, 0xc0, 0xf3, 0xed,
0x4c, 0x54, 0x9f, 0x17, 0x89, 0x08, 0x75, 0x3e, 0xaa, 0xa0, 0xfb, 0x69, 0xe8, 0xf0, 0x7f, 0x4f,
0xe8, 0xf0, 0x4f, 0x6b, 0x39, 0xf1, 0xbc, 0x69, 0x22, 0x19, 0x54, 0xe1, 0x52, 0x01, 0xbd, 0x6b,
0xfa, 0xda, 0xfb, 0x54, 0x01, 0xa7, 0xb6, 0xf8, 0xbe, 0xa6, 0x47, 0xf4, 0x8a, 0x78, 0xb5, 0x90,
0xde, 0xad, 0x64, 0x48, 0xef, 0x4c, 0x01, 0x77, 0x2a, 0xa6, 0x77, 0x4d, 0x8f, 0xe9, 0x15, 0xd5,
0xae, 0x06, 0xf5, 0xfe, 0x9f, 0x85, 0xd1, 0x7e, 0x2b, 0x27, 0xec, 0xf3, 0x49, 0x3d, 0xec, 0x33,
0x41, 0x6b, 0x7e, 0x52, 0x71, 0x9f, 0xdf, 0x6e, 0xe4, 0xc4, 0x7d, 0xae, 0x6a, 0x71, 0x9f, 0x09,
0x2d, 0x4b, 0x06, 0x7e, 0xae, 0xe9, 0x81, 0x9f, 0x53, 0x05, 0x9c, 0x5a, 0xe4, 0xe7, 0xaa, 0x16,
0xf9, 0x29, 0xaa, 0x54, 0x09, 0xfd, 0x5c, 0xd5, 0x42, 0x3f, 0x45, 0x8c, 0x4a, 0xec, 0xe7, 0xaa,
0x16, 0xfb, 0x29, 0x62, 0x54, 0x82, 0x3f, 0x57, 0xb5, 0xe0, 0x4f, 0x11, 0xa3, 0x12, 0xfd, 0xb9,
0xa6, 0x47, 0x7f, 0x8a, 0xc7, 0x47, 0x11, 0xfa, 0x4f, 0x03, 0x35, 0xff, 0x8d, 0x81, 0x9a, 0x5f,
0xad, 0xe6, 0x04, 0x60, 0x70, 0x76, 0x00, 0xe6, 0x5c, 0xbe, 0x24, 0x8b, 0x23, 0x30, 0xd3, 0xcf,
0x02, 0xe9, 0x10, 0xcc, 0xf5, 0x44, 0x08, 0xe6, 0x74, 0x01, 0xb3, 0x1e, 0x83, 0xf9, 0x3f, 0x13,
0x64, 0xf8, 0xc3, 0xc6, 0x84, 0xfd, 0xf4, 0x3b, 0xea, 0x7e, 0x7a, 0xc2, 0x4c, 0x96, 0xde, 0x50,
0xdf, 0xd0, 0x37, 0xd4, 0x67, 0xa7, 0xe0, 0xd5, 0x76, 0xd4, 0xeb, 0x59, 0x3b, 0xea, 0xee, 0x14,
0x28, 0xb9, 0x5b, 0xea, 0x3b, 0xe9, 0x2d, 0xf5, 0xb9, 0x29, 0xf0, 0x32, 0xf7, 0xd4, 0xeb, 0x59,
0x7b, 0xea, 0x69, 0x5a, 0x97, 0xbb, 0xa9, 0xfe, 0x94, 0xb6, 0xa9, 0x7e, 0x6d, 0x9a, 0xe1, 0x8a,
0x27, 0x87, 0xcf, 0xe6, 0xec, 0xaa, 0xdf, 0x9a, 0x06, 0x66, 0x72, 0x10, 0xfb, 0xa7, 0xfb, 0x62,
0xbd, 0x9a, 0x3f, 0x78, 0x19, 0x5a, 0xd1, 0x45, 0x1b, 0xf3, 0x4b, 0xd0, 0x8c, 0x3e, 0x61, 0x4b,
0x5a, 0xce, 0x31, 0xb9, 0xa9, 0xe3, 0xab, 0x67, 0x91, 0x42, 0x37, 0xa0, 0x46, 0xff, 0x09, 0xb3,
0x78, 0x7d, 0xba, 0x0b, 0x3d, 0xb4, 0x12, 0xcc, 0xf8, 0xcc, 0x7f, 0x3b, 0x0a, 0xa0, 0x7c, 0xd9,
0x33, 0x6d, 0xb5, 0xef, 0x51, 0x67, 0x36, 0x0a, 0x89, 0xcf, 0x2e, 0x72, 0x15, 0x7e, 0xf9, 0x12,
0xd7, 0x40, 0xb5, 0x25, 0x24, 0x3e, 0x16, 0xec, 0xe8, 0x3e, 0xb4, 0xa2, 0x40, 0xaa, 0x51, 0x63,
0x50, 0x6f, 0x4d, 0x0d, 0x15, 0x85, 0xf6, 0xb0, 0x84, 0x40, 0x8b, 0x50, 0x0b, 0x3c, 0x3f, 0x34,
0xea, 0x0c, 0xea, 0xcd, 0xa9, 0xa1, 0x36, 0x3c, 0x3f, 0xc4, 0x8c, 0x95, 0x77, 0x4d, 0xf9, 0x70,
0x7a, 0x96, 0xae, 0x69, 0x1e, 0xfb, 0x5f, 0xab, 0xd2, 0x87, 0x2e, 0x0b, 0x6b, 0xe4, 0x3a, 0x74,
0x7e, 0x7a, 0x29, 0xa9, 0x56, 0x89, 0xc4, 0x22, 0x88, 0x4b, 0x82, 0xaf, 0x6f, 0x5e, 0x87, 0xce,
0xc0, 0xdb, 0x23, 0x3e, 0x8e, 0xaf, 0x38, 0x89, 0x5b, 0x68, 0xa9, 0x7c, 0x64, 0x42, 0x6b, 0xdb,
0xb1, 0x49, 0x7f, 0x20, 0xfc, 0x5f, 0x0b, 0xcb, 0x34, 0xba, 0x0b, 0x2d, 0x16, 0x63, 0x8f, 0x22,
0xfc, 0xb3, 0x35, 0x92, 0x87, 0xfa, 0x23, 0x00, 0x5a, 0x11, 0xab, 0xfc, 0xb6, 0x13, 0xb2, 0x31,
0x6c, 0x61, 0x99, 0xa6, 0x0d, 0x66, 0xf7, 0xc8, 0xd4, 0x06, 0x37, 0x79, 0x83, 0x93, 0xf9, 0xe8,
0x32, 0x3c, 0xc7, 0xf2, 0x12, 0x5b, 0x4c, 0x1e, 0xaa, 0x6f, 0xe1, 0xec, 0x42, 0x76, 0x6f, 0xce,
0x1a, 0xf2, 0xcf, 0x24, 0x58, 0xf0, 0xae, 0x8e, 0xe3, 0x0c, 0x74, 0x0e, 0x0e, 0xdb, 0x64, 0xcb,
0xda, 0x1d, 0x85, 0x0f, 0xc9, 0xce, 0x78, 0x64, 0x85, 0xa4, 0x6f, 0xb3, 0x6f, 0xb7, 0xdb, 0x38,
0x5d, 0x80, 0x2e, 0xc0, 0x11, 0x91, 0xc9, 0xcd, 0x98, 0x4a, 0xa3, 0x6f, 0xb3, 0x4f, 0x99, 0xdb,
0x38, 0xab, 0xc8, 0xfc, 0x7e, 0x8d, 0x0a, 0x9d, 0xa9, 0xf6, 0x7b, 0x50, 0xb5, 0x6c, 0x5b, 0x4c,
0x9b, 0x97, 0x66, 0x34, 0x10, 0x71, 0xf7, 0x9e, 0x22, 0xa0, 0x75, 0x79, 0xe5, 0x8e, 0x4f, 0x9c,
0x57, 0x66, 0xc5, 0x92, 0x4f, 0x4a, 0x08, 0x1c, 0x8a, 0xb8, 0xcb, 0x6f, 0xf1, 0x57, 0x7f, 0x3c,
0x44, 0x79, 0xc1, 0x5f, 0xe0, 0xa0, 0x3b, 0x50, 0x63, 0x2d, 0xe4, 0x13, 0xeb, 0xe5, 0x59, 0xf1,
0xee, 0xf3, 0xf6, 0x31, 0x0c, 0x73, 0xc0, 0xef, 0xbe, 0x29, 0x17, 0x2e, 0xcb, 0xfa, 0x85, 0xcb,
0x25, 0xa8, 0x3b, 0x21, 0xd9, 0x49, 0xdf, 0xbf, 0x9d, 0xa8, 0xaa, 0xc2, 0xf3, 0x70, 0xd6, 0x89,
0xf7, 0x00, 0x3f, 0xc8, 0xbd, 0x7d, 0x7f, 0x0b, 0x6a, 0x94, 0x3d, 0xb5, 0x96, 0x9c, 0xa6, 0x62,
0xc6, 0x69, 0x5e, 0x84, 0x1a, 0xed, 0xec, 0x84, 0xde, 0x89, 0xf6, 0x54, 0x64, 0x7b, 0x96, 0xe6,
0xa0, 0xed, 0x8d, 0x89, 0xcf, 0x0c, 0xc3, 0xfc, 0x97, 0x9a, 0x72, 0x29, 0xae, 0xaf, 0xea, 0xd8,
0xdb, 0x33, 0x7b, 0x4e, 0x55, 0xcb, 0x70, 0x42, 0xcb, 0xde, 0x99, 0x1d, 0x2d, 0xa5, 0x67, 0x38,
0xa1, 0x67, 0x3f, 0x06, 0x66, 0x4a, 0xd3, 0xee, 0x69, 0x9a, 0x76, 0x65, 0x76, 0x44, 0x4d, 0xd7,
0x48, 0x91, 0xae, 0xad, 0xe8, 0xba, 0xd6, 0x9d, 0x4e, 0xe4, 0x72, 0x6a, 0x9a, 0x42, 0xdb, 0x3e,
0x9f, 0xab, 0x6d, 0x4b, 0x9a, 0xb6, 0xcd, 0x5a, 0xf5, 0xc7, 0xa4, 0x6f, 0xdf, 0xab, 0x41, 0x8d,
0x4e, 0x8f, 0x68, 0x55, 0xd5, 0xb5, 0xb7, 0x66, 0x9a, 0x5a, 0x55, 0x3d, 0x5b, 0x4b, 0xe8, 0xd9,
0xe5, 0xd9, 0x90, 0x52, 0x3a, 0xb6, 0x96, 0xd0, 0xb1, 0x19, 0xf1, 0x52, 0xfa, 0xd5, 0xd3, 0xf4,
0xeb, 0xe2, 0x6c, 0x68, 0x9a, 0x6e, 0x59, 0x45, 0xba, 0x75, 0x4b, 0xd7, 0xad, 0x29, 0x57, 0x6f,
0x6c, 0xad, 0x32, 0x85, 0x5e, 0xbd, 0x9f, 0xab, 0x57, 0x37, 0x34, 0xbd, 0x9a, 0xa5, 0xda, 0x8f,
0x49, 0xa7, 0x2e, 0xf3, 0x45, 0x67, 0xf6, 0xc7, 0x4f, 0x79, 0x8b, 0x4e, 0xf3, 0x6d, 0x68, 0xc7,
0x4f, 0x23, 0x64, 0x5c, 0xcf, 0xe7, 0x64, 0x51, 0xad, 0x51, 0xd2, 0xbc, 0x04, 0xed, 0xf8, 0xb9,
0x83, 0x8c, 0xba, 0x02, 0x56, 0x28, 0xb8, 0x44, 0xca, 0x5c, 0x85, 0xc3, 0xe9, 0x8f, 0xb1, 0x33,
0xe2, 0xf0, 0xca, 0xdd, 0xf2, 0xe8, 0x53, 0x14, 0x25, 0xcb, 0x7c, 0x0a, 0xf3, 0x89, 0xcf, 0xab,
0x67, 0xc6, 0x40, 0x97, 0x94, 0x25, 0x72, 0x35, 0xf1, 0xb1, 0x9e, 0x7e, 0x5b, 0x3e, 0x5e, 0x08,
0x9b, 0x2b, 0x30, 0x5f, 0xd0, 0xf8, 0x69, 0x2e, 0xcb, 0x7f, 0x01, 0xe6, 0x26, 0xb5, 0xfd, 0x63,
0xb8, 0xcc, 0x1f, 0x42, 0x27, 0xf5, 0x34, 0x44, 0xb2, 0x9a, 0x75, 0x80, 0xa1, 0xa4, 0x11, 0x4a,
0x7b, 0x61, 0x86, 0x4f, 0x17, 0x18, 0x1f, 0x56, 0x30, 0xcc, 0xdf, 0x2b, 0xc3, 0xe1, 0xf4, 0xbb,
0x10, 0xd3, 0x6e, 0x7e, 0x0c, 0x68, 0x32, 0x2c, 0xf9, 0xc5, 0x47, 0x94, 0x44, 0xf7, 0xe1, 0x40,
0x30, 0x72, 0x06, 0x64, 0x79, 0xdb, 0x72, 0x87, 0x24, 0x10, 0x3b, 0x9a, 0x82, 0xb7, 0x1d, 0x36,
0x62, 0x0e, 0xac, 0xb1, 0x9b, 0x4f, 0x61, 0x4e, 0x29, 0x44, 0xef, 0x42, 0xc5, 0x1b, 0xa7, 0xee,
0x35, 0xe6, 0x63, 0x3e, 0x88, 0xec, 0x0d, 0x57, 0xbc, 0x71, 0xda, 0x24, 0x55, 0xf3, 0xad, 0x6a,
0xe6, 0x6b, 0xde, 0x85, 0xc3, 0xe9, 0xa7, 0x17, 0x92, 0xc3, 0x73, 0x26, 0x15, 0x25, 0xe0, 0xc3,
0x94, 0xdc, 0xf2, 0x5f, 0x85, 0x43, 0xc9, 0x07, 0x15, 0x32, 0xbe, 0xc6, 0x89, 0x3f, 0x6a, 0x8a,
0xc2, 0xf5, 0x0b, 0xbf, 0x52, 0x86, 0x79, 0xbd, 0x23, 0xe8, 0x18, 0x20, 0x3d, 0x67, 0xcd, 0x73,
0x49, 0xa7, 0x84, 0x9e, 0x83, 0xc3, 0x7a, 0xfe, 0xa2, 0x6d, 0x77, 0xca, 0x69, 0x72, 0xea, 0xb6,
0x3a, 0x15, 0x64, 0xc0, 0xd1, 0xc4, 0x08, 0x31, 0x27, 0xda, 0xa9, 0xa2, 0x17, 0xe0, 0xb9, 0x64,
0xc9, 0x78, 0x64, 0x0d, 0x48, 0xa7, 0x66, 0xfe, 0xa8, 0x02, 0xb5, 0x47, 0x01, 0xf1, 0xcd, 0x7f,
0xaa, 0x44, 0x5f, 0x69, 0xbc, 0x03, 0x35, 0xf6, 0xd6, 0x81, 0xf2, 0x35, 0x63, 0x39, 0xf1, 0x35,
0xa3, 0xf6, 0x45, 0x5c, 0xfc, 0x35, 0xe3, 0x3b, 0x50, 0x63, 0xaf, 0x1b, 0xcc, 0xce, 0xf9, 0xcd,
0x32, 0xb4, 0xe3, 0x97, 0x06, 0x66, 0xe6, 0x57, 0xbf, 0x0a, 0xa9, 0xe8, 0x5f, 0x85, 0xbc, 0x0e,
0x75, 0x9f, 0x7d, 0xbf, 0xc1, 0xbd, 0x4c, 0xf2, 0x5b, 0x13, 0x56, 0x21, 0xe6, 0x24, 0x26, 0x81,
0x39, 0xf5, 0x1d, 0x85, 0xd9, 0x9b, 0x71, 0x4a, 0x3c, 0xa2, 0xd4, 0xb7, 0x83, 0x45, 0xdf, 0xb7,
0xf6, 0x85, 0x62, 0xea, 0x99, 0xe6, 0x71, 0xa8, 0xad, 0x3b, 0xee, 0x30, 0xfb, 0x23, 0x52, 0xf3,
0xcf, 0xca, 0xd0, 0x14, 0x97, 0x77, 0xcd, 0xab, 0x50, 0x5d, 0x23, 0x4f, 0x69, 0x43, 0xc4, 0xb5,
0xe1, 0x54, 0x43, 0xee, 0xb3, 0x5e, 0x08, 0x7a, 0x1c, 0x91, 0x99, 0xd7, 0xe4, 0x34, 0x39, 0x3b,
0xef, 0x3b, 0x50, 0x63, 0xcf, 0x1f, 0xcc, 0xce, 0xf9, 0xe7, 0x2d, 0x68, 0xf0, 0x2f, 0x31, 0xcd,
0x3f, 0x6a, 0x41, 0x83, 0x3f, 0x89, 0x80, 0x6e, 0x40, 0x33, 0xd8, 0xdd, 0xd9, 0xb1, 0xfc, 0x7d,
0x23, 0xfb, 0xfd, 0x4d, 0xed, 0x05, 0x85, 0xee, 0x06, 0xa7, 0xc5, 0x11, 0x13, 0x7a, 0x1b, 0x6a,
0x03, 0x6b, 0x8b, 0xa4, 0x8e, 0x73, 0xb3, 0x98, 0x97, 0xad, 0x2d, 0x82, 0x19, 0x39, 0xba, 0x05,
0x2d, 0x21, 0x96, 0x40, 0xc4, 0x73, 0x26, 0xd7, 0x1b, 0x09, 0x53, 0x72, 0x99, 0x77, 0xa0, 0x29,
0x1a, 0x83, 0x6e, 0xca, 0xef, 0x50, 0x93, 0x91, 0xe7, 0xcc, 0x2e, 0xc8, 0x6f, 0xe5, 0xe5, 0x17,
0xa9, 0xdf, 0xa9, 0x40, 0x8d, 0x36, 0xee, 0x23, 0x23, 0xa1, 0x13, 0x00, 0x23, 0x2b, 0x08, 0xd7,
0x77, 0x47, 0x23, 0x62, 0x8b, 0x2f, 0xec, 0x94, 0x1c, 0x74, 0x16, 0x0e, 0xf1, 0x54, 0xb0, 0xbd,
0xb1, 0x3b, 0x18, 0x10, 0xf9, 0x99, 0x68, 0x32, 0x1b, 0x2d, 0x42, 0x9d, 0x3d, 0xd2, 0x27, 0x56,
0x85, 0x6f, 0x14, 0x8e, 0x6c, 0x77, 0xdd, 0x71, 0x45, 0x6b, 0x38, 0xa7, 0xe9, 0x41, 0x5b, 0xe6,
0x51, 0x23, 0x1c, 0x3b, 0xae, 0xeb, 0xb8, 0x43, 0xa1, 0xd1, 0x51, 0x92, 0x4e, 0x3a, 0xf4, 0xaf,
0x68, 0x6f, 0x1d, 0x8b, 0x14, 0xcd, 0xdf, 0xb2, 0x9c, 0x91, 0x68, 0x62, 0x1d, 0x8b, 0x14, 0x45,
0xda, 0x15, 0x0f, 0x49, 0xd4, 0x58, 0x07, 0xa3, 0xa4, 0xf9, 0x61, 0x59, 0x7e, 0x8c, 0x9d, 0xf5,
0x71, 0x66, 0x2a, 0x96, 0x74, 0x5c, 0x0d, 0x68, 0xf3, 0x09, 0x41, 0x09, 0x51, 0x1f, 0x83, 0x86,
0xe7, 0x8e, 0x1c, 0x97, 0x88, 0xd8, 0x91, 0x48, 0x25, 0xc6, 0xb8, 0x9e, 0x1a, 0x63, 0x51, 0xbe,
0x6a, 0x3b, 0xb4, 0x89, 0x8d, 0xb8, 0x9c, 0xe7, 0xa0, 0xeb, 0xd0, 0xb4, 0xc9, 0x9e, 0x33, 0x20,
0x81, 0xd1, 0x64, 0xaa, 0xf7, 0xea, 0xc4, 0xb1, 0x5d, 0x61, 0xb4, 0x38, 0xe2, 0x31, 0x43, 0x68,
0xf0, 0x2c, 0xd9, 0xa5, 0xb2, 0xd2, 0xa5, 0xb8, 0xd1, 0x95, 0x09, 0x8d, 0xae, 0x16, 0x34, 0xba,
0x96, 0x6c, 0xf4, 0xc2, 0x57, 0x01, 0x62, 0x75, 0x43, 0x73, 0xd0, 0x7c, 0xe4, 0x3e, 0x71, 0xbd,
0xa7, 0x6e, 0xa7, 0x44, 0x13, 0x0f, 0xb6, 0xb6, 0x68, 0x2d, 0x9d, 0x32, 0x4d, 0x50, 0x3a, 0xc7,
0x1d, 0x76, 0x2a, 0x08, 0xa0, 0x41, 0x13, 0xc4, 0xee, 0x54, 0xe9, 0xff, 0xdb, 0x4c, 0x7e, 0x9d,
0x1a, 0x7a, 0x1e, 0x8e, 0xf4, 0xdd, 0x81, 0xb7, 0x33, 0xb6, 0x42, 0x67, 0x73, 0x44, 0x1e, 0x13,
0x3f, 0x70, 0x3c, 0xb7, 0x53, 0xa7, 0xb3, 0xd7, 0x1a, 0x09, 0x9f, 0x7a, 0xfe, 0x93, 0x35, 0x42,
0x6c, 0xf1, 0xfe, 0x43, 0xa7, 0x61, 0xfe, 0x47, 0x99, 0x9f, 0x06, 0x9b, 0xb7, 0xe0, 0x80, 0xf6,
0xe2, 0x89, 0x01, 0x4d, 0xf6, 0x00, 0x45, 0xbc, 0x1e, 0x17, 0x49, 0xa6, 0x3d, 0xfc, 0x73, 0x79,
0xb1, 0x94, 0xe1, 0x29, 0xf3, 0x36, 0x80, 0xf2, 0xce, 0xc9, 0x09, 0x80, 0xcd, 0xfd, 0x90, 0x04,
0xfc, 0x8d, 0x13, 0x0a, 0x51, 0xc3, 0x4a, 0x8e, 0x8a, 0x5f, 0xd1, 0xf0, 0xcd, 0x2b, 0x00, 0xca,
0x2b, 0x27, 0xd4, 0xae, 0x68, 0x6a, 0x29, 0x09, 0x96, 0xcc, 0x36, 0xbb, 0xa2, 0x07, 0xd1, 0x7b,
0x26, 0x51, 0x0b, 0x78, 0xf4, 0x4e, 0x6d, 0x01, 0xcb, 0x31, 0x57, 0x01, 0xe2, 0x27, 0x3d, 0xcc,
0xab, 0xd2, 0x75, 0xbf, 0x09, 0x35, 0xdb, 0x0a, 0x2d, 0xe1, 0x35, 0x5f, 0x48, 0xcc, 0x5c, 0x31,
0x0b, 0x66, 0x64, 0xe6, 0xb7, 0xca, 0x70, 0x40, 0x7d, 0xbe, 0xc4, 0x7c, 0x0f, 0x6a, 0xec, 0xfd,
0x93, 0x9b, 0x70, 0x40, 0x7d, 0xbf, 0x24, 0xf5, 0x7c, 0x34, 0xc7, 0x53, 0x59, 0xb1, 0xc6, 0x60,
0xf6, 0x65, 0x93, 0x3e, 0x32, 0xd4, 0x05, 0x68, 0x8a, 0xe7, 0x50, 0xcc, 0xd3, 0xd0, 0x8e, 0x5f,
0x3f, 0xa1, 0xbe, 0x83, 0xe7, 0x47, 0x52, 0x16, 0x49, 0xf3, 0x9f, 0xab, 0x50, 0x67, 0xe2, 0x34,
0xbf, 0x5e, 0x51, 0x35, 0xd4, 0xfc, 0x51, 0x39, 0x77, 0x2f, 0x78, 0x49, 0x7b, 0x36, 0x60, 0x3e,
0xf5, 0xea, 0x8f, 0x78, 0xec, 0x44, 0x77, 0xac, 0x57, 0xa0, 0xe9, 0x72, 0xcd, 0x64, 0xc6, 0x33,
0x9f, 0x7e, 0xe9, 0x87, 0x71, 0x09, 0xed, 0xc5, 0x11, 0x31, 0xba, 0x0c, 0x75, 0xe2, 0xfb, 0x9e,
0xcf, 0x4c, 0x6a, 0x3e, 0xf5, 0x7e, 0x4e, 0xfc, 0xb0, 0xca, 0x2a, 0xa5, 0xc2, 0x9c, 0x18, 0x5d,
0x86, 0xe7, 0x02, 0x6e, 0x45, 0x7c, 0x4d, 0x19, 0x88, 0xef, 0xaa, 0x85, 0xb7, 0xc9, 0x2e, 0x5c,
0xf8, 0x74, 0x34, 0xc1, 0x2a, 0x86, 0x57, 0x52, 0x2d, 0xb2, 0x8c, 0xda, 0x50, 0x67, 0x15, 0x75,
0x2a, 0xaa, 0xd9, 0x56, 0x73, 0x0c, 0xaf, 0xb6, 0x70, 0x09, 0x9a, 0x22, 0x9f, 0xd2, 0x2f, 0xf2,
0xb6, 0x77, 0x4a, 0xe8, 0x00, 0xb4, 0x36, 0xc8, 0x68, 0xab, 0xe7, 0x05, 0x61, 0xa7, 0x8c, 0x0e,
0x42, 0x9b, 0xd9, 0xc2, 0x03, 0x77, 0xb4, 0xdf, 0xa9, 0x2c, 0xbc, 0x0f, 0x6d, 0xd9, 0x23, 0xd4,
0x82, 0xda, 0xda, 0xee, 0x68, 0xd4, 0x29, 0xb1, 0xa5, 0x69, 0xe8, 0xf9, 0x51, 0x60, 0x7a, 0xf5,
0x19, 0x9d, 0x67, 0x3a, 0xe5, 0x3c, 0x6f, 0x50, 0x41, 0x1d, 0x38, 0x20, 0x2a, 0xe7, 0x6d, 0xae,
0x9a, 0xff, 0x58, 0x86, 0xb6, 0x7c, 0x31, 0x86, 0xae, 0x0b, 0x23, 0x19, 0xe7, 0xfb, 0x81, 0xab,
0x09, 0x69, 0xe7, 0x3f, 0x40, 0x93, 0x90, 0xf8, 0x19, 0x98, 0x17, 0x2e, 0x37, 0x1a, 0x7c, 0xee,
0x35, 0x13, 0xb9, 0x0b, 0x77, 0xe4, 0xa8, 0x77, 0x98, 0x89, 0x2d, 0x7b, 0xae, 0x4b, 0x06, 0x21,
0x1b, 0xfb, 0x43, 0x30, 0xb7, 0xe6, 0x85, 0xeb, 0x5e, 0x10, 0xd0, 0x9e, 0xf1, 0x91, 0x8a, 0xcb,
0x2b, 0x68, 0x1e, 0x20, 0xba, 0x6b, 0x46, 0x9d, 0xa4, 0xf9, 0xbb, 0x65, 0x68, 0xf0, 0x77, 0x6c,
0xcc, 0xdf, 0x28, 0x43, 0x43, 0xbc, 0x5d, 0xf3, 0x3a, 0x74, 0x7c, 0x8f, 0x02, 0x47, 0x1b, 0x8a,
0xfe, 0x8a, 0xe8, 0x65, 0x2a, 0x9f, 0xee, 0x71, 0x3d, 0x45, 0x2b, 0xc4, 0x12, 0x40, 0xcb, 0x43,
0xd7, 0x00, 0xf8, 0xdb, 0x38, 0x0f, 0xf7, 0xc7, 0x44, 0xa8, 0x73, 0xf2, 0x8a, 0x99, 0x78, 0x4d,
0x87, 0x1d, 0xc6, 0x28, 0xd4, 0x0b, 0x5f, 0x81, 0x83, 0x98, 0x04, 0x63, 0xcf, 0x0d, 0xc8, 0x4f,
0xea, 0xad, 0xfc, 0xdc, 0x57, 0xef, 0x17, 0xbe, 0x57, 0x87, 0x3a, 0x5b, 0x5d, 0x9a, 0x7f, 0x55,
0x97, 0xeb, 0xe0, 0x94, 0x7d, 0x5f, 0x54, 0x2f, 0xfa, 0xa8, 0x86, 0xaa, 0x2d, 0x4c, 0xf5, 0x0b,
0x3e, 0x9f, 0x82, 0xd6, 0xd8, 0xf7, 0x86, 0x3e, 0x5d, 0xcf, 0xd6, 0x12, 0x0f, 0x15, 0xe9, 0x6c,
0xeb, 0x82, 0x0c, 0x4b, 0x06, 0x55, 0xf9, 0xea, 0xba, 0xf2, 0xdd, 0x82, 0xb6, 0xed, 0x7b, 0x63,
0xf6, 0x89, 0xba, 0x38, 0x5c, 0x3b, 0x99, 0x83, 0xbb, 0x12, 0xd1, 0xf5, 0x4a, 0x38, 0x66, 0xa2,
0xea, 0xcb, 0x47, 0x5f, 0x9c, 0x6b, 0xbf, 0x94, 0xc3, 0xce, 0xe5, 0xd5, 0x2b, 0x61, 0x41, 0x4e,
0x19, 0xc9, 0x33, 0xc6, 0xd8, 0x9a, 0xc8, 0xb8, 0xfa, 0x2c, 0x62, 0xe4, 0xe4, 0xe8, 0x3a, 0xb4,
0x02, 0x6b, 0x8f, 0xb0, 0xd7, 0x79, 0xdb, 0x13, 0x87, 0x62, 0x43, 0x90, 0xf5, 0x4a, 0x58, 0xb2,
0xd0, 0x2e, 0xef, 0x38, 0x43, 0xbe, 0x93, 0x14, 0x4f, 0x04, 0xe7, 0x75, 0xf9, 0x7e, 0x44, 0xc7,
0xde, 0x73, 0x8e, 0x12, 0x74, 0xe7, 0xc3, 0x5d, 0xe6, 0x1c, 0x3f, 0x36, 0x66, 0x09, 0x73, 0x0e,
0xda, 0x72, 0x88, 0xcc, 0x96, 0x34, 0x93, 0x16, 0x34, 0x78, 0x0f, 0x4c, 0x80, 0x56, 0xd4, 0x20,
0x4a, 0x2c, 0xc1, 0xcd, 0x35, 0x68, 0x45, 0x42, 0xcb, 0x79, 0x96, 0x02, 0x41, 0xcd, 0xf6, 0xc4,
0x92, 0xa9, 0x8a, 0xd9, 0x7f, 0x2a, 0x54, 0xf5, 0x7d, 0xa3, 0xb6, 0x7c, 0x59, 0x68, 0x61, 0x31,
0xba, 0xaf, 0x44, 0x5d, 0x1b, 0xdf, 0x8c, 0xcf, 0x41, 0x13, 0xef, 0xb2, 0xd5, 0x6c, 0xa7, 0x4c,
0xb3, 0xe9, 0x16, 0xa9, 0x53, 0xa1, 0x5e, 0x72, 0xd9, 0x72, 0x07, 0x64, 0xc4, 0x56, 0x40, 0xd2,
0xf7, 0xd6, 0x96, 0xda, 0x12, 0x7c, 0xe9, 0xf8, 0x5f, 0x7f, 0x78, 0xa2, 0xfc, 0xdd, 0x0f, 0x4f,
0x94, 0x7f, 0xf0, 0xe1, 0x89, 0xf2, 0xaf, 0xff, 0xf0, 0x44, 0xe9, 0xbb, 0x3f, 0x3c, 0x51, 0xfa,
0x87, 0x1f, 0x9e, 0x28, 0x7d, 0x50, 0x19, 0x6f, 0x6e, 0x36, 0xd8, 0x9d, 0x93, 0x4b, 0xff, 0x15,
0x00, 0x00, 0xff, 0xff, 0x16, 0x7e, 0xb6, 0xbe, 0x02, 0x63, 0x00, 0x00,
0xe4, 0xda, 0x8e, 0xe3, 0xd8, 0x0e, 0x82, 0x00, 0x09, 0x92, 0x43, 0x90, 0x04, 0xb9, 0x04, 0x08,
0x12, 0x20, 0x87, 0x20, 0x48, 0x90, 0x4b, 0x72, 0x88, 0x11, 0x20, 0x08, 0xf2, 0x3c, 0xd8, 0xb7,
0x5c, 0x02, 0x1b, 0xf2, 0x25, 0x87, 0xe4, 0xe0, 0x04, 0x08, 0x72, 0x0a, 0x82, 0x7a, 0x74, 0x75,
0x55, 0x3f, 0xa6, 0x67, 0x2c, 0x39, 0x0f, 0xc4, 0xa7, 0x99, 0xaa, 0xfa, 0xff, 0xef, 0xaf, 0xc7,
0xff, 0xff, 0x55, 0xf5, 0x57, 0x75, 0xc1, 0xb1, 0xf1, 0xe6, 0xf9, 0xb1, 0xef, 0x85, 0x5e, 0x70,
0x9e, 0xec, 0x11, 0x37, 0x0c, 0xba, 0x2c, 0x85, 0x9a, 0x96, 0xbb, 0x1f, 0xee, 0x8f, 0x89, 0x79,
0x6a, 0xfc, 0x64, 0x78, 0x7e, 0xe4, 0x6c, 0x9e, 0x1f, 0x6f, 0x9e, 0xdf, 0xf1, 0x6c, 0x32, 0x8a,
0xc8, 0x59, 0x42, 0x90, 0x9b, 0xc7, 0x87, 0x9e, 0x37, 0x1c, 0x11, 0x5e, 0xb6, 0xb9, 0xbb, 0x75,
0x3e, 0x08, 0xfd, 0xdd, 0x41, 0xc8, 0x4b, 0x17, 0xfe, 0xec, 0xdb, 0x65, 0xa8, 0xaf, 0x52, 0x78,
0x74, 0x11, 0x5a, 0x3b, 0x24, 0x08, 0xac, 0x21, 0x09, 0x8c, 0xf2, 0xc9, 0xea, 0xd9, 0xb9, 0x8b,
0xc7, 0xba, 0x42, 0x54, 0x97, 0x51, 0x74, 0xef, 0xf3, 0x62, 0x2c, 0xe9, 0xd0, 0x71, 0x68, 0x0f,
0x3c, 0x37, 0x24, 0xcf, 0xc2, 0xbe, 0x6d, 0x54, 0x4e, 0x96, 0xcf, 0xb6, 0x71, 0x9c, 0x81, 0x2e,
0x43, 0xdb, 0x71, 0x9d, 0xd0, 0xb1, 0x42, 0xcf, 0x37, 0xaa, 0x27, 0xcb, 0x1a, 0x24, 0xab, 0x64,
0x77, 0x71, 0x30, 0xf0, 0x76, 0xdd, 0x10, 0xc7, 0x84, 0xc8, 0x80, 0x66, 0xe8, 0x5b, 0x03, 0xd2,
0xb7, 0x8d, 0x1a, 0x43, 0x8c, 0x92, 0xe6, 0xf7, 0x2f, 0x40, 0x53, 0xd4, 0x01, 0xbd, 0x00, 0xcd,
0x60, 0xcc, 0xa9, 0xbe, 0x55, 0xe6, 0x64, 0x22, 0x8d, 0x6e, 0xc2, 0x9c, 0xc5, 0x61, 0x37, 0xb6,
0xbd, 0xa7, 0x46, 0x99, 0x09, 0x7e, 0x31, 0xd1, 0x16, 0x21, 0xb8, 0x4b, 0x49, 0x7a, 0x25, 0xac,
0x72, 0xa0, 0x3e, 0xcc, 0x8b, 0xe4, 0x0a, 0x09, 0x2d, 0x67, 0x14, 0x18, 0x7f, 0xc3, 0x41, 0x4e,
0xe4, 0x80, 0x08, 0xb2, 0x5e, 0x09, 0x27, 0x18, 0xd1, 0x67, 0xe1, 0x88, 0xc8, 0x59, 0xf6, 0xdc,
0x2d, 0x67, 0xf8, 0x68, 0x6c, 0x5b, 0x21, 0x31, 0xfe, 0x96, 0xe3, 0x9d, 0xca, 0xc1, 0xe3, 0xb4,
0x5d, 0x4e, 0xdc, 0x2b, 0xe1, 0x2c, 0x0c, 0x74, 0x1b, 0x0e, 0x8a, 0x6c, 0x01, 0xfa, 0x77, 0x1c,
0xf4, 0xa5, 0x1c, 0x50, 0x89, 0xa6, 0xb3, 0xa1, 0xcf, 0xc1, 0x51, 0x91, 0x71, 0xcf, 0x71, 0x9f,
0x2c, 0x6f, 0x5b, 0xa3, 0x11, 0x71, 0x87, 0xc4, 0xf8, 0xfb, 0xc9, 0x75, 0xd4, 0x88, 0x7b, 0x25,
0x9c, 0x09, 0x82, 0x1e, 0x40, 0xc7, 0xdb, 0xfc, 0x22, 0x19, 0x44, 0x1d, 0xb2, 0x41, 0x42, 0xa3,
0xc3, 0x70, 0x5f, 0x49, 0xe0, 0x3e, 0x60, 0x64, 0x51, 0x57, 0x76, 0x37, 0x48, 0xd8, 0x2b, 0xe1,
0x14, 0x33, 0x7a, 0x04, 0x48, 0xcb, 0x5b, 0xdc, 0x21, 0xae, 0x6d, 0x5c, 0x64, 0x90, 0xaf, 0x4e,
0x86, 0x64, 0xa4, 0xbd, 0x12, 0xce, 0x00, 0x48, 0xc1, 0x3e, 0x72, 0x03, 0x12, 0x1a, 0x97, 0xa6,
0x81, 0x65, 0xa4, 0x29, 0x58, 0x96, 0x4b, 0xfb, 0x96, 0xe7, 0x62, 0x32, 0xb2, 0x42, 0xc7, 0x73,
0x45, 0x7d, 0x2f, 0x33, 0xe0, 0xd3, 0xd9, 0xc0, 0x92, 0x56, 0xd6, 0x38, 0x13, 0x04, 0xfd, 0x14,
0x3c, 0x97, 0xc8, 0xc7, 0x64, 0xc7, 0xdb, 0x23, 0xc6, 0xdb, 0x0c, 0xfd, 0x4c, 0x11, 0x3a, 0xa7,
0xee, 0x95, 0x70, 0x36, 0x0c, 0x5a, 0x82, 0x03, 0x51, 0x01, 0x83, 0xbd, 0xc2, 0x60, 0x8f, 0xe7,
0xc1, 0x0a, 0x30, 0x8d, 0x87, 0xda, 0x22, 0x4f, 0x2f, 0x8f, 0xbc, 0x80, 0x18, 0x8b, 0x99, 0xb6,
0x28, 0x20, 0x18, 0x09, 0xb5, 0x45, 0x85, 0x43, 0x6d, 0x64, 0x10, 0xfa, 0xce, 0x80, 0x55, 0x90,
0x6a, 0xd1, 0xd5, 0xc9, 0x8d, 0x8c, 0x89, 0x85, 0x2a, 0x65, 0xc3, 0x20, 0x0c, 0x87, 0x82, 0xdd,
0xcd, 0x60, 0xe0, 0x3b, 0x63, 0x9a, 0xb7, 0x68, 0xdb, 0xc6, 0xbb, 0x93, 0x90, 0x37, 0x14, 0xe2,
0xee, 0xa2, 0x4d, 0x47, 0x27, 0x09, 0x80, 0x3e, 0x07, 0x48, 0xcd, 0x12, 0xdd, 0x77, 0x9d, 0xc1,
0x7e, 0x62, 0x0a, 0x58, 0xd9, 0x97, 0x19, 0x30, 0xc8, 0x82, 0xa3, 0x6a, 0xee, 0xba, 0x17, 0x38,
0xf4, 0xd7, 0xb8, 0xc1, 0xe0, 0xdf, 0x98, 0x02, 0x3e, 0x62, 0xa1, 0x8a, 0x95, 0x05, 0x95, 0x14,
0xb1, 0x4c, 0xcd, 0x9a, 0xf8, 0x81, 0x71, 0x73, 0x6a, 0x11, 0x11, 0x4b, 0x52, 0x44, 0x94, 0x9f,
0xec, 0xa2, 0xf7, 0x7c, 0x6f, 0x77, 0x1c, 0x18, 0xb7, 0xa6, 0xee, 0x22, 0xce, 0x90, 0xec, 0x22,
0x9e, 0x8b, 0xae, 0x40, 0x6b, 0x73, 0xe4, 0x0d, 0x9e, 0xd0, 0xc1, 0xac, 0x30, 0x48, 0x23, 0x01,
0xb9, 0x44, 0x8b, 0xc5, 0xf0, 0x49, 0x5a, 0xaa, 0xac, 0xec, 0xff, 0x0a, 0x19, 0x91, 0x90, 0x88,
0x19, 0xeb, 0xc5, 0x4c, 0x56, 0x4e, 0x42, 0x95, 0x55, 0xe1, 0x40, 0x2b, 0x30, 0xb7, 0xe5, 0x8c,
0x48, 0xf0, 0x68, 0x3c, 0xf2, 0x2c, 0x3e, 0x7d, 0xcd, 0x5d, 0x3c, 0x99, 0x09, 0x70, 0x3b, 0xa6,
0xa3, 0x28, 0x0a, 0x1b, 0xba, 0x01, 0xed, 0x1d, 0xcb, 0x7f, 0x12, 0xf4, 0xdd, 0x2d, 0xcf, 0xa8,
0x67, 0x4e, 0x3c, 0x1c, 0xe3, 0x7e, 0x44, 0xd5, 0x2b, 0xe1, 0x98, 0x85, 0x4e, 0x5f, 0xac, 0x52,
0x1b, 0x24, 0xbc, 0xed, 0x90, 0x91, 0x1d, 0x18, 0x0d, 0x06, 0xf2, 0x72, 0x26, 0xc8, 0x06, 0x09,
0xbb, 0x9c, 0x8c, 0x4e, 0x5f, 0x3a, 0x23, 0x7a, 0x1f, 0x8e, 0x44, 0x39, 0xcb, 0xdb, 0xce, 0xc8,
0xf6, 0x89, 0xdb, 0xb7, 0x03, 0xa3, 0x99, 0x39, 0x33, 0xc4, 0x78, 0x0a, 0x2d, 0x9d, 0xbd, 0x32,
0x20, 0xa8, 0x67, 0x8c, 0xb2, 0x55, 0x93, 0x34, 0x5a, 0x99, 0x9e, 0x31, 0x86, 0x56, 0x89, 0xa9,
0x76, 0x65, 0x81, 0x20, 0x1b, 0x9e, 0x8f, 0xf2, 0x97, 0xac, 0xc1, 0x93, 0xa1, 0xef, 0xed, 0xba,
0xf6, 0xb2, 0x37, 0xf2, 0x7c, 0xa3, 0xcd, 0xf0, 0xcf, 0xe6, 0xe2, 0x27, 0xe8, 0x7b, 0x25, 0x9c,
0x07, 0x85, 0x96, 0xe1, 0x40, 0x54, 0xf4, 0x90, 0x3c, 0x0b, 0x0d, 0xc8, 0x9c, 0x7e, 0x63, 0x68,
0x4a, 0x44, 0x1d, 0xa4, 0xca, 0xa4, 0x82, 0x50, 0x95, 0x30, 0xe6, 0x0a, 0x40, 0x28, 0x91, 0x0a,
0x42, 0xd3, 0x2a, 0x08, 0x9d, 0x7e, 0x8d, 0x83, 0x05, 0x20, 0x94, 0x48, 0x05, 0xa1, 0x69, 0x3a,
0x55, 0xcb, 0x96, 0x7a, 0xde, 0x13, 0xaa, 0x4f, 0xc6, 0x7c, 0xe6, 0x54, 0xad, 0xf4, 0x96, 0x20,
0xa4, 0x53, 0x75, 0x92, 0x99, 0x2e, 0x50, 0xa2, 0xbc, 0xc5, 0x91, 0x33, 0x74, 0x8d, 0x43, 0x13,
0x74, 0x99, 0xa2, 0x31, 0x2a, 0xba, 0x40, 0xd1, 0xd8, 0xd0, 0x2d, 0x61, 0x96, 0x1b, 0x24, 0x5c,
0x71, 0xf6, 0x8c, 0xc3, 0x99, 0xd3, 0x50, 0x8c, 0xb2, 0xe2, 0xec, 0x49, 0xbb, 0xe4, 0x2c, 0x6a,
0xd3, 0xa2, 0x49, 0xce, 0x78, 0xae, 0xa0, 0x69, 0x11, 0xa1, 0xda, 0xb4, 0x28, 0x4f, 0x6d, 0xda,
0x3d, 0x2b, 0x24, 0xcf, 0x8c, 0x17, 0x0a, 0x9a, 0xc6, 0xa8, 0xd4, 0xa6, 0xb1, 0x0c, 0x3a, 0xbb,
0x45, 0x19, 0x8f, 0x89, 0x1f, 0x3a, 0x03, 0x6b, 0xc4, 0xbb, 0xea, 0x54, 0xe6, 0x1c, 0x14, 0xe3,
0x69, 0xd4, 0x74, 0x76, 0xcb, 0x84, 0x51, 0x1b, 0xfe, 0xd0, 0xda, 0x1c, 0x11, 0xec, 0x3d, 0x35,
0x4e, 0x17, 0x34, 0x3c, 0x22, 0x54, 0x1b, 0x1e, 0xe5, 0xa9, 0xbe, 0xe5, 0x33, 0x8e, 0x3d, 0x24,
0xa1, 0x71, 0xb6, 0xc0, 0xb7, 0x70, 0x32, 0xd5, 0xb7, 0xf0, 0x1c, 0xe9, 0x01, 0x56, 0xac, 0xd0,
0xda, 0x73, 0xc8, 0xd3, 0xc7, 0x0e, 0x79, 0x4a, 0x27, 0xf6, 0x23, 0x13, 0x3c, 0x40, 0x44, 0xdb,
0x15, 0xc4, 0xd2, 0x03, 0x24, 0x40, 0xa4, 0x07, 0x50, 0xf3, 0x85, 0x5b, 0x3f, 0x3a, 0xc1, 0x03,
0x68, 0xf8, 0xd2, 0xc7, 0xe7, 0x41, 0x21, 0x0b, 0x8e, 0xa5, 0x8a, 0x1e, 0xf8, 0x36, 0xf1, 0x8d,
0x97, 0x98, 0x90, 0xd7, 0x8a, 0x85, 0x30, 0xf2, 0x5e, 0x09, 0xe7, 0x00, 0xa5, 0x44, 0x6c, 0x78,
0xbb, 0xfe, 0x80, 0xd0, 0x7e, 0x7a, 0x75, 0x1a, 0x11, 0x92, 0x3c, 0x25, 0x42, 0x96, 0xa0, 0x3d,
0x78, 0x49, 0x96, 0x50, 0xc1, 0x6c, 0x16, 0x65, 0xd2, 0xc5, 0xc6, 0xe2, 0x0c, 0x93, 0xd4, 0x9d,
0x2c, 0x29, 0xc9, 0xd5, 0x2b, 0xe1, 0xc9, 0xb0, 0x68, 0x1f, 0x4e, 0x68, 0x04, 0x7c, 0x9e, 0x57,
0x05, 0xbf, 0xc6, 0x04, 0x9f, 0x9f, 0x2c, 0x38, 0xc5, 0xd6, 0x2b, 0xe1, 0x02, 0x60, 0x34, 0x86,
0x17, 0xb5, 0xce, 0x88, 0x0c, 0x5b, 0xa8, 0xc8, 0x57, 0x99, 0xdc, 0x73, 0x93, 0xe5, 0xea, 0x3c,
0xbd, 0x12, 0x9e, 0x04, 0x89, 0x86, 0x60, 0x64, 0x16, 0xd3, 0x91, 0xfc, 0x4a, 0xe6, 0xb2, 0x27,
0x47, 0x1c, 0x1f, 0xcb, 0x5c, 0xb0, 0x4c, 0xcd, 0x17, 0xdd, 0xf9, 0xd3, 0xd3, 0x6a, 0xbe, 0xec,
0xc7, 0x3c, 0x28, 0x6d, 0xec, 0x68, 0xd1, 0x43, 0xcb, 0x1f, 0x92, 0x90, 0x77, 0x74, 0xdf, 0xa6,
0x8d, 0xfa, 0xda, 0x34, 0x63, 0x97, 0x62, 0xd3, 0xc6, 0x2e, 0x13, 0x18, 0x05, 0x70, 0x5c, 0xa3,
0xe8, 0x07, 0xcb, 0xde, 0x68, 0x44, 0x06, 0x51, 0x6f, 0xfe, 0x0c, 0x13, 0xfc, 0xe6, 0x64, 0xc1,
0x09, 0xa6, 0x5e, 0x09, 0x4f, 0x04, 0x4d, 0xb5, 0xf7, 0xc1, 0xc8, 0x4e, 0xe8, 0x8c, 0x31, 0x95,
0xae, 0x26, 0xd9, 0x52, 0xed, 0x4d, 0x51, 0xa4, 0x74, 0x55, 0xa1, 0xa0, 0xcd, 0x7d, 0x7e, 0x1a,
0x5d, 0xd5, 0x79, 0x52, 0xba, 0xaa, 0x17, 0xd3, 0xd9, 0x6d, 0x37, 0x20, 0x3e, 0xc3, 0xb8, 0xe3,
0x39, 0xae, 0xf1, 0x72, 0xe6, 0xec, 0xf6, 0x28, 0x20, 0xbe, 0x10, 0x44, 0xa9, 0xe8, 0xec, 0xa6,
0xb1, 0x69, 0x38, 0xf7, 0xc8, 0x56, 0x68, 0x9c, 0x2c, 0xc2, 0xa1, 0x54, 0x1a, 0x0e, 0xcd, 0xa0,
0x33, 0x85, 0xcc, 0xd8, 0x20, 0x74, 0x54, 0xb0, 0xe5, 0x0e, 0x89, 0xf1, 0x4a, 0xe6, 0x4c, 0xa1,
0xc0, 0x29, 0xc4, 0x74, 0xa6, 0xc8, 0x02, 0xa1, 0x3b, 0x7f, 0x99, 0x4f, 0x57, 0x64, 0x1c, 0x7a,
0x21, 0x73, 0xe7, 0xaf, 0x40, 0x4b, 0x52, 0xba, 0x07, 0x49, 0x03, 0xa0, 0x4f, 0x40, 0x6d, 0xec,
0xb8, 0x43, 0xc3, 0x66, 0x40, 0x47, 0x12, 0x40, 0xeb, 0x8e, 0x3b, 0xec, 0x95, 0x30, 0x23, 0x41,
0xef, 0x02, 0x8c, 0x7d, 0x6f, 0x40, 0x82, 0x60, 0x8d, 0x3c, 0x35, 0x08, 0x63, 0x30, 0x93, 0x0c,
0x9c, 0xa0, 0xbb, 0x46, 0xe8, 0xbc, 0xac, 0xd0, 0xa3, 0x55, 0x38, 0x28, 0x52, 0xc2, 0xca, 0xb7,
0x32, 0x17, 0x7f, 0x11, 0x40, 0x1c, 0x05, 0xd2, 0xb8, 0xe8, 0xde, 0x47, 0x64, 0xac, 0x78, 0x2e,
0x31, 0x86, 0x99, 0x7b, 0x9f, 0x08, 0x84, 0x92, 0xd0, 0x35, 0x96, 0xc2, 0x81, 0x96, 0xe0, 0x40,
0xb8, 0xed, 0x13, 0xcb, 0xde, 0x08, 0xad, 0x70, 0x37, 0x30, 0xdc, 0xcc, 0x65, 0x1a, 0x2f, 0xec,
0x3e, 0x64, 0x94, 0x74, 0x09, 0xaa, 0xf2, 0xa0, 0x35, 0xe8, 0xd0, 0x8d, 0xd0, 0x3d, 0x67, 0xc7,
0x09, 0x31, 0xb1, 0x06, 0xdb, 0xc4, 0x36, 0xbc, 0xcc, 0x4d, 0x14, 0x5d, 0xf6, 0x76, 0x55, 0x3a,
0xba, 0x5a, 0x49, 0xf2, 0xa2, 0x1e, 0xcc, 0xd3, 0xbc, 0x8d, 0xb1, 0x35, 0x20, 0x8f, 0x02, 0x6b,
0x48, 0x8c, 0x71, 0xa6, 0x06, 0x32, 0xb4, 0x98, 0x8a, 0x2e, 0x56, 0x74, 0xbe, 0x08, 0xe9, 0x9e,
0x37, 0xb0, 0x46, 0x1c, 0xe9, 0x4b, 0xf9, 0x48, 0x31, 0x55, 0x84, 0x14, 0xe7, 0x68, 0x6d, 0xe4,
0x7d, 0x6f, 0x1b, 0x7b, 0x05, 0x6d, 0x14, 0x74, 0x5a, 0x1b, 0x45, 0x1e, 0xc5, 0x73, 0xbd, 0xd0,
0xd9, 0x72, 0x06, 0xc2, 0x7e, 0x5d, 0xdb, 0xf0, 0x33, 0xf1, 0xd6, 0x14, 0xb2, 0xee, 0x06, 0x8f,
0x2c, 0xa5, 0x78, 0xd1, 0x43, 0x40, 0x6a, 0x9e, 0x50, 0xaa, 0x80, 0x21, 0x2e, 0x4c, 0x42, 0x94,
0x9a, 0x95, 0xc1, 0x4f, 0x6b, 0x39, 0xb6, 0xf6, 0xe9, 0xf6, 0x76, 0xc9, 0xf7, 0x2c, 0x7b, 0x60,
0x05, 0xa1, 0x11, 0x66, 0xd6, 0x72, 0x9d, 0x93, 0x75, 0x25, 0x1d, 0xad, 0x65, 0x92, 0x97, 0xe2,
0xed, 0x90, 0x9d, 0x4d, 0xe2, 0x07, 0xdb, 0xce, 0x58, 0xd4, 0x71, 0x37, 0x13, 0xef, 0xbe, 0x24,
0x8b, 0x6b, 0x98, 0xe2, 0xa5, 0x0b, 0x71, 0x16, 0x3e, 0xde, 0xd8, 0x77, 0x07, 0x5c, 0x19, 0x05,
0xe8, 0xd3, 0xcc, 0x85, 0x38, 0xd3, 0x8c, 0x6e, 0x4c, 0x1c, 0x43, 0x67, 0xc3, 0xa0, 0xbb, 0x70,
0x68, 0x7c, 0x71, 0xac, 0x21, 0x3f, 0xcb, 0x5c, 0x38, 0xaf, 0x5f, 0x5c, 0x4f, 0x42, 0x26, 0x39,
0xa9, 0xa9, 0x39, 0x3b, 0x63, 0xcf, 0x0f, 0x6f, 0x3b, 0xae, 0x13, 0x6c, 0x1b, 0xfb, 0x99, 0xa6,
0xd6, 0x67, 0x24, 0x5d, 0x4e, 0x43, 0x4d, 0x4d, 0xe5, 0x41, 0x97, 0xa1, 0x39, 0xd8, 0xb6, 0xc2,
0x45, 0xdb, 0x36, 0xbe, 0xce, 0x03, 0xbd, 0xcf, 0x27, 0xf8, 0x97, 0xb7, 0xad, 0x50, 0x84, 0x48,
0x22, 0x52, 0x74, 0x1d, 0x80, 0xfe, 0x15, 0x2d, 0xf8, 0xd9, 0x72, 0xa6, 0xaf, 0x62, 0x8c, 0xb2,
0xf6, 0x0a, 0x03, 0x7a, 0x1f, 0x8e, 0xc4, 0x29, 0x6a, 0xa4, 0x7c, 0xcf, 0xff, 0x8d, 0x72, 0xa6,
0xb7, 0x55, 0x70, 0x24, 0x6d, 0xaf, 0x84, 0xb3, 0x20, 0xa2, 0x8a, 0x89, 0xb9, 0xf8, 0x9b, 0x13,
0x2a, 0x26, 0xe7, 0x5d, 0x85, 0x61, 0xa9, 0x09, 0xf5, 0x3d, 0x6b, 0xb4, 0x4b, 0xcc, 0x6f, 0x57,
0xa0, 0x46, 0xc9, 0x4c, 0x02, 0x55, 0xda, 0xe0, 0x79, 0xa8, 0x38, 0xb6, 0xc1, 0x0f, 0x18, 0x2a,
0x8e, 0x8d, 0x0c, 0x68, 0x7a, 0x74, 0x1d, 0x29, 0x8f, 0x3b, 0xa2, 0x24, 0xed, 0x50, 0x71, 0x2c,
0x22, 0x02, 0x47, 0x66, 0xe2, 0xa8, 0x83, 0xc2, 0x46, 0x27, 0x28, 0x11, 0xa9, 0x69, 0x40, 0x43,
0x4c, 0xf3, 0x09, 0x49, 0xe6, 0x1a, 0x34, 0x44, 0xaf, 0x25, 0xeb, 0xa0, 0x48, 0xaa, 0x4c, 0x2f,
0x89, 0xc0, 0xa1, 0x64, 0xa7, 0x25, 0x81, 0x97, 0xa0, 0xed, 0xcb, 0x41, 0xa9, 0x24, 0x62, 0x3c,
0x29, 0xe8, 0xae, 0x04, 0xc2, 0x31, 0x9b, 0xf9, 0x47, 0x75, 0x68, 0x8a, 0x23, 0x02, 0x73, 0x0d,
0x6a, 0xec, 0x3c, 0xe5, 0x28, 0xd4, 0x1d, 0xd7, 0x26, 0xcf, 0x98, 0xa8, 0x3a, 0xe6, 0x09, 0x74,
0x01, 0x9a, 0xe2, 0xc8, 0x40, 0xc8, 0xca, 0x3b, 0x1b, 0x8a, 0xc8, 0xcc, 0x0f, 0xa0, 0x19, 0x9d,
0xab, 0x1c, 0x87, 0xf6, 0xd8, 0xf7, 0xa8, 0x33, 0xec, 0x47, 0x2d, 0x88, 0x33, 0xd0, 0x5b, 0xd0,
0xb4, 0xc5, 0xc9, 0x4d, 0x45, 0xe8, 0x36, 0x3f, 0x05, 0xeb, 0x46, 0xa7, 0x60, 0xdd, 0x0d, 0x76,
0x0a, 0x86, 0x23, 0x3a, 0xf3, 0xeb, 0x65, 0x68, 0xf0, 0xe3, 0x15, 0x73, 0x4f, 0xf6, 0xfc, 0xdb,
0xd0, 0x18, 0xb0, 0x3c, 0x23, 0x79, 0xb4, 0xa2, 0xd5, 0x50, 0x9c, 0xd7, 0x60, 0x41, 0x4c, 0xd9,
0x02, 0x3e, 0x09, 0x56, 0x26, 0xb2, 0x71, 0xa3, 0xc6, 0x82, 0xf8, 0x7f, 0x4c, 0xee, 0x7f, 0x96,
0xe1, 0xa0, 0x7e, 0x6a, 0x73, 0x1c, 0xda, 0x03, 0x79, 0x0e, 0x24, 0x7a, 0x77, 0xa0, 0x9c, 0xe9,
0xc0, 0x60, 0xe4, 0x10, 0x37, 0x64, 0x01, 0xca, 0x4a, 0xe6, 0xba, 0x37, 0xf3, 0x94, 0xa8, 0xbb,
0x2c, 0xd9, 0xb0, 0x02, 0x61, 0x7e, 0x0d, 0x20, 0x2e, 0x41, 0x27, 0xe5, 0x4a, 0x64, 0xcd, 0xda,
0x89, 0xc4, 0xab, 0x59, 0x0a, 0xc5, 0xba, 0x15, 0x6e, 0x0b, 0x43, 0x54, 0xb3, 0xd0, 0x39, 0x38,
0x1c, 0x38, 0x43, 0xd7, 0x0a, 0x77, 0x7d, 0xf2, 0x98, 0xf8, 0xce, 0x96, 0x43, 0x6c, 0x66, 0x96,
0x2d, 0x9c, 0x2e, 0x30, 0x7f, 0xa1, 0x0d, 0x0d, 0xbe, 0xc3, 0x30, 0xff, 0xbd, 0x22, 0x75, 0xcc,
0xfc, 0x8b, 0x32, 0xd4, 0xf9, 0x49, 0x4b, 0xd2, 0x50, 0x6e, 0xab, 0xfa, 0x55, 0xcd, 0x58, 0x7e,
0x67, 0x9d, 0x3c, 0x75, 0xef, 0x92, 0xfd, 0xc7, 0xd4, 0xc9, 0x48, 0xa5, 0x43, 0xc7, 0xa0, 0x11,
0xec, 0x6e, 0xf6, 0xed, 0xc0, 0xa8, 0x9e, 0xac, 0x9e, 0x6d, 0x63, 0x91, 0x32, 0xef, 0x40, 0x2b,
0x22, 0x46, 0x1d, 0xa8, 0x3e, 0x21, 0xfb, 0x42, 0x38, 0xfd, 0x8b, 0xce, 0x09, 0x67, 0x25, 0xcd,
0x26, 0xa9, 0xdb, 0x5c, 0x8a, 0xf0, 0x68, 0x5f, 0x80, 0x2a, 0x5d, 0xd3, 0x27, 0x9b, 0x30, 0xbb,
0x89, 0xe4, 0xd6, 0x76, 0x19, 0xea, 0xfc, 0xb4, 0x2b, 0x29, 0x03, 0x41, 0xed, 0x09, 0xd9, 0xe7,
0x7d, 0xd4, 0xc6, 0xec, 0x7f, 0x2e, 0xc8, 0x9f, 0x57, 0xe1, 0x80, 0x1a, 0xe1, 0x37, 0x57, 0x73,
0x1d, 0xb0, 0xb5, 0x15, 0xaa, 0x0e, 0x58, 0x24, 0xa9, 0x97, 0x61, 0x58, 0x6c, 0x9c, 0xdb, 0x98,
0x27, 0xcc, 0x2e, 0x34, 0xc4, 0xc1, 0x49, 0x12, 0x49, 0xd2, 0x57, 0x54, 0xfa, 0x3b, 0xd0, 0x92,
0xe7, 0x20, 0x1f, 0x55, 0xb6, 0x0f, 0x2d, 0x79, 0xe0, 0x71, 0x14, 0xea, 0xa1, 0x17, 0x5a, 0x23,
0x06, 0x57, 0xc5, 0x3c, 0x41, 0x0d, 0xcd, 0x25, 0xcf, 0xc2, 0x65, 0xe9, 0x05, 0xab, 0x38, 0xce,
0xe0, 0x4e, 0x8e, 0xec, 0xf1, 0xd2, 0x2a, 0x2f, 0x95, 0x19, 0xb1, 0xcc, 0x9a, 0x2a, 0x73, 0x1f,
0x1a, 0xe2, 0x14, 0x44, 0x96, 0x97, 0x95, 0x72, 0xb4, 0x08, 0xf5, 0x21, 0x2d, 0x17, 0xa3, 0xfe,
0x46, 0xc2, 0x45, 0xf0, 0xcd, 0xcd, 0xb2, 0xe7, 0x86, 0x54, 0x8d, 0xf5, 0xe0, 0x0e, 0xe6, 0x9c,
0x74, 0x08, 0x7d, 0x7e, 0xa4, 0xc5, 0x2d, 0x4a, 0xa4, 0xcc, 0xdf, 0x2d, 0x43, 0x5b, 0x9e, 0x21,
0x9a, 0x1f, 0xe4, 0x19, 0xcf, 0x22, 0x1c, 0xf4, 0x05, 0x15, 0xf5, 0x0e, 0x91, 0x09, 0xbd, 0x98,
0xa8, 0x09, 0x56, 0x68, 0xb0, 0xce, 0x61, 0xbe, 0x9b, 0x3b, 0xa8, 0x0b, 0x70, 0x20, 0x22, 0xbd,
0x1b, 0xab, 0x9e, 0x96, 0x67, 0x9a, 0x92, 0xbb, 0x03, 0x55, 0xc7, 0xe6, 0xb7, 0x1d, 0xda, 0x98,
0xfe, 0x35, 0xb7, 0xe0, 0x80, 0x7a, 0x92, 0x60, 0x3e, 0xce, 0xb6, 0x9e, 0x9b, 0x54, 0x8c, 0x72,
0x6a, 0x51, 0x49, 0x6c, 0x97, 0xa2, 0x26, 0xc4, 0x24, 0x58, 0x63, 0x30, 0x9f, 0x87, 0x3a, 0x3f,
0xdf, 0x4c, 0x4e, 0xfb, 0xbf, 0x39, 0x80, 0x3a, 0x1b, 0x04, 0xf3, 0x12, 0x37, 0x80, 0x73, 0xd0,
0x60, 0x7b, 0xf5, 0xe8, 0x52, 0xc6, 0xd1, 0xac, 0x11, 0xc3, 0x82, 0xc6, 0x5c, 0x86, 0x39, 0xe5,
0x64, 0x89, 0x6a, 0x2c, 0x2b, 0x90, 0x5a, 0x10, 0x25, 0x91, 0x09, 0x2d, 0x3a, 0x59, 0x0a, 0x07,
0x4a, 0xdb, 0x2f, 0xd3, 0xe6, 0x29, 0xb9, 0x28, 0x31, 0xc5, 0x49, 0x5a, 0x5f, 0xf6, 0x92, 0x4c,
0x9b, 0x9f, 0x87, 0xb6, 0x3c, 0x80, 0x42, 0x0f, 0xe0, 0x80, 0x38, 0x80, 0xe2, 0xfb, 0x67, 0x4a,
0x3c, 0x5f, 0xa0, 0x5d, 0x74, 0xb3, 0xcc, 0xce, 0xb0, 0xba, 0x0f, 0xf7, 0xc7, 0x04, 0x6b, 0x00,
0xe6, 0xcf, 0x9d, 0x65, 0x3d, 0x6f, 0x8e, 0xa1, 0x25, 0xa3, 0xee, 0xc9, 0x51, 0xb8, 0xca, 0x5d,
0x63, 0xa5, 0xf0, 0xc8, 0x88, 0xf3, 0x53, 0x07, 0xcc, 0x3c, 0xa8, 0xf9, 0x22, 0x54, 0xef, 0x92,
0x7d, 0x6a, 0x21, 0xdc, 0x91, 0x0a, 0x0b, 0xe1, 0x0e, 0xb3, 0x0f, 0x0d, 0x71, 0xfa, 0x95, 0x94,
0x77, 0x1e, 0x1a, 0x5b, 0xfc, 0x40, 0xad, 0xc0, 0x65, 0x0a, 0x32, 0xf3, 0x26, 0xcc, 0xa9, 0x67,
0x5e, 0x49, 0xbc, 0x93, 0x30, 0x37, 0x50, 0x4e, 0xd5, 0xf8, 0x30, 0xa8, 0x59, 0x26, 0xd1, 0xd5,
0x31, 0x85, 0xb0, 0x9a, 0xa9, 0x87, 0xaf, 0x64, 0x76, 0xfb, 0x04, 0x6d, 0xbc, 0x0b, 0x87, 0x92,
0x87, 0x5b, 0x49, 0x49, 0x67, 0xe1, 0xd0, 0x66, 0xe2, 0x28, 0x8d, 0xfb, 0xc0, 0x64, 0xb6, 0xd9,
0x87, 0x3a, 0x3f, 0x7c, 0x48, 0x42, 0x5c, 0x80, 0xba, 0xc5, 0x0e, 0x37, 0x28, 0xe3, 0x7c, 0x6a,
0xd5, 0x2a, 0xce, 0x64, 0x29, 0x05, 0xe6, 0x84, 0xa6, 0x03, 0x07, 0xf5, 0xf3, 0x8c, 0x24, 0x64,
0x0f, 0x0e, 0xee, 0x69, 0xe7, 0x26, 0x1c, 0x7a, 0x21, 0x13, 0x5a, 0x83, 0xc2, 0x3a, 0xa3, 0xf9,
0x8d, 0x06, 0xd4, 0xd8, 0x81, 0x5c, 0x52, 0xc4, 0x15, 0xa8, 0x85, 0xe4, 0x59, 0xb4, 0x46, 0x5d,
0x98, 0x78, 0xba, 0xc7, 0xa3, 0x42, 0x8c, 0x1e, 0x7d, 0x12, 0xea, 0x41, 0xb8, 0x3f, 0x8a, 0x76,
0x03, 0xaf, 0x4e, 0x66, 0xdc, 0xa0, 0xa4, 0x98, 0x73, 0x50, 0x56, 0x66, 0x0b, 0xe2, 0x00, 0xb9,
0x80, 0x95, 0x19, 0x21, 0xe6, 0x1c, 0xe8, 0x26, 0xdd, 0xd6, 0x91, 0xc1, 0x13, 0x62, 0x8b, 0x93,
0xe3, 0xd3, 0x93, 0x99, 0x97, 0x39, 0x31, 0x8e, 0xb8, 0xa8, 0xec, 0x01, 0x1b, 0xdd, 0xc6, 0x34,
0xb2, 0xd9, 0x88, 0x63, 0xce, 0x81, 0x56, 0xa1, 0xed, 0x0c, 0x3c, 0x77, 0x75, 0xc7, 0xfb, 0xa2,
0x23, 0x8e, 0x88, 0x5f, 0x9b, 0xcc, 0xde, 0x8f, 0xc8, 0x71, 0xcc, 0x19, 0xc1, 0xf4, 0x77, 0xe8,
0x06, 0xa7, 0x35, 0x2d, 0x0c, 0x23, 0xc7, 0x31, 0xa7, 0x79, 0x5c, 0x8c, 0x67, 0xb6, 0x91, 0xdf,
0x86, 0x3a, 0xeb, 0x72, 0x74, 0x5d, 0x2d, 0x9e, 0x57, 0x24, 0xe5, 0x7a, 0x2c, 0x31, 0x54, 0x12,
0x87, 0xf5, 0xbf, 0x8e, 0x33, 0x37, 0x0d, 0x8e, 0x18, 0x37, 0x8e, 0xf3, 0x32, 0x34, 0xc5, 0x50,
0xe8, 0x15, 0x6e, 0x45, 0x04, 0x2f, 0x41, 0x9d, 0x1b, 0x66, 0x76, 0x7b, 0x5e, 0x81, 0xb6, 0xec,
0xcc, 0xc9, 0x24, 0xac, 0x77, 0x72, 0x48, 0x7e, 0xbe, 0x02, 0x75, 0x7e, 0x30, 0x99, 0x76, 0xb5,
0xaa, 0x15, 0xbc, 0x3a, 0xf9, 0x9c, 0x53, 0x35, 0x83, 0xdb, 0x6c, 0xa3, 0x46, 0x17, 0xe6, 0xf2,
0x0e, 0xe0, 0xd9, 0x02, 0xee, 0xf5, 0x88, 0x1e, 0xc7, 0xac, 0x05, 0xc3, 0xf9, 0x00, 0xda, 0x92,
0x0b, 0x2d, 0xe9, 0x43, 0x7a, 0x6e, 0xe2, 0x50, 0x24, 0x45, 0x0a, 0xc0, 0x5f, 0x2b, 0x43, 0x75,
0xc5, 0xd9, 0x4b, 0xf5, 0xc3, 0x3b, 0x91, 0x55, 0x17, 0xb9, 0x83, 0x15, 0x67, 0x4f, 0x33, 0x6a,
0x73, 0x35, 0xd2, 0xb8, 0x77, 0xf5, 0xea, 0x9d, 0x99, 0xbc, 0x02, 0x8b, 0x61, 0x78, 0xc5, 0x7e,
0xb9, 0x09, 0x35, 0x76, 0xe6, 0x9f, 0xe5, 0xa7, 0xf6, 0xc7, 0xc5, 0x15, 0x63, 0x51, 0x45, 0x36,
0xe1, 0x32, 0x7a, 0xee, 0xa7, 0xac, 0xb0, 0xd8, 0x4f, 0xf1, 0x20, 0x29, 0x25, 0xc5, 0x9c, 0x83,
0x8a, 0xdc, 0x71, 0x76, 0x88, 0x70, 0x53, 0x05, 0x22, 0xef, 0x3b, 0x3b, 0x04, 0x33, 0x7a, 0xca,
0xb7, 0x6d, 0x05, 0xdb, 0xc2, 0x43, 0x15, 0xf0, 0xf5, 0xac, 0x60, 0x1b, 0x33, 0x7a, 0xca, 0xe7,
0xd2, 0x2d, 0x61, 0x63, 0x1a, 0x3e, 0xba, 0x53, 0xc4, 0x8c, 0x9e, 0xf2, 0x05, 0xce, 0x97, 0x89,
0xf0, 0x49, 0x05, 0x7c, 0x1b, 0xce, 0x97, 0x09, 0x66, 0xf4, 0xb1, 0x0b, 0x6f, 0x4d, 0xd7, 0x35,
0x8a, 0x0b, 0x7f, 0x08, 0xf3, 0xa1, 0x76, 0x72, 0x25, 0x2e, 0x9e, 0x9c, 0x2b, 0x18, 0x17, 0x8d,
0x07, 0x27, 0x30, 0xa8, 0x11, 0xb0, 0x0d, 0x70, 0xb6, 0x11, 0xbc, 0x04, 0xf5, 0xcf, 0x38, 0x76,
0xb8, 0xad, 0x17, 0xd7, 0x35, 0x97, 0x47, 0x87, 0x6d, 0x26, 0x97, 0xa7, 0x8e, 0x3a, 0xc7, 0x59,
0x81, 0x1a, 0x55, 0x9f, 0xd9, 0xf4, 0x38, 0xd6, 0xba, 0x8f, 0xe4, 0x80, 0xd5, 0x8e, 0xe6, 0x38,
0xc7, 0xa1, 0x46, 0x35, 0x24, 0xa7, 0x4b, 0x8e, 0x43, 0x8d, 0xea, 0x5d, 0x7e, 0x29, 0x1d, 0x6d,
0xbd, 0xb4, 0x1a, 0x95, 0x9e, 0x81, 0x79, 0x7d, 0x38, 0x72, 0x50, 0xbe, 0xdd, 0x84, 0x1a, 0xbb,
0x40, 0x93, 0xb4, 0xc8, 0x4f, 0xc3, 0x41, 0x3e, 0x7e, 0x4b, 0x62, 0x09, 0x5e, 0xc9, 0xbc, 0x3f,
0xa7, 0x5f, 0xcb, 0x11, 0x2a, 0x20, 0x58, 0xb0, 0x8e, 0x30, 0xfd, 0xa2, 0x82, 0x41, 0x69, 0x1a,
0xf9, 0xae, 0x5c, 0xbc, 0xd6, 0x0a, 0x6e, 0x6f, 0x31, 0x5e, 0xbe, 0x04, 0x8e, 0x56, 0xb2, 0x68,
0x09, 0x5a, 0x74, 0x6a, 0xa5, 0xdd, 0x25, 0xcc, 0xf6, 0xcc, 0x64, 0xfe, 0xbe, 0xa0, 0xc6, 0x92,
0x8f, 0x4e, 0xec, 0x03, 0xcb, 0xb7, 0x59, 0xad, 0x84, 0x0d, 0xbf, 0x36, 0x19, 0x64, 0x39, 0x22,
0xc7, 0x31, 0x27, 0xba, 0x0b, 0x73, 0x36, 0x91, 0x71, 0x02, 0x61, 0xd4, 0x9f, 0x98, 0x0c, 0xb4,
0x12, 0x33, 0x60, 0x95, 0x9b, 0xd6, 0x29, 0xda, 0x1b, 0x06, 0x85, 0x8b, 0x0d, 0x06, 0x15, 0xdf,
0x92, 0x8d, 0x39, 0xcd, 0xd3, 0x70, 0x50, 0x1b, 0xb7, 0x8f, 0x75, 0xd5, 0xa1, 0x8e, 0x25, 0xc7,
0xb9, 0x2a, 0xb7, 0x28, 0x6f, 0xea, 0xcb, 0x8e, 0xdc, 0x1d, 0x89, 0x60, 0xbc, 0x07, 0xad, 0x68,
0x60, 0xd0, 0x2d, 0xbd, 0x0e, 0xaf, 0x17, 0xd7, 0x41, 0x8e, 0xa9, 0x40, 0x5b, 0x83, 0xb6, 0x1c,
0x21, 0xb4, 0xa8, 0xc3, 0xbd, 0x51, 0x0c, 0x17, 0x8f, 0xae, 0xc0, 0xc3, 0x30, 0xa7, 0x0c, 0x14,
0x5a, 0xd6, 0x11, 0xdf, 0x2c, 0x46, 0x54, 0x87, 0x39, 0x5e, 0xf5, 0xc8, 0x11, 0x53, 0x47, 0xa5,
0x1a, 0x8f, 0xca, 0x1f, 0x36, 0xa1, 0x25, 0x2f, 0xad, 0x65, 0xec, 0x31, 0x77, 0xfd, 0x51, 0xe1,
0x1e, 0x33, 0xe2, 0xef, 0x3e, 0xf2, 0x47, 0x98, 0x72, 0xd0, 0x21, 0x0e, 0x9d, 0x50, 0x9a, 0xea,
0x6b, 0xc5, 0xac, 0x0f, 0x29, 0x39, 0xe6, 0x5c, 0xe8, 0x81, 0xae, 0xe5, 0xb5, 0x09, 0x97, 0x1a,
0x34, 0x90, 0x5c, 0x4d, 0xef, 0x43, 0xdb, 0xa1, 0x4b, 0xbf, 0x5e, 0x3c, 0xf3, 0xbe, 0x51, 0x0c,
0xd7, 0x8f, 0x58, 0x70, 0xcc, 0x4d, 0xeb, 0xb6, 0x65, 0xed, 0x51, 0xbb, 0x66, 0x60, 0x8d, 0x69,
0xeb, 0x76, 0x3b, 0x66, 0xc2, 0x2a, 0x02, 0xba, 0x26, 0xd6, 0x2e, 0xcd, 0x02, 0xcf, 0x12, 0x77,
0x55, 0xbc, 0x7e, 0x79, 0x3f, 0x35, 0xd3, 0x72, 0x33, 0xbe, 0x30, 0x05, 0xca, 0xc4, 0xd9, 0x96,
0x8e, 0x20, 0x5f, 0x19, 0xb5, 0xa7, 0x1d, 0x41, 0x75, 0x75, 0x64, 0xbe, 0x08, 0xd5, 0x47, 0xfe,
0x28, 0x7f, 0xae, 0x66, 0xc3, 0x9d, 0x53, 0xfc, 0xaa, 0x6e, 0x09, 0xf9, 0x0b, 0x7a, 0x39, 0x26,
0xb9, 0x38, 0x4a, 0xa7, 0xe7, 0x10, 0x5d, 0x17, 0x13, 0xfa, 0xdb, 0xba, 0xbd, 0xbd, 0x9c, 0xb0,
0x37, 0x6a, 0x61, 0xeb, 0x3e, 0xe1, 0xf7, 0x76, 0x94, 0x99, 0x7c, 0xda, 0x79, 0xf2, 0x4e, 0xb4,
0xfe, 0x98, 0xc9, 0x53, 0x24, 0xfb, 0x96, 0x63, 0x7d, 0xab, 0x0c, 0x2d, 0x79, 0x27, 0x31, 0x1d,
0x9d, 0x6f, 0x39, 0x41, 0x8f, 0x58, 0x36, 0xf1, 0x85, 0xdd, 0xbe, 0x5e, 0x78, 0xd9, 0xb1, 0xdb,
0x17, 0x1c, 0x58, 0xf2, 0x9a, 0x27, 0xa1, 0x15, 0xe5, 0xe6, 0x6c, 0xca, 0xbe, 0x5f, 0x81, 0x86,
0xb8, 0xcd, 0x98, 0xac, 0xc4, 0x0d, 0x68, 0x8c, 0xac, 0x7d, 0x6f, 0x37, 0xda, 0x32, 0x9d, 0x29,
0xb8, 0x20, 0xd9, 0xbd, 0xc7, 0xa8, 0xb1, 0xe0, 0x42, 0x9f, 0x82, 0xfa, 0xc8, 0xd9, 0x71, 0x42,
0xe1, 0x3e, 0x4e, 0x17, 0xb2, 0xb3, 0x7b, 0x0f, 0x9c, 0x87, 0x0a, 0x67, 0x97, 0x98, 0xa2, 0x2b,
0xe8, 0x85, 0xc2, 0x1f, 0x33, 0x6a, 0x2c, 0xb8, 0xcc, 0x3b, 0xd0, 0xe0, 0xd5, 0x99, 0x6d, 0x92,
0xd0, 0x5b, 0x12, 0x6b, 0x3a, 0xab, 0x5b, 0xce, 0xaa, 0xf4, 0x04, 0x34, 0xb8, 0xf0, 0x1c, 0xad,
0xf9, 0xde, 0x0b, 0x6c, 0xbf, 0x33, 0x32, 0xef, 0xc5, 0x87, 0x7f, 0x1f, 0xfd, 0x2c, 0xc3, 0x7c,
0x08, 0x87, 0x56, 0xac, 0xd0, 0xda, 0xb4, 0x02, 0x82, 0xc9, 0xc0, 0xf3, 0xed, 0x4c, 0x54, 0x9f,
0x17, 0x89, 0x08, 0x75, 0x3e, 0xaa, 0xa0, 0xfb, 0x49, 0xe8, 0xf0, 0x7f, 0x4f, 0xe8, 0xf0, 0x8f,
0x6b, 0x39, 0xf1, 0xbc, 0x69, 0x22, 0x19, 0x54, 0xe1, 0x52, 0x01, 0xbd, 0x6b, 0xfa, 0xda, 0xfb,
0x54, 0x01, 0xa7, 0xb6, 0xf8, 0xbe, 0xa6, 0x47, 0xf4, 0x8a, 0x78, 0xb5, 0x90, 0xde, 0xad, 0x64,
0x48, 0xef, 0x4c, 0x01, 0x77, 0x2a, 0xa6, 0x77, 0x4d, 0x8f, 0xe9, 0x15, 0x49, 0x57, 0x83, 0x7a,
0xff, 0xcf, 0xc2, 0x68, 0xbf, 0x9e, 0x13, 0xf6, 0xf9, 0xa4, 0x1e, 0xf6, 0x99, 0xa0, 0x35, 0x3f,
0xae, 0xb8, 0xcf, 0x6f, 0x34, 0x72, 0xe2, 0x3e, 0x57, 0xb5, 0xb8, 0xcf, 0x84, 0x9a, 0x25, 0x03,
0x3f, 0xd7, 0xf4, 0xc0, 0xcf, 0xa9, 0x02, 0x4e, 0x2d, 0xf2, 0x73, 0x55, 0x8b, 0xfc, 0x14, 0x09,
0x55, 0x42, 0x3f, 0x57, 0xb5, 0xd0, 0x4f, 0x11, 0xa3, 0x12, 0xfb, 0xb9, 0xaa, 0xc5, 0x7e, 0x8a,
0x18, 0x95, 0xe0, 0xcf, 0x55, 0x2d, 0xf8, 0x53, 0xc4, 0xa8, 0x44, 0x7f, 0xae, 0xe9, 0xd1, 0x9f,
0xe2, 0xfe, 0x51, 0x06, 0xfd, 0x27, 0x81, 0x9a, 0xff, 0xc6, 0x40, 0xcd, 0x2f, 0x55, 0x73, 0x02,
0x30, 0x38, 0x3b, 0x00, 0x73, 0x2e, 0x7f, 0x24, 0x8b, 0x23, 0x30, 0xd3, 0xcf, 0x02, 0xe9, 0x10,
0xcc, 0xf5, 0x44, 0x08, 0xe6, 0x74, 0x01, 0xb3, 0x1e, 0x83, 0xf9, 0x3f, 0x13, 0x64, 0xf8, 0xfd,
0xc6, 0x84, 0xfd, 0xf4, 0x3b, 0xea, 0x7e, 0x7a, 0xc2, 0x4c, 0x96, 0xde, 0x50, 0xdf, 0xd0, 0x37,
0xd4, 0x67, 0xa7, 0xe0, 0xd5, 0x76, 0xd4, 0xeb, 0x59, 0x3b, 0xea, 0xee, 0x14, 0x28, 0xb9, 0x5b,
0xea, 0x3b, 0xe9, 0x2d, 0xf5, 0xb9, 0x29, 0xf0, 0x32, 0xf7, 0xd4, 0xeb, 0x59, 0x7b, 0xea, 0x69,
0x6a, 0x97, 0xbb, 0xa9, 0xfe, 0x94, 0xb6, 0xa9, 0x7e, 0x6d, 0x9a, 0xee, 0x8a, 0x27, 0x87, 0xcf,
0xe6, 0xec, 0xaa, 0xdf, 0x9a, 0x06, 0x66, 0x72, 0x10, 0xfb, 0x27, 0xfb, 0x62, 0x5d, 0xcc, 0xef,
0xbd, 0x0c, 0xad, 0xe8, 0xa2, 0x8d, 0xf9, 0x25, 0x68, 0x46, 0x9f, 0xb0, 0x25, 0x2d, 0xe7, 0x98,
0xdc, 0xd4, 0xf1, 0xd5, 0xb3, 0x48, 0xa1, 0x1b, 0x50, 0xa3, 0xff, 0x84, 0x59, 0xbc, 0x3e, 0xdd,
0x85, 0x1e, 0x2a, 0x04, 0x33, 0x3e, 0xf3, 0xdf, 0x8e, 0x02, 0x28, 0x5f, 0xf6, 0x4c, 0x2b, 0xf6,
0x3d, 0xea, 0xcc, 0x46, 0x21, 0xf1, 0xd9, 0x45, 0xae, 0xc2, 0x2f, 0x5f, 0x62, 0x09, 0x54, 0x5b,
0x42, 0xe2, 0x63, 0xc1, 0x8e, 0xee, 0x43, 0x2b, 0x0a, 0xa4, 0x1a, 0x35, 0x06, 0xf5, 0xd6, 0xd4,
0x50, 0x51, 0x68, 0x0f, 0x4b, 0x08, 0xb4, 0x08, 0xb5, 0xc0, 0xf3, 0x43, 0xa3, 0xce, 0xa0, 0xde,
0x9c, 0x1a, 0x6a, 0xc3, 0xf3, 0x43, 0xcc, 0x58, 0x79, 0xd3, 0x94, 0x0f, 0xa7, 0x67, 0x69, 0x9a,
0xe6, 0xb1, 0xff, 0xb5, 0x2a, 0x7d, 0xe8, 0xb2, 0xb0, 0x46, 0xae, 0x43, 0xe7, 0xa7, 0x1f, 0x25,
0xd5, 0x2a, 0x91, 0x58, 0x04, 0xf1, 0x91, 0xe0, 0xeb, 0x9b, 0xd7, 0xa1, 0x33, 0xf0, 0xf6, 0x88,
0x8f, 0xe3, 0x2b, 0x4e, 0xe2, 0x16, 0x5a, 0x2a, 0x1f, 0x99, 0xd0, 0xda, 0x76, 0x6c, 0xd2, 0x1f,
0x08, 0xff, 0xd7, 0xc2, 0x32, 0x8d, 0xee, 0x42, 0x8b, 0xc5, 0xd8, 0xa3, 0x08, 0xff, 0x6c, 0x95,
0xe4, 0xa1, 0xfe, 0x08, 0x80, 0x0a, 0x62, 0xc2, 0x6f, 0x3b, 0x21, 0xeb, 0xc3, 0x16, 0x96, 0x69,
0x5a, 0x61, 0x76, 0x8f, 0x4c, 0xad, 0x70, 0x93, 0x57, 0x38, 0x99, 0x8f, 0x2e, 0xc3, 0x73, 0x2c,
0x2f, 0xb1, 0xc5, 0xe4, 0xa1, 0xfa, 0x16, 0xce, 0x2e, 0x64, 0xf7, 0xe6, 0xac, 0x21, 0xff, 0x4c,
0x82, 0x05, 0xef, 0xea, 0x38, 0xce, 0x40, 0xe7, 0xe0, 0xb0, 0x4d, 0xb6, 0xac, 0xdd, 0x51, 0xf8,
0x90, 0xec, 0x8c, 0x47, 0x56, 0x48, 0xfa, 0x36, 0xfb, 0x76, 0xbb, 0x8d, 0xd3, 0x05, 0xe8, 0x02,
0x1c, 0x11, 0x99, 0xdc, 0x8c, 0xe9, 0x68, 0xf4, 0x6d, 0xf6, 0x29, 0x73, 0x1b, 0x67, 0x15, 0x99,
0xdf, 0xab, 0xd1, 0x41, 0x67, 0xaa, 0xfd, 0x1e, 0x54, 0x2d, 0xdb, 0x16, 0xd3, 0xe6, 0xa5, 0x19,
0x0d, 0x44, 0xdc, 0xbd, 0xa7, 0x08, 0x68, 0x5d, 0x5e, 0xb9, 0xe3, 0x13, 0xe7, 0x95, 0x59, 0xb1,
0xe4, 0x93, 0x12, 0x02, 0x87, 0x22, 0xee, 0xf2, 0x5b, 0xfc, 0xd5, 0x1f, 0x0d, 0x51, 0x5e, 0xf0,
0x17, 0x38, 0xe8, 0x0e, 0xd4, 0x58, 0x0d, 0xf9, 0xc4, 0x7a, 0x79, 0x56, 0xbc, 0xfb, 0xbc, 0x7e,
0x0c, 0xc3, 0x1c, 0xf0, 0xbb, 0x6f, 0xca, 0x85, 0xcb, 0xb2, 0x7e, 0xe1, 0x72, 0x09, 0xea, 0x4e,
0x48, 0x76, 0xd2, 0xf7, 0x6f, 0x27, 0xaa, 0xaa, 0xf0, 0x3c, 0x9c, 0x75, 0xe2, 0x3d, 0xc0, 0x0f,
0x72, 0x6f, 0xdf, 0xdf, 0x82, 0x1a, 0x65, 0x4f, 0xad, 0x25, 0xa7, 0x11, 0xcc, 0x38, 0xcd, 0x8b,
0x50, 0xa3, 0x8d, 0x9d, 0xd0, 0x3a, 0x51, 0x9f, 0x8a, 0xac, 0xcf, 0xd2, 0x1c, 0xb4, 0xbd, 0x31,
0xf1, 0x99, 0x61, 0x98, 0xff, 0x52, 0x53, 0x2e, 0xc5, 0xf5, 0x55, 0x1d, 0x7b, 0x7b, 0x66, 0xcf,
0xa9, 0x6a, 0x19, 0x4e, 0x68, 0xd9, 0x3b, 0xb3, 0xa3, 0xa5, 0xf4, 0x0c, 0x27, 0xf4, 0xec, 0x47,
0xc0, 0x4c, 0x69, 0xda, 0x3d, 0x4d, 0xd3, 0xae, 0xcc, 0x8e, 0xa8, 0xe9, 0x1a, 0x29, 0xd2, 0xb5,
0x15, 0x5d, 0xd7, 0xba, 0xd3, 0x0d, 0xb9, 0x9c, 0x9a, 0xa6, 0xd0, 0xb6, 0xcf, 0xe7, 0x6a, 0xdb,
0x92, 0xa6, 0x6d, 0xb3, 0x8a, 0xfe, 0x98, 0xf4, 0xed, 0xbb, 0x35, 0xa8, 0xd1, 0xe9, 0x11, 0xad,
0xaa, 0xba, 0xf6, 0xd6, 0x4c, 0x53, 0xab, 0xaa, 0x67, 0x6b, 0x09, 0x3d, 0xbb, 0x3c, 0x1b, 0x52,
0x4a, 0xc7, 0xd6, 0x12, 0x3a, 0x36, 0x23, 0x5e, 0x4a, 0xbf, 0x7a, 0x9a, 0x7e, 0x5d, 0x9c, 0x0d,
0x4d, 0xd3, 0x2d, 0xab, 0x48, 0xb7, 0x6e, 0xe9, 0xba, 0x35, 0xe5, 0xea, 0x8d, 0xad, 0x55, 0xa6,
0xd0, 0xab, 0xf7, 0x73, 0xf5, 0xea, 0x86, 0xa6, 0x57, 0xb3, 0x88, 0xfd, 0x98, 0x74, 0xea, 0x32,
0x5f, 0x74, 0x66, 0x7f, 0xfc, 0x94, 0xb7, 0xe8, 0x34, 0xdf, 0x86, 0x76, 0xfc, 0x34, 0x42, 0xc6,
0xf5, 0x7c, 0x4e, 0x16, 0x49, 0x8d, 0x92, 0xe6, 0x25, 0x68, 0xc7, 0xcf, 0x1d, 0x64, 0xc8, 0x0a,
0x58, 0xa1, 0xe0, 0x12, 0x29, 0x73, 0x15, 0x0e, 0xa7, 0x3f, 0xc6, 0xce, 0x88, 0xc3, 0x2b, 0x77,
0xcb, 0xa3, 0x4f, 0x51, 0x94, 0x2c, 0xf3, 0x29, 0xcc, 0x27, 0x3e, 0xaf, 0x9e, 0x19, 0x03, 0x5d,
0x52, 0x96, 0xc8, 0xd5, 0xc4, 0xc7, 0x7a, 0xfa, 0x6d, 0xf9, 0x78, 0x21, 0x6c, 0xae, 0xc0, 0x7c,
0x41, 0xe5, 0xa7, 0xb9, 0x2c, 0xff, 0x05, 0x98, 0x9b, 0x54, 0xf7, 0x8f, 0xe1, 0x32, 0x7f, 0x08,
0x9d, 0xd4, 0xd3, 0x10, 0x49, 0x31, 0xeb, 0x00, 0x43, 0x49, 0x23, 0x94, 0xf6, 0xc2, 0x0c, 0x9f,
0x2e, 0x30, 0x3e, 0xac, 0x60, 0x98, 0xbf, 0x53, 0x86, 0xc3, 0xe9, 0x77, 0x21, 0xa6, 0xdd, 0xfc,
0x18, 0xd0, 0x64, 0x58, 0xf2, 0x8b, 0x8f, 0x28, 0x89, 0xee, 0xc3, 0x81, 0x60, 0xe4, 0x0c, 0xc8,
0xf2, 0xb6, 0xe5, 0x0e, 0x49, 0x20, 0x76, 0x34, 0x05, 0x6f, 0x3b, 0x6c, 0xc4, 0x1c, 0x58, 0x63,
0x37, 0x9f, 0xc2, 0x9c, 0x52, 0x88, 0xde, 0x85, 0x8a, 0x37, 0x4e, 0xdd, 0x6b, 0xcc, 0xc7, 0x7c,
0x10, 0xd9, 0x1b, 0xae, 0x78, 0xe3, 0xb4, 0x49, 0xaa, 0xe6, 0x5b, 0xd5, 0xcc, 0xd7, 0xbc, 0x0b,
0x87, 0xd3, 0x4f, 0x2f, 0x24, 0xbb, 0xe7, 0x4c, 0x2a, 0x4a, 0xc0, 0xbb, 0x29, 0xb9, 0xe5, 0xbf,
0x0a, 0x87, 0x92, 0x0f, 0x2a, 0x64, 0x7c, 0x8d, 0x13, 0x7f, 0xd4, 0x14, 0x85, 0xeb, 0x17, 0x7e,
0xb1, 0x0c, 0xf3, 0x7a, 0x43, 0xd0, 0x31, 0x40, 0x7a, 0xce, 0x9a, 0xe7, 0x92, 0x4e, 0x09, 0x3d,
0x07, 0x87, 0xf5, 0xfc, 0x45, 0xdb, 0xee, 0x94, 0xd3, 0xe4, 0xd4, 0x6d, 0x75, 0x2a, 0xc8, 0x80,
0xa3, 0x89, 0x1e, 0x62, 0x4e, 0xb4, 0x53, 0x45, 0x2f, 0xc0, 0x73, 0xc9, 0x92, 0xf1, 0xc8, 0x1a,
0x90, 0x4e, 0xcd, 0xfc, 0x61, 0x05, 0x6a, 0x8f, 0x02, 0xe2, 0x9b, 0xff, 0x54, 0x89, 0xbe, 0xd2,
0x78, 0x07, 0x6a, 0xec, 0xad, 0x03, 0xe5, 0x6b, 0xc6, 0x72, 0xe2, 0x6b, 0x46, 0xed, 0x8b, 0xb8,
0xf8, 0x6b, 0xc6, 0x77, 0xa0, 0xc6, 0x5e, 0x37, 0x98, 0x9d, 0xf3, 0x9b, 0x65, 0x68, 0xc7, 0x2f,
0x0d, 0xcc, 0xcc, 0xaf, 0x7e, 0x15, 0x52, 0xd1, 0xbf, 0x0a, 0x79, 0x1d, 0xea, 0x3e, 0xfb, 0x7e,
0x83, 0x7b, 0x99, 0xe4, 0xb7, 0x26, 0x4c, 0x20, 0xe6, 0x24, 0x26, 0x81, 0x39, 0xf5, 0x1d, 0x85,
0xd9, 0xab, 0x71, 0x4a, 0x3c, 0xa2, 0xd4, 0xb7, 0x83, 0x45, 0xdf, 0xb7, 0xf6, 0x85, 0x62, 0xea,
0x99, 0xe6, 0x71, 0xa8, 0xad, 0x3b, 0xee, 0x30, 0xfb, 0x23, 0x52, 0xf3, 0x4f, 0xca, 0xd0, 0x14,
0x97, 0x77, 0xcd, 0xab, 0x50, 0x5d, 0x23, 0x4f, 0x69, 0x45, 0xc4, 0xb5, 0xe1, 0x54, 0x45, 0xee,
0xb3, 0x56, 0x08, 0x7a, 0x1c, 0x91, 0x99, 0xd7, 0xe4, 0x34, 0x39, 0x3b, 0xef, 0x3b, 0x50, 0x63,
0xcf, 0x1f, 0xcc, 0xce, 0xf9, 0xa7, 0x2d, 0x68, 0xf0, 0x2f, 0x31, 0xcd, 0x3f, 0x68, 0x41, 0x83,
0x3f, 0x89, 0x80, 0x6e, 0x40, 0x33, 0xd8, 0xdd, 0xd9, 0xb1, 0xfc, 0x7d, 0x23, 0xfb, 0xfd, 0x4d,
0xed, 0x05, 0x85, 0xee, 0x06, 0xa7, 0xc5, 0x11, 0x13, 0x7a, 0x1b, 0x6a, 0x03, 0x6b, 0x8b, 0xa4,
0x8e, 0x73, 0xb3, 0x98, 0x97, 0xad, 0x2d, 0x82, 0x19, 0x39, 0xba, 0x05, 0x2d, 0x31, 0x2c, 0x81,
0x88, 0xe7, 0x4c, 0x96, 0x1b, 0x0d, 0xa6, 0xe4, 0x32, 0xef, 0x40, 0x53, 0x54, 0x06, 0xdd, 0x94,
0xdf, 0xa1, 0x26, 0x23, 0xcf, 0x99, 0x4d, 0x90, 0xdf, 0xca, 0xcb, 0x2f, 0x52, 0xff, 0xb2, 0x02,
0x35, 0x5a, 0xb9, 0x8f, 0x8c, 0x84, 0x4e, 0x00, 0x8c, 0xac, 0x20, 0x5c, 0xdf, 0x1d, 0x8d, 0x88,
0x2d, 0xbe, 0xb0, 0x53, 0x72, 0xd0, 0x59, 0x38, 0xc4, 0x53, 0xc1, 0xf6, 0xc6, 0xee, 0x60, 0x40,
0xe4, 0x67, 0xa2, 0xc9, 0x6c, 0xb4, 0x08, 0x75, 0xf6, 0x48, 0x9f, 0x58, 0x15, 0xbe, 0x51, 0xd8,
0xb3, 0xdd, 0x75, 0xc7, 0x15, 0xb5, 0xe1, 0x9c, 0xa6, 0x07, 0x6d, 0x99, 0x47, 0x8d, 0x70, 0xec,
0xb8, 0xae, 0xe3, 0x0e, 0x85, 0x46, 0x47, 0x49, 0x3a, 0xe9, 0xd0, 0xbf, 0xa2, 0xbe, 0x75, 0x2c,
0x52, 0x34, 0x7f, 0xcb, 0x72, 0x46, 0xa2, 0x8a, 0x75, 0x2c, 0x52, 0x14, 0x69, 0x57, 0x3c, 0x24,
0x51, 0x63, 0x0d, 0x8c, 0x92, 0xe6, 0x87, 0x65, 0xf9, 0x31, 0x76, 0xd6, 0xc7, 0x99, 0xa9, 0x58,
0xd2, 0x71, 0x35, 0xa0, 0xcd, 0x27, 0x04, 0x25, 0x44, 0x7d, 0x0c, 0x1a, 0x9e, 0x3b, 0x72, 0x5c,
0x22, 0x62, 0x47, 0x22, 0x95, 0xe8, 0xe3, 0x7a, 0xaa, 0x8f, 0x45, 0xf9, 0xaa, 0xed, 0xd0, 0x2a,
0x36, 0xe2, 0x72, 0x9e, 0x83, 0xae, 0x43, 0xd3, 0x26, 0x7b, 0xce, 0x80, 0x04, 0x46, 0x93, 0xa9,
0xde, 0xab, 0x13, 0xfb, 0x76, 0x85, 0xd1, 0xe2, 0x88, 0xc7, 0x0c, 0xa1, 0xc1, 0xb3, 0x64, 0x93,
0xca, 0x4a, 0x93, 0xe2, 0x4a, 0x57, 0x26, 0x54, 0xba, 0x5a, 0x50, 0xe9, 0x5a, 0xb2, 0xd2, 0x0b,
0x5f, 0x05, 0x88, 0xd5, 0x0d, 0xcd, 0x41, 0xf3, 0x91, 0xfb, 0xc4, 0xf5, 0x9e, 0xba, 0x9d, 0x12,
0x4d, 0x3c, 0xd8, 0xda, 0xa2, 0x52, 0x3a, 0x65, 0x9a, 0xa0, 0x74, 0x8e, 0x3b, 0xec, 0x54, 0x10,
0x40, 0x83, 0x26, 0x88, 0xdd, 0xa9, 0xd2, 0xff, 0xb7, 0xd9, 0xf8, 0x75, 0x6a, 0xe8, 0x79, 0x38,
0xd2, 0x77, 0x07, 0xde, 0xce, 0xd8, 0x0a, 0x9d, 0xcd, 0x11, 0x79, 0x4c, 0xfc, 0xc0, 0xf1, 0xdc,
0x4e, 0x9d, 0xce, 0x5e, 0x6b, 0x24, 0x7c, 0xea, 0xf9, 0x4f, 0xd6, 0x08, 0xb1, 0xc5, 0xfb, 0x0f,
0x9d, 0x86, 0xf9, 0x1f, 0x65, 0x7e, 0x1a, 0x6c, 0xde, 0x82, 0x03, 0xda, 0x8b, 0x27, 0x46, 0xfc,
0x2c, 0x72, 0xe2, 0x55, 0xe4, 0x63, 0x2c, 0x5e, 0x4b, 0xe2, 0xa5, 0x0c, 0x4f, 0x99, 0xb7, 0x01,
0x94, 0x77, 0x4e, 0x4e, 0x00, 0x6c, 0xee, 0x87, 0x24, 0xe0, 0x6f, 0x9c, 0x50, 0x88, 0x1a, 0x56,
0x72, 0x54, 0xfc, 0x8a, 0x86, 0x6f, 0x5e, 0x01, 0x50, 0x5e, 0x39, 0xa1, 0x76, 0x45, 0x53, 0x4b,
0x49, 0xb0, 0x64, 0xb6, 0xd9, 0x15, 0x2d, 0x88, 0xde, 0x33, 0x89, 0x6a, 0xc0, 0xa3, 0x77, 0x6a,
0x0d, 0x58, 0x8e, 0xb9, 0x0a, 0x10, 0x3f, 0xe9, 0x61, 0x5e, 0x95, 0xae, 0xfb, 0x4d, 0xa8, 0xd9,
0x56, 0x68, 0x09, 0xaf, 0xf9, 0x42, 0x62, 0xe6, 0x8a, 0x59, 0x30, 0x23, 0x33, 0x7f, 0xbb, 0x0c,
0x07, 0xd4, 0xe7, 0x4b, 0xcc, 0xf7, 0xa0, 0xc6, 0xde, 0x3f, 0xb9, 0x09, 0x07, 0xd4, 0xf7, 0x4b,
0x52, 0xcf, 0x47, 0x73, 0x3c, 0x95, 0x15, 0x6b, 0x0c, 0x66, 0x5f, 0x56, 0xe9, 0x23, 0x43, 0x5d,
0x80, 0xa6, 0x78, 0x0e, 0xc5, 0x3c, 0x0d, 0xed, 0xf8, 0xf5, 0x13, 0xea, 0x3b, 0x78, 0x7e, 0x34,
0xca, 0x22, 0x69, 0xfe, 0x73, 0x15, 0xea, 0x6c, 0x38, 0xcd, 0xaf, 0x57, 0x54, 0x0d, 0x35, 0x7f,
0x58, 0xce, 0xdd, 0x0b, 0x5e, 0xd2, 0x9e, 0x0d, 0x98, 0x4f, 0xbd, 0xfa, 0x23, 0x1e, 0x3b, 0xd1,
0x1d, 0xeb, 0x15, 0x68, 0xba, 0x5c, 0x33, 0x99, 0xf1, 0xcc, 0xa7, 0x5f, 0xfa, 0x61, 0x5c, 0x42,
0x7b, 0x71, 0x44, 0x8c, 0x2e, 0x43, 0x9d, 0xf8, 0xbe, 0xe7, 0x33, 0x93, 0x9a, 0x4f, 0xbd, 0x9f,
0x13, 0x3f, 0xac, 0xb2, 0x4a, 0xa9, 0x30, 0x27, 0x46, 0x97, 0xe1, 0xb9, 0x80, 0x5b, 0x11, 0x5f,
0x53, 0x06, 0xe2, 0xbb, 0x6a, 0xe1, 0x6d, 0xb2, 0x0b, 0x17, 0x3e, 0x1d, 0x4d, 0xb0, 0x8a, 0xe1,
0x95, 0x54, 0x8b, 0x2c, 0xa3, 0x36, 0xd4, 0x99, 0xa0, 0x4e, 0x45, 0x35, 0xdb, 0x6a, 0x8e, 0xe1,
0xd5, 0x16, 0x2e, 0x41, 0x53, 0xe4, 0x53, 0xfa, 0x45, 0x5e, 0xf7, 0x4e, 0x09, 0x1d, 0x80, 0xd6,
0x06, 0x19, 0x6d, 0xf5, 0xbc, 0x20, 0xec, 0x94, 0xd1, 0x41, 0x68, 0x33, 0x5b, 0x78, 0xe0, 0x8e,
0xf6, 0x3b, 0x95, 0x85, 0xf7, 0xa1, 0x2d, 0x5b, 0x84, 0x5a, 0x50, 0x5b, 0xdb, 0x1d, 0x8d, 0x3a,
0x25, 0xb6, 0x34, 0x0d, 0x3d, 0x3f, 0x0a, 0x4c, 0xaf, 0x3e, 0xa3, 0xf3, 0x4c, 0xa7, 0x9c, 0xe7,
0x0d, 0x2a, 0xa8, 0x03, 0x07, 0x84, 0x70, 0x5e, 0xe7, 0xaa, 0xf9, 0x8f, 0x65, 0x68, 0xcb, 0x17,
0x63, 0xe8, 0xba, 0x30, 0x1a, 0xe3, 0x7c, 0x3f, 0x70, 0x35, 0x31, 0xda, 0xf9, 0x0f, 0xd0, 0x24,
0x46, 0xfc, 0x0c, 0xcc, 0x0b, 0x97, 0x1b, 0x75, 0x3e, 0xf7, 0x9a, 0x89, 0xdc, 0x85, 0x3b, 0xb2,
0xd7, 0x3b, 0xcc, 0xc4, 0x96, 0x3d, 0xd7, 0x25, 0x83, 0x90, 0xf5, 0xfd, 0x21, 0x98, 0x5b, 0xf3,
0xc2, 0x75, 0x2f, 0x08, 0x68, 0xcb, 0x78, 0x4f, 0xc5, 0xe5, 0x15, 0x34, 0x0f, 0x10, 0xdd, 0x35,
0xa3, 0x4e, 0xd2, 0xfc, 0xad, 0x32, 0x34, 0xf8, 0x3b, 0x36, 0xe6, 0xaf, 0x96, 0xa1, 0x21, 0xde,
0xae, 0x79, 0x1d, 0x3a, 0xbe, 0x47, 0x81, 0xa3, 0x0d, 0x45, 0x7f, 0x45, 0xb4, 0x32, 0x95, 0x4f,
0xf7, 0xb8, 0x9e, 0xa2, 0x15, 0x62, 0x09, 0xa0, 0xe5, 0xa1, 0x6b, 0x00, 0xfc, 0x6d, 0x9c, 0x87,
0xfb, 0x63, 0x22, 0xd4, 0x39, 0x79, 0xc5, 0x4c, 0xbc, 0xa6, 0xc3, 0x0e, 0x63, 0x14, 0xea, 0x85,
0xaf, 0xc0, 0x41, 0x4c, 0x82, 0xb1, 0xe7, 0x06, 0xe4, 0xc7, 0xf5, 0x8c, 0x7e, 0xee, 0x83, 0xf8,
0x0b, 0xdf, 0xad, 0x43, 0x9d, 0xad, 0x2e, 0xcd, 0xbf, 0xaa, 0xcb, 0x75, 0x70, 0xca, 0xbe, 0x2f,
0xaa, 0x17, 0x7d, 0x54, 0x43, 0xd5, 0x16, 0xa6, 0xfa, 0x05, 0x9f, 0x4f, 0x41, 0x6b, 0xec, 0x7b,
0x43, 0x9f, 0xae, 0x67, 0x6b, 0x89, 0x87, 0x8a, 0x74, 0xb6, 0x75, 0x41, 0x86, 0x25, 0x83, 0xaa,
0x7c, 0x75, 0x5d, 0xf9, 0x6e, 0x41, 0xdb, 0xf6, 0xbd, 0x31, 0xfb, 0x44, 0x5d, 0x1c, 0xae, 0x9d,
0xcc, 0xc1, 0x5d, 0x89, 0xe8, 0x7a, 0x25, 0x1c, 0x33, 0x51, 0xf5, 0xe5, 0xbd, 0x2f, 0xce, 0xb5,
0x5f, 0xca, 0x61, 0xe7, 0xe3, 0xd5, 0x2b, 0x61, 0x41, 0x4e, 0x19, 0xc9, 0x33, 0xc6, 0xd8, 0x9a,
0xc8, 0xb8, 0xfa, 0x2c, 0x62, 0xe4, 0xe4, 0xe8, 0x3a, 0xb4, 0x02, 0x6b, 0x8f, 0xb0, 0xd7, 0x79,
0xdb, 0x13, 0xbb, 0x62, 0x43, 0x90, 0xf5, 0x4a, 0x58, 0xb2, 0xd0, 0x26, 0xef, 0x38, 0x43, 0xbe,
0x93, 0x14, 0x4f, 0x04, 0xe7, 0x35, 0xf9, 0x7e, 0x44, 0xc7, 0xde, 0x73, 0x8e, 0x12, 0x74, 0xe7,
0xc3, 0x5d, 0xe6, 0x1c, 0x3f, 0x36, 0x66, 0x09, 0x73, 0x0e, 0xda, 0xb2, 0x8b, 0xcc, 0x96, 0x34,
0x93, 0x16, 0x34, 0x78, 0x0b, 0x4c, 0x80, 0x56, 0x54, 0x21, 0x4a, 0x2c, 0xc1, 0xcd, 0x35, 0x68,
0x45, 0x83, 0x96, 0xf3, 0x2c, 0x05, 0x82, 0x9a, 0xed, 0x89, 0x25, 0x53, 0x15, 0xb3, 0xff, 0x74,
0x50, 0xd5, 0xf7, 0x8d, 0xda, 0xf2, 0x65, 0xa1, 0x85, 0xc5, 0xe8, 0xbe, 0x12, 0x75, 0x6d, 0x7c,
0x33, 0x3e, 0x07, 0x4d, 0xbc, 0xcb, 0x56, 0xb3, 0x9d, 0x32, 0xcd, 0xa6, 0x5b, 0xa4, 0x4e, 0x85,
0x7a, 0xc9, 0x65, 0xcb, 0x1d, 0x90, 0x11, 0x5b, 0x01, 0x49, 0xdf, 0x5b, 0x5b, 0x6a, 0x4b, 0xf0,
0xa5, 0xe3, 0x7f, 0xfd, 0xe1, 0x89, 0xf2, 0x77, 0x3e, 0x3c, 0x51, 0xfe, 0xfe, 0x87, 0x27, 0xca,
0xbf, 0xf2, 0x83, 0x13, 0xa5, 0xef, 0xfc, 0xe0, 0x44, 0xe9, 0x1f, 0x7e, 0x70, 0xa2, 0xf4, 0x41,
0x65, 0xbc, 0xb9, 0xd9, 0x60, 0x77, 0x4e, 0x2e, 0xfd, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9a,
0xe0, 0x31, 0x2b, 0x1d, 0x63, 0x00, 0x00,
}
func (m *Event) Marshal() (dAtA []byte, err error) {
@ -12739,6 +12748,15 @@ func (m *EventMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
}
}
}
if len(m.SpaceId) > 0 {
i -= len(m.SpaceId)
copy(dAtA[i:], m.SpaceId)
i = encodeVarintEvents(dAtA, i, uint64(len(m.SpaceId)))
i--
dAtA[i] = 0x8
i--
dAtA[i] = 0xa2
}
return len(dAtA) - i, nil
}
@ -22709,6 +22727,10 @@ func (m *EventMessage) Size() (n int) {
if m.Value != nil {
n += m.Value.Size()
}
l = len(m.SpaceId)
if l > 0 {
n += 2 + l + sovEvents(uint64(l))
}
return n
}
@ -29778,6 +29800,38 @@ func (m *EventMessage) Unmarshal(dAtA []byte) error {
}
m.Value = &EventMessageValueOfChatDelete{v}
iNdEx = postIndex
case 132:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SpaceId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvents
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthEvents
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SpaceId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 201:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AccountDetails", wireType)

View file

@ -15,6 +15,7 @@ message Event {
string traceId = 4;
message Message {
string spaceId = 132;
oneof value {
Account.Show accountShow = 1;
Account.Details accountDetails = 201;

View file

@ -438,8 +438,8 @@ func (f *ftSearchTantivy) buildObjectQuery(qb *tantivy.QueryBuilder, query strin
func (f *ftSearchTantivy) buildDetailedQuery(qb *tantivy.QueryBuilder, query string) {
if containsChineseCharacters(query) {
qb.BooleanQuery(tantivy.Must, qb.NestedBuilder().
Query(tantivy.Should, fieldTitleZh, query, tantivy.PhrasePrefixQuery, 10.0).
Query(tantivy.Should, fieldTitleZh, query, tantivy.PhraseQuery, 10.0).
Query(tantivy.Should, fieldTitleZh, query, tantivy.PhrasePrefixQuery, 20.0).
Query(tantivy.Should, fieldTitleZh, query, tantivy.PhraseQuery, 20.0).
Query(tantivy.Should, fieldTitleZh, query, tantivy.EveryTermQuery, 0.75).
Query(tantivy.Should, fieldTitleZh, query, tantivy.OneOfTermQuery, 0.5).
Query(tantivy.Should, fieldTextZh, query, tantivy.PhrasePrefixQuery, 1.0).
@ -450,8 +450,8 @@ func (f *ftSearchTantivy) buildDetailedQuery(qb *tantivy.QueryBuilder, query str
)
} else {
qb.BooleanQuery(tantivy.Must, qb.NestedBuilder().
Query(tantivy.Should, fieldTitle, query, tantivy.PhrasePrefixQuery, 10.0).
Query(tantivy.Should, fieldTitle, query, tantivy.PhraseQuery, 10.0).
Query(tantivy.Should, fieldTitle, query, tantivy.PhrasePrefixQuery, 20.0).
Query(tantivy.Should, fieldTitle, query, tantivy.PhraseQuery, 20.0).
Query(tantivy.Should, fieldTitle, query, tantivy.EveryTermQuery, 0.75).
Query(tantivy.Should, fieldTitle, query, tantivy.OneOfTermQuery, 0.5).
Query(tantivy.Should, fieldText, query, tantivy.PhrasePrefixQuery, 1.0).

View file

@ -215,7 +215,7 @@ func (s *dsObjectStore) QueryFromFulltext(results []database.FulltextResult, par
if index != -1 {
from := int32(text2.UTF16RuneCount(titleArr[:index]))
rec.Meta.HighlightRanges = []*model.Range{{
From: int32(text2.UTF16RuneCount(titleArr[:from])),
From: from,
To: from + int32(text2.UTF16RuneCount([]byte(ftsSearch)))}}
rec.Meta.Highlight = title
}

View file

@ -13,6 +13,6 @@ func BuildStateFromAST(root *blockbuilder.Block) *state.State {
Blocks: root.Build(),
},
}).(*state.State)
state.ApplyState(st, true)
state.ApplyState("", st, true)
return st.NewState()
}

View file

@ -6,6 +6,7 @@ import (
"github.com/gogo/protobuf/types"
"github.com/stretchr/testify/assert"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
@ -47,22 +48,20 @@ func TestChange(t *testing.T) {
},
},
},
changeUpdate(&pb.EventMessage{
Value: &pb.EventMessageValueOfBlockSetText{
BlockSetText: &pb.EventBlockSetText{
Id: "text",
Text: &pb.EventBlockSetTextText{
Value: "set text event",
},
Marks: &pb.EventBlockSetTextMarks{Value: &model.BlockContentTextMarks{
Marks: []*model.BlockContentTextMark{{
Param: "https://randomsite.com/kosilica",
Type: model.BlockContentTextMark_Link,
}},
}},
changeUpdate(event.NewMessage("", &pb.EventMessageValueOfBlockSetText{
BlockSetText: &pb.EventBlockSetText{
Id: "text",
Text: &pb.EventBlockSetTextText{
Value: "set text event",
},
Marks: &pb.EventBlockSetTextMarks{Value: &model.BlockContentTextMarks{
Marks: []*model.BlockContentTextMark{{
Param: "https://randomsite.com/kosilica",
Type: model.BlockContentTextMark_Link,
}},
}},
},
}),
})),
},
Snapshot: nil,
FileKeys: nil,

Binary file not shown.