Example #1
0
        /// <summary>
        /// 撤销一个订阅者已有的订阅(如果没有订阅,不会进行任何操作)
        /// </summary>
        /// <param name="subscriberId">订阅者 ID</param>
        /// <param name="targetId">目标 ID</param>
        /// <param name="targetType">目标类型</param>
        /// <exception cref="ArgumentNullException">有参数为 null</exception>
        public async Task RemoveAsync([NotNull] string subscriberId, [NotNull] string targetId,
                                      SubscriptionTargetType targetType)
        {
            if (subscriberId == null)
            {
                throw new ArgumentNullException(nameof(subscriberId));
            }
            if (targetId == null)
            {
                throw new ArgumentNullException(nameof(targetId));
            }

            if (subscriberId == targetId || !await IsSubscribedAsync(subscriberId, targetId, targetType))
            {
                return;
            }

            var subscriptions = await _dbContext.Subscriptions.Where(s => s.SubscriberId == subscriberId &&
                                                                     s.TargetId == targetId &&
                                                                     s.TargetType == targetType)
                                .ToListAsync();

            _dbContext.Subscriptions.RemoveRange(subscriptions);
            await _dbContext.SaveChangesAsync();

            var redisDb  = _redis.GetDatabase();
            var cacheKey = UserSubscribedTargetsCacheKey(subscriberId);

            foreach (var subscription in subscriptions)
            {
                await redisDb.SetRemoveAsync(cacheKey,
                                             UserSubscribedTargetCacheValue(subscription.TargetId, subscription.TargetType));
            }
            await IncreaseSubscriberCountAsync(targetId, targetType, -subscriptions.Count);
        }
Example #2
0
        public async Task <IHttpActionResult> DeleteOne(string targetId, SubscriptionTargetType targetType)
        {
            var subscriberId = User.Identity.GetUserId();
            await _cachedData.Subscriptions.RemoveAsync(subscriberId, targetId, targetType);

            return(Ok());
        }
Example #3
0
        /// <summary>
        /// 添加一个新订阅(如果已经订阅,不会进行任何操作)
        /// </summary>
        /// <param name="subscriberId">订阅者 ID</param>
        /// <param name="targetId">目标 ID</param>
        /// <param name="targetType">目标类型</param>
        /// <returns>订阅成功返回 <c>true</c></returns>
        /// <exception cref="ArgumentNullException">有参数为 null</exception>
        public async Task <bool> AddAsync([NotNull] string subscriberId, [NotNull] string targetId,
                                          SubscriptionTargetType targetType)
        {
            if (subscriberId == null)
            {
                throw new ArgumentNullException(nameof(subscriberId));
            }
            if (targetId == null)
            {
                throw new ArgumentNullException(nameof(targetId));
            }

            if (subscriberId == targetId || await IsSubscribedAsync(subscriberId, targetId, targetType))
            {
                return(false);
            }

            _dbContext.Subscriptions.Add(new Subscription
            {
                SubscriberId = subscriberId,
                TargetId     = targetId,
                TargetType   = targetType
            });
            await _dbContext.SaveChangesAsync();

            var redisDb = _redis.GetDatabase();
            await redisDb.SetAddAsync(UserSubscribedTargetsCacheKey(subscriberId),
                                      UserSubscribedTargetCacheValue(targetId, targetType));

            await IncreaseSubscriberCountAsync(targetId, targetType, 1);

            return(true);
        }
Example #4
0
        /// <summary>
        /// 判断指定用户是否订阅过指定目标
        /// </summary>
        /// <param name="userId">用户 ID</param>
        /// <param name="targetId">目标 ID</param>
        /// <param name="targetType">目标类型</param>
        /// <returns>如果用户订阅过,返回 <c>true</c></returns>
        public async Task <bool> IsSubscribedAsync(string userId, string targetId, SubscriptionTargetType targetType)
        {
            if (userId == null || targetId == null)
            {
                return(false);
            }
            var cacheKey = await InitUserSubscribedTargetsAsync(userId);

            return(await _redis.GetDatabase()
                   .SetContainsAsync(cacheKey, UserSubscribedTargetCacheValue(targetId, targetType)));
        }
Example #5
0
        private async Task IncreaseSubscriberCountAsync([NotNull] string targetId, SubscriptionTargetType targetType,
                                                        long value)
        {
            var cacheKey = TargetSubscriberCountCacheKey(targetId, targetType);
            var redisDb  = _redis.GetDatabase();

            if (await redisDb.KeyExistsAsync(cacheKey))
            {
                if (value >= 0)
                {
                    await redisDb.StringIncrementAsync(cacheKey, value);
                }
                else
                {
                    await redisDb.StringDecrementAsync(cacheKey, -value);
                }
            }
        }
Example #6
0
        /// <summary>
        /// 获取指定目标的订阅者数量
        /// </summary>
        /// <param name="targetId">目标 ID</param>
        /// <param name="targetType">目标类型</param>
        /// <exception cref="ArgumentNullException"><paramref name="targetId"/> 为 null</exception>
        /// <returns>目标的订阅者数量</returns>
        public async Task <long> GetSubscriberCountAsync([NotNull] string targetId, SubscriptionTargetType targetType)
        {
            if (targetId == null)
            {
                throw new ArgumentNullException(nameof(targetId));
            }
            var cacheKey    = TargetSubscriberCountCacheKey(targetId, targetType);
            var redisDb     = _redis.GetDatabase();
            var cacheResult = await redisDb.StringGetAsync(cacheKey);

            if (cacheResult.HasValue)
            {
                await redisDb.KeyExpireAsync(cacheKey, CachedDataProvider.DefaultTtl);

                return((long)cacheResult);
            }

            var subscriberCount = await _dbContext.Subscriptions
                                  .LongCountAsync(s => s.TargetId == targetId && s.TargetType == targetType);

            await redisDb.StringSetAsync(cacheKey, subscriberCount, CachedDataProvider.DefaultTtl);

            return(subscriberCount);
        }
Example #7
0
        public async Task <IHttpActionResult> CreateOne(string targetId, SubscriptionTargetType targetType)
        {
            var        subscriberId = User.Identity.GetUserId();
            bool       existed;
            KeylolUser targetUser = null;

            switch (targetType)
            {
            case SubscriptionTargetType.Point:
                existed = await _dbContext.Points.AnyAsync(p => p.Id == targetId);

                break;

            case SubscriptionTargetType.User:
                if (subscriberId.Equals(targetId, StringComparison.OrdinalIgnoreCase))
                {
                    return(this.BadRequest(nameof(targetId), Errors.Invalid));
                }
                targetUser = await _userManager.FindByIdAsync(targetId);

                existed = targetUser != null;
                break;

            case SubscriptionTargetType.Conference:
                existed = await _dbContext.Conferences.AnyAsync(c => c.Id == targetId);

                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(targetType), targetType, null);
            }
            if (!existed)
            {
                return(this.BadRequest(nameof(targetId), Errors.NonExistent));
            }
            var succeed = await _cachedData.Subscriptions.AddAsync(subscriberId, targetId, targetType);

            if (targetType == SubscriptionTargetType.User && succeed)
            {
                Debug.Assert(targetUser != null, "targetUser != null");
                var subscriberCount =
                    (int)await _cachedData.Subscriptions.GetSubscriberCountAsync(targetId, targetType);

                if (targetUser.NotifyOnSubscribed)
                {
                    await _cachedData.Messages.AddAsync(new Message
                    {
                        Type       = MessageType.NewSubscriber,
                        OperatorId = subscriberId,
                        ReceiverId = targetId,
                        Count      = subscriberCount
                    });
                }
                if (targetUser.SteamNotifyOnSubscribed)
                {
                    var subscriber = await _userManager.FindByIdAsync(subscriberId);

                    await _userManager.SendSteamChatMessageAsync(targetUser,
                                                                 await _cachedData.Users.IsFriendAsync(subscriberId, targetId)
                                                                 ?$"用户 {subscriber.UserName} 成为了你的第 {subscriberCount} 位听众,并开始与你互相关注。换句话说,你们已经成为好友啦!"
                                                                 : $"用户 {subscriber.UserName} 关注了你并成为你的第 {subscriberCount} 位听众,你们之间互相关注后会成为好友。");
                }
            }
            return(Ok());
        }
Example #8
0
 private static string TargetSubscriberCountCacheKey(string targetId, SubscriptionTargetType targetType) =>
 $"subscriber-count:{targetType.ToString().ToCase(NameConventionCase.PascalCase, NameConventionCase.DashedCase)}:{targetId}";
Example #9
0
 private static string UserSubscribedTargetCacheValue(string targetId, SubscriptionTargetType targetType) =>
 $"{targetType.ToString().ToCase(NameConventionCase.PascalCase, NameConventionCase.DashedCase)}:{targetId}";