diff --git a/configs.properties.example b/configs.properties.example index 2934e7a..3de2f63 100644 --- a/configs.properties.example +++ b/configs.properties.example @@ -1,9 +1,10 @@ -# Web server config +# Web server configs webserver.http.port=4000 webserver.maxThreads=512 # Twitch config twitch.user_url=https://api.twitch.tv/kraken/user +twitch.users_url=https://api.twitch.tv/kraken/users/ twitch.client_id=cs5900eog2wajva8rnvf2jtx6gazsvd twitch.channels_url=https://api.twitch.tv/kraken/channels/ twitch.accept_header=application/vnd.twitchtv.v5+json diff --git a/database/5-ffs-add-check-subscription.sql b/database/5-ffs-add-check-subscription.sql new file mode 100644 index 0000000..b0f66d9 --- /dev/null +++ b/database/5-ffs-add-check-subscription.sql @@ -0,0 +1,2 @@ +ALTER TABLE `ffs`.`account_event_status` +ADD COLUMN `subscribe_to_winner` TINYINT(1) NULL ; \ No newline at end of file diff --git a/pom.xml b/pom.xml index c7208ab..3266eb2 100644 --- a/pom.xml +++ b/pom.xml @@ -2,9 +2,9 @@ 4.0.0 tv.zerator.ffs api - 0.9.2-SNAPSHOT + 0.9.8 - 0.6.2 + 0.6.4 @@ -22,14 +22,39 @@ + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + run + none + + exec + + + java + ${basedir}/config + + -classpath + + tv.zerator.ffs.api.Main + + + + + + maven-compiler-plugin 3.2 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/src/main/java/tv/zerator/ffs/api/dao/AccountsDao.java b/src/main/java/tv/zerator/ffs/api/dao/AccountsDao.java index 027db37..81fcd0c 100644 --- a/src/main/java/tv/zerator/ffs/api/dao/AccountsDao.java +++ b/src/main/java/tv/zerator/ffs/api/dao/AccountsDao.java @@ -1,10 +1,8 @@ package tv.zerator.ffs.api.dao; -import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; -import com.jolbox.bonecp.BoneCPDataSource; import com.jolbox.bonecp.PreparedStatementHandle; import alexmog.apilib.dao.DAO; @@ -12,16 +10,10 @@ import tv.zerator.ffs.api.dao.beans.AccountBean; @Dao(database = "general") -public class AccountsDao extends DAO { +public class AccountsDao extends DAO { - public AccountsDao(BoneCPDataSource dataSource) { - super(dataSource); - } - - @Override public int insert(AccountBean data) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("INSERT INTO accounts " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("INSERT INTO accounts " + "(twitch_id, username, email, views, followers, broadcaster_type, url, grade, email_activation_key, logo) VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { prep.setInt(1, data.getTwitchId()); @@ -39,10 +31,8 @@ public int insert(AccountBean data) throws SQLException { } } - @Override public AccountBean update(AccountBean data) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("UPDATE accounts SET " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("UPDATE accounts SET " + "username = ?, email = ?, views = ?, followers = ?, broadcaster_type = ?, url = ?, grade = ?, email_activation_key = ?, logo = ? " + "WHERE twitch_id = ?")) { prep.setString(1, data.getUsername()); @@ -61,8 +51,7 @@ public AccountBean update(AccountBean data) throws SQLException { } public AccountBean getAccountFromToken(String token) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT " + "a.broadcaster_type, a.email, a.email_activation_key, a.followers, a.grade, a.twitch_id, a.url, a.username, a.views, a.logo " + "FROM accounts a LEFT JOIN auth_tokens t ON t.account_id = a.twitch_id WHERE t.token = ?")) { prep.setString(1, token); @@ -100,8 +89,7 @@ private AccountBean constructAccountBean(ResultSet rs) throws SQLException { } public AccountBean get(int twitchId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT * FROM accounts WHERE twitch_id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT * FROM accounts WHERE twitch_id = ?")) { prep.setInt(1, twitchId); try (ResultSet rs = prep.executeQuery()) { if (!rs.next()) return null; @@ -111,8 +99,7 @@ public AccountBean get(int twitchId) throws SQLException { } public AccountBean getFromValidationCode(String code) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT * FROM accounts WHERE email_activation_key = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT * FROM accounts WHERE email_activation_key = ?")) { prep.setString(1, code); try (ResultSet rs = prep.executeQuery()) { if (!rs.next()) return null; diff --git a/src/main/java/tv/zerator/ffs/api/dao/EventsDao.java b/src/main/java/tv/zerator/ffs/api/dao/EventsDao.java index a003aee..03c6a68 100644 --- a/src/main/java/tv/zerator/ffs/api/dao/EventsDao.java +++ b/src/main/java/tv/zerator/ffs/api/dao/EventsDao.java @@ -1,13 +1,11 @@ package tv.zerator.ffs.api.dao; -import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; -import com.jolbox.bonecp.BoneCPDataSource; import com.jolbox.bonecp.PreparedStatementHandle; import alexmog.apilib.dao.DAO; @@ -18,16 +16,10 @@ import tv.zerator.ffs.api.dao.beans.EventBean; @Dao(database = "general") -public class EventsDao extends DAO { +public class EventsDao extends DAO { - public EventsDao(BoneCPDataSource dataSource) { - super(dataSource); - } - - @Override public int insert(EventBean data) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("INSERT INTO events " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("INSERT INTO events " + "(name, description, status, reserved_to_affiliates, reserved_to_partners, minimum_views, minimum_followers, ranking_type) VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) { prep.setString(1, data.getName()); @@ -62,8 +54,7 @@ private EventBean constructEvent(ResultSet rs) throws SQLException { } public List getEvents(EventBean.Status status, int start, int end) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT * FROM events WHERE status = ? ORDER BY id DESC LIMIT ?, ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT * FROM events WHERE status = ? ORDER BY id DESC LIMIT ?, ?")) { prep.setString(1, status.name()); prep.setInt(2, start); prep.setInt(3, end); @@ -76,8 +67,7 @@ public List getEvents(EventBean.Status status, int start, int end) th } public List getEvents(int start, int end) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT * FROM events ORDER BY id DESC LIMIT ?, ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT * FROM events ORDER BY id DESC LIMIT ?, ?")) { prep.setInt(1, start); prep.setInt(2, end); try (ResultSet rs = prep.executeQuery()) { @@ -89,8 +79,7 @@ public List getEvents(int start, int end) throws SQLException { } public EventBean getEvent(int id) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT * FROM events WHERE id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT * FROM events WHERE id = ?")) { prep.setInt(1, id); try (ResultSet rs = prep.executeQuery()) { if (!rs.next()) return null; @@ -100,8 +89,7 @@ public EventBean getEvent(int id) throws SQLException { } public EventBean getCurrent() throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT * FROM events WHERE is_current = 1")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT * FROM events WHERE is_current = 1")) { try (ResultSet rs = prep.executeQuery()) { if (!rs.next()) return null; return constructEvent(rs); @@ -109,10 +97,8 @@ public EventBean getCurrent() throws SQLException { } } - @Override public EventBean update(EventBean data) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("UPDATE events SET " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("UPDATE events SET " + "name = ?, description = ?, status = ?, reserved_to_affiliates = ?, " + "reserved_to_partners = ?, is_current = ?, minimum_views = ?, minimum_followers = ?, ranking_type = ? WHERE id = ?")) { prep.setString(1, data.getName()); @@ -126,7 +112,7 @@ public EventBean update(EventBean data) throws SQLException { prep.setString(9, data.getRankingType().name()); prep.setInt(10, data.getId()); if (data.isCurrent()) { - try (PreparedStatementHandle prep2 = (PreparedStatementHandle) conn.prepareStatement("UPDATE events SET " + try (PreparedStatementHandle prep2 = (PreparedStatementHandle) getConnection().prepareStatement("UPDATE events SET " + "is_current = 0 WHERE is_current = 1")) { prep2.executeUpdate(); } @@ -137,8 +123,7 @@ public EventBean update(EventBean data) throws SQLException { } public List getRounds(int eventId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT round_id FROM event_rounds WHERE event_id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT round_id FROM event_rounds WHERE event_id = ?")) { prep.setInt(1, eventId); try (ResultSet rs = prep.executeQuery()) { List ret = new ArrayList<>(); @@ -149,8 +134,7 @@ public List getRounds(int eventId) throws SQLException { } public boolean roundExists(int eventId, int roundId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT round_id FROM event_rounds WHERE event_id = ? AND round_id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT round_id FROM event_rounds WHERE event_id = ? AND round_id = ?")) { prep.setInt(1, eventId); prep.setInt(2, roundId); try (ResultSet rs = prep.executeQuery()) { @@ -160,8 +144,7 @@ public boolean roundExists(int eventId, int roundId) throws SQLException { } public int addRound(int eventId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("INSERT INTO event_rounds " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("INSERT INTO event_rounds " + "(event_id) VALUES " + "(?)", Statement.RETURN_GENERATED_KEYS)) { prep.setInt(1, eventId); @@ -174,8 +157,7 @@ public int addRound(int eventId) throws SQLException { } public void deleteRound(int eventId, int roundId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("DELETE FROM event_rounds " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("DELETE FROM event_rounds " + "WHERE event_id = ? AND round_id = ?")) { prep.setInt(1, eventId); prep.setInt(2, roundId); @@ -184,8 +166,7 @@ public void deleteRound(int eventId, int roundId) throws SQLException { } public void addScore(int roundId, int accountId, double score) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("INSERT INTO round_scores " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("INSERT INTO round_scores " + "(round_id, account_id, score) VALUES " + "(?, ?, ?)")) { prep.setInt(1, roundId); @@ -196,8 +177,7 @@ public void addScore(int roundId, int accountId, double score) throws SQLExcepti } public void updateScore(int roundId, int accountId, double score) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("UPDATE round_scores SET " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("UPDATE round_scores SET " + "score = ? WHERE round_id = ? AND account_id = ?")) { prep.setDouble(1, score); prep.setInt(2, roundId); @@ -214,8 +194,7 @@ public void updateScore(int roundId, int accountId, double score) throws SQLExce } public List getScores(int roundId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT s.score, a.username, a.url, a.twitch_id, a.logo FROM accounts a LEFT JOIN round_scores s ON s.account_id = a.twitch_id WHERE s.round_id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT s.score, a.username, a.url, a.twitch_id, a.logo FROM accounts a LEFT JOIN round_scores s ON s.account_id = a.twitch_id WHERE s.round_id = ?")) { prep.setInt(1, roundId); try (ResultSet rs = prep.executeQuery()) { List ret = new ArrayList<>(); @@ -226,8 +205,7 @@ public List getScores(int roundId) throws SQLException { } public List getAllScores(int eventId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT s.score, s.round_id, a.username, a.url, a.twitch_id, a.logo FROM accounts a " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT s.score, s.round_id, a.username, a.url, a.twitch_id, a.logo FROM accounts a " + "LEFT JOIN round_scores s ON s.account_id = a.twitch_id " + "INNER JOIN event_rounds e ON s.round_id = e.round_id " + "WHERE e.event_id = ?")) { @@ -241,8 +219,7 @@ public List getAllScores(int eventId) throws SQLException { } public Double getScore(int roundId, int accountId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT score FROM round_scores WHERE round_id = ? AND account_id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT score FROM round_scores WHERE round_id = ? AND account_id = ?")) { prep.setInt(1, roundId); prep.setInt(2, accountId); try (ResultSet rs = prep.executeQuery()) { @@ -253,8 +230,7 @@ public Double getScore(int roundId, int accountId) throws SQLException { } public List getUsers(int eventId, UserStatus status) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT a.twitch_id, a.username, a.email, a.views, a.followers, a.broadcaster_type, a.url, a.grade, a.logo, s.status, s.rank " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT a.twitch_id, a.username, a.email, a.views, a.followers, a.broadcaster_type, a.url, a.grade, a.logo, s.status, s.rank " + " FROM accounts a LEFT JOIN account_event_status s ON s.account_id = a.twitch_id WHERE s.event_id = ? AND s.status = ?")) { prep.setInt(1, eventId); prep.setString(2, status.name()); @@ -273,6 +249,7 @@ public List getUsers(int eventId, UserStatus status) throws S bean.setLogo(rs.getString("a.logo")); bean.setStatus(UserStatus.valueOf(rs.getString("s.status"))); bean.setRank(rs.getInt("s.rank")); + bean.setSubscribeToWinner(rs.getBoolean("s.subscribe_to_winner")); ret.add(bean); } return ret; @@ -281,8 +258,7 @@ public List getUsers(int eventId, UserStatus status) throws S } public List getUsers(int eventId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT a.twitch_id, a.username, a.email, a.views, a.followers, a.broadcaster_type, a.url, a.grade, a.logo, s.status, s.rank " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT a.twitch_id, a.username, a.email, a.views, a.followers, a.broadcaster_type, a.url, a.grade, a.logo, s.status, s.rank, s.subscribe_to_winner " + " FROM accounts a LEFT JOIN account_event_status s ON s.account_id = a.twitch_id WHERE s.event_id = ?")) { prep.setInt(1, eventId); try (ResultSet rs = prep.executeQuery()) { @@ -300,6 +276,7 @@ public List getUsers(int eventId) throws SQLException { bean.setLogo(rs.getString("a.logo")); bean.setStatus(UserStatus.valueOf(rs.getString("s.status"))); bean.setRank(rs.getInt("s.rank")); + bean.setSubscribeToWinner(rs.getBoolean("s.subscribe_to_winner")); ret.add(bean); } return ret; @@ -308,8 +285,7 @@ public List getUsers(int eventId) throws SQLException { } public void delete(int eventId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("DELETE FROM events WHERE id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("DELETE FROM events WHERE id = ?")) { prep.setInt(1, eventId); prep.executeUpdate(); } @@ -323,8 +299,7 @@ public enum UserStatus { } public void registerUser(int eventId, int accountId, UserStatus status, String emailActivationKey) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("INSERT INTO account_event_status " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("INSERT INTO account_event_status " + "(account_id, event_id, status, email_activation_key) VALUES (?, ?, ?, ?)")) { prep.setInt(1, accountId); prep.setInt(2, eventId); @@ -342,8 +317,7 @@ public void registerUser(int eventId, int accountId, UserStatus status, String e } public UserStatusBean getUser(int eventId, int accountId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT s.event_id, s.status, s.email_activation_key, a.twitch_id, a.username, a.email, a.views, a.followers, a.broadcaster_type, a.url, a.grade, a.logo " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT s.event_id, s.status, s.email_activation_key, a.twitch_id, a.username, a.email, a.views, a.followers, a.broadcaster_type, a.url, a.grade, a.logo " + " FROM accounts a LEFT JOIN account_event_status s ON s.account_id = a.twitch_id " + "WHERE s.account_id = ? AND s.event_id = ?")) { prep.setInt(1, accountId); @@ -371,8 +345,7 @@ public UserStatusBean getUser(int eventId, int accountId) throws SQLException { } public void removeUser(int eventId, int accountId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("DELETE FROM account_event_status WHERE account_id = ? AND event_id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("DELETE FROM account_event_status WHERE account_id = ? AND event_id = ?")) { prep.setInt(1, accountId); prep.setInt(2, eventId); prep.executeUpdate(); @@ -380,8 +353,7 @@ public void removeUser(int eventId, int accountId) throws SQLException { } public void updateUser(int eventId, int accountId, UserStatus status) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("UPDATE account_event_status SET status = ? WHERE account_id = ? AND event_id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("UPDATE account_event_status SET status = ? WHERE account_id = ? AND event_id = ?")) { prep.setString(1, status.name()); prep.setInt(2, accountId); prep.setInt(3, eventId); @@ -390,23 +362,30 @@ public void updateUser(int eventId, int accountId, UserStatus status) throws SQL } public void updateUserRank(int eventId, int accountId, int rank) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("UPDATE account_event_status SET rank = ? WHERE account_id = ? AND event_id = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("UPDATE account_event_status SET rank = ? WHERE account_id = ? AND event_id = ?")) { prep.setInt(1, rank); prep.setInt(2, accountId); prep.setInt(3, eventId); prep.executeUpdate(); } } + public void updateUserSubscriptionToWinner(int eventId, int accountId, boolean hasSubscribe) throws SQLException { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("UPDATE account_event_status SET subscribe_to_winner = ? WHERE account_id = ? AND event_id = ?")) { + prep.setBoolean(1, hasSubscribe); + prep.setInt(2, accountId); + prep.setInt(3, eventId); + prep.executeUpdate(); + } + } public @Data class AccountStatusBean extends AccountBean { public UserStatus status; public Integer rank; + public boolean subscribeToWinner; } public AccountStatusBean getRegistered(int eventId, int accountId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT a.twitch_id, a.username, a.email, a.views, a.followers, a.broadcaster_type, a.url, a.grade, s.status, a.logo, s.rank " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT a.twitch_id, a.username, a.email, a.views, a.followers, a.broadcaster_type, a.url, a.grade, s.status, a.logo, s.rank, s.subscribe_to_winner " + " FROM accounts a LEFT JOIN account_event_status s ON s.account_id = a.twitch_id WHERE s.event_id = ? AND a.twitch_id = ?")) { prep.setInt(1, eventId); prep.setInt(2, accountId); @@ -424,6 +403,7 @@ public AccountStatusBean getRegistered(int eventId, int accountId) throws SQLExc bean.setLogo(rs.getString("a.logo")); bean.status = UserStatus.valueOf(rs.getString("s.status")); bean.rank = rs.getInt("s.rank"); + bean.subscribeToWinner = rs.getBoolean("s.subscribe_to_winner"); return bean; } return null; @@ -432,8 +412,7 @@ public AccountStatusBean getRegistered(int eventId, int accountId) throws SQLExc } public UserStatus getUserStatusFromEmailKey(int eventId, int accountId, String emailKey) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT status FROM account_event_status " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT status FROM account_event_status " + "WHERE event_id = ? AND account_id = ? AND email_activation_key = ?")) { prep.setInt(1, eventId); prep.setInt(2, accountId); @@ -444,6 +423,33 @@ public UserStatus getUserStatusFromEmailKey(int eventId, int accountId, String e } } } + + public AccountStatusBean getUserFromRank(int eventId, int rank) throws SQLException { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT a.twitch_id, a.username, a.email, a.views, a.followers, a.broadcaster_type, a.url, a.grade, s.status, a.logo, s.rank, s.subscribe_to_winner " + + " FROM accounts a LEFT JOIN account_event_status s ON s.account_id = a.twitch_id WHERE s.event_id = ? AND s.rank = ?")) { + prep.setInt(1, eventId); + prep.setInt(2, rank); + try (ResultSet rs = prep.executeQuery()) { + if (rs.next()) { + AccountStatusBean bean = new AccountStatusBean(); + bean.setTwitchId(rs.getInt("a.twitch_id")); + bean.setUsername(rs.getString("a.username")); + bean.setEmail(rs.getString("a.email")); + bean.setViews(rs.getInt("a.views")); + bean.setFollowers(rs.getInt("a.followers")); + bean.setBroadcasterType(BroadcasterType.valueOf(rs.getString("a.broadcaster_type"))); + bean.setUrl(rs.getString("a.url")); + bean.setGrade(rs.getInt("a.grade")); + bean.setLogo(rs.getString("a.logo")); + bean.status = UserStatus.valueOf(rs.getString("s.status")); + bean.rank = rs.getInt("s.rank"); + bean.subscribeToWinner = rs.getBoolean("s.subscribe_to_winner"); + return bean; + } + return null; + } + } + } public static @Data class AccountEventBean { public EventBean event; @@ -451,8 +457,7 @@ public UserStatus getUserStatusFromEmailKey(int eventId, int accountId, String e } public List getEventsForAccount(int accountId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT s.status, e.id, e.name, e.description, e.status, e.reserved_to_affiliates, e.reserved_to_partners, e.is_current, e.ranking_type " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT s.status, e.id, e.name, e.description, e.status, e.reserved_to_affiliates, e.reserved_to_partners, e.is_current, e.ranking_type " + "FROM events e LEFT JOIN account_event_status s ON s.event_id = e.id WHERE s.account_id = ?")) { prep.setInt(1, accountId); try (ResultSet rs = prep.executeQuery()) { @@ -478,8 +483,7 @@ public List getEventsForAccount(int accountId) throws SQLExcep } public List getEventsForAccountAndStatus(int accountId, UserStatus status) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("SELECT s.status, e.name, e.description, e.status, e.reserved_to_affiliates, e.reserved_to_partners, e.is_current, e.minimum_views, e.minimum_followers, e.ranking_type " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("SELECT s.status, e.name, e.description, e.status, e.reserved_to_affiliates, e.reserved_to_partners, e.is_current, e.minimum_views, e.minimum_followers, e.ranking_type " + "FROM events e LEFT JOIN account_event_status s ON s.event_id = e.id WHERE s.account_id = ? AND s.status = ?")) { prep.setInt(1, accountId); prep.setString(2, status.name()); diff --git a/src/main/java/tv/zerator/ffs/api/dao/TokensDao.java b/src/main/java/tv/zerator/ffs/api/dao/TokensDao.java index b8920bb..71a31f5 100644 --- a/src/main/java/tv/zerator/ffs/api/dao/TokensDao.java +++ b/src/main/java/tv/zerator/ffs/api/dao/TokensDao.java @@ -1,9 +1,7 @@ package tv.zerator.ffs.api.dao; -import java.sql.Connection; import java.sql.SQLException; -import com.jolbox.bonecp.BoneCPDataSource; import com.jolbox.bonecp.PreparedStatementHandle; import alexmog.apilib.dao.DAO; @@ -11,16 +9,10 @@ import tv.zerator.ffs.api.dao.beans.TokenBean; @Dao(database = "general") -public class TokensDao extends DAO { +public class TokensDao extends DAO { - public TokensDao(BoneCPDataSource dataSource) { - super(dataSource); - } - - @Override public int insert(TokenBean data) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("INSERT INTO auth_tokens " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("INSERT INTO auth_tokens " + "(account_id, token, last_used_timestamp) VALUES (?, ?, ?)")) { prep.setInt(1, data.getAccountId()); prep.setString(2, data.getToken()); @@ -31,17 +23,14 @@ public int insert(TokenBean data) throws SQLException { } public void delete(String tokenId) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("DELETE FROM auth_tokens WHERE token = ?")) { + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("DELETE FROM auth_tokens WHERE token = ?")) { prep.setString(1, tokenId); prep.executeUpdate(); } } - @Override public TokenBean update(TokenBean data) throws SQLException { - try (Connection conn = mDataSource.getConnection(); - PreparedStatementHandle prep = (PreparedStatementHandle) conn.prepareStatement("UPDATE auth_tokens SET " + try (PreparedStatementHandle prep = (PreparedStatementHandle) getConnection().prepareStatement("UPDATE auth_tokens SET " + "account_id = ?, last_used_timestamp = ? WHERE token = ?")) { prep.setInt(1, data.getAccountId()); prep.setLong(2, data.getLastUsedTimestamp()); diff --git a/src/main/java/tv/zerator/ffs/api/v1/ApiV1.java b/src/main/java/tv/zerator/ffs/api/v1/ApiV1.java index 46b4c38..758a374 100644 --- a/src/main/java/tv/zerator/ffs/api/v1/ApiV1.java +++ b/src/main/java/tv/zerator/ffs/api/v1/ApiV1.java @@ -23,6 +23,7 @@ import tv.zerator.ffs.api.v1.resources.LoginResource; import tv.zerator.ffs.api.v1.resources.MeEventsResource; import tv.zerator.ffs.api.v1.resources.MeResource; +import tv.zerator.ffs.api.v1.resources.EventCheckSubscriptionResource; import tv.zerator.ffs.api.v1.verifiers.OAuthVerifier; public class ApiV1 extends ApiBase { @@ -66,6 +67,7 @@ protected void configureRouter(int group, Router router) { break; case USER: router.attach("/event/{EVENT_ID}/register", EventRegisterResource.class); + router.attach("/event/{EVENT_ID}/check_subscription", EventCheckSubscriptionResource.class); break; case MODERATOR: router.attach("/event/{EVENT_ID}/round/{ROUND_ID}/score/{USER_ID}", EventRoundUserScoreResource.class); diff --git a/src/main/java/tv/zerator/ffs/api/v1/resources/EventCheckSubscriptionResource.java b/src/main/java/tv/zerator/ffs/api/v1/resources/EventCheckSubscriptionResource.java new file mode 100644 index 0000000..19b81ba --- /dev/null +++ b/src/main/java/tv/zerator/ffs/api/v1/resources/EventCheckSubscriptionResource.java @@ -0,0 +1,112 @@ +package tv.zerator.ffs.api.v1.resources; + +import alexmog.apilib.api.validation.ValidationErrors; +import alexmog.apilib.exceptions.BadAuthenticationException; +import alexmog.apilib.exceptions.BadEntityException; +import alexmog.apilib.exceptions.ConflictException; +import alexmog.apilib.exceptions.NotFoundException; +import alexmog.apilib.exceptions.InternalServerError; +import alexmog.apilib.managers.DaoManager; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.restlet.data.Status; +import org.restlet.resource.Post; +import org.restlet.resource.ResourceException; +import org.restlet.resource.ServerResource; +import tv.zerator.ffs.api.Main; +import tv.zerator.ffs.api.dao.EventsDao; +import tv.zerator.ffs.api.dao.beans.AccountBean; +import tv.zerator.ffs.api.dao.beans.EventBean; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.sql.SQLException; +import java.util.logging.Level; + +public class EventCheckSubscriptionResource extends ServerResource { + @DaoManager.DaoInject + private static EventsDao mEvents; + + private int mEventId; + + private final CloseableHttpClient mHttpClient = HttpClients.createDefault(); + private static String mTwitchUsersUrl = null, mTwitchClientId, mTwitchAccept; + + public EventCheckSubscriptionResource() { + if (mTwitchUsersUrl != null) return; + mTwitchUsersUrl = Main.getInstance().getConfig().getProperty("twitch.users_url"); + mTwitchClientId = Main.getInstance().getConfig().getProperty("twitch.client_id"); + mTwitchAccept = Main.getInstance().getConfig().getProperty("twitch.accept_header"); + } + + @Override + protected void doInit() throws ResourceException { + mEventId = Integer.parseInt(getAttribute("EVENT_ID")); + } + + @Post + public Status checkSubscription(LoginBean entity) throws SQLException { + EventBean event = mEvents.getEvent(mEventId); + if (event == null) throw new NotFoundException("EVENT_NOT_FOUND"); + + if (event.getStatus() != EventBean.Status.ENDED) throw new ConflictException("EVENT_NOT_ENDED"); + + AccountBean acc = (AccountBean) getRequest().getAttributes().get("account"); + + ValidationErrors err = new ValidationErrors(); + + if (entity == null) throw new BadEntityException("Entity not found."); + + err.verifyFieldEmptyness("twitch_token", entity.twitch_token, 1); + + err.checkErrors("LOGIN_ERROR"); + + AccountBean winnerAccount = mEvents.getUserFromRank(mEventId,1); + + if (winnerAccount == null){ + throw new ConflictException("WINNER_NOT_DEFINED"); + } + + int retCode; + try { + HttpGet httpGet = new HttpGet(new URI(mTwitchUsersUrl + acc.getTwitchId() + "/subscriptions/" + winnerAccount.getTwitchId())); + + httpGet.addHeader("Accept", mTwitchAccept); + httpGet.addHeader("Client-ID", mTwitchClientId); + httpGet.addHeader("Authorization", "OAuth " + entity.twitch_token); + + try (CloseableHttpResponse resp = mHttpClient.execute(httpGet, HttpClientContext.create());) { + retCode = resp.getStatusLine().getStatusCode(); + } + + httpGet.releaseConnection(); + + switch (retCode){ + case 404: + throw new NotFoundException("USER_NOT_SUBSCRIBE"); + + case 403: + throw new BadAuthenticationException("TOKEN_NOT_ALLOW_TO_CHECK_SUBSCRIPTION"); + + case 200: + mEvents.updateUserSubscriptionToWinner(mEventId,acc.getTwitchId(),true); + return Status.SUCCESS_OK; + + default: + throw new BadAuthenticationException("BAD_AUTHENTICATION"); + } + + } catch (URISyntaxException | IOException e) { + Main.LOGGER.log(Level.SEVERE, "Impossible to login", e); + throw new InternalServerError("TWITCH_API_ERROR"); + } + } + + private static class LoginBean { + public String twitch_token; + } +} diff --git a/src/main/java/tv/zerator/ffs/api/v1/resources/EventResource.java b/src/main/java/tv/zerator/ffs/api/v1/resources/EventResource.java index 7b5170d..9ff05f4 100644 --- a/src/main/java/tv/zerator/ffs/api/v1/resources/EventResource.java +++ b/src/main/java/tv/zerator/ffs/api/v1/resources/EventResource.java @@ -1,7 +1,17 @@ package tv.zerator.ffs.api.v1.resources; import java.sql.SQLException; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; +import java.util.Comparator; + +import lombok.RequiredArgsConstructor; import org.restlet.data.Status; import org.restlet.resource.Delete; import org.restlet.resource.Get; @@ -21,34 +31,39 @@ public class EventResource extends ServerResource { @DaoInject private static EventsDao mEvents; - + private int mEventId; @Override protected void doInit() throws ResourceException { mEventId = Integer.parseInt(getAttribute("EVENT_ID")); } - + @Get public EventBean getEvent() throws SQLException { EventBean event = mEvents.getEvent(mEventId); if (event == null) throw new NotFoundException("EVENT_NOT_FOUND"); return event; } - + @Put public Status updateEvent(UpdateEventEntity entity) throws SQLException { ValidationUtils.verifyGroup(getRequest(), ApiV1.ADMIN); ValidationErrors err = new ValidationErrors(); - + if (entity == null) throw new BadEntityException("ENTITY_NOT_FOUND"); - + err.verifyFieldEmptyness("name", entity.name, 3, 200); err.verifyFieldEmptyness("description", entity.description, 3, 2048); - + err.checkErrors("EVENT_UPDATE_ERROR"); - + EventBean bean = mEvents.getEvent(mEventId); + + if (entity.status == EventBean.Status.ENDED && bean.getStatus() != EventBean.Status.ENDED){ + rankAllUsers(mEventId); + } + if (bean == null) throw new NotFoundException("EVENT_NOT_FOUND"); bean.setCurrent(entity.current); bean.setDescription(entity.description); @@ -60,16 +75,17 @@ public Status updateEvent(UpdateEventEntity entity) throws SQLException { bean.setMinimumFollowers(entity.minimum_followers); bean.setRankingType(entity.ranking_type); mEvents.update(bean); + return Status.SUCCESS_OK; } - + @Delete public Status deleteEvent() throws SQLException { ValidationUtils.verifyGroup(getRequest(), ApiV1.ADMIN); mEvents.delete(mEventId); return Status.SUCCESS_OK; } - + private static class UpdateEventEntity { public String name, description; public boolean current, reserved_to_affiliates, reserved_to_partners; @@ -77,4 +93,69 @@ private static class UpdateEventEntity { public EventBean.Status status; public EventBean.RankingType ranking_type; } + + private void rankAllUsers(int eventId) throws SQLException { + EventBean event = mEvents.getEvent(mEventId); + List allScores = mEvents.getAllScores(eventId); + + Set lastUsers = new HashSet<>(); + + Map map = new HashMap<>(); + + for (EventsDao.RoundUserScoreBean rus: + allScores) { + if (rus.getScore() == 0){ + lastUsers.add(rus.getId()); + } + if (map.containsKey(rus.getId())){ + map.put(rus.getId(),map.get(rus.getId()) + rus.getScore()); + } else { + map.put(rus.getId(),rus.getScore()); + } + } + + for (Integer userId: + lastUsers) { + map.remove(userId); + } + + List> list = new ArrayList<>(map.entrySet()); + Collections.sort(list, new ScoreUserValueComparator(event.getRankingType())); + + int i = 1; + int currentRank = 1; + Double currentScore = null ; + for (Map.Entry entry: + list) { + + if (currentScore == null || !currentScore.equals(entry.getValue())){ + currentRank = i; + currentScore = entry.getValue(); + } + + mEvents.updateUserRank(mEventId, entry.getKey(), currentRank); + + i++; + } + + for (Integer userId: + lastUsers) { + mEvents.updateUserRank(mEventId, userId, i); + } + + } + + @RequiredArgsConstructor + private static class ScoreUserValueComparator implements Comparator> { + private final EventBean.RankingType rankingType; + + @Override + public int compare(Map.Entry e1, Map.Entry e2) { + if (rankingType.equals(EventBean.RankingType.SCORE_ASC)){ + return Double.compare(e1.getValue(),e2.getValue()); + } else { + return Double.compare(e2.getValue(),e1.getValue()); + } + } + } } diff --git a/src/main/java/tv/zerator/ffs/api/v1/resources/EventUsersResource.java b/src/main/java/tv/zerator/ffs/api/v1/resources/EventUsersResource.java index 8971bcb..63e14a8 100644 --- a/src/main/java/tv/zerator/ffs/api/v1/resources/EventUsersResource.java +++ b/src/main/java/tv/zerator/ffs/api/v1/resources/EventUsersResource.java @@ -96,8 +96,8 @@ public List getUsers() throws SQLException { List users = statusStr != null ? mEvents.getUsers(mEventId, status) : mEvents.getUsers(mEventId); List ret = new ArrayList<>(); - for (AccountStatusBean ac : users) ret.add(isModerator ? new UserRepresentation(ac.getTwitchId(), ac.getViews(), ac.getFollowers(), ac.getGrade(), ac.getRank(), ac.getUsername(), ac.getEmail(), ac.getUrl(), ac.getLogo(), ac.getBroadcasterType(), ac.getStatus()) - : new UserRepresentation(ac.getTwitchId(), ac.getViews(), ac.getFollowers(), ac.getGrade(), ac.getRank(), ac.getUsername(), null, ac.getUrl(), ac.getLogo(), null, ac.getStatus())); + for (AccountStatusBean ac : users) ret.add(isModerator ? new UserRepresentation(ac.getTwitchId(), ac.getViews(), ac.getFollowers(), ac.getGrade(), ac.getRank(), ac.getUsername(), ac.getEmail(), ac.getUrl(), ac.getLogo(), ac.getBroadcasterType(), ac.getStatus(), ac.isSubscribeToWinner()) + : new UserRepresentation(ac.getTwitchId(), ac.getViews(), ac.getFollowers(), ac.getGrade(), ac.getRank(), ac.getUsername(), null, ac.getUrl(), ac.getLogo(), null, ac.getStatus(), ac.isSubscribeToWinner())); return ret; } @@ -166,6 +166,7 @@ public Status registerUser(RegisterUserEntity entity) throws SQLException { private final String username, email, url, logo; private final BroadcasterType broadcasterType; private final EventsDao.UserStatus status; + private final boolean subscribeToWinner; } private static class RegisterUserEntity {