|
| 1 | +package main |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "encoding/csv" |
| 6 | + "encoding/json" |
| 7 | + "flag" |
| 8 | + "fmt" |
| 9 | + "os" |
| 10 | + "strings" |
| 11 | + |
| 12 | + "github.com/DIMO-Network/device-definitions-api/internal/contracts" |
| 13 | + "github.com/DIMO-Network/device-definitions-api/internal/core/common" |
| 14 | + "github.com/DIMO-Network/device-definitions-api/internal/core/models" |
| 15 | + "github.com/DIMO-Network/device-definitions-api/internal/infrastructure/gateways" |
| 16 | + "github.com/DIMO-Network/device-definitions-api/internal/infrastructure/sender" |
| 17 | + "github.com/ethereum/go-ethereum/ethclient" |
| 18 | + |
| 19 | + "github.com/DIMO-Network/device-definitions-api/internal/config" |
| 20 | + "github.com/DIMO-Network/shared/pkg/db" |
| 21 | + "github.com/google/subcommands" |
| 22 | + "github.com/rs/zerolog" |
| 23 | +) |
| 24 | + |
| 25 | +type bulkUpdatePowertrain struct { |
| 26 | + logger zerolog.Logger |
| 27 | + settings config.Settings |
| 28 | + |
| 29 | + sender sender.Sender |
| 30 | +} |
| 31 | + |
| 32 | +func (*bulkUpdatePowertrain) Name() string { return "bulk-update-powertrain" } |
| 33 | +func (*bulkUpdatePowertrain) Synopsis() string { |
| 34 | + return "updates definitions from csv file with corresponding definitionId,powertrain pair per row" |
| 35 | +} |
| 36 | +func (*bulkUpdatePowertrain) Usage() string { |
| 37 | + return `bulk-update-powertrain <filename csv>` |
| 38 | +} |
| 39 | + |
| 40 | +func (p *bulkUpdatePowertrain) SetFlags(_ *flag.FlagSet) { |
| 41 | +} |
| 42 | + |
| 43 | +func (p *bulkUpdatePowertrain) Execute(ctx context.Context, _ *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { |
| 44 | + filename := "" |
| 45 | + for _, arg := range os.Args { |
| 46 | + if strings.Contains(arg, ".csv") { |
| 47 | + filename = arg |
| 48 | + } |
| 49 | + } |
| 50 | + file, err := os.Open(filename) |
| 51 | + if err != nil { |
| 52 | + fmt.Printf("Error opening file: %v\n", err) |
| 53 | + return subcommands.ExitFailure |
| 54 | + } |
| 55 | + defer file.Close() |
| 56 | + |
| 57 | + reader := csv.NewReader(file) |
| 58 | + |
| 59 | + records, err := reader.ReadAll() |
| 60 | + if err != nil { |
| 61 | + fmt.Printf("Error reading CSV: %v\n", err) |
| 62 | + return subcommands.ExitFailure |
| 63 | + } |
| 64 | + |
| 65 | + pdb := db.NewDbConnectionFromSettings(ctx, &p.settings.DB, true) |
| 66 | + pdb.WaitForDB(p.logger) |
| 67 | + |
| 68 | + ethClient, err := ethclient.Dial(p.settings.EthereumRPCURL.String()) |
| 69 | + if err != nil { |
| 70 | + p.logger.Fatal().Err(err).Msg("Failed to create Ethereum client.") |
| 71 | + } |
| 72 | + |
| 73 | + chainID, err := ethClient.ChainID(ctx) |
| 74 | + if err != nil { |
| 75 | + p.logger.Fatal().Err(err).Msg("Couldn't retrieve chain id.") |
| 76 | + } |
| 77 | + onChainSvc := gateways.NewDeviceDefinitionOnChainService(&p.settings, &p.logger, ethClient, chainID, p.sender, pdb.DBS) |
| 78 | + |
| 79 | + for i, record := range records { |
| 80 | + if len(record) < 2 { |
| 81 | + fmt.Printf("Skipping malformed line %d: %v\n", i+1, record) |
| 82 | + continue |
| 83 | + } |
| 84 | + definitionID := record[0] |
| 85 | + powertrain := record[1] |
| 86 | + if definitionID == "" || powertrain == "" { |
| 87 | + fmt.Printf("Skipping malformed line %d: %v\n", i+1, record) |
| 88 | + continue |
| 89 | + } |
| 90 | + fmt.Printf("DefinitionID: %s, Powertrain: %s\n", definitionID, powertrain) |
| 91 | + |
| 92 | + deviceDefinition, manufID, err := onChainSvc.GetDefinitionByID(ctx, definitionID) |
| 93 | + if err != nil { |
| 94 | + fmt.Printf("%s: Error getting device definition: %v\n", definitionID, err) |
| 95 | + continue |
| 96 | + } |
| 97 | + |
| 98 | + manufName, err := onChainSvc.GetManufacturerNameByID(ctx, manufID) |
| 99 | + if err != nil { |
| 100 | + fmt.Printf("%s: Error getting manufacturer name: %v\n", manufID, err) |
| 101 | + continue |
| 102 | + } |
| 103 | + set := false |
| 104 | + for i2, attribute := range deviceDefinition.Metadata.DeviceAttributes { |
| 105 | + if attribute.Name == common.PowerTrainType { |
| 106 | + deviceDefinition.Metadata.DeviceAttributes[i2].Value = powertrain |
| 107 | + set = true |
| 108 | + break |
| 109 | + } |
| 110 | + } |
| 111 | + if !set { |
| 112 | + deviceDefinition.Metadata.DeviceAttributes = append(deviceDefinition.Metadata.DeviceAttributes, models.DeviceTypeAttribute{ |
| 113 | + Name: common.PowerTrainType, |
| 114 | + Value: powertrain, |
| 115 | + }) |
| 116 | + } |
| 117 | + md, _ := json.Marshal(deviceDefinition.Metadata) |
| 118 | + |
| 119 | + update, err := onChainSvc.Update(ctx, manufName, contracts.DeviceDefinitionUpdateInput{ |
| 120 | + Id: deviceDefinition.ID, |
| 121 | + Metadata: string(md), |
| 122 | + Ksuid: deviceDefinition.KSUID, |
| 123 | + DeviceType: deviceDefinition.DeviceType, |
| 124 | + ImageURI: deviceDefinition.ImageURI, |
| 125 | + }) |
| 126 | + if err != nil { |
| 127 | + fmt.Printf("%s: Error updating device definition: %v\n", definitionID, err) |
| 128 | + return subcommands.ExitFailure |
| 129 | + } |
| 130 | + fmt.Printf("%s: Updated device definition trx id: %s\n", definitionID, *update) |
| 131 | + } |
| 132 | + |
| 133 | + return subcommands.ExitSuccess |
| 134 | +} |
0 commit comments