/// <summary> /// Send notification mail with the results of price push to Streamline. /// </summary> /// <param name="logWrittenDateTime">Log written date and time.</param> public void SendNotificationToStreamLine(DateTime logWrittenDateTime) { var config = new TemplateServiceConfiguration { BaseTemplateType = typeof(HtmlSupportTemplateBase <>), DisableTempFileLocking = true, CachingProvider = new DefaultCachingProvider(t => { }) }; var pricingPushLogger = new OperationsJsonLogger <PricePushResult>(Config.I.PricingPushAttemptsLogFile); var pricingPushlogs = pricingPushLogger.GetLogRecordsForExactDateTime(logWrittenDateTime); var streamLineLogs = pricingPushlogs.Where(p => p.Channel == Channel.StreamLine || p.Channel == Channel.Common); var templatePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var template = File.ReadAllText(Path.Combine(templatePath, "Templates/StreamLinePricingPushNotificationTemplate.cshtml")); using (var service = RazorEngineService.Create(config)) { var body = service.RunCompile(template, "StreamLinePricingPushNotificationTemplate", null, new { ProcessStartedAt = logWrittenDateTime.ToString("yyyy-M-d HH:mm tt"), ErrorsCount = streamLineLogs.Where(p => p.LogType == PricingPushLogType.Error).Count(), ParsingCSV = streamLineLogs.Where(p => ((p.LogArea == PricePushLogArea.ParsingCSV || p.LogArea == PricePushLogArea.CSVFileNotFound) && p.LogType == PricingPushLogType.Error)), PropertyDetails = streamLineLogs.Where(p => p.LogArea == PricePushLogArea.ParsingCSV && p.LogType == PricingPushLogType.Information), LoginDetails = streamLineLogs.Where(p => p.LogArea == PricePushLogArea.Login && p.LogType == PricingPushLogType.Information), LoginErrors = streamLineLogs.Where(p => p.LogArea == PricePushLogArea.Login && p.LogType == PricingPushLogType.Error), SeasonGroupErrors = streamLineLogs.Where(p => ((p.LogArea == PricePushLogArea.SeasonGroup || p.LogArea == PricePushLogArea.ChangeSeasonGroup) && p.LogType == PricingPushLogType.Error)), SeasonErrors = streamLineLogs.Where(p => p.LogArea == PricePushLogArea.Season && p.LogType == PricingPushLogType.Error), PropertyErrors = streamLineLogs.Where(p => p.LogArea == PricePushLogArea.Property && p.LogType == PricingPushLogType.Error), PriceUpdationErrors = streamLineLogs.Where(p => p.LogArea == PricePushLogArea.PriceUpdate && p.LogType == PricingPushLogType.Error), }); EmailNotification.Send(Config.I.PricingPushNotificationsEmail, "Streamline Pricing Push Report", body); } }
static void Main(string[] args) { List <AirBnbAccountCredentials> passwords = null; var logger = new OperationsJsonLogger <PasswordSyncError>(Config.I.PasswordSyncLogFile); try { Config.I.UseProxy = true; passwords = SSGoogleSpreadsheet.GetAirBnbPasswordsFromSpreadsheet(); } catch (Exception e) { logger.Log(new PasswordSyncError(PasswordErrorType.SpreadsheetConnectionError)); } if (passwords == null) { return; } try { AirBnbAccountsConfigBuilder.Init(); AirBnbAccountsConfigBuilder.SetAccountCredentials(passwords); AirBnbAccountsConfigBuilder.Save(); } catch (Exception e) { logger.Log(new PasswordSyncError(PasswordErrorType.SaveDataError)); } }
public static void ProcessPricePush() { N.Note("Price input file has been updated"); DateTime processStartedAt = DateTime.UtcNow; N.Note("Process started at :" + processStartedAt.ToString()); var pricePushLogger = new OperationsJsonLogger <PricePushResult>(Config.I.PricingPushAttemptsLogFile, processStartedAt); var properties = PricingPushCSVReader.ReadPricingData(pricePushLogger); PricingPushNotification pricingPushNotification = new PricingPushNotification(); if (properties != null) { pricingPushNotification.SendInitialNotification(processStartedAt); if (Config.I.PushPriceToAirBnb) { if (!string.IsNullOrEmpty(properties[0].AirbnbId)) { N.Note("Starting the price push to AirBnb"); pricePushLogger.Log(new PricePushResult(Channel.AirBnb, PricePushLogArea.ProcessStarted, PricingPushLogType.Information, "Pricing push process started at :" + DateTime.UtcNow.ToString())); PricingPushCSVReader.LogPropertiesForAirBnb(properties, pricePushLogger); // Kick start the Airbnb process. PricePush.PushPriceToAirBnb(processStartedAt, pricePushLogger, properties); N.Note("Pricing push to AirBnb is finished"); // Read the log files and send the email with respect to Airbnb. N.Note("Send notification email for AirBnb"); pricingPushNotification.SendNotification(processStartedAt); } } if (Config.I.PushPriceToStreamLine) { if (!string.IsNullOrEmpty(properties[0].StreamLineHomeId)) { N.Note("Starting the price push to Streamline"); pricePushLogger.Log(new PricePushResult(Channel.StreamLine, PricePushLogArea.ProcessStarted, PricingPushLogType.Information, "Pricing push process started at :" + DateTime.UtcNow.ToString())); PricingPushCSVReader.LogPropertiesForStreamLine(properties, pricePushLogger); // Kick start the Stream Line process StreamlinePricePush.PushPriceToStreamLine(processStartedAt, pricePushLogger, properties); N.Note("Pricing push to streamline is finished"); N.Note("Send notification email for Streamline"); pricingPushNotification.SendNotificationToStreamLine(processStartedAt); } } } }
/// <summary> /// Main method. /// </summary> /// <param name="args">Arguments which can be passed into the program.</param> public static void Main(string[] args) { Console.WriteLine("Begin pricing push to AirBnb"); var pricePushLogger = new OperationsJsonLogger <PricePushResult>(Config.I.PricingPushAttemptsLogFile, DateTime.UtcNow); var properties = PricingPushCSVReader.ReadPricingData(pricePushLogger); PricePush.PushPriceToAirBnb(DateTime.UtcNow, pricePushLogger, properties); Console.WriteLine("End pricing push to AirBnb"); }
private static bool NavigatToDailyPricingTab(int homeId, IWebDriver driver, OperationsJsonLogger <PricePushResult> pricePushLogger) { //div[@id='home_tabs']/ul[@class='yui-nav']//li/a/descendant::em[text()='Daily Pricing'] bool navigateToPricingTab = true; try { var dailyPricingLink = driver.FindElement(By.XPath("//div[@id='home_tabs']/ul[@class='yui-nav']//li/a/descendant::em[text()='Daily Pricing']")); dailyPricingLink.Click(); } catch (NoSuchElementException) { navigateToPricingTab = false; pricePushLogger.Log(new PricePushResult(Channel.StreamLine, PricePushLogArea.PriceUpdate, PricingPushLogType.Error, "Cannot navigate to daily pricing tab :" + homeId.ToString())); } return(navigateToPricingTab); }
static void Main(string[] args) { var config = new TemplateServiceConfiguration { DisableTempFileLocking = true, CachingProvider = new DefaultCachingProvider(t => { }) }; var logDate = DateTime.UtcNow.AddDays(-1); var loginAttemptsLogger = new OperationsJsonLogger <LoginAttempt>(Config.I.LoginAttemptsLogFile); var statistics = loginAttemptsLogger.GetStatistics(logDate); var passSyncAttemptsLogger = new OperationsJsonLogger <PasswordSyncError>(Config.I.PasswordSyncLogFile); var errors = passSyncAttemptsLogger.GetLogRecords(logDate) .Select(x => new { Description = x.ErrorType.ToDescription(), x.Date }); var templatePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var template = File.ReadAllText(Path.Combine(templatePath, "Templates/NotificationTemplate.cshtml")); using (var service = RazorEngineService.Create(config)) { var body = service.RunCompile(template, "NotificationEmailTemplate", null, new { statistics.ErrorsCount, LoginAttempts = statistics.ErrorLogins, TotalAccountsProcessed = statistics.LoginCount, PasswordSyncErrors = errors, ProxyErrors = statistics.InvalidProxies }); EmailNotification.Send(Config.I.NotificationsEmail, "Airbnb Export report", body); } passSyncAttemptsLogger.Clear(); passSyncAttemptsLogger.Clear(); }
static void Main(string[] args) { Logger.Setup(); Config.I.UseProxy = true; AirBnbAccounts.Load(); var yesterday = DateTime.Now.AddDays(-1); var yesterdayLockHash = yesterday.ToString("yyyy\\MMMM-d") + @"\lock"; var jsonLogger = new OperationsJsonLogger <LoginAttempt>(Config.I.LoginAttemptsLogFile); Temp.UnlockFolder(yesterdayLockHash); var logger = LogManager.GetLogger(typeof(Program)); var accounts = AirBnbAccounts.Accounts.Where(x => !string.IsNullOrEmpty(x.Password)).ToList(); foreach (var airAccount in accounts) { logger.Info(string.Format("processing {0} is started", airAccount.Email)); var transactionLoader = new TransactionLoader(airAccount, jsonLogger, logger); transactionLoader.DownloadTransactions(); } }
public static void PushPriceToStreamLine(DateTime processStartTime, OperationsJsonLogger <PricePushResult> pricePushLogger, List <Property> streamLineProperties) { try { using (RemoteWebDriver driver = SeleniumFactory.GetFirefoxDriver(null)) { // Login to the streamline system. StreamlineAccount streamLineAccount = new StreamlineAccount(); streamLineAccount.Login = Config.I.StreamLineAccountLogin; streamLineAccount.Password = Config.I.StreamLineAccountPassword; N.Note("Trying to login with the user :"******"Login succeeded"); WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60)); wait.Until(ExpectedConditions.ElementExists(By.Id("menu"))); N.Note("Check whether news dialog has popped up"); // Close the dialog which pop's up as soon as you login. StreamlineLogin.CheckNewsDialogPopup(driver); N.Note("Create season group"); List <Season> streamLineSeasons = new List <Season>(); string groupId = StreamlineSeasonProcesser.CreateSeasonGroup(driver, processStartTime); if (!string.IsNullOrEmpty(groupId) && groupId != "0") { N.Note("Created Group :" + StreamlineSeasonProcesser.GetSeasonGroupName(processStartTime)); // Filter the rates based on the valid dates N.Note("Filtering the valid property prices"); var validPropertyPrices = streamLineProperties[0].Prices.Where(x => x.SeasonEndDate > DateTime.UtcNow).ToList(); N.Note("Create Seasons for the season group"); foreach (Price season in validPropertyPrices) { Thread.Sleep(TimeSpan.FromSeconds(1)); var seasonId = StreamlineSeasonProcesser.CreateSeason(driver, groupId, season.SeasonStartDate, season.SeasonEndDate, season.MinimumLos); if (!string.IsNullOrEmpty(seasonId) && seasonId != "0") { N.Note("Created Season : " + StreamlineSeasonProcesser.GetSeasonName(season.SeasonStartDate, season.SeasonEndDate)); streamLineSeasons.Add(new Season { SeasonStartDate = season.SeasonStartDate, SeasonEndDate = season.SeasonEndDate, SeasonId = seasonId }); //season.SeasonId = seasonId; } else { pricePushLogger.Log(new PricePushResult(Channel.StreamLine, PricePushLogArea.Season, PricingPushLogType.Error, "Season was not created for the dates starting with " + season.SeasonStartDate.ToShortDateString() + " and ending with " + season.SeasonEndDate.ToShortDateString() + " for the season group" + StreamlineSeasonProcesser.GetSeasonGroupName(processStartTime))); } } } else { pricePushLogger.Log(new PricePushResult( Channel.StreamLine, PricePushLogArea.SeasonGroup, PricingPushLogType.Error, "Season group was not created : " + StreamlineSeasonProcesser.GetSeasonGroupName(processStartTime))); } foreach (Property streamLineProperty in streamLineProperties) { N.Note("Check whether property exists : " + streamLineProperty.StreamLineHomeName); // Check whether the property exists in streamline or not. if (StreamlineDailyPrice.CheckWhetherPropertyExists(driver, streamLineProperty.StreamLineHomeId)) { N.Note("Changing the default season group for the property to the new one"); if (StreamlineSeasonProcesser.ChangeSeasonGroup(driver, streamLineProperty.StreamLineHomeId, streamLineProperty.StreamLineHomeName, groupId)) { N.Note("Default season group changed successfully"); // Map the season id's to the corresponding season in the property foreach (Season season in streamLineSeasons) { var mappedPropertySeason = streamLineProperty.Prices.FirstOrDefault(p => p.SeasonStartDate == season.SeasonStartDate && p.SeasonEndDate == season.SeasonEndDate); if (mappedPropertySeason != null) { mappedPropertySeason.SeasonId = season.SeasonId; } } N.Note("Update season price for the unit"); StreamlineDailyPrice.SetPricesForUnit(driver, Convert.ToInt32(streamLineProperty.StreamLineHomeId), streamLineProperty.Prices, pricePushLogger); } else { N.Note("Changing the default season group failed"); pricePushLogger.Log(new PricePushResult( Channel.StreamLine, PricePushLogArea.Property, PricingPushLogType.Error, "The process was not able to update the default Season group of the property : " + streamLineProperty.StreamLineHomeName, Config.I.StreamLineAccountLogin, streamLineProperty.StreamLineHomeId, string.Empty, streamLineProperty.StreamLineHomeName, streamLineProperty.PropertyCode, string.Empty, string.Empty, string.Empty)); } } else { pricePushLogger.Log(new PricePushResult( Channel.StreamLine, PricePushLogArea.Property, PricingPushLogType.Error, "The property was not found in Streamline : " + streamLineProperty.StreamLineHomeName, streamLineAccount.Login, streamLineProperty.StreamLineHomeId, string.Empty, streamLineProperty.StreamLineHomeName, streamLineProperty.PropertyCode, string.Empty, string.Empty, string.Empty)); } } } else { pricePushLogger.Log(new PricePushResult( Channel.StreamLine, PricePushLogArea.Login, PricingPushLogType.Error, "Login failed for the user : "******"Pricing push to Streamline failed", ex.Message)); } }
public static void SetPricesForUnit(IWebDriver driver, int UnitEditId, List <Price> Prices, OperationsJsonLogger <PricePushResult> pricePushLog = null) { try { NavigateToPage(driver, UnitEditId); CloseControlPanel(driver); if (NavigatToDailyPricingTab(UnitEditId, driver, pricePushLog)) { SetPrices(driver, Prices, UnitEditId, pricePushLog); if (Submit(driver)) { pricePushLog.Log(new PricePushResult(Channel.StreamLine, PricePushLogArea.PriceUpdate, PricingPushLogType.Information, "Price updated successfully for the property: " + UnitEditId)); } } } catch (Exception ex) { pricePushLog.Log(new PricePushResult(Channel.StreamLine, PricePushLogArea.PriceUpdate, PricingPushLogType.Error, ex.Message, Config.I.StreamLineAccountLogin, UnitEditId.ToString(), string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty)); } }
/// <summary> /// Set the property's daily price for the various seasons. /// </summary> /// <param name="driver">Web driver.</param> /// <param name="dailyPrices">Daily prices.</param> private static void SetPrices(IWebDriver driver, List <Price> dailyPrices, int homeId, OperationsJsonLogger <PricePushResult> pricePushLogger) { foreach (Price price in dailyPrices) { try { // The delay here is needed so that the screen doesnt refresh like a bullet. Thread.Sleep(TimeSpan.FromMilliseconds(500)); if (string.IsNullOrEmpty(price.SeasonId) || price.SeasonId == "0") { continue; } string nameStartsWith = "value_1415"; string nameEndsWith = price.SeasonId + "_" + "price1"; var priceInput = driver.FindElement(By.XPath("//input[starts-with(@name,'" + nameStartsWith + "') and contains(@name,'" + nameEndsWith + "')]")); var readOnly = priceInput.GetAttribute("readonly"); if (readOnly == "true") { continue; } priceInput.Clear(); priceInput.SendKeys(price.PropertyPrice.ToString()); } catch (Exception ex) { pricePushLogger.Log(new PricePushResult(Channel.StreamLine, PricePushLogArea.PriceUpdate, PricingPushLogType.Error, ex.Message, Config.I.StreamLineAccountLogin, homeId.ToString(), price.SeasonStartDate.ToString("MMM dd") + " - " + price.SeasonEndDate.ToString("MMM dd") + " " + price.SeasonEndDate.Year.ToString(), string.Empty, // Property Name string.Empty, // Property Code price.PropertyPrice.ToString(), // Property Price ex.Message, // Exception Message string.Empty // Proxy IP )); } } }
internal TransactionLoader(AirBnbAccount airAccount, OperationsJsonLogger <LoginAttempt> loginAttemptsProcessor, ILog logger) { _airAccount = airAccount; _loginAttemptsProcessor = loginAttemptsProcessor; _logger = logger; }
/// <summary> /// Push price to airbnb. /// </summary> /// <param name="processStartTime">Process start time.</param> /// <param name="pricePushLogger">Price push logger.</param> /// <param name="airBnbProperties">List of airbnb properties.</param> public static void PushPriceToAirBnb(DateTime processStartTime, OperationsJsonLogger <PricePushResult> pricePushLogger, List <Property> airBnbProperties) { List <PricePushResult> pricePushLogResults = new List <PricePushResult>(); try { if (airBnbProperties != null) { // Group the properties by their login email id. var propertiesGroupedByEmail = airBnbProperties.GroupBy(x => x.LoginAccount.Email); if (propertiesGroupedByEmail != null) { foreach (var propertyGroup in propertiesGroupedByEmail) { // Get the property list that needs to be updated. List <Property> properties = propertyGroup.ToList(); // Setup the login acccount which should be used to login to the account. var loginAccount = properties[0].LoginAccount; AirBnbAccount account = new AirBnbAccount { Email = loginAccount.Email, Password = loginAccount.Password, ProxyAddress = loginAccount.ProxyAddress, Active = loginAccount.Active, Test = loginAccount.Test }; // Set the firefox profile. //var firefoxProfile = SeleniumProxy.GetFirefoxProfileWithProxy(account.ProxyAddress[0]); var chromeOptions = SeleniumProxy.GetChromeOptionsWithProxy(account.ProxyAddress[0]); try { using (RemoteWebDriver driver = SeleniumFactory.GetChromeDriver(chromeOptions)) //using (RemoteWebDriver driver = SeleniumFactory.GetFirefoxDriver(firefoxProfile)) { N.Note("Trying to login with the user :"******"Login succeeded"); foreach (Property property in properties) { var validPropertyPrices = property.Prices.Where(x => (x.SeasonEndDate.Date > DateTime.UtcNow.Date)); if (AirBnbCalendar.NavigateToCalendar(driver, property.AirbnbId)) { ///AirBnbCalendar.ZoomOut(driver); if (validPropertyPrices.Count() > 0) { string currentMonthYear = string.Empty; bool navigateToMonth = true; foreach (Price propPrice in validPropertyPrices) { int noOfDays = propPrice.NoOfDaysToBeUpdated(); if (string.Compare(currentMonthYear, propPrice.SeasonStartDate.Month.ToString() + propPrice.SeasonStartDate.Year.ToString(), true) != 0) { navigateToMonth = AirBnbCalendar.NavigateToMonth(driver, propPrice.SeasonStartDate.Month, propPrice.SeasonStartDate.Year); if (navigateToMonth) { currentMonthYear = propPrice.SeasonStartDate.Month.ToString() + propPrice.SeasonStartDate.Year.ToString(); } Thread.Sleep(TimeSpan.FromSeconds(2)); } if (navigateToMonth) { for (int i = 1; i <= noOfDays; i++) { DateTime startDate = propPrice.SeasonStartDate.AddDays(i); if (string.Compare(currentMonthYear, startDate.Month.ToString() + startDate.Year.ToString(), true) != 0) { AirBnbCalendar.NavigateToMonth(driver, startDate.Month, startDate.Year); Thread.Sleep(TimeSpan.FromSeconds(2)); } Thread.Sleep(TimeSpan.FromMilliseconds(700)); N.Note("Updating price for the day :" + propPrice.SeasonStartDate.AddDays(i).ToString("yyyy-MM-dd")); try { AirBnbCalendar.UpdateUnitPrice( driver, propPrice.SeasonStartDate.AddDays(i), propPrice.PropertyPrice); } catch (Exception ex) { PricingPushLogType logType = PricingPushLogType.Error; if (ex.GetType() == typeof(PriceUpdateInformation)) { logType = PricingPushLogType.Information; } LogPriceUpdationError(pricePushLogResults, PricePushLogArea.PriceUpdate, logType, property, propPrice.SeasonStartDate.AddDays(i), propPrice.PropertyPrice, ex.Message); } } } else { for (int startDay = 1; startDay <= noOfDays; startDay++) { LogPriceUpdationError(pricePushLogResults, PricePushLogArea.PriceUpdate, PricingPushLogType.Error, property, propPrice.SeasonStartDate.AddDays(startDay), propPrice.PropertyPrice, "Navigating to the month " + propPrice.SeasonStartDate.ToString("MMMM") + " in the calendar failed for the property " + property.AirbnbTitle); } } } } } else { LogError(pricePushLogResults, PricePushLogArea.Property, PricingPushLogType.Error, property, "Listing Id :" + property.AirbnbId + " for the property " + property.AirbnbTitle + " is wrong"); } RetryFailedPriceUpdates(driver, pricePushLogResults, property.AirbnbId); } } else { LogError(pricePushLogResults, PricePushLogArea.Login, PricingPushLogType.Error, signInSucceed.Message.Replace(System.Environment.NewLine, string.Empty)); try { driver.Quit(); } catch (Exception ex) { N.Note("Exception while closing the driver : " + ex.Message); } } } } catch (Exception ex) { LogError(pricePushLogResults, PricePushLogArea.Property, PricingPushLogType.Error, "Pricing push to AirBnb failed", ex.Message); } } } } } catch (Exception ex) { LogError(pricePushLogResults, PricePushLogArea.Property, PricingPushLogType.Error, "Pricing push to AirBnb failed", ex.Message); } finally { pricePushLogger.Log(pricePushLogResults); } }