Beispiel #1
0
 ///<summary>Viewに使うアイコンのURLを返す(ホスト名より後だけ)
 ///user_idとprofile_image_urlが必要</summary>
 public static string ProfileImageUrl(TweetData._user User, bool IsDefaultProfileImage)
 {
     if (User.local_profile_image_url == null)
     {
         return(null);
     }
     if (IsDefaultProfileImage)
     {
         return("/twimg/profile_image/" + '_' + Path.GetFileName(User.local_profile_image_url));
     }
     else
     {
         return("/twimg/profile_image/" + User.user_id.ToString() + Path.GetExtension(User.local_profile_image_url));
     }
 }
Beispiel #2
0
        /// <summary>
        /// Userテーブルを取得してオブジェクトに詰めるだけのやっつけメソッド
        /// cmd次第で何アカウント分でも取得できる
        /// </summary>
        /// <param name="cmd">GetUsersHeadで始まるSQL文を含むMySqlCommand</param>
        /// <returns></returns>
        async Task <TweetData._user[]> GetUsers(MySqlCommand cmd)
        {
            var users = new List <TweetData._user>();

            await ExecuteReader(cmd, (r) =>
            {
                var tmpuser = new TweetData._user()
                {
                    user_id                  = r.GetInt64(0),
                    name                     = r.GetString(1),
                    screen_name              = r.GetString(2),
                    isprotected              = r.GetBoolean(3),
                    local_profile_image_url  = r.GetString(4),
                    is_default_profile_image = r.GetBoolean(5),
                    location                 = r.IsDBNull(6) ? null : r.GetString(6),
                    description_html         = r.IsDBNull(7) ? null : LocalText.TextToLink(r.GetString(7))
                };
                tmpuser.local_profile_image_url = LocalText.ProfileImageUrl(tmpuser, r.GetBoolean(5));
                users.Add(tmpuser);
            }).ConfigureAwait(false);

            return(users.ToArray());
        }
Beispiel #3
0
        const int MultipleMediaOffset = 3;  //複画は今のところ4枚まで これを同ページに収めたいマン
        /// <summary>
        /// 指定したユーザーのタイムライン上のツイートをずらりと
        /// 鍵かつフォロー外なら何も出ない
        /// </summary>
        /// <param name="target_user_id"></param>
        /// <param name="login_user_id"></param>
        /// <param name="LastTweet"></param>
        /// <param name="TweetCount">最大件数(複画がラストに来ると増える)</param>
        /// <param name="SimilarLimit">類似画像の枚数上限(古い順)</param>
        /// <param name="GetRetweet">RTを含める</param>
        /// <param name="ShowNoDup">類似画像がない</param>
        /// <param name="Before">true→LastTweetより古いツイートを検索する/false→(同文)新しいツイート(同文)</param>
        /// <returns></returns>
        public async Task <SimilarMediaTweet[]> SimilarMediaTimeline(long target_user_id, long?login_user_id, long LastTweet, int TweetCount, int SimilarLimit, bool GetRetweet, bool ShowNoDup, bool Before)
        {
            //鍵垢のTLはフォローしてない限り表示しない
            //未登録のアカウントもここで弾かれる
            TweetData._user TargetUserInfo = await SelectUser(target_user_id).ConfigureAwait(false);

            if (TargetUserInfo != null && TargetUserInfo.isprotected && login_user_id != target_user_id)
            {
                if (login_user_id == null)
                {
                    return(new SimilarMediaTweet[0]);
                }
                using (MySqlCommand cmd = new MySqlCommand(@"SELECT COUNT(*) FROM friend WHERE user_id = @login_user_id AND friend_id = @target_user_id"))
                {
                    cmd.Parameters.Add("@login_user_id", MySqlDbType.Int64).Value  = login_user_id;
                    cmd.Parameters.Add("@target_user_id", MySqlDbType.Int64).Value = target_user_id;
                    switch (await SelectCount(cmd).ConfigureAwait(false))
                    {
                    case 0:
                        return(new SimilarMediaTweet[0]);

                    case -1:
                        throw new Exception("SelectCount() failed.");
                        //それ以外は↓の処理を続行する
                    }
                }
            }

            const long QueryRangeSnowFlake   = 90 * 1000 * SnowFlake.msinSnowFlake;
            long       QuerySnowFlake        = LastTweet;
            long       NowSnowFlake          = SnowFlake.Now(true);
            long       NoTweetSnowFlake      = 0;
            const long NoTweetLimitSnowFlake = 86400 * 1000 * SnowFlake.msinSnowFlake;
            const int  GiveupMilliSeconds    = 5000;
            Stopwatch  sw = new Stopwatch();

            sw.Start();

            CancellationTokenSource       CancelToken = new CancellationTokenSource();
            ExecutionDataflowBlockOptions op          = new ExecutionDataflowBlockOptions()
            {
                CancellationToken         = CancelToken.Token,
                MaxDegreeOfParallelism    = Environment.ProcessorCount,
                SingleProducerConstrained = true
            };
            string QueryText;

            if (GetRetweet)
            {
                QueryText = SimilarMediaHeadRT + @"
FROM friend f 
JOIN user ou ON f.friend_id = ou.user_id
JOIN tweet o USE INDEX (PRIMARY) ON ou.user_id = o.user_id
LEFT JOIN tweet rt ON o.retweet_id = rt.tweet_id
LEFT JOIN user ru ON rt.user_id = ru.user_id
JOIN tweet_media t ON COALESCE(rt.tweet_id, o.tweet_id) = t.tweet_id
JOIN media m ON t.media_id = m.media_id
LEFT JOIN tweet_text ot ON o.tweet_id = ot.tweet_id
LEFT JOIN tweet_text rtt ON rt.tweet_id = rtt.tweet_id
LEFT JOIN media_text mt ON m.media_id = mt.media_id
WHERE " + (ShowNoDup ? "" : @"(
    EXISTS (SELECT * FROM media WHERE dcthash = m.dcthash AND media_id != m.media_id)
    OR EXISTS (SELECT * FROM dcthashpairslim WHERE hash_small = m.dcthash)
    OR EXISTS (SELECT * FROM dcthashpairslim WHERE hash_large = m.dcthash)
) AND") + @"
o.tweet_id BETWEEN " + (Before ? "@time - @timerange AND @time" : "@time AND @time + @timerange") + @"
AND f.user_id = @target_user_id
AND (@login_user_id = @target_user_id
    OR ou.isprotected = 0 
    OR ou.user_id = @login_user_id
    OR EXISTS (SELECT * FROM friend WHERE user_id = @login_user_id AND friend_id = ou.user_id)
)
AND NOT EXISTS (SELECT * FROM block WHERE user_id = @login_user_id AND target_id = rt.user_id)
AND NOT EXISTS(
    SELECT *
    FROM friend fs
    JOIN user ous ON fs.user_id = ous.user_id
    JOIN tweet os ON ous.user_id = os.user_id
    WHERE os.retweet_id = rt.tweet_id
    AND fs.user_id = @target_user_id
    AND (@login_user_id = @target_user_id
        OR (ous.isprotected = 0
        OR ous.user_id = @login_user_id
        OR EXISTS (SELECT * FROM friend WHERE user_id = @login_user_id AND friend_id = ous.user_id))
    )
    AND o.tweet_id < os.tweet_id
)
ORDER BY o.tweet_id " + (Before ? "DESC" : "ASC") + " LIMIT @limitplus;";
            }
            else
            {
                QueryText = SimilarMediaHeadnoRT + @"
FROM friend f 
JOIN user ou ON f.friend_id = ou.user_id
JOIN tweet o USE INDEX (PRIMARY) ON ou.user_id = o.user_id
JOIN tweet_media t ON o.tweet_id = t.tweet_id
JOIN media m ON t.media_id = m.media_id
LEFT JOIN tweet_text ot ON o.tweet_id = ot.tweet_id
LEFT JOIN media_text mt ON m.media_id = mt.media_id
WHERE " + (ShowNoDup ? "" : @"(
    EXISTS (SELECT * FROM media WHERE dcthash = m.dcthash AND media_id != m.media_id)
    OR EXISTS (SELECT * FROM dcthashpairslim WHERE hash_small = m.dcthash)
    OR EXISTS (SELECT * FROM dcthashpairslim WHERE hash_large = m.dcthash)
) AND") + @"
f.user_id = @target_user_id
AND o.tweet_id BETWEEN " + (Before ? "@time - @timerange AND @time" : "@time AND @time + @timerange") + @"
AND o.retweet_id IS NULL
AND (@login_user_id = @target_user_id
    OR ou.user_id = @login_user_id
    OR ou.isprotected = 0
    OR EXISTS (SELECT * FROM friend WHERE user_id = @login_user_id AND friend_id = ou.user_id)
)
ORDER BY o.tweet_id " + (Before ? "DESC" : "ASC") + " LIMIT @limitplus;";
            }

            var GetTimelineBlock = new TransformBlock <int, SimilarMediaTweet[]>(
                async(int i) =>
            {
                using (MySqlCommand cmd = new MySqlCommand(QueryText))
                {
                    cmd.Parameters.Add("@target_user_id", MySqlDbType.Int64).Value = target_user_id;
                    cmd.Parameters.Add("@login_user_id", MySqlDbType.Int64).Value  = login_user_id;
                    cmd.Parameters.Add("@time", MySqlDbType.Int64).Value           = (Before ? QuerySnowFlake - QueryRangeSnowFlake * i : QuerySnowFlake + QueryRangeSnowFlake * i);
                    cmd.Parameters.Add("@timerange", MySqlDbType.Int64).Value      = QueryRangeSnowFlake;
                    //類似画像が表示できない画像を弾くときだけ多めに取得する
                    cmd.Parameters.Add("@limitplus", MySqlDbType.Int64).Value = ShowNoDup ? TweetCount : TweetCount + MultipleMediaOffset;
                    return(await TableToTweet(cmd, login_user_id, SimilarLimit, ShowNoDup).ConfigureAwait(false));
                }
            }, op);
            int PostedCount = 0;

            for (; PostedCount <= Environment.ProcessorCount; PostedCount++)
            {
                GetTimelineBlock.Post(PostedCount);
            }

            var ret           = new List <SimilarMediaTweet>();
            int RecievedCount = 0;

            do
            {
                var Tweets = await GetTimelineBlock.ReceiveAsync().ConfigureAwait(false);

                RecievedCount++;

                //ツイートがない期間が続いたら打ち切る
                if (Tweets.Length > 0)
                {
                    NoTweetSnowFlake = 0;
                }
                else
                {
                    NoTweetSnowFlake += QueryRangeSnowFlake;
                }

                //必要数が取得できたら打ち切る 複画の分だけ多めに取得する
                foreach (var tweet in Tweets)
                {
                    ret.Add(tweet);
                    if (ret.Count >= TweetCount + MultipleMediaOffset)
                    {
                        break;
                    }
                }

                if (Before || QuerySnowFlake + QueryRangeSnowFlake * (PostedCount - 1) < NowSnowFlake)   //未来は取得しない
                {
                    GetTimelineBlock.Post(PostedCount);
                    PostedCount++;
                }
            } while (PostedCount > RecievedCount && (ret.Count < TweetCount) &&
                     NoTweetSnowFlake < NoTweetLimitSnowFlake &&
                     sw.ElapsedMilliseconds < GiveupMilliSeconds);
            CancelToken.Cancel();

            if (!Before)
            {
                ret.Reverse();
            }
            //TableToTweetで類似画像が表示できないやつが削られるので
            //多めに拾ってきて溢れた分を捨てる
            //あと複画は件数超えても同ページに入れる
            for (int i = TweetCount; i < ret.Count; i++)
            {
                if (ret[i].tweet.tweet_id != ret[TweetCount - 1].tweet.tweet_id)
                {
                    return(ret.Take(i - 1).ToArray());
                }
            }
            return(ret.ToArray());
        }