~edwargix/tallyard

a840e446d8eec05a66731c9d4640976c0602cf9e — David Florness 4 years ago e641e3b
Store entire create event in election
5 files changed, 30 insertions(+), 38 deletions(-)

M election/election.go
M election/map.go
M election/msg.go
M election/voter.go
M ui/tui.go
M election/election.go => election/election.go +14 -21
@@ 11,30 11,22 @@ import (
type Election struct {
	sync.RWMutex

	Candidates        []Candidate           `json:"candidates"`
	CreateEventId     id.EventID            `json:"create_event_id"`
	CreationTimestamp int64                 `json:"creation_timestamp"`
	Creator           id.UserID             `json:"creator"`
	FinalVoters       *[]id.EventID         `json:"final_voters,omitempty"`
	Joins             map[id.EventID]*Voter `json:"joins"`
	LocalVoter        *LocalVoter           `json:"local_voter,omitempty"`
	RoomID            id.RoomID             `json:"room_id"`
	Save              func() error          `json:"-"`
	StartEvt          *event.Event          `json:"start_evt,omitempty"`
	Title             string                `json:"title"`
	Candidates  []Candidate           `json:"candidates"`
	CreateEvt   event.Event           `json:"create_evt"`
	FinalVoters *[]id.EventID         `json:"final_voters,omitempty"`
	Joins       map[id.EventID]*Voter `json:"joins"`
	LocalVoter  *LocalVoter           `json:"local_voter,omitempty"`
	Save        func() error          `json:"-"`
	StartEvt    *event.Event          `json:"start_evt,omitempty"`
	Title       string                `json:"title"`
}

func NewElection(candidates []Candidate, createEventId id.EventID,
	creationTimestamp int64, creator id.UserID, roomID id.RoomID,
	title string) *Election {
func NewElection(candidates []Candidate, createEvt event.Event, title string) *Election {
	return &Election{
		Candidates:        candidates,
		CreateEventId:     createEventId,
		CreationTimestamp: creationTimestamp,
		Creator:           creator,
		Joins:             make(map[id.EventID]*Voter),
		RoomID:            roomID,
		Title:             title,
		Candidates: candidates,
		CreateEvt:  createEvt,
		Joins:      make(map[id.EventID]*Voter),
		Title:      title,
	}
}



@@ 49,6 41,7 @@ func (el *Election) UnmarshalJSON(b []byte) error {
	if el.LocalVoter != nil {
		el.Joins[el.LocalVoter.JoinEvt.ID] = el.LocalVoter.Voter
	}
	el.CreateEvt.Content.ParseRaw(CreateElectionMessage)
	for _, voter := range el.Joins {
		// TODO: for some reason I can't get this to work in (*Voter).UnmarshalJSON
		voter.JoinEvt.Content.ParseRaw(JoinElectionMessage)

M election/map.go => election/map.go +4 -4
@@ 43,7 43,7 @@ type ElectionsMap struct {
	UserID    id.UserID                   `json:"userid"`
}

const electionsMapVersion = 2
const electionsMapVersion = 3

var electionsFname = xdg.DataHome() + "/tallyard/elections.json"



@@ 162,14 162,14 @@ func (em *ElectionsMap) set(createEventID id.EventID, el *Election) {
}

func (em *ElectionsMap) insort(createEventID id.EventID, el *Election) {
	list := em.L[el.RoomID]
	list := em.L[el.CreateEvt.RoomID]
	i := sort.Search(len(list), func(i int) bool {
		return list[i].CreationTimestamp < el.CreationTimestamp
		return list[i].CreateEvt.Timestamp < el.CreateEvt.Timestamp
	})
	newList := make([]*Election, len(list)+1)
	copy(newList[:i], list[:i])
	newList[i] = el
	copy(newList[i+1:], list[i:])
	em.L[el.RoomID] = newList
	em.L[el.CreateEvt.RoomID] = newList
	em.Ltime = time.Now()
}

M election/msg.go => election/msg.go +2 -3
@@ 127,8 127,7 @@ func OnCreateElectionMessage(evt *event.Event, elections *ElectionsMap) {
		log.Warnf("ignoring %s's create since we couldn't cast message content to CreateElectionContent", evt.Sender)
		return
	}
	elections.SetIfNotExists(evt.ID, NewElection(content.Candidates, evt.ID,
		evt.Timestamp, evt.Sender, evt.RoomID, content.Title))
	elections.SetIfNotExists(evt.ID, NewElection(content.Candidates, *evt, content.Title))
}

func OnJoinElectionMessage(client *mautrix.Client, evt *event.Event, elections *ElectionsMap) {


@@ 180,7 179,7 @@ func OnStartElectionMessage(client *mautrix.Client, evt *event.Event, elections 
	}
	el.Lock()
	defer el.Unlock()
	if evt.Sender != el.Creator {
	if evt.Sender != el.CreateEvt.Sender {
		log.Warnf("ignoring %s's start msg since they didn't start the election", evt.Sender)
		return
	}

M election/voter.go => election/voter.go +8 -8
@@ 86,8 86,8 @@ func (el *Election) JoinElection(client *mautrix.Client) error {
	defer el.Save()
	defer el.Unlock()

	resp, err := client.SendMessageEvent(el.RoomID, JoinElectionMessage, JoinElectionContent{
		CreateEventId: el.CreateEventId,
	resp, err := client.SendMessageEvent(el.CreateEvt.RoomID, JoinElectionMessage, JoinElectionContent{
		CreateEventId: el.CreateEvt.ID,
		Input:         base64.StdEncoding.EncodeToString(input.Bytes()),
		NaclPublicKey: base64.StdEncoding.EncodeToString((*pubKey)[:]),
	})


@@ 95,7 95,7 @@ func (el *Election) JoinElection(client *mautrix.Client) error {
		return err
	}

	joinEvt, err := client.GetEvent(el.RoomID, resp.EventID)
	joinEvt, err := client.GetEvent(el.CreateEvt.RoomID, resp.EventID)
	if err != nil {
		return err
	}


@@ 134,14 134,14 @@ func (el *Election) StartElection(client *mautrix.Client) error {
	for _, voter := range userIdMap {
		voters = append(voters, voter.JoinEvt.ID)
	}
	resp, err := client.SendMessageEvent(el.RoomID, StartElectionMessage, StartElectionContent{
		CreateEventId: el.CreateEventId,
	resp, err := client.SendMessageEvent(el.CreateEvt.RoomID, StartElectionMessage, StartElectionContent{
		CreateEventId: el.CreateEvt.ID,
		VoterJoinIds:  voters,
	})
	if err != nil {
		return err
	}
	startEvt, err := client.GetEvent(el.RoomID, resp.EventID)
	startEvt, err := client.GetEvent(el.CreateEvt.RoomID, resp.EventID)
	if err != nil {
		return err
	}


@@ 201,7 201,7 @@ func (el *Election) SendEvals(client *mautrix.Client) error {
		encrypted := box.Seal(nonce[:], output.Bytes(), &nonce, &voter.PubKey, &el.LocalVoter.PrivKey)
		content.Outputs[voter.JoinEvt.ID] = base64.StdEncoding.EncodeToString(encrypted)
	}
	_, err := client.SendMessageEvent(el.RoomID, EvalMessage, content)
	_, err := client.SendMessageEvent(el.CreateEvt.RoomID, EvalMessage, content)
	if err != nil {
		el.LocalVoter.Eval = nil
		return err


@@ 223,7 223,7 @@ func (el *Election) SendSum(client *mautrix.Client) error {
		}(el.Joins[voterJoinId])
	}
	wg.Wait()
	_, err := client.SendMessageEvent(el.RoomID, SumMessage, SumMessageContent{
	_, err := client.SendMessageEvent(el.CreateEvt.RoomID, SumMessage, SumMessageContent{
		JoinEventId: el.LocalVoter.JoinEvt.ID,
		Sum:         base64.StdEncoding.EncodeToString(sum.Bytes()),
	})

M ui/tui.go => ui/tui.go +2 -2
@@ 105,7 105,7 @@ func RoomTUI(client *mautrix.Client, roomID id.RoomID, elections *election.Elect
			if title == "" {
				title = "<no name>"
			}
			list.AddItem(title, fmt.Sprintf("created by %s, ID: %s", el.Creator, el.CreateEventId), 0, nil)
			list.AddItem(title, fmt.Sprintf("created by %s, ID: %s", el.CreateEvt.Sender, el.CreateEvt.ID), 0, nil)
		}
	}
	go func() {


@@ 249,7 249,7 @@ func ElectionWaitTUI(client *mautrix.Client, el *election.Election) error {
	frame.SetTitle(el.Title).SetBorder(true)
	app := newTallyardApplication()
	el.RLock()
	if el.Creator == el.LocalVoter.UserID {
	if el.CreateEvt.Sender == el.LocalVoter.UserID {
		frame.AddText("Press enter to start the election", false, tview.AlignCenter, tcell.ColorWhite)
		app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
			if event.Key() == tcell.KeyEnter {