Ejemplo n.º 1
0
        public async Task NextStage(Incident incident)
        {
            incident.WentToVoicemail = false;
            var stage = CallSequence[incident.Index];

            if (stage.Attempts > 1 && incident.Attempt < stage.Attempts)
            {
                incident.Attempt++;
                await StatusHub.UpdateClientAsync(incident.UserId, "phoneDelay", stage.Delay.ToString(), HttpContext);

                await Task.Delay(stage.Delay * 1000);
            }
            else
            {
                incident.Index++;
                incident.Attempt = 1;
                if (incident.Index >= CallSequence.Count)
                {
                    await StatusHub.UpdateClientAsync(incident.UserId, "phoneFail", null, HttpContext);

                    return;
                }
                stage = CallSequence[incident.Index];
            }
            var phoner = new Phoner();
            await phoner.CallAsync(incident, stage, Configuration["Twilio:FromNumber"], HttpContext);
        }
Ejemplo n.º 2
0
        public async Task <IActionResult> Post(string studentName, string room, int priority)
        {
            if (string.IsNullOrWhiteSpace(studentName) || string.IsNullOrWhiteSpace(room) || priority < 1 || priority > 2)
            {
                return(StatusCode(500, "Invalid inputs."));
            }
            if (!BritishTime.IsSchoolHours())
            {
                return(StatusCode(500, "This service is unavailable out of hours."));
            }

            var userId   = User.Identity.GetUserId();
            var incident = new Incident(Guid.NewGuid().ToString("D"), studentName.Split(',')[0].ToTitleCase(), room, User.Identity.Name, userId);

            if (priority == 1)
            {
                Cache.Set(incident.Id, incident, TimeSpan.FromMinutes(20));
                var phoner = new Phoner();
                await phoner.CallAsync(incident, CallSequence[0], Configuration["Twilio:FromNumber"], HttpContext);
            }

            var mailer = new Mailer(Configuration["Email:SenderEmail"], Configuration["Email:SenderPassword"], Configuration["Email:To"], Configuration["Email:Bcc"]);
            await mailer.SendAsync(studentName, room, User.Identity.Name, priority, User.Identity.GetEmail());

            await StatusHub.UpdateClientAsync(userId, "emailSent", priority, HttpContext);

            return(new EmptyResult());
        }
Ejemplo n.º 3
0
        public OverseerBootstrapper(IDataContext context)
        {
            _context = context;

            var applicationSettings = _context.GetApplicationSettings();

            _monitoringService = new MonitoringService(applicationSettings.Interval, () =>
            {
                var providerManager = Container.Resolve <PrinterProviderManager>();
                return(providerManager.GetPrinterProviders());
            });

            _monitoringService.StatusUpdate += (sender, args) =>
            {
                StatusHub.PushStatusUpdate(args.Status);
            };
        }
Ejemplo n.º 4
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, OverseerBootstrapper bootstrapper, IHubContext <StatusHub> statusHub)
        {
            bootstrapper.Container.Register <Action <MachineStatus> >((c, n) =>
            {
                return(status => StatusHub.PushStatusUpdate(statusHub, status));
            });

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseSpaStaticFiles();

            app.Map("/api", builder =>
            {
                builder.UseAuthentication();
                builder.UseOwin(owin => owin.UseNancy(options => options.Bootstrapper = bootstrapper));
            });

            app.Map("/push", builder =>
            {
                builder.UseSignalR(routes =>
                {
                    routes.MapHub <StatusHub>("/status");
                });
            });

            app.UseSpa(spa =>
            {
                if (env.IsDevelopment())
                {
                    spa.Options.SourcePath = "../OverseerUI";
                    spa.UseAngularCliServer(npmScript: "start");
                }
                else
                {
                    spa.Options.SourcePath = "/OverseerUI";
                }
            });
        }
Ejemplo n.º 5
0
 public async Task <IActionResult> StatusCallback(string incidentId, string callStatus)
 {
     if (incidentId == null || !Cache.TryGetValue(incidentId, out Incident incident))
     {
         return(StatusCode(401, "Incident token not recognised."));
     }
     if (incident.Index > -1)
     {
         var stage = CallSequence[incident.Index];
         if (callStatus == "busy" || callStatus == "no-answer" || callStatus == "failed" || callStatus == "canceled" || incident.WentToVoicemail || stage.RequireKeyPress)
         {
             await NextStage(incident);
         }
         else
         {
             incident.Index = -1;
             await StatusHub.UpdateClientAsync(incident.UserId, "phoneDone", null, HttpContext);
         }
     }
     return(Content("Handled.", "text/plain"));
 }
Ejemplo n.º 6
0
        public async Task <IActionResult> KeyPress(string incidentId, string callStatus, string digits)
        {
            if (incidentId == null || !Cache.TryGetValue(incidentId, out Incident incident))
            {
                return(StatusCode(401, "Incident token not recognised."));
            }
            if (digits == "1")
            {
                incident.Index = -1;
                await StatusHub.UpdateClientAsync(incident.UserId, "phoneDone", null, HttpContext);

                var response = new VoiceResponse()
                               .Say($"Thank you for agreeing to support in {incident.Room}.", Say.VoiceEnum.Woman)
                               .Pause(1)
                               .Say("Goodbye.", Say.VoiceEnum.Woman)
                               .Hangup();
                return(Content(response.ToString(), "text/xml"));
            }
            else
            {
                return(Index(incidentId, "human"));
            }
        }
Ejemplo n.º 7
0
        public static void Start(string endpoint, OverseerBootstrapper bootstrapper)
        {
            Log.Info("Starting Server...");

            bootstrapper.Container.Register <StatusHubService>();
            bootstrapper.Container.Register <Action <MachineStatus> >(s => StatusHub.PushStatusUpdate(s));

            GlobalHost.DependencyResolver.Register(typeof(StatusHub), () =>
            {
                return(bootstrapper.Container.Resolve <StatusHub>());
            });

            GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () =>
            {
                return(new JsonSerializer
                {
                    ContractResolver = new OverseerContractResolver(),
                    Formatting = Formatting.None
                });
            });

            WebApp.Start(endpoint, app =>
            {
                app.UseOverseerAuthentication(bootstrapper.Container);

                app.MapSignalR("/push", new HubConfiguration
                {
                    EnableDetailedErrors    = true,
                    EnableJavaScriptProxies = true,
                    EnableJSONP             = false
                });

                app.Map("/api", a =>
                {
                    a.UseNancy(new NancyOptions {
                        Bootstrapper = bootstrapper
                    });
                });

                /*
                 * This is needed to support client side routing without the use of hash bang urls.
                 * If the request wasn't for a file, an api request, or a signalr request then redirect to the root to be handled by index.html
                 */
                app.Use(async(IOwinContext context, Func <Task> next) =>
                {
                    await next.Invoke();

                    if (context.Response.StatusCode == 404 &&
                        !Path.HasExtension(context.Request.Path.Value) &&
                        !context.Request.Path.Value.StartsWith("/push") &&
                        !context.Request.Path.Value.StartsWith("/api"))
                    {
                        context.Request.Path = new PathString("/index.html");
                        await next.Invoke();
                    }
                });

                app.UseFileServer(new FileServerOptions
                {
                    EnableDirectoryBrowsing = false,
                    EnableDefaultFiles      = true,
                    DefaultFilesOptions     = { DefaultFileNames = { "index.html" } },
                    FileSystem        = new PhysicalFileSystem(ClientPath),
                    StaticFileOptions = { ContentTypeProvider = new OverseerContentTypeProvider() }
                });
            });

            Log.Info($"Listening at {endpoint}...");
        }