コード例 #1
0
ファイル: phase.go プロジェクト: arlm/diplicity
func (self *Phase) Schedule(c common.SkinnyContext) error {
	if !self.Resolved {
		ep, err := epoch.Get(c.DB())
		if err != nil {
			return err
		}
		timeout := self.Deadline - ep
		c.BetweenTransactions(func(c common.SkinnyContext) {
			if timeout > 0 {
				time.AfterFunc(timeout, func() {
					if err := self.autoResolve(c); err != nil {
						c.Errorf("Failed resolving %+v after %v: %v", self, timeout, err)
					}
				})
				c.Debugf("Scheduled resolution of %v/%v in %v at %v", self.GameId, self.Id, timeout, time.Now().Add(timeout))
			} else {
				c.Debugf("Resolving %v/%v immediately, it is %v overdue", self.GameId, self.Id, -timeout)
				if err := self.autoResolve(c); err != nil {
					c.Errorf("Failed resolving %+v immediately: %v", self, err)
				}
			}
		})
	}
	return nil
}
コード例 #2
0
ファイル: message.go プロジェクト: JorenC/diplicity
func IncomingMail(c common.SkinnyContext, msg *enmime.MIMEBody) (err error) {
	text := gmail.DecodeText(msg.Text, msg.GetHeader("Content-Type"))
	c.Debugf("Incoming mail to %#v\n%v", msg.GetHeader("To"), text)
	if match := gmail.AddrReg.FindString(msg.GetHeader("To")); match != "" {
		lines := []string{}
		mailUser := strings.Split(c.SendAddress(), "@")[0]
		for _, line := range strings.Split(text, "\n") {
			if !strings.Contains(line, mailUser) && strings.Index(line, ">") != 0 {
				lines = append(lines, line)
			}
		}
		for len(lines) > 0 && strings.TrimSpace(lines[0]) == "" {
			lines = lines[1:]
		}
		for len(lines) > 0 && strings.TrimSpace(lines[len(lines)-1]) == "" {
			lines = lines[:len(lines)-1]
		}
		if len(lines) > 0 {
			if match2 := emailPlusReg.FindStringSubmatch(match); match2 != nil {
				var tag *MailTag
				if tag, err = DecodeMailTag(c.Secret(), match2[1]); err == nil {
					sender := &Member{Id: tag.R}
					if err = c.DB().Get(sender); err != nil {
						return
					}
					parent := &Message{Id: tag.M}
					if err = c.DB().Get(parent); err != nil {
						return
					}
					game := &Game{Id: parent.GameId}
					if err = c.DB().Get(game); err != nil {
						return
					}
					message := &Message{
						Body:         strings.TrimSpace(strings.Join(lines, "\n")),
						GameId:       game.Id,
						RecipientIds: parent.RecipientIds,
					}
					c.Infof("Mail resulted in %+v from %+v", message, sender.Nation)
					return message.Send(c, game, sender)
				}
			}
		}
	}
	return nil
}
コード例 #3
0
ファイル: epoch.go プロジェクト: arlm/diplicity
func Start(c common.SkinnyContext) (err error) {
	startedAt, err := Get(c.DB())
	if err != nil {
		return
	}
	c.Infof("Started at epoch %v", startedAt)
	startedTime := time.Now()
	var currently time.Duration
	go func() {
		for {
			time.Sleep(time.Minute)
			currently = time.Now().Sub(startedTime) + startedAt
			atomic.StoreInt64(&deltaPoint, int64(time.Now().UnixNano()))
			if err = Set(c.DB(), currently); err != nil {
				panic(err)
			}
			c.Debugf("Epoch %v", currently)
		}
	}()
	return
}
コード例 #4
0
ファイル: message.go プロジェクト: JorenC/diplicity
func (self *Message) Send(c common.SkinnyContext, game *Game, sender *Member) (err error) {
	c.Debugf("Sending %#v from %#v in %#v", self.Body, sender.Nation, game.Id.String())
	// make sure the sender is correct
	self.SenderId = sender.Id

	senderUser := &user.User{Id: sender.UserId}
	if err = c.DB().Get(senderUser); err != nil {
		return
	}

	// make sure the sender is one of the recipients
	self.RecipientIds[sender.Id.String()] = true

	// The sender but nobody else saw it...
	self.SeenBy = map[string]bool{
		sender.Id.String(): true,
	}

	// See what phase type the game is in
	var phaseType dip.PhaseType
	switch game.State {
	case common.GameStateCreated:
		phaseType = common.BeforeGamePhaseType
	case common.GameStateStarted:
		var phase *Phase
		if _, phase, err = game.Phase(c.DB(), 0); err != nil {
			return
		}
		phaseType = phase.Type
	case common.GameStateEnded:
		phaseType = common.AfterGamePhaseType
	default:
		err = fmt.Errorf("Unknown game state for %+v", game)
		return
	}

	// Find what chats are allowed during this phase type
	allowedFlags := game.ChatFlags[phaseType]

	// See if the recipient count is allowed
	recipients := len(self.RecipientIds)
	if recipients == 2 {
		if (allowedFlags & common.ChatPrivate) == 0 {
			err = IllegalMessageError{
				Description: fmt.Sprintf("%+v does not allow %+v during %+v", game, self, phaseType),
				Phrase:      "This kind of message is not allowed at this stage of the game",
			}
			return
		}
	} else if recipients == len(common.VariantMap[game.Variant].Nations) {
		if (allowedFlags & common.ChatConference) == 0 {
			err = IllegalMessageError{
				Description: fmt.Sprintf("%+v does not allow %+v during %+v", game, self, phaseType),
				Phrase:      "This kind of message is not allowed at this stage of the game",
			}
			return
		}
	} else if recipients > 2 {
		if (allowedFlags & common.ChatGroup) == 0 {
			err = IllegalMessageError{
				Description: fmt.Sprintf("%+v does not allow %+v during %+v", game, self, phaseType),
				Phrase:      "This kind of message is not allowed at this stage of the game",
			}
			return
		}
	} else {
		err = fmt.Errorf("%+v doesn't have any recipients", self)
		return
	}

	members, err := game.Members(c.DB())
	if err != nil {
		return
	}
	if err = c.DB().Set(self); err != nil {
		return
	}

	recipNations := sort.StringSlice{}
	for memberId, _ := range self.RecipientIds {
		for _, member := range members {
			if memberId == member.Id.String() {
				if member.Nation != "" {
					recipNations = append(recipNations, string(member.Nation))
				}
			}
		}
	}
	sort.Sort(recipNations)
	recipName := strings.Join(recipNations, ", ")
	subKey := fmt.Sprintf("/games/%v/messages", game.Id)
	for memberId, _ := range self.RecipientIds {
		for _, member := range members {
			if memberId == member.Id.String() && self.SenderId.String() != memberId {
				user := &user.User{Id: member.UserId}
				if err = c.DB().Get(user); err == nil {
					if !user.MessageEmailDisabled {
						if !c.IsSubscribing(user.Email, subKey) {
							memberCopy := member
							gameDescription := ""
							if gameDescription, err = game.Describe(c, user); err == nil {
								go self.EmailTo(c, game, sender, senderUser, &memberCopy, user, gameDescription, recipName)
							} else {
								c.Errorf("Trying to describe %+v to %+v: %v", game, user, err)
							}
						} else {
							c.Infof("Not sending to %#v, already subscribing to %#v", user.Id.String(), subKey)
						}
					} else {
						c.Infof("Not sending to %#v, message email disabled", user.Id.String())
					}
				} else {
					c.Errorf("Trying to load user %#v: %v", member.UserId.String(), err)
				}
			}
		}
	}

	return
}