multi-client but one ntg search, nontrivial config.json change

master
Bel LaPointe 2022-01-11 22:54:18 -05:00
parent 5a4bcecac7
commit e546034c26
8 changed files with 138 additions and 54 deletions

View File

@ -1,6 +1,12 @@
package broker
import "local/truckstop/config"
import (
"local/truckstop/config"
"golang.org/x/time/rate"
)
var limiter = rate.NewLimiter(rate.Limit(0.3), 1)
type Broker interface {
Search([]config.State) ([]Job, error)

View File

@ -3,6 +3,8 @@ package broker
import (
"fmt"
"local/truckstop/config"
"log"
"strings"
"time"
)
@ -37,15 +39,29 @@ func (j JobLocation) String() string {
}
func (j Job) FormatMultilineText() string {
return fmt.Sprintf(
"--- %s: %s => %s ---\nPickup: %s\nDropoff: %s\nNotes: %d lbs, %d miles, %s",
config.Get().Name,
j.Pickup.State,
j.Dropoff.State,
j.Pickup.String(),
j.Dropoff.String(),
j.Weight,
j.Miles,
j.Meta,
)
foo := func(client string) string {
return fmt.Sprintf(
"--- %s: %s => %s ---\nPickup: %s\nDropoff: %s\nNotes: %d lbs, %d miles, %s",
client,
j.Pickup.State,
j.Dropoff.State,
j.Pickup.String(),
j.Dropoff.String(),
j.Weight,
j.Miles,
j.Meta,
)
}
out := ""
clients := config.Get().Clients
for k := range clients {
log.Printf("job multiline: %+v contains %s then use %v", clients[k].States, j.Pickup.State, k)
if strings.Contains(fmt.Sprint(clients[k].States), j.Pickup.State) {
if len(out) > 0 {
out += "\n\n"
}
out += foo(k)
}
}
return out
}

View File

@ -1,23 +1,33 @@
{
"Name": "pa",
"Interval": {
"Input": "10s..30s",
"OK": "6h0m0s..6h0m0s",
"Error": "6h0m0s..6h0m0s"
},
"States": [
"FL",
"GA",
"NC"
],
"Clients": {
"pa": {
"States": [
"OH"
],
"IDs": {
"Matrix": "@belandbroc:matrix.org"
}
},
"caleb": {
"States": [
"OH"
],
"IDs": {
"Matrix": "@belandbroc:matrix.org"
}
}
},
"Storage": [
"map"
],
"Client": "breellocaldev@gmail.com",
"Message": {
"Matrix": {
"ReceiveEnabled": true,
"Client": "@belandbroc:matrix.org",
"Mock": true,
"Homeserver": "https://matrix-client.matrix.org",
"Username": "@breellocaldev:matrix.org",

View File

@ -9,19 +9,21 @@ import (
)
type Config struct {
Name string
Interval struct {
Input Duration
OK Duration
Error Duration
}
States []State
Clients map[string]struct {
States []State
IDs struct {
Matrix string
}
}
Storage []string
Client string
Message struct {
Matrix struct {
ReceiveEnabled bool
Client string
Mock bool
Homeserver string
Username string
@ -54,6 +56,21 @@ func configPath() string {
return p
}
func AllStates() []State {
c := Get()
statem := map[State]struct{}{}
for _, v := range c.Clients {
for _, state := range v.States {
statem[state] = struct{}{}
}
}
states := make([]State, 0, len(statem)+1)
for k := range statem {
states = append(states, k)
}
return states
}
func Refresh() error {
b, err := ioutil.ReadFile(configPath())
if err != nil {

50
main.go
View File

@ -49,39 +49,51 @@ func matrixrecv() error {
if err != nil {
return err
}
states := map[config.State]struct{}{}
states := map[string]map[config.State]struct{}{}
for _, msg := range messages {
if len(states) > 0 {
if _, ok := states[msg.Sender]; ok {
continue
}
for _, state := range parseOutStates([]byte(msg)) {
states[state] = struct{}{}
states[msg.Sender] = map[config.State]struct{}{}
for _, state := range parseOutStates([]byte(msg.Content)) {
states[msg.Sender][state] = struct{}{}
}
}
setNewStates(states)
return nil
}
func setNewStates(states map[config.State]struct{}) {
func setNewStates(states map[string]map[config.State]struct{}) {
if len(states) == 0 {
return
}
newstates := []config.State{}
for k := range states {
newstates = append(newstates, k)
}
sort.Slice(newstates, func(i, j int) bool {
return newstates[i] < newstates[j]
})
conf := *config.Get()
if fmt.Sprint(newstates) == fmt.Sprint(conf.States) {
changed := map[string][]config.State{}
for client, clientStates := range states {
newstates := []config.State{}
for k := range clientStates {
newstates = append(newstates, k)
}
sort.Slice(newstates, func(i, j int) bool {
return newstates[i] < newstates[j]
})
clientconf := conf.Clients[client]
if fmt.Sprint(newstates) == fmt.Sprint(clientconf.States) {
continue
}
clientconf.States = newstates
conf.Clients[client] = clientconf
changed[client] = newstates
}
if len(changed) == 0 {
return
}
conf.States = newstates
log.Printf("updating config new states: %+v", conf)
config.Set(conf)
if err := sendNewStates(conf.States); err != nil {
log.Printf("failed to send new states %+v: %v", conf.States, err)
for client, states := range changed {
if err := sendNewStates(client, states); err != nil {
log.Printf("failed to send new states %s/%+v: %v", client, states, err)
}
}
}
@ -160,7 +172,7 @@ func once() error {
}
func getJobs() ([]broker.Job, error) {
states := config.Get().States
states := config.AllStates()
ntg := broker.NewNTGVision()
if config.Get().Brokers.NTG.Mock {
ntg = ntg.WithMock()
@ -200,7 +212,7 @@ func sendJob(job broker.Job) error {
return sender.Send(job.FormatMultilineText())
}
func sendNewStates(states []config.State) error {
func sendNewStates(client string, states []config.State) error {
sender := message.NewMatrix()
return sender.Send(fmt.Sprintf("now searching for loads from: %+v", states))
return sender.Send(fmt.Sprintf("%s: now searching for loads from: %+v", client, states))
}

View File

@ -13,7 +13,6 @@ type Matrix struct {
username string
token string
room string
client string
}
func NewMatrix() Matrix {
@ -24,7 +23,6 @@ func NewMatrix() Matrix {
token: conf.Token,
room: conf.Room,
mock: conf.Mock,
client: conf.Client,
}
}
@ -32,32 +30,51 @@ func (m Matrix) getclient() (*gomatrix.Client, error) {
return gomatrix.NewClient(m.homeserver, m.username, m.token)
}
func (m Matrix) Receive() ([]string, error) {
func (m Matrix) Receive() ([]Message, error) {
if m.mock {
log.Printf("matrix.Receive()")
return []string{"FL, GA, NC"}, nil
messages := make([]Message, 0)
for k := range config.Get().Clients {
messages = append(messages, Message{Sender: k, Content: "OH"})
}
return messages, nil
}
clients := config.Get().Clients
matrixIDs := map[string]struct{}{}
for k := range clients {
matrixIDs[clients[k].IDs.Matrix] = struct{}{}
}
if len(matrixIDs) == 0 {
return nil, nil
}
c, err := m.getclient()
if err != nil {
return nil, err
}
messages := make([]string, 0)
messages := make([]Message, 0)
result, err := c.Messages(m.room, "", "", 'b', 50)
for _, event := range result.Chunk {
if event.Sender != m.client {
if _, ok := matrixIDs[event.Sender]; !ok {
continue
}
switch event.Type {
case "m.room.message":
b, ok := event.Body()
if ok {
messages = append(messages, b)
messages = append(messages, Message{Sender: event.Sender, Content: b})
}
}
}
if err != nil {
return nil, err
}
for i := range messages {
for k, v := range config.Get().Clients {
if v.IDs.Matrix == messages[i].Sender {
messages[i].Sender = k
}
}
}
return messages, nil
}

View File

@ -2,5 +2,10 @@ package message
type Sender interface {
Send(string) error
Receive() ([]string, error)
Receive() ([]Message, error)
}
type Message struct {
Sender string
Content string
}

View File

@ -1,8 +1,7 @@
todo:
- modify old items once no longer available
- many users -> 1 ntg query
- accept after date
- "caleb: my-usual-stuff" to alias
- modify old items once no longer available; drop stale jobs good candidate but requires new matrix interaction
- "caleb: commands: args"
- rate LIMIT
- more than NTG
- accept pause commands
@ -16,6 +15,8 @@ todo:
- accept states via element for one system
- set up copy for caleb, broc
done:
- many users -> 1 ntg query
- multi client
- rm email
- send matrix msg on config change
- setup pa on element