public static PostHandlerOutput[] PCNarration( IDocumentSession documentSession, IMember sender, IRoom room, string source) { documentSession.Ensure("documentSession"); sender.Ensure("sender"); room.Ensure("room"); source.Ensure("source"); source = source.Trim(); if (source.StartsWith("/", StringComparison.OrdinalIgnoreCase)) return null; if (!sender.IsRoomPlayer(room)) return null; var player = room.Players.SingleOrDefault(x => x.MemberId == sender.Id); if (player == null) return null; var text = string.Concat( player.CharacterName, ": ", source); documentSession.CreatePost(room.Id, sender.Id, null, source, "pc-narration", text); return PostHandlerOutput.Empty; }
public static PostHandlerOutput[] RollCommand( IDocumentSession documentSession, IMember sender, IRoom room, string source) { documentSession.Ensure("documentSession"); sender.Ensure("sender"); room.Ensure("room"); source.Ensure("source"); var match = rollCommandRegex.Match(source); if (!match.Success) return null; var number = int.Parse(match.Groups[1].Value); var sides = int.Parse(match.Groups[2].Value); var diceRolled = string.Join( ", ", fn.RollDice(number, sides).ToArray()); var text = string.Format( CultureInfo.CurrentUICulture, "{0} rolled {1}d{2} with the result: {3}.", sender.Alias, number, sides, diceRolled); documentSession.CreatePost(room.Id, sender.Id, null, source, "roll-result", text); return PostHandlerOutput.Empty; }
public static PostHandlerOutput[] OOCMessage( IDocumentSession documentSession, IMember sender, IRoom room, string source) { documentSession.Ensure("documentSession"); sender.Ensure("sender"); room.Ensure("room"); source.Ensure("source"); var match = oocMessageRegex.Match(source); if (!match.Success) return null; var message = match.Groups[1].Value; var text = string.Concat( "(( ", sender.Alias, ": ", message, " ))"); documentSession.CreatePost(room.Id, sender.Id, sender.EmailAddress.GravatarUrl(), source, "ooc-message", text); return PostHandlerOutput.Empty; }
public static PostHandlerOutput[] GMNarration( IDocumentSession documentSession, IMember sender, IRoom room, string source) { documentSession.Ensure("documentSession"); sender.Ensure("sender"); room.Ensure("room"); source.Ensure("source"); if (!sender.IsRoomOwner(room)) return null; source = source.Trim(); if (source.StartsWith("/", StringComparison.OrdinalIgnoreCase)) return null; var text = string.Concat( "GM: ", source); documentSession.CreatePost(room.Id, sender.Id, null, source, "gm-narration", text); return PostHandlerOutput.Empty; }
static object GetRoom( NancyContext context, IDocumentSession documentSession, string slug) { context.Ensure("context"); documentSession.Ensure("documentSession"); if (string.IsNullOrEmpty(slug)) return 404; if (!context.IsSignedUp()) return 403; var room = documentSession.GetRoomBySlug(slug); if (room == null) return 404; var currentMember = context.GetCurrentMember(documentSession); Debug.Assert(currentMember != null, "`requireSignedUp()` should ensure a current member."); var posts = documentSession.GetPostsByRoom(room.Id).ToArray(); return new RoomResponse(currentMember, room, posts); }
public static PostHandlerOutput[] HandlePost( IDocumentSession documentSession, IMember sender, IRoom room, string source) { documentSession.Ensure("documentSession"); sender.Ensure("sender"); room.Ensure("room"); source.Ensure("source"); if (_postHandlers == null) throw new InvalidOperationException("Post handlers haven't been set yet."); if (!CanPost(room, sender)) { throw new InvalidOperationException( String.Format( CultureInfo.InvariantCulture, "Member '{0}' cannot post to room '{1}'.", sender.Id, room.Id)); } return _postHandlers .Select(slashCommand => slashCommand( documentSession, sender, room, source)) .FirstOrDefault(result => result != null); }
public static PostHandlerOutput[] InvitationsCommand( IDocumentSession documentSession, IMember sender, IRoom room, string source) { documentSession.Ensure("documentSession"); sender.Ensure("sender"); room.Ensure("sender"); source.Ensure("source"); var match = invitationsRegex.Match(source); if (!match.Success) return null; if (!sender.IsRoomOwner(room)) return new[] { new PostHandlerOutput { message = "Only the room's owner can view unused invitations.", type= "error" } }; var invitations = documentSession.GetInvitationsByRoom(room.Id) .ToArray(); if (invitations.Length == 0) return new[] { new PostHandlerOutput { message = "There are no unused invitations.", type = "system" } }; var buffer = new StringBuilder(); buffer.AppendLine("Unused invitations:"); foreach (var invitation in invitations) { buffer.AppendFormat("- {0}?invitation-code={1}", fn.MakeAbsoluteUri(Paths.AcceptInvitationForm()), invitation.Code); buffer.AppendLine(); } return new[] { new PostHandlerOutput { message = buffer.ToString(), type = "system" } }; }
static object GetSignUpForm( NancyContext context, IDocumentSession documentSession) { context.Ensure("context"); documentSession.Ensure("documentSession"); if (!context.IsSignedIn()) return 403; var currentMember = context.GetCurrentMember(documentSession); if (currentMember != null) return 403; return new SignUpFormResponse(); }
public static PostHandlerOutput[] NPCDialogue( IDocumentSession documentSession, IMember sender, IRoom room, string source) { documentSession.Ensure("documentSession"); sender.Ensure("sender"); room.Ensure("room"); source.Ensure("source"); source = source.Trim(); var match = npcDialogueRegex.Match(source); if (!match.Success) return null; if (!sender.IsRoomOwner(room)) return new[] { new PostHandlerOutput { message = "Only the room's owner can speak as an NPC.", type= "error" } }; var npc = match.Groups[1].Value; var dialogue = match.Groups[2].Value.Trim(); if (!dialogue.StartsWith("\"", StringComparison.OrdinalIgnoreCase)) dialogue = String.Concat("\"", dialogue); if (!dialogue.EndsWith("\"", StringComparison.OrdinalIgnoreCase)) dialogue = String.Concat(dialogue, "\""); var text = string.Concat( npc, ": ", dialogue); documentSession.CreatePost(room.Id, sender.Id, null, source, "npc-dialogue", text); return PostHandlerOutput.Empty; }
public static object PostMember( NancyContext context, IDocumentSession documentSession, string alias, string emailAddress) { context.Ensure("context"); documentSession.Ensure("documentSession"); if (!context.IsSignedIn()) return 403; var errors = new List<string>(); errors.AddRange(fn.ValidateRequired("Alias", alias)); errors.AddRange(fn.ValidateLength("Alias", alias, 32)); errors.AddRange(fn.ValidateFormat("Alias", alias, new Regex("[a-z][a-z0-9_-]+"))); errors.AddRange(fn.ValidateRequired("Email Address", emailAddress)); errors.AddRange(fn.ValidateLength("Email Address", emailAddress, 1024)); var member = documentSession.GetMemberByAlias(alias); if (member != null) errors.Add(Strings.AliasNotAvailable(alias)); if (errors.Count > 0) return context.ModelWithStatus(new SignUpFormResponse(alias, emailAddress, errors), 400); var authType = context.ReadSession<string>(Constants.AuthTypeSessionKey); var authId = context.ReadSession<string>(Constants.AuthIdSessionKey); if (String.IsNullOrEmpty(authType)) throw new InvalidOperationException(Strings.AuthTypeMissing()); if (String.IsNullOrEmpty(authId)) throw new InvalidOperationException(Strings.AuthIdMissing()); member = documentSession.CreateMember(authType, authId, alias, emailAddress); var returnUrl = context.GetReturnUrl(); return context.Redirect(returnUrl ?? Paths.Member(member.Alias)); }
public static PostHandlerOutput[] InviteCommand( IDocumentSession documentSession, IMember sender, IRoom room, string source) { documentSession.Ensure("documentSession"); sender.Ensure("sender"); room.Ensure("sender"); source.Ensure("source"); var match = inviteRegex.Match(source); if (!match.Success) return null; if (!sender.IsRoomOwner(room)) return new[] { new PostHandlerOutput { message = "Only the room's owner can invite players.", type= "error" } }; var playerInvitation = documentSession.CreatePlayerInvitation(room.Id); return new[] { new PostHandlerOutput { message = string.Format( CultureInfo.CurrentUICulture, "Give this URL to someone to join the game:{0}{1}?invitation-code={2}", Environment.NewLine, fn.MakeAbsoluteUri(Paths.AcceptInvitationForm()), playerInvitation.Code), type= "system" } }; }
public static object GetAcceptInvitationForm( NancyContext context, IDocumentSession documentSession, string invitationCode) { context.Ensure("context"); documentSession.Ensure("documentSession"); if (!context.IsSignedUp()) return 403; var playerInvitation = documentSession.GetPlayerInvitationByCode(invitationCode); if (playerInvitation == null || playerInvitation.Used) return 404; var room = documentSession.GetRoomById(playerInvitation.RoomId); if (room == null) return 404; return new AcceptInvitationFormResponse(room, invitationCode); }
static object PostRoom( NancyContext context, IDocumentSession documentSession, string title, string slug, string description) { context.Ensure("context"); documentSession.Ensure("documentSession"); if (!context.IsSignedUp()) return 403; var errors = new List<string>(); errors.AddRange(fn.ValidateRequired("Title", title)); errors.AddRange(fn.ValidateLength("Title", title, 128)); errors.AddRange(fn.ValidateRequired("Slug", slug)); errors.AddRange(fn.ValidateLength("Slug", slug, 128)); errors.AddRange(fn.ValidateFormat("Slug", slug, new Regex("[a-z][a-z0-9_-]+"))); if (description != null) errors.AddRange(fn.ValidateLength("Description", description, 1024)); var existingRoom =documentSession.GetRoomBySlug(slug); if (existingRoom != null) errors.Add(Strings.NotAvailable("slug", slug)); existingRoom = documentSession.GetRoomByTitle(title); if (existingRoom != null) errors.Add(Strings.NotAvailable("title", title)); if (errors.Count > 0) return context.ModelWithStatus(new CreateRoomFormResponse(title, slug, description, errors), 400); var currentMember = context.GetCurrentMember(documentSession); Debug.Assert(currentMember != null, "`IsSignedUp` should ensure current member is not null."); var room = documentSession.CreateRoom(currentMember.Id, slug, title, description); return context.Redirect(Paths.Room(room.Slug)); }
static object PostPost( NancyContext context, IDocumentSession documentSession, IMailSender mailSender, string slug, string source) { context.Ensure("context"); documentSession.Ensure("documentSession"); if (String.IsNullOrEmpty(slug)) return 404; if (!context.IsSignedUp()) return 403; var room = documentSession.GetRoomBySlug(slug); if (room == null) return 404; if (String.IsNullOrEmpty(source)) return 400; var currentMember = context.GetCurrentMember(documentSession); if (!room.CanPost(currentMember)) return 403; var output = fn.HandlePost(documentSession, currentMember, room, source); if (output == null) output = new[] { InvalidPostHandlerOuput }; if (output.Length > 0) return new SlashCommandOutputResponse(output); return 204; }
public static object PostPlayer( NancyContext context, IDocumentSession documentSession, IMailSender mailSender, string roomSlug, string invitationCode, string characterName, string characterAvatarUrl) { context.Ensure("context"); documentSession.Ensure("documentSession"); mailSender.Ensure("mailSender"); if (string.IsNullOrEmpty(roomSlug)) return 404; if (!context.IsSignedUp()) return 403; var room = documentSession.GetRoomBySlug(roomSlug); if (room == null) return 404; var currentMember = context.GetCurrentMember(documentSession); Debug.Assert(currentMember != null, "`requireSignedUp()` should ensure a current member."); var errors = new List<string>(); errors.AddRange(fn.ValidateRequired("Invitation code", invitationCode)); var playerInvitation = documentSession.GetPlayerInvitationByCode(invitationCode); if (playerInvitation == null) errors.Add("The invitation code is not valid."); if (playerInvitation != null && playerInvitation.Used) errors.Add("The invitation code has already been used."); errors.AddRange(fn.ValidateRequired("Character Name", characterName)); errors.AddRange(fn.ValidateLength("Character Name", characterName, 64)); errors.AddRange(fn.ValidateFormat("Character Name", characterName, new Regex("^[a-z][a-z0-9 .'-]+$", RegexOptions.IgnoreCase))); if (!string.IsNullOrEmpty(characterAvatarUrl)) errors.AddRange(fn.ValidateUrl("Avatar URL", characterAvatarUrl)); var existingPlayer = room.Players.FirstOrDefault(p => p.CharacterName.Equals(characterName, StringComparison.OrdinalIgnoreCase)); if (existingPlayer != null) errors.Add(Strings.NotAvailable("character name", characterName)); if (errors.Count > 0) return context.ModelWithStatus(new AcceptInvitationFormResponse(room, invitationCode, characterName, characterAvatarUrl, errors), 400); var player = new Player { CharacterAvatarUrl = characterAvatarUrl, CharacterName = characterName, MemberAlias = currentMember.Alias, MemberId = currentMember.Id, MemberEmailAddress = currentMember.EmailAddress, RoomId = room.Id }; room.Players.Add(player); documentSession.UpdatePlayerInvitation(playerInvitation.Id, used: true); string text = Strings.Format("{0} joined the room as {1}.", player.MemberAlias, player.CharacterName); documentSession.CreatePost(mailSender, room.Id, currentMember.Id, null, null, "system", text); return context.Redirect(Paths.Room(room.Slug)); }