Ejemplo n.º 1
0
        private void SendMail(App app, AppUpdate update) {
            ICollection<AppTrack> tracks = repository.AppTrack.RetrieveByApp(app.Id);
            foreach (AppTrack track in tracks) {
                User user = repository.User.Retrieve(track.User);
                if (track.RequireNotification(user, update.Type)) {
                    MailMessage message = CreateMailMessage(user, app, update);

                    if (settings.Debug) {
                        StringBuilder text = new StringBuilder()
                            .AppendLine("Send mail:")
                            .AppendLine("From: " + message.From.Address)
                            .AppendLine("To: " + message.To[0].Address)
                            .AppendLine("Subject: " + message.Subject)
                            .AppendLine(message.Body);
                        logger.Trace(text.ToString());
                    }
                    else {
                        try {
                            smtp.Send(message);
                            logger.Trace(
                                "Sent mail to user {0}-{1} via {2} for update{3}",
                                user.Id, user.Username, user.Email, update.Id
                            );
                        }
                        catch (SmtpFailedRecipientException) {
                            logger.Warn("Failed to send email to {0}, address may be invalid", user.Email);
                        }
                        catch (Exception ex) {
                            logger.ErrorException("Encountered unexpected exception when send email", ex);
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public ICollection<AppUpdate> CheckForUpdate(AppBrief newOne) {
            DateTime now = DateTime.Now;
            List<AppUpdate> updates = new List<AppUpdate>();
            // 检查版本
            if (Version != newOne.Version) {
                AppUpdate update = new AppUpdate() {
                    App = Id,
                    Time = now,
                    NewValue = newOne.Version,
                    OldValue = Version,
                    Type = AppUpdateType.NewRelease,
                };
                updates.Add(update);
            }
            // 检查价格,价格单位有变动时涉及换算问题,不计入价格变化中
            if (Price != newOne.Price && Currency == newOne.Currency) {
                AppUpdate update = new AppUpdate() {
                    App = Id,
                    Time = now,
                    NewValue = newOne.Price.ToString(),
                    OldValue = Price.ToString(),
                    Type = newOne.Price == 0 ? AppUpdateType.PriceFree :
                        (newOne.Price > Price ? AppUpdateType.PriceIncrease : AppUpdateType.PriceDecrease)
                };
                updates.Add(update);
            }

            return updates;
        }
Ejemplo n.º 3
0
 public void ProcessUpdate(App app, AppUpdate update) {
     lock (UpdateData) {
         if (!UpdateData.ContainsKey(app)) {
             UpdateData[app] = new List<AppUpdate>();
         }
         UpdateData[app].Add(update);
     }
 }
Ejemplo n.º 4
0
        public void ProcessUpdate(App app, AppUpdate update) {
            /*
             * 1. 把所有AppTrack的HasRead改回false
             * 2. 发送邮件通知用户
             */

            int trackCount = repository.AppTrack.ResetReadStatusByApp(update.App);
            logger.Trace("Set {0} tracks to unread for app {1}-{2}", trackCount, app.Id, app.Brief.Name);

            SendMail(app, update);
        }
Ejemplo n.º 5
0
        public void Save(AppUpdate update) {
            update.Id = Guid.NewGuid();

            string sql =
@"insert into `AppUpdate` (
    `Id`, `App`, `Time`, `Type`, `OldValue`, `NewValue`
) values (
    ?Id, ?App, ?Time, ?Type, ?OldValue, ?NewValue
);";
            MySqlCommand command = connection.CreateCommand();
            command.CommandText = sql;
            command.Parameters.AddWithValue("?Id", update.Id.ToString("N"));
            command.Parameters.AddWithValue("?App", update.App);
            command.Parameters.AddWithValue("Time", update.Time);
            command.Parameters.AddWithValue("?Type", update.Type);
            command.Parameters.AddWithValue("?OldValue", update.OldValue);
            command.Parameters.AddWithValue("?NewValue", update.NewValue);
            command.ExecuteNonQuery();
        }
Ejemplo n.º 6
0
        private MailMessage CreateMailMessage(User user, App app, AppUpdate update) {
            MailMessage message = new MailMessage(
                new MailAddress(settings.MailAddress, settings.MailUser, Encoding.UTF8),
                new MailAddress(user.Email)
            );
            message.SubjectEncoding = Encoding.UTF8;
            message.Subject = String.Format(subjects[update.Type], app.Brief.Name, update.OldValue, update.NewValue);
            message.BodyEncoding = Encoding.UTF8;
            message.IsBodyHtml = true;
            message.Body = String.Format(
                templates[update.Type],
                user.Username,
                app.Brief.Name,
                update.OldValue,
                update.NewValue,
                app.Id,
                app.Brief.ViewUrl,
                DateTime.Now,
                app.ReleaseNotes
            );

            return message;
        }
Ejemplo n.º 7
0
 public static AppUpdate ToAppUpdate(this IDataRecord record) {
     AppUpdate update = new AppUpdate() {
         App = record.GetInt32("App"),
         Id = record.GetGuid("Id"), 
         NewValue = record.GetString("NewValue"), 
         OldValue = record.GetString("OldValue"), 
         Type = (AppUpdateType)record.GetInt32("Type"), 
         Time = record.GetDateTime("Time")
     };
     return update;
 }
Ejemplo n.º 8
0
 public void Save(AppUpdate update) {
     appUpdates.Save(update);
 }
Ejemplo n.º 9
0
        private static int MigrateAppUpdates(int offset, int batchSize) {
            var command = souce.CreateCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = "select App, Time, Type, OldValue, NewValue from AppUpdate limit ?offset, ?batchSize";
            command.Parameters.AddWithValue("?offset", offset);
            command.Parameters.AddWithValue("?batchSize", batchSize);

            List<AppUpdate> updates = new List<AppUpdate>();

            Stopwatch watch = new Stopwatch();
            watch.Start();

            using (var reader = command.ExecuteReader()) {
                while (reader.Read()) {
                    AppUpdate update = new AppUpdate() {
                        App = reader.GetInt32(0),
                        Time = reader.GetDateTime(1),
                        Type = (AppUpdateType)reader.GetInt32(2),
                        OldValue = reader.GetString(3),
                        NewValue = reader.GetString(4)
                    };

                    // 新建和加入到应用的2个更新,在新系统中使用的是NewValue,需要换过来
                    if (update.Type == AppUpdateType.New || update.Type == AppUpdateType.AddToPing) {
                        update.NewValue = update.OldValue;
                        update.OldValue = String.Empty;
                    }

                    // 现有AppStore中国区全部是用人民币作为价格,因此将美元全部换回人民币
                    if (update.Type == AppUpdateType.PriceIncrease ||
                        update.Type == AppUpdateType.PriceDecrease ||
                        update.Type == AppUpdateType.PriceFree) {
                        // 价格相关的更新,OldValue和NewValue都是价格直接值
                        float oldPrice = Single.Parse(update.OldValue);
                        float newPrice = Single.Parse(update.NewValue);
                        if ((int)oldPrice != oldPrice) {
                            update.OldValue = priceMapping[oldPrice].ToString();
                        }
                        if ((int)newPrice != newPrice) {
                            update.NewValue = priceMapping[newPrice].ToString();
                        }
                    }
                    else if (update.Type == AppUpdateType.New ||
                        update.Type == AppUpdateType.AddToPing ||
                        update.Type == AppUpdateType.Revoke) {
                        // 另外几个更新,用的是{version, $price}的形式,需要分隔开来再计算
                        string[] oldValueParts = update.OldValue.Split(new string[] { ", " }, StringSplitOptions.None);
                        string[] newValueParts = update.NewValue.Split(new string[] { ", " }, StringSplitOptions.None);
                        if (oldValueParts.Length > 1) {
                            float oldPrice = Single.Parse(oldValueParts.Last().Substring(1));
                            if ((int)oldPrice != oldPrice) {
                                oldValueParts[oldValueParts.Length - 1] = priceMapping[oldPrice].ToString();
                                update.OldValue = String.Join(", ", oldValueParts);
                            }
                        }
                        if (newValueParts.Length > 1) {
                            float newPrice = Single.Parse(newValueParts.Last().Substring(1));
                            if ((int)newPrice != newPrice) {
                                newValueParts[newValueParts.Length - 1] = priceMapping[newPrice].ToString();
                                update.NewValue = String.Join(", ", newValueParts);
                            }
                        }
                    }
                    // 版本更新不需要动

                    updates.Add(update);
                }
            }

            watch.Stop();
            Console.WriteLine("Retrieved {0} updates using {1}", updates.Count, watch.Elapsed);

            watch.Reset();
            watch.Start();

            using (MySqlTransaction transaction = destination.BeginTransaction()) {
                foreach (AppUpdate update in updates) {
                    repository.AppUpdate.Save(update);
                }
                transaction.Commit();
            }

            watch.Stop();
            Console.WriteLine("Saved to mongo using {0}", watch.Elapsed);

            return updates.Count;
        }
Ejemplo n.º 10
0
        public void Save(App app) {
            AppUpdate updateForNew = new AppUpdate() {
                App = app.Id,
                Time = app.Brief.ReleaseDate.Date,
                Type = AppUpdateType.New,
                NewValue = app.Brief.Version + ", " + app.Brief.PriceWithSymbol
            };
            appUpdates.Save(updateForNew);
            AppUpdate updateForAdd = new AppUpdate() {
                App = app.Id,
                Time = DateTime.Now,
                Type = AppUpdateType.AddToPing,
                NewValue = app.Brief.Version + ", " + app.Brief.PriceWithSymbol
            };
            appUpdates.Save(updateForAdd);

            app.Brief.LastValidUpdate = updateForAdd;
            apps.Save(app);
        }
Ejemplo n.º 11
0
        private void RevokeApps(RepositoryEmitter repository) {
            Stopwatch watch = new Stopwatch();
            watch.Start();

            foreach (App app in revokedApps) {
                // 添加下架信息
                AppUpdate update = new AppUpdate() {
                    App = app.Id,
                    Type = AppUpdateType.Revoke,
                    OldValue = app.Brief.Version + ", " + app.Brief.PriceWithSymbol,
                    Time = DateTime.Now
                };
                repository.AppUpdate.Save(update);

                // 从在售应用中移除
                repository.App.Delete(app.Id);

                // 添加到下架应用中
                RevokedApp revoked = new RevokedApp(app);
                revoked.RevokeTime = DateTime.Now;
                repository.App.SaveRevoked(revoked);

                // 移除全文索引
                indexer.DeleteApp(app);

                logger.Trace("Set app {0}-{1} to be revoked", app.Id, app.Brief.Name);
            }

            watch.Stop();
            logger.Info("Revoked {0} apps using {1}ms", revokedApps.Count, watch.ElapsedMilliseconds);

            watch.Reset();
            watch.Stop();

            indexer.Flush();

            watch.Stop();
            logger.Info("Deleted index for {0} apps using {1}ms", revokedApps.Count, watch.ElapsedMilliseconds);
        }
Ejemplo n.º 12
0
 public static IHtmlString UpdateDescrioption(this HtmlHelper helper, AppUpdate update) {
     if (update.Type == AppUpdateType.New || update.Type == AppUpdateType.AddToPing || update.Type == AppUpdateType.Revoke) {
         return helper.Raw(update.OldValue);
     }
     else if (update.Type == AppUpdateType.NewRelease) {
         return helper.Raw(update.OldValue + " -> " + update.NewValue);
     }
     else {
         char unit = update.Time < unitChangeDate ? '$' : '¥';
         return helper.Raw(unit + update.OldValue + " -> " + unit + update.NewValue);
     }
 }
Ejemplo n.º 13
0
        private void TryRescue(IEnumerable<RevokedApp> apps) {
            int[] identities = apps.Select(a => a.Id).ToArray();
            ICollection<App> retrievedApps = appParser.RetrieveApps(identities);

            if (retrievedApps == null) {
                return;
            }

            foreach (App resurrected in retrievedApps) {
                // 添加重新上架信息
                AppUpdate update = new AppUpdate() {
                    App = resurrected.Id,
                    NewValue = resurrected.Brief.Version + ", " + resurrected.Brief.PriceWithSymbol,
                    Time = DateTime.Now,
                    Type = AppUpdateType.Resurrect
                };
                repository.AppUpdate.Save(update);

                // 从下架应用中移除
                repository.App.DeleteRevoked(resurrected.Id);

                // 重新加入到应用集合中,并标记最后更新
                resurrected.Brief.LastValidUpdate = update;
                repository.App.Save(resurrected);

                // 添加到全文索引
                indexer.AddApp(resurrected);

                logger.Trace("Resurrected app {0}-{1}", resurrected.Id, resurrected.Brief.Name);
            }

            Stopwatch watch = new Stopwatch();
            watch.Start();

            indexer.Flush();

            watch.Stop();
            logger.Debug("Indexed {0} apps using {1}ms", retrievedApps.Count, watch.ElapsedMilliseconds);
        }