Exemplo 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
}
Exemplo n.º 2
0
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
}
Exemplo n.º 3
0
func (self *Message) EmailTo(c common.SkinnyContext, game *Game, sender *Member, senderUser *user.User, recip *Member, recipUser *user.User, subject, recipName string) {
	mailTag := &MailTag{
		M: self.Id,
		R: recip.Id,
	}
	mailTag.H = mailTag.Hash(c.Secret())
	encodedMailTag, err := mailTag.Encode()
	if err != nil {
		c.Errorf("Failed to encode %+v: %v", mailTag, err)
		return
	}

	unsubTag := &common.UnsubscribeTag{
		T: common.UnsubscribeMessageEmail,
		U: recipUser.Id,
	}
	unsubTag.H = unsubTag.Hash(c.Secret())
	encodedUnsubTag, err := unsubTag.Encode()
	if err != nil {
		c.Errorf("Failed to encode %+v: %v", unsubTag, err)
		return
	}

	parts := strings.Split(c.ReceiveAddress(), "@")
	if len(parts) != 2 {
		if c.Env() == common.Development {
			parts = []string{"user", "host.tld"}
		} else {
			c.Errorf("Failed parsing %#v as an email address", c.ReceiveAddress())
			return
		}
	}
	senderName := sender.ShortName(game, senderUser)
	replyTo := fmt.Sprintf("%v+%v@%v", parts[0], encodedMailTag, parts[1])
	to := fmt.Sprintf("%v <%v>", recipName, recipUser.Email)
	memberIds := []string{}
	for memberId, _ := range self.RecipientIds {
		memberIds = append(memberIds, memberId)
	}
	sort.Sort(sort.StringSlice(memberIds))
	contextLink, err := recipUser.I("To see this message in context: http://%v/games/%v/messages/%v", recipUser.DiplicityHost, self.GameId, self.ChannelId())
	if err != nil {
		c.Errorf("Failed translating context link: %v", err)
		return
	}
	unsubLink, err := recipUser.I("To unsubscribe: http://%v/unsubscribe/%v", recipUser.DiplicityHost, encodedUnsubTag)
	if err != nil {
		c.Errorf("Failed translating unsubscribe link: %v", err)
		return
	}
	body := fmt.Sprintf(common.EmailTemplate, self.Body, contextLink, unsubLink)
	c.SendMail(senderName, replyTo, subject, body, []string{to})
}
Exemplo n.º 4
0
func (self *Phase) SendScheduleEmails(c common.SkinnyContext, game *Game) {
	members, err := game.Members(c.DB())
	for _, member := range members {
		user := &user.User{Id: member.UserId}
		if err = c.DB().Get(user); err != nil {
			return
		}
		to := fmt.Sprintf("%v <%v>", member.Nation, user.Email)
		if !user.PhaseEmailDisabled && !c.IsSubscribing(user.Email, fmt.Sprintf("/games/%v", game.Id)) {
			unsubTag := &common.UnsubscribeTag{
				T: common.UnsubscribePhaseEmail,
				U: user.Id,
			}
			unsubTag.H = unsubTag.Hash(c.Secret())
			encodedUnsubTag, err := unsubTag.Encode()
			if err != nil {
				c.Errorf("Failed to encode %+v: %v", unsubTag, err)
				return
			}
			contextLink, err := user.I("To see this in context: http://%v/games/%v", user.DiplicityHost, self.GameId)
			if err != nil {
				c.Errorf("Failed translating context link: %v", err)
				return
			}
			unsubLink, err := user.I("To unsubscribe: http://%v/unsubscribe/%v", user.DiplicityHost, encodedUnsubTag)
			if err != nil {
				c.Errorf("Failed translating unsubscribe link: %v", err)
				return
			}
			text, err := user.I("A new phase has been created")
			if err != nil {
				c.Errorf("Failed translating: %v", err)
				return
			}
			subject, err := game.Describe(c, user)
			if err != nil {
				c.Errorf("Failed describing: %v", err)
				return
			}
			body := fmt.Sprintf(common.EmailTemplate, text, contextLink, unsubLink)
			c.SendMail("diplicity", c.ReceiveAddress(), subject, body, []string{to})
		}
	}
}
Exemplo 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
}