From 248c05840275516cbc5c99c8e5d87d007ca37284 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Thu, 21 Jun 2018 20:24:45 +0300 Subject: www project disabled, all new web development moved to separate repo --- juick-api/build.gradle | 7 - .../src/main/java/com/juick/server/api/Post.java | 205 --- .../server/configuration/ApiSecurityConfig.java | 125 -- .../com/juick/server/configuration/PostConfig.java | 9 - juick-server-jdbc/build.gradle | 6 - .../juick/configuration/UpdaterConfiguration.java | 47 - .../main/java/com/juick/database/MySqlUpdater.java | 153 -- .../java/com/juick/service/BaseJdbcService.java | 41 - .../com/juick/service/CrosspostServiceImpl.java | 273 ---- .../java/com/juick/service/EmailServiceImpl.java | 92 -- .../com/juick/service/MessagesServiceImpl.java | 1006 ------------- .../com/juick/service/MessengerServiceImpl.java | 71 - .../com/juick/service/PMQueriesServiceImpl.java | 174 --- .../juick/service/PrivacyQueriesServiceImpl.java | 63 - .../com/juick/service/PushQueriesServiceImpl.java | 143 -- .../com/juick/service/ShowQueriesServiceImpl.java | 62 - .../com/juick/service/SphinxSearchService.java | 85 -- .../com/juick/service/SubscriptionServiceImpl.java | 249 ---- .../java/com/juick/service/TagServiceImpl.java | 273 ---- .../com/juick/service/TelegramServiceImpl.java | 94 -- .../java/com/juick/service/UserServiceImpl.java | 689 --------- juick-server-jdbc/src/main/resources/juick.sql | 947 ------------ juick-server-jdbc/src/main/resources/pg_schema_wip | 1539 -------------------- juick-server-jdbc/src/main/resources/schema.sql | 379 ----- juick-server-jdbc/src/main/resources/update.sql | 12 - juick-server/build.gradle | 7 +- .../src/main/java/com/juick/server/api/Post.java | 205 +++ .../server/configuration/ApiSecurityConfig.java | 125 ++ .../com/juick/server/configuration/PostConfig.java | 9 + .../java/com/juick/service/BaseJdbcService.java | 41 + .../com/juick/service/CrosspostServiceImpl.java | 273 ++++ .../java/com/juick/service/EmailServiceImpl.java | 92 ++ .../com/juick/service/MessagesServiceImpl.java | 1006 +++++++++++++ .../com/juick/service/MessengerServiceImpl.java | 71 + .../com/juick/service/PMQueriesServiceImpl.java | 174 +++ .../juick/service/PrivacyQueriesServiceImpl.java | 63 + .../com/juick/service/PushQueriesServiceImpl.java | 143 ++ .../com/juick/service/ShowQueriesServiceImpl.java | 62 + .../com/juick/service/SphinxSearchService.java | 85 ++ .../com/juick/service/SubscriptionServiceImpl.java | 249 ++++ .../java/com/juick/service/TagServiceImpl.java | 273 ++++ .../com/juick/service/TelegramServiceImpl.java | 94 ++ .../java/com/juick/service/UserServiceImpl.java | 689 +++++++++ juick-server/src/main/java/ru/sape/Sape.java | 23 + .../src/main/java/ru/sape/SapeConnection.java | 108 ++ .../src/main/java/ru/sape/SapePageLinks.java | 76 + juick-server/src/main/resources/juick.sql | 947 ++++++++++++ juick-server/src/main/resources/pg_schema_wip | 1539 ++++++++++++++++++++ juick-server/src/main/resources/schema.sql | 379 +++++ juick-server/src/main/resources/update.sql | 12 + .../pebble/extension/FormatterExtension.java | 38 - .../extension/filters/FormatMessageFilter.java | 52 - .../pebble/extension/filters/PrettyTimeFilter.java | 51 - .../pebble/extension/filters/TagsListFilter.java | 41 - .../pebble/extension/filters/TimestampFilter.java | 23 - juick-www/src/main/java/ru/sape/Sape.java | 23 - .../src/main/java/ru/sape/SapeConnection.java | 108 -- juick-www/src/main/java/ru/sape/SapePageLinks.java | 76 - settings.gradle | 2 +- 59 files changed, 6744 insertions(+), 7159 deletions(-) delete mode 100644 juick-api/build.gradle delete mode 100644 juick-api/src/main/java/com/juick/server/api/Post.java delete mode 100644 juick-api/src/main/java/com/juick/server/configuration/ApiSecurityConfig.java delete mode 100644 juick-api/src/main/java/com/juick/server/configuration/PostConfig.java delete mode 100644 juick-server-jdbc/build.gradle delete mode 100644 juick-server-jdbc/src/main/java/com/juick/configuration/UpdaterConfiguration.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/database/MySqlUpdater.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/BaseJdbcService.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/CrosspostServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/EmailServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/MessagesServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/MessengerServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/PMQueriesServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/PrivacyQueriesServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/PushQueriesServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/ShowQueriesServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/SphinxSearchService.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/SubscriptionServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/TagServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/TelegramServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/java/com/juick/service/UserServiceImpl.java delete mode 100644 juick-server-jdbc/src/main/resources/juick.sql delete mode 100644 juick-server-jdbc/src/main/resources/pg_schema_wip delete mode 100644 juick-server-jdbc/src/main/resources/schema.sql delete mode 100644 juick-server-jdbc/src/main/resources/update.sql create mode 100644 juick-server/src/main/java/com/juick/server/api/Post.java create mode 100644 juick-server/src/main/java/com/juick/server/configuration/ApiSecurityConfig.java create mode 100644 juick-server/src/main/java/com/juick/server/configuration/PostConfig.java create mode 100644 juick-server/src/main/java/com/juick/service/BaseJdbcService.java create mode 100644 juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/EmailServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/MessengerServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/PMQueriesServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/PrivacyQueriesServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/PushQueriesServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/ShowQueriesServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/SphinxSearchService.java create mode 100644 juick-server/src/main/java/com/juick/service/SubscriptionServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/TagServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/TelegramServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/UserServiceImpl.java create mode 100644 juick-server/src/main/java/ru/sape/Sape.java create mode 100644 juick-server/src/main/java/ru/sape/SapeConnection.java create mode 100644 juick-server/src/main/java/ru/sape/SapePageLinks.java create mode 100644 juick-server/src/main/resources/juick.sql create mode 100644 juick-server/src/main/resources/pg_schema_wip create mode 100644 juick-server/src/main/resources/schema.sql create mode 100644 juick-server/src/main/resources/update.sql delete mode 100644 juick-www/src/main/java/com/mitchellbosecke/pebble/extension/FormatterExtension.java delete mode 100644 juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/FormatMessageFilter.java delete mode 100644 juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/PrettyTimeFilter.java delete mode 100644 juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/TagsListFilter.java delete mode 100644 juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/TimestampFilter.java delete mode 100644 juick-www/src/main/java/ru/sape/Sape.java delete mode 100644 juick-www/src/main/java/ru/sape/SapeConnection.java delete mode 100644 juick-www/src/main/java/ru/sape/SapePageLinks.java diff --git a/juick-api/build.gradle b/juick-api/build.gradle deleted file mode 100644 index 2899529a..00000000 --- a/juick-api/build.gradle +++ /dev/null @@ -1,7 +0,0 @@ -apply plugin: 'java' - -dependencies { - compile project(':juick-common') - compile project(':juick-server-jdbc') - compile 'org.apache.commons:commons-email:1.5' -} \ No newline at end of file diff --git a/juick-api/src/main/java/com/juick/server/api/Post.java b/juick-api/src/main/java/com/juick/server/api/Post.java deleted file mode 100644 index afe9d2d5..00000000 --- a/juick-api/src/main/java/com/juick/server/api/Post.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.api; - -import com.juick.Reaction; -import com.juick.Status; -import com.juick.User; -import com.juick.server.CommandsManager; -import com.juick.server.helpers.CommandResult; -import com.juick.server.util.*; -import com.juick.service.MessagesService; -import com.juick.service.SubscriptionService; -import com.juick.service.UserService; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.inject.Inject; -import javax.validation.constraints.NotNull; -import java.net.URI; -import java.net.URL; -import java.util.List; - -/** - * Created by vt on 24/11/2016. - */ -@RestController -public class Post { - private static Logger logger = LoggerFactory.getLogger(Post.class); - - @Inject - private UserService userService; - @Inject - private MessagesService messagesService; - @Inject - private SubscriptionService subscriptionService; - @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String tmpDir; - @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String imgDir; - @Inject - CommandsManager commandsManager; - - @RequestMapping(value = "/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) - @ResponseStatus(value = HttpStatus.OK) - public CommandResult doPostMessage( - @RequestParam(required = false, defaultValue = StringUtils.EMPTY) String body, - @RequestParam(required = false) String img, - @RequestParam(required = false) MultipartFile attach) throws Exception { - User visitor = UserUtils.getCurrentUser(); - - if (visitor.isAnonymous()) - throw new HttpForbiddenException(); - - if (body.length() > 4096) { - throw new HttpBadRequestException(); - } - body = body.replace("\r", StringUtils.EMPTY); - - URI attachmentFName = HttpUtils.receiveMultiPartFile(attach, tmpDir); - - if (StringUtils.isBlank(attachmentFName.toString()) && img != null && img.length() > 10) { - URI juickUri = URI.create(img); - if (juickUri.getScheme().equals("juick")) { - attachmentFName = juickUri; - } else { - try { - URL imgUrl = new URL(img); - attachmentFName = HttpUtils.downloadImage(imgUrl, tmpDir); - } catch (Exception e) { - logger.error("DOWNLOAD ERROR", e); - throw new HttpBadRequestException(); - } - } - } - if (StringUtils.isBlank(body) && StringUtils.isBlank(attachmentFName.toString())) { - // Should be there for compatibility - throw new HttpBadRequestException(); - } - return commandsManager.processCommand(visitor, body, attachmentFName); - } - - @RequestMapping(value = "/comment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) - public com.juick.Message doPostComment( - @RequestParam(defaultValue = "0") int mid, - @RequestParam(defaultValue = "0") int rid, - @RequestParam(required = false, defaultValue = StringUtils.EMPTY) String body, - @RequestParam(required = false) String img, - @RequestParam(required = false) MultipartFile attach) - throws Exception { - User visitor = UserUtils.getCurrentUser(); - int vuid = visitor.getUid(); - if (vuid == 0) { - throw new HttpForbiddenException(); - } - if (mid == 0) { - throw new HttpBadRequestException(); - } - com.juick.Message msg = messagesService.getMessage(mid); - if (msg == null) { - throw new HttpNotFoundException(); - } - - com.juick.Message reply = null; - if (rid > 0) { - reply = messagesService.getReply(mid, rid); - if (reply == null) { - throw new HttpNotFoundException(); - } - } - - if (body.length() > 4096) { - throw new HttpBadRequestException(); - } - body = body.replace("\r", StringUtils.EMPTY); - - if ((msg.ReadOnly && msg.getUser().getUid() != vuid) || userService.isInBLAny(msg.getUser().getUid(), vuid) - || (reply != null && userService.isInBLAny(reply.getUser().getUid(), vuid))) { - throw new HttpForbiddenException(); - } - - URI attachmentFName = HttpUtils.receiveMultiPartFile(attach, tmpDir); - - if (StringUtils.isBlank(attachmentFName.toString()) && img != null && img.length() > 10) { - try { - attachmentFName = HttpUtils.downloadImage(new URL(img), tmpDir); - } catch (Exception e) { - logger.error("DOWNLOAD ERROR", e); - throw new HttpBadRequestException(); - } - } - - return commandsManager.processCommand(visitor, String.format("#%d/%d %s", mid, rid, body), attachmentFName).getNewMessage().get(); - } - - @PostMapping("/like") - @ResponseStatus(value = HttpStatus.OK) - public Status doPostRecomm(@RequestParam Integer mid) throws Exception { - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.isAnonymous()) { - throw new HttpForbiddenException(); - } - com.juick.Message msg = messagesService.getMessage(mid); - if (msg == null) { - throw new HttpNotFoundException(); - } - if (msg.getUser().getUid() == visitor.getUid()) { - throw new HttpForbiddenException(); - } - CommandResult status = commandsManager.processCommand(visitor, String.format("! #%d", mid), - URI.create(StringUtils.EMPTY)); - return Status.getStatus(status.getText()); - } - - @GetMapping("/reactions") - @ResponseStatus(value = HttpStatus.OK) - public List reactionsList() { - return messagesService.listReactions(); - } - - @PostMapping("/react") - @ResponseStatus(value = HttpStatus.OK) - public Status doPostReact(@RequestParam Integer mid,@RequestParam @NotNull int reactionId, - @RequestParam (required = false, defaultValue = "1") int count) { - - logger.info("got reaction with type: {}", reactionId); - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.isAnonymous()) { - throw new HttpForbiddenException(); - } - com.juick.Message msg = messagesService.getMessage(mid); - if (msg == null) { - throw new HttpNotFoundException(); - } - if (msg.getUser().getUid() == visitor.getUid()) { - throw new HttpForbiddenException(); - } - MessagesService.RecommendStatus recommendStatus = MessagesService.RecommendStatus.Error; - for (int i = 0; i < count; i++) - recommendStatus = messagesService.likeMessage(mid, visitor.getUid(), - reactionId); - - return recommendStatus == MessagesService.RecommendStatus.Error ? Status.ERROR :Status.OK; - } -} diff --git a/juick-api/src/main/java/com/juick/server/configuration/ApiSecurityConfig.java b/juick-api/src/main/java/com/juick/server/configuration/ApiSecurityConfig.java deleted file mode 100644 index 94c1f1a8..00000000 --- a/juick-api/src/main/java/com/juick/server/configuration/ApiSecurityConfig.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.configuration; - -import com.juick.service.UserService; -import com.juick.service.security.JuickUserDetailsService; -import com.juick.service.security.deprecated.RequestParamHashRememberMeServices; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.security.authentication.dao.DaoAuthenticationProvider; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.security.web.authentication.HttpStatusEntryPoint; -import org.springframework.security.web.authentication.RememberMeServices; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -import javax.inject.Inject; -import java.util.Arrays; -import java.util.Collections; -import java.util.concurrent.TimeUnit; - -/** - * Created by aalexeev on 11/21/16. - */ -@Configuration -@EnableWebSecurity -public class ApiSecurityConfig extends WebSecurityConfigurerAdapter { - @Value("${auth_remember_me_key:secret}") - private String rememberMeKey; - @Inject - private UserService userService; - - ApiSecurityConfig() { - super(true); - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests() - .antMatchers(HttpMethod.OPTIONS).permitAll() - .antMatchers("/", "/messages", "/users", "/thread", "/tags", "/tlgmbtwbhk", "/fbwbhk", - "/skypebotendpoint").permitAll() - .anyRequest().hasRole("USER") - .and().httpBasic().authenticationEntryPoint(juickAuthenticationEntryPoint()) - .and().anonymous() - .and().cors().configurationSource(corsConfigurationSource()) - .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and().exceptionHandling().authenticationEntryPoint(juickAuthenticationEntryPoint()) - .and() - .rememberMe() - .alwaysRemember(true) - .tokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(6 * 30)) - .rememberMeServices(rememberMeServices()) - .key(rememberMeKey) - .and().authenticationProvider(authenticationProvider()) - .headers().defaultsDisabled().cacheControl(); - } - - @Bean - public DaoAuthenticationProvider authenticationProvider() { - DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); - - authenticationProvider.setUserDetailsService(userDetailsService()); - - return authenticationProvider; - } - - @Bean - public JuickUserDetailsService userDetailsService() { - return new JuickUserDetailsService(userService); - } - - @Bean - public RememberMeServices rememberMeServices() { - return new RequestParamHashRememberMeServices(rememberMeKey, userService); - } - - @Bean - public AuthenticationEntryPoint juickAuthenticationEntryPoint() { - return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED); - } - - @Bean - public CorsConfigurationSource corsConfigurationSource() { - CorsConfiguration configuration = new CorsConfiguration(); - - configuration.setAllowedOrigins(Collections.singletonList("*")); - configuration.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "OPTIONS", "DELETE")); - configuration.setAllowedHeaders(Collections.singletonList("*")); - - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", configuration); - - return source; - } - @Override - public void configure(WebSecurity web) throws Exception { - web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", - "/configuration/**", "/swagger-ui.html", "/webjars/**", "/ws/**", "/rss/**"); - } -} diff --git a/juick-api/src/main/java/com/juick/server/configuration/PostConfig.java b/juick-api/src/main/java/com/juick/server/configuration/PostConfig.java deleted file mode 100644 index 598a7435..00000000 --- a/juick-api/src/main/java/com/juick/server/configuration/PostConfig.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.juick.server.configuration; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.context.annotation.ComponentScan; - -@EnableAutoConfiguration -@ComponentScan({"com.juick.server", "com.juick.service"}) -public class PostConfig { -} diff --git a/juick-server-jdbc/build.gradle b/juick-server-jdbc/build.gradle deleted file mode 100644 index 7052b04d..00000000 --- a/juick-server-jdbc/build.gradle +++ /dev/null @@ -1,6 +0,0 @@ -apply plugin: 'java' - -dependencies { - compile("org.springframework.boot:spring-boot-starter-jdbc") - compile project(':juick-common') -} diff --git a/juick-server-jdbc/src/main/java/com/juick/configuration/UpdaterConfiguration.java b/juick-server-jdbc/src/main/java/com/juick/configuration/UpdaterConfiguration.java deleted file mode 100644 index 979b38f9..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/configuration/UpdaterConfiguration.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.configuration; - -import com.juick.database.MySqlUpdater; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.DependsOn; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.transaction.PlatformTransactionManager; - -import javax.inject.Inject; - -/** - * Created by aalexeev on 12/13/16. - */ -@Configuration -public class UpdaterConfiguration { - @Inject - JdbcTemplate jdbcTemplate; - @Inject - PlatformTransactionManager transactionManager; - - @Bean - @DependsOn({"jdbcTemplate", "transactionManager"}) - public MySqlUpdater updater() { - return new MySqlUpdater( - jdbcTemplate, - transactionManager, - "update.sql"); - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/database/MySqlUpdater.java b/juick-server-jdbc/src/main/java/com/juick/database/MySqlUpdater.java deleted file mode 100644 index 69cde40b..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/database/MySqlUpdater.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.database; - -import org.apache.commons.codec.CharEncoding; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.support.TransactionTemplate; -import org.springframework.util.Assert; - -import javax.annotation.PostConstruct; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRED; - -/** - * Created by aalexeev on 12/13/16. - */ -public class MySqlUpdater { - private static final Pattern UPDATE_PATTERN = Pattern.compile( - "update\\s+(version|`version`)\\s+set\\s+(version|`version`)\\s+=\\s*(\\d+)", - Pattern.CASE_INSENSITIVE); - - private final Logger logger = LoggerFactory.getLogger(getClass()); - - private final JdbcTemplate jdbcTemplate; - private final TransactionTemplate transactionTemplate; - private final String updateSqlResource; - - - public MySqlUpdater(JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager, String updateSqlResource) { - Assert.notNull(jdbcTemplate, "JdbcTemplate must be initialized"); - Assert.notNull(transactionManager, "PlatformTransactionManager must be initialized"); - Assert.notNull(updateSqlResource, "sqlResource must be initialized"); - - this.jdbcTemplate = jdbcTemplate; - this.transactionTemplate = new TransactionTemplate(transactionManager); - this.updateSqlResource = updateSqlResource; - } - - @PostConstruct - public void init() { - try ( - InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(updateSqlResource); - ) { - if (is != null) { - String content = IOUtils.toString(is, CharEncoding.UTF_8); - if (StringUtils.isNotEmpty(content)) { - String[] sqlArray = content.split(";"); - if (sqlArray.length > 0) { - List sqlList = new ArrayList<>(sqlArray.length); - for (String sql : sqlArray) - if (!sql.isEmpty()) { - String sqlTrimmed = sql.trim(); - if (!sqlTrimmed.isEmpty()) - sqlList.add(sqlTrimmed); - } - if (!sqlList.isEmpty()) - processingSql(sqlList); - } - } - } - } catch (Exception e) { - logger.error("MySqlUpdater initialization exception", e); - } - } - - private void processingSql(final List sqls) { - long currentDbVersion = getSingleResult(this::getVersionRaw); - long actualVersion; - - List changesSql = new ArrayList<>(); - - for (String sql : sqls) { - changesSql.add(sql); - - Matcher m = UPDATE_PATTERN.matcher(sql); - if (m.matches()) { - actualVersion = Long.valueOf(m.group(3)); - - if (actualVersion > currentDbVersion) { - updateInTransaction(changesSql); - currentDbVersion = actualVersion; - } - changesSql.clear(); - } - } - } - - private void updateInTransaction(final List sqls) { - transactionTemplate.setReadOnly(false); - transactionTemplate.setPropagationBehavior(PROPAGATION_REQUIRED); - transactionTemplate.execute(status -> { - for (String sql : sqls) - jdbcTemplate.execute(sql); - return 0; - }); - } - - private T getSingleResult(Supplier supplier) { - transactionTemplate.setReadOnly(true); - transactionTemplate.setPropagationBehavior(PROPAGATION_REQUIRED); - - return transactionTemplate.execute(status -> supplier.get()); - } - - private long getVersionRaw() { - int cnt = jdbcTemplate.query( - "SELECT count(*) FROM information_schema.tables WHERE table_schema = ? AND table_name = ?", - rs -> { - int result = 0; - if (rs.next()) - result = rs.getInt(1); - return result; - }, - "juick", "version"); - - long version = 0l; - - if (cnt == 1) { - List list = jdbcTemplate.queryForList("select version from version", Long.class); - if (!list.isEmpty()) - version = list.get(0); - } - - return version; - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/BaseJdbcService.java b/juick-server-jdbc/src/main/java/com/juick/service/BaseJdbcService.java deleted file mode 100644 index 496a04ba..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/BaseJdbcService.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; - -import javax.inject.Inject; - -/** - * Created by aalexeev on 11/13/16. - */ -public class BaseJdbcService { - @Inject - JdbcTemplate jdbcTemplate; - @Inject - NamedParameterJdbcTemplate namedParameterJdbcTemplate; - - public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() { - return namedParameterJdbcTemplate; - } - - public JdbcTemplate getJdbcTemplate() { - return jdbcTemplate; - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/CrosspostServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/CrosspostServiceImpl.java deleted file mode 100644 index 0bd5fe66..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/CrosspostServiceImpl.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import com.juick.ExternalToken; -import com.juick.server.helpers.ApplicationStatus; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.Optional; - -/** - * Created by aalexeev on 11/13/16. - */ -@Repository -public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostService { - - @Transactional(readOnly = true) - @Override - public Optional getTwitterToken(final int uid) { - List list = getJdbcTemplate().query( - "SELECT uname, access_token, access_token_secret FROM twitter WHERE user_id = ? AND crosspost = 1", - (rs, num) -> new ExternalToken(rs.getString(1), "twitter", - rs.getString(2), rs.getString(3)), - uid); - - return list.isEmpty() ? - Optional.empty() : Optional.of(list.get(0)); - } - - @Transactional - @Override - public boolean deleteTwitterToken(Integer uid) { - return getJdbcTemplate().update("DELETE FROM twitter WHERE user_id=?", uid) > 0 - && getJdbcTemplate().update("DELETE FROM subscr_users WHERE user_id=? AND suser_id=1741", uid) > 0; - } - - @Override - public void addFacebookState(String state) { - jdbcTemplate.update("INSERT INTO facebook(loginhash) VALUES(?)", state); - } - - @Override - public boolean verifyFacebookState(String state) { - try { - return jdbcTemplate.queryForObject("SELECT COUNT(loginhash) FROM facebook WHERE loginhash=?", - Integer.class, state) == 1; - } catch (EmptyResultDataAccessException e) { - return false; - } - } - - @Transactional(readOnly = true) - @Override - public Optional> getFacebookTokens(final int uid) { - List>> list = getJdbcTemplate().query( - "SELECT fb_id, access_token FROM facebook WHERE user_id = ? AND access_token IS NOT NULL AND crosspost = 1", - (rs, num) -> Optional.of(Pair.of(rs.getString(1), rs.getString(2))), - uid); - return list.isEmpty() ? - Optional.empty() : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public ApplicationStatus getFbCrossPostStatus(final int uid) { - List list = getJdbcTemplate().query( - "SELECT 1, crosspost FROM facebook WHERE user_id = ? LIMIT 1", - (rs, num) -> { - ApplicationStatus status = new ApplicationStatus(); - - status.setConnected(rs.getInt(1) > 0); - status.setCrosspostEnabled(rs.getBoolean(2)); - - return status; - }, - uid); - - return list.isEmpty() ? - new ApplicationStatus() : list.get(0); - } - - @Transactional - @Override - public boolean enableFBCrosspost(Integer uid) { - return getJdbcTemplate().update("UPDATE facebook SET crosspost=1 WHERE user_id=?", uid) > 0 - && getJdbcTemplate().update( - "INSERT INTO subscr_users(user_id,suser_id,jid,active) VALUES (?,5863,'juick@facebook.juick.com',1)", - uid) > 0; - } - - @Transactional - @Override - public void disableFBCrosspost(Integer uid) { - getJdbcTemplate().update("UPDATE facebook SET crosspost=0 WHERE user_id=?", uid); - // TODO: stop using magic numbers for system users - getJdbcTemplate().update("DELETE FROM subscr_users WHERE user_id=? AND suser_id=5863", uid); - } - - @Transactional(readOnly = true) - @Override - public String getTwitterName(final int uid) { - List list = getJdbcTemplate().queryForList( - "SELECT uname FROM twitter WHERE user_id = ?", - String.class, - uid); - - return list.isEmpty() ? - StringUtils.EMPTY : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public String getTelegramName(final int uid) { - List list = getJdbcTemplate().queryForList( - "SELECT tg_name FROM telegram WHERE user_id = ?", - String.class, - uid); - - return list.isEmpty() ? - StringUtils.EMPTY : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public Optional> getVkTokens(final int uid) { - List>> list = getJdbcTemplate().query( - "SELECT vk_id, access_token FROM vk WHERE user_id = ? AND crosspost = 1", - (rs, num) -> Optional.of(Pair.of(rs.getString(1), rs.getString(2))), - uid); - - return list.isEmpty() ? - Optional.empty() : list.get(0); - } - - @Transactional - @Override - public void deleteVKUser(Integer uid) { - getJdbcTemplate().update("DELETE FROM vk WHERE user_id=?", uid); - } - - @Transactional(readOnly = true) - @Override - public int getUIDbyFBID(long fbID) { - try { - return getJdbcTemplate().queryForObject("SELECT user_id FROM facebook WHERE fb_id=? AND user_id IS NOT NULL", - Integer.class, fbID); - } catch (EmptyResultDataAccessException e) { - return 0; - } - } - - @Transactional - @Override - public boolean createFacebookUser(long fbID, String loginhash, String token, String fbName, String fbLink) { - return getJdbcTemplate().update("UPDATE facebook SET fb_id=?, access_token=?, fb_name=?, fb_link=? WHERE loginhash=?", - fbID, token, fbName, fbLink, loginhash) > 0; - } - - @Transactional - @Override - public boolean updateFacebookUser(long fbID, String token, String fbName, String fbLink) { - return getJdbcTemplate().update("UPDATE facebook SET access_token=?,fb_name=?,fb_link=? WHERE fb_id=?", - token, fbName, fbLink, fbID) > 0; - } - - @Transactional(readOnly = true) - @Override - public int getUIDbyVKID(long vkID) { - try { - return getJdbcTemplate().queryForObject("SELECT user_id FROM vk WHERE vk_id=? AND user_id IS NOT NULL", Integer.class, vkID); - } catch (EmptyResultDataAccessException e) { - return 0; - } - } - - @Transactional - @Override - public boolean createVKUser(long vkID, String loginhash, String token, String vkName, String vkLink) { - return getJdbcTemplate().update("INSERT INTO vk(vk_id,loginhash,access_token,vk_name,vk_link) VALUES (?,?,?,?,?)", - vkID, loginhash, token, vkName, vkLink) > 0; - } - - @Transactional(readOnly = true) - @Override - public String getFacebookNameByHash(String hash) { - try { - List> fb = getJdbcTemplate().query("SELECT fb_name,fb_link FROM facebook WHERE loginhash=?", - (rs, num) -> Pair.of(rs.getString(1), rs.getString(2)), hash); - if (fb.size() > 0) { - return "" + fb.get(0).getLeft() + ""; - } - return null; - } catch (EmptyResultDataAccessException e) { - return null; - } - } - - @Transactional - @Override - public String getTelegramNameByHash(String hash) { - try { - String name = getJdbcTemplate().queryForObject("SELECT tg_name FROM telegram WHERE loginhash=?", String.class, hash); - return "" + name + ""; - } catch (EmptyResultDataAccessException e) { - return null; - } - } - - @Transactional - @Override - public boolean setFacebookUser(String hash, int uid) { - return getJdbcTemplate().update("UPDATE facebook SET user_id=?,loginhash=NULL WHERE loginhash=?", uid, hash) > 0; - } - - @Transactional - @Override - public String getVKNameByHash(String hash) { - List> logins = getJdbcTemplate().query("SELECT vk_name,vk_link FROM vk WHERE loginhash=?", - (rs, num) -> Pair.of(rs.getString(1), rs.getString(2)), hash); - if (logins.size() > 0) { - return "" + logins.get(0).getLeft() + ""; - } - return null; - } - - @Transactional - @Override - public boolean setVKUser(String hash, int uid) { - return getJdbcTemplate().update("UPDATE vk SET user_id=?,loginhash=NULL WHERE loginhash=?", uid, hash) > 0; - } - - @Transactional - @Override - public boolean setTelegramUser(String hash, int uid) { - return getJdbcTemplate().update("UPDATE telegram SET user_id=?,loginhash=NULL WHERE loginhash=?", uid, hash) > 0; - } - - @Transactional(readOnly = true) - @Override - public String getJIDByHash(String hash) { - try { - return getJdbcTemplate().queryForObject("SELECT jid FROM jids WHERE loginhash=?", String.class, hash); - } catch (EmptyResultDataAccessException e) { - return null; - } - } - - @Transactional - @Override - public boolean setJIDUser(String hash, int uid) { - return getJdbcTemplate().update("UPDATE jids SET user_id=?,loginhash=NULL WHERE loginhash=?", uid, hash) > 0; - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/EmailServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/EmailServiceImpl.java deleted file mode 100644 index 0cccc915..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/EmailServiceImpl.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import javax.inject.Inject; -import java.util.List; - -/** - * Created by vitalyster on 09.12.2016. - */ -@Repository -@Transactional -public class EmailServiceImpl extends BaseJdbcService implements EmailService { - - @Override - public boolean verifyAddressByCode(Integer userId, String code) { - try { - String address = getJdbcTemplate().queryForObject("SELECT account FROM auth WHERE user_id=? AND protocol='email' AND authcode=?", - String.class, userId, code); - addEmail(userId, address); - getJdbcTemplate().update("DELETE FROM auth WHERE user_id=? AND authcode=?", userId, code); - } catch (EmptyResultDataAccessException e) { - return false; - } - return true; - } - - @Override - public boolean addVerificationCode(Integer userId, String account, String code) { - return getJdbcTemplate().update("INSERT INTO auth(user_id,protocol,account,authcode) VALUES (?,'email',?,?)", - userId, account, code) > 0; - } - - @Override - public boolean addEmail(Integer userId, String email) { - return getJdbcTemplate().update("INSERT INTO emails(user_id,email) VALUES (?,?)", userId, email) > 0; - } - - @Override - public boolean deleteEmail(Integer userId, String account) { - return getNamedParameterJdbcTemplate().update("DELETE FROM emails " + - "WHERE (SELECT COUNT(*) cnt FROM (select user_id, email FROM emails e) c WHERE user_id=:uid) > 1 " + - "AND user_id=:uid AND email=:email", - new MapSqlParameterSource() - .addValue("uid", userId) - .addValue("email", account)) > 0; - } - - @Transactional(readOnly = true) - @Override - public String getNotificationsEmail(Integer userId) { - List list = getJdbcTemplate().queryForList( - "SELECT email FROM emails WHERE user_id=? AND subscr_hour IS NOT NULL", String.class, userId); - return list.isEmpty() ? StringUtils.EMPTY : list.get(0); - } - - @Override - public boolean setNotificationsEmail(Integer userId, String account) { - getJdbcTemplate().update("UPDATE emails SET subscr_hour=NULL WHERE user_id=?", userId); - return StringUtils.isNotEmpty(account) && getJdbcTemplate().update( - "UPDATE emails SET subscr_hour=1 WHERE user_id=? AND email=?", userId, account) > 0; - } - - @Transactional(readOnly = true) - @Override - public List getEmails(Integer userId, boolean active) { - return getJdbcTemplate().queryForList("SELECT email FROM emails WHERE user_id=? " + - (active ? "AND subscr_hour IS NOT NULL" : ""), String.class, userId); - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/MessagesServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/MessagesServiceImpl.java deleted file mode 100644 index 35e48383..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/MessagesServiceImpl.java +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import com.juick.*; -import com.juick.server.helpers.PrivacyOpts; -import com.juick.server.helpers.ResponseReply; -import com.juick.util.MessageUtils; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.dao.IncorrectResultSizeDataAccessException; -import org.springframework.jdbc.core.ConnectionCallback; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.SqlParameterSource; -import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import javax.inject.Inject; -import java.sql.*; -import java.time.Instant; -import java.util.*; -import java.util.Date; -import java.util.stream.Collectors; - -/** - * Created by aalexeev on 11/13/16. - */ -@Repository -public class MessagesServiceImpl extends BaseJdbcService implements MessagesService { - private static final Logger logger = LoggerFactory.getLogger(MessagesServiceImpl.class); - @Inject - private UserService userService; - @Inject - private TagService tagService; - @Inject - private SearchService searchService; - @Inject - private ImagesService imagesService; - @Value("${img_url:https://i.juick.com/}") - private String baseImagesUrl; - - private class MessageMapper implements RowMapper { - @Override - public Message mapRow(ResultSet rs, int rowNum) throws SQLException { - Message msg = new Message(); - msg.setMid(rs.getInt(1)); - msg.setRid(rs.getInt(2)); - msg.setReplyto(rs.getInt(3)); - User user = new User(); - user.setUid(rs.getInt(4)); - user.setName(rs.getString(5)); - user.setBanned(rs.getBoolean(6)); - msg.setUser(user); - msg.setTimestamp(rs.getTimestamp(7).toInstant()); - msg.ReadOnly = rs.getBoolean(8); - msg.setPrivacy(rs.getInt(9)); - msg.FriendsOnly = msg.getPrivacy() < 0; - msg.setReplies(rs.getInt(10)); - msg.setAttachmentType(rs.getString(11)); - msg.setLikes(rs.getInt(12)); - msg.Hidden = rs.getBoolean(13); - String tagsStr = rs.getString(14); - msg.setTags(MessageUtils.parseTags(tagsStr)); - msg.setRepliesBy(rs.getString(15)); - msg.setText(rs.getString(16)); - msg.setReplyQuote(MessageUtils.formatQuote(rs.getString(17))); - msg.setUpdated(rs.getTimestamp(18).toInstant()); - int quoteUid = rs.getInt(19); - if (quoteUid > 0) { - User quoteUser = new User(); - quoteUser.setUid(quoteUid); - quoteUser.setName(rs.getString(20)); - msg.setTo(quoteUser); - } - if (StringUtils.isNotEmpty(msg.getAttachmentType())) { - try { - imagesService.setAttachmentMetadata(baseImagesUrl, msg); - } catch (Exception e) { - logger.warn("exception reading images for mid {} rid {}", msg.getMid(), msg.getRid(), e); - } - } - return msg; - } - } - - - - /** - * @see Java, JDBC and MySQL Types - */ - @Transactional - @Override - public int createMessage(final int uid, final String txt, final String attachment, final Collection tags) { - SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(getJdbcTemplate()).withTableName("messages") - .usingColumns("user_id", "attach", "ts") - .usingGeneratedKeyColumns("message_id"); - Map insertMap = new HashMap<>(); - insertMap.put("user_id", uid); - Instant now = Instant.now(); - insertMap.put("ts", Timestamp.from(now)); - if (attachment != null) { - insertMap.put("attach", attachment); - } - int mid = simpleJdbcInsert.executeAndReturnKey(insertMap).intValue(); - if (mid > 0) { - String tagsNames = StringUtils.EMPTY; - - if (CollectionUtils.isNotEmpty(tags)) { - StringBuilder tasNamesBuilder = new StringBuilder(); - List params = new ArrayList<>(tags.size()); - - boolean next = false; - - for (Tag tag : tags) { - if (next) { - tasNamesBuilder.append(" "); - } else - next = true; - - tasNamesBuilder.append(tag.getName()); - params.add(new Object[]{mid, tag.TID}); - } - tagsNames = tasNamesBuilder.toString(); - - getJdbcTemplate().batchUpdate( - "INSERT INTO messages_tags(message_id, tag_id) VALUES (?, ?)", - params, new int[]{Types.INTEGER, Types.INTEGER}); - } - - getJdbcTemplate().update( - "INSERT INTO messages_txt(message_id, tags, txt) VALUES (?, ?, ?)", - new Object[]{mid, tagsNames, txt}, - new int[]{Types.INTEGER, Types.VARCHAR, Types.VARCHAR}); - getJdbcTemplate().update("UPDATE users SET lastmessage=? where id=?", Timestamp.from(now), uid); - } - - return mid; - } - - /** - * @param mid - * @param rid - * @param user - * @param txt - * @param attachment - * @return - * @see Java, JDBC and MySQL Types - */ - @Transactional - @Override - public int createReply(final int mid, final int rid, final User user, final String txt, final String attachment) { - int ridnew = getReplyIDIncrement(mid); - Date ts = Date.from(Instant.now()); - getJdbcTemplate().update("INSERT INTO replies(message_id, reply_id, user_id, replyto, attach, txt, ts) " + - "VALUES (?, ?, ?, ?, ?, ?, ?)", - mid, ridnew, user.getUid(), rid, attachment, txt, ts); - - if (ridnew > 0) { - getJdbcTemplate().update( - "UPDATE messages SET replies = replies + 1, updated=? WHERE message_id = ?", - ts, mid); - setLastReadComment(user, mid, ridnew); - getJdbcTemplate().update("UPDATE users SET lastmessage=? where id=?", ts, user.getUid()); - } - return ridnew; - } - - @Override - public int getReplyIDIncrement(final int mid) { - return getJdbcTemplate().execute((ConnectionCallback) conn -> { - conn.setAutoCommit(false); - final int replyNo; - try (PreparedStatement ps = conn.prepareStatement("SELECT maxreplyid+1 FROM messages WHERE message_id=? FOR UPDATE")) { - ps.setInt(1, mid); - try (ResultSet resultSet = ps.executeQuery()) { - if (resultSet.next()) { - replyNo = resultSet.getInt(1); - } else { - throw new IncorrectResultSizeDataAccessException("while getting getReplyIDIncrement, mid=" + mid, 1, 0); - } - } - } - try (PreparedStatement ps = conn.prepareStatement("UPDATE messages SET maxreplyid=? WHERE message_id=?")) { - ps.setInt(1, replyNo); - ps.setInt(2, mid); - if (ps.executeUpdate() != 1) { - throw new IncorrectResultSizeDataAccessException("Cannot find a message to update: " + mid, 1, 0); - } - } - conn.commit(); - return replyNo; - }); - - } - - @Transactional - void updateRepliesBy(int mid) { - List users = getJdbcTemplate().queryForList("SELECT users.nick FROM replies " + - "INNER JOIN users ON replies.user_id=users.id WHERE replies.message_id=? " + - "GROUP BY replies.user_id ORDER BY COUNT(replies.reply_id) DESC LIMIT 5", String.class, mid); - String result = users.stream().map(u -> "@" + u).collect(Collectors.joining(",")); - getJdbcTemplate().update("UPDATE messages_txt SET repliesby=? WHERE message_id=?", result, mid); - } - - @Transactional - @Override - public RecommendStatus recommendMessage(final int mid, final int vuid) { - int wasDeleted = getJdbcTemplate() - .update("DELETE FROM favorites WHERE user_id=? AND message_id=? and like_id=?", vuid, mid, Reaction.LIKE); - if (wasDeleted > 0) { - return RecommendStatus.Deleted; - } else { - boolean wasAdded = getJdbcTemplate() - .update("INSERT INTO favorites(user_id, message_id, ts, like_id ) VALUES (?, ?, NOW(), ?)", vuid, mid,Reaction.LIKE) == 1; - if (wasAdded) { - return RecommendStatus.Added; - } - } - return RecommendStatus.Error; - } - - @Override - public List listReactions() { - return jdbcTemplate.query("SELECT like_id, description FROM reactions", (rs, rowNum) -> { - Reaction reaction = new Reaction(rs.getInt("like_id")); - reaction.setDescription(rs.getString("description")); - return reaction; - }); - } - - @Transactional - @Override - public RecommendStatus likeMessage(int mid, int vuid, int reactionId) throws IllegalArgumentException { - boolean wasAdded = getJdbcTemplate() - .update("INSERT INTO favorites(user_id, message_id, ts, like_id ) VALUES (?, ?, NOW(), ?)", vuid, mid, reactionId) == 1; - if (wasAdded) { - return RecommendStatus.Added; - } - - return RecommendStatus.Error; - } - - @Transactional(readOnly = true) - @Override - public boolean canViewThread(final int mid, final int uid) { - List list = getJdbcTemplate().query( - "SELECT user_id, privacy FROM messages WHERE message_id = ?", - (rs, rowNum) -> { - PrivacyOpts res = new PrivacyOpts(); - - res.setUid(rs.getInt(1)); - res.setPrivacy(rs.getInt(2)); - - return res; - }, - mid); - - PrivacyOpts privacyOpts = list.isEmpty() ? null : list.get(0); - - return privacyOpts == null || - privacyOpts.getPrivacy() >= 0 || - uid == privacyOpts.getUid() || - ((privacyOpts.getPrivacy() == -1 || privacyOpts.getPrivacy() == -2) && - uid > 0 && userService.isInWL(privacyOpts.getUid(), uid)); - } - - @Transactional(readOnly = true) - @Override - public boolean isReadOnly(final int mid) { - List list = getJdbcTemplate().queryForList( - "SELECT readonly FROM messages WHERE message_id = ?", - new Object[]{mid}, - Integer.class); - - return !list.isEmpty() && list.get(0) == 1; - } - - @Transactional(readOnly = true) - @Override - public boolean isSubscribed(final int uid, final int mid) { - List list = getJdbcTemplate().queryForList( - "SELECT 1 FROM subscr_messages WHERE suser_id = ? AND message_id = ?", - new Object[]{uid, mid}, - Integer.class); - - return !list.isEmpty() && list.get(0) == 1; - } - - @Transactional(readOnly = true) - @Override - public int getMessagePrivacy(final int mid) { - List list = getJdbcTemplate().queryForList( - "SELECT privacy FROM messages WHERE message_id = ?", - new Object[]{mid}, - Integer.class); - - return list.isEmpty() ? -4 : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public com.juick.Message getMessage(final int mid) { - - List list = getJdbcTemplate().query( - "SELECT messages.message_id as mid, 0 as rid, 0 as replyto, " - + "messages.user_id as uid, users.nick, users.banned as banned, " - + "" - + "messages.ts," - + "messages.readonly, messages.privacy, messages.replies," - + "messages.attach, COUNT(DISTINCT favorites.user_id) as likes, messages.hidden," - + "txt.tags, txt.repliesby, txt.txt, '' as q, messages.updated, 0 as to_uid, " - + "NULL as to_name FROM messages " - + "INNER JOIN users ON messages.user_id = users.id " - + "INNER JOIN messages_txt AS txt " - + "ON messages.message_id = txt.message_id " - + "LEFT JOIN favorites " - + "ON messages.message_id = favorites.message_id AND favorites.like_id=1 " - + "WHERE messages.message_id = ? " - + "GROUP BY mid, rid, replyto, uid, nick, banned, messages.ts, readonly, " - + "privacy, replies, attach, tags, repliesby, q", - new MessageMapper(), - mid); - if (!list.isEmpty()) { - final Message message = list.get(0); - Map> reactionStats = updateReactionsFor(Collections.singletonList(mid)); - message.setReactions(reactionStats.get(message.getMid())); - return message; - } - return null; - } - - @Transactional(readOnly = true) - @Override - public com.juick.Message getReply(final int mid, final int rid) { - List list = getJdbcTemplate().query( - "SELECT replies.user_id, users.nick," - + "replies.replyto, replies.ts," - + "replies.attach, replies.txt, IFNULL(q.txt,t.txt) as quote, " - + "COALESCE(q.user_id, m.user_id) AS to_uid, COALESCE(qu.nick, mu.nick) AS to_name " - + "FROM replies INNER JOIN users ON replies.user_id = users.id " - + "LEFT JOIN replies q ON replies.message_id = q.message_id and replies.replyto = q.reply_id " - + "LEFT JOIN messages_txt t ON replies.message_id = t.message_id " - + "LEFT JOIN messages m ON replies.message_id = m.message_id " - + "LEFT JOIN users qu ON q.user_id=qu.id " - + "LEFT JOIN users mu ON m.user_id=mu.id " - + "WHERE replies.message_id = ? AND replies.reply_id = ?", - (rs, num) -> { - Message msg = new Message(); - - msg.setMid(mid); - msg.setRid(rid); - msg.setUser(new User()); - msg.getUser().setUid(rs.getInt(1)); - msg.getUser().setName(rs.getString(2)); - msg.setReplyto(rs.getInt(3)); - msg.setTimestamp(rs.getTimestamp(4).toInstant()); - msg.setAttachmentType(rs.getString(5)); - msg.setText(rs.getString(6)); - String quote = rs.getString(7); - - if (!StringUtils.isEmpty(quote)) { - msg.setReplyQuote(MessageUtils.formatQuote(quote)); - } - int quoteUid = rs.getInt(8); - if (quoteUid > 0) { - User quoteUser = new User(); - quoteUser.setUid(quoteUid); - quoteUser.setName(rs.getString(9)); - msg.setTo(quoteUser); - } - - return msg; - }, - mid, rid); - - return list.isEmpty() ? null : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public User getMessageAuthor(final int mid) { - List list = getJdbcTemplate().query( - "SELECT messages.user_id, users.nick " - + "FROM messages INNER JOIN users ON messages.user_id = users.id WHERE messages.message_id = ?", - new Object[]{mid}, - (rs, num) -> { - User res = new com.juick.User(); - res.setUid(rs.getInt(1)); - res.setName(rs.getString(2)); - return res; - }); - - return list.isEmpty() ? - null : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public List getMessageRecommendations(final int mid) { - return getJdbcTemplate().queryForList( - "SELECT DISTINCT users.nick FROM favorites INNER JOIN users " + - "ON (favorites.message_id = ? AND favorites.user_id = users.id) WHERE favorites.like_id=1", - new Object[]{mid}, - String.class); - } - - @Transactional(readOnly = true) - @Override - public List getAll(final int visitorUid, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("before", before) - .addValue("visitorUid", visitorUid); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT m.message_id FROM messages m WHERE " + - (before > 0 ? - " m.message_id < :before AND " : StringUtils.EMPTY) + - " m.hidden = 0 AND (m.privacy > 0" + - (visitorUid > 1 ? - " OR m.user_id = :visitorUid) AND NOT EXISTS (" + - " SELECT 1 FROM bl_users b WHERE b.user_id = :visitorUid AND b.bl_user_id = m.user_id)" : - ")") + - " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + - "(SELECT tag_id FROM messages_tags WHERE message_id = m.message_id) and :visitorUid = bt.user_id)" + - " AND NOT EXISTS (SELECT 1 from users u WHERE u.banned = 1 and u.id = m.user_id) ORDER BY m.message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getTag(final int tid, final int visitorUid, final int before, final int cnt) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("tid", tid) - .addValue("cnt", cnt) - .addValue("before", before) - .addValue("visitorUid", visitorUid); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT message_id FROM (tags INNER JOIN messages_tags " + - "ON ((tags.synonym_id = :tid OR tags.tag_id = :tid) AND tags.tag_id = messages_tags.tag_id)) " + - "INNER JOIN messages USING(message_id) WHERE " + - (before > 0 ? - " messages.message_id < :before AND " : StringUtils.EMPTY) + - "(messages.privacy > 0 OR messages.user_id = :visitorUid) ORDER BY message_id DESC LIMIT :cnt", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getTags(final String tids, final int visitorUid, final int before, final int cnt) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("cnt", cnt) - .addValue("before", before) - .addValue("visitorUid", visitorUid); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT messages.message_id FROM messages_tags " + - "INNER JOIN messages USING(message_id) WHERE messages_tags.tag_id IN (" + tids + ") " + - (before > 0 ? - " AND messages.message_id < :before " : StringUtils.EMPTY) + - " AND (messages.privacy > 0 OR messages.user_id = :visitorUid) " + - "ORDER BY messages.message_id DESC LIMIT :cnt", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getPlace(final int placeId, final int visitorUid, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("placeId", placeId) - .addValue("before", before) - .addValue("visitorUid", visitorUid); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT message_id FROM messages WHERE place_id = :placeId " + - (before > 0 ? - " AND message_id < :before " : StringUtils.EMPTY) + - " AND (privacy > 0 OR user_id = :visitorUid) ORDER BY message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getMyFeed(final int uid, final int before, boolean recommended) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("before", before); - - List mids = getNamedParameterJdbcTemplate().queryForList( - "(SELECT message_id FROM messages " + - " INNER JOIN subscr_users ON (subscr_users.suser_id = :uid AND subscr_users.user_id = messages.user_id) " + - " WHERE " + - (before > 0 ? - " message_id < :before AND " : StringUtils.EMPTY) + - " (privacy >= 0 OR (privacy >= -2 AND privacy <= -1" + - " AND EXISTS (SELECT 1 FROM wl_users w WHERE w.wl_user_id = :uid and w.user_id = messages.user_id)))) " + - " UNION " + - " (SELECT message_id FROM messages WHERE user_id=:uid " + - (before > 0 ? - " AND message_id < :before " : StringUtils.EMPTY) + - (recommended ? - ") UNION " + - " (SELECT f.message_id as message_id FROM favorites f WHERE " + - "EXISTS (SELECT 1 FROM subscr_users s WHERE s.suser_id = :uid and f.user_id = s.user_id)" + - (before > 0 ? - " AND f.message_id < :before " : StringUtils.EMPTY) : StringUtils.EMPTY) + - ") ORDER BY message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - - return mids; - } - - @Transactional(readOnly = true) - @Override - public List getPrivate(final int uid, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("before", before); - - return getNamedParameterJdbcTemplate().queryForList - ("SELECT message_id FROM messages WHERE user_id = :uid AND privacy < 0" + - (before > 0 ? - " AND message_id < :before " : StringUtils.EMPTY) + - "ORDER BY message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getDiscussions(final int uid, final Long to) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("to", new Timestamp(to)); - - return getNamedParameterJdbcTemplate().query( - "SELECT messages.message_id, messages.updated FROM subscr_messages " + - "INNER JOIN messages ON messages.message_id=subscr_messages.message_id " + - "WHERE suser_id = :uid " + - (to != 0 ? - "AND updated < :to " : StringUtils.EMPTY) + - "ORDER BY updated DESC, message_id DESC LIMIT 20", - sqlParameterSource, - (rs, rowNum) -> rs.getInt(1)); - } - - @Transactional(readOnly = true) - @Override - public List getRecommended(final int uid, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("before", before); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT f.message_id FROM favorites f WHERE " + - "EXISTS (SELECT 1 FROM subscr_users s WHERE s.suser_id = :uid and f.user_id = s.user_id)" + - (before > 0 ? - " AND f.message_id < :before " : StringUtils.EMPTY) + - "ORDER BY f.message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getPopular(final int visitorUid, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("vid", visitorUid) - .addValue("before", before); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT m.message_id FROM messages m WHERE m.privacy > 0 " + - (before > 0 ? - " AND m.message_id < :before " : StringUtils.EMPTY) + - " AND m.popular > 0 AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :vid and b.bl_user_id = m.user_id) " + - " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + - "(SELECT tag_id FROM messages_tags WHERE message_id = m.message_id) and :vid = bt.user_id)" + - " ORDER BY m.message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getPhotos(final int visitorUid, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("vid", visitorUid) - .addValue("before", before); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT m.message_id FROM messages m WHERE (m.privacy > 0 OR m.user_id = :vid) " + - (before > 0 ? - " AND m.message_id < :before " : StringUtils.EMPTY) + - " AND m.attach IS NOT NULL " + - " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + - "(SELECT tag_id FROM messages_tags WHERE message_id = m.message_id) and :vid = bt.user_id)" + - " AND NOT EXISTS (SELECT 1 from users u WHERE u.banned = 1 and u.id = m.user_id) " + - " AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :vid and b.bl_user_id = m.user_id) " + - " ORDER BY m.message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getSearch(final String search, final int before) { - List mids = searchService.searchInAllMessages(search, before); - - if (!mids.isEmpty()) - return getNamedParameterJdbcTemplate().queryForList( - "SELECT message_id FROM messages WHERE message_id IN (:ids) AND privacy > 0 ORDER BY message_id DESC LIMIT 20", - new MapSqlParameterSource("ids", mids), - Integer.class); - return mids; - } - - @Transactional(readOnly = true) - @Override - public List getUserBlog(final int uid, final int privacy, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("privacy", privacy) - .addValue("before", before); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT message_id FROM messages WHERE user_id = :uid" + - (before > 0 ? - " AND message_id < :before" : StringUtils.EMPTY) + - " AND privacy >= :privacy ORDER BY message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getUserTag(final int uid, final int tid, final int privacy, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("tid", tid) - .addValue("privacy", privacy) - .addValue("before", before); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT messages.message_id FROM messages_tags INNER JOIN messages " + - " USING (message_id) WHERE messages.user_id = :uid AND messages_tags.tag_id = :tid " + - (before > 0 ? - " AND messages.message_id < :before " : StringUtils.EMPTY) + - " AND messages.privacy >= :privacy ORDER BY messages.message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getUserBlogAtDay(final int uid, final int privacy, final int daysback) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("privacy", privacy) - .addValue("daysback", daysback); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT message_id FROM messages WHERE user_id = :uid" + - (daysback > 0 ? - " AND ts >= date(NOW() - INTERVAL :daysback day)" + - " AND ts < date(NOW() - INTERVAL :daysback day + INTERVAL 1 day)" : StringUtils.EMPTY) + - " AND privacy >= :privacy ORDER BY message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getUserBlogWithRecommendations(final int uid, final int privacy, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("privacy", privacy) - .addValue("before", before); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT message_id FROM " + - "(SELECT message_id FROM favorites " + - " WHERE user_id = :uid " + - (before > 0 ? - " AND message_id < :before " : StringUtils.EMPTY) + - " ORDER BY message_id DESC LIMIT 20) as r" + - " UNION ALL " + - "SELECT message_id FROM " + - "(SELECT message_id FROM messages WHERE user_id = :uid" + - (before > 0 ? - " AND message_id < :before" : StringUtils.EMPTY) + - " AND privacy >= :privacy ORDER BY message_id DESC LIMIT 20) as m " + - "ORDER BY message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getUserRecommendations(final int uid, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("before", before); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT message_id FROM favorites " + - " WHERE user_id = :uid " + - (before > 0 ? - " AND message_id < :before " : StringUtils.EMPTY) + - " ORDER BY message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getUserPhotos(final int uid, final int privacy, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("privacy", privacy) - .addValue("before", before); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT message_id FROM messages WHERE user_id = :uid " + - (before > 0 ? - " AND message_id < :before " : StringUtils.EMPTY) + - " AND privacy >= :privacy AND attach IS NOT NULL ORDER BY message_id DESC LIMIT 20", - sqlParameterSource, - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public List getUserSearch(final int UID, final String search, final int privacy, final int before) { - List mids = searchService.searchByStringAndUser(search, UID, before); - - if (!mids.isEmpty()) { - return getNamedParameterJdbcTemplate().queryForList( - "SELECT message_id FROM messages WHERE message_id IN (:ids) AND privacy >= :privacy ORDER BY message_id DESC", - new MapSqlParameterSource("ids", mids) - .addValue("privacy", privacy), - Integer.class); - } - return mids; - } - - @Transactional(readOnly = true) - @Override - public List getMessages(final List mids) { - if (CollectionUtils.isNotEmpty(mids)) { - - List msgs = getNamedParameterJdbcTemplate().query( - "SELECT messages.message_id, 0 as rid, 0 as replyto, " - + "messages.user_id,users.nick, 0 as banned, " - + "messages.ts," - + "messages.readonly,messages.privacy,messages.replies," - + "messages.attach,COUNT(DISTINCT favorites.user_id) AS likes,messages.hidden," - + "messages_txt.tags,messages_txt.repliesby, messages_txt.txt, '' as q, " - + "messages.updated, 0 as to_uid, NULL as to_name " - + "FROM (messages INNER JOIN messages_txt " - + "ON messages.message_id=messages_txt.message_id) " - + "INNER JOIN users ON messages.user_id=users.id " - + "LEFT JOIN favorites " - + "ON messages.message_id = favorites.message_id AND favorites.like_id=1 " - + "WHERE messages.message_id IN (:ids) GROUP BY messages.message_id", - new MapSqlParameterSource("ids", mids), - new MessageMapper()); - - - Map> likes = updateReactionsFor(mids); - - msgs.forEach(i -> i.setReactions(likes.get(i.getMid()))); - - msgs.sort(Comparator.comparing(item -> mids.indexOf(item.getMid()))); - - return msgs; - } - return Collections.emptyList(); - } - - - @Transactional(readOnly = true) - @Override - public Map> updateReactionsFor(final List mids) { - - return getNamedParameterJdbcTemplate().query("select f.message_id as mid, f.like_id as lid," + - " r.description as descr, count(f.like_id) as cnt" + - " from favorites f LEFT JOIN reactions r ON f.like_id = r.like_id " + - " where f.message_id IN (:mids) " + - " group by f.message_id, f.like_id", new MapSqlParameterSource("mids", mids), (ResultSet rs) -> { - Map> results = new HashMap<>(); - - - while (rs.next()) { - int messageId = rs.getInt("mid"); - int likeId = rs.getInt("lid"); - int count = rs.getInt("cnt"); - String description = rs.getString("descr"); - Reaction reaction = new Reaction(likeId); - reaction.setCount(count); - reaction.setDescription(description); - results.computeIfAbsent(messageId, HashSet::new); - results.get(messageId).add(reaction); - } - - return results; - }); - - } - - - @Transactional - @Override - public List getReplies(final User user, final int mid) { - List replies = getNamedParameterJdbcTemplate().query( - "SELECT replies.message_id as mid, replies.reply_id, replies.replyto, " + - "replies.user_id, users.nick, users.banned, " + - "replies.ts, " + - "0 as readonly, 0 as privacy, 0 as replies, " + - "replies.attach, 0 as likes, 0 as hidden, " + - "NULL as tags, NULL as repliesby, replies.txt, " + - "IFNULL(qw.txt, t.txt) as q, " + - "NOW(), " + - "COALESCE(qw.user_id, m.user_id) as to_uid, COALESCE(qu.nick, mu.nick) as to_name " + - "FROM replies INNER JOIN users " + - "ON replies.user_id = users.id " + - "LEFT JOIN replies qw ON replies.message_id = qw.message_id and replies.replyto = qw.reply_id " + - "LEFT JOIN messages_txt t on replies.message_id = t.message_id " + - "LEFT JOIN messages m on replies.message_id = m.message_id " + - "LEFT JOIN users qu ON qw.user_id=qu.id " + - "LEFT JOIN users mu ON m.user_id=mu.id " + - "WHERE replies.message_id = :mid ORDER BY replies.reply_id ASC", - new MapSqlParameterSource("mid", mid), - new MessageMapper()); - if (replies.size() > 0) { - setLastReadComment(user, mid, replies.stream().map(Message::getRid).max(Comparator.naturalOrder()).get()); - } - return replies; - } - - @Transactional - @Override - public boolean setMessagePopular(final int mid, final int popular) { - int ret; - MapSqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("mid", mid) - .addValue("popular", popular); - - switch (popular) { - case -2: - ret = getNamedParameterJdbcTemplate().update( - "UPDATE messages SET hidden = 1 WHERE message_id = :mid", - sqlParameterSource); - break; - case -1: - sqlParameterSource.addValue("popular", 0); - default: - ret = getNamedParameterJdbcTemplate().update( - "UPDATE messages SET popular = :popular WHERE message_id = :mid", - sqlParameterSource); - break; - } - - if (popular == -1) - ret = getNamedParameterJdbcTemplate().update( - "INSERT INTO top_ignore_messages VALUES (:mid)", - sqlParameterSource); - - return ret > 0; - } - - @Transactional - @Override - public boolean setMessagePrivacy(final int mid) { - return getJdbcTemplate().update("UPDATE messages SET privacy=1 WHERE message_id=?", mid) > 0; - } - - @Transactional - @Override - public boolean deleteMessage(final int uid, final int mid) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("mid", mid) - .addValue("uid", uid); - - if (getNamedParameterJdbcTemplate().update( - "DELETE FROM messages WHERE message_id = :mid AND user_id = :uid", sqlParameterSource) > 0) { - - getNamedParameterJdbcTemplate().update("DELETE FROM messages_txt WHERE message_id = :mid", sqlParameterSource); - getNamedParameterJdbcTemplate().update("DELETE FROM replies WHERE message_id = :mid", sqlParameterSource); - getNamedParameterJdbcTemplate().update("DELETE FROM subscr_messages WHERE message_id = :mid", sqlParameterSource); - getNamedParameterJdbcTemplate().update("DELETE FROM messages_tags WHERE message_id = :mid", sqlParameterSource); - - return true; - } - return false; - } - @Transactional - @Override - public boolean deleteReply(final int uid, final int mid, final int rid) { - User author = getMessageAuthor(mid); - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("mid", mid) - .addValue("uid", uid) - .addValue("rid", rid); - boolean result; - if (author.getUid() == uid) { - result = getNamedParameterJdbcTemplate() - .update("DELETE FROM replies WHERE message_id=:mid AND reply_id=:rid", sqlParameterSource) > 0; - } else { - result = getNamedParameterJdbcTemplate() - .update("DELETE FROM replies WHERE message_id=:mid AND reply_id=:rid AND user_id=:uid" - , sqlParameterSource) > 0; - } - if (result) { - getNamedParameterJdbcTemplate().update("UPDATE messages SET replies=replies-1 WHERE message_id=:mid", sqlParameterSource); - updateRepliesBy(mid); - return true; - } - return false; - } - - @Transactional(readOnly = true) - @Override - public List getLastMessages(int hours) { - return getJdbcTemplate().queryForList("SELECT message_id FROM messages WHERE messages.ts>TIMESTAMPADD(HOUR,?,NOW())", - Integer.class, -hours); - - } - - @Transactional(readOnly = true) - @Override - public List getLastReplies(int hours) { - return getJdbcTemplate().query("SELECT users2.nick,replies.message_id,replies.reply_id," + - "users.nick,replies.txt," + - "replies.ts,replies.attach,replies.ts+0 " + - "FROM ((replies INNER JOIN users ON replies.user_id=users.id) " + - "INNER JOIN messages ON replies.message_id=messages.message_id) " + - "INNER JOIN users AS users2 ON messages.user_id=users2.id " + - "WHERE replies.ts>TIMESTAMPADD(HOUR,?,NOW()) AND messages.privacy>0", (rs, rowNum) -> { - ResponseReply reply = new ResponseReply(); - reply.setMuname(rs.getString(1)); - reply.setMid(rs.getInt(2)); - reply.setRid(rs.getInt(3)); - reply.setUname(rs.getString(4)); - reply.setDescription(rs.getString(5)); - reply.setPubDate(rs.getTimestamp(6)); - reply.setAttachmentType(rs.getString(7)); - return reply; - }, -hours); - } - @Transactional(readOnly = true) - @Override - public List getPopularCandidates() { - return getJdbcTemplate().queryForList("SELECT replies.message_id FROM replies " + - "INNER JOIN messages ON replies.message_id = messages.message_id " + - "LEFT JOIN messages_tags ON messages_tags.message_id = messages.message_id " + - "WHERE COALESCE(messages_tags.tag_id, 0) != 2 " + - "AND COALESCE(messages_tags.tag_id, 0) != 805 AND replies.ts > TIMESTAMPADD(HOUR, -2, CURRENT_TIMESTAMP) " + - "AND messages.popular=0 GROUP BY messages.message_id having COUNT(DISTINCT(replies.user_id)) > 5 " + - "UNION ALL SELECT favorites.message_id FROM favorites " + - "INNER JOIN messages ON messages.message_id = favorites.message_id " + - "LEFT JOIN messages_tags ON messages_tags.message_id = messages.message_id " + - "WHERE COALESCE(messages_tags.tag_id, 0) != 2 AND favorites.ts > TIMESTAMPADD(HOUR, -2, CURRENT_TIMESTAMP) " + - "AND messages.popular=0 GROUP BY messages.message_id HAVING COUNT(DISTINCT favorites.user_id) > 1;", Integer.class); - } - @Transactional - @Override - public void setLastReadComment(User user, Integer mid, Integer rid) { - jdbcTemplate.update("UPDATE subscr_messages SET last_read_rid=GREATEST(?, last_read_rid) WHERE message_id=? AND suser_id=?", - rid, mid, user.getUid()); - } - - @Override - public List getUnread(User user) { - return jdbcTemplate.queryForList( - "select subscr_messages.message_id " + - "from subscr_messages inner join messages on subscr_messages.message_id=messages.message_id " + - "where subscr_messages.suser_id=? and " + - "messages.replies>subscr_messages.last_read_rid", - Integer.class, user.getUid()); - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/MessengerServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/MessengerServiceImpl.java deleted file mode 100644 index 57101ffe..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/MessengerServiceImpl.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.juick.service; - -import com.juick.User; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -@Repository -public class MessengerServiceImpl extends BaseJdbcService implements MessengerService { - - @Transactional(readOnly = true) - @Override - public Integer getUserId(String senderId) { - List list = getJdbcTemplate().queryForList( - "SELECT id FROM users INNER JOIN messenger " + - "ON messenger.user_id = users.id WHERE messenger.sender_id=?", Integer.class, senderId); - - return list.isEmpty() ? 0 : list.get(0); - } - @Transactional(readOnly = true) - @Override - public Optional getSenderId(User user) { - List list = getJdbcTemplate().queryForList( - "SELECT sender_id FROM messenger " + - "WHERE user_id=?", String.class, user.getUid()); - - return list.isEmpty() ? Optional.empty() : Optional.of(list.get(0)); - } - - @Transactional - @Override - public boolean createMessengerUser(String senderId, String displayName) { - return getJdbcTemplate().update( - "INSERT INTO messenger(sender_id, display_name, loginhash) VALUES(?,?,?)", - senderId, displayName, UUID.randomUUID().toString()) > 0; - } - @Transactional(readOnly = true) - @Override - public String getDisplayName(String hash) { - try { - return getJdbcTemplate().queryForObject("SELECT display_name FROM messenger WHERE loginhash=?", String.class, hash); - } catch (EmptyResultDataAccessException e) { - return null; - } - } - @Transactional - @Override - public String getSignUpHash(final String senderId, final String username) { - List list = getJdbcTemplate().queryForList( - "SELECT loginhash FROM messenger WHERE sender_id = ? AND user_id IS NULL", - String.class, - senderId); - - if (list.isEmpty()) { - String hash = UUID.randomUUID().toString(); - getJdbcTemplate().update( - "INSERT INTO messenger(sender_id, loginhash, display_name) VALUES (?, ?, ?)", senderId, hash, username); - return hash; - } - return list.get(0); - } - @Transactional - @Override - public boolean linkMessengerUser(String hash, int uid) { - return getJdbcTemplate().update("UPDATE messenger SET user_id=?, loginhash=NULL WHERE loginhash=?", uid, hash) > 0; - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/PMQueriesServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/PMQueriesServiceImpl.java deleted file mode 100644 index b68e0236..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/PMQueriesServiceImpl.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import com.juick.User; -import org.springframework.dao.DuplicateKeyException; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.SqlParameterSource; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -/** - * Created by aalexeev on 11/13/16. - */ -@Repository -public class PMQueriesServiceImpl extends BaseJdbcService implements PMQueriesService { - - @Transactional - @Override - public boolean createPM(final int uidFrom, final int uid_to, final String body) { - boolean ret = getJdbcTemplate().update( - "INSERT INTO pm(user_id, user_id_to, txt) VALUES (?, ?, ?)", - uidFrom, uid_to, body) > 0; - - if (ret) { - try { - getJdbcTemplate().update( - "INSERT INTO pm_streams(user_id, user_id_to, lastmessage, unread) VALUES (?, ?, NOW(), 1)", - uidFrom, uid_to); - } catch (DuplicateKeyException e) { - // ignore - } - } - return ret; - } - - @Transactional - @Override - public boolean addPMinRoster(final int uid, final String jid) { - return getJdbcTemplate().update( - "INSERT INTO pm_inroster(user_id, jid) VALUES (?, ?) ON DUPLICATE KEY UPDATE user_id=user_id", uid, jid) > 0; - } - - @Transactional - @Override - public boolean removePMinRoster(final int uid, final String jid) { - return getJdbcTemplate().update( - "DELETE FROM pm_inroster WHERE user_id = ? AND jid = ?", uid, jid) > 0; - } - - @Transactional - @Override - public boolean havePMinRoster(final int uid, final String jid) { - List res = getJdbcTemplate().queryForList( - "SELECT 1 FROM pm_inroster WHERE user_id = ? AND jid = ?", - Integer.class, - uid, jid); - return res.size() > 0; - } - - @Transactional(readOnly = true) - @Override - public String getLastView(final int uidFrom, final int uidTo) { - List list = getJdbcTemplate().queryForList( - "SELECT lastview FROM pm_streams WHERE user_id = ? AND user_id_to = ?", - String.class, - uidFrom, uidTo); - - return list.isEmpty() ? - null : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public List getPMLastConversationsUsers(final int uid, final int cnt) { - return getJdbcTemplate().query( - "SELECT pm_streams.user_id, users.nick, pm_streams.unread FROM pm_streams " - + "INNER JOIN users ON users.id = pm_streams.user_id " - + "WHERE pm_streams.user_id_to=? " - + "ORDER BY pm_streams.unread DESC, pm_streams.lastmessage DESC LIMIT ?", - (rs, rowNum) -> { - com.juick.User u = new com.juick.User(); - u.setUid(rs.getInt(1)); - u.setName(rs.getString(2)); - u.setUnreadCount(rs.getInt(3)); - return u; - }, - uid, cnt); - } - - @Transactional - @Override - public List getPMMessages(final int uid, final int uidTo) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("uidTo", uidTo); - - List msgs = getNamedParameterJdbcTemplate().query( - "SELECT pm.user_id, pm.txt, pm.ts, users.nick FROM pm INNER JOIN users ON users.id=pm.user_id WHERE (user_id = :uid AND user_id_to = :uidTo) " - + "OR (user_id_to = :uid AND user_id = :uidTo) ORDER BY ts DESC LIMIT 20", - sqlParameterSource, - (rs, rowNum) -> { - com.juick.Message msg = new com.juick.Message(); - int uuid = rs.getInt(1); - User user = new User(); - user.setUid(uuid); - user.setName(rs.getString(4)); - msg.setUser(user); - msg.setText(rs.getString(2)); - msg.setTimestamp(rs.getTimestamp(3).toInstant()); - return msg; - }); - - getNamedParameterJdbcTemplate().update( - "UPDATE pm_streams SET lastview = NOW(), unread = 0 WHERE user_id_to = :uid AND user_id = :uidTo", - sqlParameterSource); - - return msgs; - } - - @Transactional(readOnly = true) - @Override - public List getLastPMInbox(final int uid) { - return getJdbcTemplate().query( - "SELECT pm.user_id, users.nick, pm.txt, pm.ts " + - "FROM pm INNER JOIN users ON pm.user_id=users.id WHERE pm.user_id_to=? ORDER BY pm.ts DESC LIMIT 20", - (rs, num) -> { - com.juick.Message msg = new com.juick.Message(); - msg.setUser(new User()); - msg.getUser().setUid(rs.getInt(1)); - msg.getUser().setName(rs.getString(2)); - msg.setText(rs.getString(3)); - msg.setTimestamp(rs.getTimestamp(4).toInstant()); - return msg; - }, - uid); - } - - @Transactional(readOnly = true) - @Override - public List getLastPMSent(final int uid) { - return getJdbcTemplate().query( - "SELECT pm.user_id_to, users.nick, pm.txt, " + - "pm.ts FROM pm INNER JOIN users ON pm.user_id_to=users.id " + - "WHERE pm.user_id=? ORDER BY pm.ts DESC LIMIT 20", - (rs, num) -> { - com.juick.Message msg = new com.juick.Message(); - msg.setUser(new User()); - msg.getUser().setUid(rs.getInt(1)); - msg.getUser().setName(rs.getString(2)); - msg.setText(rs.getString(3)); - msg.setTimestamp(rs.getTimestamp(4).toInstant()); - return msg; - }, - uid); - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/PrivacyQueriesServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/PrivacyQueriesServiceImpl.java deleted file mode 100644 index 9f9cda1d..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/PrivacyQueriesServiceImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import com.juick.Tag; -import com.juick.User; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -/** - * Created by aalexeev on 11/13/16. - */ -@Repository -@Transactional -public class PrivacyQueriesServiceImpl extends BaseJdbcService implements PrivacyQueriesService { - - @Override - public PrivacyResult blacklistUser(final User user, final User target) { - int result = getJdbcTemplate().update( - "DELETE FROM bl_users WHERE user_id = ? AND bl_user_id = ?", - user.getUid(), target.getUid()); - - if (result > 0) - return PrivacyResult.Removed; - - getJdbcTemplate().update( - "INSERT INTO bl_users(user_id, bl_user_id) VALUES (?, ?)", - user.getUid(), target.getUid()); - - return PrivacyResult.Added; - } - - @Override - public PrivacyResult blacklistTag(final User user, final Tag tag) { - int result = getJdbcTemplate().update( - "DELETE FROM bl_tags WHERE user_id = ? AND tag_id = ?", - user.getUid(), tag.TID); - - if (result > 0) - return PrivacyResult.Removed; - - getJdbcTemplate().update( - "INSERT INTO bl_tags(user_id, tag_id) VALUES (?, ?)", - user.getUid(), tag.TID); - - return PrivacyResult.Added; - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/PushQueriesServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/PushQueriesServiceImpl.java deleted file mode 100644 index 7f97956c..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/PushQueriesServiceImpl.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import org.apache.commons.collections4.CollectionUtils; -import org.springframework.dao.DuplicateKeyException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import javax.inject.Inject; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Created by aalexeev on 11/13/16. - */ -@Repository -public class PushQueriesServiceImpl extends BaseJdbcService implements PushQueriesService { - - @Transactional(readOnly = true) - @Override - public List getGCMRegID(final int uid) { - return getJdbcTemplate().queryForList( - "SELECT regid FROM android WHERE user_id=?", - String.class, - uid); - } - - @Transactional(readOnly = true) - @Override - public List getGCMTokens(final Collection uids) { - if (CollectionUtils.isEmpty(uids)) - return Collections.emptyList(); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT regid FROM android INNER JOIN users ON (users.id = android.user_id) WHERE users.id IN (:ids)", - new MapSqlParameterSource("ids", uids), - String.class); - } - - @Transactional - @Override - public boolean addGCMToken(Integer uid, String token) { - return getJdbcTemplate().update("INSERT IGNORE INTO android(user_id,regid) VALUES (?, ?)", - uid, token) > 0; - } - - @Transactional - @Override - public boolean deleteGCMToken(String token) { - return getJdbcTemplate().update("DELETE FROM android WHERE regid=?", token) > 0; - } - - @Transactional(readOnly = true) - @Override - public List getMPNSURL(final int uid) { - return getJdbcTemplate().queryForList( - "SELECT url FROM winphone WHERE user_id=?", - String.class, - uid); - } - - @Transactional(readOnly = true) - @Override - public List getMPNSTokens(final Collection uids) { - if (CollectionUtils.isEmpty(uids)) - return Collections.emptyList(); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT url FROM winphone INNER JOIN users ON (users.id=winphone.user_id) WHERE users.id IN (:ids)", - new MapSqlParameterSource("ids", uids), - String.class); - } - - @Transactional - @Override - public boolean addMPNSToken(Integer uid, String token) { - return getJdbcTemplate().update("INSERT IGNORE INTO winphone(user_id,url) VALUES (?, ?)", - uid, token) > 0; - } - - @Transactional - @Override - public boolean deleteMPNSToken(String token) { - return getJdbcTemplate().update("DELETE FROM winphone WHERE url=?", token) > 0; - } - - @Transactional(readOnly = true) - @Override - public List getAPNSToken(final int uid) { - return getJdbcTemplate().queryForList( - "SELECT token from ios WHERE user_id=?", - String.class, - uid); - } - - @Transactional - @Override - public boolean deleteAPNSToken(String token) { - return getJdbcTemplate().update("DELETE FROM ios WHERE token=?", token) > 0; - } - - @Transactional(readOnly = true) - @Override - public List getAPNSTokens(final Collection uids) { - if (CollectionUtils.isEmpty(uids)) - return Collections.emptyList(); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT token FROM ios INNER JOIN users ON (users.id = ios.user_id) WHERE users.id IN (:ids)", - new MapSqlParameterSource("ids", uids), - String.class); - } - - @Transactional - @Override - public boolean addAPNSToken(Integer uid, String token) { - try { - return getJdbcTemplate().update("INSERT INTO ios(user_id,token) VALUES (?, ?)", - uid, token) > 0; - } catch (DuplicateKeyException e) { - return true; - } - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/ShowQueriesServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/ShowQueriesServiceImpl.java deleted file mode 100644 index 0fba35f1..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/ShowQueriesServiceImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import com.juick.User; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collections; -import java.util.List; - -/** - * Created by aalexeev on 11/13/16. - */ -@Repository -@Transactional(readOnly = true) -public class ShowQueriesServiceImpl extends BaseJdbcService implements ShowQueriesService { - - @Override - public List getRecommendedUsers(final User forUser) { - if (forUser == null) - return Collections.emptyList(); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT u.nick FROM subscr_users su1 INNER JOIN users u " + - "ON su1.user_id = u.id " + - "WHERE NOT EXISTS (SELECT 1 FROM subscr_users su2 WHERE su2.suser_id = :uid and su1.user_id = su2.user_id) " + - "AND EXISTS (SELECT 1 FROM subscr_users su3 WHERE su3.suser_id = :uid and su3.user_id = su1.suser_id ) " + - "AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :uid and su1.user_id = b.bl_user_id) " + - "AND su1.user_id != :uid AND u.lastmessage > UNIX_TIMESTAMP() - 259200 " + - "GROUP BY su1.user_id ORDER BY count(*) DESC LIMIT 10", - new MapSqlParameterSource("uid", forUser.getUid()), - String.class); - } - - @Override - public List getTopUsers() { - return getJdbcTemplate().query( - "SELECT users.nick,COUNT(subscr_users.suser_id) AS cnt " + - "FROM (subscr_users INNER JOIN users ON subscr_users.user_id=users.id) " + - "INNER JOIN useroptions ON users.id=useroptions.user_id " + - "WHERE useroptions.privacy_view>0 AND users.lastmessage > UNIX_TIMESTAMP() - 259200 " + - "AND users.id!=2 GROUP BY subscr_users.user_id ORDER BY cnt DESC LIMIT 10", - (rs, rowNum) -> rs.getString(1)); - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/SphinxSearchService.java b/juick-server-jdbc/src/main/java/com/juick/service/SphinxSearchService.java deleted file mode 100644 index f102ab47..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/SphinxSearchService.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Created by aalexeev on 11/18/16. - */ - -@Repository -@Transactional(readOnly = true) -public class SphinxSearchService extends BaseJdbcService implements SearchService { - private static final int DEFAULT_MAX_RESULT = 20; - - private int maxResult = DEFAULT_MAX_RESULT; - - @Override - public List searchInAllMessages(final String searchString, final int messageIdBefore) { - if (StringUtils.isBlank(searchString)) - return Collections.emptyList(); - - Map sphinxQuery = new HashMap<>(); - sphinxQuery.put("limit", String.valueOf(maxResult)); - sphinxQuery.put("mode", "any"); - sphinxQuery.put("sort", "extended:@id desc"); - if (messageIdBefore > 0) { - sphinxQuery.put("maxid", String.valueOf(messageIdBefore - 1)); - } - - return getJdbcTemplate().queryForList( - String.format("SELECT id FROM search WHERE query = '%s;%s'", searchString, - sphinxQuery.entrySet().stream().map(Object::toString) - .collect(Collectors.joining(";"))), Integer.class); - } - - @Override - public List searchByStringAndUser(final String searchString, final int userId, int messageIdBefore) { - if (StringUtils.isBlank(searchString)) - return Collections.emptyList(); - - Map sphinxQuery = new HashMap<>(); - sphinxQuery.put("limit", String.valueOf(maxResult)); - sphinxQuery.put("mode", "any"); - sphinxQuery.put("sort", "extended:@id desc"); - if (messageIdBefore > 0) { - sphinxQuery.put("maxid", String.valueOf(messageIdBefore - 1)); - } - return getJdbcTemplate().queryForList( - String.format("SELECT id FROM search WHERE query = '%s;%s;filter=user_id,%d'", searchString, - sphinxQuery.entrySet().stream().map(Object::toString) - .collect(Collectors.joining(";")), userId), Integer.class); - } - - @Override - public void setMaxResult(int maxResult) { - if (maxResult <= 0) - throw new IllegalArgumentException("maxResult value (" + maxResult + ") must be greater then 0"); - - this.maxResult = maxResult; - } -} \ No newline at end of file diff --git a/juick-server-jdbc/src/main/java/com/juick/service/SubscriptionServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/SubscriptionServiceImpl.java deleted file mode 100644 index b97fc0a4..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/SubscriptionServiceImpl.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import com.juick.Message; -import com.juick.Tag; -import com.juick.User; -import com.juick.server.helpers.NotifyOpts; -import org.apache.commons.lang3.StringUtils; -import org.springframework.dao.DuplicateKeyException; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.Assert; - -import javax.annotation.Nonnull; -import javax.inject.Inject; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Created by aalexeev on 11/13/16. - */ -@Repository -public class SubscriptionServiceImpl extends BaseJdbcService implements SubscriptionService { - @Inject - private UserService userService; - @Inject - private MessagesService messagesService; - @Inject - private TagService tagService; - - @Transactional(readOnly = true) - @Override - public List getJIDSubscribedToUser(final int uid, final boolean friendsonly) { - return getNamedParameterJdbcTemplate().queryForList( - "SELECT jids.jid FROM subscr_users INNER JOIN jids " + - "ON (subscr_users.user_id = :uid AND subscr_users.suser_id = jids.user_id) WHERE jids.active = 1 " + - (friendsonly ? - " AND EXISTS (SELECT 1 FROM wl_users w WHERE w.user_id = :uid and jids.user_id = w.wl_user_id)" : StringUtils.EMPTY), - new MapSqlParameterSource("uid", uid), - String.class); - } - - @Transactional(readOnly = true) - @Override - public List getSubscribedUsers(final int uid, final int mid) { - User author = messagesService.getMessageAuthor(mid); - - List userids = userService.getUserReaders(uid); - List tags = tagService.getMessageTagsIDs(mid); - List tagsStr = tagService.getMessageTags(mid).stream().map(t -> t.getTag().getName()).collect(Collectors.toList()); - - Set set = new HashSet<>(); - set.addAll( - userids.stream() - .map(User::getUid).filter(u -> Collections.disjoint(tagService.getUserBLTags(u), tagsStr)) - .collect(Collectors.toList())); - - - if (!tags.isEmpty()) { - List tagUsers = getNamedParameterJdbcTemplate().queryForList( - "SELECT st.suser_id FROM subscr_tags st " + - "WHERE st.tag_id IN (:ids) AND st.suser_id != :uid " + - " AND NOT EXISTS (SELECT 1 FROM bl_users bu WHERE bu.bl_user_id = :authorUid and st.suser_id = bu.user_id)" + - " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN (:ids) and st.suser_id = bt.user_id)", - new MapSqlParameterSource() - .addValue("ids", tags) - .addValue("uid", uid) - .addValue("authorUid", author.getUid()), - Integer.class); - set.addAll(tagUsers); - } - return userService.getUsersByID(set); - } - @Override - public List getUsersSubscribedToComments(@Nonnull final Message msg, @Nonnull final Message reply) { - return getUsersSubscribedToComments(msg, reply, false); - } - - @Transactional(readOnly = true) - @Override - public List getUsersSubscribedToComments(@Nonnull final Message msg, @Nonnull final Message reply, - boolean blacklisted) { - List userids = getJdbcTemplate().queryForList( - "SELECT suser_id FROM subscr_messages WHERE message_id=? AND suser_id!=?", - Integer.class, - msg.getMid(), reply.getUser().getUid()); - - if (!userids.isEmpty()) { - return userService.getUsersByID(userids.stream() - .filter(u -> blacklisted || !userService.isInBLAny(u, reply.getUser().getUid())) - .collect(Collectors.toList())); - } - return Collections.emptyList(); - } - - @Transactional(readOnly = true) - @Override - public List getUsersSubscribedToUserRecommendations(final int uid, final int mid, final int muid) { - List tags = tagService.getMessageTagsIDs(mid); - - String query = "SELECT s.suser_id FROM subscr_users s WHERE s.user_id = :uid " + - " AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.bl_user_id = :muid and b.user_id = s.user_id) " + - " AND NOT EXISTS (SELECT 1 FROM subscr_users s1 WHERE s1.user_id = :muid AND s.user_id = s1.suser_id) " + - " AND NOT EXISTS (SELECT 1 FROM subscr_messages sm WHERE sm.message_id = :mid AND s.user_id = sm.suser_id) " + - " AND NOT EXISTS (SELECT 1 FROM favorites WHERE favorites.message_id = :mid AND favorites.user_id = s.user_id) " + - " AND s.user_id NOT IN (SELECT s2.suser_id FROM subscr_users s2 " + - " INNER JOIN favorites f ON (f.message_id = :mid AND s2.user_id = f.user_id AND f.user_id != :uid))"; - - MapSqlParameterSource sqlParameterSource = new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("muid", muid) - .addValue("mid", mid); - - if (!tags.isEmpty()) { - sqlParameterSource.addValue("ids", tags); - query += " AND NOT EXISTS (SELECT 1 FROM subscr_tags st WHERE st.tag_id IN (:ids) AND s.user_id = st.suser_id) " + - " AND NOT EXISTS (SELECT 1 FROM bl_tags b WHERE b.tag_id IN (:ids) AND s.user_id = b.user_id)"; - } - - List userids = getNamedParameterJdbcTemplate().queryForList( - query, sqlParameterSource, Integer.class); - - return userService.getUsersByID(userids); - } - - @Transactional - @Override - public boolean subscribeMessage(final Message message, final User user) { - try { - boolean result = getJdbcTemplate().update( - "INSERT INTO subscr_messages(suser_id, message_id) VALUES (?, ?)", user.getUid(), message.getMid()) == 1; - messagesService.setLastReadComment(user, message.getMid(), message.getReplies()); - return result; - } catch (DuplicateKeyException e) { - return true; - } - } - - @Transactional - @Override - public boolean unSubscribeMessage(final int mid, final int vuid) { - return getJdbcTemplate().update( - "DELETE FROM subscr_messages WHERE message_id=? AND suser_id=?", mid, vuid) > 0; - } - - @Transactional - @Override - public boolean subscribeUser(final User user, final User toUser) { - try { - return getJdbcTemplate().update( - "INSERT INTO subscr_users(user_id,suser_id) VALUES (?,?)", toUser.getUid(), user.getUid()) == 1; - } catch (DuplicateKeyException e) { - return true; - } - } - - @Transactional - @Override - public boolean unSubscribeUser(final User user, final User fromUser) { - return getJdbcTemplate().update( - "DELETE FROM subscr_users WHERE suser_id=? AND user_id=?", user.getUid(), fromUser.getUid()) > 0; - } - - @Transactional - @Override - public boolean subscribeTag(final User user, final Tag toTag) { - try { - - return getJdbcTemplate().update( - "INSERT INTO subscr_tags(tag_id,suser_id) VALUES (?,?)", toTag.TID, user.getUid()) == 1; - } catch (DuplicateKeyException e) { - return true; - } - } - - @Transactional - @Override - public boolean unSubscribeTag(final User user, final Tag toTag) { - return getJdbcTemplate().update( - "DELETE FROM subscr_tags WHERE tag_id=? AND suser_id=?", toTag.TID, user.getUid()) > 0; - } - - @Transactional(readOnly = true) - @Override - public List getSubscribedTags(User user) { - return getJdbcTemplate().queryForList("SELECT tags.name FROM subscr_tags INNER JOIN tags " + - "ON(tags.tag_id = subscr_tags.tag_id) " + - "WHERE subscr_tags.suser_id=? ORDER BY tags.name", String.class, user.getUid()); - } - - @Transactional(readOnly = true) - @Override - public NotifyOpts getNotifyOptions(final User user) { - List list = getJdbcTemplate().query( - "SELECT jnotify,subscr_notify,recommendations FROM useroptions WHERE user_id=?", - (rs, num) -> { - NotifyOpts options = new NotifyOpts(); - options.setRepliesEnabled(rs.getInt(1) > 0); - options.setSubscriptionsEnabled(rs.getInt(2) > 0); - options.setRecommendationsEnabled(rs.getInt(3) > 0); - return options; - }, - user.getUid()); - - return list.isEmpty() ? - new NotifyOpts() : list.get(0); - } - - @Transactional - @Override - public boolean setNotifyOptions(final User user, final NotifyOpts options) { - int jnotify = getJdbcTemplate().update( - "UPDATE useroptions SET jnotify=? WHERE user_id=?", - options.isRepliesEnabled() ? 1 : 0, - user.getUid()); - - int subscr_notify = getJdbcTemplate().update( - "UPDATE useroptions SET subscr_notify=? WHERE user_id=?", - options.isSubscriptionsEnabled() ? 1 : 0, - user.getUid()); - - int recommendations = getJdbcTemplate().update( - "UPDATE useroptions SET recommendations=? WHERE user_id=?", - options.isRecommendationsEnabled() ? 1 : 0, - user.getUid()); - - return jnotify > 0 && subscr_notify > 0 && recommendations > 0; - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/TagServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/TagServiceImpl.java deleted file mode 100644 index 524ad32d..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/TagServiceImpl.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import com.juick.Tag; -import com.juick.User; -import com.juick.server.helpers.TagStats; -import com.juick.util.StreamUtils; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -/** - * Created by aalexeev on 11/13/16. - */ -@Repository -public class TagServiceImpl extends BaseJdbcService implements TagService { - - @Transactional(readOnly = true) - @Override - public com.juick.Tag getTag(final int tid) { - List list = getJdbcTemplate().query( - "SELECT synonym_id,name FROM tags WHERE tag_id=?", - (rs, num) -> { - Tag ret = new Tag(rs.getString(2)); - ret.TID = tid; - ret.SynonymID = rs.getInt(1); - return ret; - }, - tid); - - return list.isEmpty() ? - null : list.get(0); - } - - @Transactional - @Override - public com.juick.Tag getTag(final String tag, final boolean autoCreate) { - if (StringUtils.isBlank(tag)) - return null; - - List list = getJdbcTemplate().query( - "SELECT tag_id, synonym_id, name FROM tags WHERE name = ?", - (rs, rowNum) -> { - Tag ret1 = new Tag(rs.getString(3)); - ret1.TID = rs.getInt(1); - ret1.SynonymID = rs.getInt(2); - return ret1; - }, - tag); - - Tag ret = list.isEmpty() ? - null : list.get(0); - - if (ret == null && autoCreate) { - ret = new com.juick.Tag(tag); - ret.TID = createTag(tag); - } - - return ret; - } - - @Override - public List getTags(Stream tags, final boolean autoCreate) { - return tags.filter(StringUtils::isNotBlank).map(tag -> getTag(tag, autoCreate)).filter(Objects::nonNull).distinct() - .collect(Collectors.toList()); - } - - @Transactional(readOnly = true) - @Override - public boolean getTagNoIndex(final int tagId) { - List list = getJdbcTemplate().queryForList( - "SELECT noindex FROM tags WHERE tag_id=?", Integer.class, tagId); - - return !list.isEmpty() && list.get(0) == 1; - } - - @Transactional - @Override - public int createTag(final String name) { - KeyHolder holder = new GeneratedKeyHolder(); - getJdbcTemplate().update( - con -> { - PreparedStatement stmt = con.prepareStatement( - "INSERT INTO tags(name) VALUES (?)", - Statement.RETURN_GENERATED_KEYS); - stmt.setString(1, name); - return stmt; - }, - holder); - - return holder.getKey().intValue(); - } - - private class TagStatsMapper implements RowMapper { - - @Override - public TagStats mapRow(ResultSet rs, int rowNum) throws SQLException { - Tag t = new Tag(rs.getString(1)); - TagStats s = new TagStats(); - s.setTag(t); - s.setUsageCount(rs.getInt(2)); - return s; - } - } - - @Transactional(readOnly = true) - @Override - public List getUserTagStats(final int uid) { - return getJdbcTemplate().query( - "SELECT tags.name,COUNT(messages.message_id) " + - "FROM (messages INNER JOIN messages_tags ON (messages.user_id=? " + - "AND messages.message_id=messages_tags.message_id)) " + - "INNER JOIN tags ON messages_tags.tag_id=tags.tag_id GROUP BY tags.tag_id ORDER BY tags.name ASC", - new TagStatsMapper(), - uid); - } - - @Transactional(readOnly = true) - @Override - public List getUserBLTags(final int uid) { - return getJdbcTemplate().queryForList( - "SELECT tags.name FROM tags INNER JOIN bl_tags " + - "ON (bl_tags.user_id = ? AND bl_tags.tag_id = tags.tag_id) ORDER BY tags.name", - String.class, uid); - } - - @Transactional(readOnly = true) - @Override - public List getPopularTags() { - return getJdbcTemplate().queryForList( - "select name from tags where noindex=0 order by stat_messages desc limit 20", String.class); - } - - @Transactional(readOnly = true) - @Override - public List getTagStats() { - return getJdbcTemplate().query( - "SELECT tags.name,COUNT(DISTINCT messages.user_id) AS cnt " + - "FROM (messages INNER JOIN messages_tags ON (messages.ts>TIMESTAMPADD(DAY,-3,NOW()) " + - "AND messages.message_id=messages_tags.message_id)) " + - "INNER JOIN tags ON messages_tags.tag_id=tags.tag_id " + - "WHERE tags.tag_id NOT IN (SELECT tag_id FROM tags_ignore) " + - "GROUP BY tags.tag_id ORDER BY cnt DESC LIMIT 20", new TagStatsMapper()); - } - - @Transactional - @Override - public List updateTags(final int mid, final Collection newTags) { - List currentTags = getMessageTags(mid).stream() - .map(TagStats::getTag).collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(newTags)) - return currentTags; - - List idsForDelete = newTags.stream() - .filter(currentTags::contains) - .map(tag -> tag.TID) - .collect(Collectors.toList()); - if (newTags.size() - idsForDelete.size() >= 5) { - return currentTags; - } - - if (!idsForDelete.isEmpty()) - getNamedParameterJdbcTemplate().update( - "DELETE FROM messages_tags WHERE message_id = :mid AND tag_id in (:ids)", - new MapSqlParameterSource().addValue("ids", idsForDelete).addValue("mid", mid)); - - newTags.stream().filter(t -> !currentTags.contains(t)) - .forEach(t -> getJdbcTemplate().update("INSERT INTO messages_tags(message_id,tag_id) VALUES (?,?)", mid, t.TID)); - - List result = getMessageTags(mid).stream() - .map(TagStats::getTag).collect(Collectors.toList()); - jdbcTemplate.update("UPDATE messages_txt SET tags=? WHERE message_id=?", result.stream() - .map(Tag::getName).collect(Collectors.joining(" ")), mid); - return result; - } - - @Override - public List fromString(final String txt) { - String firstLine = txt.split("\\n", 2)[0]; - return StreamUtils.takeWhile(Arrays.stream(firstLine.split("\\ ")), - t -> !t.equals("*") && t.startsWith("*")) - .map(t -> getTag(t.substring(1), true)) - .collect(Collectors.toList()); - } - - @Transactional(readOnly = true) - @Override - public List getMessageTags(final int mid) { - return getJdbcTemplate().query( - "SELECT tags.tag_id,synonym_id,name,stat_messages FROM tags " + - "INNER JOIN messages_tags ON (messages_tags.message_id = ? AND messages_tags.tag_id = tags.tag_id)", - (rs, num) -> { - com.juick.Tag t = new com.juick.Tag(rs.getString(3)); - t.TID = rs.getInt(1); - t.SynonymID = rs.getInt(2); - TagStats s = new TagStats(); - s.setTag(t); - s.setUsageCount(rs.getInt(4)); - return s; - }, mid); - } - - @Transactional(readOnly = true) - @Override - public List getMessageTagsIDs(final int mid) { - return getJdbcTemplate().queryForList( - "SELECT tag_id FROM messages_tags WHERE message_id = ?", - Integer.class, mid); - } - - @Override - public boolean blacklistTag(User user, Tag tag) { - int rowcount = getNamedParameterJdbcTemplate().update("DELETE FROM bl_tags WHERE tag_id = :tid AND user_id = :uid", - new MapSqlParameterSource().addValue("tid", tag.TID).addValue("uid", user.getUid())); - return rowcount <= 0 && getNamedParameterJdbcTemplate() - .update("INSERT INTO bl_tags(user_id, tag_id) VALUES(:uid,:tid)", - new MapSqlParameterSource().addValue("tid", tag.TID) - .addValue("uid", user.getUid())) > 0; - } - - @Transactional(readOnly = true) - @Override - public boolean isInBL(User user, Tag tag) { - List list = getJdbcTemplate().queryForList( - "SELECT 1 FROM bl_tags WHERE user_id = ? AND tag_id = ?", - Integer.class, user.getUid(), tag.TID); - return !list.isEmpty() && list.get(0) == 1; - } - - @Transactional(readOnly = true) - @Override - public boolean isSubscribed(User user, Tag tag) { - List list = getJdbcTemplate().queryForList( - "SELECT 1 FROM subscr_tags WHERE suser_id = ? AND tag_id = ?", - Integer.class, user.getUid(), tag.TID); - return !list.isEmpty() && list.get(0) == 1; - } - -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/TelegramServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/TelegramServiceImpl.java deleted file mode 100644 index 4e37bfac..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/TelegramServiceImpl.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import com.juick.User; -import org.springframework.dao.DuplicateKeyException; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collections; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; - -/** - * Created by vt on 24/11/2016. - */ -@Repository -public class TelegramServiceImpl extends BaseJdbcService implements TelegramService { - - @Transactional - @Override - public boolean addChat(final Long id) { - try { - return getJdbcTemplate().update("INSERT INTO telegram_chats(chat_id) VALUES(?)", id) > 0; - } catch (DuplicateKeyException e) { - return true; - } - } - - @Transactional - @Override - public boolean deleteChat(Long id) { - return getJdbcTemplate().update("DELETE FROM telegram_chats WHERE chat_id=?", id) > 0; - } - - @Transactional(readOnly = true) - @Override - public List getChats() { - return getJdbcTemplate().queryForList("SELECT chat_id FROM telegram_chats", Long.class); - } - - @Transactional(readOnly = true) - @Override - public int getUser(final long tgId) { - List list = getJdbcTemplate().queryForList( - "SELECT id FROM users INNER JOIN telegram " + - "ON telegram.user_id = users.id WHERE telegram.tg_id=?", Integer.class, tgId); - - return list.isEmpty() ? 0 : list.get(0); - } - - @Transactional - @Override - public boolean createTelegramUser(final long tgID, final String tgName) { - return getJdbcTemplate().update( - "INSERT INTO telegram(tg_id, tg_name, loginhash) VALUES(?,?,?)", - tgID, tgName, UUID.randomUUID().toString()) > 0; - } - - @Transactional - @Override - public boolean deleteTelegramUser(Integer uid) { - return getJdbcTemplate().update("DELETE FROM telegram WHERE user_id=?", uid) > 0; - } - - @Transactional(readOnly = true) - @Override - public List getTelegramIdentifiers(List users) { - List uids = users.stream().map(User::getUid).collect(Collectors.toList()); - if (uids.isEmpty()) { - return Collections.emptyList(); - } - return getNamedParameterJdbcTemplate().queryForList("" + - "SELECT tg_id FROM telegram WHERE user_id IN(:uids)", new MapSqlParameterSource() - .addValue("uids", uids), Long.class); - } -} diff --git a/juick-server-jdbc/src/main/java/com/juick/service/UserServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/UserServiceImpl.java deleted file mode 100644 index a0a07fb3..00000000 --- a/juick-server-jdbc/src/main/java/com/juick/service/UserServiceImpl.java +++ /dev/null @@ -1,689 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service; - -import com.juick.User; -import com.juick.server.helpers.AnonymousUser; -import com.juick.server.helpers.Auth; -import com.juick.server.helpers.UserInfo; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.dao.DuplicateKeyException; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.*; - -/** - * Created by aalexeev on 11/13/16. - */ -@Repository -public class UserServiceImpl extends BaseJdbcService implements UserService { - - private class UserMapper implements RowMapper { - @Override - public User mapRow(ResultSet rs, int rowNum) throws SQLException { - User user = new User(); - - user.setUid(rs.getInt(1)); - user.setName(rs.getString(2)); - user.setBanned(rs.getBoolean(3)); - user.setLang(rs.getString(4)); - - return user; - } - } - - @Transactional - @Override - public String getSignUpHashByJID(final String jid) { - List list = getJdbcTemplate().queryForList( - "SELECT loginhash FROM jids WHERE jid = ? AND user_id IS NULL", String.class, jid); - - if (list.isEmpty()) { - String hash = UUID.randomUUID().toString(); - getJdbcTemplate().update("INSERT INTO jids(jid, loginhash) VALUES (?, ?)", jid, hash); - return hash; - } - return list.get(0); - } - - @Transactional - @Override - public String getSignUpHashByTelegramID(final Long telegramId, final String username) { - List list = getJdbcTemplate().queryForList( - "SELECT loginhash FROM telegram WHERE tg_id = ? AND user_id IS NULL", - String.class, - telegramId); - - if (list.isEmpty()) { - String hash = UUID.randomUUID().toString(); - getJdbcTemplate().update( - "INSERT INTO telegram(tg_id, loginhash, tg_name) VALUES (?, ?, ?)", telegramId, hash, username); - return hash; - } - return list.get(0); - } - - @Transactional - @Override - public int createUser(final String username, final String password) { - KeyHolder holder = new GeneratedKeyHolder(); - try { - getJdbcTemplate().update( - con -> { - PreparedStatement stmt = con.prepareStatement( - "INSERT INTO users(nick,passw) VALUES (?,?)", - Statement.RETURN_GENERATED_KEYS); - stmt.setString(1, username); - stmt.setString(2, password); - return stmt; - }, - holder); - } catch (DuplicateKeyException e) { - return -1; - } - - int uid = holder.getKey().intValue(); - - getJdbcTemplate().update("INSERT INTO useroptions(user_id) VALUES (?)", uid); - getJdbcTemplate().update("INSERT INTO subscr_users(user_id, suser_id) VALUES (2, ?)", uid); - - return uid; - } - - @Transactional(readOnly = true) - @Override - public Optional getUserByUID(final int uid) { - List list = getJdbcTemplate().query( - "SELECT id, nick, banned, lang FROM users WHERE id = ?", new UserMapper(), uid); - - return list.isEmpty() ? Optional.empty() : Optional.of(list.get(0)); - } - - @Transactional(readOnly = true) - @Override - public User getUserByName(final String username) { - if (StringUtils.isNotBlank(username)) { - List list = getJdbcTemplate().query( - "SELECT id, nick, banned, lang FROM users WHERE nick = ?", new UserMapper(), username); - - if (!list.isEmpty()) - return list.get(0); - } - // TODO: @NonNullable ? - return AnonymousUser.INSTANCE; - } - - @Override - // No need marks with @Transactional annotation - public User getFullyUserByName(final String username) { - if (StringUtils.isNotBlank(username)) { - List list = getFullyUsersByNames(Collections.singletonList(username)); - if (!list.isEmpty()) - return list.get(0); - } - return null; - } - - @Override - @Transactional(readOnly = true) - public User getUserByEmail(String email) { - if (StringUtils.isNotBlank(email)) { - List list = getJdbcTemplate().query( - "SELECT id, nick, banned, lang FROM users WHERE id = (SELECT DISTINCT user_id FROM emails WHERE email = ?)", - new UserMapper(), - email); - - if (!list.isEmpty()) - return list.get(0); - } - return AnonymousUser.INSTANCE; - } - - @Transactional(readOnly = true) - @Override - public List getFullyUsersByNames(final Collection usernames) { - if (CollectionUtils.isEmpty(usernames)) - return Collections.emptyList(); - - return getNamedParameterJdbcTemplate().query( - "SELECT id, nick, passw, lang, banned FROM users WHERE nick in (:names)", - new MapSqlParameterSource("names", usernames), - (rs, rowNum) -> { - User user = new User(); - - user.setUid(rs.getInt(1)); - user.setName(rs.getString(2)); - user.setCredentials(rs.getString(3)); - user.setLang(rs.getString(4)); - user.setBanned(rs.getBoolean(5)); - - return user; - }); - } - - @Transactional(readOnly = true) - @Override - public User getUserByJID(final String jid) { - User result = null; - - if (StringUtils.isNotBlank(jid)) { - List list = getJdbcTemplate().query( - "SELECT id, nick, banned, lang FROM users WHERE id = (SELECT user_id FROM jids WHERE jid = ?)", - new UserMapper(), - jid); - - if (!list.isEmpty()) - result = list.get(0); - } - return result; - } - - @Transactional(readOnly = true) - @Override - public List getUsersByName(final Collection unames) { - if (CollectionUtils.isEmpty(unames)) - return Collections.emptyList(); - - return getNamedParameterJdbcTemplate().query( - "SELECT id, nick, banned, lang FROM users WHERE nick IN (:unames)", - new MapSqlParameterSource("unames", unames), - new UserMapper()); - } - - @Transactional(readOnly = true) - @Override - public List getUsersByID(final Collection uids) { - if (CollectionUtils.isEmpty(uids)) - return Collections.emptyList(); - - return getNamedParameterJdbcTemplate().query( - "SELECT id, nick, banned, lang FROM users WHERE id IN (:ids)", - new MapSqlParameterSource("ids", uids), - new UserMapper()); - } - - @Transactional(readOnly = true) - @Override - public List getJIDsbyUID(final int uid) { - return getJdbcTemplate().queryForList("SELECT jid FROM jids WHERE user_id = ? AND active = 1", String.class, uid); - } - - @Transactional(readOnly = true) - @Override - public int getUIDbyJID(final String jid) { - if (StringUtils.isNotBlank(jid)) { - List list = getJdbcTemplate().queryForList( - "SELECT user_id FROM jids WHERE jid = ?", Integer.class, jid); - - if (!list.isEmpty()) - return list.get(0); - } - return 0; - } - - @Transactional(readOnly = true) - @Override - public int getUIDbyName(final String uname) { - if (StringUtils.isNotBlank(uname)) { - List list = getJdbcTemplate().queryForList( - "SELECT id FROM users WHERE nick = ?", Integer.class, uname); - - if (!list.isEmpty()) - return list.get(0); - } - return 0; - } - - @Transactional(readOnly = true) - @Override - public int getUIDbyHash(final String hash) { - if (StringUtils.isNotBlank(hash)) { - List list = getJdbcTemplate().queryForList( - "SELECT user_id FROM logins WHERE hash = ?", Integer.class, hash); - - if (!list.isEmpty()) - return list.get(0); - } - return 0; - } - - @Transactional(readOnly = true) - @Override - public com.juick.User getUserByHash(final String hash) { - if (StringUtils.isNotBlank(hash)) { - List list = getJdbcTemplate().query( - "SELECT logins.user_id, users.nick, users.banned, users.lang FROM logins " + - "INNER JOIN users ON logins.user_id = users.id WHERE logins.hash = ?", - new UserMapper(), - hash); - - if (!list.isEmpty()) { - User user = list.get(0); - user.setAuthHash(hash); - return user; - } - } - return AnonymousUser.INSTANCE; - } - - @Transactional - @Override - public String getHashByUID(final int uid) { - List list = getJdbcTemplate().queryForList( - "SELECT hash FROM logins WHERE user_id = ?", String.class, uid); - - if (list.isEmpty()) { - String hash = RandomStringUtils.randomAlphanumeric(16).toUpperCase(); - getJdbcTemplate().update("INSERT INTO logins(user_id, hash) VALUES (?, ?)", uid, hash); - return hash; - } - return list.get(0); - } - - @Override - public int getUIDByHttpAuth(String auth) { - if (auth != null && auth.length() > 8 && auth.startsWith("Basic ")) { - Base64.Decoder dec = Base64.getDecoder(); - String loginpassw[] = new String(dec.decode(auth.substring(6))).split(":", 2); - if (loginpassw.length == 2 && loginpassw[0].length() > 1 && loginpassw[0].length() < 16 && loginpassw[0].matches("[a-zA-Z0-9\\-]+") && !loginpassw[1].isEmpty()) { - return checkPassword(loginpassw[0], loginpassw[1]); - } - } - return 0; - } - - @Transactional(readOnly = true) - @Override - public int checkPassword(final String username, final String password) { - if (StringUtils.isNotBlank(username)) { - List list = getJdbcTemplate().query( - "SELECT id, nick, banned, passw FROM users WHERE nick = ?", - (rs, rowNum) -> { - User user = new User(); - user.setUid(rs.getInt(1)); - user.setName(rs.getString(2)); - user.setBanned(rs.getBoolean(3)); - user.setCredentials(rs.getString(4)); - return user; - }, - username); - - if (!list.isEmpty()) { - User user = list.get(0); - if (Objects.equals(password, user.getCredentials())) - return user.getUid(); - } - } - return -1; - } - - @Transactional - @Override - public boolean updatePassword(final User user, final String newPassword) { - return user != null && - user.getUid() > 0 && - getJdbcTemplate().update("UPDATE users SET passw = ? WHERE id = ?", newPassword, user.getUid()) > 0; - } - - @Transactional(readOnly = true) - @Override - public int getUserOptionInt(final int uid, final String option, final int defaultValue) { - if (StringUtils.isBlank(option)) - return defaultValue; - - List list = getJdbcTemplate().queryForList( - "SELECT " + option + " FROM useroptions WHERE user_id = ?", Integer.class, uid); - - return list.isEmpty() ? defaultValue : list.get(0); - } - - @Transactional - @Override - public int setUserOptionInt(final int uid, final String option, final int value) { - if (StringUtils.isBlank(option)) - return 0; - - return getJdbcTemplate().update("UPDATE useroptions SET " + option + "= ? WHERE user_id = ?", value, uid); - } - - @Transactional(readOnly = true) - @Override - public UserInfo getUserInfo(final User user) { - List list = getJdbcTemplate().query( - "SELECT fullname, country, url, descr FROM usersinfo WHERE user_id = ?", - ((rs, rowNum) -> { - UserInfo info = new UserInfo(); - info.setFullName(rs.getString(1)); - info.setCountry(rs.getString(2)); - info.setUrl(rs.getString(3)); - info.setDescription(rs.getString(4)); - return info; - }), - user.getUid()); - - return list.isEmpty() ? new UserInfo() : list.get(0); - } - - @Transactional - @Override - public boolean updateUserInfo(final User user, final UserInfo info) { - return getJdbcTemplate().update( - "INSERT INTO usersinfo(user_id, fullname, country, url, descr) VALUES (?, ?, ?, ?, ?) " + - "ON DUPLICATE KEY UPDATE fullname = ?, country = ?, url = ?, descr = ?", - user.getUid(), - info.getFullName(), - info.getCountry(), - info.getUrl(), - info.getDescription(), - info.getFullName(), - info.getCountry(), - info.getUrl(), - info.getDescription()) > 0; - } - - @Transactional(readOnly = true) - @Override - public boolean getCanMedia(final int uid) { - List list = getJdbcTemplate().queryForList( - "SELECT users.lastphoto - UNIX_TIMESTAMP() FROM users WHERE id = ?", - Integer.class, - uid); - - return !list.isEmpty() && list.get(0) < 3600; - } - - @Transactional(readOnly = true) - @Override - public boolean isInWL(final int uid, final int check) { - List list = getJdbcTemplate().queryForList( - "SELECT 1 FROM wl_users WHERE user_id = ? AND wl_user_id = ?", - Integer.class, uid, check); - - return !list.isEmpty() && list.get(0) == 1; - } - - @Transactional(readOnly = true) - @Override - public boolean isInBL(final int uid, final int check) { - List list = getJdbcTemplate().queryForList( - "SELECT 1 FROM bl_users WHERE user_id = ? AND bl_user_id = ?", Integer.class, uid, check); - - return !list.isEmpty() && list.get(0) == 1; - } - - @Transactional(readOnly = true) - @Override - public boolean isInBLAny(final int uid, final int uid2) { - List list = getJdbcTemplate().queryForList( - "SELECT 1 FROM bl_users WHERE (user_id = ? AND bl_user_id = ?) " - + "OR (user_id = ? AND bl_user_id = ?)", - new Object[]{uid, uid2, uid2, uid}, - Integer.class); - - return !list.isEmpty() && list.get(0) == 1; - } - - @Transactional(readOnly = true) - @Override - public List checkBL(final int visitor, final Collection uids) { - if (CollectionUtils.isEmpty(uids)) - return Collections.emptyList(); - - return getNamedParameterJdbcTemplate().queryForList( - "SELECT user_id FROM bl_users WHERE bl_user_id = :visitor and user_id IN (:ids)", - new MapSqlParameterSource() - .addValue("visitor", visitor) - .addValue("ids", uids), - Integer.class); - } - - @Transactional(readOnly = true) - @Override - public boolean isSubscribed(final int uid, final int check) { - List list = getJdbcTemplate().queryForList( - "SELECT 1 FROM subscr_users WHERE suser_id = ? AND user_id = ?", - Integer.class, uid, check); - - return !list.isEmpty() && list.get(0) == 1; - } - - @Transactional(readOnly = true) - @Override - public List getUserRead(final int uid) { - return getJdbcTemplate().queryForList( - "SELECT user_id FROM subscr_users WHERE suser_id=?", Integer.class, uid); - } - - @Transactional(readOnly = true) - @Override - public List getUserReadLeastPopular(final int uid, final int cnt) { - return getJdbcTemplate().query( - "SELECT users.id,users.nick FROM (subscr_users " + - "INNER JOIN users_subscr ON (subscr_users.suser_id=? " + - "AND subscr_users.user_id=users_subscr.user_id)) INNER JOIN users " + - "ON subscr_users.user_id=users.id ORDER BY cnt LIMIT ?", - (rs, num) -> { - com.juick.User u = new com.juick.User(); - u.setUid(rs.getInt(1)); - u.setName(rs.getString(2)); - return u; - }, - uid, - cnt); - } - - @Transactional(readOnly = true) - @Override - public List getUserReaders(final int uid) { - return getJdbcTemplate().query( - "SELECT users.id, users.nick FROM subscr_users " + - "INNER JOIN users ON subscr_users.suser_id=users.id " + - "WHERE subscr_users.user_id=? ORDER BY users.nick", - (rs, num) -> { - com.juick.User u = new com.juick.User(); - u.setUid(rs.getInt(1)); - u.setName(rs.getString(2)); - return u; - }, - uid); - } - - @Transactional(readOnly = true) - @Override - public List getUserFriends(final int uid) { - return getJdbcTemplate().query( - "SELECT users.id,users.nick FROM subscr_users " + - "INNER JOIN users ON subscr_users.user_id=users.id " + - "WHERE subscr_users.suser_id=? AND users.id!=? " + - "ORDER BY users.nick", - (rs, num) -> { - com.juick.User u = new com.juick.User(); - u.setUid(rs.getInt(1)); - u.setName(rs.getString(2)); - return u; - }, - uid, - uid); - } - - @Transactional(readOnly = true) - @Override - public List getUserBLUsers(final int uid) { - return getJdbcTemplate().query("SELECT users.id,users.nick FROM users INNER JOIN bl_users " + - "ON(bl_users.bl_user_id=users.id) WHERE bl_users.user_id=? ORDER BY users.nick", - (rs, num) -> { - com.juick.User u = new com.juick.User(); - u.setUid(rs.getInt(1)); - u.setName(rs.getString(2)); - return u; - }, uid); - } - - @Transactional - @Override - public boolean linkTwitterAccount( - final User user, final String accessToken, final String accessTokenSecret, final String screenName) { - if (getJdbcTemplate().update("INSERT INTO twitter(user_id,access_token,access_token_secret,uname) " + - "VALUES (?,?,?,?)" + - " ON DUPLICATE KEY UPDATE access_token=?,access_token_secret=?,uname=?", - user.getUid(), accessToken, accessTokenSecret, screenName, accessToken, accessTokenSecret, screenName) > 0) { - return getJdbcTemplate().update("INSERT INTO subscr_users(user_id,suser_id,jid) " + - "VALUES (?,1741,'juick\\@twitter.juick.com')", user.getUid()) > 0; - } - return false; - - } - - @Transactional(readOnly = true) - @Override - public int getStatsIRead(final int uid) { - List list = getJdbcTemplate().queryForList( - "SELECT COUNT(*) FROM subscr_users WHERE suser_id = ?", Integer.class, uid); - return list.isEmpty() ? 0 : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public int getStatsMyReaders(final int uid) { - List list = getJdbcTemplate().queryForList("SELECT COUNT(*) FROM subscr_users WHERE user_id = ?", Integer.class, uid); - return list.isEmpty() ? 0 : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public int getStatsMessages(final int uid) { - List list = getJdbcTemplate().queryForList("SELECT COUNT(*) FROM messages WHERE user_id = ?", Integer.class, uid); - return list.isEmpty() ? 0 : list.get(0); - } - - @Transactional(readOnly = true) - @Override - public int getStatsReplies(final int uid) { - List list = getJdbcTemplate().queryForList("SELECT COUNT(*) FROM replies WHERE user_id = ?", Integer.class, uid); - return list.isEmpty() ? 0 : list.get(0); - } - - @Transactional - @Override - public boolean setActiveStatusForJID(final String JID, final UserService.ActiveStatus jidStatus) { - User user = getUserByJID(JID); - if (user != null) { - int newStatus = jidStatus == UserService.ActiveStatus.Active ? 1 : 0; - return getJdbcTemplate().update( - "UPDATE jids SET active = ? WHERE user_id = ? AND jid = ?", - newStatus, user.getUid(), JID) >= 0; - } - return false; - } - - @Transactional(readOnly = true) - @Override - public List getAllJIDs(final User user) { - return getJdbcTemplate().queryForList( - "SELECT jid FROM jids WHERE user_id=?", String.class, user.getUid()); - } - - @Transactional(readOnly = true) - @Override - public List getAuthCodes(final User user) { - return getJdbcTemplate().query( - "SELECT account,authcode FROM auth WHERE user_id=? AND protocol='xmpp'", - (rs, num) -> new Auth(rs.getString(1), rs.getString(2)), - user.getUid()); - } - - @Transactional(readOnly = true) - @Override - public List getEmails(final User user) { - return getJdbcTemplate().queryForList("SELECT email FROM emails WHERE user_id=?", String.class, user.getUid()); - } - - @Transactional(readOnly = true) - @Override - public String getEmailHash(final User user) { - List list = getJdbcTemplate().queryForList( - "SELECT hash FROM mail WHERE user_id = ?", - String.class, - user.getUid()); - return list.isEmpty() ? StringUtils.EMPTY : list.get(0) + "@mail.juick.com"; - } - - @Transactional - @Override - public int deleteLoginForUser(final String name) { - if (StringUtils.isBlank(name)) - return 0; - - return getJdbcTemplate().update( - "delete from logins where user_id in (select id from users where nick = ?)", name); - } - - @Transactional - @Override - public int setLoginForUser(final int uid, final String loginHash) { - if (StringUtils.isEmpty(loginHash)) - return 0; - - return getNamedParameterJdbcTemplate().update( - "INSERT INTO logins (user_id, hash) VALUES(:uid, :hash) ON DUPLICATE KEY UPDATE hash = :hash", - new MapSqlParameterSource() - .addValue("hash", loginHash) - .addValue("uid", uid)); - } - - @Transactional - @Override - public void logout(int uid) { - getJdbcTemplate().update("DELETE FROM logins WHERE user_id=?", uid); - } - - @Transactional - @Override - public boolean deleteJID(int uid, String jid) { - return getNamedParameterJdbcTemplate().update("DELETE FROM jids " + - "WHERE (SELECT COUNT(*) cnt FROM (select user_id, jid FROM jids j) c WHERE user_id=:uid) > 1 " + - "AND user_id=:uid AND jid=:jid", - new MapSqlParameterSource() - .addValue("uid", uid) - .addValue("jid", jid)) > 0; - } - - @Transactional - @Override - public boolean unauthJID(int uid, String jid) { - return getJdbcTemplate() - .update("DELETE FROM auth WHERE user_id=? AND protocol='xmpp' AND account=?", uid, jid) > 0; - } - - @Transactional(readOnly = true) - @Override - public List getActiveJIDs() { - return getJdbcTemplate().queryForList("SELECT jid FROM jids WHERE active=1 AND loginhash IS NULL", String.class); - } -} diff --git a/juick-server-jdbc/src/main/resources/juick.sql b/juick-server-jdbc/src/main/resources/juick.sql deleted file mode 100644 index ce34385f..00000000 --- a/juick-server-jdbc/src/main/resources/juick.sql +++ /dev/null @@ -1,947 +0,0 @@ --- MySQL dump 10.16 Distrib 10.1.26-MariaDB, for debian-linux-gnu (x86_64) --- --- Host: localhost Database: juick --- ------------------------------------------------------ -use juick; --- Server version 10.1.26-MariaDB-0+deb9u1 -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Table structure for table `ads_messages` --- - -DROP TABLE IF EXISTS `ads_messages`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ads_messages` ( - `message_id` int(10) unsigned NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ads_messages_log` --- - -DROP TABLE IF EXISTS `ads_messages_log`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ads_messages_log` ( - `user_id` int(10) unsigned NOT NULL, - `message_id` int(10) unsigned NOT NULL, - `ts` int(10) unsigned NOT NULL DEFAULT '0' -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `android` --- - -DROP TABLE IF EXISTS `android`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `android` ( - `user_id` int(10) unsigned NOT NULL, - `regid` char(255) NOT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE KEY `regid` (`regid`), - KEY `user_id` (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `auth` --- - -DROP TABLE IF EXISTS `auth`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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 -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `bl_tags` --- - -DROP TABLE IF EXISTS `bl_tags`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `bl_tags` ( - `user_id` int(10) unsigned NOT NULL, - `tag_id` int(10) unsigned NOT NULL, - KEY `tag_id` (`tag_id`), - KEY `user_id` (`user_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `bl_users` --- - -DROP TABLE IF EXISTS `bl_users`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `bl_users` ( - `user_id` int(10) unsigned NOT NULL, - `bl_user_id` int(10) unsigned NOT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`user_id`,`bl_user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `captcha` --- - -DROP TABLE IF EXISTS `captcha`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `captcha` ( - `jid` char(64) NOT NULL, - `hash` char(16) NOT NULL, - `confirmed` tinyint(4) NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `captchaimg` --- - -DROP TABLE IF EXISTS `captchaimg`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `captchaimg` ( - `id` char(16) NOT NULL, - `txt` char(6) NOT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `ip` char(16) NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `emails` --- - -DROP TABLE IF EXISTS `emails`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `emails` ( - `user_id` int(10) unsigned NOT NULL, - `email` char(64) NOT NULL, - `subscr_hour` tinyint(4) DEFAULT NULL, - KEY `email` (`email`) USING HASH -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `facebook` --- - -DROP TABLE IF EXISTS `facebook`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `facebook` ( - `user_id` int(10) unsigned DEFAULT NULL, - `fb_id` bigint(20) unsigned DEFAULT NULL, - `loginhash` char(36) DEFAULT NULL, - `access_token` char(255) DEFAULT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `fb_name` char(64) DEFAULT NULL, - `fb_link` char(255) DEFAULT NULL, - `crosspost` tinyint(1) unsigned NOT NULL DEFAULT '1', - KEY `user_id` (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `favorites` --- - -DROP TABLE IF EXISTS `favorites`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `favorites` ( - `user_id` int(10) unsigned NOT NULL, - `message_id` int(10) unsigned NOT NULL, - `ts` datetime NOT NULL, - `like_id` int(10) unsigned NOT NULL DEFAULT '1', - KEY `user_id` (`user_id`), - KEY `message_id` (`message_id`), - KEY `like_id` (`like_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `friends_facebook` --- - -DROP TABLE IF EXISTS `friends_facebook`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `friends_facebook` ( - `user_id` int(10) unsigned NOT NULL, - `friend_id` bigint(20) unsigned NOT NULL, - UNIQUE KEY `user_id` (`user_id`,`friend_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `images` --- - -DROP TABLE IF EXISTS `images`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ios` --- - -DROP TABLE IF EXISTS `ios`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ios` ( - `user_id` int(10) unsigned NOT NULL, - `token` char(64) COLLATE utf8mb4_unicode_ci NOT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE KEY `token` (`token`), - KEY `user_id` (`user_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `jids` --- - -DROP TABLE IF EXISTS `jids`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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`), - KEY `user_id` (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `logins` --- - -DROP TABLE IF EXISTS `logins`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `logins` ( - `user_id` int(10) unsigned NOT NULL, - `hash` char(16) NOT NULL, - UNIQUE KEY `user_id` (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `mail` --- - -DROP TABLE IF EXISTS `mail`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `mail` ( - `user_id` int(10) unsigned NOT NULL, - `hash` char(16) NOT NULL, - PRIMARY KEY (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `meon` --- - -DROP TABLE IF EXISTS `meon`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `messages` --- - -DROP TABLE IF EXISTS `messages`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `messages` ( - `message_id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `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` enum('jpg','mp4','png') DEFAULT NULL, - `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, - PRIMARY KEY (`message_id`), - KEY `user_id` (`user_id`), - KEY `ts` (`ts`), - KEY `attach` (`attach`), - KEY `place_id` (`place_id`), - KEY `popular` (`popular`), - KEY `hidden` (`hidden`), - KEY `updated_indx` (`updated`,`message_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `messages_access` --- - -DROP TABLE IF EXISTS `messages_access`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `messages_access` ( - `message_id` int(10) unsigned NOT NULL, - `user_id` int(10) unsigned NOT NULL, - KEY `message_id` (`message_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `messages_tags` --- - -DROP TABLE IF EXISTS `messages_tags`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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`), - KEY `message_id` (`message_id`), - KEY `tag_id` (`tag_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `messages_txt` --- - -DROP TABLE IF EXISTS `messages_txt`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `messages_txt` ( - `message_id` int(10) unsigned NOT NULL, - `tags` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, - `repliesby` varchar(96) COLLATE utf8mb4_unicode_ci DEFAULT NULL, - `txt` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, - PRIMARY KEY (`message_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `messages_votes` --- - -DROP TABLE IF EXISTS `messages_votes`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `messenger` --- - -DROP TABLE IF EXISTS `messenger`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `messenger` ( - `user_id` int(10) unsigned DEFAULT NULL, - `sender_id` bigint(20) NOT NULL, - `display_name` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `loginhash` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `places` --- - -DROP TABLE IF EXISTS `places`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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 ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`place_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `places_tags` --- - -DROP TABLE IF EXISTS `places_tags`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `places_tags` ( - `place_id` int(10) unsigned NOT NULL, - `tag_id` int(10) unsigned NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `pm` --- - -DROP TABLE IF EXISTS `pm`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `pm` ( - `user_id` int(10) unsigned NOT NULL, - `user_id_to` int(10) unsigned NOT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `txt` text NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `pm_inroster` --- - -DROP TABLE IF EXISTS `pm_inroster`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `pm_inroster` ( - `user_id` int(10) unsigned NOT NULL, - `jid` char(64) NOT NULL, - UNIQUE KEY `user_id_2` (`user_id`,`jid`), - KEY `user_id` (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `pm_streams` --- - -DROP TABLE IF EXISTS `pm_streams`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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`,`user_id_to`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `presence` --- - -DROP TABLE IF EXISTS `presence`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `presence` ( - `user_id` int(10) unsigned NOT NULL, - `jid` char(64) DEFAULT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY `jid` (`jid`) -) ENGINE=MEMORY DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `reactions` --- - -DROP TABLE IF EXISTS `reactions`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `reactions` ( - `like_id` int(10) unsigned NOT NULL, - `description` varchar(100) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `reader_links` --- - -DROP TABLE IF EXISTS `reader_links`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `reader_links` ( - `link_id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `rss_id` int(10) unsigned NOT NULL, - `url` char(255) NOT NULL, - `title` char(255) NOT NULL, - `ts` datetime NOT NULL, - PRIMARY KEY (`link_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `reader_rss` --- - -DROP TABLE IF EXISTS `reader_rss`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `reader_rss` ( - `rss_id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `url` char(255) NOT NULL, - `lastcheck` datetime NOT NULL, - PRIMARY KEY (`rss_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `replies` --- - -DROP TABLE IF EXISTS `replies`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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 NOT NULL DEFAULT CURRENT_TIMESTAMP, - `attach` enum('jpg','mp4','png') COLLATE utf8mb4_unicode_ci DEFAULT NULL, - `txt` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, - KEY `ts` (`ts`), - KEY `message_id` (`message_id`), - KEY `uid` (`user_id`), - KEY `reply_indx` (`message_id`,`reply_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `search` --- - -DROP TABLE IF EXISTS `search`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `search` ( - `id` bigint(20) unsigned NOT NULL, - `weight` int(11) NOT NULL, - `query` varchar(3072) NOT NULL, - `group_id` int(11) DEFAULT NULL, - KEY `query` (`query`(768)) -) ENGINE=SPHINX DEFAULT CHARSET=utf8mb4 CONNECTION='sphinx://127.0.0.1:3312/messages'; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `sphinx` --- - -DROP TABLE IF EXISTS `sphinx`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `sphinx` ( - `counter_id` tinyint(3) unsigned NOT NULL, - `max_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`counter_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `subscr_messages` --- - -DROP TABLE IF EXISTS `subscr_messages`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `subscr_messages` ( - `message_id` int(10) unsigned NOT NULL, - `suser_id` int(10) unsigned NOT NULL, - `last_read_rid` smallint(5) NOT NULL DEFAULT '0', - UNIQUE KEY `message_id` (`message_id`,`suser_id`), - KEY `last_read_indx` (`suser_id`,`last_read_rid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `subscr_tags` --- - -DROP TABLE IF EXISTS `subscr_tags`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `subscr_tags` ( - `tag_id` int(10) unsigned NOT NULL, - `suser_id` int(10) unsigned NOT NULL, - UNIQUE KEY `tag_id` (`tag_id`,`suser_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `subscr_users` --- - -DROP TABLE IF EXISTS `subscr_users`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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 b'1', - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE KEY `user_id` (`user_id`,`suser_id`), - KEY `suser_id` (`suser_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `tags` --- - -DROP TABLE IF EXISTS `tags`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `tags` ( - `tag_id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `synonym_id` int(10) unsigned DEFAULT NULL, - `name` char(70) CHARACTER SET utf8mb4 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`), - KEY `synonym_id` (`synonym_id`), - KEY `stat_msg_indx` (`name`,`stat_messages`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `tags_ignore` --- - -DROP TABLE IF EXISTS `tags_ignore`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `tags_ignore` ( - `tag_id` int(10) unsigned NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `tags_synonyms` --- - -DROP TABLE IF EXISTS `tags_synonyms`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `tags_synonyms` ( - `name` char(64) NOT NULL, - `changeto` char(64) NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `telegram` --- - -DROP TABLE IF EXISTS `telegram`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `telegram` ( - `user_id` int(10) unsigned DEFAULT NULL, - `tg_id` bigint(20) NOT NULL, - `tg_name` char(64) COLLATE utf8mb4_unicode_ci NOT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `loginhash` char(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `telegram_chats` --- - -DROP TABLE IF EXISTS `telegram_chats`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `telegram_chats` ( - `chat_id` bigint(20) DEFAULT NULL, - UNIQUE KEY `chat_id` (`chat_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `top_ignore_messages` --- - -DROP TABLE IF EXISTS `top_ignore_messages`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `top_ignore_messages` ( - `message_id` int(10) unsigned NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `top_ignore_tags` --- - -DROP TABLE IF EXISTS `top_ignore_tags`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `top_ignore_tags` ( - `tag_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`tag_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `top_ignore_users` --- - -DROP TABLE IF EXISTS `top_ignore_users`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `top_ignore_users` ( - `user_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `twitter` --- - -DROP TABLE IF EXISTS `twitter`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `useroptions` --- - -DROP TABLE IF EXISTS `useroptions`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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 '0000-00-00 00:00:00', - `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`), - KEY `recommendations` (`recommendations`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `users` --- - -DROP TABLE IF EXISTS `users`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `users` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `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 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`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `users_refs` --- - -DROP TABLE IF EXISTS `users_refs`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `users_refs` ( - `user_id` int(10) unsigned NOT NULL, - `ref` int(10) unsigned NOT NULL, - KEY `ref` (`ref`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `users_subscr` --- - -DROP TABLE IF EXISTS `users_subscr`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `users_subscr` ( - `user_id` int(10) unsigned NOT NULL, - `cnt` smallint(5) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `usersinfo` --- - -DROP TABLE IF EXISTS `usersinfo`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `version` --- - -DROP TABLE IF EXISTS `version`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `version` ( - `version` bigint(20) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `vk` --- - -DROP TABLE IF EXISTS `vk`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `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` tinyint(3) unsigned NOT NULL DEFAULT '1', - KEY `user_id` (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `winphone` --- - -DROP TABLE IF EXISTS `winphone`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `winphone` ( - `user_id` int(10) unsigned NOT NULL, - `url` char(255) NOT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE KEY `url` (`url`), - KEY `user_id` (`user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `wl_users` --- - -DROP TABLE IF EXISTS `wl_users`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `wl_users` ( - `user_id` int(10) unsigned NOT NULL, - `wl_user_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`user_id`,`wl_user_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2018-06-13 9:49:48 diff --git a/juick-server-jdbc/src/main/resources/pg_schema_wip b/juick-server-jdbc/src/main/resources/pg_schema_wip deleted file mode 100644 index 61178495..00000000 --- a/juick-server-jdbc/src/main/resources/pg_schema_wip +++ /dev/null @@ -1,1539 +0,0 @@ --- --- 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/juick-server-jdbc/src/main/resources/schema.sql b/juick-server-jdbc/src/main/resources/schema.sql deleted file mode 100644 index 296fd486..00000000 --- a/juick-server-jdbc/src/main/resources/schema.sql +++ /dev/null @@ -1,379 +0,0 @@ -SET DB_CLOSE_ON_EXIT TRUE; - -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 NOT NULL, - `loginhash` char(36) DEFAULT NULL, - `access_token` char(255) DEFAULT NULL, - `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `fb_name` char(64) NOT NULL, - `fb_link` char(255) NOT 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, - `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(9) 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(9) 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`) -); \ No newline at end of file diff --git a/juick-server-jdbc/src/main/resources/update.sql b/juick-server-jdbc/src/main/resources/update.sql deleted file mode 100644 index 13a62c3d..00000000 --- a/juick-server-jdbc/src/main/resources/update.sql +++ /dev/null @@ -1,12 +0,0 @@ --- if version table not exists set up version = 0; -update version set version = 0; - -DROP TABLE IF EXISTS `version`; - -CREATE TABLE `version` ( - `version` bigint NOT NULL -); - -insert into version values (0); - -update version set version = 1; \ No newline at end of file diff --git a/juick-server/build.gradle b/juick-server/build.gradle index d75a9bff..a4b8b940 100644 --- a/juick-server/build.gradle +++ b/juick-server/build.gradle @@ -2,15 +2,18 @@ apply plugin: 'war' apply plugin: 'org.springframework.boot' dependencies { - compile project(':juick-server-jdbc') - compile project(':juick-api') + compile project(':juick-common') compile ('org.springframework.boot:spring-boot-starter-security') + compile ('org.springframework.boot:spring-boot-starter-jdbc') + providedRuntime("org.springframework.boot:spring-boot-starter-tomcat") providedRuntime 'com.h2database:h2:1.4.196' compile 'io.springfox:springfox-swagger2:2.9.0' compile 'io.springfox:springfox-swagger-ui:2.9.0' + compile 'org.apache.commons:commons-email:1.5' + compile 'com.github.ooxi:serialized-php-parser:0.5.0' compile 'com.github.pengrad:java-telegram-bot-api:3.6.0' compile 'com.github.messenger4j:messenger4j:1.0.0' compile 'org.springframework.social:spring-social-twitter:1.1.2.RELEASE' diff --git a/juick-server/src/main/java/com/juick/server/api/Post.java b/juick-server/src/main/java/com/juick/server/api/Post.java new file mode 100644 index 00000000..afe9d2d5 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/api/Post.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.api; + +import com.juick.Reaction; +import com.juick.Status; +import com.juick.User; +import com.juick.server.CommandsManager; +import com.juick.server.helpers.CommandResult; +import com.juick.server.util.*; +import com.juick.service.MessagesService; +import com.juick.service.SubscriptionService; +import com.juick.service.UserService; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.inject.Inject; +import javax.validation.constraints.NotNull; +import java.net.URI; +import java.net.URL; +import java.util.List; + +/** + * Created by vt on 24/11/2016. + */ +@RestController +public class Post { + private static Logger logger = LoggerFactory.getLogger(Post.class); + + @Inject + private UserService userService; + @Inject + private MessagesService messagesService; + @Inject + private SubscriptionService subscriptionService; + @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") + private String tmpDir; + @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}") + private String imgDir; + @Inject + CommandsManager commandsManager; + + @RequestMapping(value = "/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public CommandResult doPostMessage( + @RequestParam(required = false, defaultValue = StringUtils.EMPTY) String body, + @RequestParam(required = false) String img, + @RequestParam(required = false) MultipartFile attach) throws Exception { + User visitor = UserUtils.getCurrentUser(); + + if (visitor.isAnonymous()) + throw new HttpForbiddenException(); + + if (body.length() > 4096) { + throw new HttpBadRequestException(); + } + body = body.replace("\r", StringUtils.EMPTY); + + URI attachmentFName = HttpUtils.receiveMultiPartFile(attach, tmpDir); + + if (StringUtils.isBlank(attachmentFName.toString()) && img != null && img.length() > 10) { + URI juickUri = URI.create(img); + if (juickUri.getScheme().equals("juick")) { + attachmentFName = juickUri; + } else { + try { + URL imgUrl = new URL(img); + attachmentFName = HttpUtils.downloadImage(imgUrl, tmpDir); + } catch (Exception e) { + logger.error("DOWNLOAD ERROR", e); + throw new HttpBadRequestException(); + } + } + } + if (StringUtils.isBlank(body) && StringUtils.isBlank(attachmentFName.toString())) { + // Should be there for compatibility + throw new HttpBadRequestException(); + } + return commandsManager.processCommand(visitor, body, attachmentFName); + } + + @RequestMapping(value = "/comment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public com.juick.Message doPostComment( + @RequestParam(defaultValue = "0") int mid, + @RequestParam(defaultValue = "0") int rid, + @RequestParam(required = false, defaultValue = StringUtils.EMPTY) String body, + @RequestParam(required = false) String img, + @RequestParam(required = false) MultipartFile attach) + throws Exception { + User visitor = UserUtils.getCurrentUser(); + int vuid = visitor.getUid(); + if (vuid == 0) { + throw new HttpForbiddenException(); + } + if (mid == 0) { + throw new HttpBadRequestException(); + } + com.juick.Message msg = messagesService.getMessage(mid); + if (msg == null) { + throw new HttpNotFoundException(); + } + + com.juick.Message reply = null; + if (rid > 0) { + reply = messagesService.getReply(mid, rid); + if (reply == null) { + throw new HttpNotFoundException(); + } + } + + if (body.length() > 4096) { + throw new HttpBadRequestException(); + } + body = body.replace("\r", StringUtils.EMPTY); + + if ((msg.ReadOnly && msg.getUser().getUid() != vuid) || userService.isInBLAny(msg.getUser().getUid(), vuid) + || (reply != null && userService.isInBLAny(reply.getUser().getUid(), vuid))) { + throw new HttpForbiddenException(); + } + + URI attachmentFName = HttpUtils.receiveMultiPartFile(attach, tmpDir); + + if (StringUtils.isBlank(attachmentFName.toString()) && img != null && img.length() > 10) { + try { + attachmentFName = HttpUtils.downloadImage(new URL(img), tmpDir); + } catch (Exception e) { + logger.error("DOWNLOAD ERROR", e); + throw new HttpBadRequestException(); + } + } + + return commandsManager.processCommand(visitor, String.format("#%d/%d %s", mid, rid, body), attachmentFName).getNewMessage().get(); + } + + @PostMapping("/like") + @ResponseStatus(value = HttpStatus.OK) + public Status doPostRecomm(@RequestParam Integer mid) throws Exception { + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.isAnonymous()) { + throw new HttpForbiddenException(); + } + com.juick.Message msg = messagesService.getMessage(mid); + if (msg == null) { + throw new HttpNotFoundException(); + } + if (msg.getUser().getUid() == visitor.getUid()) { + throw new HttpForbiddenException(); + } + CommandResult status = commandsManager.processCommand(visitor, String.format("! #%d", mid), + URI.create(StringUtils.EMPTY)); + return Status.getStatus(status.getText()); + } + + @GetMapping("/reactions") + @ResponseStatus(value = HttpStatus.OK) + public List reactionsList() { + return messagesService.listReactions(); + } + + @PostMapping("/react") + @ResponseStatus(value = HttpStatus.OK) + public Status doPostReact(@RequestParam Integer mid,@RequestParam @NotNull int reactionId, + @RequestParam (required = false, defaultValue = "1") int count) { + + logger.info("got reaction with type: {}", reactionId); + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.isAnonymous()) { + throw new HttpForbiddenException(); + } + com.juick.Message msg = messagesService.getMessage(mid); + if (msg == null) { + throw new HttpNotFoundException(); + } + if (msg.getUser().getUid() == visitor.getUid()) { + throw new HttpForbiddenException(); + } + MessagesService.RecommendStatus recommendStatus = MessagesService.RecommendStatus.Error; + for (int i = 0; i < count; i++) + recommendStatus = messagesService.likeMessage(mid, visitor.getUid(), + reactionId); + + return recommendStatus == MessagesService.RecommendStatus.Error ? Status.ERROR :Status.OK; + } +} diff --git a/juick-server/src/main/java/com/juick/server/configuration/ApiSecurityConfig.java b/juick-server/src/main/java/com/juick/server/configuration/ApiSecurityConfig.java new file mode 100644 index 00000000..94c1f1a8 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/configuration/ApiSecurityConfig.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.configuration; + +import com.juick.service.UserService; +import com.juick.service.security.JuickUserDetailsService; +import com.juick.service.security.deprecated.RequestParamHashRememberMeServices; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.HttpStatusEntryPoint; +import org.springframework.security.web.authentication.RememberMeServices; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import javax.inject.Inject; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.TimeUnit; + +/** + * Created by aalexeev on 11/21/16. + */ +@Configuration +@EnableWebSecurity +public class ApiSecurityConfig extends WebSecurityConfigurerAdapter { + @Value("${auth_remember_me_key:secret}") + private String rememberMeKey; + @Inject + private UserService userService; + + ApiSecurityConfig() { + super(true); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers(HttpMethod.OPTIONS).permitAll() + .antMatchers("/", "/messages", "/users", "/thread", "/tags", "/tlgmbtwbhk", "/fbwbhk", + "/skypebotendpoint").permitAll() + .anyRequest().hasRole("USER") + .and().httpBasic().authenticationEntryPoint(juickAuthenticationEntryPoint()) + .and().anonymous() + .and().cors().configurationSource(corsConfigurationSource()) + .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and().exceptionHandling().authenticationEntryPoint(juickAuthenticationEntryPoint()) + .and() + .rememberMe() + .alwaysRemember(true) + .tokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(6 * 30)) + .rememberMeServices(rememberMeServices()) + .key(rememberMeKey) + .and().authenticationProvider(authenticationProvider()) + .headers().defaultsDisabled().cacheControl(); + } + + @Bean + public DaoAuthenticationProvider authenticationProvider() { + DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); + + authenticationProvider.setUserDetailsService(userDetailsService()); + + return authenticationProvider; + } + + @Bean + public JuickUserDetailsService userDetailsService() { + return new JuickUserDetailsService(userService); + } + + @Bean + public RememberMeServices rememberMeServices() { + return new RequestParamHashRememberMeServices(rememberMeKey, userService); + } + + @Bean + public AuthenticationEntryPoint juickAuthenticationEntryPoint() { + return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED); + } + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + + configuration.setAllowedOrigins(Collections.singletonList("*")); + configuration.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "OPTIONS", "DELETE")); + configuration.setAllowedHeaders(Collections.singletonList("*")); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + + return source; + } + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", + "/configuration/**", "/swagger-ui.html", "/webjars/**", "/ws/**", "/rss/**"); + } +} diff --git a/juick-server/src/main/java/com/juick/server/configuration/PostConfig.java b/juick-server/src/main/java/com/juick/server/configuration/PostConfig.java new file mode 100644 index 00000000..598a7435 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/configuration/PostConfig.java @@ -0,0 +1,9 @@ +package com.juick.server.configuration; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@EnableAutoConfiguration +@ComponentScan({"com.juick.server", "com.juick.service"}) +public class PostConfig { +} diff --git a/juick-server/src/main/java/com/juick/service/BaseJdbcService.java b/juick-server/src/main/java/com/juick/service/BaseJdbcService.java new file mode 100644 index 00000000..496a04ba --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/BaseJdbcService.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; + +import javax.inject.Inject; + +/** + * Created by aalexeev on 11/13/16. + */ +public class BaseJdbcService { + @Inject + JdbcTemplate jdbcTemplate; + @Inject + NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() { + return namedParameterJdbcTemplate; + } + + public JdbcTemplate getJdbcTemplate() { + return jdbcTemplate; + } +} diff --git a/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java b/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java new file mode 100644 index 00000000..0bd5fe66 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import com.juick.ExternalToken; +import com.juick.server.helpers.ApplicationStatus; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; + +/** + * Created by aalexeev on 11/13/16. + */ +@Repository +public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostService { + + @Transactional(readOnly = true) + @Override + public Optional getTwitterToken(final int uid) { + List list = getJdbcTemplate().query( + "SELECT uname, access_token, access_token_secret FROM twitter WHERE user_id = ? AND crosspost = 1", + (rs, num) -> new ExternalToken(rs.getString(1), "twitter", + rs.getString(2), rs.getString(3)), + uid); + + return list.isEmpty() ? + Optional.empty() : Optional.of(list.get(0)); + } + + @Transactional + @Override + public boolean deleteTwitterToken(Integer uid) { + return getJdbcTemplate().update("DELETE FROM twitter WHERE user_id=?", uid) > 0 + && getJdbcTemplate().update("DELETE FROM subscr_users WHERE user_id=? AND suser_id=1741", uid) > 0; + } + + @Override + public void addFacebookState(String state) { + jdbcTemplate.update("INSERT INTO facebook(loginhash) VALUES(?)", state); + } + + @Override + public boolean verifyFacebookState(String state) { + try { + return jdbcTemplate.queryForObject("SELECT COUNT(loginhash) FROM facebook WHERE loginhash=?", + Integer.class, state) == 1; + } catch (EmptyResultDataAccessException e) { + return false; + } + } + + @Transactional(readOnly = true) + @Override + public Optional> getFacebookTokens(final int uid) { + List>> list = getJdbcTemplate().query( + "SELECT fb_id, access_token FROM facebook WHERE user_id = ? AND access_token IS NOT NULL AND crosspost = 1", + (rs, num) -> Optional.of(Pair.of(rs.getString(1), rs.getString(2))), + uid); + return list.isEmpty() ? + Optional.empty() : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public ApplicationStatus getFbCrossPostStatus(final int uid) { + List list = getJdbcTemplate().query( + "SELECT 1, crosspost FROM facebook WHERE user_id = ? LIMIT 1", + (rs, num) -> { + ApplicationStatus status = new ApplicationStatus(); + + status.setConnected(rs.getInt(1) > 0); + status.setCrosspostEnabled(rs.getBoolean(2)); + + return status; + }, + uid); + + return list.isEmpty() ? + new ApplicationStatus() : list.get(0); + } + + @Transactional + @Override + public boolean enableFBCrosspost(Integer uid) { + return getJdbcTemplate().update("UPDATE facebook SET crosspost=1 WHERE user_id=?", uid) > 0 + && getJdbcTemplate().update( + "INSERT INTO subscr_users(user_id,suser_id,jid,active) VALUES (?,5863,'juick@facebook.juick.com',1)", + uid) > 0; + } + + @Transactional + @Override + public void disableFBCrosspost(Integer uid) { + getJdbcTemplate().update("UPDATE facebook SET crosspost=0 WHERE user_id=?", uid); + // TODO: stop using magic numbers for system users + getJdbcTemplate().update("DELETE FROM subscr_users WHERE user_id=? AND suser_id=5863", uid); + } + + @Transactional(readOnly = true) + @Override + public String getTwitterName(final int uid) { + List list = getJdbcTemplate().queryForList( + "SELECT uname FROM twitter WHERE user_id = ?", + String.class, + uid); + + return list.isEmpty() ? + StringUtils.EMPTY : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public String getTelegramName(final int uid) { + List list = getJdbcTemplate().queryForList( + "SELECT tg_name FROM telegram WHERE user_id = ?", + String.class, + uid); + + return list.isEmpty() ? + StringUtils.EMPTY : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public Optional> getVkTokens(final int uid) { + List>> list = getJdbcTemplate().query( + "SELECT vk_id, access_token FROM vk WHERE user_id = ? AND crosspost = 1", + (rs, num) -> Optional.of(Pair.of(rs.getString(1), rs.getString(2))), + uid); + + return list.isEmpty() ? + Optional.empty() : list.get(0); + } + + @Transactional + @Override + public void deleteVKUser(Integer uid) { + getJdbcTemplate().update("DELETE FROM vk WHERE user_id=?", uid); + } + + @Transactional(readOnly = true) + @Override + public int getUIDbyFBID(long fbID) { + try { + return getJdbcTemplate().queryForObject("SELECT user_id FROM facebook WHERE fb_id=? AND user_id IS NOT NULL", + Integer.class, fbID); + } catch (EmptyResultDataAccessException e) { + return 0; + } + } + + @Transactional + @Override + public boolean createFacebookUser(long fbID, String loginhash, String token, String fbName, String fbLink) { + return getJdbcTemplate().update("UPDATE facebook SET fb_id=?, access_token=?, fb_name=?, fb_link=? WHERE loginhash=?", + fbID, token, fbName, fbLink, loginhash) > 0; + } + + @Transactional + @Override + public boolean updateFacebookUser(long fbID, String token, String fbName, String fbLink) { + return getJdbcTemplate().update("UPDATE facebook SET access_token=?,fb_name=?,fb_link=? WHERE fb_id=?", + token, fbName, fbLink, fbID) > 0; + } + + @Transactional(readOnly = true) + @Override + public int getUIDbyVKID(long vkID) { + try { + return getJdbcTemplate().queryForObject("SELECT user_id FROM vk WHERE vk_id=? AND user_id IS NOT NULL", Integer.class, vkID); + } catch (EmptyResultDataAccessException e) { + return 0; + } + } + + @Transactional + @Override + public boolean createVKUser(long vkID, String loginhash, String token, String vkName, String vkLink) { + return getJdbcTemplate().update("INSERT INTO vk(vk_id,loginhash,access_token,vk_name,vk_link) VALUES (?,?,?,?,?)", + vkID, loginhash, token, vkName, vkLink) > 0; + } + + @Transactional(readOnly = true) + @Override + public String getFacebookNameByHash(String hash) { + try { + List> fb = getJdbcTemplate().query("SELECT fb_name,fb_link FROM facebook WHERE loginhash=?", + (rs, num) -> Pair.of(rs.getString(1), rs.getString(2)), hash); + if (fb.size() > 0) { + return "" + fb.get(0).getLeft() + ""; + } + return null; + } catch (EmptyResultDataAccessException e) { + return null; + } + } + + @Transactional + @Override + public String getTelegramNameByHash(String hash) { + try { + String name = getJdbcTemplate().queryForObject("SELECT tg_name FROM telegram WHERE loginhash=?", String.class, hash); + return "" + name + ""; + } catch (EmptyResultDataAccessException e) { + return null; + } + } + + @Transactional + @Override + public boolean setFacebookUser(String hash, int uid) { + return getJdbcTemplate().update("UPDATE facebook SET user_id=?,loginhash=NULL WHERE loginhash=?", uid, hash) > 0; + } + + @Transactional + @Override + public String getVKNameByHash(String hash) { + List> logins = getJdbcTemplate().query("SELECT vk_name,vk_link FROM vk WHERE loginhash=?", + (rs, num) -> Pair.of(rs.getString(1), rs.getString(2)), hash); + if (logins.size() > 0) { + return "" + logins.get(0).getLeft() + ""; + } + return null; + } + + @Transactional + @Override + public boolean setVKUser(String hash, int uid) { + return getJdbcTemplate().update("UPDATE vk SET user_id=?,loginhash=NULL WHERE loginhash=?", uid, hash) > 0; + } + + @Transactional + @Override + public boolean setTelegramUser(String hash, int uid) { + return getJdbcTemplate().update("UPDATE telegram SET user_id=?,loginhash=NULL WHERE loginhash=?", uid, hash) > 0; + } + + @Transactional(readOnly = true) + @Override + public String getJIDByHash(String hash) { + try { + return getJdbcTemplate().queryForObject("SELECT jid FROM jids WHERE loginhash=?", String.class, hash); + } catch (EmptyResultDataAccessException e) { + return null; + } + } + + @Transactional + @Override + public boolean setJIDUser(String hash, int uid) { + return getJdbcTemplate().update("UPDATE jids SET user_id=?,loginhash=NULL WHERE loginhash=?", uid, hash) > 0; + } +} diff --git a/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java b/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java new file mode 100644 index 00000000..0cccc915 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import javax.inject.Inject; +import java.util.List; + +/** + * Created by vitalyster on 09.12.2016. + */ +@Repository +@Transactional +public class EmailServiceImpl extends BaseJdbcService implements EmailService { + + @Override + public boolean verifyAddressByCode(Integer userId, String code) { + try { + String address = getJdbcTemplate().queryForObject("SELECT account FROM auth WHERE user_id=? AND protocol='email' AND authcode=?", + String.class, userId, code); + addEmail(userId, address); + getJdbcTemplate().update("DELETE FROM auth WHERE user_id=? AND authcode=?", userId, code); + } catch (EmptyResultDataAccessException e) { + return false; + } + return true; + } + + @Override + public boolean addVerificationCode(Integer userId, String account, String code) { + return getJdbcTemplate().update("INSERT INTO auth(user_id,protocol,account,authcode) VALUES (?,'email',?,?)", + userId, account, code) > 0; + } + + @Override + public boolean addEmail(Integer userId, String email) { + return getJdbcTemplate().update("INSERT INTO emails(user_id,email) VALUES (?,?)", userId, email) > 0; + } + + @Override + public boolean deleteEmail(Integer userId, String account) { + return getNamedParameterJdbcTemplate().update("DELETE FROM emails " + + "WHERE (SELECT COUNT(*) cnt FROM (select user_id, email FROM emails e) c WHERE user_id=:uid) > 1 " + + "AND user_id=:uid AND email=:email", + new MapSqlParameterSource() + .addValue("uid", userId) + .addValue("email", account)) > 0; + } + + @Transactional(readOnly = true) + @Override + public String getNotificationsEmail(Integer userId) { + List list = getJdbcTemplate().queryForList( + "SELECT email FROM emails WHERE user_id=? AND subscr_hour IS NOT NULL", String.class, userId); + return list.isEmpty() ? StringUtils.EMPTY : list.get(0); + } + + @Override + public boolean setNotificationsEmail(Integer userId, String account) { + getJdbcTemplate().update("UPDATE emails SET subscr_hour=NULL WHERE user_id=?", userId); + return StringUtils.isNotEmpty(account) && getJdbcTemplate().update( + "UPDATE emails SET subscr_hour=1 WHERE user_id=? AND email=?", userId, account) > 0; + } + + @Transactional(readOnly = true) + @Override + public List getEmails(Integer userId, boolean active) { + return getJdbcTemplate().queryForList("SELECT email FROM emails WHERE user_id=? " + + (active ? "AND subscr_hour IS NOT NULL" : ""), String.class, userId); + } +} diff --git a/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java b/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java new file mode 100644 index 00000000..35e48383 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java @@ -0,0 +1,1006 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import com.juick.*; +import com.juick.server.helpers.PrivacyOpts; +import com.juick.server.helpers.ResponseReply; +import com.juick.util.MessageUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.jdbc.core.ConnectionCallback; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import javax.inject.Inject; +import java.sql.*; +import java.time.Instant; +import java.util.*; +import java.util.Date; +import java.util.stream.Collectors; + +/** + * Created by aalexeev on 11/13/16. + */ +@Repository +public class MessagesServiceImpl extends BaseJdbcService implements MessagesService { + private static final Logger logger = LoggerFactory.getLogger(MessagesServiceImpl.class); + @Inject + private UserService userService; + @Inject + private TagService tagService; + @Inject + private SearchService searchService; + @Inject + private ImagesService imagesService; + @Value("${img_url:https://i.juick.com/}") + private String baseImagesUrl; + + private class MessageMapper implements RowMapper { + @Override + public Message mapRow(ResultSet rs, int rowNum) throws SQLException { + Message msg = new Message(); + msg.setMid(rs.getInt(1)); + msg.setRid(rs.getInt(2)); + msg.setReplyto(rs.getInt(3)); + User user = new User(); + user.setUid(rs.getInt(4)); + user.setName(rs.getString(5)); + user.setBanned(rs.getBoolean(6)); + msg.setUser(user); + msg.setTimestamp(rs.getTimestamp(7).toInstant()); + msg.ReadOnly = rs.getBoolean(8); + msg.setPrivacy(rs.getInt(9)); + msg.FriendsOnly = msg.getPrivacy() < 0; + msg.setReplies(rs.getInt(10)); + msg.setAttachmentType(rs.getString(11)); + msg.setLikes(rs.getInt(12)); + msg.Hidden = rs.getBoolean(13); + String tagsStr = rs.getString(14); + msg.setTags(MessageUtils.parseTags(tagsStr)); + msg.setRepliesBy(rs.getString(15)); + msg.setText(rs.getString(16)); + msg.setReplyQuote(MessageUtils.formatQuote(rs.getString(17))); + msg.setUpdated(rs.getTimestamp(18).toInstant()); + int quoteUid = rs.getInt(19); + if (quoteUid > 0) { + User quoteUser = new User(); + quoteUser.setUid(quoteUid); + quoteUser.setName(rs.getString(20)); + msg.setTo(quoteUser); + } + if (StringUtils.isNotEmpty(msg.getAttachmentType())) { + try { + imagesService.setAttachmentMetadata(baseImagesUrl, msg); + } catch (Exception e) { + logger.warn("exception reading images for mid {} rid {}", msg.getMid(), msg.getRid(), e); + } + } + return msg; + } + } + + + + /** + * @see Java, JDBC and MySQL Types + */ + @Transactional + @Override + public int createMessage(final int uid, final String txt, final String attachment, final Collection tags) { + SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(getJdbcTemplate()).withTableName("messages") + .usingColumns("user_id", "attach", "ts") + .usingGeneratedKeyColumns("message_id"); + Map insertMap = new HashMap<>(); + insertMap.put("user_id", uid); + Instant now = Instant.now(); + insertMap.put("ts", Timestamp.from(now)); + if (attachment != null) { + insertMap.put("attach", attachment); + } + int mid = simpleJdbcInsert.executeAndReturnKey(insertMap).intValue(); + if (mid > 0) { + String tagsNames = StringUtils.EMPTY; + + if (CollectionUtils.isNotEmpty(tags)) { + StringBuilder tasNamesBuilder = new StringBuilder(); + List params = new ArrayList<>(tags.size()); + + boolean next = false; + + for (Tag tag : tags) { + if (next) { + tasNamesBuilder.append(" "); + } else + next = true; + + tasNamesBuilder.append(tag.getName()); + params.add(new Object[]{mid, tag.TID}); + } + tagsNames = tasNamesBuilder.toString(); + + getJdbcTemplate().batchUpdate( + "INSERT INTO messages_tags(message_id, tag_id) VALUES (?, ?)", + params, new int[]{Types.INTEGER, Types.INTEGER}); + } + + getJdbcTemplate().update( + "INSERT INTO messages_txt(message_id, tags, txt) VALUES (?, ?, ?)", + new Object[]{mid, tagsNames, txt}, + new int[]{Types.INTEGER, Types.VARCHAR, Types.VARCHAR}); + getJdbcTemplate().update("UPDATE users SET lastmessage=? where id=?", Timestamp.from(now), uid); + } + + return mid; + } + + /** + * @param mid + * @param rid + * @param user + * @param txt + * @param attachment + * @return + * @see Java, JDBC and MySQL Types + */ + @Transactional + @Override + public int createReply(final int mid, final int rid, final User user, final String txt, final String attachment) { + int ridnew = getReplyIDIncrement(mid); + Date ts = Date.from(Instant.now()); + getJdbcTemplate().update("INSERT INTO replies(message_id, reply_id, user_id, replyto, attach, txt, ts) " + + "VALUES (?, ?, ?, ?, ?, ?, ?)", + mid, ridnew, user.getUid(), rid, attachment, txt, ts); + + if (ridnew > 0) { + getJdbcTemplate().update( + "UPDATE messages SET replies = replies + 1, updated=? WHERE message_id = ?", + ts, mid); + setLastReadComment(user, mid, ridnew); + getJdbcTemplate().update("UPDATE users SET lastmessage=? where id=?", ts, user.getUid()); + } + return ridnew; + } + + @Override + public int getReplyIDIncrement(final int mid) { + return getJdbcTemplate().execute((ConnectionCallback) conn -> { + conn.setAutoCommit(false); + final int replyNo; + try (PreparedStatement ps = conn.prepareStatement("SELECT maxreplyid+1 FROM messages WHERE message_id=? FOR UPDATE")) { + ps.setInt(1, mid); + try (ResultSet resultSet = ps.executeQuery()) { + if (resultSet.next()) { + replyNo = resultSet.getInt(1); + } else { + throw new IncorrectResultSizeDataAccessException("while getting getReplyIDIncrement, mid=" + mid, 1, 0); + } + } + } + try (PreparedStatement ps = conn.prepareStatement("UPDATE messages SET maxreplyid=? WHERE message_id=?")) { + ps.setInt(1, replyNo); + ps.setInt(2, mid); + if (ps.executeUpdate() != 1) { + throw new IncorrectResultSizeDataAccessException("Cannot find a message to update: " + mid, 1, 0); + } + } + conn.commit(); + return replyNo; + }); + + } + + @Transactional + void updateRepliesBy(int mid) { + List users = getJdbcTemplate().queryForList("SELECT users.nick FROM replies " + + "INNER JOIN users ON replies.user_id=users.id WHERE replies.message_id=? " + + "GROUP BY replies.user_id ORDER BY COUNT(replies.reply_id) DESC LIMIT 5", String.class, mid); + String result = users.stream().map(u -> "@" + u).collect(Collectors.joining(",")); + getJdbcTemplate().update("UPDATE messages_txt SET repliesby=? WHERE message_id=?", result, mid); + } + + @Transactional + @Override + public RecommendStatus recommendMessage(final int mid, final int vuid) { + int wasDeleted = getJdbcTemplate() + .update("DELETE FROM favorites WHERE user_id=? AND message_id=? and like_id=?", vuid, mid, Reaction.LIKE); + if (wasDeleted > 0) { + return RecommendStatus.Deleted; + } else { + boolean wasAdded = getJdbcTemplate() + .update("INSERT INTO favorites(user_id, message_id, ts, like_id ) VALUES (?, ?, NOW(), ?)", vuid, mid,Reaction.LIKE) == 1; + if (wasAdded) { + return RecommendStatus.Added; + } + } + return RecommendStatus.Error; + } + + @Override + public List listReactions() { + return jdbcTemplate.query("SELECT like_id, description FROM reactions", (rs, rowNum) -> { + Reaction reaction = new Reaction(rs.getInt("like_id")); + reaction.setDescription(rs.getString("description")); + return reaction; + }); + } + + @Transactional + @Override + public RecommendStatus likeMessage(int mid, int vuid, int reactionId) throws IllegalArgumentException { + boolean wasAdded = getJdbcTemplate() + .update("INSERT INTO favorites(user_id, message_id, ts, like_id ) VALUES (?, ?, NOW(), ?)", vuid, mid, reactionId) == 1; + if (wasAdded) { + return RecommendStatus.Added; + } + + return RecommendStatus.Error; + } + + @Transactional(readOnly = true) + @Override + public boolean canViewThread(final int mid, final int uid) { + List list = getJdbcTemplate().query( + "SELECT user_id, privacy FROM messages WHERE message_id = ?", + (rs, rowNum) -> { + PrivacyOpts res = new PrivacyOpts(); + + res.setUid(rs.getInt(1)); + res.setPrivacy(rs.getInt(2)); + + return res; + }, + mid); + + PrivacyOpts privacyOpts = list.isEmpty() ? null : list.get(0); + + return privacyOpts == null || + privacyOpts.getPrivacy() >= 0 || + uid == privacyOpts.getUid() || + ((privacyOpts.getPrivacy() == -1 || privacyOpts.getPrivacy() == -2) && + uid > 0 && userService.isInWL(privacyOpts.getUid(), uid)); + } + + @Transactional(readOnly = true) + @Override + public boolean isReadOnly(final int mid) { + List list = getJdbcTemplate().queryForList( + "SELECT readonly FROM messages WHERE message_id = ?", + new Object[]{mid}, + Integer.class); + + return !list.isEmpty() && list.get(0) == 1; + } + + @Transactional(readOnly = true) + @Override + public boolean isSubscribed(final int uid, final int mid) { + List list = getJdbcTemplate().queryForList( + "SELECT 1 FROM subscr_messages WHERE suser_id = ? AND message_id = ?", + new Object[]{uid, mid}, + Integer.class); + + return !list.isEmpty() && list.get(0) == 1; + } + + @Transactional(readOnly = true) + @Override + public int getMessagePrivacy(final int mid) { + List list = getJdbcTemplate().queryForList( + "SELECT privacy FROM messages WHERE message_id = ?", + new Object[]{mid}, + Integer.class); + + return list.isEmpty() ? -4 : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public com.juick.Message getMessage(final int mid) { + + List list = getJdbcTemplate().query( + "SELECT messages.message_id as mid, 0 as rid, 0 as replyto, " + + "messages.user_id as uid, users.nick, users.banned as banned, " + + "" + + "messages.ts," + + "messages.readonly, messages.privacy, messages.replies," + + "messages.attach, COUNT(DISTINCT favorites.user_id) as likes, messages.hidden," + + "txt.tags, txt.repliesby, txt.txt, '' as q, messages.updated, 0 as to_uid, " + + "NULL as to_name FROM messages " + + "INNER JOIN users ON messages.user_id = users.id " + + "INNER JOIN messages_txt AS txt " + + "ON messages.message_id = txt.message_id " + + "LEFT JOIN favorites " + + "ON messages.message_id = favorites.message_id AND favorites.like_id=1 " + + "WHERE messages.message_id = ? " + + "GROUP BY mid, rid, replyto, uid, nick, banned, messages.ts, readonly, " + + "privacy, replies, attach, tags, repliesby, q", + new MessageMapper(), + mid); + if (!list.isEmpty()) { + final Message message = list.get(0); + Map> reactionStats = updateReactionsFor(Collections.singletonList(mid)); + message.setReactions(reactionStats.get(message.getMid())); + return message; + } + return null; + } + + @Transactional(readOnly = true) + @Override + public com.juick.Message getReply(final int mid, final int rid) { + List list = getJdbcTemplate().query( + "SELECT replies.user_id, users.nick," + + "replies.replyto, replies.ts," + + "replies.attach, replies.txt, IFNULL(q.txt,t.txt) as quote, " + + "COALESCE(q.user_id, m.user_id) AS to_uid, COALESCE(qu.nick, mu.nick) AS to_name " + + "FROM replies INNER JOIN users ON replies.user_id = users.id " + + "LEFT JOIN replies q ON replies.message_id = q.message_id and replies.replyto = q.reply_id " + + "LEFT JOIN messages_txt t ON replies.message_id = t.message_id " + + "LEFT JOIN messages m ON replies.message_id = m.message_id " + + "LEFT JOIN users qu ON q.user_id=qu.id " + + "LEFT JOIN users mu ON m.user_id=mu.id " + + "WHERE replies.message_id = ? AND replies.reply_id = ?", + (rs, num) -> { + Message msg = new Message(); + + msg.setMid(mid); + msg.setRid(rid); + msg.setUser(new User()); + msg.getUser().setUid(rs.getInt(1)); + msg.getUser().setName(rs.getString(2)); + msg.setReplyto(rs.getInt(3)); + msg.setTimestamp(rs.getTimestamp(4).toInstant()); + msg.setAttachmentType(rs.getString(5)); + msg.setText(rs.getString(6)); + String quote = rs.getString(7); + + if (!StringUtils.isEmpty(quote)) { + msg.setReplyQuote(MessageUtils.formatQuote(quote)); + } + int quoteUid = rs.getInt(8); + if (quoteUid > 0) { + User quoteUser = new User(); + quoteUser.setUid(quoteUid); + quoteUser.setName(rs.getString(9)); + msg.setTo(quoteUser); + } + + return msg; + }, + mid, rid); + + return list.isEmpty() ? null : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public User getMessageAuthor(final int mid) { + List list = getJdbcTemplate().query( + "SELECT messages.user_id, users.nick " + + "FROM messages INNER JOIN users ON messages.user_id = users.id WHERE messages.message_id = ?", + new Object[]{mid}, + (rs, num) -> { + User res = new com.juick.User(); + res.setUid(rs.getInt(1)); + res.setName(rs.getString(2)); + return res; + }); + + return list.isEmpty() ? + null : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public List getMessageRecommendations(final int mid) { + return getJdbcTemplate().queryForList( + "SELECT DISTINCT users.nick FROM favorites INNER JOIN users " + + "ON (favorites.message_id = ? AND favorites.user_id = users.id) WHERE favorites.like_id=1", + new Object[]{mid}, + String.class); + } + + @Transactional(readOnly = true) + @Override + public List getAll(final int visitorUid, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("before", before) + .addValue("visitorUid", visitorUid); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT m.message_id FROM messages m WHERE " + + (before > 0 ? + " m.message_id < :before AND " : StringUtils.EMPTY) + + " m.hidden = 0 AND (m.privacy > 0" + + (visitorUid > 1 ? + " OR m.user_id = :visitorUid) AND NOT EXISTS (" + + " SELECT 1 FROM bl_users b WHERE b.user_id = :visitorUid AND b.bl_user_id = m.user_id)" : + ")") + + " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + + "(SELECT tag_id FROM messages_tags WHERE message_id = m.message_id) and :visitorUid = bt.user_id)" + + " AND NOT EXISTS (SELECT 1 from users u WHERE u.banned = 1 and u.id = m.user_id) ORDER BY m.message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getTag(final int tid, final int visitorUid, final int before, final int cnt) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("tid", tid) + .addValue("cnt", cnt) + .addValue("before", before) + .addValue("visitorUid", visitorUid); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT message_id FROM (tags INNER JOIN messages_tags " + + "ON ((tags.synonym_id = :tid OR tags.tag_id = :tid) AND tags.tag_id = messages_tags.tag_id)) " + + "INNER JOIN messages USING(message_id) WHERE " + + (before > 0 ? + " messages.message_id < :before AND " : StringUtils.EMPTY) + + "(messages.privacy > 0 OR messages.user_id = :visitorUid) ORDER BY message_id DESC LIMIT :cnt", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getTags(final String tids, final int visitorUid, final int before, final int cnt) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("cnt", cnt) + .addValue("before", before) + .addValue("visitorUid", visitorUid); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT messages.message_id FROM messages_tags " + + "INNER JOIN messages USING(message_id) WHERE messages_tags.tag_id IN (" + tids + ") " + + (before > 0 ? + " AND messages.message_id < :before " : StringUtils.EMPTY) + + " AND (messages.privacy > 0 OR messages.user_id = :visitorUid) " + + "ORDER BY messages.message_id DESC LIMIT :cnt", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getPlace(final int placeId, final int visitorUid, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("placeId", placeId) + .addValue("before", before) + .addValue("visitorUid", visitorUid); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT message_id FROM messages WHERE place_id = :placeId " + + (before > 0 ? + " AND message_id < :before " : StringUtils.EMPTY) + + " AND (privacy > 0 OR user_id = :visitorUid) ORDER BY message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getMyFeed(final int uid, final int before, boolean recommended) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("before", before); + + List mids = getNamedParameterJdbcTemplate().queryForList( + "(SELECT message_id FROM messages " + + " INNER JOIN subscr_users ON (subscr_users.suser_id = :uid AND subscr_users.user_id = messages.user_id) " + + " WHERE " + + (before > 0 ? + " message_id < :before AND " : StringUtils.EMPTY) + + " (privacy >= 0 OR (privacy >= -2 AND privacy <= -1" + + " AND EXISTS (SELECT 1 FROM wl_users w WHERE w.wl_user_id = :uid and w.user_id = messages.user_id)))) " + + " UNION " + + " (SELECT message_id FROM messages WHERE user_id=:uid " + + (before > 0 ? + " AND message_id < :before " : StringUtils.EMPTY) + + (recommended ? + ") UNION " + + " (SELECT f.message_id as message_id FROM favorites f WHERE " + + "EXISTS (SELECT 1 FROM subscr_users s WHERE s.suser_id = :uid and f.user_id = s.user_id)" + + (before > 0 ? + " AND f.message_id < :before " : StringUtils.EMPTY) : StringUtils.EMPTY) + + ") ORDER BY message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + + return mids; + } + + @Transactional(readOnly = true) + @Override + public List getPrivate(final int uid, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("before", before); + + return getNamedParameterJdbcTemplate().queryForList + ("SELECT message_id FROM messages WHERE user_id = :uid AND privacy < 0" + + (before > 0 ? + " AND message_id < :before " : StringUtils.EMPTY) + + "ORDER BY message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getDiscussions(final int uid, final Long to) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("to", new Timestamp(to)); + + return getNamedParameterJdbcTemplate().query( + "SELECT messages.message_id, messages.updated FROM subscr_messages " + + "INNER JOIN messages ON messages.message_id=subscr_messages.message_id " + + "WHERE suser_id = :uid " + + (to != 0 ? + "AND updated < :to " : StringUtils.EMPTY) + + "ORDER BY updated DESC, message_id DESC LIMIT 20", + sqlParameterSource, + (rs, rowNum) -> rs.getInt(1)); + } + + @Transactional(readOnly = true) + @Override + public List getRecommended(final int uid, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("before", before); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT f.message_id FROM favorites f WHERE " + + "EXISTS (SELECT 1 FROM subscr_users s WHERE s.suser_id = :uid and f.user_id = s.user_id)" + + (before > 0 ? + " AND f.message_id < :before " : StringUtils.EMPTY) + + "ORDER BY f.message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getPopular(final int visitorUid, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("vid", visitorUid) + .addValue("before", before); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT m.message_id FROM messages m WHERE m.privacy > 0 " + + (before > 0 ? + " AND m.message_id < :before " : StringUtils.EMPTY) + + " AND m.popular > 0 AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :vid and b.bl_user_id = m.user_id) " + + " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + + "(SELECT tag_id FROM messages_tags WHERE message_id = m.message_id) and :vid = bt.user_id)" + + " ORDER BY m.message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getPhotos(final int visitorUid, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("vid", visitorUid) + .addValue("before", before); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT m.message_id FROM messages m WHERE (m.privacy > 0 OR m.user_id = :vid) " + + (before > 0 ? + " AND m.message_id < :before " : StringUtils.EMPTY) + + " AND m.attach IS NOT NULL " + + " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + + "(SELECT tag_id FROM messages_tags WHERE message_id = m.message_id) and :vid = bt.user_id)" + + " AND NOT EXISTS (SELECT 1 from users u WHERE u.banned = 1 and u.id = m.user_id) " + + " AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :vid and b.bl_user_id = m.user_id) " + + " ORDER BY m.message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getSearch(final String search, final int before) { + List mids = searchService.searchInAllMessages(search, before); + + if (!mids.isEmpty()) + return getNamedParameterJdbcTemplate().queryForList( + "SELECT message_id FROM messages WHERE message_id IN (:ids) AND privacy > 0 ORDER BY message_id DESC LIMIT 20", + new MapSqlParameterSource("ids", mids), + Integer.class); + return mids; + } + + @Transactional(readOnly = true) + @Override + public List getUserBlog(final int uid, final int privacy, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("privacy", privacy) + .addValue("before", before); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT message_id FROM messages WHERE user_id = :uid" + + (before > 0 ? + " AND message_id < :before" : StringUtils.EMPTY) + + " AND privacy >= :privacy ORDER BY message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getUserTag(final int uid, final int tid, final int privacy, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("tid", tid) + .addValue("privacy", privacy) + .addValue("before", before); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT messages.message_id FROM messages_tags INNER JOIN messages " + + " USING (message_id) WHERE messages.user_id = :uid AND messages_tags.tag_id = :tid " + + (before > 0 ? + " AND messages.message_id < :before " : StringUtils.EMPTY) + + " AND messages.privacy >= :privacy ORDER BY messages.message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getUserBlogAtDay(final int uid, final int privacy, final int daysback) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("privacy", privacy) + .addValue("daysback", daysback); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT message_id FROM messages WHERE user_id = :uid" + + (daysback > 0 ? + " AND ts >= date(NOW() - INTERVAL :daysback day)" + + " AND ts < date(NOW() - INTERVAL :daysback day + INTERVAL 1 day)" : StringUtils.EMPTY) + + " AND privacy >= :privacy ORDER BY message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getUserBlogWithRecommendations(final int uid, final int privacy, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("privacy", privacy) + .addValue("before", before); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT message_id FROM " + + "(SELECT message_id FROM favorites " + + " WHERE user_id = :uid " + + (before > 0 ? + " AND message_id < :before " : StringUtils.EMPTY) + + " ORDER BY message_id DESC LIMIT 20) as r" + + " UNION ALL " + + "SELECT message_id FROM " + + "(SELECT message_id FROM messages WHERE user_id = :uid" + + (before > 0 ? + " AND message_id < :before" : StringUtils.EMPTY) + + " AND privacy >= :privacy ORDER BY message_id DESC LIMIT 20) as m " + + "ORDER BY message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getUserRecommendations(final int uid, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("before", before); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT message_id FROM favorites " + + " WHERE user_id = :uid " + + (before > 0 ? + " AND message_id < :before " : StringUtils.EMPTY) + + " ORDER BY message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getUserPhotos(final int uid, final int privacy, final int before) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("privacy", privacy) + .addValue("before", before); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT message_id FROM messages WHERE user_id = :uid " + + (before > 0 ? + " AND message_id < :before " : StringUtils.EMPTY) + + " AND privacy >= :privacy AND attach IS NOT NULL ORDER BY message_id DESC LIMIT 20", + sqlParameterSource, + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public List getUserSearch(final int UID, final String search, final int privacy, final int before) { + List mids = searchService.searchByStringAndUser(search, UID, before); + + if (!mids.isEmpty()) { + return getNamedParameterJdbcTemplate().queryForList( + "SELECT message_id FROM messages WHERE message_id IN (:ids) AND privacy >= :privacy ORDER BY message_id DESC", + new MapSqlParameterSource("ids", mids) + .addValue("privacy", privacy), + Integer.class); + } + return mids; + } + + @Transactional(readOnly = true) + @Override + public List getMessages(final List mids) { + if (CollectionUtils.isNotEmpty(mids)) { + + List msgs = getNamedParameterJdbcTemplate().query( + "SELECT messages.message_id, 0 as rid, 0 as replyto, " + + "messages.user_id,users.nick, 0 as banned, " + + "messages.ts," + + "messages.readonly,messages.privacy,messages.replies," + + "messages.attach,COUNT(DISTINCT favorites.user_id) AS likes,messages.hidden," + + "messages_txt.tags,messages_txt.repliesby, messages_txt.txt, '' as q, " + + "messages.updated, 0 as to_uid, NULL as to_name " + + "FROM (messages INNER JOIN messages_txt " + + "ON messages.message_id=messages_txt.message_id) " + + "INNER JOIN users ON messages.user_id=users.id " + + "LEFT JOIN favorites " + + "ON messages.message_id = favorites.message_id AND favorites.like_id=1 " + + "WHERE messages.message_id IN (:ids) GROUP BY messages.message_id", + new MapSqlParameterSource("ids", mids), + new MessageMapper()); + + + Map> likes = updateReactionsFor(mids); + + msgs.forEach(i -> i.setReactions(likes.get(i.getMid()))); + + msgs.sort(Comparator.comparing(item -> mids.indexOf(item.getMid()))); + + return msgs; + } + return Collections.emptyList(); + } + + + @Transactional(readOnly = true) + @Override + public Map> updateReactionsFor(final List mids) { + + return getNamedParameterJdbcTemplate().query("select f.message_id as mid, f.like_id as lid," + + " r.description as descr, count(f.like_id) as cnt" + + " from favorites f LEFT JOIN reactions r ON f.like_id = r.like_id " + + " where f.message_id IN (:mids) " + + " group by f.message_id, f.like_id", new MapSqlParameterSource("mids", mids), (ResultSet rs) -> { + Map> results = new HashMap<>(); + + + while (rs.next()) { + int messageId = rs.getInt("mid"); + int likeId = rs.getInt("lid"); + int count = rs.getInt("cnt"); + String description = rs.getString("descr"); + Reaction reaction = new Reaction(likeId); + reaction.setCount(count); + reaction.setDescription(description); + results.computeIfAbsent(messageId, HashSet::new); + results.get(messageId).add(reaction); + } + + return results; + }); + + } + + + @Transactional + @Override + public List getReplies(final User user, final int mid) { + List replies = getNamedParameterJdbcTemplate().query( + "SELECT replies.message_id as mid, replies.reply_id, replies.replyto, " + + "replies.user_id, users.nick, users.banned, " + + "replies.ts, " + + "0 as readonly, 0 as privacy, 0 as replies, " + + "replies.attach, 0 as likes, 0 as hidden, " + + "NULL as tags, NULL as repliesby, replies.txt, " + + "IFNULL(qw.txt, t.txt) as q, " + + "NOW(), " + + "COALESCE(qw.user_id, m.user_id) as to_uid, COALESCE(qu.nick, mu.nick) as to_name " + + "FROM replies INNER JOIN users " + + "ON replies.user_id = users.id " + + "LEFT JOIN replies qw ON replies.message_id = qw.message_id and replies.replyto = qw.reply_id " + + "LEFT JOIN messages_txt t on replies.message_id = t.message_id " + + "LEFT JOIN messages m on replies.message_id = m.message_id " + + "LEFT JOIN users qu ON qw.user_id=qu.id " + + "LEFT JOIN users mu ON m.user_id=mu.id " + + "WHERE replies.message_id = :mid ORDER BY replies.reply_id ASC", + new MapSqlParameterSource("mid", mid), + new MessageMapper()); + if (replies.size() > 0) { + setLastReadComment(user, mid, replies.stream().map(Message::getRid).max(Comparator.naturalOrder()).get()); + } + return replies; + } + + @Transactional + @Override + public boolean setMessagePopular(final int mid, final int popular) { + int ret; + MapSqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("mid", mid) + .addValue("popular", popular); + + switch (popular) { + case -2: + ret = getNamedParameterJdbcTemplate().update( + "UPDATE messages SET hidden = 1 WHERE message_id = :mid", + sqlParameterSource); + break; + case -1: + sqlParameterSource.addValue("popular", 0); + default: + ret = getNamedParameterJdbcTemplate().update( + "UPDATE messages SET popular = :popular WHERE message_id = :mid", + sqlParameterSource); + break; + } + + if (popular == -1) + ret = getNamedParameterJdbcTemplate().update( + "INSERT INTO top_ignore_messages VALUES (:mid)", + sqlParameterSource); + + return ret > 0; + } + + @Transactional + @Override + public boolean setMessagePrivacy(final int mid) { + return getJdbcTemplate().update("UPDATE messages SET privacy=1 WHERE message_id=?", mid) > 0; + } + + @Transactional + @Override + public boolean deleteMessage(final int uid, final int mid) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("mid", mid) + .addValue("uid", uid); + + if (getNamedParameterJdbcTemplate().update( + "DELETE FROM messages WHERE message_id = :mid AND user_id = :uid", sqlParameterSource) > 0) { + + getNamedParameterJdbcTemplate().update("DELETE FROM messages_txt WHERE message_id = :mid", sqlParameterSource); + getNamedParameterJdbcTemplate().update("DELETE FROM replies WHERE message_id = :mid", sqlParameterSource); + getNamedParameterJdbcTemplate().update("DELETE FROM subscr_messages WHERE message_id = :mid", sqlParameterSource); + getNamedParameterJdbcTemplate().update("DELETE FROM messages_tags WHERE message_id = :mid", sqlParameterSource); + + return true; + } + return false; + } + @Transactional + @Override + public boolean deleteReply(final int uid, final int mid, final int rid) { + User author = getMessageAuthor(mid); + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("mid", mid) + .addValue("uid", uid) + .addValue("rid", rid); + boolean result; + if (author.getUid() == uid) { + result = getNamedParameterJdbcTemplate() + .update("DELETE FROM replies WHERE message_id=:mid AND reply_id=:rid", sqlParameterSource) > 0; + } else { + result = getNamedParameterJdbcTemplate() + .update("DELETE FROM replies WHERE message_id=:mid AND reply_id=:rid AND user_id=:uid" + , sqlParameterSource) > 0; + } + if (result) { + getNamedParameterJdbcTemplate().update("UPDATE messages SET replies=replies-1 WHERE message_id=:mid", sqlParameterSource); + updateRepliesBy(mid); + return true; + } + return false; + } + + @Transactional(readOnly = true) + @Override + public List getLastMessages(int hours) { + return getJdbcTemplate().queryForList("SELECT message_id FROM messages WHERE messages.ts>TIMESTAMPADD(HOUR,?,NOW())", + Integer.class, -hours); + + } + + @Transactional(readOnly = true) + @Override + public List getLastReplies(int hours) { + return getJdbcTemplate().query("SELECT users2.nick,replies.message_id,replies.reply_id," + + "users.nick,replies.txt," + + "replies.ts,replies.attach,replies.ts+0 " + + "FROM ((replies INNER JOIN users ON replies.user_id=users.id) " + + "INNER JOIN messages ON replies.message_id=messages.message_id) " + + "INNER JOIN users AS users2 ON messages.user_id=users2.id " + + "WHERE replies.ts>TIMESTAMPADD(HOUR,?,NOW()) AND messages.privacy>0", (rs, rowNum) -> { + ResponseReply reply = new ResponseReply(); + reply.setMuname(rs.getString(1)); + reply.setMid(rs.getInt(2)); + reply.setRid(rs.getInt(3)); + reply.setUname(rs.getString(4)); + reply.setDescription(rs.getString(5)); + reply.setPubDate(rs.getTimestamp(6)); + reply.setAttachmentType(rs.getString(7)); + return reply; + }, -hours); + } + @Transactional(readOnly = true) + @Override + public List getPopularCandidates() { + return getJdbcTemplate().queryForList("SELECT replies.message_id FROM replies " + + "INNER JOIN messages ON replies.message_id = messages.message_id " + + "LEFT JOIN messages_tags ON messages_tags.message_id = messages.message_id " + + "WHERE COALESCE(messages_tags.tag_id, 0) != 2 " + + "AND COALESCE(messages_tags.tag_id, 0) != 805 AND replies.ts > TIMESTAMPADD(HOUR, -2, CURRENT_TIMESTAMP) " + + "AND messages.popular=0 GROUP BY messages.message_id having COUNT(DISTINCT(replies.user_id)) > 5 " + + "UNION ALL SELECT favorites.message_id FROM favorites " + + "INNER JOIN messages ON messages.message_id = favorites.message_id " + + "LEFT JOIN messages_tags ON messages_tags.message_id = messages.message_id " + + "WHERE COALESCE(messages_tags.tag_id, 0) != 2 AND favorites.ts > TIMESTAMPADD(HOUR, -2, CURRENT_TIMESTAMP) " + + "AND messages.popular=0 GROUP BY messages.message_id HAVING COUNT(DISTINCT favorites.user_id) > 1;", Integer.class); + } + @Transactional + @Override + public void setLastReadComment(User user, Integer mid, Integer rid) { + jdbcTemplate.update("UPDATE subscr_messages SET last_read_rid=GREATEST(?, last_read_rid) WHERE message_id=? AND suser_id=?", + rid, mid, user.getUid()); + } + + @Override + public List getUnread(User user) { + return jdbcTemplate.queryForList( + "select subscr_messages.message_id " + + "from subscr_messages inner join messages on subscr_messages.message_id=messages.message_id " + + "where subscr_messages.suser_id=? and " + + "messages.replies>subscr_messages.last_read_rid", + Integer.class, user.getUid()); + } +} diff --git a/juick-server/src/main/java/com/juick/service/MessengerServiceImpl.java b/juick-server/src/main/java/com/juick/service/MessengerServiceImpl.java new file mode 100644 index 00000000..57101ffe --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/MessengerServiceImpl.java @@ -0,0 +1,71 @@ +package com.juick.service; + +import com.juick.User; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Repository +public class MessengerServiceImpl extends BaseJdbcService implements MessengerService { + + @Transactional(readOnly = true) + @Override + public Integer getUserId(String senderId) { + List list = getJdbcTemplate().queryForList( + "SELECT id FROM users INNER JOIN messenger " + + "ON messenger.user_id = users.id WHERE messenger.sender_id=?", Integer.class, senderId); + + return list.isEmpty() ? 0 : list.get(0); + } + @Transactional(readOnly = true) + @Override + public Optional getSenderId(User user) { + List list = getJdbcTemplate().queryForList( + "SELECT sender_id FROM messenger " + + "WHERE user_id=?", String.class, user.getUid()); + + return list.isEmpty() ? Optional.empty() : Optional.of(list.get(0)); + } + + @Transactional + @Override + public boolean createMessengerUser(String senderId, String displayName) { + return getJdbcTemplate().update( + "INSERT INTO messenger(sender_id, display_name, loginhash) VALUES(?,?,?)", + senderId, displayName, UUID.randomUUID().toString()) > 0; + } + @Transactional(readOnly = true) + @Override + public String getDisplayName(String hash) { + try { + return getJdbcTemplate().queryForObject("SELECT display_name FROM messenger WHERE loginhash=?", String.class, hash); + } catch (EmptyResultDataAccessException e) { + return null; + } + } + @Transactional + @Override + public String getSignUpHash(final String senderId, final String username) { + List list = getJdbcTemplate().queryForList( + "SELECT loginhash FROM messenger WHERE sender_id = ? AND user_id IS NULL", + String.class, + senderId); + + if (list.isEmpty()) { + String hash = UUID.randomUUID().toString(); + getJdbcTemplate().update( + "INSERT INTO messenger(sender_id, loginhash, display_name) VALUES (?, ?, ?)", senderId, hash, username); + return hash; + } + return list.get(0); + } + @Transactional + @Override + public boolean linkMessengerUser(String hash, int uid) { + return getJdbcTemplate().update("UPDATE messenger SET user_id=?, loginhash=NULL WHERE loginhash=?", uid, hash) > 0; + } +} diff --git a/juick-server/src/main/java/com/juick/service/PMQueriesServiceImpl.java b/juick-server/src/main/java/com/juick/service/PMQueriesServiceImpl.java new file mode 100644 index 00000000..b68e0236 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/PMQueriesServiceImpl.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import com.juick.User; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * Created by aalexeev on 11/13/16. + */ +@Repository +public class PMQueriesServiceImpl extends BaseJdbcService implements PMQueriesService { + + @Transactional + @Override + public boolean createPM(final int uidFrom, final int uid_to, final String body) { + boolean ret = getJdbcTemplate().update( + "INSERT INTO pm(user_id, user_id_to, txt) VALUES (?, ?, ?)", + uidFrom, uid_to, body) > 0; + + if (ret) { + try { + getJdbcTemplate().update( + "INSERT INTO pm_streams(user_id, user_id_to, lastmessage, unread) VALUES (?, ?, NOW(), 1)", + uidFrom, uid_to); + } catch (DuplicateKeyException e) { + // ignore + } + } + return ret; + } + + @Transactional + @Override + public boolean addPMinRoster(final int uid, final String jid) { + return getJdbcTemplate().update( + "INSERT INTO pm_inroster(user_id, jid) VALUES (?, ?) ON DUPLICATE KEY UPDATE user_id=user_id", uid, jid) > 0; + } + + @Transactional + @Override + public boolean removePMinRoster(final int uid, final String jid) { + return getJdbcTemplate().update( + "DELETE FROM pm_inroster WHERE user_id = ? AND jid = ?", uid, jid) > 0; + } + + @Transactional + @Override + public boolean havePMinRoster(final int uid, final String jid) { + List res = getJdbcTemplate().queryForList( + "SELECT 1 FROM pm_inroster WHERE user_id = ? AND jid = ?", + Integer.class, + uid, jid); + return res.size() > 0; + } + + @Transactional(readOnly = true) + @Override + public String getLastView(final int uidFrom, final int uidTo) { + List list = getJdbcTemplate().queryForList( + "SELECT lastview FROM pm_streams WHERE user_id = ? AND user_id_to = ?", + String.class, + uidFrom, uidTo); + + return list.isEmpty() ? + null : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public List getPMLastConversationsUsers(final int uid, final int cnt) { + return getJdbcTemplate().query( + "SELECT pm_streams.user_id, users.nick, pm_streams.unread FROM pm_streams " + + "INNER JOIN users ON users.id = pm_streams.user_id " + + "WHERE pm_streams.user_id_to=? " + + "ORDER BY pm_streams.unread DESC, pm_streams.lastmessage DESC LIMIT ?", + (rs, rowNum) -> { + com.juick.User u = new com.juick.User(); + u.setUid(rs.getInt(1)); + u.setName(rs.getString(2)); + u.setUnreadCount(rs.getInt(3)); + return u; + }, + uid, cnt); + } + + @Transactional + @Override + public List getPMMessages(final int uid, final int uidTo) { + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("uidTo", uidTo); + + List msgs = getNamedParameterJdbcTemplate().query( + "SELECT pm.user_id, pm.txt, pm.ts, users.nick FROM pm INNER JOIN users ON users.id=pm.user_id WHERE (user_id = :uid AND user_id_to = :uidTo) " + + "OR (user_id_to = :uid AND user_id = :uidTo) ORDER BY ts DESC LIMIT 20", + sqlParameterSource, + (rs, rowNum) -> { + com.juick.Message msg = new com.juick.Message(); + int uuid = rs.getInt(1); + User user = new User(); + user.setUid(uuid); + user.setName(rs.getString(4)); + msg.setUser(user); + msg.setText(rs.getString(2)); + msg.setTimestamp(rs.getTimestamp(3).toInstant()); + return msg; + }); + + getNamedParameterJdbcTemplate().update( + "UPDATE pm_streams SET lastview = NOW(), unread = 0 WHERE user_id_to = :uid AND user_id = :uidTo", + sqlParameterSource); + + return msgs; + } + + @Transactional(readOnly = true) + @Override + public List getLastPMInbox(final int uid) { + return getJdbcTemplate().query( + "SELECT pm.user_id, users.nick, pm.txt, pm.ts " + + "FROM pm INNER JOIN users ON pm.user_id=users.id WHERE pm.user_id_to=? ORDER BY pm.ts DESC LIMIT 20", + (rs, num) -> { + com.juick.Message msg = new com.juick.Message(); + msg.setUser(new User()); + msg.getUser().setUid(rs.getInt(1)); + msg.getUser().setName(rs.getString(2)); + msg.setText(rs.getString(3)); + msg.setTimestamp(rs.getTimestamp(4).toInstant()); + return msg; + }, + uid); + } + + @Transactional(readOnly = true) + @Override + public List getLastPMSent(final int uid) { + return getJdbcTemplate().query( + "SELECT pm.user_id_to, users.nick, pm.txt, " + + "pm.ts FROM pm INNER JOIN users ON pm.user_id_to=users.id " + + "WHERE pm.user_id=? ORDER BY pm.ts DESC LIMIT 20", + (rs, num) -> { + com.juick.Message msg = new com.juick.Message(); + msg.setUser(new User()); + msg.getUser().setUid(rs.getInt(1)); + msg.getUser().setName(rs.getString(2)); + msg.setText(rs.getString(3)); + msg.setTimestamp(rs.getTimestamp(4).toInstant()); + return msg; + }, + uid); + } +} diff --git a/juick-server/src/main/java/com/juick/service/PrivacyQueriesServiceImpl.java b/juick-server/src/main/java/com/juick/service/PrivacyQueriesServiceImpl.java new file mode 100644 index 00000000..9f9cda1d --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/PrivacyQueriesServiceImpl.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import com.juick.Tag; +import com.juick.User; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +/** + * Created by aalexeev on 11/13/16. + */ +@Repository +@Transactional +public class PrivacyQueriesServiceImpl extends BaseJdbcService implements PrivacyQueriesService { + + @Override + public PrivacyResult blacklistUser(final User user, final User target) { + int result = getJdbcTemplate().update( + "DELETE FROM bl_users WHERE user_id = ? AND bl_user_id = ?", + user.getUid(), target.getUid()); + + if (result > 0) + return PrivacyResult.Removed; + + getJdbcTemplate().update( + "INSERT INTO bl_users(user_id, bl_user_id) VALUES (?, ?)", + user.getUid(), target.getUid()); + + return PrivacyResult.Added; + } + + @Override + public PrivacyResult blacklistTag(final User user, final Tag tag) { + int result = getJdbcTemplate().update( + "DELETE FROM bl_tags WHERE user_id = ? AND tag_id = ?", + user.getUid(), tag.TID); + + if (result > 0) + return PrivacyResult.Removed; + + getJdbcTemplate().update( + "INSERT INTO bl_tags(user_id, tag_id) VALUES (?, ?)", + user.getUid(), tag.TID); + + return PrivacyResult.Added; + } +} diff --git a/juick-server/src/main/java/com/juick/service/PushQueriesServiceImpl.java b/juick-server/src/main/java/com/juick/service/PushQueriesServiceImpl.java new file mode 100644 index 00000000..7f97956c --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/PushQueriesServiceImpl.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import javax.inject.Inject; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Created by aalexeev on 11/13/16. + */ +@Repository +public class PushQueriesServiceImpl extends BaseJdbcService implements PushQueriesService { + + @Transactional(readOnly = true) + @Override + public List getGCMRegID(final int uid) { + return getJdbcTemplate().queryForList( + "SELECT regid FROM android WHERE user_id=?", + String.class, + uid); + } + + @Transactional(readOnly = true) + @Override + public List getGCMTokens(final Collection uids) { + if (CollectionUtils.isEmpty(uids)) + return Collections.emptyList(); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT regid FROM android INNER JOIN users ON (users.id = android.user_id) WHERE users.id IN (:ids)", + new MapSqlParameterSource("ids", uids), + String.class); + } + + @Transactional + @Override + public boolean addGCMToken(Integer uid, String token) { + return getJdbcTemplate().update("INSERT IGNORE INTO android(user_id,regid) VALUES (?, ?)", + uid, token) > 0; + } + + @Transactional + @Override + public boolean deleteGCMToken(String token) { + return getJdbcTemplate().update("DELETE FROM android WHERE regid=?", token) > 0; + } + + @Transactional(readOnly = true) + @Override + public List getMPNSURL(final int uid) { + return getJdbcTemplate().queryForList( + "SELECT url FROM winphone WHERE user_id=?", + String.class, + uid); + } + + @Transactional(readOnly = true) + @Override + public List getMPNSTokens(final Collection uids) { + if (CollectionUtils.isEmpty(uids)) + return Collections.emptyList(); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT url FROM winphone INNER JOIN users ON (users.id=winphone.user_id) WHERE users.id IN (:ids)", + new MapSqlParameterSource("ids", uids), + String.class); + } + + @Transactional + @Override + public boolean addMPNSToken(Integer uid, String token) { + return getJdbcTemplate().update("INSERT IGNORE INTO winphone(user_id,url) VALUES (?, ?)", + uid, token) > 0; + } + + @Transactional + @Override + public boolean deleteMPNSToken(String token) { + return getJdbcTemplate().update("DELETE FROM winphone WHERE url=?", token) > 0; + } + + @Transactional(readOnly = true) + @Override + public List getAPNSToken(final int uid) { + return getJdbcTemplate().queryForList( + "SELECT token from ios WHERE user_id=?", + String.class, + uid); + } + + @Transactional + @Override + public boolean deleteAPNSToken(String token) { + return getJdbcTemplate().update("DELETE FROM ios WHERE token=?", token) > 0; + } + + @Transactional(readOnly = true) + @Override + public List getAPNSTokens(final Collection uids) { + if (CollectionUtils.isEmpty(uids)) + return Collections.emptyList(); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT token FROM ios INNER JOIN users ON (users.id = ios.user_id) WHERE users.id IN (:ids)", + new MapSqlParameterSource("ids", uids), + String.class); + } + + @Transactional + @Override + public boolean addAPNSToken(Integer uid, String token) { + try { + return getJdbcTemplate().update("INSERT INTO ios(user_id,token) VALUES (?, ?)", + uid, token) > 0; + } catch (DuplicateKeyException e) { + return true; + } + } +} diff --git a/juick-server/src/main/java/com/juick/service/ShowQueriesServiceImpl.java b/juick-server/src/main/java/com/juick/service/ShowQueriesServiceImpl.java new file mode 100644 index 00000000..0fba35f1 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/ShowQueriesServiceImpl.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import com.juick.User; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.List; + +/** + * Created by aalexeev on 11/13/16. + */ +@Repository +@Transactional(readOnly = true) +public class ShowQueriesServiceImpl extends BaseJdbcService implements ShowQueriesService { + + @Override + public List getRecommendedUsers(final User forUser) { + if (forUser == null) + return Collections.emptyList(); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT u.nick FROM subscr_users su1 INNER JOIN users u " + + "ON su1.user_id = u.id " + + "WHERE NOT EXISTS (SELECT 1 FROM subscr_users su2 WHERE su2.suser_id = :uid and su1.user_id = su2.user_id) " + + "AND EXISTS (SELECT 1 FROM subscr_users su3 WHERE su3.suser_id = :uid and su3.user_id = su1.suser_id ) " + + "AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :uid and su1.user_id = b.bl_user_id) " + + "AND su1.user_id != :uid AND u.lastmessage > UNIX_TIMESTAMP() - 259200 " + + "GROUP BY su1.user_id ORDER BY count(*) DESC LIMIT 10", + new MapSqlParameterSource("uid", forUser.getUid()), + String.class); + } + + @Override + public List getTopUsers() { + return getJdbcTemplate().query( + "SELECT users.nick,COUNT(subscr_users.suser_id) AS cnt " + + "FROM (subscr_users INNER JOIN users ON subscr_users.user_id=users.id) " + + "INNER JOIN useroptions ON users.id=useroptions.user_id " + + "WHERE useroptions.privacy_view>0 AND users.lastmessage > UNIX_TIMESTAMP() - 259200 " + + "AND users.id!=2 GROUP BY subscr_users.user_id ORDER BY cnt DESC LIMIT 10", + (rs, rowNum) -> rs.getString(1)); + } +} diff --git a/juick-server/src/main/java/com/juick/service/SphinxSearchService.java b/juick-server/src/main/java/com/juick/service/SphinxSearchService.java new file mode 100644 index 00000000..f102ab47 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/SphinxSearchService.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Created by aalexeev on 11/18/16. + */ + +@Repository +@Transactional(readOnly = true) +public class SphinxSearchService extends BaseJdbcService implements SearchService { + private static final int DEFAULT_MAX_RESULT = 20; + + private int maxResult = DEFAULT_MAX_RESULT; + + @Override + public List searchInAllMessages(final String searchString, final int messageIdBefore) { + if (StringUtils.isBlank(searchString)) + return Collections.emptyList(); + + Map sphinxQuery = new HashMap<>(); + sphinxQuery.put("limit", String.valueOf(maxResult)); + sphinxQuery.put("mode", "any"); + sphinxQuery.put("sort", "extended:@id desc"); + if (messageIdBefore > 0) { + sphinxQuery.put("maxid", String.valueOf(messageIdBefore - 1)); + } + + return getJdbcTemplate().queryForList( + String.format("SELECT id FROM search WHERE query = '%s;%s'", searchString, + sphinxQuery.entrySet().stream().map(Object::toString) + .collect(Collectors.joining(";"))), Integer.class); + } + + @Override + public List searchByStringAndUser(final String searchString, final int userId, int messageIdBefore) { + if (StringUtils.isBlank(searchString)) + return Collections.emptyList(); + + Map sphinxQuery = new HashMap<>(); + sphinxQuery.put("limit", String.valueOf(maxResult)); + sphinxQuery.put("mode", "any"); + sphinxQuery.put("sort", "extended:@id desc"); + if (messageIdBefore > 0) { + sphinxQuery.put("maxid", String.valueOf(messageIdBefore - 1)); + } + return getJdbcTemplate().queryForList( + String.format("SELECT id FROM search WHERE query = '%s;%s;filter=user_id,%d'", searchString, + sphinxQuery.entrySet().stream().map(Object::toString) + .collect(Collectors.joining(";")), userId), Integer.class); + } + + @Override + public void setMaxResult(int maxResult) { + if (maxResult <= 0) + throw new IllegalArgumentException("maxResult value (" + maxResult + ") must be greater then 0"); + + this.maxResult = maxResult; + } +} \ No newline at end of file diff --git a/juick-server/src/main/java/com/juick/service/SubscriptionServiceImpl.java b/juick-server/src/main/java/com/juick/service/SubscriptionServiceImpl.java new file mode 100644 index 00000000..b97fc0a4 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/SubscriptionServiceImpl.java @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import com.juick.Message; +import com.juick.Tag; +import com.juick.User; +import com.juick.server.helpers.NotifyOpts; +import org.apache.commons.lang3.StringUtils; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; + +import javax.annotation.Nonnull; +import javax.inject.Inject; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Created by aalexeev on 11/13/16. + */ +@Repository +public class SubscriptionServiceImpl extends BaseJdbcService implements SubscriptionService { + @Inject + private UserService userService; + @Inject + private MessagesService messagesService; + @Inject + private TagService tagService; + + @Transactional(readOnly = true) + @Override + public List getJIDSubscribedToUser(final int uid, final boolean friendsonly) { + return getNamedParameterJdbcTemplate().queryForList( + "SELECT jids.jid FROM subscr_users INNER JOIN jids " + + "ON (subscr_users.user_id = :uid AND subscr_users.suser_id = jids.user_id) WHERE jids.active = 1 " + + (friendsonly ? + " AND EXISTS (SELECT 1 FROM wl_users w WHERE w.user_id = :uid and jids.user_id = w.wl_user_id)" : StringUtils.EMPTY), + new MapSqlParameterSource("uid", uid), + String.class); + } + + @Transactional(readOnly = true) + @Override + public List getSubscribedUsers(final int uid, final int mid) { + User author = messagesService.getMessageAuthor(mid); + + List userids = userService.getUserReaders(uid); + List tags = tagService.getMessageTagsIDs(mid); + List tagsStr = tagService.getMessageTags(mid).stream().map(t -> t.getTag().getName()).collect(Collectors.toList()); + + Set set = new HashSet<>(); + set.addAll( + userids.stream() + .map(User::getUid).filter(u -> Collections.disjoint(tagService.getUserBLTags(u), tagsStr)) + .collect(Collectors.toList())); + + + if (!tags.isEmpty()) { + List tagUsers = getNamedParameterJdbcTemplate().queryForList( + "SELECT st.suser_id FROM subscr_tags st " + + "WHERE st.tag_id IN (:ids) AND st.suser_id != :uid " + + " AND NOT EXISTS (SELECT 1 FROM bl_users bu WHERE bu.bl_user_id = :authorUid and st.suser_id = bu.user_id)" + + " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN (:ids) and st.suser_id = bt.user_id)", + new MapSqlParameterSource() + .addValue("ids", tags) + .addValue("uid", uid) + .addValue("authorUid", author.getUid()), + Integer.class); + set.addAll(tagUsers); + } + return userService.getUsersByID(set); + } + @Override + public List getUsersSubscribedToComments(@Nonnull final Message msg, @Nonnull final Message reply) { + return getUsersSubscribedToComments(msg, reply, false); + } + + @Transactional(readOnly = true) + @Override + public List getUsersSubscribedToComments(@Nonnull final Message msg, @Nonnull final Message reply, + boolean blacklisted) { + List userids = getJdbcTemplate().queryForList( + "SELECT suser_id FROM subscr_messages WHERE message_id=? AND suser_id!=?", + Integer.class, + msg.getMid(), reply.getUser().getUid()); + + if (!userids.isEmpty()) { + return userService.getUsersByID(userids.stream() + .filter(u -> blacklisted || !userService.isInBLAny(u, reply.getUser().getUid())) + .collect(Collectors.toList())); + } + return Collections.emptyList(); + } + + @Transactional(readOnly = true) + @Override + public List getUsersSubscribedToUserRecommendations(final int uid, final int mid, final int muid) { + List tags = tagService.getMessageTagsIDs(mid); + + String query = "SELECT s.suser_id FROM subscr_users s WHERE s.user_id = :uid " + + " AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.bl_user_id = :muid and b.user_id = s.user_id) " + + " AND NOT EXISTS (SELECT 1 FROM subscr_users s1 WHERE s1.user_id = :muid AND s.user_id = s1.suser_id) " + + " AND NOT EXISTS (SELECT 1 FROM subscr_messages sm WHERE sm.message_id = :mid AND s.user_id = sm.suser_id) " + + " AND NOT EXISTS (SELECT 1 FROM favorites WHERE favorites.message_id = :mid AND favorites.user_id = s.user_id) " + + " AND s.user_id NOT IN (SELECT s2.suser_id FROM subscr_users s2 " + + " INNER JOIN favorites f ON (f.message_id = :mid AND s2.user_id = f.user_id AND f.user_id != :uid))"; + + MapSqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("muid", muid) + .addValue("mid", mid); + + if (!tags.isEmpty()) { + sqlParameterSource.addValue("ids", tags); + query += " AND NOT EXISTS (SELECT 1 FROM subscr_tags st WHERE st.tag_id IN (:ids) AND s.user_id = st.suser_id) " + + " AND NOT EXISTS (SELECT 1 FROM bl_tags b WHERE b.tag_id IN (:ids) AND s.user_id = b.user_id)"; + } + + List userids = getNamedParameterJdbcTemplate().queryForList( + query, sqlParameterSource, Integer.class); + + return userService.getUsersByID(userids); + } + + @Transactional + @Override + public boolean subscribeMessage(final Message message, final User user) { + try { + boolean result = getJdbcTemplate().update( + "INSERT INTO subscr_messages(suser_id, message_id) VALUES (?, ?)", user.getUid(), message.getMid()) == 1; + messagesService.setLastReadComment(user, message.getMid(), message.getReplies()); + return result; + } catch (DuplicateKeyException e) { + return true; + } + } + + @Transactional + @Override + public boolean unSubscribeMessage(final int mid, final int vuid) { + return getJdbcTemplate().update( + "DELETE FROM subscr_messages WHERE message_id=? AND suser_id=?", mid, vuid) > 0; + } + + @Transactional + @Override + public boolean subscribeUser(final User user, final User toUser) { + try { + return getJdbcTemplate().update( + "INSERT INTO subscr_users(user_id,suser_id) VALUES (?,?)", toUser.getUid(), user.getUid()) == 1; + } catch (DuplicateKeyException e) { + return true; + } + } + + @Transactional + @Override + public boolean unSubscribeUser(final User user, final User fromUser) { + return getJdbcTemplate().update( + "DELETE FROM subscr_users WHERE suser_id=? AND user_id=?", user.getUid(), fromUser.getUid()) > 0; + } + + @Transactional + @Override + public boolean subscribeTag(final User user, final Tag toTag) { + try { + + return getJdbcTemplate().update( + "INSERT INTO subscr_tags(tag_id,suser_id) VALUES (?,?)", toTag.TID, user.getUid()) == 1; + } catch (DuplicateKeyException e) { + return true; + } + } + + @Transactional + @Override + public boolean unSubscribeTag(final User user, final Tag toTag) { + return getJdbcTemplate().update( + "DELETE FROM subscr_tags WHERE tag_id=? AND suser_id=?", toTag.TID, user.getUid()) > 0; + } + + @Transactional(readOnly = true) + @Override + public List getSubscribedTags(User user) { + return getJdbcTemplate().queryForList("SELECT tags.name FROM subscr_tags INNER JOIN tags " + + "ON(tags.tag_id = subscr_tags.tag_id) " + + "WHERE subscr_tags.suser_id=? ORDER BY tags.name", String.class, user.getUid()); + } + + @Transactional(readOnly = true) + @Override + public NotifyOpts getNotifyOptions(final User user) { + List list = getJdbcTemplate().query( + "SELECT jnotify,subscr_notify,recommendations FROM useroptions WHERE user_id=?", + (rs, num) -> { + NotifyOpts options = new NotifyOpts(); + options.setRepliesEnabled(rs.getInt(1) > 0); + options.setSubscriptionsEnabled(rs.getInt(2) > 0); + options.setRecommendationsEnabled(rs.getInt(3) > 0); + return options; + }, + user.getUid()); + + return list.isEmpty() ? + new NotifyOpts() : list.get(0); + } + + @Transactional + @Override + public boolean setNotifyOptions(final User user, final NotifyOpts options) { + int jnotify = getJdbcTemplate().update( + "UPDATE useroptions SET jnotify=? WHERE user_id=?", + options.isRepliesEnabled() ? 1 : 0, + user.getUid()); + + int subscr_notify = getJdbcTemplate().update( + "UPDATE useroptions SET subscr_notify=? WHERE user_id=?", + options.isSubscriptionsEnabled() ? 1 : 0, + user.getUid()); + + int recommendations = getJdbcTemplate().update( + "UPDATE useroptions SET recommendations=? WHERE user_id=?", + options.isRecommendationsEnabled() ? 1 : 0, + user.getUid()); + + return jnotify > 0 && subscr_notify > 0 && recommendations > 0; + } +} diff --git a/juick-server/src/main/java/com/juick/service/TagServiceImpl.java b/juick-server/src/main/java/com/juick/service/TagServiceImpl.java new file mode 100644 index 00000000..524ad32d --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/TagServiceImpl.java @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import com.juick.Tag; +import com.juick.User; +import com.juick.server.helpers.TagStats; +import com.juick.util.StreamUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +/** + * Created by aalexeev on 11/13/16. + */ +@Repository +public class TagServiceImpl extends BaseJdbcService implements TagService { + + @Transactional(readOnly = true) + @Override + public com.juick.Tag getTag(final int tid) { + List list = getJdbcTemplate().query( + "SELECT synonym_id,name FROM tags WHERE tag_id=?", + (rs, num) -> { + Tag ret = new Tag(rs.getString(2)); + ret.TID = tid; + ret.SynonymID = rs.getInt(1); + return ret; + }, + tid); + + return list.isEmpty() ? + null : list.get(0); + } + + @Transactional + @Override + public com.juick.Tag getTag(final String tag, final boolean autoCreate) { + if (StringUtils.isBlank(tag)) + return null; + + List list = getJdbcTemplate().query( + "SELECT tag_id, synonym_id, name FROM tags WHERE name = ?", + (rs, rowNum) -> { + Tag ret1 = new Tag(rs.getString(3)); + ret1.TID = rs.getInt(1); + ret1.SynonymID = rs.getInt(2); + return ret1; + }, + tag); + + Tag ret = list.isEmpty() ? + null : list.get(0); + + if (ret == null && autoCreate) { + ret = new com.juick.Tag(tag); + ret.TID = createTag(tag); + } + + return ret; + } + + @Override + public List getTags(Stream tags, final boolean autoCreate) { + return tags.filter(StringUtils::isNotBlank).map(tag -> getTag(tag, autoCreate)).filter(Objects::nonNull).distinct() + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public boolean getTagNoIndex(final int tagId) { + List list = getJdbcTemplate().queryForList( + "SELECT noindex FROM tags WHERE tag_id=?", Integer.class, tagId); + + return !list.isEmpty() && list.get(0) == 1; + } + + @Transactional + @Override + public int createTag(final String name) { + KeyHolder holder = new GeneratedKeyHolder(); + getJdbcTemplate().update( + con -> { + PreparedStatement stmt = con.prepareStatement( + "INSERT INTO tags(name) VALUES (?)", + Statement.RETURN_GENERATED_KEYS); + stmt.setString(1, name); + return stmt; + }, + holder); + + return holder.getKey().intValue(); + } + + private class TagStatsMapper implements RowMapper { + + @Override + public TagStats mapRow(ResultSet rs, int rowNum) throws SQLException { + Tag t = new Tag(rs.getString(1)); + TagStats s = new TagStats(); + s.setTag(t); + s.setUsageCount(rs.getInt(2)); + return s; + } + } + + @Transactional(readOnly = true) + @Override + public List getUserTagStats(final int uid) { + return getJdbcTemplate().query( + "SELECT tags.name,COUNT(messages.message_id) " + + "FROM (messages INNER JOIN messages_tags ON (messages.user_id=? " + + "AND messages.message_id=messages_tags.message_id)) " + + "INNER JOIN tags ON messages_tags.tag_id=tags.tag_id GROUP BY tags.tag_id ORDER BY tags.name ASC", + new TagStatsMapper(), + uid); + } + + @Transactional(readOnly = true) + @Override + public List getUserBLTags(final int uid) { + return getJdbcTemplate().queryForList( + "SELECT tags.name FROM tags INNER JOIN bl_tags " + + "ON (bl_tags.user_id = ? AND bl_tags.tag_id = tags.tag_id) ORDER BY tags.name", + String.class, uid); + } + + @Transactional(readOnly = true) + @Override + public List getPopularTags() { + return getJdbcTemplate().queryForList( + "select name from tags where noindex=0 order by stat_messages desc limit 20", String.class); + } + + @Transactional(readOnly = true) + @Override + public List getTagStats() { + return getJdbcTemplate().query( + "SELECT tags.name,COUNT(DISTINCT messages.user_id) AS cnt " + + "FROM (messages INNER JOIN messages_tags ON (messages.ts>TIMESTAMPADD(DAY,-3,NOW()) " + + "AND messages.message_id=messages_tags.message_id)) " + + "INNER JOIN tags ON messages_tags.tag_id=tags.tag_id " + + "WHERE tags.tag_id NOT IN (SELECT tag_id FROM tags_ignore) " + + "GROUP BY tags.tag_id ORDER BY cnt DESC LIMIT 20", new TagStatsMapper()); + } + + @Transactional + @Override + public List updateTags(final int mid, final Collection newTags) { + List currentTags = getMessageTags(mid).stream() + .map(TagStats::getTag).collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(newTags)) + return currentTags; + + List idsForDelete = newTags.stream() + .filter(currentTags::contains) + .map(tag -> tag.TID) + .collect(Collectors.toList()); + if (newTags.size() - idsForDelete.size() >= 5) { + return currentTags; + } + + if (!idsForDelete.isEmpty()) + getNamedParameterJdbcTemplate().update( + "DELETE FROM messages_tags WHERE message_id = :mid AND tag_id in (:ids)", + new MapSqlParameterSource().addValue("ids", idsForDelete).addValue("mid", mid)); + + newTags.stream().filter(t -> !currentTags.contains(t)) + .forEach(t -> getJdbcTemplate().update("INSERT INTO messages_tags(message_id,tag_id) VALUES (?,?)", mid, t.TID)); + + List result = getMessageTags(mid).stream() + .map(TagStats::getTag).collect(Collectors.toList()); + jdbcTemplate.update("UPDATE messages_txt SET tags=? WHERE message_id=?", result.stream() + .map(Tag::getName).collect(Collectors.joining(" ")), mid); + return result; + } + + @Override + public List fromString(final String txt) { + String firstLine = txt.split("\\n", 2)[0]; + return StreamUtils.takeWhile(Arrays.stream(firstLine.split("\\ ")), + t -> !t.equals("*") && t.startsWith("*")) + .map(t -> getTag(t.substring(1), true)) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public List getMessageTags(final int mid) { + return getJdbcTemplate().query( + "SELECT tags.tag_id,synonym_id,name,stat_messages FROM tags " + + "INNER JOIN messages_tags ON (messages_tags.message_id = ? AND messages_tags.tag_id = tags.tag_id)", + (rs, num) -> { + com.juick.Tag t = new com.juick.Tag(rs.getString(3)); + t.TID = rs.getInt(1); + t.SynonymID = rs.getInt(2); + TagStats s = new TagStats(); + s.setTag(t); + s.setUsageCount(rs.getInt(4)); + return s; + }, mid); + } + + @Transactional(readOnly = true) + @Override + public List getMessageTagsIDs(final int mid) { + return getJdbcTemplate().queryForList( + "SELECT tag_id FROM messages_tags WHERE message_id = ?", + Integer.class, mid); + } + + @Override + public boolean blacklistTag(User user, Tag tag) { + int rowcount = getNamedParameterJdbcTemplate().update("DELETE FROM bl_tags WHERE tag_id = :tid AND user_id = :uid", + new MapSqlParameterSource().addValue("tid", tag.TID).addValue("uid", user.getUid())); + return rowcount <= 0 && getNamedParameterJdbcTemplate() + .update("INSERT INTO bl_tags(user_id, tag_id) VALUES(:uid,:tid)", + new MapSqlParameterSource().addValue("tid", tag.TID) + .addValue("uid", user.getUid())) > 0; + } + + @Transactional(readOnly = true) + @Override + public boolean isInBL(User user, Tag tag) { + List list = getJdbcTemplate().queryForList( + "SELECT 1 FROM bl_tags WHERE user_id = ? AND tag_id = ?", + Integer.class, user.getUid(), tag.TID); + return !list.isEmpty() && list.get(0) == 1; + } + + @Transactional(readOnly = true) + @Override + public boolean isSubscribed(User user, Tag tag) { + List list = getJdbcTemplate().queryForList( + "SELECT 1 FROM subscr_tags WHERE suser_id = ? AND tag_id = ?", + Integer.class, user.getUid(), tag.TID); + return !list.isEmpty() && list.get(0) == 1; + } + +} diff --git a/juick-server/src/main/java/com/juick/service/TelegramServiceImpl.java b/juick-server/src/main/java/com/juick/service/TelegramServiceImpl.java new file mode 100644 index 00000000..4e37bfac --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/TelegramServiceImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import com.juick.User; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * Created by vt on 24/11/2016. + */ +@Repository +public class TelegramServiceImpl extends BaseJdbcService implements TelegramService { + + @Transactional + @Override + public boolean addChat(final Long id) { + try { + return getJdbcTemplate().update("INSERT INTO telegram_chats(chat_id) VALUES(?)", id) > 0; + } catch (DuplicateKeyException e) { + return true; + } + } + + @Transactional + @Override + public boolean deleteChat(Long id) { + return getJdbcTemplate().update("DELETE FROM telegram_chats WHERE chat_id=?", id) > 0; + } + + @Transactional(readOnly = true) + @Override + public List getChats() { + return getJdbcTemplate().queryForList("SELECT chat_id FROM telegram_chats", Long.class); + } + + @Transactional(readOnly = true) + @Override + public int getUser(final long tgId) { + List list = getJdbcTemplate().queryForList( + "SELECT id FROM users INNER JOIN telegram " + + "ON telegram.user_id = users.id WHERE telegram.tg_id=?", Integer.class, tgId); + + return list.isEmpty() ? 0 : list.get(0); + } + + @Transactional + @Override + public boolean createTelegramUser(final long tgID, final String tgName) { + return getJdbcTemplate().update( + "INSERT INTO telegram(tg_id, tg_name, loginhash) VALUES(?,?,?)", + tgID, tgName, UUID.randomUUID().toString()) > 0; + } + + @Transactional + @Override + public boolean deleteTelegramUser(Integer uid) { + return getJdbcTemplate().update("DELETE FROM telegram WHERE user_id=?", uid) > 0; + } + + @Transactional(readOnly = true) + @Override + public List getTelegramIdentifiers(List users) { + List uids = users.stream().map(User::getUid).collect(Collectors.toList()); + if (uids.isEmpty()) { + return Collections.emptyList(); + } + return getNamedParameterJdbcTemplate().queryForList("" + + "SELECT tg_id FROM telegram WHERE user_id IN(:uids)", new MapSqlParameterSource() + .addValue("uids", uids), Long.class); + } +} diff --git a/juick-server/src/main/java/com/juick/service/UserServiceImpl.java b/juick-server/src/main/java/com/juick/service/UserServiceImpl.java new file mode 100644 index 00000000..a0a07fb3 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/UserServiceImpl.java @@ -0,0 +1,689 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service; + +import com.juick.User; +import com.juick.server.helpers.AnonymousUser; +import com.juick.server.helpers.Auth; +import com.juick.server.helpers.UserInfo; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.*; + +/** + * Created by aalexeev on 11/13/16. + */ +@Repository +public class UserServiceImpl extends BaseJdbcService implements UserService { + + private class UserMapper implements RowMapper { + @Override + public User mapRow(ResultSet rs, int rowNum) throws SQLException { + User user = new User(); + + user.setUid(rs.getInt(1)); + user.setName(rs.getString(2)); + user.setBanned(rs.getBoolean(3)); + user.setLang(rs.getString(4)); + + return user; + } + } + + @Transactional + @Override + public String getSignUpHashByJID(final String jid) { + List list = getJdbcTemplate().queryForList( + "SELECT loginhash FROM jids WHERE jid = ? AND user_id IS NULL", String.class, jid); + + if (list.isEmpty()) { + String hash = UUID.randomUUID().toString(); + getJdbcTemplate().update("INSERT INTO jids(jid, loginhash) VALUES (?, ?)", jid, hash); + return hash; + } + return list.get(0); + } + + @Transactional + @Override + public String getSignUpHashByTelegramID(final Long telegramId, final String username) { + List list = getJdbcTemplate().queryForList( + "SELECT loginhash FROM telegram WHERE tg_id = ? AND user_id IS NULL", + String.class, + telegramId); + + if (list.isEmpty()) { + String hash = UUID.randomUUID().toString(); + getJdbcTemplate().update( + "INSERT INTO telegram(tg_id, loginhash, tg_name) VALUES (?, ?, ?)", telegramId, hash, username); + return hash; + } + return list.get(0); + } + + @Transactional + @Override + public int createUser(final String username, final String password) { + KeyHolder holder = new GeneratedKeyHolder(); + try { + getJdbcTemplate().update( + con -> { + PreparedStatement stmt = con.prepareStatement( + "INSERT INTO users(nick,passw) VALUES (?,?)", + Statement.RETURN_GENERATED_KEYS); + stmt.setString(1, username); + stmt.setString(2, password); + return stmt; + }, + holder); + } catch (DuplicateKeyException e) { + return -1; + } + + int uid = holder.getKey().intValue(); + + getJdbcTemplate().update("INSERT INTO useroptions(user_id) VALUES (?)", uid); + getJdbcTemplate().update("INSERT INTO subscr_users(user_id, suser_id) VALUES (2, ?)", uid); + + return uid; + } + + @Transactional(readOnly = true) + @Override + public Optional getUserByUID(final int uid) { + List list = getJdbcTemplate().query( + "SELECT id, nick, banned, lang FROM users WHERE id = ?", new UserMapper(), uid); + + return list.isEmpty() ? Optional.empty() : Optional.of(list.get(0)); + } + + @Transactional(readOnly = true) + @Override + public User getUserByName(final String username) { + if (StringUtils.isNotBlank(username)) { + List list = getJdbcTemplate().query( + "SELECT id, nick, banned, lang FROM users WHERE nick = ?", new UserMapper(), username); + + if (!list.isEmpty()) + return list.get(0); + } + // TODO: @NonNullable ? + return AnonymousUser.INSTANCE; + } + + @Override + // No need marks with @Transactional annotation + public User getFullyUserByName(final String username) { + if (StringUtils.isNotBlank(username)) { + List list = getFullyUsersByNames(Collections.singletonList(username)); + if (!list.isEmpty()) + return list.get(0); + } + return null; + } + + @Override + @Transactional(readOnly = true) + public User getUserByEmail(String email) { + if (StringUtils.isNotBlank(email)) { + List list = getJdbcTemplate().query( + "SELECT id, nick, banned, lang FROM users WHERE id = (SELECT DISTINCT user_id FROM emails WHERE email = ?)", + new UserMapper(), + email); + + if (!list.isEmpty()) + return list.get(0); + } + return AnonymousUser.INSTANCE; + } + + @Transactional(readOnly = true) + @Override + public List getFullyUsersByNames(final Collection usernames) { + if (CollectionUtils.isEmpty(usernames)) + return Collections.emptyList(); + + return getNamedParameterJdbcTemplate().query( + "SELECT id, nick, passw, lang, banned FROM users WHERE nick in (:names)", + new MapSqlParameterSource("names", usernames), + (rs, rowNum) -> { + User user = new User(); + + user.setUid(rs.getInt(1)); + user.setName(rs.getString(2)); + user.setCredentials(rs.getString(3)); + user.setLang(rs.getString(4)); + user.setBanned(rs.getBoolean(5)); + + return user; + }); + } + + @Transactional(readOnly = true) + @Override + public User getUserByJID(final String jid) { + User result = null; + + if (StringUtils.isNotBlank(jid)) { + List list = getJdbcTemplate().query( + "SELECT id, nick, banned, lang FROM users WHERE id = (SELECT user_id FROM jids WHERE jid = ?)", + new UserMapper(), + jid); + + if (!list.isEmpty()) + result = list.get(0); + } + return result; + } + + @Transactional(readOnly = true) + @Override + public List getUsersByName(final Collection unames) { + if (CollectionUtils.isEmpty(unames)) + return Collections.emptyList(); + + return getNamedParameterJdbcTemplate().query( + "SELECT id, nick, banned, lang FROM users WHERE nick IN (:unames)", + new MapSqlParameterSource("unames", unames), + new UserMapper()); + } + + @Transactional(readOnly = true) + @Override + public List getUsersByID(final Collection uids) { + if (CollectionUtils.isEmpty(uids)) + return Collections.emptyList(); + + return getNamedParameterJdbcTemplate().query( + "SELECT id, nick, banned, lang FROM users WHERE id IN (:ids)", + new MapSqlParameterSource("ids", uids), + new UserMapper()); + } + + @Transactional(readOnly = true) + @Override + public List getJIDsbyUID(final int uid) { + return getJdbcTemplate().queryForList("SELECT jid FROM jids WHERE user_id = ? AND active = 1", String.class, uid); + } + + @Transactional(readOnly = true) + @Override + public int getUIDbyJID(final String jid) { + if (StringUtils.isNotBlank(jid)) { + List list = getJdbcTemplate().queryForList( + "SELECT user_id FROM jids WHERE jid = ?", Integer.class, jid); + + if (!list.isEmpty()) + return list.get(0); + } + return 0; + } + + @Transactional(readOnly = true) + @Override + public int getUIDbyName(final String uname) { + if (StringUtils.isNotBlank(uname)) { + List list = getJdbcTemplate().queryForList( + "SELECT id FROM users WHERE nick = ?", Integer.class, uname); + + if (!list.isEmpty()) + return list.get(0); + } + return 0; + } + + @Transactional(readOnly = true) + @Override + public int getUIDbyHash(final String hash) { + if (StringUtils.isNotBlank(hash)) { + List list = getJdbcTemplate().queryForList( + "SELECT user_id FROM logins WHERE hash = ?", Integer.class, hash); + + if (!list.isEmpty()) + return list.get(0); + } + return 0; + } + + @Transactional(readOnly = true) + @Override + public com.juick.User getUserByHash(final String hash) { + if (StringUtils.isNotBlank(hash)) { + List list = getJdbcTemplate().query( + "SELECT logins.user_id, users.nick, users.banned, users.lang FROM logins " + + "INNER JOIN users ON logins.user_id = users.id WHERE logins.hash = ?", + new UserMapper(), + hash); + + if (!list.isEmpty()) { + User user = list.get(0); + user.setAuthHash(hash); + return user; + } + } + return AnonymousUser.INSTANCE; + } + + @Transactional + @Override + public String getHashByUID(final int uid) { + List list = getJdbcTemplate().queryForList( + "SELECT hash FROM logins WHERE user_id = ?", String.class, uid); + + if (list.isEmpty()) { + String hash = RandomStringUtils.randomAlphanumeric(16).toUpperCase(); + getJdbcTemplate().update("INSERT INTO logins(user_id, hash) VALUES (?, ?)", uid, hash); + return hash; + } + return list.get(0); + } + + @Override + public int getUIDByHttpAuth(String auth) { + if (auth != null && auth.length() > 8 && auth.startsWith("Basic ")) { + Base64.Decoder dec = Base64.getDecoder(); + String loginpassw[] = new String(dec.decode(auth.substring(6))).split(":", 2); + if (loginpassw.length == 2 && loginpassw[0].length() > 1 && loginpassw[0].length() < 16 && loginpassw[0].matches("[a-zA-Z0-9\\-]+") && !loginpassw[1].isEmpty()) { + return checkPassword(loginpassw[0], loginpassw[1]); + } + } + return 0; + } + + @Transactional(readOnly = true) + @Override + public int checkPassword(final String username, final String password) { + if (StringUtils.isNotBlank(username)) { + List list = getJdbcTemplate().query( + "SELECT id, nick, banned, passw FROM users WHERE nick = ?", + (rs, rowNum) -> { + User user = new User(); + user.setUid(rs.getInt(1)); + user.setName(rs.getString(2)); + user.setBanned(rs.getBoolean(3)); + user.setCredentials(rs.getString(4)); + return user; + }, + username); + + if (!list.isEmpty()) { + User user = list.get(0); + if (Objects.equals(password, user.getCredentials())) + return user.getUid(); + } + } + return -1; + } + + @Transactional + @Override + public boolean updatePassword(final User user, final String newPassword) { + return user != null && + user.getUid() > 0 && + getJdbcTemplate().update("UPDATE users SET passw = ? WHERE id = ?", newPassword, user.getUid()) > 0; + } + + @Transactional(readOnly = true) + @Override + public int getUserOptionInt(final int uid, final String option, final int defaultValue) { + if (StringUtils.isBlank(option)) + return defaultValue; + + List list = getJdbcTemplate().queryForList( + "SELECT " + option + " FROM useroptions WHERE user_id = ?", Integer.class, uid); + + return list.isEmpty() ? defaultValue : list.get(0); + } + + @Transactional + @Override + public int setUserOptionInt(final int uid, final String option, final int value) { + if (StringUtils.isBlank(option)) + return 0; + + return getJdbcTemplate().update("UPDATE useroptions SET " + option + "= ? WHERE user_id = ?", value, uid); + } + + @Transactional(readOnly = true) + @Override + public UserInfo getUserInfo(final User user) { + List list = getJdbcTemplate().query( + "SELECT fullname, country, url, descr FROM usersinfo WHERE user_id = ?", + ((rs, rowNum) -> { + UserInfo info = new UserInfo(); + info.setFullName(rs.getString(1)); + info.setCountry(rs.getString(2)); + info.setUrl(rs.getString(3)); + info.setDescription(rs.getString(4)); + return info; + }), + user.getUid()); + + return list.isEmpty() ? new UserInfo() : list.get(0); + } + + @Transactional + @Override + public boolean updateUserInfo(final User user, final UserInfo info) { + return getJdbcTemplate().update( + "INSERT INTO usersinfo(user_id, fullname, country, url, descr) VALUES (?, ?, ?, ?, ?) " + + "ON DUPLICATE KEY UPDATE fullname = ?, country = ?, url = ?, descr = ?", + user.getUid(), + info.getFullName(), + info.getCountry(), + info.getUrl(), + info.getDescription(), + info.getFullName(), + info.getCountry(), + info.getUrl(), + info.getDescription()) > 0; + } + + @Transactional(readOnly = true) + @Override + public boolean getCanMedia(final int uid) { + List list = getJdbcTemplate().queryForList( + "SELECT users.lastphoto - UNIX_TIMESTAMP() FROM users WHERE id = ?", + Integer.class, + uid); + + return !list.isEmpty() && list.get(0) < 3600; + } + + @Transactional(readOnly = true) + @Override + public boolean isInWL(final int uid, final int check) { + List list = getJdbcTemplate().queryForList( + "SELECT 1 FROM wl_users WHERE user_id = ? AND wl_user_id = ?", + Integer.class, uid, check); + + return !list.isEmpty() && list.get(0) == 1; + } + + @Transactional(readOnly = true) + @Override + public boolean isInBL(final int uid, final int check) { + List list = getJdbcTemplate().queryForList( + "SELECT 1 FROM bl_users WHERE user_id = ? AND bl_user_id = ?", Integer.class, uid, check); + + return !list.isEmpty() && list.get(0) == 1; + } + + @Transactional(readOnly = true) + @Override + public boolean isInBLAny(final int uid, final int uid2) { + List list = getJdbcTemplate().queryForList( + "SELECT 1 FROM bl_users WHERE (user_id = ? AND bl_user_id = ?) " + + "OR (user_id = ? AND bl_user_id = ?)", + new Object[]{uid, uid2, uid2, uid}, + Integer.class); + + return !list.isEmpty() && list.get(0) == 1; + } + + @Transactional(readOnly = true) + @Override + public List checkBL(final int visitor, final Collection uids) { + if (CollectionUtils.isEmpty(uids)) + return Collections.emptyList(); + + return getNamedParameterJdbcTemplate().queryForList( + "SELECT user_id FROM bl_users WHERE bl_user_id = :visitor and user_id IN (:ids)", + new MapSqlParameterSource() + .addValue("visitor", visitor) + .addValue("ids", uids), + Integer.class); + } + + @Transactional(readOnly = true) + @Override + public boolean isSubscribed(final int uid, final int check) { + List list = getJdbcTemplate().queryForList( + "SELECT 1 FROM subscr_users WHERE suser_id = ? AND user_id = ?", + Integer.class, uid, check); + + return !list.isEmpty() && list.get(0) == 1; + } + + @Transactional(readOnly = true) + @Override + public List getUserRead(final int uid) { + return getJdbcTemplate().queryForList( + "SELECT user_id FROM subscr_users WHERE suser_id=?", Integer.class, uid); + } + + @Transactional(readOnly = true) + @Override + public List getUserReadLeastPopular(final int uid, final int cnt) { + return getJdbcTemplate().query( + "SELECT users.id,users.nick FROM (subscr_users " + + "INNER JOIN users_subscr ON (subscr_users.suser_id=? " + + "AND subscr_users.user_id=users_subscr.user_id)) INNER JOIN users " + + "ON subscr_users.user_id=users.id ORDER BY cnt LIMIT ?", + (rs, num) -> { + com.juick.User u = new com.juick.User(); + u.setUid(rs.getInt(1)); + u.setName(rs.getString(2)); + return u; + }, + uid, + cnt); + } + + @Transactional(readOnly = true) + @Override + public List getUserReaders(final int uid) { + return getJdbcTemplate().query( + "SELECT users.id, users.nick FROM subscr_users " + + "INNER JOIN users ON subscr_users.suser_id=users.id " + + "WHERE subscr_users.user_id=? ORDER BY users.nick", + (rs, num) -> { + com.juick.User u = new com.juick.User(); + u.setUid(rs.getInt(1)); + u.setName(rs.getString(2)); + return u; + }, + uid); + } + + @Transactional(readOnly = true) + @Override + public List getUserFriends(final int uid) { + return getJdbcTemplate().query( + "SELECT users.id,users.nick FROM subscr_users " + + "INNER JOIN users ON subscr_users.user_id=users.id " + + "WHERE subscr_users.suser_id=? AND users.id!=? " + + "ORDER BY users.nick", + (rs, num) -> { + com.juick.User u = new com.juick.User(); + u.setUid(rs.getInt(1)); + u.setName(rs.getString(2)); + return u; + }, + uid, + uid); + } + + @Transactional(readOnly = true) + @Override + public List getUserBLUsers(final int uid) { + return getJdbcTemplate().query("SELECT users.id,users.nick FROM users INNER JOIN bl_users " + + "ON(bl_users.bl_user_id=users.id) WHERE bl_users.user_id=? ORDER BY users.nick", + (rs, num) -> { + com.juick.User u = new com.juick.User(); + u.setUid(rs.getInt(1)); + u.setName(rs.getString(2)); + return u; + }, uid); + } + + @Transactional + @Override + public boolean linkTwitterAccount( + final User user, final String accessToken, final String accessTokenSecret, final String screenName) { + if (getJdbcTemplate().update("INSERT INTO twitter(user_id,access_token,access_token_secret,uname) " + + "VALUES (?,?,?,?)" + + " ON DUPLICATE KEY UPDATE access_token=?,access_token_secret=?,uname=?", + user.getUid(), accessToken, accessTokenSecret, screenName, accessToken, accessTokenSecret, screenName) > 0) { + return getJdbcTemplate().update("INSERT INTO subscr_users(user_id,suser_id,jid) " + + "VALUES (?,1741,'juick\\@twitter.juick.com')", user.getUid()) > 0; + } + return false; + + } + + @Transactional(readOnly = true) + @Override + public int getStatsIRead(final int uid) { + List list = getJdbcTemplate().queryForList( + "SELECT COUNT(*) FROM subscr_users WHERE suser_id = ?", Integer.class, uid); + return list.isEmpty() ? 0 : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public int getStatsMyReaders(final int uid) { + List list = getJdbcTemplate().queryForList("SELECT COUNT(*) FROM subscr_users WHERE user_id = ?", Integer.class, uid); + return list.isEmpty() ? 0 : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public int getStatsMessages(final int uid) { + List list = getJdbcTemplate().queryForList("SELECT COUNT(*) FROM messages WHERE user_id = ?", Integer.class, uid); + return list.isEmpty() ? 0 : list.get(0); + } + + @Transactional(readOnly = true) + @Override + public int getStatsReplies(final int uid) { + List list = getJdbcTemplate().queryForList("SELECT COUNT(*) FROM replies WHERE user_id = ?", Integer.class, uid); + return list.isEmpty() ? 0 : list.get(0); + } + + @Transactional + @Override + public boolean setActiveStatusForJID(final String JID, final UserService.ActiveStatus jidStatus) { + User user = getUserByJID(JID); + if (user != null) { + int newStatus = jidStatus == UserService.ActiveStatus.Active ? 1 : 0; + return getJdbcTemplate().update( + "UPDATE jids SET active = ? WHERE user_id = ? AND jid = ?", + newStatus, user.getUid(), JID) >= 0; + } + return false; + } + + @Transactional(readOnly = true) + @Override + public List getAllJIDs(final User user) { + return getJdbcTemplate().queryForList( + "SELECT jid FROM jids WHERE user_id=?", String.class, user.getUid()); + } + + @Transactional(readOnly = true) + @Override + public List getAuthCodes(final User user) { + return getJdbcTemplate().query( + "SELECT account,authcode FROM auth WHERE user_id=? AND protocol='xmpp'", + (rs, num) -> new Auth(rs.getString(1), rs.getString(2)), + user.getUid()); + } + + @Transactional(readOnly = true) + @Override + public List getEmails(final User user) { + return getJdbcTemplate().queryForList("SELECT email FROM emails WHERE user_id=?", String.class, user.getUid()); + } + + @Transactional(readOnly = true) + @Override + public String getEmailHash(final User user) { + List list = getJdbcTemplate().queryForList( + "SELECT hash FROM mail WHERE user_id = ?", + String.class, + user.getUid()); + return list.isEmpty() ? StringUtils.EMPTY : list.get(0) + "@mail.juick.com"; + } + + @Transactional + @Override + public int deleteLoginForUser(final String name) { + if (StringUtils.isBlank(name)) + return 0; + + return getJdbcTemplate().update( + "delete from logins where user_id in (select id from users where nick = ?)", name); + } + + @Transactional + @Override + public int setLoginForUser(final int uid, final String loginHash) { + if (StringUtils.isEmpty(loginHash)) + return 0; + + return getNamedParameterJdbcTemplate().update( + "INSERT INTO logins (user_id, hash) VALUES(:uid, :hash) ON DUPLICATE KEY UPDATE hash = :hash", + new MapSqlParameterSource() + .addValue("hash", loginHash) + .addValue("uid", uid)); + } + + @Transactional + @Override + public void logout(int uid) { + getJdbcTemplate().update("DELETE FROM logins WHERE user_id=?", uid); + } + + @Transactional + @Override + public boolean deleteJID(int uid, String jid) { + return getNamedParameterJdbcTemplate().update("DELETE FROM jids " + + "WHERE (SELECT COUNT(*) cnt FROM (select user_id, jid FROM jids j) c WHERE user_id=:uid) > 1 " + + "AND user_id=:uid AND jid=:jid", + new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("jid", jid)) > 0; + } + + @Transactional + @Override + public boolean unauthJID(int uid, String jid) { + return getJdbcTemplate() + .update("DELETE FROM auth WHERE user_id=? AND protocol='xmpp' AND account=?", uid, jid) > 0; + } + + @Transactional(readOnly = true) + @Override + public List getActiveJIDs() { + return getJdbcTemplate().queryForList("SELECT jid FROM jids WHERE active=1 AND loginhash IS NULL", String.class); + } +} diff --git a/juick-server/src/main/java/ru/sape/Sape.java b/juick-server/src/main/java/ru/sape/Sape.java new file mode 100644 index 00000000..38577c45 --- /dev/null +++ b/juick-server/src/main/java/ru/sape/Sape.java @@ -0,0 +1,23 @@ +/* + * http://code.google.com/p/javasape/ + */ +package ru.sape; + +public class Sape { + + private final String sapeUser; + private final SapeConnection sapePageLinkConnection; + + public Sape(String sapeUser, String host, int socketTimeout, int cacheLifeTime) { + this.sapeUser = sapeUser; + + this.sapePageLinkConnection = new SapeConnection( + "/code.php?user=" + sapeUser + "&host=" + host, + "SAPE_Client PHP", socketTimeout, cacheLifeTime); + } + public boolean debug = false; + + public SapePageLinks getPageLinks(String requestUri, String cookie) { + return new SapePageLinks(sapePageLinkConnection, sapeUser, requestUri, cookie, debug); + } +} diff --git a/juick-server/src/main/java/ru/sape/SapeConnection.java b/juick-server/src/main/java/ru/sape/SapeConnection.java new file mode 100644 index 00000000..a15658fa --- /dev/null +++ b/juick-server/src/main/java/ru/sape/SapeConnection.java @@ -0,0 +1,108 @@ +package ru.sape; + +import com.github.ooxi.phparser.SerializedPhpParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.*; + +public class SapeConnection { + private static final Logger logger = LoggerFactory.getLogger(SapeConnection.class); + private final String version = "1.0.3"; + private final List serverList = Arrays.asList("dispenser-01.sape.ru", "dispenser-02.sape.ru"); + private final String dispenserPath; + private final String userAgent; + private final int socketTimeout; + private final int cacheLifeTime; + + public SapeConnection(String dispenserPath, String userAgent, int socketTimeout, int cacheLifeTime) { + this.dispenserPath = dispenserPath; + this.userAgent = userAgent; + this.socketTimeout = socketTimeout; + this.cacheLifeTime = cacheLifeTime; + } + + protected String fetchRemoteFile(String host, String path) throws IOException { + Reader r = null; + + try { + HttpURLConnection connection = (HttpURLConnection) ((new URL(("http://" + host + path)).openConnection())); + + if (socketTimeout > 0) { + connection.setConnectTimeout(socketTimeout); + connection.setReadTimeout(socketTimeout); + } + + connection.addRequestProperty("User-Agent", userAgent + ' ' + version); + + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setUseCaches(false); + connection.setRequestMethod("GET"); + connection.connect(); + + r = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); + + StringWriter sw = new StringWriter(); + + int b; + + while ((b = r.read()) != -1) { + sw.write(b); + } + + return sw.toString(); + } finally { + if (r != null) { + r.close(); + } + } + } + Map cached; + long cacheUpdated; + + @SuppressWarnings("unchecked") + public Map getData() { + if (cacheLifeTime <= (System.currentTimeMillis() - cacheUpdated) / 1000) { + for (String server : serverList) { + String data; + + try { + data = fetchRemoteFile(server, dispenserPath + "&charset=UTF-8"); + } catch (IOException e1) { + continue; + } + + if (data.startsWith("FATAL ERROR:")) { + logger.error("Sape responded with error: {}", data); + + continue; + } + + try { + cached = (Map) new SerializedPhpParser(data).parse(); + } catch (Exception e) { + logger.error("Can't parse Sape data", e); + continue; + } + + cacheUpdated = System.currentTimeMillis(); + + return cached; + } + + logger.error("Unable to fetch Sape data"); + + return Collections.emptyMap(); + } + + return cached; + } +} diff --git a/juick-server/src/main/java/ru/sape/SapePageLinks.java b/juick-server/src/main/java/ru/sape/SapePageLinks.java new file mode 100644 index 00000000..e89b4e71 --- /dev/null +++ b/juick-server/src/main/java/ru/sape/SapePageLinks.java @@ -0,0 +1,76 @@ +package ru.sape; + +import java.util.*; + +public class SapePageLinks { + + private boolean showCode; + + public SapePageLinks(SapeConnection sapeConnection, String sapeUser, String requestUri, String sapeCookie) { + this(sapeConnection, sapeUser, requestUri, sapeCookie, false); + } + + @SuppressWarnings("unchecked") + public SapePageLinks(SapeConnection sapeConnection, String sapeUser, String requestUri, String sapeCookie, boolean showCode) { + if (sapeUser.equals(sapeCookie)) { + showCode = true; + } + + Map data = sapeConnection.getData(); + + if (data.containsKey("__sape_delimiter__")) { + linkDelimiter = (String) data.get("__sape_delimiter__"); + } + + if (data.containsKey(requestUri)) { + pageLinks = new ArrayList<>(((Map) data.get(requestUri)).values()); + } + + if (data.containsKey("__sape_new_url__")) { + if (showCode) { + Object newUrl = data.get("__sape_new_url__"); + + if (newUrl instanceof Map) { + pageLinks = new ArrayList<>(((Map) newUrl).values()); + } else { + pageLinks = new ArrayList<>(Collections.singletonList((String) newUrl)); + } + } + } + + this.showCode = showCode; + } + private String linkDelimiter = "."; + private List pageLinks = new ArrayList<>(); + + public String render() { + return render(-1); + } + + public String render(int count) { + StringBuilder s = new StringBuilder(); + + if (count < 0) { + count = pageLinks.size(); + } + + for (Iterator i = pageLinks.iterator(); i.hasNext() && count > 0; count--) { + if (s.length() > 0) { + s.append(linkDelimiter); + } + + String l = i.next(); + + s.append(l); + + i.remove(); + } + + if (showCode) { + s.insert(0, ""); + s.append(""); + } + + return s.toString(); + } +} diff --git a/juick-server/src/main/resources/juick.sql b/juick-server/src/main/resources/juick.sql new file mode 100644 index 00000000..ce34385f --- /dev/null +++ b/juick-server/src/main/resources/juick.sql @@ -0,0 +1,947 @@ +-- MySQL dump 10.16 Distrib 10.1.26-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: juick +-- ------------------------------------------------------ +use juick; +-- Server version 10.1.26-MariaDB-0+deb9u1 +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `ads_messages` +-- + +DROP TABLE IF EXISTS `ads_messages`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ads_messages` ( + `message_id` int(10) unsigned NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ads_messages_log` +-- + +DROP TABLE IF EXISTS `ads_messages_log`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ads_messages_log` ( + `user_id` int(10) unsigned NOT NULL, + `message_id` int(10) unsigned NOT NULL, + `ts` int(10) unsigned NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `android` +-- + +DROP TABLE IF EXISTS `android`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `android` ( + `user_id` int(10) unsigned NOT NULL, + `regid` char(255) NOT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY `regid` (`regid`), + KEY `user_id` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `auth` +-- + +DROP TABLE IF EXISTS `auth`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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 +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bl_tags` +-- + +DROP TABLE IF EXISTS `bl_tags`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `bl_tags` ( + `user_id` int(10) unsigned NOT NULL, + `tag_id` int(10) unsigned NOT NULL, + KEY `tag_id` (`tag_id`), + KEY `user_id` (`user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bl_users` +-- + +DROP TABLE IF EXISTS `bl_users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `bl_users` ( + `user_id` int(10) unsigned NOT NULL, + `bl_user_id` int(10) unsigned NOT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`user_id`,`bl_user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `captcha` +-- + +DROP TABLE IF EXISTS `captcha`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `captcha` ( + `jid` char(64) NOT NULL, + `hash` char(16) NOT NULL, + `confirmed` tinyint(4) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `captchaimg` +-- + +DROP TABLE IF EXISTS `captchaimg`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `captchaimg` ( + `id` char(16) NOT NULL, + `txt` char(6) NOT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `ip` char(16) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `emails` +-- + +DROP TABLE IF EXISTS `emails`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `emails` ( + `user_id` int(10) unsigned NOT NULL, + `email` char(64) NOT NULL, + `subscr_hour` tinyint(4) DEFAULT NULL, + KEY `email` (`email`) USING HASH +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `facebook` +-- + +DROP TABLE IF EXISTS `facebook`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `facebook` ( + `user_id` int(10) unsigned DEFAULT NULL, + `fb_id` bigint(20) unsigned DEFAULT NULL, + `loginhash` char(36) DEFAULT NULL, + `access_token` char(255) DEFAULT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `fb_name` char(64) DEFAULT NULL, + `fb_link` char(255) DEFAULT NULL, + `crosspost` tinyint(1) unsigned NOT NULL DEFAULT '1', + KEY `user_id` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `favorites` +-- + +DROP TABLE IF EXISTS `favorites`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `favorites` ( + `user_id` int(10) unsigned NOT NULL, + `message_id` int(10) unsigned NOT NULL, + `ts` datetime NOT NULL, + `like_id` int(10) unsigned NOT NULL DEFAULT '1', + KEY `user_id` (`user_id`), + KEY `message_id` (`message_id`), + KEY `like_id` (`like_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `friends_facebook` +-- + +DROP TABLE IF EXISTS `friends_facebook`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `friends_facebook` ( + `user_id` int(10) unsigned NOT NULL, + `friend_id` bigint(20) unsigned NOT NULL, + UNIQUE KEY `user_id` (`user_id`,`friend_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `images` +-- + +DROP TABLE IF EXISTS `images`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ios` +-- + +DROP TABLE IF EXISTS `ios`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ios` ( + `user_id` int(10) unsigned NOT NULL, + `token` char(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY `token` (`token`), + KEY `user_id` (`user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `jids` +-- + +DROP TABLE IF EXISTS `jids`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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`), + KEY `user_id` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `logins` +-- + +DROP TABLE IF EXISTS `logins`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `logins` ( + `user_id` int(10) unsigned NOT NULL, + `hash` char(16) NOT NULL, + UNIQUE KEY `user_id` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `mail` +-- + +DROP TABLE IF EXISTS `mail`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `mail` ( + `user_id` int(10) unsigned NOT NULL, + `hash` char(16) NOT NULL, + PRIMARY KEY (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `meon` +-- + +DROP TABLE IF EXISTS `meon`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `messages` +-- + +DROP TABLE IF EXISTS `messages`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `messages` ( + `message_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `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` enum('jpg','mp4','png') DEFAULT NULL, + `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, + PRIMARY KEY (`message_id`), + KEY `user_id` (`user_id`), + KEY `ts` (`ts`), + KEY `attach` (`attach`), + KEY `place_id` (`place_id`), + KEY `popular` (`popular`), + KEY `hidden` (`hidden`), + KEY `updated_indx` (`updated`,`message_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `messages_access` +-- + +DROP TABLE IF EXISTS `messages_access`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `messages_access` ( + `message_id` int(10) unsigned NOT NULL, + `user_id` int(10) unsigned NOT NULL, + KEY `message_id` (`message_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `messages_tags` +-- + +DROP TABLE IF EXISTS `messages_tags`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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`), + KEY `message_id` (`message_id`), + KEY `tag_id` (`tag_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `messages_txt` +-- + +DROP TABLE IF EXISTS `messages_txt`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `messages_txt` ( + `message_id` int(10) unsigned NOT NULL, + `tags` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `repliesby` varchar(96) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `txt` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`message_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `messages_votes` +-- + +DROP TABLE IF EXISTS `messages_votes`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `messenger` +-- + +DROP TABLE IF EXISTS `messenger`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `messenger` ( + `user_id` int(10) unsigned DEFAULT NULL, + `sender_id` bigint(20) NOT NULL, + `display_name` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `loginhash` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `places` +-- + +DROP TABLE IF EXISTS `places`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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 ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`place_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `places_tags` +-- + +DROP TABLE IF EXISTS `places_tags`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `places_tags` ( + `place_id` int(10) unsigned NOT NULL, + `tag_id` int(10) unsigned NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `pm` +-- + +DROP TABLE IF EXISTS `pm`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pm` ( + `user_id` int(10) unsigned NOT NULL, + `user_id_to` int(10) unsigned NOT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `txt` text NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `pm_inroster` +-- + +DROP TABLE IF EXISTS `pm_inroster`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pm_inroster` ( + `user_id` int(10) unsigned NOT NULL, + `jid` char(64) NOT NULL, + UNIQUE KEY `user_id_2` (`user_id`,`jid`), + KEY `user_id` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `pm_streams` +-- + +DROP TABLE IF EXISTS `pm_streams`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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`,`user_id_to`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `presence` +-- + +DROP TABLE IF EXISTS `presence`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `presence` ( + `user_id` int(10) unsigned NOT NULL, + `jid` char(64) DEFAULT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY `jid` (`jid`) +) ENGINE=MEMORY DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `reactions` +-- + +DROP TABLE IF EXISTS `reactions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `reactions` ( + `like_id` int(10) unsigned NOT NULL, + `description` varchar(100) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `reader_links` +-- + +DROP TABLE IF EXISTS `reader_links`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `reader_links` ( + `link_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `rss_id` int(10) unsigned NOT NULL, + `url` char(255) NOT NULL, + `title` char(255) NOT NULL, + `ts` datetime NOT NULL, + PRIMARY KEY (`link_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `reader_rss` +-- + +DROP TABLE IF EXISTS `reader_rss`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `reader_rss` ( + `rss_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `url` char(255) NOT NULL, + `lastcheck` datetime NOT NULL, + PRIMARY KEY (`rss_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `replies` +-- + +DROP TABLE IF EXISTS `replies`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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 NOT NULL DEFAULT CURRENT_TIMESTAMP, + `attach` enum('jpg','mp4','png') COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `txt` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, + KEY `ts` (`ts`), + KEY `message_id` (`message_id`), + KEY `uid` (`user_id`), + KEY `reply_indx` (`message_id`,`reply_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `search` +-- + +DROP TABLE IF EXISTS `search`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `search` ( + `id` bigint(20) unsigned NOT NULL, + `weight` int(11) NOT NULL, + `query` varchar(3072) NOT NULL, + `group_id` int(11) DEFAULT NULL, + KEY `query` (`query`(768)) +) ENGINE=SPHINX DEFAULT CHARSET=utf8mb4 CONNECTION='sphinx://127.0.0.1:3312/messages'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sphinx` +-- + +DROP TABLE IF EXISTS `sphinx`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `sphinx` ( + `counter_id` tinyint(3) unsigned NOT NULL, + `max_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`counter_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `subscr_messages` +-- + +DROP TABLE IF EXISTS `subscr_messages`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `subscr_messages` ( + `message_id` int(10) unsigned NOT NULL, + `suser_id` int(10) unsigned NOT NULL, + `last_read_rid` smallint(5) NOT NULL DEFAULT '0', + UNIQUE KEY `message_id` (`message_id`,`suser_id`), + KEY `last_read_indx` (`suser_id`,`last_read_rid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `subscr_tags` +-- + +DROP TABLE IF EXISTS `subscr_tags`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `subscr_tags` ( + `tag_id` int(10) unsigned NOT NULL, + `suser_id` int(10) unsigned NOT NULL, + UNIQUE KEY `tag_id` (`tag_id`,`suser_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `subscr_users` +-- + +DROP TABLE IF EXISTS `subscr_users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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 b'1', + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY `user_id` (`user_id`,`suser_id`), + KEY `suser_id` (`suser_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `tags` +-- + +DROP TABLE IF EXISTS `tags`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tags` ( + `tag_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `synonym_id` int(10) unsigned DEFAULT NULL, + `name` char(70) CHARACTER SET utf8mb4 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`), + KEY `synonym_id` (`synonym_id`), + KEY `stat_msg_indx` (`name`,`stat_messages`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `tags_ignore` +-- + +DROP TABLE IF EXISTS `tags_ignore`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tags_ignore` ( + `tag_id` int(10) unsigned NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `tags_synonyms` +-- + +DROP TABLE IF EXISTS `tags_synonyms`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tags_synonyms` ( + `name` char(64) NOT NULL, + `changeto` char(64) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `telegram` +-- + +DROP TABLE IF EXISTS `telegram`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `telegram` ( + `user_id` int(10) unsigned DEFAULT NULL, + `tg_id` bigint(20) NOT NULL, + `tg_name` char(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `loginhash` char(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `telegram_chats` +-- + +DROP TABLE IF EXISTS `telegram_chats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `telegram_chats` ( + `chat_id` bigint(20) DEFAULT NULL, + UNIQUE KEY `chat_id` (`chat_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `top_ignore_messages` +-- + +DROP TABLE IF EXISTS `top_ignore_messages`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `top_ignore_messages` ( + `message_id` int(10) unsigned NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `top_ignore_tags` +-- + +DROP TABLE IF EXISTS `top_ignore_tags`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `top_ignore_tags` ( + `tag_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`tag_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `top_ignore_users` +-- + +DROP TABLE IF EXISTS `top_ignore_users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `top_ignore_users` ( + `user_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `twitter` +-- + +DROP TABLE IF EXISTS `twitter`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `useroptions` +-- + +DROP TABLE IF EXISTS `useroptions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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 '0000-00-00 00:00:00', + `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`), + KEY `recommendations` (`recommendations`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `users` +-- + +DROP TABLE IF EXISTS `users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `users` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `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 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`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `users_refs` +-- + +DROP TABLE IF EXISTS `users_refs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `users_refs` ( + `user_id` int(10) unsigned NOT NULL, + `ref` int(10) unsigned NOT NULL, + KEY `ref` (`ref`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `users_subscr` +-- + +DROP TABLE IF EXISTS `users_subscr`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `users_subscr` ( + `user_id` int(10) unsigned NOT NULL, + `cnt` smallint(5) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `usersinfo` +-- + +DROP TABLE IF EXISTS `usersinfo`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `version` +-- + +DROP TABLE IF EXISTS `version`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `version` ( + `version` bigint(20) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `vk` +-- + +DROP TABLE IF EXISTS `vk`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `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` tinyint(3) unsigned NOT NULL DEFAULT '1', + KEY `user_id` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `winphone` +-- + +DROP TABLE IF EXISTS `winphone`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `winphone` ( + `user_id` int(10) unsigned NOT NULL, + `url` char(255) NOT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY `url` (`url`), + KEY `user_id` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `wl_users` +-- + +DROP TABLE IF EXISTS `wl_users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `wl_users` ( + `user_id` int(10) unsigned NOT NULL, + `wl_user_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`user_id`,`wl_user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2018-06-13 9:49:48 diff --git a/juick-server/src/main/resources/pg_schema_wip b/juick-server/src/main/resources/pg_schema_wip new file mode 100644 index 00000000..61178495 --- /dev/null +++ b/juick-server/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/juick-server/src/main/resources/schema.sql b/juick-server/src/main/resources/schema.sql new file mode 100644 index 00000000..296fd486 --- /dev/null +++ b/juick-server/src/main/resources/schema.sql @@ -0,0 +1,379 @@ +SET DB_CLOSE_ON_EXIT TRUE; + +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 NOT NULL, + `loginhash` char(36) DEFAULT NULL, + `access_token` char(255) DEFAULT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `fb_name` char(64) NOT NULL, + `fb_link` char(255) NOT 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, + `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(9) 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(9) 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`) +); \ No newline at end of file diff --git a/juick-server/src/main/resources/update.sql b/juick-server/src/main/resources/update.sql new file mode 100644 index 00000000..13a62c3d --- /dev/null +++ b/juick-server/src/main/resources/update.sql @@ -0,0 +1,12 @@ +-- if version table not exists set up version = 0; +update version set version = 0; + +DROP TABLE IF EXISTS `version`; + +CREATE TABLE `version` ( + `version` bigint NOT NULL +); + +insert into version values (0); + +update version set version = 1; \ No newline at end of file diff --git a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/FormatterExtension.java b/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/FormatterExtension.java deleted file mode 100644 index 9189c2be..00000000 --- a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/FormatterExtension.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.mitchellbosecke.pebble.extension; - -import com.mitchellbosecke.pebble.extension.filters.*; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by vitalyster on 04.05.2017. - */ -public class FormatterExtension extends AbstractExtension { - @Override - public Map getFilters() { - Map filters = new HashMap<>(); - filters.put("formatMessage", new FormatMessageFilter()); - filters.put("prettyTime", new PrettyTimeFilter()); - filters.put("timestamp", new TimestampFilter()); - filters.put("tagsList", new TagsListFilter()); - return filters; - } -} diff --git a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/FormatMessageFilter.java b/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/FormatMessageFilter.java deleted file mode 100644 index edb6c827..00000000 --- a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/FormatMessageFilter.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.mitchellbosecke.pebble.extension.filters; - -import com.juick.Message; -import com.juick.util.MessageUtils; -import com.mitchellbosecke.pebble.extension.Filter; -import com.mitchellbosecke.pebble.extension.escaper.SafeString; -import org.apache.commons.lang3.StringUtils; - -import java.util.List; -import java.util.Map; - -/** - * Created by vitalyster on 04.05.2017. - */ -public class FormatMessageFilter implements Filter { - @Override - public Object apply(Object input, Map args) { - if (input instanceof Message) { - Message msg = (Message) input; - boolean isCode = msg.getTags().stream().anyMatch(t -> t.getName().equals("code")); - String formatString = MessageUtils.replyStartsWithQuote(msg) ? "@%s,\n%s" : "@%s, %s"; - String msgTxt = msg.getRid() > 0 ? String.format(formatString, msg.getTo().getName(), StringUtils.defaultString(msg.getText())) - : StringUtils.defaultString(msg.getText()); - String formattedMessage = isCode ? MessageUtils.formatMessageCode(msgTxt) - : MessageUtils.formatMessage(msgTxt); - return new SafeString(formattedMessage); - } - throw new IllegalArgumentException("invalid input"); - } - - @Override - public List getArgumentNames() { - return null; - } -} diff --git a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/PrettyTimeFilter.java b/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/PrettyTimeFilter.java deleted file mode 100644 index 1d58ce79..00000000 --- a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/PrettyTimeFilter.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.mitchellbosecke.pebble.extension.filters; - -import com.juick.util.PrettyTimeFormatter; -import com.mitchellbosecke.pebble.extension.Filter; -import com.mitchellbosecke.pebble.template.EvaluationContext; - -import java.time.Instant; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -/** - * Created by vitalyster on 04.05.2017. - */ -public class PrettyTimeFilter implements Filter { - - PrettyTimeFormatter formatter = new PrettyTimeFormatter(); - - @Override - public Object apply(Object input, Map args) { - if (input instanceof Instant) { - EvaluationContext context = (EvaluationContext) args.get("_context"); - Locale locale = context.getLocale(); - return formatter.format(locale, Date.from((Instant)input)); - } - throw new IllegalArgumentException("invalid input"); - } - - @Override - public List getArgumentNames() { - return null; - } -} diff --git a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/TagsListFilter.java b/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/TagsListFilter.java deleted file mode 100644 index bfbf18fb..00000000 --- a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/TagsListFilter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.mitchellbosecke.pebble.extension.filters; - -import com.juick.Tag; -import com.mitchellbosecke.pebble.extension.Filter; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Created by vitalyster on 23.05.2017. - */ -public class TagsListFilter implements Filter { - @SuppressWarnings("unchecked") - @Override - public Object apply(Object input, Map args) { - return ((List) input).stream().map(Tag::getName).collect(Collectors.toList()); - } - - @Override - public List getArgumentNames() { - return null; - } -} diff --git a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/TimestampFilter.java b/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/TimestampFilter.java deleted file mode 100644 index 35efb314..00000000 --- a/juick-www/src/main/java/com/mitchellbosecke/pebble/extension/filters/TimestampFilter.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.mitchellbosecke.pebble.extension.filters; - -import com.mitchellbosecke.pebble.extension.Filter; - -import java.time.Instant; -import java.util.Date; -import java.util.List; -import java.util.Map; - -public class TimestampFilter implements Filter { - @Override - public Object apply(Object input, Map args) { - if (input instanceof Instant) { - return Date.from((Instant)input); - } - throw new IllegalArgumentException("invalid input"); - } - - @Override - public List getArgumentNames() { - return null; - } -} diff --git a/juick-www/src/main/java/ru/sape/Sape.java b/juick-www/src/main/java/ru/sape/Sape.java deleted file mode 100644 index 38577c45..00000000 --- a/juick-www/src/main/java/ru/sape/Sape.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * http://code.google.com/p/javasape/ - */ -package ru.sape; - -public class Sape { - - private final String sapeUser; - private final SapeConnection sapePageLinkConnection; - - public Sape(String sapeUser, String host, int socketTimeout, int cacheLifeTime) { - this.sapeUser = sapeUser; - - this.sapePageLinkConnection = new SapeConnection( - "/code.php?user=" + sapeUser + "&host=" + host, - "SAPE_Client PHP", socketTimeout, cacheLifeTime); - } - public boolean debug = false; - - public SapePageLinks getPageLinks(String requestUri, String cookie) { - return new SapePageLinks(sapePageLinkConnection, sapeUser, requestUri, cookie, debug); - } -} diff --git a/juick-www/src/main/java/ru/sape/SapeConnection.java b/juick-www/src/main/java/ru/sape/SapeConnection.java deleted file mode 100644 index a15658fa..00000000 --- a/juick-www/src/main/java/ru/sape/SapeConnection.java +++ /dev/null @@ -1,108 +0,0 @@ -package ru.sape; - -import com.github.ooxi.phparser.SerializedPhpParser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringWriter; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.*; - -public class SapeConnection { - private static final Logger logger = LoggerFactory.getLogger(SapeConnection.class); - private final String version = "1.0.3"; - private final List serverList = Arrays.asList("dispenser-01.sape.ru", "dispenser-02.sape.ru"); - private final String dispenserPath; - private final String userAgent; - private final int socketTimeout; - private final int cacheLifeTime; - - public SapeConnection(String dispenserPath, String userAgent, int socketTimeout, int cacheLifeTime) { - this.dispenserPath = dispenserPath; - this.userAgent = userAgent; - this.socketTimeout = socketTimeout; - this.cacheLifeTime = cacheLifeTime; - } - - protected String fetchRemoteFile(String host, String path) throws IOException { - Reader r = null; - - try { - HttpURLConnection connection = (HttpURLConnection) ((new URL(("http://" + host + path)).openConnection())); - - if (socketTimeout > 0) { - connection.setConnectTimeout(socketTimeout); - connection.setReadTimeout(socketTimeout); - } - - connection.addRequestProperty("User-Agent", userAgent + ' ' + version); - - connection.setDoOutput(true); - connection.setDoInput(true); - connection.setUseCaches(false); - connection.setRequestMethod("GET"); - connection.connect(); - - r = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); - - StringWriter sw = new StringWriter(); - - int b; - - while ((b = r.read()) != -1) { - sw.write(b); - } - - return sw.toString(); - } finally { - if (r != null) { - r.close(); - } - } - } - Map cached; - long cacheUpdated; - - @SuppressWarnings("unchecked") - public Map getData() { - if (cacheLifeTime <= (System.currentTimeMillis() - cacheUpdated) / 1000) { - for (String server : serverList) { - String data; - - try { - data = fetchRemoteFile(server, dispenserPath + "&charset=UTF-8"); - } catch (IOException e1) { - continue; - } - - if (data.startsWith("FATAL ERROR:")) { - logger.error("Sape responded with error: {}", data); - - continue; - } - - try { - cached = (Map) new SerializedPhpParser(data).parse(); - } catch (Exception e) { - logger.error("Can't parse Sape data", e); - continue; - } - - cacheUpdated = System.currentTimeMillis(); - - return cached; - } - - logger.error("Unable to fetch Sape data"); - - return Collections.emptyMap(); - } - - return cached; - } -} diff --git a/juick-www/src/main/java/ru/sape/SapePageLinks.java b/juick-www/src/main/java/ru/sape/SapePageLinks.java deleted file mode 100644 index e89b4e71..00000000 --- a/juick-www/src/main/java/ru/sape/SapePageLinks.java +++ /dev/null @@ -1,76 +0,0 @@ -package ru.sape; - -import java.util.*; - -public class SapePageLinks { - - private boolean showCode; - - public SapePageLinks(SapeConnection sapeConnection, String sapeUser, String requestUri, String sapeCookie) { - this(sapeConnection, sapeUser, requestUri, sapeCookie, false); - } - - @SuppressWarnings("unchecked") - public SapePageLinks(SapeConnection sapeConnection, String sapeUser, String requestUri, String sapeCookie, boolean showCode) { - if (sapeUser.equals(sapeCookie)) { - showCode = true; - } - - Map data = sapeConnection.getData(); - - if (data.containsKey("__sape_delimiter__")) { - linkDelimiter = (String) data.get("__sape_delimiter__"); - } - - if (data.containsKey(requestUri)) { - pageLinks = new ArrayList<>(((Map) data.get(requestUri)).values()); - } - - if (data.containsKey("__sape_new_url__")) { - if (showCode) { - Object newUrl = data.get("__sape_new_url__"); - - if (newUrl instanceof Map) { - pageLinks = new ArrayList<>(((Map) newUrl).values()); - } else { - pageLinks = new ArrayList<>(Collections.singletonList((String) newUrl)); - } - } - } - - this.showCode = showCode; - } - private String linkDelimiter = "."; - private List pageLinks = new ArrayList<>(); - - public String render() { - return render(-1); - } - - public String render(int count) { - StringBuilder s = new StringBuilder(); - - if (count < 0) { - count = pageLinks.size(); - } - - for (Iterator i = pageLinks.iterator(); i.hasNext() && count > 0; count--) { - if (s.length() > 0) { - s.append(linkDelimiter); - } - - String l = i.next(); - - s.append(l); - - i.remove(); - } - - if (showCode) { - s.insert(0, ""); - s.append(""); - } - - return s.toString(); - } -} diff --git a/settings.gradle b/settings.gradle index dc9123cf..86d92c90 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ rootProject.name = "Juick" -include ':juick-common', ':juick-server-jdbc', ':juick-api', ':juick-server', ':juick-www', ':juick-notifications' +include ':juick-common', ':juick-server', ':juick-notifications' -- cgit v1.2.3