import.go (4769B)
1 // GoToSocial 2 // Copyright (C) GoToSocial Authors admin@gotosocial.org 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package trans 19 20 import ( 21 "context" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "io" 26 "os" 27 28 "github.com/superseriousbusiness/gotosocial/internal/log" 29 transmodel "github.com/superseriousbusiness/gotosocial/internal/trans/model" 30 ) 31 32 func (i *importer) Import(ctx context.Context, path string) error { 33 if path == "" { 34 return errors.New("Export: path empty") 35 } 36 37 file, err := os.Open(path) 38 if err != nil { 39 return fmt.Errorf("Import: couldn't export to %s: %s", path, err) 40 } 41 42 decoder := json.NewDecoder(file) 43 decoder.UseNumber() 44 45 for { 46 entry := transmodel.Entry{} 47 err := decoder.Decode(&entry) 48 if err != nil { 49 if err == io.EOF { 50 log.Infof(ctx, "reached end of file") 51 return neatClose(file) 52 } 53 return fmt.Errorf("Import: error decoding in readLoop: %s", err) 54 } 55 if err := i.inputEntry(ctx, entry); err != nil { 56 return fmt.Errorf("Import: error inputting entry: %s", err) 57 } 58 } 59 } 60 61 func (i *importer) inputEntry(ctx context.Context, entry transmodel.Entry) error { 62 t, ok := entry[transmodel.TypeKey].(string) 63 if !ok { 64 return errors.New("inputEntry: could not derive entry type: missing or malformed 'type' key in json") 65 } 66 67 switch transmodel.Type(t) { 68 case transmodel.TransAccount: 69 account, err := i.accountDecode(entry) 70 if err != nil { 71 return fmt.Errorf("inputEntry: error decoding entry into account: %s", err) 72 } 73 if err := i.putInDB(ctx, account); err != nil { 74 return fmt.Errorf("inputEntry: error adding account to database: %s", err) 75 } 76 log.Infof(ctx, "added account with id %s", account.ID) 77 return nil 78 case transmodel.TransBlock: 79 block, err := i.blockDecode(entry) 80 if err != nil { 81 return fmt.Errorf("inputEntry: error decoding entry into block: %s", err) 82 } 83 if err := i.putInDB(ctx, block); err != nil { 84 return fmt.Errorf("inputEntry: error adding block to database: %s", err) 85 } 86 log.Infof(ctx, "added block with id %s", block.ID) 87 return nil 88 case transmodel.TransDomainBlock: 89 block, err := i.domainBlockDecode(entry) 90 if err != nil { 91 return fmt.Errorf("inputEntry: error decoding entry into domain block: %s", err) 92 } 93 if err := i.putInDB(ctx, block); err != nil { 94 return fmt.Errorf("inputEntry: error adding domain block to database: %s", err) 95 } 96 log.Infof(ctx, "added domain block with id %s", block.ID) 97 return nil 98 case transmodel.TransFollow: 99 follow, err := i.followDecode(entry) 100 if err != nil { 101 return fmt.Errorf("inputEntry: error decoding entry into follow: %s", err) 102 } 103 if err := i.putInDB(ctx, follow); err != nil { 104 return fmt.Errorf("inputEntry: error adding follow to database: %s", err) 105 } 106 log.Infof(ctx, "added follow with id %s", follow.ID) 107 return nil 108 case transmodel.TransFollowRequest: 109 fr, err := i.followRequestDecode(entry) 110 if err != nil { 111 return fmt.Errorf("inputEntry: error decoding entry into follow request: %s", err) 112 } 113 if err := i.putInDB(ctx, fr); err != nil { 114 return fmt.Errorf("inputEntry: error adding follow request to database: %s", err) 115 } 116 log.Infof(ctx, "added follow request with id %s", fr.ID) 117 return nil 118 case transmodel.TransInstance: 119 inst, err := i.instanceDecode(entry) 120 if err != nil { 121 return fmt.Errorf("inputEntry: error decoding entry into instance: %s", err) 122 } 123 if err := i.putInDB(ctx, inst); err != nil { 124 return fmt.Errorf("inputEntry: error adding instance to database: %s", err) 125 } 126 log.Infof(ctx, "added instance with id %s", inst.ID) 127 return nil 128 case transmodel.TransUser: 129 user, err := i.userDecode(entry) 130 if err != nil { 131 return fmt.Errorf("inputEntry: error decoding entry into user: %s", err) 132 } 133 if err := i.putInDB(ctx, user); err != nil { 134 return fmt.Errorf("inputEntry: error adding user to database: %s", err) 135 } 136 log.Infof(ctx, "added user with id %s", user.ID) 137 return nil 138 } 139 140 log.Errorf(ctx, "didn't recognize transtype '%s', skipping it", t) 141 return nil 142 } 143 144 func (i *importer) putInDB(ctx context.Context, entry interface{}) error { 145 return i.db.Put(ctx, entry) 146 }