Esempio n. 1
0
func (self *Phase) SendStartedEmails(c common.SkinnyContext, game *Game) (err error) {
	members, err := game.Members(c.DB())
	if err != nil {
		return
	}
	for _, member := range members {
		user := &user.User{Id: member.UserId}
		if err = c.DB().Get(user); err != nil {
			return
		}
		if !user.PhaseEmailDisabled {
			subKey := fmt.Sprintf("/games/%v", game.Id)
			if !c.IsSubscribing(user.Email, subKey, common.SubscriptionTimeout) {
				if err = self.emailTo(c, game, &member, user); err != nil {
					c.Errorf("Failed sending to %#v: %v", user.Id.String(), err)
					return
				}
			} else {
				c.Infof("Not sending to %#v, already subscribing to %#v", user.Email, subKey)
			}
		} else {
			c.Infof("Not sending to %#v, phase email disabled", user.Email)
		}
	}

	return
}
Esempio n. 2
0
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
}
Esempio n. 3
0
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
}
Esempio n. 4
0
func (self *Phase) autoResolve(c common.SkinnyContext) (err error) {
	c.Infof("Auto resolving %v/%v due to timeout", self.GameId, self.Id)
	if err = c.Transact(func(c common.SkinnyContext) (err error) {
		if err = c.DB().Get(self); err != nil {
			err = fmt.Errorf("While trying to load %+v: %v", self, err)
			return
		}
		if self.Resolved {
			c.Infof("%+v was already resolved", self)
			return
		}
		game := &Game{Id: self.GameId}
		if err = c.DB().Get(game); err != nil {
			err = fmt.Errorf("While trying to load %+v's game: %v", self, err)
			return
		}
		return game.resolve(c, self)
	}); err != nil {
		return
	}
	return
}
Esempio n. 5
0
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
}
Esempio n. 6
0
func (self *Game) endPhaseConsequences(c common.SkinnyContext, phase *Phase, member *Member, opts dip.Options, waitFor, active, nonSurrendering *[]*Member) (err error) {
	surrender := false
	if !member.Committed {
		alreadyHitReliability := false
		if (self.NonCommitConsequences & common.ReliabilityHit) == common.ReliabilityHit {
			if err = member.ReliabilityDelta(c.DB(), -1); err != nil {
				return
			}
			c.Infof("Increased MISSED deadlines for %#v by one because %+v and %+v", string(member.UserId), self, phase)
			alreadyHitReliability = true
		}
		if (self.NonCommitConsequences & common.NoWait) == common.NoWait {
			c.Infof("Setting %#v to NoWait because of %+v and %+v", string(member.UserId), self, phase)
			member.NoWait = true
		}
		if (self.NonCommitConsequences & common.Surrender) == common.Surrender {
			c.Infof("Setting %#v to Surrender because of %+v and %+v", string(member.UserId), self, phase)
			surrender = true
		}
		if len(phase.Orders[member.Nation]) == 0 {
			if !alreadyHitReliability && (self.NMRConsequences&common.ReliabilityHit) == common.ReliabilityHit {
				if err = member.ReliabilityDelta(c.DB(), -1); err != nil {
					return
				}
				c.Infof("Increased MISSED deadlines for %#v by one because %+v and %+v", string(member.UserId), self, phase)
			}
			if (self.NMRConsequences & common.NoWait) == common.NoWait {
				c.Infof("Setting %#v to NoWait because of %+v and %+v", string(member.UserId), self, phase)
				member.NoWait = true
			}
			if (self.NMRConsequences & common.Surrender) == common.Surrender {
				c.Infof("Setting %#v to Surrender because of %+v and %+v", string(member.UserId), self, phase)
				surrender = true
			}
		}
	} else {
		if (self.NonCommitConsequences & common.ReliabilityHit) == common.ReliabilityHit {
			if err = member.ReliabilityDelta(c.DB(), 1); err != nil {
				return
			}
			c.Infof("Increased HELD deadlines for %#v by one because %+v and %+v", string(member.UserId), self, phase)
		}
	}
	if !surrender {
		*nonSurrendering = append(*nonSurrendering, member)
	}
	member.Options = opts
	if member.NoWait {
		member.Committed = false
		member.NoOrders = false
	} else {
		*active = append(*active, member)
		if len(opts) == 0 {
			member.Committed = true
			member.NoOrders = true
		} else {
			*waitFor = append(*waitFor, member)
			member.Committed = false
			member.NoOrders = false
		}
	}
	if err = c.DB().Set(member); err != nil {
		return
	}
	return
}