using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using CPE.App.Web.Code;
using CPE.App.Web.Connect;
using CPE.App.Web.Helpers;
using CPE.App.Web.Models;
namespace CPE.App.Web.Controllers {
public class RebroadcastController : BaseController {
[HttpGet]
public ActionResult RebroadcastSchedule(int meetingSessionKey) {
var meetingSession = Database.MeetingSessions.Single(ms => ms.MeetingSessionKey == meetingSessionKey);
return View(meetingSession);
}
[HttpGet]
public ActionResult RebroadcastSessions(int meetingSessionKey) {
var meetingScoId = Database.MeetingSessions.Single(ms => ms.MeetingSessionKey == meetingSessionKey)
.SCO_ID;
var recordingSessions =
Database.RecordingSessions.Where(rs => rs.MeetingSCO_ID == meetingScoId)
.OrderByDescending(rs => rs.StartTime)
.ToList();
return PartialView(recordingSessions);
}
[HttpGet]
public ActionResult RebroadcastPauses(int recordingKey) {
var recording = Database.RecordingSessions.Single(r => r.RecordingKey == recordingKey);
var meeting = Database.MeetingSessions.Single(ms => ms.MeetingSessionKey == recording.MeetingSessionKey);
var recordingPauses = new RecordingPauses {
Session = meeting,
SessionPauses = meeting.MeetingSessionPauses.ToList()
};
return View(recordingPauses);
}
[HttpPost]
public JsonResult DeletePause(int pauseKey) {
var result = false;
try {
var pause = Database.MeetingSessionPauses.Single(p => p.MesstingSessionPauseKey == pauseKey);
Database.MeetingSessionPauses.DeleteOnSubmit(pause);
Database.SubmitChanges();
result = true;
} catch (Exception ex) {
result = false;
}
return Json(result);
}
[HttpPost]
public JsonResult UpdatePauses(MeetingSessionPause[] pauses) {
var result = false;
try {
foreach (var meetingSessionPause in pauses) {
var dbPause =
Database.MeetingSessionPauses.Single(
msp => msp.MesstingSessionPauseKey == meetingSessionPause.MesstingSessionPauseKey);
dbPause.StartDate = meetingSessionPause.StartDate.ToUniversalTime();
dbPause.EndDate = meetingSessionPause.EndDate.Value.ToUniversalTime();
}
Database.SubmitChanges();
result = true;
} catch (Exception ex) {
result = false;
}
return Json(result);
}
[HttpGet]
public ActionResult ViewRecording(string meetingUrl, string d = null, string c = null) {
meetingUrl = meetingUrl?.Trim();
d = d?.Trim();
c = c?.Trim();
Extensions.LogServiceCall("[RebroadcastController][ViewRecording]", string.Format("meetingUrl = {0} d (PurchaseDate) = {1} c (TicketFromUrl) = {2}", meetingUrl, d, c));
if(meetingUrl.ToLower() == "test_room") {
var baseUrl = ConfigurationManager.AppSettings["Connect.Url"];
var testUrl = ConfigurationManager.AppSettings["Connect.AccessTestMeetingUrl"];
var accessTestUrl = baseUrl + '/' + testUrl;
return Redirect(accessTestUrl);
}
var meeting = AdobeMeetingConnection.getAdobeMeeting(meetingUrl);
if(meeting != null) {
var sco_id = int.Parse(meeting.SelectSingleNode("//sco")
.Attributes["sco-id"].Value);
DateTime? startDate = null;
DateTime? endDate = null;
string msg = "";
bool isActive = false;
var recordingSession = getActiveRecordingSession(sco_id);
//this now returns a recording that starts within an hour, instead of now
if(recordingSession == null) {
recordingSession = getNextRecordingSession(sco_id);
//this now returns the next recording that starts more than an hour from now
if(recordingSession != null) {
msg =
"This webcast session is not currently available. The next scheduled session is: ";
startDate = recordingSession.StartTime;
endDate = recordingSession.EndTime;
} else {
msg = "There are no webcasts scheduled for this session";
}
} else {
isActive = true;
startDate = recordingSession.StartTime;
endDate = recordingSession.EndTime;
}
RestoreModelState();
var now = DateTime.UtcNow;
return View("recordinglogin",
new RecordingView {
Name = meeting.SelectSingleNode("//sco/name")
.InnerText,
HasPassCode = recordingSession != null && recordingSession.Passcode != null,
Url = meetingUrl,
IsActive = isActive,
Start = startDate,
End = endDate,
Message = msg,
TicketFromUrl = c,
PurchaseDate = d
});
}
return null;
}
[HttpPost]
public ActionResult ViewRecordingLogin(string meetingUrl, string firstname, string lastname, string email,
string ticket, string passcode, string ticketFromUrl, string purchaseDate) {
meetingUrl = meetingUrl?.Trim();
firstname = firstname?.Trim();
lastname = lastname?.Trim();
email = email?.Trim();
passcode = passcode?.Trim();
ticket = ticket?.Trim();
ticketFromUrl = ticketFromUrl?.Trim();
purchaseDate = purchaseDate?.Trim();
Extensions.LogServiceCall("[RebroadcastController][ViewRecordingLogin]", string.Format("email = {0} meetingUrl = {1} ticket = {2} ticketFromUrl = {3} purchaseDate = {4} firstname = {5} lastname = {6} passcode = {7}", email, meetingUrl, ticket, ticketFromUrl, purchaseDate, firstname, lastname, passcode));
var loginInfo = new loginInfo {
meetingUrl = meetingUrl,
firstname = firstname,
lastname = lastname,
email = email,
ticket = ticket,
passcode = passcode,
ticketFromUrl = ticketFromUrl,
purchaseDate = purchaseDate,
meetingSessionKey = 0
};
var magicTicketLogin = string.IsNullOrEmpty(ticketFromUrl);
// I commented out the check of CPE.AdobeTicketingOn both because I didn't understand it and it complicated adding the else clause I added.
//if ((ConfigurationManager.AppSettings["CPE.AdobeTicketingOn"].ToLower() == "true") & !magicTicketLogin)
if(!magicTicketLogin) {
if(!ticketFromUrl.Equals(ticket)) {
ModelState.AddModelError("ticket", "You have entered an invalid pass code.");
SaveModelState();
return RedirectToRoute("ViewRecording", new {meetingUrl});
}
if(!VerifyAccess.VerifyTicket(ticket, meetingUrl, firstname, lastname, email, purchaseDate)) {
ModelState.AddModelError("ticket",
"Invalid Login. Please re-enter your information. If you continue to have trouble, please contact Customer Service at 1-800-544-1114 or email us at sswebcast@cpeincmail.com.");
SaveModelState();
return RedirectToRoute("ViewRecording", new {meetingUrl});
}
} else {
if((passcode == null) || (passcode == "")) {
Extensions.LogServiceCall("[RebroadcastController][ViewRecordingLogin]", string.Format("passcode found Empty! email = {0} meetingUrl = {1} ticket = {2} ticketFromUrl = {3} purchaseDate = {4} firstname = {5} lastname = {6} passcode = {7}", email, meetingUrl, ticket, ticketFromUrl, purchaseDate, firstname, lastname, passcode));
ModelState.AddModelError("passcode", "You have entered an invalid pass code.");
SaveModelState();
return RedirectToRoute("ViewRecording", new {meetingUrl});
}
if(passcode != (DateTime.UtcNow.ToString("MMM") + DateTime.UtcNow.Day.ToString("00")).ToLower()) {
Extensions.LogServiceCall("[RebroadcastController][ViewRecordingLogin]", string.Format("passcode found incorrect! email = {0} meetingUrl = {1} ticket = {2} ticketFromUrl = {3} purchaseDate = {4} firstname = {5} lastname = {6} passcode = {7}", email, meetingUrl, ticket, ticketFromUrl, purchaseDate, firstname, lastname, passcode));
ModelState.AddModelError("passcode", "You have entered an invalid pass code.");
SaveModelState();
return RedirectToRoute("ViewRecording", new {meetingUrl});
}
}
try {
var principalId = getConnectUser(loginInfo);
saveParticipant(loginInfo, principalId);
var certificateId = 0;
var recordingId = addAdobeConnectPermissions(loginInfo, principalId);
var recordingResult = getRecording(ref loginInfo, recordingId);
if(!magicTicketLogin) {
certificateId = savePurchaseInfo(loginInfo, purchaseDate, principalId, ticketFromUrl,
loginInfo.meetingSessionKey);
}
switch (recordingResult) {
case recordingResult.Now:
return RedirectToAction("GotoContent",
new {
loginInfo.meetingSessionKey, email, certificateId
});
case recordingResult.Lobby:
placeIntoLobby(loginInfo.meetingSessionKey, email, certificateId);
break;
}
} catch (Exception ex) {
Extensions.LogServiceError("[RebroadcastController][ViewRecordingLogin]", ex);
return RedirectToRoute("ViewRecording", new {meetingUrl});
}
return null;
}
[HttpGet]
public ActionResult LobbyWait() {
int meetingSessionKey = Convert.ToInt32(Request.QueryString["meetingSessionKey"]);
string email = Request.QueryString["email"];
int certificateId = Convert.ToInt32(Request.QueryString["certificateId"]);
var meeting = Database.MeetingSessions.FirstOrDefault(x => x.MeetingSessionKey == meetingSessionKey);
var lobbyData = new LobbyModel {
LobbyDuration = (DateTime.UtcNow - meeting.StartDate).TotalMilliseconds,
Email = email,
meetingSessionKey = meetingSessionKey,
CertificateId = certificateId
};
return View("lobby", lobbyData);
}
[HttpPost]
public JsonResult PublishRecording(int meetingSessionKey, DateTime startTime, DateTime endTime,
string surveyLink, string passcode) {
surveyLink = surveyLink?.Trim();
passcode = passcode?.Trim();
var result = new JsonDataResult {Success = false, Data = new {Url = "", Message = ""}};
//return this.Json(result);
var recordingsFolderId = ConfigurationManager.AppSettings["Connect.RecordingsFolderId"];
string recordingUrl = null;
var moveToContentLibrary = false;
var meeting = Database.MeetingSessions.Single(ms => ms.MeetingSessionKey == meetingSessionKey);
var admin = AdobeMeetingConnection.GetAdobeAdminSession();
var request = new Request(admin, "sco-contents");
request.Parameters.Add("sco-id", meeting.SCO_ID.ToString());
request.Parameters.Add("filter-icon", "archive");
if(request.Execute() && request.Status == Status.OK) {
var recordings = request.XmlResults.GetElementsByTagName("sco");
if(recordings.Count == 0) {
//meeting room does not have any recordings present
//look up recording in content library
var contentRequest = new Request(admin, "sco-contents");
contentRequest.Parameters.Add("sco-id", recordingsFolderId);
contentRequest.Parameters.Add("filter-description", meeting.SCO_ID.ToString());
if(contentRequest.Execute() && contentRequest.Status == Status.OK) {
recordings = contentRequest.XmlResults.GetElementsByTagName("sco");
moveToContentLibrary = false;
} else {
Console.WriteLine("wtf");
}
} else {
//meeting room has recordings. Need to move to content library.
moveToContentLibrary = true;
}
if(recordings.Count > 0) {
var recordingId = recordings[0].Attributes["sco-id"].Value;
var recordingName = recordings[0].SelectSingleNode("name")
.InnerText;
recordingUrl = recordings[0].SelectSingleNode("url-path")
.InnerText.Replace("/", "");
var durationInSeconds = int.Parse(recordings[0].Attributes["duration"].Value);
//create RecordingSession
var recordingSession = new RecordingSession {
MeetingSCO_ID = meeting.SCO_ID,
RecordingSCO_ID = int.Parse(recordingId),
StartTime = startTime.ToUniversalTime(),
EndTime = endTime.ToUniversalTime(),
Name = recordingName,
RecordingUrl = recordingUrl,
Duration = durationInSeconds,
SurveyLink = Server.UrlDecode(surveyLink),
Passcode = Server.UrlDecode(passcode)
};
Database.RecordingSessions.InsertOnSubmit(recordingSession);
Database.SubmitChanges();
var originalDate = meeting.StartDate.Date;
var diffInDays = (startTime.ToUniversalTime()
.Date - originalDate).Days;
var origStartTime = meeting.StartDate.TimeOfDay;
var origOnRebroadcastDate = startTime.Date + origStartTime;
var diffInMs = (startTime.ToUniversalTime() - origOnRebroadcastDate).TotalMilliseconds;
var createResult = Database.CreateRebroadcastSession(recordingSession.RecordingSCO_ID,
meeting.SCO_ID,
meeting.OwnerPrincipal_ID, startTime.ToUniversalTime(), endTime.ToUniversalTime(), diffInMs,
diffInDays, recordingName);
recordingSession.MeetingSessionKey = createResult.Single()
.Column1;
Database.SubmitChanges();
result.Success = true;
result.Data = new {Url = recordingUrl, Message = ""};
if(moveToContentLibrary) {
var moveRequest = new Request(admin, "sco-move");
moveRequest.Parameters.Add("folder-id", recordingsFolderId);
moveRequest.Parameters.Add("sco-id", recordingId);
if(moveRequest.Execute() && moveRequest.Status == Status.OK) {
var updateRequest = new Request(admin, "sco-update");
updateRequest.Parameters.Add("sco-id", recordingId);
updateRequest.Parameters.Add("description", meeting.SCO_ID.ToString());
if(updateRequest.Execute() && updateRequest.Status == Status.OK) {
result.Success = true;
result.Data = new {Url = recordingUrl, Message = ""};
} else {
result.Success = false;
result.Data = new {Url = "", Message = "Unable to update recording description."};
}
} else {
result.Success = false;
result.Data =
new {
Url = "",
Message = "Could not move recording to content library.",
Error = moveRequest.Status.ToString()
};
}
}
} else {
result.Success = false;
result.Data = new {Url = "", Message = "Meeting does not have any recordings."};
}
} else {
result.Success = false;
result.Data = new {Url = "", Message = "Problem listing recordings.", Error = request.Status.ToString()};
}
return Json(result, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public JsonResult DeleteRecording(int recordingSessionKey) {
var success = false;
var now = DateTime.UtcNow;
var recordingSession =
Database.RecordingSessions.SingleOrDefault(rs => rs.RecordingKey == recordingSessionKey);
if(recordingSession != null) {
if(recordingSession.MeetingSessionKey.HasValue) {
var meeting =
Database.MeetingSessions.Single(
ms => ms.MeetingSessionKey == recordingSession.MeetingSessionKey.Value);
if(meeting.StartDate > now) {
Database.DeleteSession(meeting.MeetingSessionKey);
}
}
if(recordingSession.StartTime > now) {
Database.RecordingSessions.DeleteOnSubmit(recordingSession);
Database.SubmitChanges();
success = true;
}
}
return Json(success, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public JsonResult RebroadcastActive(string recordingUrl) {
recordingUrl = recordingUrl?.Trim();
var active = false;
var recording = AdobeMeetingConnection.getAdobeMeeting(recordingUrl);
if(recording != null) {
var sco_id = int.Parse(recording.SelectSingleNode("//sco")
.Attributes["sco-id"].Value);
var recordingSession = getActiveRecordingSession(sco_id);
active = recordingSession != null;
}
return Json(active, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public ActionResult Wufoo() {
var client = new WebClient();
var response = client.DownloadString(
"http://intesolvtest.wufoo.com/forms/submit-a-question/def/field1=Course+Title&field2=Course+Code&field5=today,field3=Jason&field4=McIntosh&field2=jason.wigginton@gmail.com");
return Content(response);
}
///
///
///
///
///
///
///
private string getWufooQAlink(RecordingSession recordingSession, string email, string firstname, string lastname) {
firstname = firstname?.Trim();
lastname = lastname?.Trim();
email = email?.Trim();
var meetingDetails =
Database.MeetingDetails.SingleOrDefault(md => md.MeetingKey == recordingSession.MeetingSCO_ID);
var code = meetingDetails != null ? meetingDetails.CourseCode : "";
var instructor = meetingDetails != null ? meetingDetails.Instructor : "";
var url = recordingSession.SurveyLink;
if(url.EndsWith("/")) {
url = url.Remove(url.LastIndexOf("/"), 1);
}
//1=Course Title,2=Course Code,3=Date,4=Firstname,5=Lastname,8=email
//return url + String.Format("/def/field1={0}&field2={1}&field3={2}&field4={3}&field5={4}&field8={5}", recordingSession.Name, code, "today", firstname, lastname,email);
//1 = first name, 2 = lastname, 3 = email, 5 = Course
return url +
string.Format("/def/field1={0}&field2={1}&field3={2}&field5={3}&field7={4}&field8={5}&field9={6}",
firstname, lastname, email, recordingSession.Name, code, instructor, "today");
}
private void TrackUserEntrance(MeetingSession session, int principalId, string firstName, string lastName,
string email) {
firstName = firstName?.Trim();
lastName = lastName?.Trim();
email = email?.Trim();
//participant isnt getting tracked for the test rebroadcast -> is this a real problem or a test-data problem?
var now = DateTime.UtcNow;
var context = Database;
Extensions.LogServiceCall("TrackUser",
string.Format(
"Parameters: meetingSessionKey = {0} principal_id= {1} firstname = {2}, lastname = {3} email = {4}, type = 0",
session.MeetingSessionKey, principalId, firstName, lastName, email));
try {
if(principalId > 0) {
if(session != null) {
var user = context.Participants.SingleOrDefault(p => p.Principal_ID == principalId);
if(user == null) {
//create new user
user = new Participant {
Principal_ID = principalId,
FirstName = firstName,
LastName = lastName,
Email = email
};
context.Participants.InsertOnSubmit(user);
}
//JM 9/27/2012 - changed to grab first participant session found. Weird issue where some users were getting multiple sesions
var existingMeetingParticipantSession =
session.MeetingParticipantSessions.OrderBy(mps => mps.MeetingParticipantSessionKey)
.
FirstOrDefault(mps => mps.ParticipantKey == principalId);
if(existingMeetingParticipantSession == null) {
//create new session for user
existingMeetingParticipantSession = new MeetingParticipantSession {
MeetingSessionKey = session.MeetingSessionKey,
ParticipantKey = principalId,
PlaySound = true
};
context.MeetingParticipantSessions.InsertOnSubmit(existingMeetingParticipantSession);
context.SubmitChanges();
//JM-12/27/2012 Change to check for multiple meeting participant sessions
CheckParticipantSessions(session, principalId);
//make sure tracking gets assigned right key
existingMeetingParticipantSession = context.MeetingParticipantSessions.OrderBy(
p => p.MeetingParticipantSessionKey)
.FirstOrDefault(
p =>
p.MeetingSessionKey == session.MeetingSessionKey &
p.ParticipantKey == principalId);
}
var existingParticipantTracking =
context.ParticipantTrackings.FirstOrDefault(
pt =>
pt.MeetingParticipantSessionKey ==
existingMeetingParticipantSession.MeetingParticipantSessionKey &&
pt.Principal_ID == principalId && !pt.EndDate.HasValue);
if(existingParticipantTracking == null) {
//add entrance time
var pTrack = new ParticipantTracking {
MeetingParticipantSessionKey =
existingMeetingParticipantSession.MeetingParticipantSessionKey,
Principal_ID = principalId,
StartDate = now
};
context.ParticipantTrackings.InsertOnSubmit(pTrack);
} else {
//track enter received when there is already an entrance with no exit
//set exit on existing
ParticipantEngagement lastEngagement =
existingParticipantTracking.MeetingParticipantSession.ParticipantEngagements.OrderBy(
e => e.DisplayTime)
.LastOrDefault();
if(lastEngagement == null)
existingParticipantTracking.EndDate = existingParticipantTracking.StartDate;
else
existingParticipantTracking.EndDate = lastEngagement.ResponseTime.HasValue
? lastEngagement.ResponseTime.Value
: lastEngagement.DisplayTime;
//existingParticipantTracking.EndDate = now;
//add new entrance time
var pTrack = new ParticipantTracking {
MeetingParticipantSessionKey =
existingMeetingParticipantSession.MeetingParticipantSessionKey,
Principal_ID = principalId,
StartDate = now
};
context.ParticipantTrackings.InsertOnSubmit(pTrack);
}
context.SubmitChanges();
}
} else {
throw new ArgumentException("Principal ID: " + principalId + " is not valid");
}
} catch (Exception ex) {
Extensions.LogServiceError("TrackUser", ex);
}
}
private void CheckParticipantSessions(MeetingSession session, int principal_id) {
try {
var context = Database;
var participantSessionCount =
session.MeetingParticipantSessions.Count(mps => mps.ParticipantKey == principal_id);
if(participantSessionCount > 1) {
var participantSessions =
session.MeetingParticipantSessions.Where(mps => mps.ParticipantKey == principal_id)
.OrderBy(
mps => mps.MeetingParticipantSessionKey);
var psToKeep = participantSessions.First();
var psessionsToDelete =
participantSessions.Where(
ps => ps.MeetingParticipantSessionKey != psToKeep.MeetingParticipantSessionKey);
foreach (var meetingParticipantSession in psessionsToDelete) {
context.MeetingParticipantSessions.DeleteOnSubmit(meetingParticipantSession);
}
context.SubmitChanges();
}
} catch (Exception ex) {
Extensions.LogServiceError("CheckParticipanSessions", ex);
}
}
private RecordingSession getActiveRecordingSession(int recordingScoId) {
//for SP3 if rs.StartTime < now + 1hr., recording considered "active", user will be placed into lobby
var now = DateTime.UtcNow;
var recording = Database.RecordingSessions.SingleOrDefault(rs => rs.RecordingSCO_ID == recordingScoId
&& rs.StartTime <= now.AddHours(1) &&
rs.EndTime > now);
return recording;
}
private RecordingSession getNextRecordingSession(int recordingScoId) {
//for SP3 a user can wait in the lobby for an hour, so the next (not currently active) recording session will have start > than now+1hr
var now = DateTime.UtcNow;
var recording = Database.RecordingSessions.Where(rs => rs.RecordingSCO_ID == recordingScoId
&& rs.StartTime > now.AddHours(1))
.OrderBy(rs => rs.StartTime)
.FirstOrDefault();
return recording;
}
private void SaveModelState() {
TempData["ModelState"] = ModelState;
}
private void RestoreModelState() {
var previousModelState = TempData["ModelState"] as ModelStateDictionary;
if(previousModelState != null) {
foreach (KeyValuePair kvp in previousModelState)
if(!ModelState.ContainsKey(kvp.Key))
ModelState.Add(kvp.Key, kvp.Value);
TempData["ModelState"] = ModelState; //Add back into TempData
}
}
///
///
private void placeIntoLobby(int meetingSessionKey, string email, int certificateId) {
email = email?.Trim();
//rebroadcast/LobbyWait
Response.Redirect("/rebroadcast/LobbyWait?meetingSessionKey=" + meetingSessionKey + "&email=" + email + "&certificateId=" + certificateId, true);
}
[HttpGet]
public ActionResult GotoContent(int meetingSessionKey, string email, int certificateId) {
email = email?.Trim();
var now = DateTime.UtcNow;
var connectUrl = ConfigurationManager.AppSettings["Connect.Url"];
var accountId = int.Parse(ConfigurationManager.AppSettings["Connect.AccountId"]);
var password = Guid.NewGuid()
.ToString()
.Replace("{", "")
.Replace("}", "")
.Substring(0, 8);
var participant = Database.Participants.FirstOrDefault(p => p.Email == email);
if(participant == null) {
Extensions.LogServiceCall("[RebroadcastController][GotoContent]", string.Format("participant found null; meetingSessionKey = {0} email = {1} certificateId = {2}", meetingSessionKey, email, certificateId));
throw new Exception("Login failed! " + email);
}
var recording =
Database.RecordingSessions.FirstOrDefault(
rs => rs.MeetingSessionKey == meetingSessionKey && rs.StartTime <= now && rs.EndTime > now);
if(recording == null) {
Extensions.LogServiceCall("[RebroadcastController][GotoContent]", string.Format("recording found null; meetingSessionKey = {0} email = {1} certificateId = {2}", meetingSessionKey, email, certificateId));
throw new Exception("Login failed! " + email);
}
var meeting = Database.MeetingSessions.FirstOrDefault(y => y.MeetingSessionKey == meetingSessionKey);
if(meeting == null) {
Extensions.LogServiceCall("[RebroadcastController][GotoContent]", string.Format("meeting found null; meetingSessionKey = {0} email = {1} certificateId = {2}", meetingSessionKey, email, certificateId));
throw new Exception("Login failed! " + email);
}
var admin = AdobeMeetingConnection.GetAdobeAdminSession();
Login.ResetPassword(admin, participant.Principal_ID, password);
var session = Login.UserLogin(participant.Email, password, connectUrl, accountId);
var differenceInMilliseconds = (now - meeting.StartDate).TotalMilliseconds;
var recordingView = new RecordingView {
Name = AdobeMeetingConnection.getAdobeMeetingName(recording.RecordingUrl),
PrincipalId = participant.Principal_ID,
MeetingSessionKey = meeting.MeetingSessionKey,
FirstName = participant.FirstName,
LastName = participant.LastName,
Email = participant.Email,
QAlink = getWufooQAlink(recording, participant.Email, participant.FirstName, participant.LastName),
Url =
string.Format(
"{0}/{1}?session={2}&launcher=false&pbEIOpen=false&archiveOffset={3}",
connectUrl,
recording.RecordingUrl,
session.SessionKey, differenceInMilliseconds), //+
//((passcode == null) ? "" : "&meeting-passcode=" + passcode)
CertificateId = certificateId
};
admin = AdobeMeetingConnection.GetAdobeAdminSession();
var request = new Request(admin, "principal-update");
request.Parameters.Add("first-name", participant.FirstName);
request.Parameters.Add("last-name", participant.LastName);
request.Parameters.Add("principal-id", participant.Principal_ID.ToString());
request.Execute();
var idCookie = new HttpCookie("id") {
Value = participant.Principal_ID.ToString(),
Expires = DateTime.UtcNow.AddDays(1)
};
Response.Cookies.Add(idCookie);
TrackUserEntrance(meeting, participant.Principal_ID, participant.FirstName, participant.LastName,
participant.Email);
return View("recording", recordingView);
}
//public string SendCert(int meetingSessionKey, int certificate_id, int principal_id)
//{
// //TODO make outcome dictionary to return pass, fail, ineligible, or wonky:contact cust serv
// string _fail = "http://localhost:11038/Certificate?a=1179512338&b=20160128&c=1d633b";
// //string _fail = "FAIL";
// var meeting = Database.MeetingSessions.FirstOrDefault(x => x.MeetingSessionKey == meetingSessionKey);
// if (certificate_id > 0)
// {
// ParticipantPurchase purchase =
// Database.ParticipantPurchases.FirstOrDefault(p => p.Purchase_ID == certificate_id && p.PrincipalID == principal_id);
// if (purchase == null)
// {
// //if the certificate_id is >0 then purchase would only be null because of record being deleted while user was in the meeting, or the principalID got mis-matched
// return _fail; // TODO probably return wonky, contact cust service message
// }
// if (!purchase.EarnedCertificate)
// {
// MeetingParticipantSession meetingParticipantSession =
// Database.MeetingParticipantSessions.FirstOrDefault(
// m => m.MeetingSessionKey == meetingSessionKey && m.ParticipantKey == principal_id);
// if (meetingParticipantSession == null)
// {
// return _fail;//TODO return wonky
// }
// List participantSessionsDataResult =
// Database.ParticipantSessionsData(meetingSessionKey)
// .ToList();
// var participantSessionsData =
// participantSessionsDataResult.OrderBy(p => p.MeetingParticipantSessionKey)
// .FirstOrDefault(
// p =>
// p.MeetingParticipantSessionKey ==
// meetingParticipantSession.MeetingParticipantSessionKey);
// if (participantSessionsData == null)
// {
// return _fail;//TODO is this a return wonky? it means they weren't tracked
// }
// MeetingSessionsDataResult meetingSession = Database.MeetingSessionsData().FirstOrDefault(m => m.MeetingSessionKey == meetingSessionKey);
// if (meetingSession == null)
// {
// return _fail;//TODO return wonky
// }
// var courseLength = meetingSession.ActualSessionTime.GetValueOrDefault(); //in minutes
// double courseCredits = courseLength / 50.0; //1 credit per 50 minutes
// List maxCourseCredits = ConfigurationManager.AppSettings["MaxCourseCreditList"].Split(';').Select(s => double.Parse(s)).ToList(); //max credits cut list
// int mx = maxCourseCredits.BinarySearch(courseCredits); //find appropriate max for this course
// double maxCredits = maxCourseCredits[mx >= 0 ? mx : ~mx - 1];//...by rounding down
// double realCredits = participantSessionsData.SessionCredit == null ? 0 : (double)participantSessionsData.SessionCredit.Value; //users credits per adobe
// purchase.Credits = Math.Min(maxCredits, realCredits); //user awarded no more than max possible credits for the course
// MeetingDetail meetingDetail =
// Database.MeetingDetails.FirstOrDefault(m => m.MeetingKey == purchase.MeetingSco);
// purchase.Presenter = meetingDetail == null ? "" : meetingDetail.Instructor;
// double percentComplete = (participantSessionsData.SessionEngagementCount.GetValueOrDefault() == 0 ?
// 1 : (participantSessionsData.SessionHeartbeatCount.GetValueOrDefault() / participantSessionsData.SessionEngagementCount.Value));
// if (percentComplete >= .75) //threshold for earning a certificate is 75% response rate
// {
// purchase.EarnedCertificate = true;
// }
// Database.SubmitChanges();
// if (purchase.EarnedCertificate)
// {
// //TODO with return Pass dictionary value as string.format with replace of certUrl
// //string certUrl = AdobeCertificateHelper.SendWebcastCert(purchase);
// //format the outcome.pass.value message with certUrl replace
// //return outcome.pass with its value
// return AdobeCertificateHelper.SendWebcastCert(purchase);
// }
// //TODO return outcome.fail
// return AdobeCertificateHelper.SendFailNotice(purchase);
// }
// }
// return _fail;// TODO return ineligible. need to make AdobeCertificateHelper.SendIneligibleNotice(principalId)
//}
///
///
///
///
private int getConnectUser(loginInfo loginInfo) {
var password = Guid.NewGuid()
.ToString()
.Replace("{", "")
.Replace("}", "")
.Substring(0, 8);
var admin = AdobeMeetingConnection.GetAdobeAdminSession();
var request = new Request(admin, "principal-list");
request.Parameters.Add("filter-type", "guest");
request.Parameters.Add("filter-type", "user");
request.Parameters.Add("filter-login", loginInfo.email);
if(request.Execute() && request.Status == Status.OK) {
int principalId;
if(request.XmlResults.SelectSingleNode("//principal") == null) {
// Not found
principalId = Login.CreateGuest(admin, loginInfo.email, password, loginInfo.email, loginInfo.firstname, loginInfo.lastname);
} else {
// Found
principalId =
int.Parse(request.XmlResults.SelectSingleNode("//principal")
.Attributes["principal-id"].Value);
loginInfo.email = request.XmlResults.SelectSingleNode("//principal/login")
.InnerText;
if(request.XmlResults.SelectSingleNode("//principal")
.Attributes["type"].Value == "user") {
ModelState.AddModelError("email", "Invalid email.");
SaveModelState();
throw new Exception("Login failed!");
}
}
if(principalId < 1) {
throw new Exception("Login failed!");
}
Login.ResetPassword(admin, principalId, password);
return principalId;
}
throw new Exception("Login failed!");
}
///
///
///
///
///
private int addAdobeConnectPermissions(loginInfo loginInfo, int principalId) {
var admin = AdobeMeetingConnection.GetAdobeAdminSession();
var meetingXml = AdobeMeetingConnection.getAdobeMeeting(loginInfo.meetingUrl);
var recordingId = int.Parse(meetingXml.SelectSingleNode("//sco")
.Attributes["sco-id"].Value);
var request = new Request(admin, "permissions-update");
request.Parameters.Add("acl-id", recordingId.ToString());
request.Parameters.Add("principal-id", principalId.ToString());
request.Parameters.Add("permission-id", "view");
if(request.Execute() && request.Status == Status.OK) {
return recordingId;
}
throw new Exception("Login failed!");
}
///
///
///
///
///
private recordingResult getRecording(ref loginInfo loginInfo, int recordingId) {
var now = DateTime.UtcNow;
var recording =
Database.RecordingSessions.SingleOrDefault(
rs => rs.RecordingSCO_ID == recordingId && rs.StartTime <= now && rs.EndTime > now);
if(recording == null) {
recording =
Database.RecordingSessions.SingleOrDefault(
rs =>
rs.RecordingSCO_ID == recordingId && rs.StartTime <= now.AddHours(1) &&
rs.StartTime > now);
if(recording == null) {
loginInfo.meetingSessionKey = 0;
return recordingResult.None;
}
loginInfo.meetingSessionKey = recording.MeetingSessionKey.Value;
return recordingResult.Lobby;
}
loginInfo.meetingSessionKey = recording.MeetingSessionKey.Value;
return recordingResult.Now;
}
///
///
///
///
private void saveParticipant(loginInfo loginInfo, int principalId) {
var participant =
Database.Participants.SingleOrDefault(p => p.Principal_ID == principalId);
if(participant == null) {
participant = new Participant {
Principal_ID = principalId,
FirstName = loginInfo.firstname,
LastName = loginInfo.lastname,
Email = loginInfo.email
};
Database.Participants.InsertOnSubmit(participant);
} else {
participant.FirstName = loginInfo.firstname;
participant.LastName = loginInfo.lastname;
}
Database.SubmitChanges();
}
private int savePurchaseInfo(loginInfo loginInfo, string purchaseDate, int principalId, string ticketFromUrl, int meetingSessionKey) {
purchaseDate = purchaseDate?.Trim();
ticketFromUrl = ticketFromUrl?.Trim();
//purchase indicates hashed-ticket login that could earn a certificate. storing this info separate since participant name info gets updated based on adobe info
//and per cpe, a cert can only be earned in the exact name of purchaser.
var meeting =
Database.MeetingSessions.SingleOrDefault(
ms => ms.MeetingSessionKey == meetingSessionKey);
string formattedPdate = purchaseDate.Substring(0, 4) + '-' +
purchaseDate.Substring(4, 2) +
'-' + purchaseDate.Substring(6, 2);
DateTime pDate = Convert.ToDateTime(formattedPdate);
ParticipantPurchase purchase =
Database.ParticipantPurchases.SingleOrDefault(
p =>
p.PrincipalID == principalId & p.Ticket == ticketFromUrl &
p.MeetingSco == meeting.SCO_ID);
if(purchase == null) {
purchase = new ParticipantPurchase {
FirstName = loginInfo.firstname,
LastName = loginInfo.lastname,
Email = loginInfo.email,
PrincipalID = principalId,
MeetingName = meeting.Name,
MeetingDate = meeting.StartDate,
MeetingSco = meeting.SCO_ID,
Ticket = ticketFromUrl,
PurchaseDate = pDate,
EarnedCertificate = false,
Credits = 0
};
Database.ParticipantPurchases.InsertOnSubmit(purchase);
}
Database.SubmitChanges();
return purchase.Purchase_ID;
}
}
///
///
public class loginInfo {
//string meetingUrl, string firstname, string lastname, string email,
// string ticket, string passcode, string ticketFromUrl, string purchaseDate
public string meetingUrl { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
public string email { get; set; }
public string ticket { get; set; }
public string passcode { get; set; }
public string ticketFromUrl { get; set; }
public string purchaseDate { get; set; }
public int meetingSessionKey { get; set; }
}
///
///
public enum recordingResult {
Now,
Lobby,
None
}
}