Программер, одержимый идеей децентрализации денег
14,4
рейтинг
17 декабря 2015 в 13:30

Разработка → Как я 8 месяцев переписывал свою криптовалюту с PHP на Go. Часть 2



2-я часть истории, которая началась с смс-ки от Кати «Не звони и не пиши мне больше!!!!»

Первая часть тут. Для тех, кому лень читать, приведу краткое изложение:

4,5 года назад я имел неосторожность начать писать свою криптовалюту на совсем неподходящем для этого дела языке — на PHP. В итоге, конечно, написал (я упрямый), но получился костыль на костыле и то, что оно вообще работало было просто какой-то магией.
Сразу хочу предупредить, программер я самоучка-недоучка и пишу код, мягко сказать, неидеально.

Началось всё с того, что я расстался с девушкой, по имени Катя и в этот же день (4 апреля 2015-го) решил изучить Go и переписать свою криптовалюту. Для тех, кому интересно, что там с Катей, я сделал спойлеры, ну а кому не интересно, просто не обращайте внимание на Катю

Для тех, кто не читал 1-ю часть про Катю
Расскажу сперва как всё началось. Познакомился я с ней в интернете на сайте знакомств в начале 2015-го. Влюбился почти сразу. Уж больно внешне она была в моем вкусе. Гуляли по парку, шутили, смеялись, прикалывались, стало холодно, расставаться не хотелось. Позвал к себе мультики смотреть. Сели в такси, приехали. Включил «Три богатыря: Ход конем», очень смешной мультик, лежали на кровати, смеялись до слез.

Поздний вечер, я уверен, что Катя останется на ночь. Но она почему-то стала твердить, что ей надо домой. Я сказал, что хочу накормить её завтраком в постели. Договорись, что завтра утром она приедет завтракать. Вызвал такси, она уехала. Уснул счастливым, т.к. нашел себе красивую девушку, с которой весело и интересно. На следующий день от неё пришла смс-ка «Привет. Чем занимаешься?». Помню свои ощущения, ведь мне написала девушка, которая мне очень нравится, это было кайфово. И скоро мы с ней должны были снова встретиться…

В тот день мы так и не встретились. И на следующий тоже. Я не знаю, что у неё происходило в голове, но она постоянно переносила свидания. Даже не поздравила с 23 февраля.
Решил её как-то растормошить. Написал Кате смс-ку: «скоро буду, конечно захвачу»
Она ответила: «в смысле?»
Я: «упс, не туда»
Она: «вот значит как»
У неё включилась ревность. Через день предложил встретиться, она согласилась.

Проанализировав её поведение и, немного погуглив, я наткнулся на книгу «Новые правила. Секреты успешных отношений для современных девушек»
За вечер прочитал и понял, что она меня зачем-то в себя влюбляет, используя советы из этой книжки.

Итог 8 месяцев: приложение работает на Win (64/32), OSX(64/32), Linux(64/32), FreeBSD(64/32), Android, IOS (будет круто, если кто-то закинет в App Store).
Общего кода ~73к строк, кода под разные ОС где-то несколько сотен строчек.
40к — обработка/генерация блоков/тр-ий, 17.5к — контроллеры для интерфейса, 15.5к — шаблоны
Поддерживаются PostgreSQL, SQLite, MySQL.

Тех, кто будет тестировать мое творение, предупреждаю — могут быть баги, и если у Вас есть время, чиркните о них, пожалуйста, на darwin@dcoin.club или в личку на хабре. Пожелания и советы тоже приветствуются.

В первой части я рассказал про то, как в dcoin функционирует веб-сервер.

В этой статье опишу, как я использую html/template

Шаблоны


Для генерации html-страниц в Go есть очень удобный пакет — html/template. Проще всего понять, как он работает, можно поэкспериментировав вот с этим примером. Как правило, шаблоны хранятся в отдельных html-файлах, но в примерах на play.golang.org, для наглядности, шаблоны вставлены в go-код.

Большую часть информации по шаблонам я получил с gohugo.io/templates/go-templates

Шаблоны у меня лежат тут. Каждый шаблон начинается с определения его имени {{ define «templateName» }}, а заканчивается {{end}}

Контроллеры, которые использует шаблоны получают html код через функцию makeTemplate. В неё я передаю название html-файла, имя шаблона (которое в {{define}} указано), параметры.

TemplateStr, err := makeTemplate("template_name", "templateName", &tplPage{
		Alert:          c.Alert,
		Lang:           c.Lang,
		TxType:         txType,
		TxTypeId:       txTypeId})

Полученный в TemplateStr набор байт передается content.go и в итоге браузер получает сформированную html-страничку

В makeTemplate для всех шаблонов я подключаю дополнительные шаблоны, такие как signatures.html, alert_success.html. А также, добавляю пользовательские функции (FuncMap), которые используются для обработки данных в шаблонах.

Про Катю
На втором свидании мы просто гуляли, болтали. Всё было хорошо. Про мою смс-ку «скоро буду, конечно захвачу» она, к моему счастью, ничего не сказала.
Мне не давал покоя вопрос о книге, по которой она, как мне казалось, влюбляет меня в себя. Спросить прямо я не решился. Поинтересовался, чего читает. Она назвала каких-то авторов. На вопрос о книгах про психологию, ответила, что почитывает для себя.
Было холодно. Проводил до дома. Договорились на днях пойти на каток.

Включения в шаблоны


Чтобы включить в шаблон другой шаблон нужно использовать такую конструкцию {{ template «signatures». }}. Точка в конце говорит о том, что нужно обработать все параметры в шаблоне signatures, без точки параметры не будут обработаны. signatures я добавляю практически во все шаблоны, вот пример

Параметры


Сравнение. Приведу сразу несколько примеров, чтобы показать, как всё просто:
{{if not .UserID}} <span>Пусто</span> {{end}}
{{if .UserID}} <span>Не пусто</span> {{end}}
{{if eq .UserID 0}} <span>UserID == 0</span> {{end}}
{{if ne .UserID 0}} <span>UserID != 0</span> {{end}}
{{if lt .UserID 0}} <span>UserID < 0</span> {{end}}
{{if le .UserID 0}} <span>UserID <= 0</span> {{end}}
{{if gt .UserID 0}} <span>UserID > 0</span> {{end}}
{{if ge .UserID 0}} <span>UserID >= 0</span> {{end}}

{{.Lang.pool} — Lang — это карта. Т.е. через точку мы получаем значение, у которого ключ «pool»

Про Катю
Примерно неделю я не писал и не звонил ей. Решил проверить, позвонит ли она первой. Было капец как сложно, мучился, но ждал её звонка, хотел что бы она нарушила правила из книжки.
В итоге сдался. Написал ей, позвал в кино. Она сказала, что сегодня не может, т.к. переезжает. От помощи с переездом отказалась.

Забегу немного вперед и скажу, что после той самой смс-ки «Не звони и не пиши мне больше!!!!», я в ВК переманил на свою сторону её подружку, с которой она жила 2 года, чтобы та помогала мне вернуть Катю. Так вот, её подружка, сказала, что всю ту неделю, когда я не звонил, Катя очень переживала и ждала звонка от меня. Еще она рассказала, что после первого свидания Катя буквально светилась от радости. Также она добавила, что никакую книгу по соблазнению она не читала.

Пользовательские функции


html-код в переменных нужно дизэскейпить. Для этого необходимо добавить функцию:

funcMap := template.FuncMap{
	"noescape": func(s string) template.HTML {
		return template.HTML(s)
	},
}

Все пользовательские функции у меня собраны в makeTemplate. Использовать так:

{{noescape .Lang.htmlText}}

Про Катю
Близилось 8-е марта. Катя всё никак не хотела со мной встретиться. А я очень хотел поздравить её с праздником. В итоге я поставил вопрос ребром. Либо встречаемся 8-го марта, либо я ей больше не позвоню. Договорились отметить праздник у меня.

Купил её любимые цветы, вино и пр. Хотел весь день провести с ней, но к обеду она была еще не готова, через час тоже и через два. К моему удивлению, к шести часам она, наконец, собралась. Я вызвал ей такси.

Range


Чтобы разобрать какую-нибудь карту используется Range. Вот пример, взятый отсюда:

{{range $k, $country := .Countries}}
<option value='{{$k}}' {{if eq $k $.MyCountry}} selected {{end}}>{{$country}}</option>
{{end}}

Из кода, наверное, понятно, что происходит. Но хочу обратить особое внимание на $.MyCountry. Если не добавить $, тогда доступа к параметру .MyCountry не будет. Я по началу очень часто об этом забывал и долго думал, что не так. За пределами range доступ к MyCountry снова получается через {{.MyCountry}}

Про Катю
Приехала, вручил цветы, подарки. Открыл бутылку вина. Она увидела на одном из мониторов мои старые PHP-исходники. Спросила — «Что это?». Я рассказал ей про блокчейн, про то, как Dcoin, благодаря природному желанию людей получать прибыль («не вставая с дивана»), сможет завладеть умами миллионов, плавно заменив обычные валюты на децентрализованные, затем эмиссия остановится и у нас будет новый мир с прозрачной финансовой системой. Катя ничего не поняла. Потом смотрели какой-то фильм, целовались. Вдруг закончилось вино, я просил, хочет ли она еще, она сказала, что хочет. Я ушел в магазин.

Переменные


В шаблонах можно создавать свои переменные. Вот пример, взятый отсюда:

{{range $i, $pageType := .PagesArray}}
	{{$counter := ""}}
	{{if eq $pageType "funders"}}
		{{$counter := " <span class='count h6 bg-grey-dark white'>{{$.ProjectCountFunders}}</span>"}}
	{{else if eq $pageType "comments"}}
		{{$counter := " <span class='count h6 bg-grey-dark white'>{{$.ProjectCountComments}}</span>"}}
	{{end}}
	{{$counter}}
{{end}}

В данном примере создается новая переменная $counter, которой присваивается значение, в зависимости от условия, и ниже выводится ее результат

and/or


Несколько непривычной для меня оказалась логика работы and/or.
Примеры:

{{if and (eq .Start 1) (ne .BlockId 1) (gt .UserId 0)}}

Если .Start == 1 и .BlockId != 1 и .UserId > 0

{{if or (eq .Start 1) (ne .BlockId 1) (gt .UserId 0)}}

Если .Start == 1 или .BlockId != 1 или .UserId > 0

JS-код


Еще одна проблема отняла у меня довольно много времени. Если в контроллере нужно сформировать какой-то js-код, например:

var x="1";

То при выводе его в шаблоне через {{.SomeJSCode}} мы получим

"var x=\"1\";"

Решение 1


noescape тут не поможет. Нужно добавить новую пользовательскую функцию:

"js": func(s string) template.JS {
			return template.JS(s)
		},

И в шаблоне использовать {{js .SomeJSCode}}

Решение 2


В контроллере использовать тип template.JS. Предварительно преобразовав переменную string: template.JS(SomeJsStringVariable). В самом шаблоне в таком случае нужно выводить {{.SomeJSCode}}

Про Катю
Вернулся, допили вино. Достал массажное масло. Около часа делал массаж (на днях специально изучил вот это видео). Массаж плавно перевел в кое-что более интимное, в результате чего она испытала резкий выброс эндорфинов, и сразу после этого сказала, что хочет спать. «Что за фигня?» — подумал я. В общем, легли спать.
Продолжение в следующей части.

Заключение


В следующих статьях я расскажу про БД, плавное завершение приложения через сигналы, обработку блоков из блокчейна, шифрование в GO и расшифровку в JS, про то, как я, немного изменил gomobile, добавив уведомления и работу в фоне для IOS и Android приложений.
Дмитрий Харитонов @c-darwin
карма
70,0
рейтинг 14,4
Программер, одержимый идеей децентрализации денег
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (62)

  • +43
    О, снова статья про Катю :)
    • +2
      Да уж, разбил бы на два поста, а то все время внимание отвлекается.

      и вот почему
      Приходится спойлеры раскрывать! Да, не ту часть текста поста автор в них указал.
  • +18
    Я один читал только спойлеры????
    • +20
      изъезжено
    • +6
      Как и в первой статье — читал только про Катю.

      Щас все из предыдущей статьи соберутся, чтобы почитать про Катю :D
    • +10
      Нет конечно. К статье можно даже добавить голосование:
      • читал только про Катю
      • не читал про Катю
      • читал все

      Подозреваю какой будет результат.
      • +9
        * Не читал, сразу перешел к комментам
        • +10
          Вы не читали про Катю? 8-0
          Зачем вы вообще живете?
      • +18
        ещё один вариант: Я Катя, вечером тебя ждёт серьёзный разговор.
    • 0
      Вы украли мой коммент — это раз, а во-вторых, ваш коммент не первый, так что по обоим пунктам «неуд.» :)
  • +10
    А есть видео...? То есть, а видео будет?
    • +10
      про Катю?
      • –1
        Какая еще Катя? Стрим про шаблоны в Go!
  • +2
    Рекомендую переименовать вашу статью.
  • 0
    * Не читал, сразу перешел к комментам

    Жаль, что я не читал комменты к прошлой статье. Сейчас заминусовали.
    • +3
      Это как опоздать на начало вечеринки.
      Неловко, но не смертельно.
      Присоединяйтесь!
  • +22
    Пиши про Катю, к чёрту Go!
    • +1
      Про Катю получилось однозначно лучше!
    • +1
      Ждем отдельную статью про Катю со спойлерами про Go
  • +8
    Интересно было читать, и главное — что был «выброс эндорфинов», можно расходиться, ждем продолжения.
  • +11
    Пока что, несмотря на уверения подружки, складывается впечатление, что вы для Кати были запасным вариантом. Запасной вариант далеко отпускать нельзя, но и быть рядом смысла тоже нет.
    • +1
      Особо не надо и выбросить вроде жалко. Печальная ситуация :(
      • +1
        Причем что для варианта, что для жалеющего. В ситуации без людей — у меня полкомнаты в коробках, я с ними живу, встречаюсь раз в неделю ногой, но выбросить жалко — там же проводки, моторчики, микросхемы, старые наушники (завтра починю!)
  • +10
    Ну-у вот, на самом интересном месте.
    А php, go… Да-да, молодец.
  • 0
    Какой-то странный способ набрать «подписчиков» в стиле Pikabu… История конечно интересная, но зачем так мучить людей =)
  • +7
    А Катя читает статьи про Катю?
    • +2
      Я думаю, что нет.
      • +10
        Небось, Катя там, пока автор ходил за вином, слила исходники и пилит новую криптовалюту на основе этой. Поэтому и динами часто.
        • +1
          Все исходники на гитхабе в открытом доступе ) тут было PHP, а тут на Go
          • 0
            Заметил уже после того, как написал коммент. Поставил на гитхабе звездочку :)
            • 0
              Спасибо :)
  • +7
    Сдаётся мне, что «Катя» это вовсе и не Катя, а название новой криптовалюты, а автор еще и сам не в курсе…
    • +1
      Может попробовать убедить Катю стать майнером в качестве пиар-хода? В Dcoin для защиты от гиперинфляции есть децентрализованная проверка по фото и видео. Каждый претендент в майнеры таким образом доказывает существующим майнерам, что он живой человек и может создавать новые монеты из ничего.
      • 0
        Как тут не вспомнить Стругацких: «Не тушуйся, парень, заряжай женщину и стреляй из нее в белый свет. И она выстрелит пушкой или пушкарем, а они выстрелят своим чередом, тоже пушками и пушкарями, а те в свою очередь, и так оно и пойдет, выстрел за выстрелом, пока белый свет не станет черным».
  • –29
    Не знаю кто мне более противен в этой истории, Катя или автор.
    • +1
      Хм… Если Ваш коммент наберет больше плюсов, чем минусов, то я прекращаю писать о Кате.
      • +29
        Похоже вы обрекли меня :(
  • +2
    Я рад, что все хорошо с Катей )
  • +3
    Вы молодец в том, что не стесняетесь рассказывать публично личные моменты. Наверное вам можно и что-нибудь на них ответить?

    Во-первых, вы про себя пишете: «одержим идеей». Одержимость идеей не есть хорошо, особенно если это слепая одержимость. Нужно критически оценить свою работу и прикинуть, насколько реальны ваши планы и ваши идеи. Это по теме вашей статьи. Попросту говоря, «Зачем?».

    Во-вторых, гуглить про поведение девушки, найти какую-то пикап книгу про женское поведение. расспрашивать девушку про книги «по психологии» (лол), и уж тем более выяснять с её подружкой ваши личные отношения — не то, что неправильно, просто совсем не умно. Как должна относиться девушка к такому парню, который гуглит и читает книжки и спрашивает у её подружек «как вести себя с девушкой»? А теперь наложите сюда типичный стереотип представления женщин о программистах и получится уж совсем неуверенный юноша.
    • +3
      У меня нет сомнений, что Dcoin взлетит. В Dcoin уникальная модель майнинга, которая дает возможность создавать новые монеты любому человеку.

      Вы правы, с девушками я общаться не умею и не скрываю этого.
  • +8
    TL;DR

    Здорово, что не сидишь на месте и что-то изобретаешь. Очень здорово, что не стесняешься НЕ использовать инструменты, не предназначенные, мягко говоря, для не свойственных им задач. И очень здорово пишешь, как технически, так и литературно. Нет, я не стану критиковать за ошибки, не ошибается только тот, кто ничего не делает. А ты делаешь, и это отлично!
    Но вот что хочется тебе пожелать, дорогой автор :-)
    Будь смелее! Во всех аспектах и во всех делах! Ты придумал классную идею и хочешь внедрить? Подумай, посоветуйся, реши для себя каким инструментом эту задачу лучше сделать. Никогда не стесняйся незнакомых «монстров», ну например Scala, Haskel, Java EE. Сложных языков программирования не бывает. Бывает лениво изучать и ковыряться, это да. Всегда смотри на ситуацию так, как будто ты знаешь любой инструмент. Ведь суть не в инструменте, а в задаче, и её изящном решении.
    То же и с девушками. Я за свою жизнь встречал много девушек. Дважды был женат. Даже дети есть от одного из браков. Но нужно быть смелее. У тебя есть мечта? Иди к ней. Хочешь что-то получить — прямо скажи что хочешь. Хочешь жениться — женись! Разводиться — разводись! Главное, чтобы путь к мечте был как таковой. Гораздо хуже, если ты ничего не хочешь… Или боишься. Не бойся.

    И еще один универсальный совет :-)
    Никогда! НИКОГДА не подавай вид что ты в чём-то не уверен. Уверенность в любом деле, даже совершенно незнакомом сделает тебя лидером в любой области. Только ради всего святого, не путай уверенность и… слово забыл ))) пусть будет слово наглость, ближайший синоним. Пример:
    Дано: ты работаешь в компании N. Они хотят внедрить какую-то неведомую хрень. Ты крайний, и тема для тебя слабо изучена (не изучена).
    Уверенность: ты НЕ боишься взять на себя ответственность, но ЧЕСТНО предупреждаешь об уровне компетенции, и требуешь либо отправить тебя на повышение квалификации, либо изучаешь предмет самостоятельно, но при этом делаешь полный отчёт о своей работе перед руководством. Итог: всё внедрено, ты на коне, премия, + ты прокачался по новому скиллу
    Наглость: ты тоже не боишься взять на себя ответственность, но практически сразу же находишь кого-нибудь, на кого эту ответственность спихиваешь. Сам становишься только буфером между реальным исполнителем и заказчиком, при этом полностью присваиваешь все заслуги себе, а в случае фиаско — есть на кого спихнуть. Итог: ты вроде и в плюсе, но как человек — гавно.

    Уверенность, даже только для виду — это когда ты лидер. Когда ты не спрашиваешь у всех: «а правильно ли я иду?». Ты просто идёшь. Не знаешь — спрашиваешь. При этом говоришь всем правду. Не умеешь — учишься. При этом учишь других!!! Не успеваешь — найди способ заранее сообщить, переиграй по-другому. И никогда не бойся «крутым» показывать свои зубы. Не бойся ругать начальство прямо в глаза, если они не компетентны (и кстати да, некомпетентный начальник — беги оттуда быстрее молнии). Не бойся крутым заказчикам указывать СВОИ правила игры. Дай в конце концов понять всем что ты управляешь ситуацией, и это не они тебе нужны, а ты им. (И девушкам, и заказчикам, и клиентам, и вообще всем).

    Исключение из правила: родители. С ними нужно быть сыном. Сам будешь отцом, сам поймёшь почему.

    В заключение скажу, что эту «истину» я вывел многолетним опытом огромных жизненных ошибок. Чем я только не занимался, с кем только не общался, в каких только ситуациях не побывал. Сейчас я занимаюсь тем, что люблю. Я уверен только в себе и своих силах, и если я что-то хочу — я этого добиваюсь любым способом, но добивают на все 100%. И обязательно делюсь с другими. Не каждый может себе позволить жить так, как ему хочется, и при этом быть Д'Артаньяном. ))) Удачи, успехов, ты крутой, у тебя всё будет!

    p.s. GO — респект!
    • 0
      Спасибо! Со всем согласен. Странно, что коммент в минусах.
      • +3
        :-) А вот это как раз совсем не странно. Кругом враги )
        Нам лифт поменяли в подъезде, недостающее нужное русское и крепкое слово появилось на следующий день.
        А мои драгоценные соседи парой этажей выше считают вполне нормальным в районе 23 часов выкидывать на улицу мусор. И иногда попадать йогуртом по припаркованным машинам.
        А поскольку враги кругом, как сказал один генерал — это отлично, ведь мы можем стрелять в любом направлении ))))))
    • 0
      pandas — не жадничайте, напишите статью про это («универсальный совет») на Хабре. (Только не на Мегамозге — его никто не читает.) Я уверен, эта статья перевернет жизнь многих людей вокруг. Вы многим поможете. Я серьезно.
      • 0
        Спасибо, но не думаю что сейчас самое подходящее время. Дело в том, что моя жизнь сильно изменилась после определённых событий, и я далеко ушёл от IT в совершенно другую, но принципиально похожую сферу деятельности. И я с большим удовольствием совершенно безвозмездно поделюсь своим жизненным опытом со всеми желающими, когда в этой сфере добьюсь определённых результатов. Пока еще очень рано учить других жизни. Могу только сказать, что не ошибаться нельзя — нужно прочувствовать на себе все испытания и прелести жизни.
        Кстати, вам, Дмитрий, отдельное спасибо, благодаря ( вашей работе || вашему хобби ) я довольно долгое время занимался вебом. Потом ушёл в виртуализацию, потом vagrant, потом docker, потом из бэкенда в глубокий фронтенд, а потом наступило просветление и я больше не в айти. )))) Но вот первый опыт аякса с xmlHttpRequest получил именно от вас )))) Приятно.
        • 0
          Ну же, не томите! Куда ушли? Какое-то Rocket Science?
          • 0
            Если в двух словах: музыка и шоубиз. В контексте production. Т.е. я не медиа лицо, и не певец ))) Я боюсь «местные пацаны» не поймут такого поворота событий, поэтому готов желающим чуть подробнее, при наличии времени, ответить личными сообщениями ))))
            • 0
              У вас уже был какой-то опыт в вашей новой сфере, когда ушли из IT? Или начали с нуля?
              Можно ли чуть по-подробнее, чем занимаетесь?
              Вы «craftsman» или кто-то ближе к менеджменту? :)
              Про «местных пацанов» — это вы зря так, мало ли в ком спит призвание, отличное от IT ;)

              Ответьте сюда, пожалуйста, наверняка это будет интересно не только мне.
  • 0
    Короче, про Катю в топ, а все остальное под спойлеры — так правильнее будет.
  • 0
    В какой этап истории пришла смс от Кати «Не звони и не пиши мне больше!!!!»?
    • 0
      Это будет в заключительной части.
      • +1
        Эта смс-ка не окончание истории. Я думаю, что в 3-й части дойду до этого момента.
  • –3
    чувствуется что гоу больше подходит для интерграционнвх приложений! Меня больше интересует возможность работы как мвс фрейиворка! А так да быстро наглядно, нетворк инструмент!
  • +1
    Я прошу прощения, а чем оно собирается под винду?
  • 0
    Удивительно, что вообще у вас получилось познакомиться с кем-то на сайте знакомств. Я вот как-то пробовал, но вообще ничего — было вроде даже договариваешься о встрече и в назначенный день девушка не отвечает или вообще отсутствует в сети или трубку не берёт, если телефон оставила…

    Расскажите поподробнее именно про опыт от сервисов знакомств — быстро получилось списаться с вашей будущей девушкой? Долго ли общались там прежде чем перейти в «реал»?
    • 0
      У меня тоже не получалось, пока фотки нормальные не сделал. Вся фишка в фотках. Вначале идет отбор по внешности, затем читают профиль.
      Я сразу предлагаю встретиться, не люблю онлайн-переписки. Писал что-то вроде «привет. пошли по городу гулять, в снежки играть».
      • 0
        а что за сайт был?
        • 0
          mamba.ru
  • 0
    Когда продолжение-то будет? Сколько можно ждать?!
    :-)))
    • 0
      Уже скоро )

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.