cleanup 3
This commit is contained in:
@@ -156,10 +156,10 @@ sudo mkdir -p /run/secrets
|
|||||||
cd /opt/app/backend
|
cd /opt/app/backend
|
||||||
|
|
||||||
# Check if template file exists
|
# Check if template file exists
|
||||||
ls -la lottery-config.properties.template
|
ls -la honey-config.properties.template
|
||||||
|
|
||||||
# If it exists, copy it
|
# If it exists, copy it
|
||||||
sudo cp lottery-config.properties.template /run/secrets/lottery-config.properties
|
sudo cp honey-config.properties.template /run/secrets/lottery-config.properties
|
||||||
```
|
```
|
||||||
|
|
||||||
**Option 2: Create the file directly (if template wasn't copied)**
|
**Option 2: Create the file directly (if template wasn't copied)**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Lottery Application Configuration
|
# Honey Application Configuration
|
||||||
# Copy this file to /run/secrets/lottery-config.properties on your VPS
|
# Copy this file to /run/secrets/honey-config.properties on your VPS
|
||||||
# Replace all placeholder values with your actual configuration
|
# Replace all placeholder values with your actual configuration
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
@@ -13,9 +13,9 @@
|
|||||||
# * The MySQL service is named 'db', so use 'db' as the hostname
|
# * The MySQL service is named 'db', so use 'db' as the hostname
|
||||||
# * Both containers are on the same Docker network, so 'db' resolves to the MySQL container
|
# * Both containers are on the same Docker network, so 'db' resolves to the MySQL container
|
||||||
# - Port: '3306' (default MySQL port, internal to Docker network)
|
# - Port: '3306' (default MySQL port, internal to Docker network)
|
||||||
# - Database name: 'lottery_db' (must match MYSQL_DATABASE in docker-compose.prod.yml)
|
# - Database name: 'honey_db' (must match MYSQL_DATABASE in docker-compose.prod.yml)
|
||||||
#
|
#
|
||||||
# Example: jdbc:mysql://db:3306/lottery_db
|
# Example: jdbc:mysql://db:3306/honey_db
|
||||||
# └─┬─┘ └┬┘ └─┬──┘ └───┬────┘
|
# └─┬─┘ └┬┘ └─┬──┘ └───┬────┘
|
||||||
# │ │ │ └─ Database name
|
# │ │ │ └─ Database name
|
||||||
# │ │ └─ Port (3306 is MySQL default)
|
# │ │ └─ Port (3306 is MySQL default)
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
#
|
#
|
||||||
# IMPORTANT: Use 'db' as hostname, NOT 'localhost' or '127.0.0.1'
|
# IMPORTANT: Use 'db' as hostname, NOT 'localhost' or '127.0.0.1'
|
||||||
# This is an internal Docker network connection
|
# This is an internal Docker network connection
|
||||||
SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/lottery_db
|
SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/honey_db
|
||||||
SPRING_DATASOURCE_USERNAME=root
|
SPRING_DATASOURCE_USERNAME=root
|
||||||
SPRING_DATASOURCE_PASSWORD=your_secure_database_password_here
|
SPRING_DATASOURCE_PASSWORD=your_secure_database_password_here
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Nginx configuration for Lottery Application
|
# Nginx configuration for Honey Application
|
||||||
# Place this file at: /opt/app/nginx/nginx.conf
|
# Place this file at: /opt/app/nginx/nginx.conf
|
||||||
#
|
#
|
||||||
# This configuration assumes:
|
# This configuration assumes:
|
||||||
|
|||||||
@@ -13,21 +13,21 @@ public class TelegramProperties {
|
|||||||
/**
|
/**
|
||||||
* Bot token for checking channel membership.
|
* Bot token for checking channel membership.
|
||||||
* Can be set via environment variable TELEGRAM_CHANNEL_CHECKER_BOT_TOKEN
|
* Can be set via environment variable TELEGRAM_CHANNEL_CHECKER_BOT_TOKEN
|
||||||
* or in mounted file at /run/secrets/lottery-config.properties as telegram.channel-checker-bot-token
|
* or in mounted file at /run/secrets/honey-config.properties as telegram.channel-checker-bot-token
|
||||||
*/
|
*/
|
||||||
private String channelCheckerBotToken;
|
private String channelCheckerBotToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Channel ID for follow tasks (e.g., "@win_spin_news" or numeric ID).
|
* Channel ID for follow tasks (e.g., "@win_spin_news" or numeric ID).
|
||||||
* Can be set via environment variable TELEGRAM_FOLLOW_TASK_CHANNEL_ID
|
* Can be set via environment variable TELEGRAM_FOLLOW_TASK_CHANNEL_ID
|
||||||
* or in mounted file at /run/secrets/lottery-config.properties as telegram.follow-task-channel-id
|
* or in mounted file at /run/secrets/honey-config.properties as telegram.follow-task-channel-id
|
||||||
*/
|
*/
|
||||||
private String followTaskChannelId;
|
private String followTaskChannelId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Channel ID for follow withdrawals channel task (e.g., "@win_spin_withdrawals" or numeric ID).
|
* Channel ID for follow withdrawals channel task (e.g., "@win_spin_withdrawals" or numeric ID).
|
||||||
* Can be set via environment variable TELEGRAM_FOLLOW_TASK_CHANNEL_ID_2
|
* Can be set via environment variable TELEGRAM_FOLLOW_TASK_CHANNEL_ID_2
|
||||||
* or in mounted file at /run/secrets/lottery-config.properties as telegram.follow-task-channel-id-2
|
* or in mounted file at /run/secrets/honey-config.properties as telegram.follow-task-channel-id-2
|
||||||
*/
|
*/
|
||||||
private String followTaskChannelId2;
|
private String followTaskChannelId2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public API for the lottery app: list and view promotion details (leaderboard, user progress).
|
* Public API: list and view promotion details (leaderboard, user progress).
|
||||||
* Excludes INACTIVE promotions. Requires Bearer auth (app user).
|
* Excludes INACTIVE promotions. Requires Bearer auth (app user).
|
||||||
* When promotions feature switch is false, all endpoints return 404.
|
* When promotions feature switch is false, all endpoints return 404.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ public class AdminTransactionDto {
|
|||||||
private Long amount; // In bigint format
|
private Long amount; // In bigint format
|
||||||
private String type;
|
private String type;
|
||||||
private Integer taskId;
|
private Integer taskId;
|
||||||
private Long roundId;
|
|
||||||
private Instant createdAt;
|
private Instant createdAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.honey.honey.dto;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO for a single game history entry.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class GameHistoryEntryDto {
|
|
||||||
/**
|
|
||||||
* Amount in bigint format (positive for wins, negative for losses).
|
|
||||||
* Example: +900000000 means +900.0000 (win of 900 tickets)
|
|
||||||
* Example: -100000000 means -100.0000 (loss of 100 tickets)
|
|
||||||
*/
|
|
||||||
private Long amount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date formatted as dd.MM at HH:mm (e.g., "13.01 at 22:29")
|
|
||||||
*/
|
|
||||||
private String date;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package com.honey.honey.exception;
|
|
||||||
|
|
||||||
public class InsufficientBalanceException extends GameException {
|
|
||||||
public InsufficientBalanceException(String localizedMessage) {
|
|
||||||
super(localizedMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.honey.honey.exception;
|
|
||||||
|
|
||||||
import com.honey.honey.service.LocalizationService;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception for invalid bet amounts.
|
|
||||||
* Uses localization service to get user's language preference.
|
|
||||||
*/
|
|
||||||
public class InvalidBetAmountException extends GameException {
|
|
||||||
public InvalidBetAmountException(String localizedMessage) {
|
|
||||||
super(localizedMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to create exception with localized message.
|
|
||||||
* Converts bigint values to display format (divide by 1,000,000).
|
|
||||||
*/
|
|
||||||
public static InvalidBetAmountException create(LocalizationService localizationService, long minBet, long maxBet) {
|
|
||||||
// Convert bigint to display format for user-friendly message
|
|
||||||
double minBetDisplay = minBet / 1_000_000.0;
|
|
||||||
double maxBetDisplay = maxBet / 1_000_000.0;
|
|
||||||
String message = localizationService.getMessage("game.error.invalidBetAmount",
|
|
||||||
String.format("%.2f", minBetDisplay),
|
|
||||||
String.format("%.2f", maxBetDisplay));
|
|
||||||
return new InvalidBetAmountException(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package com.honey.honey.exception;
|
|
||||||
|
|
||||||
import com.honey.honey.model.GamePhase;
|
|
||||||
import com.honey.honey.service.LocalizationService;
|
|
||||||
|
|
||||||
public class RoomNotJoinableException extends GameException {
|
|
||||||
public RoomNotJoinableException(GamePhase currentPhase, LocalizationService localizationService) {
|
|
||||||
super(localizationService.getMessage("game.error.roomNotJoinable"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.honey.honey.exception;
|
|
||||||
|
|
||||||
public class UserAlreadyJoinedException extends GameException {
|
|
||||||
public UserAlreadyJoinedException() {
|
|
||||||
super("You have already joined this round. Please wait for the next round.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.honey.honey.model;
|
|
||||||
|
|
||||||
public enum GamePhase {
|
|
||||||
WAITING, // Zero or one player joined
|
|
||||||
COUNTDOWN, // 30 seconds countdown started
|
|
||||||
SPINNING, // Spin animation in progress
|
|
||||||
RESOLUTION // Winner resolved, payout applied
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -606,7 +606,6 @@ public class AdminUserService {
|
|||||||
.amount(t.getAmount())
|
.amount(t.getAmount())
|
||||||
.type(t.getType().name())
|
.type(t.getType().name())
|
||||||
.taskId(t.getTaskId())
|
.taskId(t.getTaskId())
|
||||||
.roundId(t.getRoundId())
|
|
||||||
.createdAt(t.getCreatedAt())
|
.createdAt(t.getCreatedAt())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +1,15 @@
|
|||||||
package com.honey.honey.service;
|
package com.honey.honey.service;
|
||||||
|
|
||||||
import com.honey.honey.model.Configuration;
|
|
||||||
import com.honey.honey.repository.ConfigurationRepository;
|
import com.honey.honey.repository.ConfigurationRepository;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configurations: key-value store for app-wide settings (e.g. lottery_bot_max_participants_before_join).
|
* Configurations: key-value store for app-wide settings.
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ConfigurationService {
|
public class ConfigurationService {
|
||||||
|
|
||||||
public static final String KEY_BOT_MAX_PARTICIPANTS_BEFORE_JOIN = "lottery_bot_max_participants_before_join";
|
|
||||||
private static final int DEFAULT_MAX_PARTICIPANTS_BEFORE_JOIN = 1;
|
|
||||||
private static final int MIN_MAX_PARTICIPANTS = 0;
|
|
||||||
private static final int MAX_MAX_PARTICIPANTS = 10;
|
|
||||||
|
|
||||||
private final ConfigurationRepository configurationRepository;
|
private final ConfigurationRepository configurationRepository;
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public int getMaxParticipantsBeforeBotJoin() {
|
|
||||||
return configurationRepository.findById(KEY_BOT_MAX_PARTICIPANTS_BEFORE_JOIN)
|
|
||||||
.map(c -> parsePositiveInt(c.getValue(), DEFAULT_MAX_PARTICIPANTS_BEFORE_JOIN))
|
|
||||||
.orElse(DEFAULT_MAX_PARTICIPANTS_BEFORE_JOIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public int setMaxParticipantsBeforeBotJoin(int value) {
|
|
||||||
int clamped = Math.max(MIN_MAX_PARTICIPANTS, Math.min(MAX_MAX_PARTICIPANTS, value));
|
|
||||||
Configuration c = configurationRepository.findById(KEY_BOT_MAX_PARTICIPANTS_BEFORE_JOIN)
|
|
||||||
.orElseGet(() -> {
|
|
||||||
Configuration newConfig = new Configuration();
|
|
||||||
newConfig.setKey(KEY_BOT_MAX_PARTICIPANTS_BEFORE_JOIN);
|
|
||||||
return newConfig;
|
|
||||||
});
|
|
||||||
c.setValue(String.valueOf(clamped));
|
|
||||||
configurationRepository.save(c);
|
|
||||||
return clamped;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int parsePositiveInt(String value, int defaultValue) {
|
|
||||||
if (value == null || value.isBlank()) return defaultValue;
|
|
||||||
try {
|
|
||||||
int v = Integer.parseInt(value.trim());
|
|
||||||
return Math.max(MIN_MAX_PARTICIPANTS, Math.min(MAX_MAX_PARTICIPANTS, v));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class DataCleanupService {
|
|||||||
log.debug("Deleted {} old transactions in batch {}", deleted, batchesProcessed);
|
log.debug("Deleted {} old transactions in batch {}", deleted, batchesProcessed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sleep between batches to let database process WebSocket inserts
|
// Sleep between batches between batches
|
||||||
if (deleted > 0 && batchesProcessed < maxBatchesPerRun) {
|
if (deleted > 0 && batchesProcessed < maxBatchesPerRun) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(batchSleepMs);
|
Thread.sleep(batchSleepMs);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class LocalizationService {
|
|||||||
/**
|
/**
|
||||||
* Gets a localized message for the current user.
|
* Gets a localized message for the current user.
|
||||||
*
|
*
|
||||||
* @param code Message code (e.g., "game.error.roomNotFound")
|
* @param code Message code (e.g., "error.code")
|
||||||
* @param args Optional arguments for message formatting
|
* @param args Optional arguments for message formatting
|
||||||
* @return Localized message string
|
* @return Localized message string
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class TelegramService {
|
|||||||
* Requires channelCheckerBotToken to be configured.
|
* Requires channelCheckerBotToken to be configured.
|
||||||
*
|
*
|
||||||
* @param telegramUserId Telegram user ID
|
* @param telegramUserId Telegram user ID
|
||||||
* @param chatId Chat ID (can be channel username like "@lottery_2026_test_channel" or numeric ID)
|
* @param chatId Chat ID (can be channel username like "@honey_channel" or numeric ID)
|
||||||
* @return true if user is a member (member, administrator, or creator), false otherwise
|
* @return true if user is a member (member, administrator, or creator), false otherwise
|
||||||
* @throws IllegalStateException if channelCheckerBotToken is not configured
|
* @throws IllegalStateException if channelCheckerBotToken is not configured
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
-- Set initial balance_a default value to 3,000,000 (3.00 tickets)
|
|
||||||
-- This represents 3 tickets in bigint format (1 ticket = 1,000,000)
|
|
||||||
ALTER TABLE `db_users_b`
|
|
||||||
MODIFY COLUMN `balance_a` BIGINT UNSIGNED NOT NULL DEFAULT 3000000;
|
|
||||||
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
-- Set initial balance_a default value to 5,000,000 (5.00 tickets)
|
|
||||||
-- New users get 5 tickets on registration (1 ticket = 1,000,000 in bigint)
|
|
||||||
ALTER TABLE `db_users_b`
|
|
||||||
MODIFY COLUMN `balance_a` BIGINT UNSIGNED NOT NULL DEFAULT 5000000;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
-- Feature switches: no seeds (kept empty).
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
-- Promotions: no seeds (tables created in V56).
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
-- Feature switches: no seeds (kept empty).
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<property name="LOG_DIR" value="${LOG_DIR:-./logs}"/>
|
<property name="LOG_DIR" value="${LOG_DIR:-./logs}"/>
|
||||||
|
|
||||||
<!-- Property: Application name -->
|
<!-- Property: Application name -->
|
||||||
<property name="APP_NAME" value="lottery-be"/>
|
<property name="APP_NAME" value="honey-be"/>
|
||||||
|
|
||||||
<!-- Console Appender (for development/local) -->
|
<!-- Console Appender (for development/local) -->
|
||||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
|||||||
Reference in New Issue
Block a user