aboutsummaryrefslogtreecommitdiff
path: root/src/main/resources
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2021-03-31 00:44:49 +0300
committerGravatar Vitaly Takmazov2021-03-31 00:44:49 +0300
commit93fe99d9bfc9ae00f4164ea0ba32290722dff4dd (patch)
treef0637a6ad99ae7033e2fee4d100ed1fc63e64728 /src/main/resources
parentfbe50e415fbb3da5a7fa151338b00e6a94dc8d5d (diff)
Resource filtering is handled by Spring Boot Maven plugin
Diffstat (limited to 'src/main/resources')
-rw-r--r--src/main/resources/1x1.pngbin0 -> 95 bytes
-rw-r--r--src/main/resources/Transparent.gifbin0 -> 42 bytes
-rw-r--r--src/main/resources/banner.txt13
-rw-r--r--src/main/resources/data-h2.sql9
-rw-r--r--src/main/resources/errors.properties20
-rw-r--r--src/main/resources/errors_ru.properties20
-rw-r--r--src/main/resources/juick-test-key.p12bin0 -> 2389 bytes
-rw-r--r--src/main/resources/juick.pngbin0 -> 4298 bytes
-rw-r--r--src/main/resources/messages.properties98
-rw-r--r--src/main/resources/messages_ru.properties96
-rw-r--r--src/main/resources/pg_schema_wip1539
-rw-r--r--src/main/resources/rome.properties19
-rw-r--r--src/main/resources/schema-h2.sql397
-rw-r--r--src/main/resources/static/av-96.pngbin0 -> 2018 bytes
-rw-r--r--src/main/resources/static/durov.pngbin0 -> 31025 bytes
-rw-r--r--src/main/resources/static/favicon.pngbin0 -> 244 bytes
-rw-r--r--src/main/resources/static/logo.pngbin0 -> 1184 bytes
-rw-r--r--src/main/resources/static/logo@2x.pngbin0 -> 4822 bytes
-rw-r--r--src/main/resources/static/tagscloud.pngbin0 -> 42316 bytes
-rw-r--r--src/main/resources/templates/email/html.html10
-rw-r--r--src/main/resources/templates/email/plaintext.html5
-rw-r--r--src/main/resources/templates/layouts/default.html54
-rw-r--r--src/main/resources/templates/layouts/login.html280
-rw-r--r--src/main/resources/templates/layouts/note.html5
-rw-r--r--src/main/resources/templates/views/404.html11
-rw-r--r--src/main/resources/templates/views/blog.html24
-rw-r--r--src/main/resources/templates/views/blog_tags.html10
-rw-r--r--src/main/resources/templates/views/help.html12
-rw-r--r--src/main/resources/templates/views/index.html29
-rw-r--r--src/main/resources/templates/views/login_success.html13
-rw-r--r--src/main/resources/templates/views/macros/tags.html11
-rw-r--r--src/main/resources/templates/views/partial/footer.html11
-rw-r--r--src/main/resources/templates/views/partial/homecolumn.html25
-rw-r--r--src/main/resources/templates/views/partial/message.html87
-rw-r--r--src/main/resources/templates/views/partial/navigation.html43
-rw-r--r--src/main/resources/templates/views/partial/settings_tabs.html11
-rw-r--r--src/main/resources/templates/views/partial/tagcolumn.html26
-rw-r--r--src/main/resources/templates/views/partial/tags.html3
-rw-r--r--src/main/resources/templates/views/partial/usercolumn.html93
-rw-r--r--src/main/resources/templates/views/partial/usertags.html3
-rw-r--r--src/main/resources/templates/views/pm_inbox.html35
-rw-r--r--src/main/resources/templates/views/pm_sent.html33
-rw-r--r--src/main/resources/templates/views/post.html22
-rw-r--r--src/main/resources/templates/views/post_success.html19
-rw-r--r--src/main/resources/templates/views/settings_about.html20
-rw-r--r--src/main/resources/templates/views/settings_auth-email.html9
-rw-r--r--src/main/resources/templates/views/settings_main.html154
-rw-r--r--src/main/resources/templates/views/settings_password.html17
-rw-r--r--src/main/resources/templates/views/settings_privacy.html9
-rw-r--r--src/main/resources/templates/views/settings_result.html9
-rw-r--r--src/main/resources/templates/views/signup.html43
-rw-r--r--src/main/resources/templates/views/signup_result.html6
-rw-r--r--src/main/resources/templates/views/thread.html188
-rw-r--r--src/main/resources/templates/views/users.html17
-rw-r--r--src/main/resources/testkey.p85
55 files changed, 3563 insertions, 0 deletions
diff --git a/src/main/resources/1x1.png b/src/main/resources/1x1.png
new file mode 100644
index 00000000..1914264c
--- /dev/null
+++ b/src/main/resources/1x1.png
Binary files differ
diff --git a/src/main/resources/Transparent.gif b/src/main/resources/Transparent.gif
new file mode 100644
index 00000000..f191b280
--- /dev/null
+++ b/src/main/resources/Transparent.gif
Binary files differ
diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt
new file mode 100644
index 00000000..c81c89f7
--- /dev/null
+++ b/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+${AnsiColor.BRIGHT_RED}
+ ___ ___ ___ ___
+ /\ \ /\__\ ___ /\ \ /\__\
+ \:\ \ /:/ / /\ \ /::\ \ /:/ /
+ ___ /::\__\ /:/ / \:\ \ /:/\:\ \ /:/__/
+ /\ /:/\/__/ /:/ / ___ /::\__\ /:/ \:\ \ /::\__\____
+ \:\/:/ / /:/__/ /\__\ __/:/\/__/ /:/__/ \:\__\ /:/\:::::\__\
+ \::/ / \:\ \ /:/ / /\/:/ / \:\ \ \/__/ \/_|:|~~|~
+ \/__/ \:\ /:/ / \::/__/ \:\ \ |:| |
+ \:\/:/ / \:\__\ \:\ \ |:| |
+ \::/ / \/__/ \:\__\ |:| |
+ \/__/ \/__/ \|__|
+${AnsiColor.DEFAULT}
diff --git a/src/main/resources/data-h2.sql b/src/main/resources/data-h2.sql
new file mode 100644
index 00000000..aff3e286
--- /dev/null
+++ b/src/main/resources/data-h2.sql
@@ -0,0 +1,9 @@
+INSERT INTO users(id, nick, passw) VALUES(0, 'Anonymous', 'password');
+INSERT INTO tags(tag_id, name) VALUES(2, 'juick');
+INSERT INTO reactions (like_id, description) VALUES (1, 'like');
+INSERT INTO reactions (like_id, description) VALUES (2, 'love');
+INSERT INTO reactions (like_id, description) VALUES (3, 'lol');
+INSERT INTO reactions (like_id, description) VALUES (4, 'hmm');
+INSERT INTO reactions (like_id, description) VALUES (5, 'angry');
+INSERT INTO reactions (like_id, description) VALUES (6, 'uhblya');
+INSERT INTO reactions (like_id, description) VALUES (7, 'ugh');
diff --git a/src/main/resources/errors.properties b/src/main/resources/errors.properties
new file mode 100644
index 00000000..6040582e
--- /dev/null
+++ b/src/main/resources/errors.properties
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2008-2020, Juick
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+error.title = Error page
+
+error.login=Wrong user or password \ No newline at end of file
diff --git a/src/main/resources/errors_ru.properties b/src/main/resources/errors_ru.properties
new file mode 100644
index 00000000..a803a7cd
--- /dev/null
+++ b/src/main/resources/errors_ru.properties
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2008-2020, Juick
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+error.title = Произошла ошибка
+
+error.login=Произошла ошибка, проверьте имя пользователя и пароль \ No newline at end of file
diff --git a/src/main/resources/juick-test-key.p12 b/src/main/resources/juick-test-key.p12
new file mode 100644
index 00000000..254004ec
--- /dev/null
+++ b/src/main/resources/juick-test-key.p12
Binary files differ
diff --git a/src/main/resources/juick.png b/src/main/resources/juick.png
new file mode 100644
index 00000000..a7b0e901
--- /dev/null
+++ b/src/main/resources/juick.png
Binary files differ
diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties
new file mode 100644
index 00000000..2aceae3d
--- /dev/null
+++ b/src/main/resources/messages.properties
@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2008-2020, Juick
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+date.format=MM/dd/yyyy
+
+link.settings=Settings
+link.returnToMain=Back to Home Page
+link.contacts=Contacts
+link.tos=TOS
+link.adv=Advertisement
+
+link.popular=Popular
+link.allMessages=Discover
+link.withPhotos=Photos
+link.trends=Trends
+link.my=My feed
+link.privateMessages=PM
+link.discuss=Discuss
+link.recommended=Recommended
+link.postMessage=Post
+link.Login=Login
+link.logout=Logout
+
+link.settings.main=Main
+link.settings.password=Password
+link.settings.about=About
+
+label.sponsor=Sponsor
+label.sponsors=Sponsors
+label.search=Search
+label.register=Register
+label.username=User name
+label.password=Password
+
+postForm.newMessage=New message...
+postForm.imageLink=Link to image
+postForm.imageFormats=JPG/PNG, up to 100 MB
+postForm.or=or
+postForm.upload=Upload
+postForm.tags=Tags (space separated)
+postForm.submit=Send
+
+message.recommend=Recommend
+message.recommendedBy=♡ recommended by
+message.recommendedOthers=and {0} others
+message.comment=Comment
+message.writeComment=Write a comment...
+message.share=Share
+message.subscribe=Subscribe
+message.subscribed=Subscribed
+message.delete=Delete
+message.loginForSending=<a href="{0}" class="a-login">Login</a> to post messages and comments
+message.sendLoginToXmpp=Send <b>LOGIN</b> to <a href="xmpp:juick@juick.com?message;body=LOGIN">juick@juick.com</a>
+
+messages.next=Next
+
+reply.reply=Reply
+reply.inReplyTo=in reply to
+reply.replies=Replies
+
+replies.showAsList=Show as list
+replies.showAsTree=Show as tree
+replies.unfoldAll=Unfold all
+
+question.areRegistered=Already registered?
+
+title.help=Help
+title.loginOrSignup=Juick - Log In or Sign Up
+title.index.anonym=Juick microblogs: popular posts
+title.index.user=Popular
+title.search=Search:
+
+error.pageNotFound=Page not found
+error.pageNotFound.description=User probably deleted this post, or this page never existed.
+
+blog.blog=Blog
+blog.recommendations=Recommendations
+blog.photos=Photos
+blog.iread=I read
+blog.readers=My readers
+blog.bl=Ignored
+blog.messages=Messages
+blog.comments=Comments
+blog.allPostsWithTag=All posts tagged
diff --git a/src/main/resources/messages_ru.properties b/src/main/resources/messages_ru.properties
new file mode 100644
index 00000000..487bf7d7
--- /dev/null
+++ b/src/main/resources/messages_ru.properties
@@ -0,0 +1,96 @@
+#
+# Copyright (C) 2008-2020, Juick
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+date.format=dd.MM.yyyy
+
+link.settings=Настройки
+link.returnToMain=Вернуться на главную
+link.contacts=Контакты
+link.tos=TOS
+
+link.popular=Популярные
+link.allMessages=Обзор
+link.withPhotos=Фото
+link.trends=Темы
+link.my=Моя лента
+link.privateMessages=Приватные
+link.discuss=Диалоги
+link.recommended=Рекомендации
+link.postMessage=Написать
+link.Login=Войти
+link.logout=Выйти
+
+link.settings.main=Главная
+link.settings.password=Пароль
+link.settings.about=О пользователе
+
+label.sponsor=Спонсор
+label.sponsors=Спонсоры
+label.search=Поиск
+label.register=Зарегистрироваться
+label.username=Имя пользователя
+label.password=Пароль
+
+postForm.newMessage=Новое сообщение...
+postForm.imageLink=Ссылка на изображение
+postForm.imageFormats=JPG/PNG, до 100 Мб
+postForm.or=или
+postForm.upload=загрузить
+postForm.tags=Теги (через пробел)
+postForm.submit=Отправить
+
+message.recommend=Рекомендовать
+message.recommendedBy=♡ рекомендовали
+message.recommendedOthers=и еще {0}
+message.comment=Комментировать
+message.writeComment=Написать комментарий...
+message.share=Поделиться
+message.subscribe=Подписаться
+message.subscribed=Подписан
+message.delete=Удалить
+message.loginForSending=Чтобы добавлять сообщения и комментарии, <a href="{0}" class="a-login">представьтесь</a>
+message.sendLoginToXmpp=Отправьте <b>LOGIN</b> на <a href="xmpp:juick@juick.com?message;body=LOGIN">juick@juick.com</a>
+
+messages.next=Читать дальше
+
+reply.reply=Ответить
+reply.inReplyTo=в ответ на
+reply.replies=Ответы
+replies.showAsList=Показать списком
+replies.showAsTree=Показать деревом
+replies.unfoldAll=Раскрыть все
+
+question.areRegistered=Уже зарегистрированы?
+
+title.help=Справка
+title.loginOrSignup=Juick - Войдите в систему или зарегистрируйтесь
+title.index.anonym=Микроблоги Juick: популярные записи
+title.index.user=Популярные
+title.search=Поиск:
+
+error.pageNotFound=Страница не найдена
+error.pageNotFound.description=Сожалеем, но страницу с этим адресом удалил её автор, либо её никогда не существовало.
+
+blog.blog=Блог
+blog.recommendations=Рекомендации
+blog.photos=Фотографии
+blog.iread=Я читаю
+blog.readers=Мои подписчики
+blog.bl=Игнорирую
+blog.messages=Сообщения
+blog.comments=Комментарии
+blog.allPostsWithTag=Все записи с тегом
diff --git a/src/main/resources/pg_schema_wip b/src/main/resources/pg_schema_wip
new file mode 100644
index 00000000..61178495
--- /dev/null
+++ b/src/main/resources/pg_schema_wip
@@ -0,0 +1,1539 @@
+--
+-- PostgreSQL database dump
+--
+
+SET statement_timeout = 0;
+SET lock_timeout = 0;
+SET client_encoding = 'UTF8';
+SET standard_conforming_strings = off;
+SET check_function_bodies = false;
+SET client_min_messages = warning;
+SET escape_string_warning = off;
+
+--
+-- Name: juick; Type: SCHEMA; Schema: -; Owner: juick
+--
+
+CREATE SCHEMA juick;
+
+
+ALTER SCHEMA juick OWNER TO juick;
+
+--
+-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:
+--
+
+CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
+
+
+--
+-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
+--
+
+COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
+
+
+SET search_path = public, pg_catalog;
+
+--
+-- Name: auth_protocol; Type: TYPE; Schema: public; Owner: juick
+--
+
+CREATE TYPE auth_protocol AS ENUM (
+ 'xmpp',
+ 'email',
+ 'sms'
+);
+
+
+ALTER TYPE auth_protocol OWNER TO juick;
+
+--
+-- Name: messages_attach; Type: TYPE; Schema: public; Owner: juick
+--
+
+CREATE TYPE messages_attach AS ENUM (
+ 'jpg',
+ 'mp4',
+ 'png'
+);
+
+
+ALTER TYPE messages_attach OWNER TO juick;
+
+--
+-- Name: messages_lang; Type: TYPE; Schema: public; Owner: juick
+--
+
+CREATE TYPE messages_lang AS ENUM (
+ 'en',
+ 'ru',
+ 'fr',
+ 'fa',
+ '__'
+);
+
+
+ALTER TYPE messages_lang OWNER TO juick;
+
+--
+-- Name: replies_attach; Type: TYPE; Schema: public; Owner: juick
+--
+
+CREATE TYPE replies_attach AS ENUM (
+ 'jpg',
+ 'mp4',
+ 'png'
+);
+
+
+ALTER TYPE replies_attach OWNER TO juick;
+
+--
+-- Name: users_lang; Type: TYPE; Schema: public; Owner: juick
+--
+
+CREATE TYPE users_lang AS ENUM (
+ 'en',
+ 'ru',
+ 'fr',
+ 'fa',
+ '__'
+);
+
+
+ALTER TYPE users_lang OWNER TO juick;
+
+SET default_tablespace = '';
+
+SET default_with_oids = false;
+
+--
+-- Name: ads_messages; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE ads_messages (
+ message_id bigint NOT NULL
+);
+
+
+ALTER TABLE ads_messages OWNER TO juick;
+
+--
+-- Name: ads_messages_log; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE ads_messages_log (
+ user_id bigint NOT NULL,
+ message_id bigint NOT NULL,
+ ts bigint DEFAULT 0::bigint NOT NULL
+);
+
+
+ALTER TABLE ads_messages_log OWNER TO juick;
+
+--
+-- Name: android; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE android (
+ user_id bigint NOT NULL,
+ regid character varying(255) NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE android OWNER TO juick;
+
+--
+-- Name: auth; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE auth (
+ user_id bigint NOT NULL,
+ protocol auth_protocol NOT NULL,
+ account character varying(64) NOT NULL,
+ authcode character varying(8) NOT NULL
+);
+
+
+ALTER TABLE auth OWNER TO juick;
+
+--
+-- Name: bl_tags; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE bl_tags (
+ user_id bigint NOT NULL,
+ tag_id bigint NOT NULL
+);
+
+
+ALTER TABLE bl_tags OWNER TO juick;
+
+--
+-- Name: bl_users; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE bl_users (
+ user_id bigint NOT NULL,
+ bl_user_id bigint NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE bl_users OWNER TO juick;
+
+--
+-- Name: captcha; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE captcha (
+ jid character varying(64) NOT NULL,
+ hash character varying(16) NOT NULL,
+ confirmed smallint NOT NULL
+);
+
+
+ALTER TABLE captcha OWNER TO juick;
+
+--
+-- Name: captchaimg; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE captchaimg (
+ id character varying(16) NOT NULL,
+ txt character varying(6) NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL,
+ ip character varying(16) NOT NULL
+);
+
+
+ALTER TABLE captchaimg OWNER TO juick;
+
+--
+-- Name: emails; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE emails (
+ user_id bigint NOT NULL,
+ email character varying(64) NOT NULL,
+ subscr_hour smallint
+);
+
+
+ALTER TABLE emails OWNER TO juick;
+
+--
+-- Name: facebook; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE facebook (
+ user_id bigint,
+ fb_id numeric NOT NULL,
+ loginhash character varying(36),
+ access_token character varying(255),
+ ts timestamp with time zone DEFAULT now() NOT NULL,
+ fb_name character varying(64) NOT NULL,
+ fb_link character varying(255) NOT NULL,
+ crosspost boolean DEFAULT true NOT NULL
+);
+
+
+ALTER TABLE facebook OWNER TO juick;
+
+--
+-- Name: favorites; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE favorites (
+ user_id bigint NOT NULL,
+ message_id bigint NOT NULL,
+ ts timestamp with time zone
+);
+
+
+ALTER TABLE favorites OWNER TO juick;
+
+--
+-- Name: friends_facebook; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE friends_facebook (
+ user_id bigint NOT NULL,
+ friend_id numeric NOT NULL
+);
+
+
+ALTER TABLE friends_facebook OWNER TO juick;
+
+--
+-- Name: images; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE images (
+ mid bigint NOT NULL,
+ rid bigint NOT NULL,
+ thumb bigint NOT NULL,
+ small bigint NOT NULL,
+ medium bigint NOT NULL,
+ height bigint NOT NULL,
+ width bigint NOT NULL
+);
+
+
+ALTER TABLE images OWNER TO juick;
+
+--
+-- Name: ios; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE ios (
+ user_id bigint NOT NULL,
+ token character varying(64) NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE ios OWNER TO juick;
+
+--
+-- Name: jids; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE jids (
+ user_id bigint,
+ jid character varying(64) NOT NULL,
+ active smallint DEFAULT 0 NOT NULL,
+ loginhash character varying(36),
+ ts timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE jids OWNER TO juick;
+
+--
+-- Name: logins; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE logins (
+ user_id bigint NOT NULL,
+ hash character varying(16) NOT NULL
+);
+
+
+ALTER TABLE logins OWNER TO juick;
+
+--
+-- Name: mail; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE mail (
+ user_id bigint NOT NULL,
+ hash character varying(16) NOT NULL
+);
+
+
+ALTER TABLE mail OWNER TO juick;
+
+--
+-- Name: meon; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE meon (
+ id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ link character varying(255) NOT NULL,
+ name character varying(32) NOT NULL,
+ ico smallint
+);
+
+
+ALTER TABLE meon OWNER TO juick;
+
+--
+-- Name: meon_id_seq; Type: SEQUENCE; Schema: public; Owner: juick
+--
+
+CREATE SEQUENCE meon_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE meon_id_seq OWNER TO juick;
+
+--
+-- Name: meon_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: juick
+--
+
+ALTER SEQUENCE meon_id_seq OWNED BY meon.id;
+
+
+--
+-- Name: messages; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE messages (
+ message_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ lang messages_lang DEFAULT '__'::messages_lang NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL,
+ replies smallint DEFAULT 0::smallint NOT NULL,
+ maxreplyid smallint DEFAULT 0::smallint NOT NULL,
+ privacy smallint DEFAULT 1::smallint NOT NULL,
+ readonly boolean DEFAULT false NOT NULL,
+ attach messages_attach,
+ place_id bigint,
+ lat numeric(10,7),
+ lon numeric(10,7),
+ popular smallint DEFAULT 0::smallint NOT NULL,
+ hidden smallint DEFAULT 0::smallint NOT NULL,
+ likes smallint DEFAULT 0::smallint NOT NULL
+);
+
+
+ALTER TABLE messages OWNER TO juick;
+
+--
+-- Name: messages_access; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE messages_access (
+ message_id bigint NOT NULL,
+ user_id bigint NOT NULL
+);
+
+
+ALTER TABLE messages_access OWNER TO juick;
+
+--
+-- Name: messages_message_id_seq; Type: SEQUENCE; Schema: public; Owner: juick
+--
+
+CREATE SEQUENCE messages_message_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE messages_message_id_seq OWNER TO juick;
+
+--
+-- Name: messages_message_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: juick
+--
+
+ALTER SEQUENCE messages_message_id_seq OWNED BY messages.message_id;
+
+
+--
+-- Name: messages_tags; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE messages_tags (
+ message_id bigint NOT NULL,
+ tag_id bigint NOT NULL
+);
+
+
+ALTER TABLE messages_tags OWNER TO juick;
+
+--
+-- Name: messages_txt; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE messages_txt (
+ message_id bigint NOT NULL,
+ tags text,
+ repliesby text,
+ txt text NOT NULL
+);
+
+
+ALTER TABLE messages_txt OWNER TO juick;
+
+--
+-- Name: messages_votes; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE messages_votes (
+ message_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ vote smallint DEFAULT 1::smallint NOT NULL
+);
+
+
+ALTER TABLE messages_votes OWNER TO juick;
+
+--
+-- Name: places; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE places (
+ place_id bigint NOT NULL,
+ lat numeric(10,7) NOT NULL,
+ lon numeric(10,7) NOT NULL,
+ name character varying(64) NOT NULL,
+ descr character varying(255),
+ url character varying(128),
+ user_id bigint NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE places OWNER TO juick;
+
+--
+-- Name: places_place_id_seq; Type: SEQUENCE; Schema: public; Owner: juick
+--
+
+CREATE SEQUENCE places_place_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE places_place_id_seq OWNER TO juick;
+
+--
+-- Name: places_place_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: juick
+--
+
+ALTER SEQUENCE places_place_id_seq OWNED BY places.place_id;
+
+
+--
+-- Name: places_tags; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE places_tags (
+ place_id bigint NOT NULL,
+ tag_id bigint NOT NULL
+);
+
+
+ALTER TABLE places_tags OWNER TO juick;
+
+--
+-- Name: pm; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE pm (
+ user_id bigint NOT NULL,
+ user_id_to bigint NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL,
+ txt text NOT NULL
+);
+
+
+ALTER TABLE pm OWNER TO juick;
+
+--
+-- Name: pm_inroster; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE pm_inroster (
+ user_id bigint NOT NULL,
+ jid character varying(64) NOT NULL
+);
+
+
+ALTER TABLE pm_inroster OWNER TO juick;
+
+--
+-- Name: pm_streams; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE pm_streams (
+ user_id bigint NOT NULL,
+ user_id_to bigint NOT NULL,
+ lastmessage timestamp with time zone NOT NULL,
+ lastview timestamp with time zone,
+ unread smallint DEFAULT 0::smallint NOT NULL
+);
+
+
+ALTER TABLE pm_streams OWNER TO juick;
+
+--
+-- Name: presence; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE presence (
+ user_id bigint NOT NULL,
+ jid character varying(64),
+ ts timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE presence OWNER TO juick;
+
+--
+-- Name: reader_links; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE reader_links (
+ link_id bigint NOT NULL,
+ rss_id bigint NOT NULL,
+ url character varying(255) NOT NULL,
+ title character varying(255) NOT NULL,
+ ts timestamp with time zone NOT NULL
+);
+
+
+ALTER TABLE reader_links OWNER TO juick;
+
+--
+-- Name: reader_links_link_id_seq; Type: SEQUENCE; Schema: public; Owner: juick
+--
+
+CREATE SEQUENCE reader_links_link_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE reader_links_link_id_seq OWNER TO juick;
+
+--
+-- Name: reader_links_link_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: juick
+--
+
+ALTER SEQUENCE reader_links_link_id_seq OWNED BY reader_links.link_id;
+
+
+--
+-- Name: reader_rss; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE reader_rss (
+ rss_id bigint NOT NULL,
+ url character varying(255) NOT NULL,
+ lastcheck timestamp with time zone NOT NULL
+);
+
+
+ALTER TABLE reader_rss OWNER TO juick;
+
+--
+-- Name: reader_rss_rss_id_seq; Type: SEQUENCE; Schema: public; Owner: juick
+--
+
+CREATE SEQUENCE reader_rss_rss_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE reader_rss_rss_id_seq OWNER TO juick;
+
+--
+-- Name: reader_rss_rss_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: juick
+--
+
+ALTER SEQUENCE reader_rss_rss_id_seq OWNED BY reader_rss.rss_id;
+
+
+--
+-- Name: replies; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE replies (
+ message_id bigint NOT NULL,
+ reply_id smallint NOT NULL,
+ user_id bigint NOT NULL,
+ replyto smallint DEFAULT 0::smallint NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL,
+ attach replies_attach,
+ txt text NOT NULL
+);
+
+
+ALTER TABLE replies OWNER TO juick;
+
+--
+-- Name: sphinx; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE sphinx (
+ counter_id smallint NOT NULL,
+ max_id bigint NOT NULL
+);
+
+
+ALTER TABLE sphinx OWNER TO juick;
+
+--
+-- Name: subscr_messages; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE subscr_messages (
+ message_id bigint NOT NULL,
+ suser_id bigint NOT NULL
+);
+
+
+ALTER TABLE subscr_messages OWNER TO juick;
+
+--
+-- Name: subscr_tags; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE subscr_tags (
+ tag_id bigint NOT NULL,
+ suser_id bigint NOT NULL,
+ jid character varying(64) NOT NULL,
+ active boolean NOT NULL
+);
+
+
+ALTER TABLE subscr_tags OWNER TO juick;
+
+--
+-- Name: subscr_users; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE subscr_users (
+ user_id bigint NOT NULL,
+ suser_id bigint NOT NULL,
+ jid character varying(64),
+ active boolean NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE subscr_users OWNER TO juick;
+
+--
+-- Name: tags; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE tags (
+ tag_id bigint NOT NULL,
+ synonym_id bigint,
+ name character varying(70),
+ top boolean DEFAULT false NOT NULL,
+ noindex boolean DEFAULT false NOT NULL,
+ stat_messages bigint DEFAULT 0::bigint NOT NULL,
+ stat_users smallint DEFAULT 0::smallint NOT NULL
+);
+
+
+ALTER TABLE tags OWNER TO juick;
+
+--
+-- Name: tags_ignore; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE tags_ignore (
+ tag_id bigint NOT NULL
+);
+
+
+ALTER TABLE tags_ignore OWNER TO juick;
+
+--
+-- Name: tags_synonyms; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE tags_synonyms (
+ name character varying(64) NOT NULL,
+ changeto character varying(64) NOT NULL
+);
+
+
+ALTER TABLE tags_synonyms OWNER TO juick;
+
+--
+-- Name: tags_tag_id_seq; Type: SEQUENCE; Schema: public; Owner: juick
+--
+
+CREATE SEQUENCE tags_tag_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE tags_tag_id_seq OWNER TO juick;
+
+--
+-- Name: tags_tag_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: juick
+--
+
+ALTER SEQUENCE tags_tag_id_seq OWNED BY tags.tag_id;
+
+
+--
+-- Name: telegram; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE telegram (
+ user_id bigint,
+ tg_id numeric NOT NULL,
+ tg_name character varying(64) NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL,
+ loginhash character varying(36)
+);
+
+
+ALTER TABLE telegram OWNER TO juick;
+
+--
+-- Name: telegram_chats; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE telegram_chats (
+ chat_id numeric
+);
+
+
+ALTER TABLE telegram_chats OWNER TO juick;
+
+--
+-- Name: top_ignore_messages; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE top_ignore_messages (
+ message_id bigint NOT NULL
+);
+
+
+ALTER TABLE top_ignore_messages OWNER TO juick;
+
+--
+-- Name: top_ignore_tags; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE top_ignore_tags (
+ tag_id bigint NOT NULL
+);
+
+
+ALTER TABLE top_ignore_tags OWNER TO juick;
+
+--
+-- Name: top_ignore_users; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE top_ignore_users (
+ user_id bigint NOT NULL
+);
+
+
+ALTER TABLE top_ignore_users OWNER TO juick;
+
+--
+-- Name: twitter; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE twitter (
+ user_id bigint NOT NULL,
+ access_token character varying(64) NOT NULL,
+ access_token_secret character varying(64) NOT NULL,
+ uname character varying(64) NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL,
+ crosspost boolean DEFAULT true NOT NULL
+);
+
+
+ALTER TABLE twitter OWNER TO juick;
+
+--
+-- Name: useroptions; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE useroptions (
+ user_id bigint NOT NULL,
+ jnotify boolean DEFAULT true NOT NULL,
+ subscr_active boolean DEFAULT true NOT NULL,
+ off_ts timestamp with time zone,
+ xmppxhtml boolean DEFAULT false NOT NULL,
+ subscr_notify boolean DEFAULT true NOT NULL,
+ recommendations boolean DEFAULT true NOT NULL,
+ privacy_view boolean DEFAULT true NOT NULL,
+ privacy_reply boolean DEFAULT true NOT NULL,
+ privacy_pm boolean DEFAULT true NOT NULL,
+ repliesview boolean DEFAULT false NOT NULL
+);
+
+
+ALTER TABLE useroptions OWNER TO juick;
+
+--
+-- Name: users; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE users (
+ id bigint NOT NULL,
+ nick character varying(64) NOT NULL,
+ passw character varying(32) NOT NULL,
+ lang users_lang DEFAULT '__'::users_lang NOT NULL,
+ banned smallint DEFAULT 0::smallint NOT NULL,
+ lastmessage bigint DEFAULT 0::bigint NOT NULL,
+ lastpm bigint DEFAULT 0::bigint NOT NULL,
+ lastphoto bigint DEFAULT 0::bigint NOT NULL,
+ karma smallint DEFAULT 0::smallint NOT NULL
+);
+
+
+ALTER TABLE users OWNER TO juick;
+
+--
+-- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: juick
+--
+
+CREATE SEQUENCE users_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE users_id_seq OWNER TO juick;
+
+--
+-- Name: users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: juick
+--
+
+ALTER SEQUENCE users_id_seq OWNED BY users.id;
+
+
+--
+-- Name: users_refs; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE users_refs (
+ user_id bigint NOT NULL,
+ ref bigint NOT NULL
+);
+
+
+ALTER TABLE users_refs OWNER TO juick;
+
+--
+-- Name: users_subscr; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE users_subscr (
+ user_id bigint NOT NULL,
+ cnt smallint DEFAULT 0::smallint NOT NULL
+);
+
+
+ALTER TABLE users_subscr OWNER TO juick;
+
+--
+-- Name: usersinfo; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE usersinfo (
+ user_id bigint NOT NULL,
+ jid character varying(32),
+ fullname character varying(32),
+ country character varying(32),
+ url character varying(64),
+ gender character varying(32),
+ bday character varying(10),
+ descr text
+);
+
+
+ALTER TABLE usersinfo OWNER TO juick;
+
+--
+-- Name: version; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE version (
+ version numeric NOT NULL
+);
+
+
+ALTER TABLE version OWNER TO juick;
+
+--
+-- Name: vk; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE vk (
+ user_id bigint,
+ vk_id numeric NOT NULL,
+ loginhash character varying(36),
+ access_token character varying(128) NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL,
+ vk_name character varying(64) NOT NULL,
+ vk_link character varying(64) NOT NULL,
+ crosspost smallint DEFAULT 1::smallint NOT NULL
+);
+
+
+ALTER TABLE vk OWNER TO juick;
+
+--
+-- Name: winphone; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE winphone (
+ user_id bigint NOT NULL,
+ url character varying(255) NOT NULL,
+ ts timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE winphone OWNER TO juick;
+
+--
+-- Name: wl_users; Type: TABLE; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE TABLE wl_users (
+ user_id bigint NOT NULL,
+ wl_user_id bigint NOT NULL
+);
+
+
+ALTER TABLE wl_users OWNER TO juick;
+
+--
+-- Name: id; Type: DEFAULT; Schema: public; Owner: juick
+--
+
+ALTER TABLE ONLY meon ALTER COLUMN id SET DEFAULT nextval('meon_id_seq'::regclass);
+
+
+--
+-- Name: message_id; Type: DEFAULT; Schema: public; Owner: juick
+--
+
+ALTER TABLE ONLY messages ALTER COLUMN message_id SET DEFAULT nextval('messages_message_id_seq'::regclass);
+
+
+--
+-- Name: place_id; Type: DEFAULT; Schema: public; Owner: juick
+--
+
+ALTER TABLE ONLY places ALTER COLUMN place_id SET DEFAULT nextval('places_place_id_seq'::regclass);
+
+
+--
+-- Name: link_id; Type: DEFAULT; Schema: public; Owner: juick
+--
+
+ALTER TABLE ONLY reader_links ALTER COLUMN link_id SET DEFAULT nextval('reader_links_link_id_seq'::regclass);
+
+
+--
+-- Name: rss_id; Type: DEFAULT; Schema: public; Owner: juick
+--
+
+ALTER TABLE ONLY reader_rss ALTER COLUMN rss_id SET DEFAULT nextval('reader_rss_rss_id_seq'::regclass);
+
+
+--
+-- Name: tag_id; Type: DEFAULT; Schema: public; Owner: juick
+--
+
+ALTER TABLE ONLY tags ALTER COLUMN tag_id SET DEFAULT nextval('tags_tag_id_seq'::regclass);
+
+
+--
+-- Name: id; Type: DEFAULT; Schema: public; Owner: juick
+--
+
+ALTER TABLE ONLY users ALTER COLUMN id SET DEFAULT nextval('users_id_seq'::regclass);
+
+
+--
+-- Name: idx_20438_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY images
+ ADD CONSTRAINT idx_20438_primary PRIMARY KEY (mid, rid);
+
+
+--
+-- Name: idx_20453_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY mail
+ ADD CONSTRAINT idx_20453_primary PRIMARY KEY (user_id);
+
+
+--
+-- Name: idx_20458_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY meon
+ ADD CONSTRAINT idx_20458_primary PRIMARY KEY (id);
+
+
+--
+-- Name: idx_20483_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY messages
+ ADD CONSTRAINT idx_20483_primary PRIMARY KEY (message_id);
+
+
+--
+-- Name: idx_20502_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY messages_txt
+ ADD CONSTRAINT idx_20502_primary PRIMARY KEY (message_id);
+
+
+--
+-- Name: idx_20514_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY places
+ ADD CONSTRAINT idx_20514_primary PRIMARY KEY (place_id);
+
+
+--
+-- Name: idx_20542_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY reader_links
+ ADD CONSTRAINT idx_20542_primary PRIMARY KEY (link_id);
+
+
+--
+-- Name: idx_20551_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY reader_rss
+ ADD CONSTRAINT idx_20551_primary PRIMARY KEY (rss_id);
+
+
+--
+-- Name: idx_20571_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY sphinx
+ ADD CONSTRAINT idx_20571_primary PRIMARY KEY (counter_id);
+
+
+--
+-- Name: idx_20586_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY tags
+ ADD CONSTRAINT idx_20586_primary PRIMARY KEY (tag_id);
+
+
+--
+-- Name: idx_20616_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY top_ignore_tags
+ ADD CONSTRAINT idx_20616_primary PRIMARY KEY (tag_id);
+
+
+--
+-- Name: idx_20619_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY top_ignore_users
+ ADD CONSTRAINT idx_20619_primary PRIMARY KEY (user_id);
+
+
+--
+-- Name: idx_20622_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY twitter
+ ADD CONSTRAINT idx_20622_primary PRIMARY KEY (user_id);
+
+
+--
+-- Name: idx_20627_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY useroptions
+ ADD CONSTRAINT idx_20627_primary PRIMARY KEY (user_id);
+
+
+--
+-- Name: idx_20653_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY users
+ ADD CONSTRAINT idx_20653_primary PRIMARY KEY (id);
+
+
+--
+-- Name: idx_20663_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY usersinfo
+ ADD CONSTRAINT idx_20663_primary PRIMARY KEY (user_id);
+
+
+--
+-- Name: idx_20672_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY users_subscr
+ ADD CONSTRAINT idx_20672_primary PRIMARY KEY (user_id);
+
+
+--
+-- Name: idx_20694_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY wl_users
+ ADD CONSTRAINT idx_20694_primary PRIMARY KEY (user_id, wl_user_id);
+
+
+--
+-- Name: idx_29418_primary; Type: CONSTRAINT; Schema: public; Owner: juick; Tablespace:
+--
+
+ALTER TABLE ONLY bl_users
+ ADD CONSTRAINT idx_29418_primary PRIMARY KEY (user_id, bl_user_id);
+
+
+--
+-- Name: idx_20390_regid; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20390_regid ON android USING btree (regid);
+
+
+--
+-- Name: idx_20390_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20390_user_id ON android USING btree (user_id);
+
+
+--
+-- Name: idx_20404_tag_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20404_tag_id ON bl_tags USING btree (tag_id);
+
+
+--
+-- Name: idx_20404_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20404_user_id ON bl_tags USING btree (user_id);
+
+
+--
+-- Name: idx_20418_email; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20418_email ON emails USING btree (email);
+
+
+--
+-- Name: idx_20421_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20421_user_id ON facebook USING btree (user_id);
+
+
+--
+-- Name: idx_20432_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20432_user_id ON friends_facebook USING btree (user_id, friend_id);
+
+
+--
+-- Name: idx_20441_token; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20441_token ON ios USING btree (token);
+
+
+--
+-- Name: idx_20441_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20441_user_id ON ios USING btree (user_id);
+
+
+--
+-- Name: idx_20445_jid; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20445_jid ON jids USING btree (jid);
+
+
+--
+-- Name: idx_20445_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20445_user_id ON jids USING btree (user_id);
+
+
+--
+-- Name: idx_20450_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20450_user_id ON logins USING btree (user_id);
+
+
+--
+-- Name: idx_20483_attach; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20483_attach ON messages USING btree (attach);
+
+
+--
+-- Name: idx_20483_hidden; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20483_hidden ON messages USING btree (hidden);
+
+
+--
+-- Name: idx_20483_place_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20483_place_id ON messages USING btree (place_id);
+
+
+--
+-- Name: idx_20483_popular; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20483_popular ON messages USING btree (popular);
+
+
+--
+-- Name: idx_20483_ts; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20483_ts ON messages USING btree (ts);
+
+
+--
+-- Name: idx_20483_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20483_user_id ON messages USING btree (user_id);
+
+
+--
+-- Name: idx_20496_message_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20496_message_id ON messages_access USING btree (message_id);
+
+
+--
+-- Name: idx_20499_message_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20499_message_id ON messages_tags USING btree (message_id);
+
+
+--
+-- Name: idx_20499_message_id_2; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20499_message_id_2 ON messages_tags USING btree (message_id, tag_id);
+
+
+--
+-- Name: idx_20499_tag_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20499_tag_id ON messages_tags USING btree (tag_id);
+
+
+--
+-- Name: idx_20508_message_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20508_message_id ON messages_votes USING btree (message_id, user_id);
+
+
+--
+-- Name: idx_20529_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20529_user_id ON pm_inroster USING btree (user_id);
+
+
+--
+-- Name: idx_20529_user_id_2; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20529_user_id_2 ON pm_inroster USING btree (user_id, jid);
+
+
+--
+-- Name: idx_20532_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20532_user_id ON pm_streams USING btree (user_id, user_id_to);
+
+
+--
+-- Name: idx_20536_jid; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20536_jid ON presence USING btree (jid);
+
+
+--
+-- Name: idx_20563_message_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20563_message_id ON replies USING btree (message_id);
+
+
+--
+-- Name: idx_20563_ts; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20563_ts ON replies USING btree (ts);
+
+
+--
+-- Name: idx_20563_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20563_user_id ON replies USING btree (user_id);
+
+
+--
+-- Name: idx_20574_message_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20574_message_id ON subscr_messages USING btree (message_id, suser_id);
+
+
+--
+-- Name: idx_20577_tag_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20577_tag_id ON subscr_tags USING btree (tag_id, suser_id);
+
+
+--
+-- Name: idx_20580_suser_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20580_suser_id ON subscr_users USING btree (suser_id);
+
+
+--
+-- Name: idx_20580_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20580_user_id ON subscr_users USING btree (user_id, suser_id);
+
+
+--
+-- Name: idx_20586_synonym_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20586_synonym_id ON tags USING btree (synonym_id);
+
+
+--
+-- Name: idx_20607_chat_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20607_chat_id ON telegram_chats USING btree (chat_id);
+
+
+--
+-- Name: idx_20627_recommendations; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20627_recommendations ON useroptions USING btree (recommendations);
+
+
+--
+-- Name: idx_20653_nick; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20653_nick ON users USING btree (nick);
+
+
+--
+-- Name: idx_20669_ref; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20669_ref ON users_refs USING btree (ref);
+
+
+--
+-- Name: idx_20682_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20682_user_id ON vk USING btree (user_id);
+
+
+--
+-- Name: idx_20690_url; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_20690_url ON winphone USING btree (url);
+
+
+--
+-- Name: idx_20690_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_20690_user_id ON winphone USING btree (user_id);
+
+
+--
+-- Name: idx_29422_message_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_29422_message_id ON favorites USING btree (message_id);
+
+
+--
+-- Name: idx_29422_user_id; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE INDEX idx_29422_user_id ON favorites USING btree (user_id);
+
+
+--
+-- Name: idx_29422_user_id_2; Type: INDEX; Schema: public; Owner: juick; Tablespace:
+--
+
+CREATE UNIQUE INDEX idx_29422_user_id_2 ON favorites USING btree (user_id, message_id);
+
+
+--
+-- Name: public; Type: ACL; Schema: -; Owner: postgres
+--
+
+REVOKE ALL ON SCHEMA public FROM PUBLIC;
+REVOKE ALL ON SCHEMA public FROM postgres;
+GRANT ALL ON SCHEMA public TO postgres;
+GRANT ALL ON SCHEMA public TO PUBLIC;
+
+
+--
+-- PostgreSQL database dump complete
+--
+
diff --git a/src/main/resources/rome.properties b/src/main/resources/rome.properties
new file mode 100644
index 00000000..a50de51b
--- /dev/null
+++ b/src/main/resources/rome.properties
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2008-2020, Juick
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+rss_2.0.item.ModuleParser.classes=com.juick.www.rss.extension.JuickModuleParser
+rss_2.0.item.ModuleGenerator.classes=com.juick.www.rss.extension.JuickModuleGenerator \ No newline at end of file
diff --git a/src/main/resources/schema-h2.sql b/src/main/resources/schema-h2.sql
new file mode 100644
index 00000000..c1b398bd
--- /dev/null
+++ b/src/main/resources/schema-h2.sql
@@ -0,0 +1,397 @@
+SET DB_CLOSE_ON_EXIT TRUE;
+SET MODE=MYSQL;
+
+CREATE TABLE IF NOT EXISTS `android` (
+ `user_id` int(10) unsigned NOT NULL,
+ `regid` char(255) NOT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+CREATE TABLE IF NOT EXISTS `auth` (
+ `user_id` int(10) unsigned NOT NULL,
+ `protocol` enum('xmpp','email','sms') NOT NULL,
+ `account` char(64) NOT NULL,
+ `authcode` char(8) NOT NULL
+);
+CREATE TABLE IF NOT EXISTS `bl_tags` (
+ `user_id` int(10) unsigned NOT NULL,
+ `tag_id` int(10) unsigned NOT NULL
+);
+CREATE TABLE IF NOT EXISTS `bl_users` (
+ `user_id` int(10) unsigned NOT NULL,
+ `bl_user_id` int(10) unsigned NOT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`user_id`,`bl_user_id`)
+);
+CREATE TABLE IF NOT EXISTS `facebook` (
+ `user_id` int(10) unsigned DEFAULT NULL,
+ `fb_id` bigint(20) unsigned NULL,
+ `loginhash` char(36) DEFAULT NULL,
+ `access_token` char(255) DEFAULT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `fb_name` char(64) NULL,
+ `fb_link` char(255) NULL,
+ `crosspost` tinyint(1) unsigned NOT NULL DEFAULT '1'
+);
+
+CREATE TABLE IF NOT EXISTS `reactions` (
+ `like_id` int(10) unsigned NOT NULL,
+ `description` varchar (100) NOT NULL
+);
+CREATE TABLE IF NOT EXISTS `favorites` (
+ `user_id` int(10) unsigned NOT NULL,
+ `message_id` int(10) unsigned NOT NULL,
+ `ts` datetime NOT NULL,
+ `like_id` int(10),
+ foreign key (like_id) references reactions(like_id)
+);
+
+
+
+CREATE TABLE IF NOT EXISTS `friends_facebook` (
+ `user_id` int(10) unsigned NOT NULL,
+ `friend_id` bigint(20) unsigned NOT NULL,
+ UNIQUE KEY `user_id` (`user_id`,`friend_id`)
+);
+CREATE TABLE IF NOT EXISTS `images` (
+ `mid` int(10) unsigned NOT NULL,
+ `rid` int(10) unsigned NOT NULL,
+ `thumb` int(10) unsigned NOT NULL,
+ `small` int(10) unsigned NOT NULL,
+ `medium` int(10) unsigned NOT NULL,
+ `height` int(10) unsigned NOT NULL,
+ `width` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`mid`,`rid`)
+);
+
+CREATE TABLE IF NOT EXISTS `mail` (
+ `user_id` int(10) unsigned NOT NULL,
+ `hash` char(16) NOT NULL,
+ PRIMARY KEY (`user_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `meon` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `user_id` int(10) unsigned NOT NULL,
+ `link` char(255) NOT NULL,
+ `name` char(32) NOT NULL,
+ `ico` smallint(5) unsigned DEFAULT NULL,
+ PRIMARY KEY (`id`)
+);
+
+
+
+CREATE TABLE IF NOT EXISTS `messages_access` (
+ `message_id` int(10) unsigned NOT NULL,
+ `user_id` int(10) unsigned NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `messages_tags` (
+ `message_id` int(10) unsigned NOT NULL,
+ `tag_id` int(10) unsigned NOT NULL,
+ UNIQUE KEY `message_id_2` (`message_id`,`tag_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `messages_txt` (
+ `message_id` int(10) unsigned NOT NULL,
+ `tags` varchar(255) DEFAULT NULL,
+ `repliesby` varchar(96) DEFAULT NULL,
+ `txt` mediumtext NOT NULL,
+ PRIMARY KEY (`message_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `messages_votes` (
+ `message_id` int(10) unsigned NOT NULL,
+ `user_id` int(10) unsigned NOT NULL,
+ `vote` tinyint(4) NOT NULL DEFAULT '1',
+ UNIQUE KEY `message_id` (`message_id`,`user_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `messenger` (
+ `user_id` int(10) unsigned DEFAULT NULL,
+ `sender_id` bigint(20) NOT NULL,
+ `display_name` char(64) NOT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `loginhash` char(36) DEFAULT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `places` (
+ `place_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `lat` decimal(10,7) NOT NULL,
+ `lon` decimal(10,7) NOT NULL,
+ `name` char(64) NOT NULL,
+ `descr` char(255) DEFAULT NULL,
+ `url` char(128) DEFAULT NULL,
+ `user_id` int(10) unsigned NOT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`place_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `places_tags` (
+ `place_id` int(10) unsigned NOT NULL,
+ `tag_id` int(10) unsigned NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `pm` (
+ `user_id` int(10) unsigned NOT NULL,
+ `user_id_to` int(10) unsigned NOT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `txt` text NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `pm_streams` (
+ `user_id` int(10) unsigned NOT NULL,
+ `user_id_to` int(10) unsigned NOT NULL,
+ `lastmessage` datetime NOT NULL,
+ `lastview` datetime DEFAULT NULL,
+ `unread` smallint(5) unsigned NOT NULL DEFAULT '0',
+ UNIQUE KEY (`user_id`,`user_id_to`)
+);
+
+CREATE TABLE IF NOT EXISTS `presence` (
+ `user_id` int(10) unsigned NOT NULL,
+ `jid` char(64) DEFAULT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ UNIQUE KEY (`jid`)
+);
+
+CREATE TABLE IF NOT EXISTS `replies` (
+ `message_id` int(10) unsigned NOT NULL,
+ `reply_id` smallint(5) unsigned NOT NULL,
+ `user_id` int(10) unsigned NOT NULL,
+ `replyto` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `ts` timestamp(9) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `attach` nchar(3) check (attach in ('jpg', 'mp4', 'png')),
+ `txt` mediumtext NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `subscr_messages` (
+ `message_id` int(10) unsigned NOT NULL,
+ `suser_id` int(10) unsigned NOT NULL,
+ `last_read_rid` smallint(5) unsigned NOT NULL DEFAULT '0',
+ UNIQUE KEY (`message_id`,`suser_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `subscr_tags` (
+ `tag_id` int(10) unsigned NOT NULL,
+ `suser_id` int(10) unsigned NOT NULL,
+ UNIQUE KEY (`tag_id`,`suser_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `subscr_users` (
+ `user_id` int(10) unsigned NOT NULL,
+ `suser_id` int(10) unsigned NOT NULL,
+ `jid` char(64) DEFAULT NULL,
+ `active` bit(1) NOT NULL DEFAULT TRUE,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ UNIQUE KEY (`user_id`,`suser_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `tags` (
+ `tag_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `synonym_id` int(10) unsigned DEFAULT NULL,
+ `name` varchar_ignorecase(70) DEFAULT NULL,
+ `top` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ `noindex` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ `stat_messages` int(10) unsigned NOT NULL DEFAULT '0',
+ `stat_users` smallint(5) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`tag_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `tags_ignore` (
+ `tag_id` int(10) unsigned NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `tags_synonyms` (
+ `name` char(64) NOT NULL,
+ `changeto` char(64) NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `telegram` (
+ `user_id` int(10) unsigned DEFAULT NULL,
+ `tg_id` bigint(20) NOT NULL,
+ `tg_name` char(64) DEFAULT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `loginhash` char(36) DEFAULT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `telegram_chats` (
+ `chat_id` bigint(20) DEFAULT NULL,
+ UNIQUE KEY `chat_id` (`chat_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `top_ignore_messages` (
+ `message_id` int(10) unsigned NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `top_ignore_tags` (
+ `tag_id` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`tag_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `top_ignore_users` (
+ `user_id` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`user_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `twitter` (
+ `user_id` int(10) unsigned NOT NULL,
+ `access_token` char(64) NOT NULL,
+ `access_token_secret` char(64) NOT NULL,
+ `uname` char(64) NOT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `crosspost` tinyint(1) unsigned NOT NULL DEFAULT '1',
+ PRIMARY KEY (`user_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `useroptions` (
+ `user_id` int(10) unsigned NOT NULL,
+ `jnotify` tinyint(1) NOT NULL DEFAULT '1',
+ `subscr_active` tinyint(1) NOT NULL DEFAULT '1',
+ `off_ts` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `xmppxhtml` tinyint(1) NOT NULL DEFAULT '0',
+ `subscr_notify` tinyint(1) NOT NULL DEFAULT '1',
+ `recommendations` tinyint(1) NOT NULL DEFAULT '1',
+ `privacy_view` tinyint(1) NOT NULL DEFAULT '1',
+ `privacy_reply` tinyint(1) NOT NULL DEFAULT '1',
+ `privacy_pm` tinyint(1) NOT NULL DEFAULT '1',
+ `repliesview` tinyint(1) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`user_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `users` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT(0),
+ `nick` char(64) NOT NULL,
+ `passw` char(32) NOT NULL,
+ `lang` enum('en','ru','fr','fa','__') NOT NULL DEFAULT '__',
+ `banned` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `lastmessage` timestamp(9) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `lastpm` int(11) NOT NULL DEFAULT '0',
+ `lastphoto` int(11) NOT NULL DEFAULT '0',
+ `karma` smallint(6) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `nick` (`nick`)
+);
+
+CREATE TABLE IF NOT EXISTS `users_refs` (
+ `user_id` int(10) unsigned NOT NULL,
+ `ref` int(10) unsigned NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `users_subscr` (
+ `user_id` int(10) unsigned NOT NULL,
+ `cnt` smallint(5) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`user_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `usersinfo` (
+ `user_id` int(10) unsigned NOT NULL,
+ `jid` char(32) DEFAULT NULL,
+ `fullname` char(32) DEFAULT NULL,
+ `country` char(32) DEFAULT NULL,
+ `url` char(64) DEFAULT NULL,
+ `gender` char(32) DEFAULT NULL,
+ `bday` char(10) DEFAULT NULL,
+ `descr` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`user_id`)
+);
+CREATE TABLE IF NOT EXISTS `emails` (
+ `user_id` int(10) unsigned NOT NULL,
+ `email` char(64) NOT NULL PRIMARY KEY,
+ `subscr_hour` tinyint(4) DEFAULT NULL,
+ foreign key (user_id) references users(id)
+);
+CREATE TABLE IF NOT EXISTS `ios` (
+ `user_id` int(10) unsigned NOT NULL,
+ `token` char(64) NOT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ UNIQUE KEY `token` (`token`),
+ foreign key (user_id) references users(id)
+);
+
+CREATE TABLE IF NOT EXISTS `jids` (
+ `user_id` int(10) unsigned DEFAULT NULL,
+ `jid` char(64) NOT NULL,
+ `active` tinyint(1) NOT NULL DEFAULT '1',
+ `loginhash` char(36) DEFAULT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ UNIQUE KEY `jid` (`jid`),
+ foreign key (user_id) references users(id)
+);
+
+CREATE TABLE IF NOT EXISTS `logins` (
+ `user_id` int(10) unsigned NOT NULL,
+ `hash` char(16) NOT NULL,
+ UNIQUE KEY (`user_id`)
+);
+CREATE TABLE IF NOT EXISTS `messages` (
+ `message_id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ `user_id` int(10) unsigned NOT NULL,
+ `lang` enum('en','ru','fr','fa','__') NOT NULL DEFAULT '__',
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `replies` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `maxreplyid` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `privacy` tinyint(4) NOT NULL DEFAULT '1',
+ `readonly` tinyint(1) NOT NULL DEFAULT '0',
+ `attach` nchar(3) check (attach in ('jpg', 'mp4', 'png')),
+ `place_id` int(10) unsigned DEFAULT NULL,
+ `lat` decimal(10,7) DEFAULT NULL,
+ `lon` decimal(10,7) DEFAULT NULL,
+ `popular` tinyint(4) NOT NULL DEFAULT '0',
+ `hidden` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `likes` smallint(6) NOT NULL DEFAULT '0',
+ `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (`user_id`) references users(id)
+);
+CREATE TABLE IF NOT EXISTS `pm_inroster` (
+ `user_id` int(10) unsigned NOT NULL,
+ `jid` char(64) NOT NULL,
+ UNIQUE KEY (`user_id`,`jid`),
+ FOREIGN KEY (`user_id`) references users(id)
+);
+
+CREATE TABLE IF NOT EXISTS `version` (
+ `version` bigint(20) NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `vk` (
+ `user_id` int(10) unsigned DEFAULT NULL,
+ `vk_id` bigint(20) NOT NULL,
+ `loginhash` char(36) DEFAULT NULL,
+ `access_token` char(128) NOT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `vk_name` char(64) NOT NULL,
+ `vk_link` char(64) NOT NULL,
+ `crosspost` bit(1) unsigned NOT NULL DEFAULT FALSE,
+ FOREIGN KEY (`user_id`) references users(id)
+);
+
+CREATE TABLE IF NOT EXISTS `winphone` (
+ `user_id` int(10) unsigned NOT NULL,
+ `url` char(255) NOT NULL,
+ `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ UNIQUE KEY (`url`),
+ FOREIGN KEY (`user_id`) references users(id)
+);
+
+CREATE TABLE IF NOT EXISTS `wl_users` (
+ `user_id` int(10) unsigned NOT NULL,
+ `wl_user_id` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`user_id`,`wl_user_id`)
+);
+
+CREATE CACHED TABLE PUBLIC."flyway_schema_history" (
+ "installed_rank" INT NOT NULL,
+ "version" VARCHAR(50),
+ "description" VARCHAR(200) NOT NULL,
+ "type" VARCHAR(20) NOT NULL,
+ "script" VARCHAR(1000) NOT NULL,
+ "checksum" INT,
+ "installed_by" VARCHAR(100) NOT NULL,
+ "installed_on" TIMESTAMP DEFAULT CURRENT_TIMESTAMP() NOT NULL,
+ "execution_time" INT NOT NULL,
+ "success" BOOLEAN NOT NULL
+);
+ALTER TABLE PUBLIC."flyway_schema_history" ADD CONSTRAINT PUBLIC."flyway_schema_history_pk" PRIMARY KEY("installed_rank");
+-- 1 +/- SELECT COUNT(*) FROM PUBLIC."flyway_schema_history";
+INSERT INTO PUBLIC."flyway_schema_history"("installed_rank", "version", "description", "type", "script", "checksum", "installed_by", "installed_on", "execution_time", "success") VALUES
+(1, '1', '<< Flyway Baseline >>', 'BASELINE', '<< Flyway Baseline >>', NULL, 'SA', TIMESTAMP '2018-08-14 13:05:13.724', 0, TRUE); \ No newline at end of file
diff --git a/src/main/resources/static/av-96.png b/src/main/resources/static/av-96.png
new file mode 100644
index 00000000..911c0522
--- /dev/null
+++ b/src/main/resources/static/av-96.png
Binary files differ
diff --git a/src/main/resources/static/durov.png b/src/main/resources/static/durov.png
new file mode 100644
index 00000000..abb80940
--- /dev/null
+++ b/src/main/resources/static/durov.png
Binary files differ
diff --git a/src/main/resources/static/favicon.png b/src/main/resources/static/favicon.png
new file mode 100644
index 00000000..bc7161e2
--- /dev/null
+++ b/src/main/resources/static/favicon.png
Binary files differ
diff --git a/src/main/resources/static/logo.png b/src/main/resources/static/logo.png
new file mode 100644
index 00000000..933f6099
--- /dev/null
+++ b/src/main/resources/static/logo.png
Binary files differ
diff --git a/src/main/resources/static/logo@2x.png b/src/main/resources/static/logo@2x.png
new file mode 100644
index 00000000..6febeaf9
--- /dev/null
+++ b/src/main/resources/static/logo@2x.png
Binary files differ
diff --git a/src/main/resources/static/tagscloud.png b/src/main/resources/static/tagscloud.png
new file mode 100644
index 00000000..3e1bf169
--- /dev/null
+++ b/src/main/resources/static/tagscloud.png
Binary files differ
diff --git a/src/main/resources/templates/email/html.html b/src/main/resources/templates/email/html.html
new file mode 100644
index 00000000..086df532
--- /dev/null
+++ b/src/main/resources/templates/email/html.html
@@ -0,0 +1,10 @@
+{{ messageBody | raw }}
+<br />
+<br />
+--
+<br />
+You are receiving this because you are subscribed to this user, discussion, tag or mentioned.
+Reply to this email directly or <a href="{{ messageUrl }}">
+ {% if msg.mid > 0 %}<img src="https://api.juick.com/thread/mark_read/{{ msg.mid }}-{{ msg.rid }}.gif?hash={{ hash }}" />{% endif %}view it</a> on Juick.
+<br />
+<a href="https://juick.com/settings?hash={{ hash }}">Configure or disable notifications</a> \ No newline at end of file
diff --git a/src/main/resources/templates/email/plaintext.html b/src/main/resources/templates/email/plaintext.html
new file mode 100644
index 00000000..a0df0038
--- /dev/null
+++ b/src/main/resources/templates/email/plaintext.html
@@ -0,0 +1,5 @@
+{{ messageBody }}
+
+--
+You are receiving this because you are subscribed to this user, discussion, tag or mentioned.
+Reply to this email directly or view it on Juick: {{ messageUrl }} \ No newline at end of file
diff --git a/src/main/resources/templates/layouts/default.html b/src/main/resources/templates/layouts/default.html
new file mode 100644
index 00000000..d3ce7dce
--- /dev/null
+++ b/src/main/resources/templates/layouts/default.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html prefix="og: http://ogp.me/ns#">
+
+<head>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <script type="text/javascript" src="{{ beans.webApp.scriptsUrl }}"></script>
+ <link rel="stylesheet" type="text/css" href="{{ beans.webApp.styleUrl }}" />
+ {% block headers %}
+ {{ headers | default('') | raw }}
+ {% endblock %}
+ <title>{{ title | default('Juick') }}</title>
+ <meta property="og:type" content="{{ ogtype | default('website') }}" />
+ <meta property="fb:app_id" content="130568668304" />
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
+ <meta name="msapplication-config" content="//i.juick.com/browserconfig.xml" />
+ <meta name="msapplication-TileColor" content="#ffffff" />
+ <meta name="msapplication-TileImage" content="//i.juick.com/ms-icon-144x144.png" />
+ <meta name="theme-color" content="#ffffff" />
+ <meta name="apple-mobile-web-app-capable" content="yes" />
+ <link rel="apple-touch-icon" sizes="57x57" href="//i.juick.com/apple-icon-57x57.png" />
+ <link rel="apple-touch-icon" sizes="60x60" href="//i.juick.com/apple-icon-60x60.png" />
+ <link rel="apple-touch-icon" sizes="72x72" href="//i.juick.com/apple-icon-72x72.png" />
+ <link rel="apple-touch-icon" sizes="76x76" href="//i.juick.com/apple-icon-76x76.png" />
+ <link rel="apple-touch-icon" sizes="114x114" href="//i.juick.com/apple-icon-114x114.png" />
+ <link rel="apple-touch-icon" sizes="120x120" href="//i.juick.com/apple-icon-120x120.png" />
+ <link rel="apple-touch-icon" sizes="144x144" href="//i.juick.com/apple-icon-144x144.png" />
+ <link rel="apple-touch-icon" sizes="152x152" href="//i.juick.com/apple-icon-152x152.png" />
+ <link rel="apple-touch-icon" sizes="180x180" href="//i.juick.com/apple-icon-180x180.png" />
+ <link rel="icon" type="image/png" sizes="32x32" href="//i.juick.com/favicon-32x32.png" />
+ <link rel="icon" type="image/png" sizes="96x96" href="//i.juick.com/favicon-96x96.png" />
+ <link rel="icon" type="image/png" sizes="16x16" href="//i.juick.com/favicon-16x16.png" />
+ <link rel="manifest" href="//i.juick.com/manifest.json" />
+</head>
+
+<body id="body" {% if visitor.uid > 0 %}data-hash="{{visitor.authHash}}" {% endif %}>
+ <div id="app">
+ {% include "views/partial/navigation" %}
+ <div id="content_wrapper">
+ <aside id="column">
+ <div id="sidebar_wrapper">
+ {% block column %}
+ {% endblock %}
+ </div>
+ </aside>
+ <section id="content" {% if msg | default('') is not empty %}data-mid="{{ msg.mid }}" {% endif %} class="content--top">
+ {% block content %}
+ {% endblock %}
+ </section>
+ </div>
+ </div>
+</body>
+
+</html> \ No newline at end of file
diff --git a/src/main/resources/templates/layouts/login.html b/src/main/resources/templates/layouts/login.html
new file mode 100644
index 00000000..4a3be9b8
--- /dev/null
+++ b/src/main/resources/templates/layouts/login.html
@@ -0,0 +1,280 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <title>Juick</title>
+ <link rel="stylesheet" type="text/css" href="{{ beans.webApp.styleUrl }}" />
+ <script>
+ function showLoginForm() {
+ var form = document.getElementById('signinform');
+ form.style.display = 'block';
+ var nick = document.getElementById('nickinput');
+ nick.focus();
+ return false;
+ }
+ function ready(fn) {
+ if (document.readyState != 'loading') {
+ fn();
+ } else {
+ document.addEventListener('DOMContentLoaded', fn);
+ }
+ }
+ ready(function() {
+ var params = new URLSearchParams(window.location.search);
+ if (params.has('error')) {
+ showLoginForm();
+ }
+ });
+ </script>
+ <style>
+ * {
+ margin: 0;
+ padding: 0;
+ }
+
+ body {
+ margin: 100px auto 0 auto;
+ width: 1000px;
+ }
+
+ a {
+ color: #069;
+ }
+
+ ul {
+ float: left;
+ width: 700px;
+ height: 350px;
+ list-style-type: none;
+ background: url(/tagscloud.png) no-repeat;
+ position: relative;
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.16);
+ }
+
+ ul a {
+ position: absolute;
+ display: block;
+ text-indent: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+
+ #bottom1 {
+ position: absolute;
+ left: 0;
+ bottom: 10px;
+ width: 100%;
+ text-align: center;
+ color: #555;
+ }
+
+ #bottom2 {
+ position: absolute;
+ left: 0;
+ bottom: -50px;
+ width: 100%;
+ padding-bottom: 20px;
+ text-align: center;
+ font-size: small;
+ color: #777;
+ }
+
+ #signup,
+ #signin {
+ margin-left: 730px;
+ width: 250px;
+ }
+
+ #signup {
+ padding-top: 25px;
+ }
+
+ #signup>div {
+ width: 100%;
+ margin: 15px 0;
+ }
+
+ #signup>div>a {
+ display: block;
+ width: 100%;
+ height: 32px;
+ line-height: 32px;
+ text-indent: 37px;
+ text-decoration: none;
+ overflow: hidden;
+ }
+
+ #facebook a {
+ color: #FFF;
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAADNQTFRFO1edX3ewl6bLnKrOoK3QrrrYvMXe2N7r3OLu3+Tv5urz7O/29vf6+Pn7+vv9/Pz9////ykQjsQAAAEZJREFUOMtjYBgFuAATO68ADxdOaUYuATDAqYBbAL8CFgECCjiBcqz4XMiPz3oQEKCtAgEkwEdIAQchBWyEFDAPkDdHsAIAhZkIwz/VK/UAAAAASUVORK5CYII=") no-repeat #3A569C;
+ }
+
+ #vk a {
+ color: #FFF;
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAHJQTFRFbY+zbo+zbpCzb5C0cpO1c5O2dZW3dpa4e5m6gJ29gZ69lq/In7bNo7jPrcDUs8XXvs3dv87dy9fkztnlz9rm0Nrm093o1N7o1+Dq3OTt3ubu4Ofv5Orw7fH27vL28PP38vX49Pb5+vv8+/z9/Pz9////2jSYlQAAAG5JREFUOMvtkEcOgDAMBE3vvXdIyP+/iMMRKfYHmMtcRtE6AD8f1Is8pyKgAs0RGYO2HSWqMQaoBHVRgYsS3AsrtyFlrqgdJlCLb95gxQO6IkZCqL+KCjz0TQU5ejOf2a3aJXPF7BOB2PvMhp8PDzGRFgEe7xvEAAAAAElFTkSuQmCC") no-repeat #6d8fb3;
+ }
+
+ #xmpp>a {
+ color: #333;
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAt9QTFRFBj5rCUFoFz5mDEFuDUNqGUJkGUNgAEprEkVtGkRhHURnHEZjAE+BIElmEEx/HEx0PUdTHE5wMEtfO0laJk5sFlN6Nk1cKFBuIlJ1R0pYRExTGF2KMVh1OFhxDGSQT1deNlx6TVhkIGKPUlphKWOFU1tiOmB+Vl1kmlAuNmaDQGpaIG6ba2Q2SGeBN2uUNW+LF3mGRmyLV3BAL3xWgmVJ2VAa2lEb0VYX11UafWlmam9mam5xy1km3lUea29y2VccvF8obHBz21gd4VcXS3ebPoVG1lwl5FkaU3iYYHaH2F0ejHFIx2Iv4V0aP4o+02As218g4l4bPYtFX351KZFaymU43mIrVYoz5mEfT4w0xGsrSo82eXqDw2s+z2k1OZVAT4SoPZU5RZM4NJVYbYc8VoSiWY43WItbuXBK52gYOI20TpM6YYSYfX98T5Q7foB9aYSZSZc8Ro21cYxH7GwdT46e0HFGeopO2HA8V5ZEf4s8528l1HM7UJs5UI+xXoyrWZhGY4ylyHdMwXhXQZS7XpdNU5tH4XJBYJZZcIuhbpJk0HdPU588kohqOZ2pVZS30XpX6XcxSaFrz4FIUqVWWqVCYZm23YBGxYRrZZ2QXpy/5YFC7IA+6oBRb6ZUcKZn44ZSgKJu54hHmJqXbbBNfKh3cq5nYqrMpJyVdrBjx5WCo56diamAjaWdyZeE8JFV8ZJWnqOlaK/Sd7Zh7pVdgbN6x52N8JdfwqCU8ZhgZLbXb7a5grtTmK+UxKKWtqahq6qhd7bHqauop6yvqqyp755pbbzRrK6rwamgib53qq+xra+sobSg86Jza8PJsLKujMVctrGwqLapv7Crr7Wr8ad1srSxj8R9uLOys7WyubSztLazkcZ/sre6tbe0r7m0tri1t7m2vri3uLq3v7m4ubu4nc9mpNBvos2UptJxtNWXtteFuNmbuNyQud2Rut6SwN+aweCbwuGdw+KeweKkF4OfHQAAAadJREFUOMtjeEoAMAwfBQ9vYJO68RCu4BYDq1bXmr2XHoMlnlzet2qGpTgX8y2EFWwensEdrW2FbUAlJ2zDKsqaYwo6eZHcIGzoor/s5IdPSfefPt3nf3Xn3HZpPU8xJAXWIvU88VOffcm78vTptrijJe4OfAmy1kgKzjMlaIfUPvvQcObp03U120ucTZQaGc8je1NZrd8g8cL7eUufPp0wfX2mvVydripKONzkTG1JXvL6TuXTR/Zb5gR6F+Vw30QNqNUss/pqn3/MvrTD7Wy1V9Y0jtXoIZnLv2nSnrfzF3bP3hDRu1wwHzOo1VWOTXn5yi/q7MTJuxTUscTFQyHNc5vfbU1btOCgjNBDbJH1UF5i9/XP6VVrJRUfYo/Nx3YcpS/euOo4Pn6MqeDx44f3LoY2SYnOXBlUfPPug8cwRQxQ6Qf39sda+HqZaQiwGydFlx+4eQ+qAqrg4b3bPqbmNhkrNm5cbGUUHply7d6Dh8hWPH744Oa186eOHDl06NDh46fP33zwEMUEiCMe3L13GwjuPbj38PHTx9jT5OPHj5G9MFQyDgA8riWAv9eLFAAAAABJRU5ErkJggg==") no-repeat #BBB;
+ }
+
+ #xmppinfo {
+ background: #FFF;
+ padding: 10px;
+ display: none;
+ }
+
+ #signin {
+ text-align: center;
+ font-size: small;
+ }
+
+ #signinform {
+ background: #FFF;
+ padding: 10px 15px;
+ margin-top: 15px;
+ display: none;
+ }
+
+ input.txt {
+ width: 212px;
+ border: 1px solid #CCC;
+ margin: 3px 0;
+ padding: 3px;
+ }
+
+ input.submit {
+ width: 70px;
+ border: 1px solid #CCC;
+ margin: 3px 0;
+ padding: 3px;
+ }
+
+ .err {
+ color: red;
+ }
+ </style>
+ <link rel="icon" href="//i.juick.com/favicon.png" />
+</head>
+
+<body>
+ <ul id="tags">
+ <li><a href="/tag/juick" style="left: 359px; top: 120px; width: 311px; height: 99px;">juick</a></li>
+ <li><a href="/tag/linux" style="left: 201px; top: 100px; width: 98px; height: 35px;">linux</a></li>
+ <li><a href="/tag/android" style="left: 314px; top: 42px; width: 45px; height: 158px;">android</a></li>
+ <li><a href="/tag/работа" style="left: 149px; top: 138px; width: 165px; height: 41px;">работа</a></li>
+ <li><a href="/tag/music" style="left: 119px; top: 249px; width: 124px; height: 32px;">music</a></li>
+ <li><a href="/tag/windows" style="left: 448px; top: 234px; width: 186px; height: 32px;">windows</a></li>
+ <li><a href="/tag/google" style="left: 244px; top: 252px; width: 134px; height: 41px;">google</a></li>
+ <li><a href="/tag/кино" style="left: 68px; top: 83px; width: 97px; height: 28px;">кино</a></li>
+ <li><a href="/tag/фото" style="left: 400px; top: 266px; width: 101px; height: 29px;">фото</a></li>
+ <li><a href="/tag/жизнь" style="left: 554px; top: 266px; width: 125px; height: 27px;">жизнь</a></li>
+ <li><a href="/tag/еда" style="left: 46px; top: 196px; width: 71px; height: 32px;">еда</a></li>
+ <li><a href="/tag/музыка" style="left: 61px; top: 111px; width: 139px; height: 27px;">музыка</a></li>
+ <li><a href="/tag/прекрасное" style="left: 152px; top: 200px; width: 205px; height: 32px;">прекрасное</a></li>
+ <li><a href="/tag/книги" style="left: 148px; top: 293px; width: 103px; height: 25px;">книги</a></li>
+ <li><a href="/tag/цитата" style="left: 325px; top: 301px; width: 126px; height: 27px;">цитата</a></li>
+ <li><a href="/tag/games" style="left: 117px; top: 142px; width: 30px; height: 104px;">games</a></li>
+ <li><a href="/tag/ubuntu" style="left: 503px; top: 2px; width: 28px; height: 102px;">ubuntu</a></li>
+ <li><a href="/tag/котэ" style="left: 534px; top: 27px; width: 76px; height: 28px;">котэ</a></li>
+ <li><a href="/tag/ВНЕЗАПНО" style="left: 501px; top: 293px; width: 146px; height: 23px;">ВНЕЗАПНО</a></li>
+ <li><a href="/tag/юмор" style="left: 73px; top: 53px; width: 84px; height: 28px;">юмор</a></li>
+ <li><a href="/tag/мысли" style="left: 202px; top: 179px; width: 102px; height: 21px;">мысли</a></li>
+ <li><a href="/tag/pic" style="left: 400px; top: 78px; width: 33px; height: 38px;">pic</a></li>
+ <li><a href="/tag/политота" style="left: 531px; top: 60px; width: 130px; height: 24px;">политота</a></li>
+ <li><a href="/tag/WOT" style="left: 159px; top: 63px; width: 48px; height: 20px;">WOT</a></li>
+ <li><a href="/tag/fail" style="left: 8px; top: 170px; width: 34px; height: 27px;">fail</a></li>
+ <li><a href="/tag/погода" style="left: 670px; top: 126px; width: 24px; height: 93px;">погода</a></li>
+ <li><a href="/tag/apple" style="left: 42px; top: 167px; width: 64px; height: 29px;">apple</a></li>
+ <li><a href="/tag/jabber" style="left: 436px; top: 43px; width: 25px; height: 75px;">jabber</a></li>
+ <li><a href="/tag/тян" style="left: 532px; top: 94px; width: 47px; height: 21px;">тян</a></li>
+ <li><a href="/tag/work" style="left: 359px; top: 55px; width: 58px; height: 23px;">work</a></li>
+ <li><a href="/tag/Python" style="left: 240px; top: 63px; width: 74px; height: 23px;">Python</a></li>
+ <li><a href="/tag/Видео" style="left: 266px; top: 232px; width: 76px; height: 20px;">Видео</a></li>
+ <li><a href="/tag/авто" style="left: 359px; top: 30px; width: 58px; height: 24px;">авто</a></li>
+ <li><a href="/tag/Anime" style="left: 360px; top: 328px; width: 66px; height: 21px;">Anime</a></li>
+ <li><a href="/tag/игры" style="left: 378px; top: 242px; width: 22px; height: 58px;">игры</a></li>
+ <li><a href="/tag/вело" style="left: 176px; top: 9px; width: 18px; height: 54px;">вело</a></li>
+ <li><a href="/tag/web" style="left: 661px; top: 219px; width: 22px; height: 47px;">web</a></li>
+ <li><a href="/tag/YouTube" style="left: 498px; top: 316px; width: 81px; height: 24px;">YouTube</a></li>
+ <li><a href="/tag/Вопрос" style="left: 208px; top: 18px; width: 22px; height: 72px;">Вопрос</a></li>
+ <li><a href="/tag/железо" style="left: 159px; top: 318px; width: 75px; height: 16px;">железо</a></li>
+ <li><a href="/tag/Microsoft" style="left: 20px; top: 146px; width: 86px; height: 21px;">Microsoft</a></li>
+ <li><a href="/tag/video" style="left: 616px; top: 101px; width: 51px; height: 19px;">video</a></li>
+ <li><a href="/tag/Россия" style="left: 32px; top: 242px; width: 68px; height: 16px;">Россия</a></li>
+ <li><a href="/tag/java" style="left: 409px; top: 226px; width: 39px; height: 22px;">java</a></li>
+ <li><a href="/tag/новости" style="left: 39px; top: 67px; width: 21px; height: 79px;">новости</a></li>
+ <li><a href="/tag/интернет" style="left: 100px; top: 233px; width: 17px; height: 85px;">интернет</a></li>
+ <li><a href="/tag/steam" style="left: 14px; top: 228px; width: 52px; height: 13px;">steam</a></li>
+ <li><a href="/tag/слова" style="left: 501px; top: 272px; width: 51px; height: 18px;">слова</a></li>
+ <li><a href="/tag/почта" style="left: 477px; top: 27px; width: 17px; height: 56px;">почта</a></li>
+ <li><a href="/tag/help" style="left: 123px; top: 281px; width: 21px; height: 35px;">help</a></li>
+ <li><a href="/tag/skype" style="left: 110px; top: 320px; width: 49px; height: 20px;">skype</a></li>
+ <li><a href="/tag/debian" style="left: 461px; top: 47px; width: 16px; height: 51px;">debian</a></li>
+ <li><a href="/tag/win" style="left: 505px; top: 104px; width: 27px; height: 16px;">win</a></li>
+ <li><a href="/tag/Религия" style="left: 33px; top: 281px; width: 67px; height: 17px;">Религия</a></li>
+ <li><a href="/tag/soft" style="left: 286px; top: 86px; width: 28px; height: 14px;">soft</a></li>
+ <li><a href="/tag/Политика" style="left: 144px; top: 281px; width: 75px; height: 12px;">Политика</a></li>
+ <li><a href="/tag/сны" style="left: 426px; top: 328px; width: 33px; height: 13px;">сны</a></li>
+ <li><a href="/tag/Питер" style="left: 146px; top: 233px; width: 50px; height: 16px;">Питер</a></li>
+ <li><a href="/tag/bash" style="left: 451px; top: 311px; width: 38px; height: 16px;">bash</a></li>
+ <li><a href="/tag/code" style="left: 279px; top: 310px; width: 39px; height: 16px;">code</a></li>
+ <li><a href="/tag/yandex" style="left: 19px; top: 263px; width: 56px; height: 18px;">yandex</a></li>
+ <li><a href="/tag/firefox" style="left: 452px; top: 295px; width: 48px; height: 16px;">firefox</a></li>
+ <li><a href="/tag/hardware" style="left: 230px; top: 40px; width: 67px; height: 18px;">hardware</a></li>
+ <li><a href="/tag/git" style="left: 78px; top: 258px; width: 20px; height: 19px;">git</a></li>
+ <li><a href="/tag/dev" style="left: 165px; top: 88px; width: 31px; height: 19px;">dev</a></li>
+ <li><a href="/tag/mobile" style="left: 421px; top: 24px; width: 15px; height: 47px;">mobile</a></li>
+ <li><a href="/tag/люди" style="left: 151px; top: 184px; width: 43px; height: 15px;">люди</a></li>
+ <li><a href="/tag/php" style="left: 149px; top: 24px; width: 27px; height: 18px;">php</a></li>
+ <li><a href="/tag/haskell" style="left: 271px; top: 293px; width: 48px; height: 16px;">haskell</a></li>
+ <li><a href="/tag/стихи" style="left: 135px; top: 42px; width: 41px; height: 11px;">стихи</a></li>
+ <li><a href="/tag/photo" style="left: 639px; top: 219px; width: 20px; height: 39px;">photo</a></li>
+ <li><a href="/tag/чай" style="left: 448px; top: 220px; width: 27px; height: 14px;">чай</a></li>
+ <li><a href="/tag/Опрос" style="left: 297px; top: 22px; width: 14px; height: 41px;">Опрос</a></li>
+ <li><a href="/tag/Chrome" style="left: 311px; top: 25px; width: 48px; height: 17px;">Chrome</a></li>
+ <li><a href="/tag/life" style="left: 255px; top: 311px; width: 23px; height: 16px;">life</a></li>
+ <li><a href="/tag/opera" style="left: 226px; top: 232px; width: 38px; height: 14px;">opera</a></li>
+ <li><a href="/tag/programming" style="left: 234px; top: 327px; width: 81px; height: 14px;">programming</a></li>
+ <li><a href="/tag/дети" style="left: 15px; top: 197px; width: 31px; height: 13px;">дети</a></li>
+ <li><a href="/tag/сериалы" style="left: 575px; top: 219px; width: 61px; height: 13px;">сериалы</a></li>
+ <li><a href="/tag/учеба" style="left: 616px; top: 84px; width: 43px; height: 17px;">учеба</a></li>
+ </ul>
+
+ <div id="bottom1">juick.com &copy; 2008-2021 &nbsp; <a href="/help/ru/contacts" rel="nofollow">Контакты</a> &middot;
+ <a href="/help/" rel="nofollow">Помощь</a>
+ </div>
+
+ <div id="signup">
+ {{ i18n("messages","label.register") }}:
+ <div id="facebook"><a href="/_fblogin" rel="nofollow">Facebook</a></div>
+ <div id="vk"><a href="/_vklogin" rel="nofollow">ВКонтакте</a></div>
+ <div id="tg">
+ <script async src="https://telegram.org/js/telegram-widget.js?3" data-telegram-login="Juick_bot"
+ data-size="medium" data-radius="0" data-auth-url="https://juick.com/_tglogin"
+ data-request-access="write"></script>
+ </div>
+ <div id="apple">
+ <a href="/_apple" rel="nofollow"><img src="https://appleid.cdn-apple.com/appleid/button" /></a>
+ </div>
+ </div>
+ <div id="signin">
+ <a href="#" onclick="return showLoginForm();">
+ {{ i18n("messages","question.areRegistered") }}
+ </a>
+ <div id="signinform">
+ <form action="/login" method="POST">
+ <p class="err">{{ authErrorMessage | default('') }}</p>
+ <input class="txt" type="text" name="username" placeholder='{{ i18n("messages","label.username") }}'
+ id="nickinput" />
+ <input class="txt" type="password" name="password"
+ placeholder='{{ i18n("messages","label.password") }}' />
+ <input class="submit" type="submit" value="OK" />
+ </form>
+ </div>
+ </div>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/src/main/resources/templates/layouts/note.html b/src/main/resources/templates/layouts/note.html
new file mode 100644
index 00000000..e832dc63
--- /dev/null
+++ b/src/main/resources/templates/layouts/note.html
@@ -0,0 +1,5 @@
+{% import "views/macros/tags" %}
+<p>{{ msg | formatMessage }}</p>
+{% if msg.tags | length > 0 %}
+<div class="msg-tags">{{ allTags(baseUri, msg.tags | tagsList) }}</div>
+{% endif %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/404.html b/src/main/resources/templates/views/404.html
new file mode 100644
index 00000000..02a790e6
--- /dev/null
+++ b/src/main/resources/templates/views/404.html
@@ -0,0 +1,11 @@
+{% extends "layouts/default" %}
+{% block content %}
+ <article>
+ <h1>Страница не найдена</h1>
+ <p>Сожалеем, но страницу с этим адресом удалил её автор, либо её никогда не существовало.</p>
+ </article>
+{% endblock %}
+
+{% block "column" %}
+{% include "views/partial/homecolumn" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/blog.html b/src/main/resources/templates/views/blog.html
new file mode 100644
index 00000000..8d6a6581
--- /dev/null
+++ b/src/main/resources/templates/views/blog.html
@@ -0,0 +1,24 @@
+{% extends "layouts/default" %}
+{% import "views/macros/tags" %}
+{% block content %}
+{% if noindex %}
+<!--noindex-->
+{% endif %}
+{% if paramTag | default('') is not empty %}
+<p class="page"><a href="/tag/{{ paramTag.name | urlencode }}">← {{ i18n("messages","blog.allPostsWithTag") }} <b>{{ paramTag.name | escape }}</b></a></p>
+{% endif %}
+<div>
+{% for msg in msgs %}
+{% include "views/partial/message" %}
+{% endfor %}
+</div>
+{% if nextpage | default('') is not empty %}
+<p class="page"><a href="{{ nextpage | raw }}" rel="prev">{{ i18n("messages","messages.next") }} →</a></p>
+{% endif %}
+{% if noindex %}
+<!--/noindex-->
+{% endif %}
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/usercolumn" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/blog_tags.html b/src/main/resources/templates/views/blog_tags.html
new file mode 100644
index 00000000..48e517eb
--- /dev/null
+++ b/src/main/resources/templates/views/blog_tags.html
@@ -0,0 +1,10 @@
+{% extends "layouts/default" %}
+{% import "views/macros/tags" %}
+{% block content %}
+<p>
+ {{ tags(user.name, tags) }}
+</p>
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/usercolumn" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/help.html b/src/main/resources/templates/views/help.html
new file mode 100644
index 00000000..169ccb3f
--- /dev/null
+++ b/src/main/resources/templates/views/help.html
@@ -0,0 +1,12 @@
+{% extends "layouts/default" %}
+{% block content %}
+<article>
+ {{ content | raw }}
+</article>
+{% endblock %}
+
+{% block "column" %}
+<div class="toolbar">
+{{ navigation | raw }}
+</div>
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/index.html b/src/main/resources/templates/views/index.html
new file mode 100644
index 00000000..e85a3aa1
--- /dev/null
+++ b/src/main/resources/templates/views/index.html
@@ -0,0 +1,29 @@
+{% extends "layouts/default" %}
+{% import "views/macros/tags" %}
+{% block content %}
+{% if noindex %}
+<!--noindex-->
+{% endif %}
+{% for msg in msgs %}
+{% include "views/partial/message" %}
+{% endfor %}
+{% if nextpage | default('') is not empty %}
+<p class="page"><a href="{{ nextpage | raw }}" rel="prev">{{ i18n("messages","messages.next") }} →</a></p>
+{% endif %}
+{% if noindex %}
+<!--/noindex-->
+{% endif %}
+{% endblock %}
+{% block "column" %}
+{% if tag | default('') is not empty %}
+{% include "views/partial/tagcolumn" %}
+{% elseif visitor.uid > 0 %}
+{% if discover %}
+{% include "views/partial/homecolumn" %}
+{% else %}
+{% include "views/partial/usercolumn" %}
+{% endif %}
+{% else %}
+{% include "views/partial/homecolumn" %}
+{% endif %}
+{% endblock %}
diff --git a/src/main/resources/templates/views/login_success.html b/src/main/resources/templates/views/login_success.html
new file mode 100644
index 00000000..ee71f12f
--- /dev/null
+++ b/src/main/resources/templates/views/login_success.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Blank window</title>
+</head>
+<body>
+ <script type="text/javascript">
+ window.opener.postMessage("{{ hash }}", "*");
+ window.close();
+ </script>
+</body>
+</html>
diff --git a/src/main/resources/templates/views/macros/tags.html b/src/main/resources/templates/views/macros/tags.html
new file mode 100644
index 00000000..08687f5a
--- /dev/null
+++ b/src/main/resources/templates/views/macros/tags.html
@@ -0,0 +1,11 @@
+{% macro tags(uname="", tagsList) %}
+{% for tag in tagsList %}
+<a href="/{{ uname }}/?tag={{ tag | urlencode }}">{{ tag }}</a>
+{% endfor %}
+{% endmacro %}
+
+{% macro allTags(baseUri, tagsList) %}
+{% for tag in tagsList %}
+<a href="{{ baseUri }}tag/{{ tag | urlencode }}">#{{ tag }}</a>
+{% endfor %}
+{% endmacro %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/partial/footer.html b/src/main/resources/templates/views/partial/footer.html
new file mode 100644
index 00000000..9a627373
--- /dev/null
+++ b/src/main/resources/templates/views/partial/footer.html
@@ -0,0 +1,11 @@
+<div id="footer" class="desktop">
+ <div id="footer-left">juick.com &copy; 2008-2021
+ {% if links | default ('') is not empty %}
+ <br/>{{ i18n("messages","label.sponsors") }}: {{ links | raw }}
+ {% endif %}
+ </div>
+ <div id="footer-right"> &middot;
+ <a href="/help/contacts" rel="nofollow">{{ i18n("messages","link.contacts") }}</a> &middot;
+ <a href="/help/tos" rel="nofollow">{{ i18n("messages","link.tos") }}</a>
+ </div>
+</div>
diff --git a/src/main/resources/templates/views/partial/homecolumn.html b/src/main/resources/templates/views/partial/homecolumn.html
new file mode 100644
index 00000000..a4cca153
--- /dev/null
+++ b/src/main/resources/templates/views/partial/homecolumn.html
@@ -0,0 +1,25 @@
+<div class="toolbar">
+ <a href="/?show=top" title="Top">
+ <i data-icon="ei-heart" data-size="s"></i>
+ <span class="desktop">Top</span>
+ </a>
+ <a href="/?show=all" title="{{ i18n("messages", "link.allMessages") }}">
+ <i data-icon="ei-search" data-size="s"></i>
+ <span class="desktop">{{ i18n("messages","link.allMessages") }}</span>
+ </a>
+ <a href="/?show=photos" title="{{ i18n("messages", "link.withPhotos") }}">
+ <i data-icon="ei-camera" data-size="s"></i>
+ <span class="desktop">{{ i18n("messages", "link.withPhotos") }}</span>
+ </a>
+</div>
+<div class="tags desktop">
+ <h4>{{ i18n("messages","link.trends") }}</h4>
+ {% include "views/partial/tags" %}
+ {% if showAdv | default(false) %}
+ <h4>Наши друзья</h4>
+ <a target="_blank" href="https://ru.jooble.org">
+ <img src="https://ru.jooble.org/css/images/logos/jooble_80x30.png" alt="Работа в России"/>
+ </a>
+ {% endif %}
+</div>
+{% include "views/partial/footer" %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/partial/message.html b/src/main/resources/templates/views/partial/message.html
new file mode 100644
index 00000000..47dfb6c5
--- /dev/null
+++ b/src/main/resources/templates/views/partial/message.html
@@ -0,0 +1,87 @@
+<article class="msg-cont" data-mid="{{ msg.mid }}">
+ <header class="h">
+ <span>
+ <a href="/{{ msg.user.name }}/"><span>{{ msg.user.name }}</span></a>
+ </span>
+ <div class="msg-avatar"><a href="/{{ msg.user.name }}/">
+ <img src="{{ msg.user.avatar }}" alt="{{ msg.user.name }}"/></a>
+ </div>
+ <div class="msg-ts">
+ {% if msg.FriendsOnly %}
+ <i data-icon="ei-lock" data-size="s"></i> &middot;
+ {% endif %}
+ <a href="/{{ msg.user.name }}/{{ msg.mid }}">
+ <time datetime="{{ msg.created | timestamp | date('yyyy-MM-dd HH:mm:ss') }}Z"
+ title="{{ msg.created | timestamp | date('yyyy-MM-dd HH:mm:ss') }} GMT">
+ {{ msg.created | prettyTime }}
+ </time>
+ </a>
+ {% if msg.created != msg.updatedAt %}
+ &middot; Edited
+ {% endif %}
+ </div>
+ </header>
+ <div class="msg-txt">
+ <span class="msg-tags">
+ {{ tags(msg.user.name, msg.tags | tagsList) }}
+ </span>
+ {{ msg | formatMessage }}
+ </div>
+ {% if msg.AttachmentType is not empty %}
+ <p class="ir"><a href="//i.juick.com/p/{{ msg.mid }}.{{ msg.AttachmentType }}" data-fname="{{ msg.mid }}.{{ msg.AttachmentType }}">
+ <img src="//i.juick.com/photos-512/{{ msg.mid }}.{{ msg.AttachmentType }}" alt=""/></a>
+ </p>
+ {% endif %}
+ <nav class="l">
+ {% if visitor.uid == msg.user.uid %}
+ <a href="/{{ msg.mid }}" class="a-like msg-button">
+ <span class="msg-button-icon">
+ <i data-icon="ei-heart" data-size="s"></i>
+ {% if msg.likes > 0 %}&nbsp;{{ msg.likes }}
+ {% else %}
+ <span>&nbsp;{{ i18n("messages","message.recommend") }}</span>
+ {% endif %}
+ </span>
+ </a>
+ {% elseif visitor.uid > 0 %}
+ <a href="/post?body=!+%23{{ msg.mid }}" class="a-like msg-button">
+ <span class="msg-button-icon">
+ <i data-icon="ei-heart" data-size="s"></i>
+ {% if msg.likes > 0 %}&nbsp;{{ msg.likes }}
+ {% else %}
+ <span>&nbsp;{{ i18n("messages","message.recommend") }}</span>
+ {% endif %}
+ </span>
+ </a>
+ {% else %}
+ <a href="/login" class="a-login msg-button">
+ <span class="msg-button-icon">
+ <i data-icon="ei-heart" data-size="s"></i>
+ {% if msg.likes > 0 %}
+ {{ msg.likes }}
+ {% else %}
+ <span>&nbsp;{{ i18n("messages","message.recommend") }}</span>
+ {% endif %}
+ </span>
+
+ </a>
+ {% endif %}
+ {% if (not msg.ReadOnly) or (visitor.uid == msg.user.uid) %}
+ <a href="/{{ msg.mid }}" class="a-comment msg-button">
+ <span class="msg-button-icon">
+ <i data-icon="ei-comment" data-size="s"></i>
+ {% if msg.Replies > 0 %}&nbsp;
+ {% if msg.unread %}
+ <span class="badge">{{ msg.Replies }}</span>
+ {% else %}
+ {{ msg.Replies }}
+ {% endif %}
+ {% else %}
+ <span>&nbsp;{{ i18n("messages","message.comment") }}</span>
+ {% endif %}
+ </span>
+
+ </a>
+ {% endif %}
+ </nav>
+</article> \ No newline at end of file
diff --git a/src/main/resources/templates/views/partial/navigation.html b/src/main/resources/templates/views/partial/navigation.html
new file mode 100644
index 00000000..184c8f2b
--- /dev/null
+++ b/src/main/resources/templates/views/partial/navigation.html
@@ -0,0 +1,43 @@
+<div id="header">
+ <div id="header_wrapper">
+ {% if visitor.uid > 0 %}
+ <div id="ctitle">
+ <a href="/{{ visitor.name }}/">
+ <img src="{{ visitor.avatar }}" alt=""/>{{ visitor.name }}
+ {% if not visitor.verified %}
+ <span style="color: red;"><i data-icon="ei-exclamation" data-size="s"></i></span>
+ {% endif %}
+ </a>
+ </div>
+ {% else %}
+ <div id="logo"><a href="/{% if visitor.uid > 0 %}?show=my{% endif %}">Juick</a></div>
+ {% endif %}
+ <div id="search" class="desktop">
+ <form action="/">
+ <input name="search" class="text"
+ placeholder="{{ i18n('messages','label.search') }}" value="{{ search | default('') }}"/>
+ </form>
+ </div>
+ <nav id="global">
+ <a href="/">
+ <i data-icon="ei-bell" data-size="s"></i>
+ <span class="icon-title desktop">{{ i18n("messages","link.discuss") }}</span>{% if visitor.unreadCount > 0 %}<span class="badge">{{ visitor.unreadCount }}</span>{% endif %}
+ </a>
+ <a href="/?show=all" rel="nofollow">
+ <i data-icon="ei-search" data-size="s"></i>
+ <span class="icon-title desktop">{{ i18n("messages","link.allMessages") }}</span>
+ </a>
+ {% if visitor.uid > 0 %}
+ <a id="post" href="/post">
+ <i data-icon="ei-pencil" data-size="s"></i>
+ <span class="icon-title desktop">{{ i18n("messages","link.postMessage") }}</span>
+ </a>
+ {% else %}
+ <a class="a-login" href="/login" rel="nofollow">
+ <i data-icon="ei-user" data-size="s"></i>
+ <span class="icon-title desktop">{{ i18n("messages", "link.Login") }}</span>
+ </a>
+ {% endif %}
+ </nav>
+ </div>
+</div>
diff --git a/src/main/resources/templates/views/partial/settings_tabs.html b/src/main/resources/templates/views/partial/settings_tabs.html
new file mode 100644
index 00000000..00f7068a
--- /dev/null
+++ b/src/main/resources/templates/views/partial/settings_tabs.html
@@ -0,0 +1,11 @@
+<div id="pagetabs">
+ <div class="toolbar">
+ <a href="/settings">{{ i18n("messages","link.settings.main") }}</a>
+ <a href="/settings?page=password">{{ i18n("messages","link.settings.password") }}</a>
+ <a href="/settings?page=about">{{ i18n("messages","link.settings.about") }}</a>
+ <a href="/logout"><i data-icon="ei-user" data-size="s"></i>{{ i18n("messages","link.logout") }}</a>
+ </div>
+</div>
+<span class="desktop">
+ {% include "views/partial/footer" %}
+</span> \ No newline at end of file
diff --git a/src/main/resources/templates/views/partial/tagcolumn.html b/src/main/resources/templates/views/partial/tagcolumn.html
new file mode 100644
index 00000000..a7728ef3
--- /dev/null
+++ b/src/main/resources/templates/views/partial/tagcolumn.html
@@ -0,0 +1,26 @@
+<div id="ctitle">
+ <h2>*{{ tag.name }}</h2>
+</div>
+{% if visitor is not empty and visitor.uid > 0 %}
+<div class="toolbar">
+ {% if isSubscribed %}
+ <a href="/post?body=U+%2A{{ tag.name }}" title="Подписан">
+ <i data-icon="ei-check" data-size="s"></i>Subscribed
+ </a>
+ {% else %}
+ <a href="/post?body=S+%2A{{ tag.name }}" title="Подписаться">
+ <i data-icon="ei-plus" data-size="s"></i>Subscribe
+ </a>
+ {% endif %}
+ {% if isInBL %}
+ <a href="/post?body=BL+%2A{{ tag.name }}" title="Разблокировать">
+ <i data-icon="ei-close-o" data-size="s"></i>Unblock
+ </a>
+ {% else %}
+ <a href="/post?body=BL+%2A{{ tag.name }}" title="Заблокировать">
+ <i data-icon="ei-close" data-size="s"></i>Block
+ </a>
+ {% endif %}
+</div>
+{% endif %}
+{% include "views/partial/footer" %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/partial/tags.html b/src/main/resources/templates/views/partial/tags.html
new file mode 100644
index 00000000..4d05b7fb
--- /dev/null
+++ b/src/main/resources/templates/views/partial/tags.html
@@ -0,0 +1,3 @@
+{% for tag in tags %}
+ <a href="/tag/{{ tag | urlencode }}" title="{{ tag }}">{{ tag }}</a>
+{% endfor %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/partial/usercolumn.html b/src/main/resources/templates/views/partial/usercolumn.html
new file mode 100644
index 00000000..ee9ab267
--- /dev/null
+++ b/src/main/resources/templates/views/partial/usercolumn.html
@@ -0,0 +1,93 @@
+<div class="toolbar">
+ {% if visitor is not empty and visitor.uid > 0 and visitor.uid != user.uid %}
+ <div id="ctitle">
+ <a href="/{{ user.name }}">
+ <img src="{{ user.avatar }}" alt="" />{{ user.name }}
+ </a>
+ </div>
+ {% if isSubscribed %}
+ <a href="/post?body=U+%40{{ user.name }}" title="Подписан">
+ <i data-icon="ei-check" data-size="s"></i>
+ <span class="desktop">Subscribed</span>
+ </a>
+ {% else %}
+ <a href="/post?body=S+%40{{ user.name }}" title="Подписаться">
+ <i data-icon="ei-plus" data-size="s"></i>
+ <span class="desktop">Subscribe</span>
+ </a>
+ {% endif %}
+ {% if isInBL %}
+ <a href="/post?body=BL+%40{{ user.name }}" title="Разблокировать">
+ <i data-icon="ei-close-o" data-size="s"></i>
+ <span class="dekstop">Unblock</span>
+ </a>
+ {% else %}
+ <a href="/post?body=BL+%40{{ user.name }}" title="Заблокировать">
+ <i data-icon="ei-close" data-size="s"></i>
+ <span class="desktop">Block</span>
+ </a>
+ {% endif %}
+ {% if not isInBLAny %}
+ <a href="/pm/sent?uname={{ user.name }}" title="Написать приватное сообщение">
+ <i data-icon="ei-envelope" data-size="s"></i>
+ <span class="desktop">PM</span>
+ </a>
+ {% endif %}
+ {% endif %}
+ {% if visitor is not empty and visitor.uid == user.uid %}
+ <a href="/?show=my"><i data-icon="ei-clock" data-size="s"></i>
+ <span class="desktop">{{ i18n("messages","link.my") }}</span>
+ </a>
+ <a href="/pm/inbox"><i data-icon="ei-envelope" data-size="s"></i>
+ <span class="desktop">{{ i18n("messages","link.privateMessages") }}</span>
+ </a>
+ <a href="/?show=discuss"><i data-icon="ei-bell" data-size="s"></i>
+ <span class="desktop">{{ i18n("messages","link.discuss") }}</span>
+ </a>
+ {% endif %}
+ {% if visitor is not empty and visitor.uid == user.uid and false %}
+ <a href="/?show=mycomments" rel="nofollow">{{ i18n("messages","blog.comments") }}</a>
+ <a href="/?show=unanswered" rel="nofollow">Неотвеченные</a>
+ {% endif %}
+ {% if visitor is not empty and visitor.uid == user.uid %}
+
+ <a href="/settings" rel="nofollow">
+ <i data-icon="ei-gear" data-size="s"></i>
+ {% if not visitor.verified %}
+ <span style="color: red;"><i data-icon="ei-exclamation" data-size="s"></i></span>
+ {% else %}
+ <span class="desktop">{{ i18n("messages","link.settings") }}</span>
+ {% endif %}
+ </a>
+ {% endif %}
+</div>
+<form action="/{{ user.name }}/" class="desktop" style="padding: 6px;">
+ <p><input type="text" name="search" class="inp" placeholder="{{ i18n('messages','label.search') }}" /></p>
+</form>
+<span class="desktop" style="padding: 6px;">
+ {% include "views/partial/usertags" %}
+</span>
+<div id="ustats" class="desktop" style="padding: 6px;">
+ <ul>
+ <li><a href="/{{ user.name }}/friends">{{ i18n("messages","blog.iread") }}: {{ statsIRead }}</a></li>
+ <li><a href="/{{ user.name }}/readers">{{ i18n("messages","blog.readers") }}: {{ statsMyReaders }}</a></li>
+ {% if statsMyBL > 0 and visitor.uid == user.uid %}
+ <li><a href="/{{ user.name }}/bl">{{ i18n("messages","blog.bl") }}: {{ statsMyBL }}</a></li>
+ {% endif %}
+ <li>{{ i18n("messages","blog.messages") }}: {{ statsMessages }}</li>
+ <li>{{ i18n("messages","blog.comments") }}: {{ statsReplies }}</li>
+ </ul>
+ {% if iread is not empty %}
+ <div class="iread">
+ {% for u in iread %}
+ <span>
+ <a href="/{{ u.name }}/">
+ <img src="//i.juick.com/as/{{ u.uid }}.png" alt="{{ u.name }}" />
+ </a>
+ </span>
+ {% endfor %}
+ </div>
+ {% endif %}
+
+</div>
+{% include "views/partial/footer" %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/partial/usertags.html b/src/main/resources/templates/views/partial/usertags.html
new file mode 100644
index 00000000..71d1303e
--- /dev/null
+++ b/src/main/resources/templates/views/partial/usertags.html
@@ -0,0 +1,3 @@
+{% import "views/macros/tags" %}
+{{ tags(user.name, tagStats) }}
+<a href="/{{ user.name }}/tags" rel="nofollow">...</a> \ No newline at end of file
diff --git a/src/main/resources/templates/views/pm_inbox.html b/src/main/resources/templates/views/pm_inbox.html
new file mode 100644
index 00000000..f89b2923
--- /dev/null
+++ b/src/main/resources/templates/views/pm_inbox.html
@@ -0,0 +1,35 @@
+{% extends "layouts/default" %}
+{% block content %}
+{% if not msgs.isEmpty() %}
+<ul id="private-messages">
+ {% for msg in msgs %}
+ <li class="msg">
+ <div class="msg-cont">
+ <div class="msg-header">
+ @<a href="/{{ msg.user.name }}/">{{ msg.user.name }}</a>:
+ <div class="msg-avatar">
+ <a href="/{{ msg.user.name }}/">
+ <img src="{{ msg.user.avatar }}" alt="{{ msg.user.name }}"/>
+ </a>
+ </div>
+ <div class="msg-ts">{{ msg.created | prettyTime }}</div>
+ </div>
+
+ <div class="msg-txt">{{ msg | formatMessage }}</div>
+ <form class="pmmsg">
+ <input type="hidden" name="uname" value="{{ msg.user.name }}"/>
+ <div class="msg-comment">
+ <div class="ta-wrapper">
+ <textarea name="body" rows="1" class="replypm" placeholder="Написать ответ"></textarea>
+ </div>
+ </div>
+ </form>
+ </div>
+ </li>
+ {% endfor %}
+</ul>
+{% endif %}
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/usercolumn" %}
+{% endblock %}
diff --git a/src/main/resources/templates/views/pm_sent.html b/src/main/resources/templates/views/pm_sent.html
new file mode 100644
index 00000000..f0af71d3
--- /dev/null
+++ b/src/main/resources/templates/views/pm_sent.html
@@ -0,0 +1,33 @@
+{% extends "layouts/default" %}
+{% block content %}
+<form class="pmmsg">
+ <div class="newpm">
+ <div class="newpm-to">To: <input type="text" name="uname" placeholder="username" value="{{ uname }}"/></div>
+ <div class="newpm-body"><textarea name="body" rows="2"></textarea></div>
+ <div class="newpm-send"><input type="submit" value="OK"/></div>
+ </div>
+</form>
+{% if not msgs.isEmpty() %}
+<ul id="private-messages">
+ {% for msg in msgs %}
+ <li class="msg">
+ <div class="msg-cont">
+ <div class="msg-header">
+ @<a href="/{{ msg.user.name }}/">{{ msg.user.name }}</a>:
+ <div class="msg-avatar">
+ <a href="/{{ msg.user.name }}/">
+ <img src="{{ msg.user.avatar }}" alt="{{ msg.user.name }}"/>
+ </a>
+ </div>
+ <div class="msg-ts">{{ msg.created | prettyTime }}</div>
+ </div>
+ <div class="msg-txt">{{ msg | formatMessage }}</div>
+ </div>
+ </li>
+ {% endfor %}
+</ul>
+{% endif %}
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/usercolumn" %}
+{% endblock %}
diff --git a/src/main/resources/templates/views/post.html b/src/main/resources/templates/views/post.html
new file mode 100644
index 00000000..a77fa3bd
--- /dev/null
+++ b/src/main/resources/templates/views/post.html
@@ -0,0 +1,22 @@
+{% extends "layouts/default" %}
+{% import "views/macros/tags" %}
+{% block content %}
+<article>
+<form id="postmsg">
+ <p style="text-align: left;">
+ <b>Фото:</b> <span id="attachmentfile">
+ <input style="width: 100%;" type="file" name="attach" accept="image/jpeg,image/png"/> <i>({{ i18n("messages","postForm.imageFormats") }})</i></span>
+ </p>
+ <p>
+ <textarea name="body" class="newmessage" rows="7" cols="10" placeholder="*weather It's very cold today!">{{ body }}</textarea>
+ <br/>
+ <input type="submit" class="subm Button" value=" {{ i18n("messages","postForm.submit") }} "/>
+ </p>
+</form>
+</article>
+<p style="text-align: left;"><b>Теги:</b></p>
+{{ tags(visitor.name, tags) }}
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/usercolumn" %}
+{% endblock %}
diff --git a/src/main/resources/templates/views/post_success.html b/src/main/resources/templates/views/post_success.html
new file mode 100644
index 00000000..2106f3cb
--- /dev/null
+++ b/src/main/resources/templates/views/post_success.html
@@ -0,0 +1,19 @@
+{% extends "layouts/minimal" %}
+{% block content %}
+<h1>Сообщение опубликовано</h1>
+<p>Поделитесь своим новым постом в социальных сетях:</p>
+{% if sharetwi | default('') is not empty %}
+<p class="social">
+ <a href="https://twitter.com/intent/tweet?text={{ sharetwi }}"
+ class="sharenew"><i data-icon="ei-sc-twitter" data-size="m"></i>Отправить в Twitter</a></p>
+{% endif %}
+<p class="social">
+ <a href="https://vk.com/share.php?url={{ url | urlencode }}"
+ class="sharenew"><i data-icon="ei-sc-vk" data-size="m"></i>Отправить в ВКонтакте</a></p>
+{% if facebook | default('') is not empty %}
+<p class="social">
+ <a href="https://www.facebook.com/sharer/sharer.php?u={{ url | urlencode }}"
+ class="sharenew"><i data-icon="ei-sc-facebook" data-size="m"></i>Отправить в Facebook</a></p>
+{% endif %}
+<p>Ссылка на сообщение: <a href="{{ url | raw }}">{{ url }}</a></p>
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/settings_about.html b/src/main/resources/templates/views/settings_about.html
new file mode 100644
index 00000000..5e308671
--- /dev/null
+++ b/src/main/resources/templates/views/settings_about.html
@@ -0,0 +1,20 @@
+{% extends "layouts/default" %}
+{% block content %}
+<article>
+ <form action="/settings" method="POST" enctype="multipart/form-data">
+ <p>Full name: <input type="text" name="fullname" value="{{ userinfo.fullName }}"/></p>
+ <p>Country: <input type="text" name="country" value="{{ userinfo.country }}"/></p>
+ <p>URL: <input type="text" name="url" value="{{ userinfo.url }}" size="32"/><br/>
+ <small>Please, start with &quot;http://&quot;</small></p>
+ <p>About:<br/>
+ <input type="text" name="descr" value="{{ userinfo.description }}" style="width: 100%;"/><br/>
+ <small>Max. 255 symbols</small></p>
+ <p>Avatar: <input type="file" name="avatar"/><br/>
+ <small>Recommendations: PNG, 96x96, &lt;50Kb. Also, JPG and GIF supported.</small></p>
+ <p><input type="hidden" name="page" value="about"/><input type="submit" value=" OK "/></p>
+ </form>
+</article>
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/settings_tabs" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/settings_auth-email.html b/src/main/resources/templates/views/settings_auth-email.html
new file mode 100644
index 00000000..e906d704
--- /dev/null
+++ b/src/main/resources/templates/views/settings_auth-email.html
@@ -0,0 +1,9 @@
+{% extends "layouts/default" %}
+{% block content %}
+<article>
+ <p>{{ result }}</p><p><a href="/settings">Settings</a>.</p>
+</article>
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/settings_tabs" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/settings_main.html b/src/main/resources/templates/views/settings_main.html
new file mode 100644
index 00000000..a6cca7a3
--- /dev/null
+++ b/src/main/resources/templates/views/settings_main.html
@@ -0,0 +1,154 @@
+{% extends "layouts/default" %}
+{% block content %}
+<article>
+ <h1>Настройки</h1>
+ {%if not visitor.verified %}
+ <h2 style="color: red; padding: 20px;">Verify your account by adding email or social account</h2>
+ {% endif %}
+ <form action="/settings" method="POST" enctype="multipart/form-data">
+ <fieldset>
+ <legend>Notification options</legend>
+ <p><input type="checkbox" name="jnotify" value="1" {% if notify_options.repliesEnabled %}
+ checked="checked" {% endif %}/> Reply notifications (&quot;Message posted&quot;)</p>
+ <p><input type="checkbox" name="subscr_notify" value="1" {% if notify_options.subscriptionsEnabled %}
+ checked="checked" {% endif %}/> Subscriptions notifications (&quot;@user subscribed...&quot;)</p>
+ <p><input type="checkbox" name="recomm" value="1" {% if notify_options.recommendationsEnabled %}
+ checked="checked" {% endif %}/> Posts recommendations (&quot;Recommended by @user&quot;)</p>
+ <p><input type="hidden" name="page" value="main"/><input type="submit" class="Button" value=" OK "/></p>
+ </fieldset>
+ </form>
+ <fieldset>
+ <legend style="background: url(/durov.png) no-repeat; padding-left: 58px; line-height: 48px; background-size: contain;">
+ Telegram</legend>
+ {% if telegram_name is not empty %}
+ <form action="/settings" method="post">
+ <div>Telegram: <b>{{ telegram_name }}</b> &mdash;
+ <input type="hidden" name="page" value="telegram-del"/>
+ <input type="submit" value=" Disable " class="Button" />
+ </div>
+ </form>
+ {% else %}
+ <p>To connect Telegram account: send any text message to <a href="https://telegram.me/Juick_bot">@Juick_bot</a>
+ </p>
+ {% endif %}
+ </fieldset>
+ {% if jids | length > 0 %}
+ <form action="/settings" method="POST" enctype="multipart/form-data">
+ <fieldset>
+ <legend style="background: url(//static.juick.com/settings/xmpp.png) no-repeat; padding-left: 58px; line-height: 48px;">
+ XMPP accounts
+ </legend>
+ <p>Your accounts:</p>
+ <p>
+ {% for jid in jids %}
+ <label><input type="radio" name="delete" value="xmpp;{{ jid }}">{{ jid }}</label><br/>
+ {% endfor %}
+ {% for auth in auths %}
+ <label><input type="radio" name="delete"
+ value="xmpp-unauth;{{ auth.account }}">{{ auth.account }}</label>
+ &mdash; <a href="#"
+ onclick="alert('To confirm, please send &quot;AUTH {{ auth.getAuthCode() }}&quot; (without quotes) from this account to &quot;juick@juick.com&quot;.'); return false;">Confirm</a><br/>
+ {% endfor %}
+ </p>
+ {% if jids | length > 1 %}
+ <p><input type="hidden" name="page" value="jid-del"/><input type="submit" class="Button" value=" Delete "/></p>
+ {% endif %}
+ <p>To add new jabber account: send any text message to <a href="xmpp:juick@juick.com?message;body=login">juick@juick.com</a>
+ </p>
+ </fieldset>
+ </form>
+ {% endif %}
+ <fieldset>
+ <legend style="background: url(//static.juick.com/settings/email.png) no-repeat; padding-left: 58px; line-height: 48px;">
+ E-mail
+ </legend>
+ <form action="/settings" method="POST" enctype="multipart/form-data">
+ <p>Add account:<br/>
+ <input type="text" name="account"/>
+ <input type="hidden" name="page" value="email-add"/>
+ <input type="submit" value=" Add " class="Button" />
+ </p>
+ </form>
+ <form action="/settings" method="POST" enctype="multipart/form-data">
+ <p>Your accounts:</p>
+ <p>
+ {% for email in emails %}
+ <label><input type="radio" name="account" value="{{ email }}">{{ email }}</label><br/>
+ {% endfor %}
+ {% if emails is empty %}
+ - </p>
+ {% else %}
+ </p>
+ {% if jids | length > 1 %}
+ <p><input type="hidden" name="page" value="email-del"/><input type="submit" class="Button" value=" Delete "/></p>
+ {% endif %}
+ {% endif %}
+ </form>
+ {% if emails is not empty %}
+ <!--email_off-->
+ <form action="/settings" method="POST" enctype="multipart/form-data">
+ <p>You can receive notifications to email:<br/>
+ Sent to <select name="account">
+ <option value="">Disabled</option>
+ {% for email in emails %}
+ <option value="{{ email }}" {% if email_active == email %} selected="selected" {% endif %}>
+ {{ email }}
+ </option>
+ {% endfor %}
+ </select>
+ <input type="hidden" name="page" value="email-subscr"/>
+ <input type="submit" class="Button" value="OK"/></p>
+ </form>
+ <!--/email_off-->
+ {% endif %}
+ <p>&nbsp;</p>
+ <p>You can post to Juick via e-mail. Send your <span style="text-decoration: underline;">plain text</span>
+ messages to <span><a href="mailto:juick@juick.com">juick@juick.com</a></span>. You can attach one photo or video file.</p>
+ </fieldset>
+ <fieldset>
+ <legend style="background: url(//static.juick.com/settings/facebook.png) no-repeat; padding-left: 58px; line-height: 48px;">
+ Facebook
+ </legend>
+ {% if fbstatus.connected %}
+ {% if fbstatus.crosspostEnabled %}
+ <form action="/settings" method="post">
+ <div>
+ Facebook: <b>Enabled</b> &mdash;
+ <input type="hidden" name="page" value="facebook-disable"/>
+ <input type="submit" class="Button" value=" Disable "/>
+ </div>
+ </form>
+ {% else %}
+ <form action="/settings" method="post">
+ <div>
+ Facebook: <b>Disabled</b> &mdash;
+ <input type="hidden" name="page" value="facebook-enable"/>
+ <input type="submit" class="Button" value=" Enable "/>
+ </div>
+ </form>
+ {% endif %}
+ {% else %}
+ <p>Cross-posting to Facebook: <a href="/_fblogin"><img src="//static.juick.com/facebook-connect.png" alt="Connect to Facebook"/></a></p>
+ {% endif %}
+ </fieldset>
+ <fieldset>
+ <legend style="background: url(//static.juick.com/settings/twitter.png) no-repeat; padding-left: 58px; line-height: 48px;">
+ Twitter</legend>
+ {% if twitter_name is not empty %}
+ <form action="/settings" method="post">
+ <div>Twitter: <b>{{ twitter_name }}</b> &mdash;
+ <input type="hidden" name="page" value="twitter-del"/>
+ <input type="submit" class="Button" value=" Disable "/>
+ </div>
+ </form>
+ {% else %}
+ <p>Cross-posting to Twitter: <a href="/_twitter"><img src="//static.juick.com/twitter-connect.png"
+ alt="Connect to Twitter"/></a></p>
+ {% endif %}
+ </fieldset>
+
+</article>
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/settings_tabs" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/settings_password.html b/src/main/resources/templates/views/settings_password.html
new file mode 100644
index 00000000..99c1676e
--- /dev/null
+++ b/src/main/resources/templates/views/settings_password.html
@@ -0,0 +1,17 @@
+{% extends "layouts/default" %}
+{% block content %}
+<article>
+ <fieldset>
+ <legend>Changing your password</legend>
+ <form action="/settings" method="post">
+ <input type="hidden" name="page" value="password"/>
+ <p>Change password: <input type="password" name="password" size="8"/> <input class="Button" type="submit"
+ value=" Update "/><br/>
+ <i>(max. length - 16 symbols)</i></p>
+ </form>
+ </fieldset>
+</article>
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/settings_tabs" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/settings_privacy.html b/src/main/resources/templates/views/settings_privacy.html
new file mode 100644
index 00000000..83b87b93
--- /dev/null
+++ b/src/main/resources/templates/views/settings_privacy.html
@@ -0,0 +1,9 @@
+{% extends "layouts/default" %}
+{% block content %}
+<article>
+ <p>Privacy</p>
+</article>
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/settings_tabs" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/settings_result.html b/src/main/resources/templates/views/settings_result.html
new file mode 100644
index 00000000..d87a5ea6
--- /dev/null
+++ b/src/main/resources/templates/views/settings_result.html
@@ -0,0 +1,9 @@
+{% extends "layouts/default" %}
+{% block content %}
+<article>
+ <p>{{ result | raw }}</p>
+</article>
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/settings_tabs" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/signup.html b/src/main/resources/templates/views/signup.html
new file mode 100644
index 00000000..d6eb921f
--- /dev/null
+++ b/src/main/resources/templates/views/signup.html
@@ -0,0 +1,43 @@
+{% extends "layouts/default" %}
+{% block content %}
+<h1 class="signup-h1">
+ {% if type | slice(0, 1) == 'f' %}
+ <img src="//static.juick.com/settings/facebook.png" alt="Facebook"/>
+ {% elseif type | slice(0, 1) == 'v' %}
+ <img src="//static.juick.com/settings/vk.png" alt="VKontakte"/>
+ {% elseif type | slice(0, 1) == 'e' %}
+ <img src="//static.juick.com/settings/email.png" alt="Email"/>
+ {% elseif type | slice(0, 1) == 'd' %}
+ <img src="//telegram.org/favicon.ico?3" alt="Telegram"/>
+ {% endif %}
+ {{ account | raw }}</h1>
+
+<h2 class="signup-h2">Связать с существующим аккаунтом Juick</h2>
+<form action="/signup" method="post">
+ <input type="hidden" name="action" value="link"/>
+ <input type="hidden" name="type" value="{{ type }}"/>
+ <input type="hidden" name="hash" value="{{ hash }}"/>
+ {% if visitor.getUID() > 0 %}
+ <input type="submit" value="Связать с этим аккаунтом"/>
+ {% else %}
+ <p>Имя пользователя: <input type="text" name="username"/></p>
+ <p>Пароль: <input type="password" name="password"/></p>
+ <p><input type="submit" value=" OK "/></p>
+ {% endif %}
+</form>
+
+{% if type != "xmpp" %}
+<hr class="signup-hr"/>
+
+<h2 class="signup-h2">Создать новый аккаунт Juick</h2>
+<form action="/signup" method="post">
+ <input type="hidden" name="action" value="new"/>
+ <input type="hidden" name="type" value="{{ type }}"/>
+ <input type="hidden" name="hash" value="{{ hash }}"/>
+ <p>Имя пользователя: <input type="text" name="username" id="username"/><br/><i>(От 2-х до 16-и латинских символов
+ и/или цифр, дефис)</i></p>
+ <p>Пароль: <input type="password" name="password"/><br/><i>(от 6-и до 32-х символов)</i></p>
+ <p><input type="submit" value=" OK "/></p>
+</form>
+{% endif %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/signup_result.html b/src/main/resources/templates/views/signup_result.html
new file mode 100644
index 00000000..b204e1b8
--- /dev/null
+++ b/src/main/resources/templates/views/signup_result.html
@@ -0,0 +1,6 @@
+{% extends "layouts/default" %}
+{% block content %}
+<article>
+ <p>{{ result | raw }}</p>
+</article>
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/thread.html b/src/main/resources/templates/views/thread.html
new file mode 100644
index 00000000..f1563a7c
--- /dev/null
+++ b/src/main/resources/templates/views/thread.html
@@ -0,0 +1,188 @@
+{% extends "layouts/default" %}
+{% import "views/macros/tags" %}
+{% block content %}
+<ul id="0">
+ <li id="msg-{{ msg.mid }}" class="msg msgthread">
+ <div class="msg-cont">
+ <div class="msg-header">
+ <div class="msg-avatar">
+ <a href="/{{ msg.user.name }}/"><img src="{{ msg.user.avatar }}" alt="{{ msg.user.name }}"/></a>
+ </div>
+ <span>
+ <a href="/{{ msg.user.name }}/"><span>{{ msg.user.name }}</span></a>
+ </span>
+ <div class="msg-ts">
+ {% if msg.FriendsOnly %}
+ <i data-icon="ei-lock" data-size="s"></i> &middot;
+ {% endif %}
+ <a href="/{{ msg.user.name }}/{{ msg.mid }}">
+ <time datetime="{{ msg.created | timestamp | date('yyyy-MM-dd HH:mm:ss') }}Z"
+ title="{{ msg.created | timestamp | date('yyyy-MM-dd HH:mm:ss') }} GMT">
+ {{ msg.created | prettyTime }}
+ </time>
+ </a>
+ {% if msg.updatedAt != msg.created %}
+ &middot; Edited
+ {% endif %}
+ </div>
+ </div>
+ <div class="msg-txt">
+ <span class="msg-tags">
+ {{ tags(msg.user.name, msg.tags | tagsList) }}
+ </span>
+ {{ msg | formatMessage }}
+ </div>
+ {% if msg.AttachmentType is not empty %}
+ <div class="msg-media">
+ <a href="//i.juick.com/p/{{ msg.mid }}.{{ msg.AttachmentType }}" data-fname="{{ msg.mid }}.{{ msg.AttachmentType }}">
+ <img src="//i.juick.com/photos-512/{{ msg.mid }}.{{ msg.AttachmentType }}" alt=""/>
+ </a>
+ </div>
+ {% endif %}
+ <nav class="l">
+ {% if visitor.uid == msg.user.uid %}
+ <a href="/{{ msg.mid }}" class="a-like msg-button">
+ <span class="msg-button-icon">
+ <i data-icon="ei-heart" data-size="s"></i>
+ {% if msg.Likes > 0 %}&nbsp;{{ msg.Likes }}
+ {% else %}
+ <span>&nbsp;{{ i18n("messages","message.recommend") }}</span>
+ {% endif %}
+ </span>
+ </a>
+ {% elseif visitor.uid > 0 %}
+ <a href="/post?body=!+%23{{ msg.mid }}" class="a-like msg-button">
+ <span class="msg-button-icon">
+ <i data-icon="ei-heart" data-size="s"></i>
+ {% if msg.Likes > 0 %}&nbsp;{{ msg.Likes }}
+ {% else %}
+ <span>&nbsp;{{ i18n("messages","message.recommend") }}</span>
+ {% endif %}
+ </span>
+ </a>
+ {% else %}
+ <a href="/login" class="a-login msg-button">
+ <span class="msg-button-icon">
+ <i data-icon="ei-heart" data-size="s"></i>
+ {% if msg.Likes > 0 %}&nbsp;{{ msg.Likes }}
+ {%else %}
+ <span>&nbsp;{{ i18n("messages","message.recommend") }}</span>
+ {% endif %}
+ </span>
+ </a>
+ {% endif %}
+ {% if visitor.uid > 0 %}
+ {% if visitor.uid != msg.user.uid %}
+ {% if visitorSubscribed %}
+ <a href="/post?body=U+%23{{ msg.mid }}" class="msg-button">
+ <i data-icon="ei-check" data-size="s"></i>
+ <span>&nbsp;{{ i18n("messages","message.subscribed") }}</span>
+ </a>
+ {% else %}
+ <a href="/post?body=S+%23{{ msg.mid }}" class="a-sub msg-button">
+ <i data-icon="ei-eye" data-size="s"></i>
+ <span>&nbsp;{{ i18n("messages","message.subscribe") }}</span>
+ </a>
+ {% endif %}
+ {% else %}
+ <a href="/post?body=D+%23{{ msg.mid }}" class="msg-button">
+ <i data-icon="ei-close" data-size="s"></i>
+ <span>&nbsp;{{ i18n("messages","message.delete") }}</span>
+ </a>
+ {% endif %}
+ {% endif %}
+ </nav>
+ {% if msg.VisitorCanComment %}
+ <form class="msg-comment-target">
+ <input type="hidden" name="mid" value="{{ msg.mid }}"/>
+ <div class="msg-comment">
+ <div class="ta-wrapper">
+ <textarea name="body" rows="1" class="reply" placeholder="{{ i18n("messages","message.writeComment") }}"></textarea>
+ </div>
+ </div>
+ </form>
+ {% endif %}
+ {% if recomm is not empty %}
+ <div class="msg-recomms">{{ i18n("messages","message.recommendedBy") }}
+ {% for rec in recomm %}
+ {% if rec.uri.toString() is empty %}
+ <a href="/{{ rec.name }}/">@{{ rec.name }}</a>{% if loop.index < (loop.length - 1) %}, {% endif %}
+ {% else %}
+ <a href="{{ rec.uri }}" data-user-uri="1">@{{ rec.name }}</a>{% if loop.index < (loop.length - 1) %}, {% endif %}
+ {% endif %}
+ {% endfor %}
+ {% if msg.likes > recomm.size() %}
+ &nbsp;{{ i18n("messages","message.recommendedOthers", msg.likes - recomm.size()) }}
+ {% endif %}
+ </div>
+ {% endif %}
+ </div>
+ </li>
+</ul>
+<div class="title2">
+ {% if visitor.uid > 0 %}
+ <img src="/api/thread/mark_read/{{ msg.mid }}-{{ msg.rid }}.gif?hash={{visitor.authHash}}" />
+ {% endif %}
+ <h2>{{ i18n("messages","reply.replies") }} ({{ replies.size() }})</h2>
+</div>
+
+<ul id="replies">
+ {% for msg in replies %}
+ <li id="{{ msg.rid }}" class="msg">
+ <div class="msg-cont">
+ <div class="msg-header" data-uri="{{ msg.user.uri }}">
+ {% if not msg.user.banned %}
+ <a class="a-username" href="/{{ msg.user.name }}/">{{ msg.user.name }}</a>
+ <div class="msg-avatar">
+ <a class="a-username" href="/{{ msg.user.name }}/">
+ <img src="{{ msg.user.avatar }}" alt="{{ msg.user.name }}"/>
+ </a>
+ </div>
+ {% else %}
+ [удалено]:
+ <div class="msg-avatar">
+ <img src="//i.juick.com/av-96.png"/>
+ </div>
+ {% endif %}
+ <div class="msg-ts">
+ <a href="/{{ msg.mid }}#{{ msg.rid }}">
+ <time datetime="{{ msg.created | timestamp | date('yyyy-MM-dd HH:mm:ss') }}Z"
+ title="{{ msg.created | timestamp | date('yyyy-MM-dd HH:mm:ss') }} GMT">
+ {{ msg.created | prettyTime }}
+ </time>
+ </a>
+ {% if msg.updatedAt != msg.created %}
+ &middot; Edited
+ {% endif %}
+ </div>
+ </div>
+ <div class="msg-txt">{{ msg | formatMessage }}</div>
+ {% if msg.AttachmentType is not empty %}
+ <div class="msg-media">
+ <a href="//i.juick.com/p/{{ msg.mid }}-{{ msg.rid }}.{{ msg.AttachmentType }}" data-fname="{{ msg.mid }}-{{ msg.rid }}.{{ msg.AttachmentType }}">
+ <img src="//i.juick.com/photos-512/{{ msg.mid }}-{{ msg.rid }}.{{ msg.AttachmentType }}" alt=""/>
+ </a>
+ </div>
+ {% endif %}
+ <div class="msg-links">/{{ msg.rid }}
+ {% if msg.replyto > 0 %}
+ {{ i18n("messages","reply.inReplyTo") }} <a href="#{{ msg.replyto }}">/{{ msg.replyto }}</a>
+ {% endif %}
+ {% if msg.VisitorCanComment %}
+ &middot; <a href="/post?body=%23{{ msg.mid }}/{{ msg.rid }}%20" class="a-thread-comment">{{ i18n("messages","reply.reply") }}</a>
+ </div>
+ <div class="msg-comment-target msg-comment-hidden"></div>
+ {% elseif visitor.uid == 0 %}
+ &middot; <a href="#" class="a-login">{{ i18n("messages","reply.reply") }}</a>
+ </div>
+ {% else %}
+ </div>
+ {% endif %}
+ </div>
+ </li>
+ {% endfor %}
+</ul>
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/usercolumn" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/templates/views/users.html b/src/main/resources/templates/views/users.html
new file mode 100644
index 00000000..702ba6b9
--- /dev/null
+++ b/src/main/resources/templates/views/users.html
@@ -0,0 +1,17 @@
+{% extends "layouts/default" %}
+{% import "views/macros/tags" %}
+{% block content %}
+<div class="users">
+ {% for u in users %}
+ <span>
+ <a href="/{{ u.name }}/">
+ <img src="//i.juick.com/as/{{ u.uid }}.png" alt="{{ u.name }}"/>
+ {{ u.name }}
+ </a>
+ </span>
+ {% endfor %}
+</div>
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/usercolumn" %}
+{% endblock %} \ No newline at end of file
diff --git a/src/main/resources/testkey.p8 b/src/main/resources/testkey.p8
new file mode 100644
index 00000000..1e5d0f98
--- /dev/null
+++ b/src/main/resources/testkey.p8
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg72/yb71r7uVirjpf
+vjAPZ5aUR0si2c1yH6Lt/NlhWcWhRANCAAQydvu0D1+DTVM0/U0rbxHfkG3AswYw
+hZZk58QvxSbxoBcmoLLMKAuaNBCVg+4I0xKvCfB0dkIjRATNpveON8y3
+-----END PRIVATE KEY-----