Beispiel #1
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            Hash            hash = new Hash(request.Address.Split('/').Last());
            List <NanoPost> all  = new List <NanoPost>(_db.GetExpandedThreadPosts(hash));

            //
            // recursively hide posts
            foreach (NanoPost p in all)
            {
                if (_db.IsHidden(p.GetHash()))
                {
                    var children = _db.GetExpandedThreadPosts(p.GetHash());

                    foreach (var child in children)
                    {
                        _db.Hide(child.GetHash());
                    }
                }
            }

            List <NanoPost> list = new List <NanoPost>(all.Where(p => !_db.IsHidden(p.GetHash())));

            new PngContainerCreator(_db).CreateWithList(list);
            return(new NanoHttpResponse(StatusCode.Ok, "\n"));
        }
Beispiel #2
0
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            Hash thread = new Hash(request.Address.Split('/').Last());

            if (thread.Invalid)
            {
                return(new ErrorHandler(StatusCode.BadRequest, "Wrong hash format.").Handle(request));
            }

            var sb = new StringBuilder();
            var p  = _db.Get(thread);

            sb.Append("{\n    \"hash\" :    \"");
            sb.Append(p.GetHash().Value);
            sb.Append("\", \n    \"isHidden\" : \"");
            sb.Append(_db.IsHidden(p.GetHash()) ? "1" : "0");
            sb.Append("\", \n    \"replyTo\" : \"");
            sb.Append(p.ReplyTo.Value);
            sb.Append("\", \n    \"message\" : \"");

            string s = p.SerializedString().Substring(32);

            s = s.Replace("\\", "\\\\");
            s = s.Replace("\n", "\\n");
            s = s.Replace("\"", "\\\"");
            s = s.Replace("\t", "\\t");
            s = s.Replace("\r", "\\r");
            sb.Append(s);
            sb.Append("\"\n}");

            return(new NanoHttpResponse(StatusCode.Ok, sb.ToString(), "application/json; charset=utf-8"));
        }
Beispiel #3
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            Hash hash = new Hash(request.Address.Split('/').Last());

            if (hash.Invalid)
            {
                return(new ErrorHandler(StatusCode.BadRequest, "Invalid hash").Handle(request));
            }

            try
            {
                if (_db.IsHidden(hash))
                {
                    _db.Unhide(hash);
                }

                else
                {
                    _db.Hide(hash);
                }

                return(new NanoHttpResponse(StatusCode.Ok, "\n"));
            }

            catch (Exception e)
            {
                return(new ErrorHandler(StatusCode.InternalServerError, e.ToString().Replace("\n", "<br>")).Handle(request));
            }
        }
Beispiel #4
0
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            int n = int.Parse(request.Address.Split('/').Last());

            var sb = new StringBuilder();
            var p  = _db.GetPost(n);

            sb.Append("{\n    \"hash\" :    \"");
            sb.Append(p.GetHash().Value);
            sb.Append("\", \n    \"isHidden\" : \"");
            sb.Append(_db.IsHidden(p.GetHash()) ? "1" : "0");
            sb.Append("\", \n    \"replyTo\" : \"");
            sb.Append(p.ReplyTo.Value);
            sb.Append("\", \n    \"message\" : \"");

            string s = p.SerializedString().Substring(32);

            s = s.Replace("\\", "\\\\");
            s = s.Replace("\n", "\\n");
            s = s.Replace("\"", "\\\"");
            s = s.Replace("\t", "\\t");
            s = s.Replace("\r", "\\r");
            sb.Append(s);
            sb.Append("\"\n}");

            return(new NanoHttpResponse(StatusCode.Ok, sb.ToString(), "application/json; charset=utf-8"));
        }
Beispiel #5
0
 public static NanoPost[] ExceptHidden(this NanoPost[] posts, NanoDB db)
 {
     if (db.IsHiddenListEmpty())
     {
         return(posts);
     }
     return(posts.Where(p => !db.IsHidden(p.GetHash())).ToArray());
 }
Beispiel #6
0
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            Hash thread = new Hash(request.Address.Split('/').Last());

            if (thread.Invalid)
            {
                return(new ErrorHandler(StatusCode.BadRequest, "Wrong hash format.").Handle(request));
            }

            var sb = new StringBuilder();

            sb.Append("{ \n    \"posts\" : [\n");

            var posts = _expanded ? _db.GetExpandedThreadPosts(thread) : _db.GetThreadPosts(thread);

            for (int i = 0; i < posts.Length; i++)
            {
                var  p    = posts[i];
                bool last = i == posts.Length - 1;
                sb.Append("    {\n        \"hash\" :    \"");
                sb.Append(p.GetHash().Value);
                sb.Append("\", \n        \"isHidden\" : \"");
                sb.Append(_db.IsHidden(p.GetHash()) ? "1" : "0");
                sb.Append("\", \n        \"replyTo\" : \"");
                sb.Append(p.ReplyTo.Value);
                sb.Append("\", \n        \"message\" : \"");

                string s = p.SerializedString().Substring(32);
                s = s.Replace("\\", "\\\\");
                s = s.Replace("\n", "\\n");
                s = s.Replace("\"", "\\\"");
                s = s.Replace("\t", "\\t");
                s = s.Replace("\r", "\\r");
                sb.Append(s);
                sb.Append("\"\n    }");
                if (!last)
                {
                    sb.Append(",\n");
                }
            }

            sb.Append("\n    ]\n}");

            return(new NanoHttpResponse(StatusCode.Ok, sb.ToString(), "application/json; charset=utf-8"));
        }
Beispiel #7
0
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            int count = int.Parse(request.Address.Split('/').Last());

            var sb = new StringBuilder();

            sb.Append("{ \n    \"posts\" : [\n");

            var posts = _db.GetNLastPosts(count);

            for (int i = 0; i < posts.Length; i++)
            {
                var  p    = posts[i];
                bool last = i == posts.Length - 1;
                sb.Append("    {\n        \"hash\" :    \"");
                sb.Append(p.GetHash().Value);
                sb.Append("\", \n        \"isHidden\" : \"");
                sb.Append(_db.IsHidden(p.GetHash()) ? "1" : "0");
                sb.Append("\", \n        \"replyTo\" : \"");
                sb.Append(p.ReplyTo.Value);
                sb.Append("\", \n        \"message\" : \"");

                string s = p.SerializedString().Substring(32);
                s = s.Replace("\\", "\\\\");
                s = s.Replace("\n", "\\n");
                s = s.Replace("\"", "\\\"");
                s = s.Replace("\t", "\\t");
                s = s.Replace("\r", "\\r");
                sb.Append(s);
                sb.Append("\"\n    }");
                if (!last)
                {
                    sb.Append(",\n");
                }
            }

            sb.Append("\n    ]\n}");

            return(new NanoHttpResponse(StatusCode.Ok, sb.ToString(), "application/json; charset=utf-8"));
        }
        /*
         *  Takes 50 or less last posts (up to 150000 bytes max total),
         *  adds  50 or less random posts (up to 150000 bytes max total),
         *  random is shifted towards latest posts.
         */
        public void Create()
        {
            var count   = _db.GetPostCount();
            var take    = 50;
            var last50s = _db.GetNLastPosts(take * 4).ExceptHidden(_db).Reverse().Take(take).ToArray();
            var list    = new List <NanoPost>(last50s);

            while (!ByteCountUnder(list, 150000))
            {
                list.RemoveAt(list.Count - 1);
            }

            var r      = new Random();
            int rbytes = 0;
            int max    = 50;

            for (int i = 0; i < max; i++)
            {
                int index = (int)Math.Min(Math.Pow(r.NextDouble(), 0.3) * count, count - 1);
                var p     = _db.GetPost(index);
                if (_db.IsHidden(p.GetHash()))
                {
                    if (max < 10000)
                    {
                        max += 1;
                    }
                    continue;
                }
                var bc = ByteCount(p);
                if (rbytes + bc > 150000)
                {
                    break;
                }
                rbytes += bc;
                list.Add(p);
            }
            CreateWithList(list);
        }
Beispiel #9
0
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            _places  = HtmlStringExtensions.UpdatePlaces().ToArray();
            _allowed = HtmlStringExtensions.UpdateAllowed();
            var sw = new System.Diagnostics.Stopwatch();

            sw.Start();

            Hash thread = null;

            if (request.Address != "/")
            {
                thread = new Hash(request.Address.Split('/').Last());

                if (thread.Invalid)
                {
                    return(new ErrorHandler(StatusCode.BadRequest, "Wrong hash format.").Handle(request));
                }
            }
            else
            {
                thread = new Hash(NanoDB.CategoriesHashValue);
            }

            var sb = new StringBuilder();

            AddHeader(sb);
            string s1 = "";

            if (thread.Value != NanoDB.CategoriesHashValue)
            {
                s1  = "<a href='#' onclick='history.go(-1)'>[Назад]</a>";
                s1 += "<a href='#' onclick='location.reload()'>[Обновить]</a>";

                if (!_expand)
                {
                    s1 += "<a href='#' onclick='window.location.href=window.location.toString().replace(\"thread\",\"expand\")'>[Развернуть]</a>";
                }
                else
                {
                    s1 += "<a href='#' onclick='window.location.href=window.location.toString().replace(\"expand\",\"thread\")'>[Свернуть]</a>";
                }
            }
            else
            {
                s1 = "<a href='#' onclick='location.reload()'>[Обновить]</a>";
            }

            sb.Append(s1.ToDiv("", ""));

            NanoPost[] posts = null;

            /*
             * if (!_expand)
             *  posts = _db.GetThreadPosts(thread).ExceptHidden(_db);
             * else
             *  posts = _db.GetExpandedThreadPosts(thread).ExceptHidden(_db);
             */

            if (!_expand)
            {
                posts = _db.GetThreadPosts(thread);
            }
            else
            {
                posts = _db.GetExpandedThreadPosts(thread);
            }

            bool first = true;

            if (!_expand)
            {
                posts = posts.OrderByDescending(p => p.NumberTag).ToArray();
            }

            string postScript = "";

            foreach (var sp in posts)
            {
                var p = sp;
                //string pMessage = p.Message;
                string pMessage = p.Message.Strip(true);

                var fmPattern = "\\[fm=.*\\]";
                var music     = Regex.Matches(pMessage, fmPattern);

                int musicNum = 0;

                foreach (var m in music)
                {
                    musicNum += 1;
                    var value   = (m as Match).Value;
                    var formula = value.Substring(4).TrimEnd(']').Replace("&gt;", ">").Replace("&lt;", "<").Replace("<grn>", "").Replace("</grn>", "").Replace("&nbsp;", " ").
                                  Replace("’", "'").Replace("“", "\"").Replace(";", "");
                    var  strictFmPattern = "()t *0123456789abcdefxABCDEF|><!%:^&.-+/?=~";
                    bool invalid         = formula.Length > 8192;
                    if (!invalid)
                    {
                        foreach (var ch in formula)
                        {
                            if (!strictFmPattern.Contains(ch))
                            {
                                invalid = true;
                                break;
                            }
                        }
                    }
                    if (invalid)
                    {
                        continue;
                    }
                    var replacement = string.Format(@"<b>Фрактальная музыка:</b>
    <small><pre>{1}</pre></small><button id='mb{0}'>Сгенерировать</button>
    <audio style='visibility:hidden;' controls='false' id='au{0}'></audio>", sp.GetHash().Value + musicNum, formula);
                    postScript += "document.getElementById('mb" + sp.GetHash().Value + musicNum +
                                  "').onclick = function() { addFractalMusic(function(t){return " + formula +
                                  ";}, 210*8000, 'au" + sp.GetHash().Value + musicNum + "');" +
                                  "this.parentNode.removeChild(this);"
                                  + "}\n";
                    pMessage = pMessage.Replace(value, replacement);
                }

                string numTag = (p.NumberTag == int.MaxValue ? "" : "<grn><sup>#" + p.GetHash().Value.ShortenHash() + "</sup></grn> ");
                bool   hidden = false;

                if (_db.IsHidden(p.GetHash()))
                {
                    hidden = true;
                }

                string handler  = "/expand/";
                bool   corePost = false;

                if (p.GetHash().Value == NanoDB.RootHashValue ||       // root
                    p.ReplyTo.Value == NanoDB.RootHashValue ||         // root
                    p.GetHash().Value == NanoDB.CategoriesHashValue || // categories
                    p.ReplyTo.Value == NanoDB.CategoriesHashValue)     // categories
                {
                    handler  = "/thread/";
                    corePost = true;
                }

                if (_db.Get(p.ReplyTo) != null &&
                    (_db.Get(p.ReplyTo).ReplyTo.Value == NanoDB.CategoriesHashValue ||
                     _db.Get(p.ReplyTo).ReplyTo.Value == NanoDB.RootHashValue))
                {
                    corePost = true;
                }

                Func <NanoPost, string> addRefs = pst => {
                    var children = _db.GetThreadPosts(pst.GetHash(), eraseDepth: false);
                    var refs1    = "<br/><div><small>";
                    int line     = 0;
                    foreach (var ch in children)
                    {
                        if (ch.GetHash().Value != pst.GetHash().Value)
                        {
                            line  += 1;
                            refs1 += "<a href='#" + ch.GetHash().Value + "'><i>&gt;&gt;" + ch.GetHash().Value.ShortenHash() + "</i></a>";
                            if (line > 5)
                            {
                                line   = 0;
                                refs1 += "</br>";
                            }
                        }
                    }
                    refs1 += "</small></div>";
                    return(refs1);
                };

                if (_expand && first && !p.GetHash().Zero&& !p.ReplyTo.Zero)
                {
                    string refs = "";

                    if (p.ReplyTo.Value != NanoDB.CategoriesHashValue &&
                        p.ReplyTo.Value != NanoDB.RootHashValue && _expand)
                    {
                        refs = addRefs(p);
                    }

                    sb.Append(
                        (
                            (numTag + pMessage + refs).Replace("\n", "<br/>").ToDiv("postinner", p.GetHash().Value) +
                            ("[Вверх]".ToRef((corePost ? "/thread/" : "/expand/") + p.ReplyTo.Value) +
                             //("[В закладки]").ToRef("/bookmark/" + p.GetHash().Value) +
                             ("<a onclick='show_reply(\"" + p.GetHash().Value + "\")'>[Быстрый ответ]</a>") + ("[Ответить]").ToRef("/reply/" + p.GetHash().Value)).ToDiv("", "")
                        ).ToDiv("post", ""));
                    first = false;
                    continue;
                }

                first = false;
                int    answers = _db.CountAnswers(p.GetHash());
                string ans     = "ответ";

                int a = answers % 100;
                if (a == 0 || a % 10 == 0 || (a > 10 && a < 20))
                {
                    ans += "ов";
                }
                else if (a % 10 >= 2 && a % 10 <= 4)
                {
                    ans += "а";
                }
                else if (a % 10 >= 5 && a % 10 <= 9)
                {
                    ans += "ов";
                }

                if (p.GetHash().Value == _db.RootHash.Value)
                {
                    sb.Append(
                        (
                            (@"    Добро пожаловать на Наноборду!
    Это корневой нанопост. 
    В целях тестирования на него можно было отвечать в предыдущих версиях. 
    Это немного засорило Главную. Рекомендуется почистить её у себя вручную.
    Негласное правило: отвечать нужно на конкретное сообщение, а не просто ""в тред"", полагаясь на то, что сообщение выше вашего будет таким же и у других - порядок попадания нанопостов к другим участникам сложно предсказать.
    Создавать тред желательно в соответствующей категории."
                            ).Strip().Replace("\n", "<br/>").ToDiv("postinner", p.GetHash().Value) +
                            //(("[Ответить]").ToRef("/reply/" + p.GetHash().Value)).ToDiv("", "") +
                            ("[Развернуть всё (осторожно!)]").ToRef("/expand/f682830a470200d738d32c69e6c2b8a4").ToDiv("", "") +
                            ("[Категории]").ToRef("/thread/bdd4b5fc1b3a933367bc6830fef72a35").ToDiv("", "")
                        ).ToDiv("post main", ""));
                }
                else
                {
                    string refs = "";

                    if (p.ReplyTo.Value != NanoDB.CategoriesHashValue &&
                        p.ReplyTo.Value != NanoDB.RootHashValue && _expand)
                    {
                        refs = addRefs(p);
                    }

                    sb.Append(
                        (
                            ((_expand?("<a href='#" + p.ReplyTo.Value + "'><i>&gt;&gt;" + p.ReplyTo.Value.ShortenHash() + "</i></a><br/>"):"") + numTag + pMessage + refs).Replace("\n", "<br/>").ToStyledDiv("postinner", p.GetHash().Value, hidden?"visibility:hidden;height:0px;":"") +
                            ((answers > MinAnswers ? ("[" + answers + " " + ans + "]").ToRef(handler + p.GetHash().Value) : "") +
                             (p.GetHash().Value != "bdd4b5fc1b3a933367bc6830fef72a35" ?
                              (
                                  (hidden?"[Вернуть]":"[Удалить]").ToButton("", "", @"var x = new XMLHttpRequest(); x.open('POST', '../hide/" + p.GetHash().Value + @"', true);
                        x.send('');
                        var elem = document.getElementById('" + p.GetHash().Value + @"');
                        if (elem.style.visibility != 'hidden') {
                            elem.style.visibility='hidden';
                            elem.style.height = '0px';
                            innerHTML = '[Вернуть]';
                        } else { 
                            elem.style.visibility='visible';
                            elem.style.height = '100%';
                            innerHTML = '[Удалить]';
                        }
                        ")) : "") +
                             //("[В закладки]").ToRef("/bookmark/" + p.GetHash().Value) +
                             ("[Дамп]".ToPostRef("/dump/" + p.GetHash().Value)) +
                             ("<a onclick='show_reply(\"" + p.GetHash().Value + "\")'>[Быстрый ответ]</a>") + ("[Ответить]").ToRef("/reply/" + p.GetHash().Value)).ToDiv("", "")
                        ).ToStyledDiv("post", "", "position:relative;left:" + p.DepthTag * 20 + "px;"));
                }
            }

            sb.Append(s1.ToDiv("", ""));

            sw.Stop();

            sb.Append("<div><br>места:");
            var places = _places.Where(l => !l.StartsWith("#")).ToList();

            places.ForEach(p => sb.Append(string.Format("<br><a target='_blank' href='{0}'>{0}</a>" +
                                                        "<a target='_blank' href='/del/{0}'>[-]</a>", p)));
            sb.Append("</div>");

            AddFooter(sb, sw.ElapsedMilliseconds, _db);

            var result = sb.ToString();

            /*
             * if (!_expand)
             *  sb.Append("Развернуть".ToButton("", "", "window.location.href=window.location.toString().replace('thread','expand')").ToDiv("",""));
             * else
             *  sb.Append("Обновить".ToButton("", "", "location.reload()").ToDiv("",""));
             */
            return(new NanoHttpResponse(StatusCode.Ok, result.AddVideo().AddReply().ToHtmlBody(JQueryMinJs + JQueryUiMinJs + Base64Js + FractalMusicScript + BitSendJs + PostScript(postScript))));
        }
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            var sw = new System.Diagnostics.Stopwatch();

            sw.Start();

            var sb = new StringBuilder();

            ThreadViewHandler.AddHeader(sb);

            sb.Append(string.Format("<div>Количество правил игнорирования постов: {0}. Настройте spamfilter.txt под себя.</div>", SpamDetector.RuleCount));

            sb.Append("[Очистить список]".ToButton("", "", @"
                var x = new XMLHttpRequest(); 
                x.open('POST', '../save/', true);
                x.send('');
                location.reload();
            ").ToDiv("", ""));

            var posts = _db.GetNewPosts();//.ExceptHidden(_db);

            posts = posts.Reverse().ToArray();

            foreach (var p in posts)
            {
                int    answers = _db.CountAnswers(p.GetHash());
                string ans     = "ответ";
                if (answers != 11 && answers % 10 == 1)
                {
                    //
                }
                else if (answers != 11 && answers % 10 == 5)
                {
                    ans += "ов";
                }
                else
                {
                    ans += "а";
                }

                bool corePost = false;

                if (_db.Get(p.ReplyTo) != null &&
                    (_db.Get(p.ReplyTo).ReplyTo.Value == NanoDB.CategoriesHashValue ||
                     _db.Get(p.ReplyTo).ReplyTo.Value == NanoDB.RootHashValue))
                {
                    corePost = true;
                }

                bool hidden = _db.IsHidden(p.GetHash());
                sb.Append(
                    (
                        p.Message.Strip(true).Replace("\n", "<br/>").ToStyledDiv("postinner", p.GetHash().Value, hidden?"visibility:hidden;height:0px;":"") +
                        ((answers > ThreadViewHandler.MinAnswers ? ("[" + answers + " " + ans + "]").ToRef("/expand/" + p.GetHash().Value):"") +
                         (hidden?"[Вернуть]":"[Удалить]").ToButton("", "", @"var x = new XMLHttpRequest(); x.open('POST', '../hide/" + p.GetHash().Value + @"', true);
                        x.send('');
                        var elem = document.getElementById('" + p.GetHash().Value + @"');
                        if (elem.style.visibility != 'hidden') {
                            elem.style.visibility='hidden';
                            elem.style.height = '0px';
                            innerHTML = '[Вернуть]';
                        } else { 
                            elem.style.visibility='visible';
                            elem.style.height = '100%';
                            innerHTML = '[Удалить]';
                        }
                        ") +
                         (p.ContainerTag != null ?
                          "[Отклонить контейнер]".ToButton("", "", @"var x = new XMLHttpRequest(); x.open('POST', '../hideall/" + p.GetHash().Value + @"', true);
                        x.send('');location.reload();") : "") +
                         //("[В закладки]").ToRef("/bookmark/" + p.GetHash().Value) +
                         ("[В тред]").ToRef((corePost?"/thread/":"/expand/") + p.ReplyTo.Value) +
                         ("[Ответить]").ToRef("/reply/" + p.GetHash().Value)).ToDiv("", "")
                    ).ToDiv("post", ""));
            }

            string s1 = "<a href='#' onclick='location.reload()'>[Обновить]</a>";

            sb.Append(s1.ToDiv("", ""));

            sw.Stop();
            ThreadViewHandler.AddFooter(sb, sw.ElapsedMilliseconds, _db);

            return(new NanoHttpResponse(StatusCode.Ok, sb.ToString().ToHtmlBody(ThreadViewHandler.NotifierScript)));
        }
        public void SaveToPngContainer(NanoDB db)
        {
            db.RewriteDbExceptHidden();
            db.ClearDb();
            db.ReadPosts();

            string[] ext   = new[] { ".png", ".jpg", ".jpeg" };
            var      files = new DirectoryInfo(Strings.Containers).GetFiles().Where(f => ext.Contains(f.Extension.ToLower())).ToArray();

            if (files.Length == 0)
            {
                NotificationHandler.Instance.AddNotification("Не найдены PNG файлы в папке containers.");
                return;
            }
            else if (files.Length <= 5)
            {
                if (!_smaller)
                {
                    NotificationHandler.Instance.AddNotification("Предупреждение: у вас мало контейнеров.");
                }
            }

            FileInfo file          = files[random.Next(files.Length - 1)];
            var      bmp           = new Bitmap(file.FullName);
            int      capacity      = (int)(bmp.Width * bmp.Height * 3 / 8) - 32;
            string   sessionPrefix = random.Next().ToString("x8");

            sessionPrefix += random.Next().ToString("x8");

            var packed = new byte[0];

            var posts = new List <NanoPost>();

            int i = db.GetPostCount() - 1;

            while (i >= 0 && posts.Count < FreshPosts)
            {
                var p = db.GetPost(i--);

                if (!db.IsHidden(p.GetHash()))
                {
                    posts.Add(p);
                }
            }

            var parr = posts.ToArray();

            var parents = new List <NanoPost>();

            foreach (var post in parr)
            {
                var p = db.Get(post.ReplyTo);

                if (p != null && !db.IsHidden(p.GetHash()))
                {
                    parents.Add(p);
                }
            }

            foreach (var post in parents)
            {
                posts.Add(post);
                var p = db.Get(post.ReplyTo);

                if (p != null && !db.IsHidden(p.GetHash()))
                {
                    posts.Add(p);
                }
            }

            var slice0 = posts.GetRange(0, Math.Max(posts.Count, FreshPostsNotLimitedTo16384Allowed));
            var slice1 = posts.GetRange(slice0.Count, posts.Count - slice0.Count);

            posts.Clear();
            posts.AddRange(slice0);
            posts.AddRange(slice1.ToArray().FilterBySize(16384));
            posts.AddRange(db.GetNRandomPosts(RandomPostsLimitedTo8192ALlowed).ExceptHidden(db).FilterBySize(8192));
            posts.AddRange(db.GetNRandomPosts(RandomPostsLimitedTo16384Allowed).ExceptHidden(db).FilterBySize(16384));
            posts  = posts.Distinct().ToList();
            packed = NanoPostPackUtil.Pack(posts.ToArray());

            float scale = 1;

            if (packed.Length > capacity)
            {
                scale = (packed.Length / (float)capacity);
                scale = (float)Math.Sqrt(scale);

                if (scale > 2 && !_smaller)
                {
                    new PngContainerCreatorNew(4).SaveToPngContainer(db);
                    return;
                }

                bmp = new Bitmap(bmp, (int)(bmp.Width * scale + 1), (int)(bmp.Height * scale + 1));
            }

            new PngStegoUtil().HideBytesInPng(
                bmp,
                Strings.Upload + Path.DirectorySeparatorChar + sessionPrefix + Strings.PngExt,
                packed);

            Console.WriteLine(
                string.Format(
                    "PNG capacity:{0}, posts amount:{1}, packed size:{2}, image scaling: {3:n2}x",
                    capacity, posts.Count, packed.Length, scale));

            Console.WriteLine("Total posts in db: {0}, post length limit (bytes): {1}", db.GetPostCount(), NanoPost.MaxPostByteLength);

            NotificationHandler.Instance.AddNotification("Контейнер сохранён: " + Strings.Upload + Path.DirectorySeparatorChar + sessionPrefix + Strings.PngExt);
        }
        public void SaveToPngContainer(NanoDB db)
        {
            db.RewriteDbExceptHidden();
            db.ClearDb();
            db.ReadPosts();

            string[] ext = new[] { ".png", ".jpg", ".jpeg" };
            var files = new DirectoryInfo(Strings.Containers).GetFiles().Where(f => ext.Contains(f.Extension.ToLower())).ToArray();

            if (files.Length == 0)
            {
                NotificationHandler.Instance.AddNotification("Не найдены PNG файлы в папке containers.");
                return;
            }
            else if (files.Length <= 5)
            {
                if (!_smaller)
                {
                    NotificationHandler.Instance.AddNotification("Предупреждение: у вас мало контейнеров.");
                }
            }

            FileInfo file = files[random.Next(files.Length - 1)];
            var bmp = new Bitmap(file.FullName);
            int capacity = (int)(bmp.Width * bmp.Height * 3 / 8) - 32;
            string sessionPrefix = random.Next().ToString("x8");
            sessionPrefix += random.Next().ToString("x8");

            var packed = new byte[0];

            var posts = new List<NanoPost>();

            int i = db.GetPostCount() - 1;

            while (i >= 0 && posts.Count < FreshPosts)
            {
                var p = db.GetPost(i--);

                if (!db.IsHidden(p.GetHash()))
                {
                    posts.Add(p);
                }
            }

            var parr = posts.ToArray();

            var parents = new List<NanoPost>();

            foreach (var post in parr)
            {
                var p = db.Get(post.ReplyTo);

                if (p != null && !db.IsHidden(p.GetHash()))
                {
                    parents.Add(p);
                }
            }

            foreach (var post in parents)
            {
                posts.Add(post);
                var p = db.Get(post.ReplyTo);

                if (p != null && !db.IsHidden(p.GetHash()))
                {
                    posts.Add(p);
                }
            }

            var slice0 = posts.GetRange(0, Math.Max(posts.Count, FreshPostsNotLimitedTo16384Allowed));
            var slice1 = posts.GetRange(slice0.Count, posts.Count - slice0.Count);
            posts.Clear();
            posts.AddRange(slice0);
            posts.AddRange(slice1.ToArray().FilterBySize(16384));
            posts.AddRange(db.GetNRandomPosts(RandomPostsLimitedTo8192ALlowed).ExceptHidden(db).FilterBySize(8192));
            posts.AddRange(db.GetNRandomPosts(RandomPostsLimitedTo16384Allowed).ExceptHidden(db).FilterBySize(16384));
            posts = posts.Distinct().ToList();
            packed = NanoPostPackUtil.Pack(posts.ToArray());

            float scale = 1;

            if (packed.Length > capacity)
            {
                scale = (packed.Length / (float)capacity);
                scale = (float)Math.Sqrt(scale);

                if (scale > 2 && !_smaller)
                {
                    new PngContainerCreatorNew(4).SaveToPngContainer(db);
                    return;
                }

                bmp = new Bitmap(bmp, (int) (bmp.Width * scale + 1), (int) (bmp.Height * scale + 1));
            }

            new PngStegoUtil().HideBytesInPng(
                        bmp,
                        Strings.Upload + Path.DirectorySeparatorChar + sessionPrefix + Strings.PngExt,
                        packed);

            Console.WriteLine(
                string.Format(
                    "PNG capacity:{0}, posts amount:{1}, packed size:{2}, image scaling: {3:n2}x",
                        capacity, posts.Count, packed.Length, scale));

            Console.WriteLine("Total posts in db: {0}, post length limit (bytes): {1}", db.GetPostCount(), NanoPost.MaxPostByteLength);

            NotificationHandler.Instance.AddNotification("Контейнер сохранён: " + Strings.Upload + Path.DirectorySeparatorChar + sessionPrefix + Strings.PngExt);
        }
 public static NanoPost[] ExceptHidden(this NanoPost[] posts, NanoDB db)
 {
     if (db.IsHiddenListEmpty()) return posts;
     return posts.Where(p => !db.IsHidden(p.GetHash())).ToArray();
 }