Compare commits

253 Commits

Author SHA1 Message Date
Chang lue Tsen 3fb23e3106 refactor(adapter): delete old adapter 2025-09-29 11:22:36 -04:00
Chang lue Tsen 766e210f06 fix(node): update FilterNodeParams to use NodeId and adjust query logic for tags 2025-09-29 11:18:47 -04:00
Chang lue Tsen 2de76104ad fix(tests): update time format in TestNewNodeMultiplierManager and add new time period 2025-09-29 15:18:58 +09:00
Chang lue Tsen 453ad18303 feat(node): add PreViewNodeMultiplier endpoint and response structure 2025-09-29 13:12:37 +09:00
Chang lue Tsen 02f0d711ba fix(manager): update time parsing format in isInTimePeriod function 2025-09-29 13:11:51 +09:00
Chang lue Tsen d6fcff1fee fix(node): NodeId filter to FilterNodeParams and update cache clearing logic 2025-09-29 10:22:11 +09:00
Ember Moth 25c7eb3927 fix(purchase): resolve balance payment transaction inconsistency causing Internal Server Error (#81) 2025-09-28 12:34:18 -04:00
Chang lue Tsen 9777a0c61a fix(purchase): update payment processing to use CryptoSaaSPayment method 2025-09-28 12:28:44 -04:00
Chang lue Tsen d74d636735 feat(traffic): add protocol handling and update traffic statistics calculation 2025-09-28 11:31:21 -04:00
Chang lue Tsen 5aa9bb61b7 refactor(server): remove Ratio field from Server struct and update adapter logic 2025-09-28 11:18:33 -04:00
Chang lue Tsen 42a31048b4 fix(subscribe): ignore subscription expiration check in Generate Subscribe 2025-09-28 11:14:54 -04:00
Chang lue Tsen 0179e9837c refactor(api): remove Ratio field from NodeConfig and related structures 2025-09-28 11:14:43 -04:00
Chang lue Tsen 0d1df5f905 feat(config): enhance NodeConfig with TrafficReportThreshold, IPStrategy, DNS, Block, and Outbound fields 2025-09-28 19:06:29 +09:00
Chang lue Tsen 64f0bcc55a feat(cache): implement cache clearing for node operations and add delete methods 2025-09-27 11:24:29 -04:00
Chang lue Tsen d2ca3eb961 fix(subscribe): add Enabled filter to node query parameters 2025-09-27 10:18:08 -04:00
Chang lue Tsen c1c324878b fix(traffic): skip logs with zero upload and download values 2025-09-27 10:16:28 -04:00
Chang lue Tsen 5ca4179285 feat(user): add OnlyFirstPurchase field to user creation logic 2025-09-27 10:13:41 -04:00
Chang lue Tsen 9ce6141b5a fix(log): correct model reference in SystemLog creation 2025-09-27 10:11:58 -04:00
Chang lue Tsen 56352de870 chore(deploy): comment out server deployment steps in workflow 2025-09-27 10:11:10 -04:00
Chang lue Tsen 4ad18a8b70 fix(model): update save method to use specific ID for record updates 2025-09-16 11:20:48 -04:00
Chang lue Tsen 596434454c feat(client): add additional options for Shadowsocks and Vless protocols 2025-09-16 11:20:39 -04:00
Chang lue Tsen b5c756af35 feat(subscribe): update subscribe path 2025-09-16 10:39:19 -04:00
Chang lue Tsen 621eda41c2 fix(client): Shadowrocket template 2025-09-16 10:26:39 -04:00
Chang lue Tsen 900096ed12 fix(coupon): add check for zero count in coupon usage validation 2025-09-16 10:17:18 -04:00
Chang lue Tsen 26fe430d7c fix(subscribe): update status filter in subscription count query 2025-09-16 10:16:56 -04:00
Chang lue Tsen 0c55d173cb fix(model): add sorting to server and node queries 2025-09-16 10:10:11 -04:00
Chang lue Tsen 537dab1c3b fix(quota): simplify gift amount calculation 2025-09-16 09:53:03 -04:00
Leif Draven 4b2976a670 fix(schema): remove unnecessary AUTO_INCREMENT values from initial schema (#79)
Co-authored-by: Chang lue Tsen <tension@ppanel.dev>
2025-09-16 09:33:28 -04:00
Chang lue Tsen 38491ddc0d Merge branch 'master' into develop 2025-09-14 11:34:07 -04:00
Leif Draven e895180388 Develop (#76)
* refactor: rename queryannouncementhandler.go to queryAnnouncementLogic.go for clarity

* feat(panDomain): update subscription logic to use V2 handler for improved functionality

* refactor(subscribe): replace V2 handler with a unified Handler method for subscription logic

* feat(subscribe): implement user agent limit feature with configurable list

* fix(subscribe): improve error handling and logging for subscription requests

* feat(subscribe): add user agent limit configuration to system settings

* refactor(api): remove deprecated application-related endpoints and types

* refactor(swagger): remove deprecated app.json generation from swagger configuration

* refactor(swagger): remove deprecated app.json check from swagger configuration

* fix(subscribe): update delete method to use Where clause for improved query accuracy

* fix(subscribe): update Id field tag to use primaryKey and improve save method query

* fix(subscribe): update Id field tag to use primaryKey and improve model queries

* fix(subscribe): rename variable for clarity and add special handling for Stash user agent

* fix(email): convert RegisterStartTime and RegisterEndTime to time.Time for accurate query filtering

* refactor(log): consolidate logging models and update related logic for improved clarity and functionality

* fix(types): change Content field type in MessageLog to interface{} for improved flexibility

* fix(log): change MessageLog list to use value type for improved performance and memory efficiency

* fix(email): set EmailTypeVerify in task payload and update content type conversion for verification email

* fix(log): remove unused Id field from SystemLog during login log insertion

* fix(login): remove debug logs and error logging during user login process

* fix(log): add traffic reset logging for subscription resets

* fix(log): insert reset traffic log during subscription activation

* feat(log): add endpoints for retrieving and resetting subscribe traffic logs

* refactor(log): remove Reset Subscribe Traffic Log endpoint and related types

* feat(traffic): add traffic statistics logging and scheduling

* fix(subscribe): ensure active status and reset timestamps during traffic resets

* feat(api): enhance server and node management with new request/response structures

* refactor(api): rename OnlineUser to ServerOnlineUser for clarity

* feat(api): define OnlineUser type with SID and IP fields

* feat(server): implement server management handlers and database schema

* feat(api): add traffic log details filtering and enhance traffic log structures

* feat(api): migrate server and node data handling, update related structures and logic

* feat(server): implement server deletion logic with error handling

* feat(api): update log filtering to use ResetSubscribe type for subscription logs

* feat(api): standardize timestamp field across log structures

* feat(api): refactor cache key handling for server and user lists

* feat(api): enhance server status handling with protocol support and refactor related logic

* fix(traffic): adjust start date for traffic statistics and improve log deletion comment

* feat(api): implement daily traffic ranking for users and servers with error handling

* feat(api): update server total data response to use 'OnlineUsers' and implement daily traffic statistics logging

* feat(api): add log settings management with auto-clear and clear days configuration

* fix(log): correct category in log settings update query

* feat(routes): add handler for scheduled traffic statistics

* feat(model): add user counts struct and update queries for new and renewal users

* feat(api): add referral percentage and only first purchase fields to user model and requests

* feat(database): update user table to add referral percentage and only first purchase fields

* feat(api): add reset sort endpoints for server and node

* feat(api): add sort field to server model

* feat(api): implement sorting functionality for nodes and servers

* fix(database): add sort column to nodes table

* fix(model): enhance user statistics queries with new order and renewal order counts

* fix(log): update timestamp handling in login and registration logs

* fix(log): update sorting logic for server and user subscribe traffic logs

* fix(server): add server status handling based on last reported time

* fix(model): correct filter condition to use 'date' instead of 'data'

* fix(migration): add index for traffic log on timestamp, user_id, and subscribe_id

* fix(log): optimize user traffic rank data handling by using append instead of index assignment

* fix(filter): refactor node list creation to use append and remove duplicates from tags

* fix(node): add ServerId and Enabled fields to node update logic

* feat(tags): add endpoint to query all node tags

* fix(preview): add Preload parameter to FilterNodeList for improved data retrieval

* fix(log): date is empty

* feat(subscribe): add Language field to subscription models and update query logic

* feat(subscription): add Language parameter to GetSubscription request and update query logic

* fix(server): encode ServerKey in base64 and update last reported time for nodes

* feat: delete common GetSubscription

* feat(subscription): implement FilterList method for subscription queries and update related logic

* fix(subscribe): remove duplicate user agents in SubscribeHandler

* fix(push): initialize onlineUsers as a map in pushOnlineUsersLogic

* fix(reset): initialize subs as a map in clearCache method

* refactor(query): simplify node and tag filtering using InSet function

* feat(userlist): enhance GetServerUserListLogic with improved node and tag handling

* fix(userlist): correct node ID assignment and update query logic for tag filtering

* fix(userlist): correct node ID assignment in getServerUserListLogic

* refactor(query): streamline query construction for tag filtering

* fix(statistics): optimize server ranking data handling in QueryServerTotalDataLogic

* refactor(statistics): simplify server ranking data construction in QueryServerTotalDataLogic

* fix(statistics): correct server traffic data assignment in QueryServerTotalDataLogic

* fix(statistics): optimize yesterday's top 10 server traffic data assignment in QueryServerTotalDataLogic

* fix(middleware): remove duplicate elements from user agent list in PanDomainMiddleware

* feat(middleware): enhance user agent handling by querying client list in PanDomainMiddleware

* feat(client): subscribe_template

* feat(oauth): add user agent and IP logging to registration and login processes

* fix(balance): add timestamp to balance logs for payment, refund, and recharge transactions

* fix(log): correct comment for CommissionTypeRefund to improve clarity

* fix(log): replace magic number with constant for gift type in purchase checkout logic

* fix(log): rename OrderId to OrderNo for consistency in balance logging

* feat(log): add logging for balance, gift amount, and commission adjustments

* fix(user): correct placement of DeepCopy for user info update logic

* feat(log): add UserSubscribeId to FilterSubscribeLogRequest for enhanced filtering

* fix(purchase): streamline error handling and improve JSON marshaling for temporary orders

* fix(order): simplify commission handling and improve payload parsing logic

* fix(order): update commission calculation to actual payment amount minus gateway handling fee

* feat(payment): add support for CryptoSaaS payment platform and enhance configuration handling

* fix(balance): update QueryUserBalanceLog response structure to include balance log list

* fix(email): update task progress handling to use specific task ID for updates

* feat(quota): add quota task creation and querying endpoints with updated data structures

* fix(email): update task handling to use generic task model and improve error logging

* fix(order): improve error logging for database transaction and user cache updates

* feat(quota): enhance quota task management with new request structures and processing logic

* fix(quota): remove redundant quota task status endpoint from admin marketing routes

* fix(worker): update task completion status handling in worker logic

* fix(quota): update taskInfo to include current subscription count in quota logic

* doc(log): rename function for clarity and add cache cleanup comment

* fix(quota): update time handling in quota logic and correct subscriber ID query

* fix(quota): update time handling to use UnixMilli for start time in quota logic

* feat(protocol): add server protocol configuration query and enhance protocol options

* fix(quota): correct time range queries for start and expire times in quota logic

* fix(types): update plugin options to include 'none' in the plugin field

---------

Co-authored-by: Chang lue Tsen <tension@ppanel.dev>
2025-09-14 09:50:22 -04:00
Chang lue Tsen 435283f962 fix(types): update plugin options to include 'none' in the plugin field 2025-09-14 09:46:14 -04:00
Chang lue Tsen b0ffb15825 fix(quota): correct time range queries for start and expire times in quota logic 2025-09-14 09:43:21 -04:00
Chang lue Tsen 2c5efa2026 feat(protocol): add server protocol configuration query and enhance protocol options 2025-09-13 14:20:04 -04:00
Chang lue Tsen c1c913cb00 fix(quota): update time handling to use UnixMilli for start time in quota logic 2025-09-13 14:12:33 -04:00
Chang lue Tsen cf4792cdc8 fix(quota): update time handling in quota logic and correct subscriber ID query 2025-09-13 14:02:49 -04:00
Chang lue Tsen 9b0e1b1e0f doc(log): rename function for clarity and add cache cleanup comment 2025-09-11 11:42:20 -04:00
Chang lue Tsen 6bc0fb4d90 fix(quota): update taskInfo to include current subscription count in quota logic 2025-09-11 06:29:12 -04:00
Chang lue Tsen 32633920b5 fix(worker): update task completion status handling in worker logic 2025-09-11 06:24:52 -04:00
Chang lue Tsen d55bad712c fix(quota): remove redundant quota task status endpoint from admin marketing routes 2025-09-10 14:54:31 -04:00
Chang lue Tsen 3f5aac239b feat(quota): enhance quota task management with new request structures and processing logic 2025-09-10 14:53:48 -04:00
Chang lue Tsen 83c1c14b01 fix(order): improve error logging for database transaction and user cache updates 2025-09-10 10:41:29 -04:00
Chang lue Tsen 1c1365d862 fix(email): update task handling to use generic task model and improve error logging 2025-09-10 09:02:54 -04:00
Chang lue Tsen d1be5febc3 feat(quota): add quota task creation and querying endpoints with updated data structures 2025-09-09 13:39:05 -04:00
Chang lue Tsen f4c6bd919b fix(email): update task progress handling to use specific task ID for updates 2025-09-08 12:53:28 -04:00
Chang lue Tsen 31cdcd2cb9 fix(balance): update QueryUserBalanceLog response structure to include balance log list 2025-09-07 11:59:34 -04:00
Chang lue Tsen 4d95834c22 feat(payment): add support for CryptoSaaS payment platform and enhance configuration handling 2025-09-06 12:22:39 -04:00
Chang lue Tsen 47446ef410 fix(order): update commission calculation to actual payment amount minus gateway handling fee 2025-09-06 11:41:17 -04:00
Chang lue Tsen 0872099e98 fix(order): simplify commission handling and improve payload parsing logic 2025-09-06 11:28:32 -04:00
Chang lue Tsen d5ed82955e fix(purchase): streamline error handling and improve JSON marshaling for temporary orders 2025-09-06 11:03:14 -04:00
Chang lue Tsen d477ba4772 feat(log): add UserSubscribeId to FilterSubscribeLogRequest for enhanced filtering 2025-09-05 13:35:55 -04:00
Chang lue Tsen 6460f2f2e1 fix(user): correct placement of DeepCopy for user info update logic 2025-09-05 11:14:38 -04:00
Chang lue Tsen 0199dc7fa2 feat(log): add logging for balance, gift amount, and commission adjustments 2025-09-05 11:00:19 -04:00
Chang lue Tsen 1d878592ed fix(log): rename OrderId to OrderNo for consistency in balance logging 2025-09-05 10:25:19 -04:00
Chang lue Tsen d0d03e724e fix(log): replace magic number with constant for gift type in purchase checkout logic 2025-09-05 09:52:45 -04:00
Chang lue Tsen 2f4cc46a38 fix(log): correct comment for CommissionTypeRefund to improve clarity 2025-09-05 09:51:28 -04:00
Chang lue Tsen 3199dc5141 fix(balance): add timestamp to balance logs for payment, refund, and recharge transactions 2025-09-05 09:29:19 -04:00
Chang lue Tsen 71d32d73bb feat(oauth): add user agent and IP logging to registration and login processes 2025-09-05 09:26:10 -04:00
Chang lue Tsen 584067375b feat(client): subscribe_template 2025-09-05 05:13:30 -04:00
Chang lue Tsen b9ef8f4572 feat(middleware): enhance user agent handling by querying client list in PanDomainMiddleware 2025-09-05 04:28:05 -04:00
Chang lue Tsen f3c73a5224 fix(middleware): remove duplicate elements from user agent list in PanDomainMiddleware 2025-09-05 04:16:33 -04:00
Chang lue Tsen 51335f4c19 fix(statistics): optimize yesterday's top 10 server traffic data assignment in QueryServerTotalDataLogic 2025-09-04 15:31:19 -04:00
Chang lue Tsen 7912d2908f fix(statistics): correct server traffic data assignment in QueryServerTotalDataLogic 2025-09-04 15:26:52 -04:00
Chang lue Tsen e913f974bb refactor(statistics): simplify server ranking data construction in QueryServerTotalDataLogic 2025-09-04 15:21:07 -04:00
Chang lue Tsen e8d3ebba68 fix(statistics): optimize server ranking data handling in QueryServerTotalDataLogic 2025-09-04 15:11:12 -04:00
Chang lue Tsen b4a05166a4 refactor(query): streamline query construction for tag filtering 2025-09-04 14:17:26 -04:00
Chang lue Tsen 712e31cc60 fix(userlist): correct node ID assignment in getServerUserListLogic 2025-09-04 14:09:17 -04:00
Chang lue Tsen 60988bc2ba fix(userlist): correct node ID assignment and update query logic for tag filtering 2025-09-04 14:05:04 -04:00
Chang lue Tsen 61ac829c37 feat(userlist): enhance GetServerUserListLogic with improved node and tag handling 2025-09-04 13:46:24 -04:00
Chang lue Tsen 805fca90e0 refactor(query): simplify node and tag filtering using InSet function 2025-09-04 13:08:57 -04:00
Chang lue Tsen ef7491d025 fix(reset): initialize subs as a map in clearCache method 2025-09-04 12:32:28 -04:00
Chang lue Tsen a2d8d7d0bd fix(push): initialize onlineUsers as a map in pushOnlineUsersLogic 2025-09-04 12:13:55 -04:00
Chang lue Tsen e798f8de1b fix(subscribe): remove duplicate user agents in SubscribeHandler 2025-09-04 11:38:46 -04:00
Chang lue Tsen 0636a4bddf feat(subscription): implement FilterList method for subscription queries and update related logic 2025-09-04 10:20:35 -04:00
Chang lue Tsen 8f11380e7a feat: delete common GetSubscription 2025-09-04 09:32:39 -04:00
Chang lue Tsen 7ecf955eb7 fix(server): encode ServerKey in base64 and update last reported time for nodes 2025-09-04 09:26:50 -04:00
Chang lue Tsen 10757612f5 feat(subscription): add Language parameter to GetSubscription request and update query logic 2025-09-04 03:14:31 -04:00
Chang lue Tsen f632ea2c89 feat(subscribe): add Language field to subscription models and update query logic 2025-09-03 15:44:04 -04:00
Chang lue Tsen f8e6cf515e fix(log): date is empty 2025-09-03 12:35:32 -04:00
Chang lue Tsen 73ffd0d1c7 fix(preview): add Preload parameter to FilterNodeList for improved data retrieval 2025-09-03 12:09:14 -04:00
Chang lue Tsen 1f824fd5a9 feat(tags): add endpoint to query all node tags 2025-09-03 11:57:12 -04:00
Chang lue Tsen 42df466104 fix(node): add ServerId and Enabled fields to node update logic 2025-09-03 09:49:57 -04:00
Chang lue Tsen 68000574b2 fix(filter): refactor node list creation to use append and remove duplicates from tags 2025-09-03 09:42:42 -04:00
Chang lue Tsen 64366d0dec fix(log): optimize user traffic rank data handling by using append instead of index assignment 2025-09-03 09:20:26 -04:00
Chang lue Tsen 949efdad34 fix(migration): add index for traffic log on timestamp, user_id, and subscribe_id 2025-09-03 07:03:37 -04:00
Chang lue Tsen 107fe82f10 fix(model): correct filter condition to use 'date' instead of 'data' 2025-09-03 06:49:55 -04:00
Chang lue Tsen ca344a1ce9 fix(server): add server status handling based on last reported time 2025-09-02 14:38:53 -04:00
Chang lue Tsen 3e5284c4ec fix(log): update sorting logic for server and user subscribe traffic logs 2025-09-02 14:29:50 -04:00
Chang lue Tsen fe629e59dd fix(log): update timestamp handling in login and registration logs 2025-09-02 14:12:06 -04:00
Chang lue Tsen d578dca17e fix(model): enhance user statistics queries with new order and renewal order counts 2025-09-02 14:06:26 -04:00
Chang lue Tsen ff574b3955 fix(database): add sort column to nodes table 2025-09-02 11:51:07 -04:00
Chang lue Tsen 26b2afe06d feat(api): implement sorting functionality for nodes and servers 2025-09-01 13:13:07 -04:00
Chang lue Tsen d4850a73f3 feat(api): add sort field to server model 2025-09-01 12:24:15 -04:00
Chang lue Tsen 367ef9d2e7 feat(api): add reset sort endpoints for server and node 2025-09-01 11:41:34 -04:00
Chang lue Tsen e910d0e345 feat(database): update user table to add referral percentage and only first purchase fields 2025-09-01 09:40:33 -04:00
Chang lue Tsen aea20ffd5e feat(api): add referral percentage and only first purchase fields to user model and requests 2025-09-01 09:03:39 -04:00
Chang lue Tsen 4438b05272 feat(model): add user counts struct and update queries for new and renewal users 2025-09-01 08:25:53 -04:00
Chang lue Tsen 1745c7194b feat(routes): add handler for scheduled traffic statistics 2025-09-01 08:14:57 -04:00
Chang lue Tsen 4432115844 fix(log): correct category in log settings update query 2025-09-01 06:31:41 -04:00
Chang lue Tsen b6cae7bbb5 feat(api): add log settings management with auto-clear and clear days configuration 2025-09-01 06:11:35 -04:00
Chang lue Tsen 4184a32c0f feat(api): update server total data response to use 'OnlineUsers' and implement daily traffic statistics logging 2025-09-01 05:30:05 -04:00
Chang lue Tsen 9ff965bbea feat(api): implement daily traffic ranking for users and servers with error handling 2025-09-01 05:03:02 -04:00
Chang lue Tsen 8a37472e61 fix(traffic): adjust start date for traffic statistics and improve log deletion comment 2025-09-01 05:02:53 -04:00
Chang lue Tsen 3012a68339 feat(api): enhance server status handling with protocol support and refactor related logic 2025-09-01 04:17:33 -04:00
Chang lue Tsen 6dc1bee14c feat(api): refactor cache key handling for server and user lists 2025-08-31 11:29:55 -04:00
Chang lue Tsen 82fd674ae4 feat(api): standardize timestamp field across log structures 2025-08-26 14:39:54 -04:00
Chang lue Tsen 88cbfbb7d6 feat(api): update log filtering to use ResetSubscribe type for subscription logs 2025-08-26 14:26:55 -04:00
Chang lue Tsen 92466d62a4 feat(server): implement server deletion logic with error handling 2025-08-26 10:49:03 -04:00
Chang lue Tsen c7884d94aa feat(api): migrate server and node data handling, update related structures and logic 2025-08-26 07:05:59 -04:00
Chang lue Tsen 9b3cdbbb4f feat(api): add traffic log details filtering and enhance traffic log structures 2025-08-26 02:29:25 -04:00
Chang lue Tsen ad4f3df74e feat(server): implement server management handlers and database schema 2025-08-25 14:06:37 -04:00
lyndon986 b5e244d83d renew readme_zh.md 2025-08-26 01:57:50 +10:00
lyndon986 2acbdbc9e0 renew README.md 2025-08-26 01:56:34 +10:00
Chang lue Tsen 1ccbdc18b1 feat(api): define OnlineUser type with SID and IP fields 2025-08-25 11:16:39 -04:00
Chang lue Tsen 630098bfbb refactor(api): rename OnlineUser to ServerOnlineUser for clarity 2025-08-25 11:16:25 -04:00
Chang lue Tsen 7bd026a600 feat(api): enhance server and node management with new request/response structures 2025-08-25 10:10:13 -04:00
Chang lue Tsen d5460d0cd1 fix(subscribe): ensure active status and reset timestamps during traffic resets 2025-08-23 09:07:56 -04:00
Chang lue Tsen d33f4cd1ce feat(traffic): add traffic statistics logging and scheduling 2025-08-21 14:11:03 -04:00
Chang lue Tsen 6b1b365734 refactor(log): remove Reset Subscribe Traffic Log endpoint and related types 2025-08-21 11:19:45 -04:00
Chang lue Tsen 062533412a feat(log): add endpoints for retrieving and resetting subscribe traffic logs 2025-08-21 11:02:11 -04:00
Chang lue Tsen ec4e95451b fix(log): insert reset traffic log during subscription activation 2025-08-21 10:53:12 -04:00
Chang lue Tsen fcdb9f72ef fix(log): add traffic reset logging for subscription resets 2025-08-21 10:35:40 -04:00
Chang lue Tsen 7c707f2ecf fix(login): remove debug logs and error logging during user login process 2025-08-21 09:18:14 -04:00
Chang lue Tsen 70815c0d50 fix(log): remove unused Id field from SystemLog during login log insertion 2025-08-21 09:15:37 -04:00
Chang lue Tsen 38706c0b29 fix(email): set EmailTypeVerify in task payload and update content type conversion for verification email 2025-08-21 09:07:48 -04:00
Chang lue Tsen 5e903868c4 fix(log): change MessageLog list to use value type for improved performance and memory efficiency 2025-08-21 08:49:13 -04:00
Chang lue Tsen c04923015e fix(types): change Content field type in MessageLog to interface{} for improved flexibility 2025-08-21 08:24:30 -04:00
Chang lue Tsen 87c771bbd4 refactor(log): consolidate logging models and update related logic for improved clarity and functionality 2025-08-20 13:36:06 -04:00
Chang lue Tsen 4f32d67113 fix(email): convert RegisterStartTime and RegisterEndTime to time.Time for accurate query filtering 2025-08-20 08:22:48 -04:00
Chang lue Tsen bc1e6315a8 fix(subscribe): rename variable for clarity and add special handling for Stash user agent 2025-08-18 02:54:00 -04:00
Chang lue Tsen 3a98616093 fix(subscribe): update Id field tag to use primaryKey and improve model queries 2025-08-18 02:33:17 -04:00
Chang lue Tsen 41c51fbbff fix(subscribe): update Id field tag to use primaryKey and improve save method query 2025-08-18 02:30:35 -04:00
Chang lue Tsen 3bb83edf05 fix(subscribe): update delete method to use Where clause for improved query accuracy 2025-08-18 02:09:15 -04:00
Chang lue Tsen 245f347d22 refactor(swagger): remove deprecated app.json check from swagger configuration 2025-08-17 12:39:17 -04:00
Chang lue Tsen 70a0fd96ab refactor(swagger): remove deprecated app.json generation from swagger configuration 2025-08-17 12:37:27 -04:00
Chang lue Tsen 8996a62b54 refactor(api): remove deprecated application-related endpoints and types 2025-08-17 12:14:55 -04:00
Chang lue Tsen 14a86c50b2 feat(subscribe): add user agent limit configuration to system settings 2025-08-17 11:52:14 -04:00
Chang lue Tsen 5d80d95568 fix(subscribe): improve error handling and logging for subscription requests 2025-08-17 10:01:12 -04:00
Chang lue Tsen 6580cc9d44 feat(subscribe): implement user agent limit feature with configurable list 2025-08-16 13:37:09 -04:00
Chang lue Tsen 4f2aafd8b2 refactor(subscribe): replace V2 handler with a unified Handler method for subscription logic 2025-08-16 12:59:28 -04:00
Chang lue Tsen 81a46d1f13 feat(panDomain): update subscription logic to use V2 handler for improved functionality 2025-08-16 06:18:44 -04:00
Chang lue Tsen 2dfb1030e1 refactor: rename queryannouncementhandler.go to queryAnnouncementLogic.go for clarity 2025-08-15 14:58:01 -04:00
Chang lue Tsen 2be1c4f6ed feat(subscription): enhance subscription cache management and improve error handling 2025-08-15 14:45:54 -04:00
Chang lue Tsen 740dd48763 feat(subscribe): update subscription route to use V2 handler 2025-08-15 13:05:36 -04:00
Leif Draven 41d660bb9e Develop (#64)
* fix(database): correct name entry for SingBox in initialization script

* fix(purchase): update gift amount deduction logic and handle zero-amount order status

* feat: add type and default fields to rule group requests and update related logic

* feat(rule): implement logic to set a default rule group during creation and update

* fix(rule): add type and default fields to rule group model and update related logic

* feat(proxy): enhance proxy group handling and sorting logic

* refactor(proxy): replace hardcoded group names with constants for better maintainability

* fix(proxy): update group selection logic to skip empty and default names

* feat(proxy): enhance proxy and group handling with new configuration options

* feat(surge): add Surge adapter support and enhance subscription URL handling

* feat(traffic): implement traffic reset logic for subscription cycles

* feat(auth): improve email and mobile config unmarshalling with default values

* fix(auth) upbind email not update

* fix(order) discount set default 1

* fix(order) discount set default 1

* fix: refactor surfboard proxy handling and enhance configuration template

* fix(renewal) discount set default 1

* feat(loon): add Loon configuration template and enhance proxy handling

* feat(subscription): update user subscription status based on expiration time

* fix(renewal): update subscription retrieval method to use token instead of order ID

* feat(order): enhance order processing logic with improved error handling and user subscription management

* fix(order): improve code quality and fix critical bugs in order processing logic

- Fix inconsistent logging calls across all order logic files
- Fix critical gift amount deduction logic bug in renewal process
- Fix variable shadowing errors in database transactions
- Add comprehensive Go-standard documentation comments
- Improve log prefix consistency for better debugging
- Remove redundant discount validation code

* fix(docker): add build argument for version in Docker image build process

* feat(version): add endpoint to retrieve application version information

* fix(auth): improve user authentication method logic and update user cache

* feat(user): add ordering functionality to user list retrieval

* fix(RevenueStatistics) fill list

* fix(UserStatistics) fill list

* fix(user): implement user cache clearing after auth method operations

* fix(auth): enhance OAuth login logic with improved request handling and user registration flow

* fix(user): implement sorting for authentication methods based on priority

* fix(user): correct ordering clause for user retrieval based on filter

* refactor(user): streamline cache management and enhance cache clearing logic

* feat(logs) set logs volume in develop

* fix(handler): implement browser interception to deny access for specific user agents

* fix(resetTraffic) reset daily server

* refactor(trojan): remove unused parameter and clean up logging in slice

* fix(middleware): add domain length check and improve user-agent handling

* fix(middleware): reorder domain processing and enhance user-agent handling

* fix(resetTraffic): update subscription reset logic to use expire_time for monthly and yearly checks

* fix(scheduler): update reset traffic task schedule to run daily at 00:30

* fix(traffic): enhance traffic reset logic for subscriptions and adjust status checks

* fix(activateOrder): update traffic reset logic to include reset day check

* feat(marketing): add batch email task management API and logic

* feat(application): implement CRUD operations for subscribe applications

* feat(types): add user agent limit and list to subscription configuration

* feat(application): update subscription application requests to include structured download links

* feat(application): add scheme field and download link handling to subscribe application

* feat(application): add endpoint to retrieve client information

* feat(application): move DownloadLink and SubscribeApplication types to types.api

* feat(application): add DownloadLink and SubscribeClient types, update client response structure

* feat(application): remove ProxyTemplate field from application API

* feat(application): implement adapter for client configuration and add preview template functionality

* feat(application): move DownloadLink type to types.api and remove from common.api

* feat(application): update PreviewSubscribeTemplate to return structured response

* feat(application): remove ProxyTemplate field from application API

* feat(application): enhance cache key generation for user list and server data

* feat(subscribe): add ClearCache method to manage subscription cache invalidation

* feat(payment): add Description field to PaymentMethodDetail response

* feat(subscribe): update next reset time calculation to use ExpireTime

* feat(purchase): include handling fee in total amount calculation

* feat(subscribe): add V2SubscribeHandler and logic for enhanced subscription management

* feat(subscribe): add output format configuration to subscription adapter

* feat(application): default data

---------

Co-authored-by: Chang lue Tsen <tension@ppanel.dev>
Co-authored-by: NoWay <Bob455668@hotmail.com>
2025-08-15 12:30:21 -04:00
Chang lue Tsen c8de30f78c fix(order): improve code quality and fix critical bugs in order processing logic
- Fix inconsistent logging calls across all order logic files
- Fix critical gift amount deduction logic bug in renewal process
- Fix variable shadowing errors in database transactions
- Add comprehensive Go-standard documentation comments
- Improve log prefix consistency for better debugging
- Remove redundant discount validation code
2025-07-24 03:06:44 +09:00
Chang lue Tsen 46ab012b6c feat(order): enhance order processing logic with improved error handling and user subscription management 2025-07-24 03:06:44 +09:00
Chang lue Tsen 8976724c1e fix(renewal): update subscription retrieval method to use token instead of order ID 2025-07-24 03:06:44 +09:00
Chang lue Tsen db63281250 feat(subscription): update user subscription status based on expiration time 2025-07-24 03:06:44 +09:00
Chang lue Tsen f3a8f94b4b feat(loon): add Loon configuration template and enhance proxy handling 2025-07-24 03:06:44 +09:00
NoWay f4cd567492 fix(renewal) discount set default 1 2025-07-24 03:06:44 +09:00
Chang lue Tsen c08fadb347 fix: refactor surfboard proxy handling and enhance configuration template 2025-07-24 03:06:44 +09:00
NoWay a155a4f8cd fix(order) discount set default 1 2025-07-24 03:06:44 +09:00
NoWay 1b78e04113 fix(order) discount set default 1 2025-07-24 03:06:44 +09:00
NoWay f6ce7b2cd3 fix(auth) upbind email not update 2025-07-24 03:06:44 +09:00
Chang lue Tsen 6034a32e85 feat(auth): improve email and mobile config unmarshalling with default values 2025-07-24 03:06:44 +09:00
Chang lue Tsen 0e8e2d442e feat(traffic): implement traffic reset logic for subscription cycles 2025-07-24 03:06:44 +09:00
Chang lue Tsen b83ce5090a feat(surge): add Surge adapter support and enhance subscription URL handling 2025-07-24 03:06:44 +09:00
Chang lue Tsen 224365ce79 feat(proxy): enhance proxy and group handling with new configuration options 2025-07-24 03:06:44 +09:00
Chang lue Tsen 82e447c55e fix(proxy): update group selection logic to skip empty and default names 2025-07-24 03:06:44 +09:00
Chang lue Tsen 8c4c7d0773 refactor(proxy): replace hardcoded group names with constants for better maintainability 2025-07-24 03:06:44 +09:00
Chang lue Tsen 97024dd1df feat(proxy): enhance proxy group handling and sorting logic 2025-07-24 03:06:44 +09:00
Chang lue Tsen 979e39b9e5 fix(rule): add type and default fields to rule group model and update related logic 2025-07-24 03:06:44 +09:00
Chang lue Tsen 94d316ec52 feat(rule): implement logic to set a default rule group during creation and update 2025-07-24 03:06:44 +09:00
Chang lue Tsen 994cc4bebb feat: add type and default fields to rule group requests and update related logic 2025-07-24 03:06:44 +09:00
Chang lue Tsen 40c24fbc85 fix(purchase): update gift amount deduction logic and handle zero-amount order status 2025-07-24 03:06:44 +09:00
Chang lue Tsen 59348c1643 fix(database): correct name entry for SingBox in initialization script 2025-07-24 03:06:44 +09:00
Chang lue Tsen 9691257bad fix(purchase): correct gift amount deduction logic and enhance payment processing comments 2025-07-07 14:26:53 -04:00
Chang lue Tsen 76816ca8ea fix(purchase): handle gift amount deduction and update order status in checkout logic 2025-07-07 12:28:44 -04:00
Chang lue Tsen e279119524 fix(user): update user balance, gift amount, and commission fields in user info 2025-07-07 12:11:59 -04:00
sky-line-1 626c3ef05c fix(api) fill renewal_order_users in user statistics (#40) 2025-07-06 15:39:42 +08:00
Chang lue Tsen 4f49dea769 feat(anytls): add AnyTLS protocol support with parsing and configuration options 2025-07-05 14:30:12 -04:00
Chang lue Tsen 1a849fd461 fix(api): standardize formatting and add missing newlines in API files 2025-07-05 14:30:05 -04:00
Chang lue Tsen 987e25e7ac fix(tuic): add additional configuration options for SNI, RTT reduction, UDP relay, and congestion control 2025-07-03 14:45:42 -04:00
ctrlbbj 189f62781e Fix schema missing
Adding the missing fields in the database initialization file.
2025-07-03 02:22:27 +09:00
Chang lue Tsen 9fc367a323 fix(statistics): add mock data for revenue and user statistics in demo mode 2025-07-02 13:18:34 -04:00
Chang lue Tsen 0825ac525d fix(user): prevent deletion and password modification of admin user in demo mode 2025-07-02 12:39:30 -04:00
sky-line-1 d26bc7f40b fix(order): correct renewal traffic reset logic (#37) 2025-07-01 23:07:27 +08:00
Chang lue Tsen be7cdcd4a6 fix(node): enqueue task for GetNodeCountry only if city or country is empty 2025-06-12 23:57:06 -04:00
Chang lue Tsen b6a2f134bb fix(parse): enable UDP support in VLESS configuration 2025-06-06 11:23:20 -04:00
Chang lue Tsen 76063bc071 fix(server): encode server key in base64 for shadowsocks protocol 2025-06-01 12:54:48 -04:00
missish 565eb8cbbf "fix(order): 修复优惠券使用限制检查逻辑,增加数量有效性验证" 2025-06-02 01:47:16 +09:00
Chang lue Tsen 617768a4a1 fix(proxy): update server key encoding in GenerateShadowsocks2022Password 2025-06-01 12:01:02 -04:00
Leif Draven aae4a10947 Merge pull request #23 from missish/develop
"feat(user/subscribe): 添加订阅折扣信息的JSON解析逻辑"
2025-06-01 22:11:04 +09:00
missish 6027102d29 Merge branch 'perfect-panel:develop' into develop 2025-06-01 14:30:54 +08:00
missish 5ad3202626 "feat(user/subscribe): 添加订阅折扣信息的JSON解析逻辑"
- 修复在续订时只能续订一个月
2025-06-01 14:20:57 +08:00
Chang lue Tsen 0dca618f85 fix(uri): update query parameters and improve transport type handling 2025-06-01 01:33:30 -04:00
Chang lue Tsen 852bde35dc refactor(v2rayN): streamline proxy URI generation by consolidating methods 2025-05-31 11:44:18 -04:00
Chang lue Tsen b4a9bb23e9 fix(proxy): simplify password generation logic in GenerateShadowsocks2022Password 2025-05-31 11:30:04 -04:00
Chang lue Tsen 0fb0aac2fa feat(shadowsocks): implement support for SIP022 AEAD-2022 ciphers 2025-05-31 11:28:06 -04:00
Chang lue Tsen 1a21984c27 feat(shadowsocks): SIP022 AEAD-2022 Ciphers 2025-05-31 10:46:28 -04:00
Chang lue Tsen ddf740600f fix(subscribe): improve logging and update query logic for server filtering 2025-05-31 09:30:13 -04:00
Chang lue Tsen 77f55f8708 style(api): standardize formatting and remove trailing newlines in API definitions 2025-05-31 09:29:31 -04:00
Leif Draven 56f6bd2542 Merge pull request #22 from missish/develop
refactor(tool): 增强复制功能并修复零值处理问题
2025-05-31 21:47:07 +09:00
missish 3ee43b14c6 Revert "chore: add ppanel.yaml to .gitignore for security"
This reverts commit a4eca9f9a6.
2025-05-31 11:53:40 +08:00
missish a4eca9f9a6 chore: add ppanel.yaml to .gitignore for security 2025-05-31 11:49:47 +08:00
missish e0a4bb028b fix(admin/server): 修复节点更新时Tags字段处理逻辑
修改DeepCopy调用以忽略空值,并完善Tags字段的处理逻辑。当Tags为空数组时清空数据库字段,避免保留旧值。
2025-05-31 11:22:02 +08:00
missish 581e3ee48a refactor(tool): 为DeepCopy和ShallowCopy添加配置选项支持
为copy工具函数添加了CopyOption配置选项,允许调用方自定义复制行为。主要修改包括:
1. 新增CopyOption函数类型和CopyWithIgnoreEmpty选项
2. 修改DeepCopy和ShallowCopy函数签名以支持可变选项参数
3. 重构内部实现以应用传入的选项配置

这使得调用方可以灵活控制是否忽略空值等复制行为,增强了工具函数的可配置性。
2025-05-31 10:40:36 +08:00
Leif Draven dbb585ddb5 Merge pull request #21 from missish/develop
fix(order): Corrected Count and UserLimit to 0, which should be unlimited
2025-05-30 21:27:58 +09:00
missish 207ffc854e fix(order): 增加优惠券使用限制的条件判断 2025-05-27 21:15:17 +08:00
lyndon986 d4089a801d Merge pull request #19 from darwinchow/fix/stripe-webhook-endpoint 2025-05-24 02:51:11 +07:00
Darwin 5cca0e7aa3 fix(payment): update Stripe webhook endpoint url 2025-05-22 14:28:32 +08:00
Chang lue Tsen 42a99c4925 feat(cache): add cache options with customizable expiry settings 2025-05-11 04:39:22 -04:00
Chang lue Tsen 9e20b270e7 fix(develop): update docker command to check for all containers instead of running ones 2025-05-06 10:50:21 -04:00
Chang lue Tsen 155c6ba290 feat(adapter): add V2rayN adapter and build method for proxy management 2025-05-06 18:36:35 +09:00
Chang lue Tsen f4050ff42e fix(model): update query logic to use OR for group_id filtering 2025-05-06 18:36:09 +09:00
Chang lue Tsen ae784cbbe4 fix(server): enhance sorting logic to handle multiple entries and reorder correctly 2025-05-06 14:27:11 +09:00
Chang lue Tsen a198c770db fix(server): update sorting logic to use FindOne and Update methods for better error handling 2025-05-06 14:07:46 +09:00
Chang lue Tsen a2e4c6d09a fix(subscribe): add BeforeDelete and BeforeUpdate methods for sort handling 2025-05-06 13:29:39 +09:00
Chang lue Tsen d6f5160be1 fix(server): remove reorderSort function to streamline server sorting logic 2025-05-06 13:26:59 +09:00
Chang lue Tsen d5f14bf665 fix(server): simplify BeforeDelete method by removing unnecessary Model call 2025-05-06 13:25:38 +09:00
Chang lue Tsen e625d9aed5 fix(server): update BeforeDelete method to use Model for sort update query 2025-05-06 13:24:20 +09:00
Chang lue Tsen 3cadd9e621 fix(server): refactor server model methods to support transaction handling 2025-05-06 13:21:27 +09:00
Chang lue Tsen 38bcacc9e7 fix(subscribe): update subscription availability check to allow status greater than 1 2025-05-06 12:05:33 +09:00
Chang lue Tsen ea74e4b7d5 fix(subscribe): update subscription query to include zero expiration time condition 2025-05-06 11:49:21 +09:00
Chang lue Tsen ead1a9a8a6 fix(subscribe): improve order details retrieval logic in resetUserSubscribeTokenLogic 2025-05-05 10:55:46 -04:00
Chang lue Tsen aef567c06f fix(subscribe): update subscribe record update logic to use ID instead of token 2025-05-05 10:43:12 -04:00
Chang lue Tsen 6912e281f3 fix(subscribe): correct subscription status update logic on renewal 2025-05-05 04:30:49 -04:00
Chang lue Tsen c5b0507187 fix(subscribe): enhance server tag handling in subscription logic 2025-05-05 04:04:18 -04:00
Chang lue Tsen 9a1942f8cf fix(server): update server filtering to support multiple tags 2025-04-30 12:53:21 +09:00
Chang lue Tsen f856dc7c01 fix(server): update server filtering to support multiple tags 2025-04-30 12:53:01 +09:00
Chang lue Tsen cdc3d8b8f1 fix(subscribe): escape site name in content-disposition headers 2025-04-29 19:21:58 +09:00
Chang lue Tsen 55ef348135 fix(proxy): replace string literals with constants for proxy group types 2025-04-29 18:09:53 +09:00
Chang lue Tsen 6d13060aeb fix(proxy): improve proxy removal logic in build functions 2025-04-29 17:02:17 +09:00
Chang lue Tsen 94416d59a6 fix(rules): remove unnecessary comments from final rules in configuration files 2025-04-29 16:19:03 +09:00
Chang lue Tsen bbe7b8c223 fix(docs): update download URLs in installation guides for server binaries 2025-04-29 15:19:10 +09:00
Chang lue Tsen fdf51a60e9 fix(docs): update architecture diagram links in English and Chinese README files 2025-04-29 14:47:39 +09:00
Leif Draven fd1e2857c8 Update architecture.svg
docs: architecture svg
2025-04-29 12:57:30 +09:00
Chang lue Tsen de74bd1d70 fix(subscribe): improve query logic and handle status filtering 2025-04-29 12:46:19 +09:00
Chang lue Tsen fd1104784b fix(docs): update Go Report Card badge link in README files 2025-04-28 11:43:59 -04:00
Chang lue Tsen f4f0756ba6 fix(docs): update CI/CD badge links in README files 2025-04-28 11:41:09 -04:00
Chang lue Tsen 08bc2f6331 fix(docs): update license badge links in README files 2025-04-28 11:32:46 -04:00
Chang lue Tsen dafe211ec7 fix(subscribe): add FinishedAt field to track subscription completion time 2025-04-28 11:18:53 -04:00
Chang lue Tsen 1fee981a58 fix(subscribe): update status and finished_at fields in subscription logic 2025-04-28 11:13:16 -04:00
Chang lue Tsen 2aaf4cf618 fix(subscribe): improve query logic and handle status filtering 2025-04-28 18:59:06 +09:00
Chang lue Tsen 105ee9cc46 fix(proxy): filter out empty proxy groups 2025-04-28 17:31:07 +09:00
Chang lue Tsen 3fd71a472b docs: update bug report and feature request links in English and Chinese README files 2025-04-27 11:25:07 +09:00
Chang lue Tsen 24e2aaeb61 docs: update header level for Special Thanks section in README 2025-04-27 11:23:09 +09:00
Chang lue Tsen a1016eef25 docs: update section header for special thanks in Chinese README 2025-04-27 11:21:29 +09:00
Chang lue Tsen af6fe2eeed docs: update README files with project links and add special thanks section 2025-04-27 11:19:53 +09:00
Chang lue Tsen b2dd1a3758 fix: add ppanel.yaml to .gitignore 2025-04-25 18:35:56 +09:00
Chang lue Tsen 9a747596e6 fix: add versioning support to Docker build process 2025-04-25 18:30:45 +09:00
Chang lue Tsen 4124dd43ce fix: update release workflow 2025-04-25 18:17:26 +09:00
Chang lue Tsen bc3f40fd69 fix: update release workflow 2025-04-25 18:13:45 +09:00
Chang lue Tsen 027596e3a8 fix: update release workflow 2025-04-25 18:03:49 +09:00
Chang lue Tsen 5b972514aa fix: update release workflow 2025-04-25 17:45:58 +09:00
Chang lue Tsen 5cccb1f8e3 refactor: simplify release workflow 2025-04-25 16:40:57 +09:00
Chang lue Tsen 579e32abd9 fix: update CI/CD badge link in README files 2025-04-25 15:38:52 +09:00
Chang lue Tsen f27b94dddf chore: rename readme.md to README.md and update Go version in documentation 2025-04-25 15:17:00 +09:00
Chang lue Tsen 81bf74e808 style: format code by adding newlines for improved readability 2025-04-25 15:10:27 +09:00
Chang lue Tsen 34c09c4618 refactor: update import paths from ppanel-server to server 2025-04-25 15:09:31 +09:00
Chang lue Tsen 52063049c5 fix: update version command to use constants for version and build time 2025-04-25 15:07:22 +09:00
Chang lue Tsen da4fd72105 chore: add Makefile for multi-platform build configuration 2025-04-25 15:03:54 +09:00
Chang lue Tsen 8addcc584b init: 1.0.0 2025-04-25 12:08:29 +09:00
79 changed files with 470 additions and 3241 deletions
-231
View File
@@ -1,231 +0,0 @@
name: Build docker and publish
run-name: 简化的Docker构建和部署流程
on:
push:
branches:
- main
- dev
pull_request:
branches:
- main
- dev
env:
# Docker镜像仓库
REPO: ${{ vars.REPO || 'registry.kxsw.us/ario-server' }}
# SSH连接信息
SSH_HOST: ${{ vars.SSH_HOST }}
SSH_PORT: ${{ vars.SSH_PORT }}
SSH_USER: ${{ vars.SSH_USER }}
SSH_PASSWORD: ${{ vars.SSH_PASSWORD }}
# TG通知
TG_BOT_TOKEN: 8114337882:AAHkEx03HSu7RxN4IHBJJEnsK9aPPzNLIk0
TG_CHAT_ID: "-4940243803"
# Go构建变量
SERVICE: ario
SERVICE_STYLE: ario
VERSION: ${{ github.sha }}
BUILDTIME: ${{ github.event.head_commit.timestamp }}
GOARCH: amd64
jobs:
build:
runs-on: ario-server
container:
image: node:20
strategy:
matrix:
# 只有node支持版本号别名
node: ['20.15.1']
steps:
# 步骤1: 下载代码
- name: 📥 下载代码
uses: actions/checkout@v4
# 步骤2: 设置动态环境变量
- name: ⚙️ 设置动态环境变量
run: |
if [ "${{ github.ref_name }}" = "main" ]; then
echo "DOCKER_TAG_SUFFIX=latest" >> $GITHUB_ENV
echo "CONTAINER_NAME=ppanel-server" >> $GITHUB_ENV
echo "DEPLOY_PATH=/root/vpn_server" >> $GITHUB_ENV
echo "为 main 分支设置生产环境变量"
elif [ "${{ github.ref_name }}" = "dev" ]; then
echo "DOCKER_TAG_SUFFIX=dev" >> $GITHUB_ENV
echo "CONTAINER_NAME=ppanel-server-dev" >> $GITHUB_ENV
echo "DEPLOY_PATH=/root/vpn_server_dev" >> $GITHUB_ENV
echo "为 dev 分支设置开发环境变量"
else
echo "DOCKER_TAG_SUFFIX=${{ github.ref_name }}" >> $GITHUB_ENV
echo "CONTAINER_NAME=ppanel-server-${{ github.ref_name }}" >> $GITHUB_ENV
echo "DEPLOY_PATH=/root/vpn_server_other" >> $GITHUB_ENV
echo "为其他分支 (${{ github.ref_name }}) 设置环境变量"
fi
# 步骤3: 安装系统工具 (Docker, curl, jq)
- name: 🔧 安装系统工具 (Docker, curl, jq)
run: |
set -e
export DEBIAN_FRONTEND=noninteractive
echo "等待 apt/dpkg 锁释放 (unattended-upgrades)..."
# 等待最多 300 秒让 unattended-upgrades/apt/dpkg 锁释放
end=$((SECONDS+300))
while true; do
LOCKS_BUSY=0
# 如果 unattended-upgrades 正在运行,标记为忙碌
if pgrep -x unattended-upgrades >/dev/null 2>&1; then LOCKS_BUSY=1; fi
# 如果 fuser 存在,检查常见的锁文件
if command -v fuser >/dev/null 2>&1; then
if fuser /var/lib/dpkg/lock >/dev/null 2>&1 \
|| fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 \
|| fuser /var/lib/apt/lists/lock >/dev/null 2>&1; then
LOCKS_BUSY=1
fi
fi
# 如果不忙碌则跳出循环
if [ "$LOCKS_BUSY" -eq 0 ]; then break; fi
# 超时后约 5 分钟
if [ $SECONDS -ge $end ]; then
echo "等待 apt/dpkg 锁超时,使用 Dpkg::Lock::Timeout 继续..."
break
fi
echo "仍在等待锁释放..."; sleep 5
done
apt-get update -y -o Dpkg::Lock::Timeout=600
apt-get install -y -o Dpkg::Lock::Timeout=600 jq curl ca-certificates docker.io
docker --version
jq --version
curl --version
# 步骤4: 构建并发布到镜像仓库
- name: 📤 构建并发布到镜像仓库
run: |
echo "开始构建并推送镜像..."
echo "仓库: ${{ env.REPO }}"
echo "版本标签: ${{ env.VERSION }}"
echo "分支标签: ${{ env.DOCKER_TAG_SUFFIX }}"
# 构建镜像,同时打上版本和分支两个标签
docker build -f Dockerfile \
--platform linux/amd64 \
--build-arg TARGETARCH=amd64 \
--build-arg VERSION=${{ env.VERSION }} \
--build-arg BUILDTIME=${{ env.BUILDTIME }} \
-t ${{ env.REPO }}:${{ env.VERSION }} \
-t ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }} \
.
echo "推送版本标签镜像: ${{ env.REPO }}:${{ env.VERSION }}"
docker push ${{ env.REPO }}:${{ env.VERSION }}
echo "推送分支标签镜像: ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}"
docker push ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}
echo "镜像推送完成"
# 步骤5: 连接服务器拉镜像启动
- name: 🚀 连接服务器拉镜像启动
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ env.SSH_HOST }}
username: ${{ env.SSH_USER }}
password: ${{ env.SSH_PASSWORD }}
port: ${{ env.SSH_PORT }}
timeout: 300s
command_timeout: 600s
script: |
echo "连接服务器成功,开始部署..."
echo "部署容器名: ${{ env.CONTAINER_NAME }}"
echo "部署路径: ${{ env.DEPLOY_PATH }}"
echo "部署镜像: ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}"
# 确保部署目录存在
mkdir -p ${{ env.DEPLOY_PATH }}/config
mkdir -p ${{ env.DEPLOY_PATH }}/logs
# 停止并删除旧容器(忽略所有错误)
if docker ps -a | grep -q ${{ env.CONTAINER_NAME }} 2>/dev/null; then
echo "停止旧容器..."
docker stop ${{ env.CONTAINER_NAME }} >/dev/null 2>&1 || true
echo "等待容器完全停止..."
sleep 5
echo "删除旧容器..."
# 静默删除,完全忽略错误输出
docker rm ${{ env.CONTAINER_NAME }} >/dev/null 2>&1 || true
sleep 2
# 如果仍然存在,尝试强制删除(静默)
if docker ps -a | grep -q ${{ env.CONTAINER_NAME }} 2>/dev/null; then
echo "尝试强制删除..."
docker rm -f ${{ env.CONTAINER_NAME }} >/dev/null 2>&1 || true
sleep 3
fi
echo "容器清理完成,继续部署..."
fi
# 拉取最新分支镜像
echo "拉取镜像: ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}..."
docker pull ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}
# 启动新容器
echo "启动新容器..."
cd ${{ env.DEPLOY_PATH }}
docker run -d \
--name ${{ env.CONTAINER_NAME }} \
--restart unless-stopped \
--network host \
-v ./config/ppanel.yaml:/app/etc/ppanel.yaml \
-v ./logs:/app/logs \
${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}
# 检查容器状态
sleep 5
if docker ps | grep -q ${{ env.CONTAINER_NAME }}; then
echo "✅ 容器启动成功"
else
echo "❌ 容器启动失败"
docker logs ${{ env.CONTAINER_NAME }}
exit 1
fi
# 步骤6: TG通知 (成功)
- name: 📱 发送成功通知到Telegram
if: success()
uses: appleboy/telegram-action@master
with:
token: ${{ env.TG_BOT_TOKEN }}
to: ${{ env.TG_CHAT_ID }}
message: |
✅ 部署成功!
📦 项目: ${{ github.repository }}
🌿 分支: ${{ github.ref_name }}
📝 提交: ${{ github.sha }}
👤 提交者: ${{ github.actor }}
🕐 时间: ${{ github.event.head_commit.timestamp }}
🚀 服务已成功部署到生产环境
parse_mode: Markdown
# 步骤5: TG通知 (失败)
- name: 📱 发送失败通知到Telegram
if: failure()
uses: appleboy/telegram-action@master
with:
token: ${{ env.TG_BOT_TOKEN }}
to: ${{ env.TG_CHAT_ID }}
message: |
❌ 部署失败!
📦 项目: ${{ github.repository }}
🌿 分支: ${{ github.ref_name }}
📝 提交: ${{ github.sha }}
👤 提交者: ${{ github.actor }}
🕐 时间: ${{ github.event.head_commit.timestamp }}
⚠️ 请检查构建日志获取详细信息
parse_mode: Markdown
+51
View File
@@ -0,0 +1,51 @@
name: Deploy
on:
push:
branches: ["develop"]
pull_request:
branches: ["develop"]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Get short Git commit ID
id: vars
run: echo "COMMIT_ID=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Build Docker image
run: docker build --build-arg VERSION=${{ env.COMMIT_ID }} -t ${{ secrets.DOCKER_USERNAME }}/ppanel-server-dev:${{ env.COMMIT_ID }} .
- name: Push Docker image
run: docker push ${{ secrets.DOCKER_USERNAME }}/ppanel-server-dev:${{ env.COMMIT_ID }}
# - name: Deploy to server
# uses: appleboy/ssh-action@v0.1.6
# with:
# host: ${{ secrets.SSH_HOST }}
# username: ${{ secrets.SSH_USER }}
# key: ${{ secrets.SSH_PRIVATE_KEY }}
# script: |
# if [ $(docker ps -a -q -f name=ppanel-server-dev) ]; then
# echo "Stopping and removing existing ppanel-server container..."
# docker stop ppanel-server-dev
# docker rm ppanel-server-dev
# else
# echo "No existing ppanel-server-dev container running."
# fi
#
# docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
# docker run -d --restart=always --log-driver=journald --name ppanel-server-dev -p 8080:8080 -v /www/wwwroot/api/etc:/app/etc -v /www/wwwroot/api/logs:/app/logs --restart=always -d ${{ secrets.DOCKER_USERNAME }}/ppanel-server-dev:${{ env.COMMIT_ID }}
#
+131
View File
@@ -0,0 +1,131 @@
name: Release
on:
push:
tags:
- 'v*'
jobs:
build-docker:
runs-on: ubuntu-latest
env:
IMAGE_NAME: ppanel-server
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract version from git tag
id: version
run: echo "VERSION=$(git describe --tags --abbrev=0 | sed 's/^v//')" >> $GITHUB_ENV
- name: Get short SHA
id: sha
run: echo "GIT_SHA=${GITHUB_SHA::8}" >> $GITHUB_ENV
- name: Set BUILD_TIME env
run: echo BUILD_TIME=$(date --iso-8601=seconds) >> ${GITHUB_ENV}
- name: Build and push Docker image for main release
if: "!contains(github.ref_name, 'beta')"
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
platforms: linux/amd64,linux/arm64
push: true
build-args: |
VERSION=${{ env.VERSION }}
tags: |
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}-${{ env.GIT_SHA }}
- name: Build and push Docker image for beta release
if: contains(github.ref_name, 'beta')
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
platforms: linux/amd64,linux/arm64
push: true
build-args: |
VERSION=${{ env.VERSION }}
tags: |
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:beta
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}-${{ env.GIT_SHA }}
release-notes:
runs-on: ubuntu-latest
needs: build-docker
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install GoReleaser
run: |
go install github.com/goreleaser/goreleaser/v2@latest
- name: Run GoReleaser
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
run: |
goreleaser check
goreleaser release --clean
releases-matrix:
name: Release ppanel-server binary
runs-on: ubuntu-latest
needs: release-notes # wait for release-notes job to finish
strategy:
matrix:
# build and publish in parallel: linux/386, linux/amd64, linux/arm64,
# windows/386, windows/amd64, windows/arm64, darwin/amd64, darwin/arm64
goos: [ linux, windows, darwin ]
goarch: [ '386', amd64, arm64 ]
exclude:
- goarch: '386'
goos: darwin
steps:
- uses: actions/checkout@v2
- name: Extract version from git tag
id: version
run: echo "VERSION=$(git describe --tags --abbrev=0 | sed 's/^v//')" >> $GITHUB_ENV
- name: Set BUILD_TIME env
run: echo BUILD_TIME=$(date --iso-8601=seconds) >> ${GITHUB_ENV}
- uses: actions/checkout@v4
- uses: wangyoucao577/go-release-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
asset_name: "ppanel-server-${{ matrix.goos }}-${{ matrix.goarch }}"
goversion: "https://dl.google.com/go/go1.23.3.linux-amd64.tar.gz"
project_path: "."
binary_name: "ppanel-server"
extra_files: LICENSE etc
ldflags: -X "github.com/perfect-panel/server/pkg/constant.Version=${{env.VERSION}}" -X "github.com/perfect-panel/server/pkg/constant.BuildTime=${{env.BUILD_TIME}}"
+81
View File
@@ -0,0 +1,81 @@
name: Go CI/CD with goctl and Swagger
on:
# release:
# types: [published]
push:
branches:
- develop
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install goctl
run: |
curl -L https://github.com/zeromicro/go-zero/releases/download/tools%2Fgoctl%2Fv1.7.2/goctl-v1.7.2-linux-amd64.tar.gz -o goctl-v1.7.2-linux-amd64.tar.gz
tar -xvzf goctl-v1.7.2-linux-amd64.tar.gz
chmod +x goctl
sudo mv goctl /usr/local/bin/goctl
goctl --version
- name: Install goctl-swagger
run: |
curl -L https://github.com/tensionc/goctl-swagger/releases/download/v1.0.1/goctl-swagger-v1.0.1-linux-amd64.tar.gz -o goctl-swagger.tar.gz
tar -xvzf goctl-swagger.tar.gz
chmod +x goctl-swagger
sudo mv goctl-swagger /usr/local/bin/
- name: Generate Swagger file
run: |
mkdir -p swagger
goctl api plugin -plugin goctl-swagger='swagger -filename common.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_common.api -dir ./swagger
goctl api plugin -plugin goctl-swagger='swagger -filename user.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_user.api -dir ./swagger
goctl api plugin -plugin goctl-swagger='swagger -filename admin.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_admin.api -dir ./swagger
goctl api plugin -plugin goctl-swagger='swagger -filename ppanel.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ppanel.api -dir ./swagger
goctl api plugin -plugin goctl-swagger='swagger -filename node.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_node.api -dir ./swagger
- name: Verify Swagger file
run: |
test -f ./swagger/common.json
test -f ./swagger/user.json
test -f ./swagger/admin.json
- name: Checkout target repository
uses: actions/checkout@v4
with:
repository: perfect-panel/ppanel-docs
token: ${{ secrets.GH_TOKEN }}
path: ppanel-docs
persist-credentials: true
- name: Verify or create public/swagger directory
run: |
mkdir -p ./ppanel-docs/public/swagger
- name: Copy Swagger files
run: |
cp -rf swagger/* ppanel-docs/public/swagger
cd ppanel-docs
- name: Check for file changes
run: |
cd ppanel-docs
git add .
git status
if [ "$(git status --porcelain)" ]; then
echo "Changes detected in the doc repository."
git config user.name "GitHub Actions"
git config user.email "actions@ppanel.dev"
git commit -m "Update Swagger files"
git push
else
echo "No changes detected."
exit 0
fi
+2 -1
View File
@@ -6,11 +6,12 @@
*.log
.DS_Store
*_test_config.go
*.log*
/build/
etc/ppanel.yaml
*.p8
*.crt
*.key
node_modules
package-lock.json
package.json
/bin
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="go build github.com/perfect-panel/server" type="GoApplicationRunConfiguration" factoryName="Go Application" nameIsGenerated="true">
<module name="server" />
<working_directory value="$PROJECT_DIR$" />
<parameters value="run --config etc/ppanel-dev.yaml" />
<kind value="PACKAGE" />
<package value="github.com/perfect-panel/server" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$/ppanel.go" />
<method v="2" />
</configuration>
</component>
-128
View File
@@ -1,128 +0,0 @@
# 设备静默登录机制设计方案
## 需求分析
1. 用户进来之后就是静默登录(设备登录)
2. 用户可以主动关联邮箱;也可以不关联邮箱
3. 用户换手机后在别的地方用邮箱登录会绑定另外一部手机的设备号
4. 没有游客概念,快捷登录进来的用户就是正式用户
## 当前系统分析
### 现有认证流程
- **设备登录**:已存在 `deviceLoginLogic.go`,通过设备标识符自动登录
- **邮箱登录**:已存在 `userLoginLogic.go`,需要邮箱+密码
- **游客模式**:通过 `Order.UserId = 0` 标识游客订单
### 现有设备管理
- **设备绑定**`bindDeviceLogic.go` 处理设备与用户绑定
- **设备解绑**`unbindDeviceLogic.go` 处理设备解绑
- **设备迁移**:支持设备在用户间转移
## 设计方案
### 1. 核心改动策略
- **保留现有设备登录机制**,作为默认登录方式
- **移除游客概念**,所有设备登录用户都是正式用户
- **增强邮箱绑定功能**,支持跨设备登录
- **优化设备迁移逻辑**,支持邮箱登录后绑定新设备
### 2. 具体实现方案
#### 2.1 修改设备登录逻辑
**文件**: `internal/logic/auth/deviceLoginLogic.go`
**改动点**:
- 移除 `registerUserAndDevice` 中的试用激活逻辑
- 确保所有通过设备登录创建的用户都是正式用户
- 保持现有的设备绑定机制
#### 2.2 修改订单处理逻辑
**文件**: `queue/logic/order/activateOrderLogic.go`
**改动点**:
- 移除 `getUserOrCreate` 中的游客判断逻辑 (`orderInfo.UserId == 0`)
- 移除 `createGuestUser` 函数
- 修改为:如果订单没有关联用户,通过设备标识符创建或获取用户
#### 2.3 修改订单关闭逻辑
**文件**: `internal/logic/public/order/closeOrderLogic.go`
**改动点**:
- 移除对 `UserId == 0` 的特殊处理
- 统一处理所有订单的关闭逻辑
#### 2.4 增强邮箱登录逻辑
**文件**: `internal/logic/auth/userLoginLogic.go`
**改动点**:
- 在邮箱登录成功后,如果提供了设备标识符,自动绑定设备
- 支持邮箱登录后在新设备上的自动绑定
#### 2.5 优化设备绑定逻辑
**文件**: `internal/logic/auth/bindDeviceLogic.go`
**改动点**:
- 增强设备迁移逻辑,支持邮箱用户登录新设备时的自动绑定
- 保持现有的设备冲突处理机制
### 3. 数据库变更
**无需修改数据库结构**,现有的用户和设备表结构已经支持新的需求。
### 4. API 变更
**无需修改 API 接口**,现有的设备登录和邮箱登录接口已经满足需求。
### 5. 前端适配
**前端需要调整**:
- 默认使用设备登录作为主要登录方式
- 提供邮箱绑定入口
- 在新设备上提供邮箱登录选项
## 实施步骤
### 第一步:修改订单逻辑
1. 修改 `activateOrderLogic.go`,移除游客概念
2. 修改 `closeOrderLogic.go`,统一订单处理逻辑
### 第二步:增强设备登录
1. 确保设备登录创建的都是正式用户
2. 优化设备绑定逻辑
### 第三步:增强邮箱登录
1. 在邮箱登录后支持设备绑定
2. 优化跨设备登录体验
### 第四步:测试验证
1. 测试设备静默登录
2. 测试邮箱绑定功能
3. 测试跨设备登录
## 优势分析
### 1. 最小化改动
- 复用现有的设备登录机制
- 保持现有的数据库结构
- 保持现有的 API 接口
### 2. 用户体验提升
- 用户进入即可使用,无需注册
- 支持邮箱绑定,便于跨设备使用
- 保持数据连续性
### 3. 系统稳定性
- 基于现有成熟机制
- 减少新增代码量
- 降低引入 bug 的风险
## 风险评估
### 1. 数据迁移
- **风险**: 现有游客数据需要处理
- **方案**: 可以保持现有游客数据不变,新用户使用新机制
### 2. 兼容性
- **风险**: 现有客户端可能需要适配
- **方案**: 保持 API 兼容,逐步引导用户使用新机制
### 3. 性能影响
- **风险**: 设备登录可能增加数据库压力
- **方案**: 现有机制已经过验证,影响可控
+3 -2
View File
@@ -24,11 +24,11 @@ RUN BUILD_TIME=$(date -u +"%Y-%m-%d %H:%M:%S") && \
go build -ldflags="-s -w -X 'github.com/perfect-panel/server/pkg/constant.Version=${VERSION}' -X 'github.com/perfect-panel/server/pkg/constant.BuildTime=${BUILD_TIME}'" -o /app/ppanel ppanel.go
# Final minimal image
FROM alpine:latest
FROM scratch
# Copy CA certificates and timezone data
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
ENV TZ=Asia/Shanghai
@@ -36,6 +36,7 @@ ENV TZ=Asia/Shanghai
WORKDIR /app
COPY --from=builder /app/ppanel /app/ppanel
COPY --from=builder /build/etc /app/etc
# Expose the port (optional)
EXPOSE 8080
+2 -2
View File
@@ -114,8 +114,8 @@ proxy services. Built with Go, it emphasizes performance, security, and scalabil
4. **Pull from Docker Hub** (after CI/CD publishes):
```bash
docker pull ppanel/ppanel-server:latest
docker run --rm -p 8080:8080 ppanel/ppanel-server:latest
docker pull yourusername/ppanel-server:latest
docker run --rm -p 8080:8080 yourusername/ppanel-server:latest
```
## 📖 API Documentation
+12 -35
View File
@@ -11,13 +11,11 @@ info (
type (
// User login request
UserLoginRequest {
Identifier string `json:"identifier"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
CfToken string `json:"cf_token,optional"`
}
// Check user is exist request
CheckUserRequest {
@@ -29,25 +27,21 @@ type (
}
// User login response
UserRegisterRequest {
Identifier string `json:"identifier"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Invite string `json:"invite,optional"`
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Invite string `json:"invite,optional"`
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
CfToken string `json:"cf_token,optional"`
}
// User login response
ResetPasswordRequest {
Identifier string `json:"identifier"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
}
LoginResponse {
@@ -66,14 +60,12 @@ type (
}
// login request
TelephoneLoginRequest {
Identifier string `json:"identifier"`
Telephone string `json:"telephone" validate:"required"`
TelephoneCode string `json:"telephone_code"`
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
Password string `json:"password"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
}
// Check user is exist request
@@ -87,7 +79,6 @@ type (
}
// User login response
TelephoneRegisterRequest {
Identifier string `json:"identifier"`
Telephone string `json:"telephone" validate:"required"`
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
Password string `json:"password" validate:"required"`
@@ -95,19 +86,16 @@ type (
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type,optional"`
CfToken string `json:"cf_token,optional"`
}
// User login response
TelephoneResetPasswordRequest {
Identifier string `json:"identifier"`
Telephone string `json:"telephone" validate:"required"`
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
Password string `json:"password" validate:"required"`
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type,optional"`
CfToken string `json:"cf_token,optional"`
}
AppleLoginCallbackRequest {
@@ -119,18 +107,11 @@ type (
Code string `form:"code"`
State string `form:"state"`
}
DeviceLoginRequest {
Identifier string `json:"identifier" validate:"required"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `json:"user_agent" validate:"required"`
CfToken string `json:"cf_token,optional"`
}
)
@server (
prefix: v1/auth
group: auth
middleware: DeviceMiddleware
)
service ppanel {
@doc "User login"
@@ -164,10 +145,6 @@ service ppanel {
@doc "Reset password"
@handler TelephoneResetPassword
post /reset/telephone (TelephoneResetPasswordRequest) returns (LoginResponse)
@doc "Device Login"
@handler DeviceLogin
post /login/device (DeviceLoginRequest) returns (LoginResponse)
}
@server (
-1
View File
@@ -92,7 +92,6 @@ type (
@server (
prefix: v1/common
group: common
middleware: DeviceMiddleware
)
service ppanel {
@doc "Get global config"
+1 -1
View File
@@ -13,7 +13,7 @@ import "../types.api"
@server (
prefix: v1/public/announcement
group: public/announcement
middleware: AuthMiddleware,DeviceMiddleware
middleware: AuthMiddleware
)
service ppanel {
@doc "Query announcement"
+1 -1
View File
@@ -13,7 +13,7 @@ import "../types.api"
@server (
prefix: v1/public/document
group: public/document
middleware: AuthMiddleware,DeviceMiddleware
middleware: AuthMiddleware
)
service ppanel {
@doc "Get document list"
+1 -1
View File
@@ -13,7 +13,7 @@ import "../types.api"
@server (
prefix: v1/public/order
group: public/order
middleware: AuthMiddleware,DeviceMiddleware
middleware: AuthMiddleware
)
service ppanel {
@doc "Pre create order"
+1 -1
View File
@@ -13,7 +13,7 @@ import "../types.api"
@server (
prefix: v1/public/payment
group: public/payment
middleware: AuthMiddleware,DeviceMiddleware
middleware: AuthMiddleware
)
service ppanel {
@doc "Get available payment methods"
-1
View File
@@ -70,7 +70,6 @@ type (
@server (
prefix: v1/public/portal
group: public/portal
middleware: DeviceMiddleware
)
service ppanel {
@doc "Get available payment methods"
+1 -42
View File
@@ -14,57 +14,16 @@ type (
QuerySubscribeListRequest {
Language string `form:"language"`
}
QueryUserSubscribeNodeListResponse {
List []UserSubscribeInfo `json:"list"`
}
UserSubscribeInfo {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
OrderId int64 `json:"order_id"`
SubscribeId int64 `json:"subscribe_id"`
StartTime int64 `json:"start_time"`
ExpireTime int64 `json:"expire_time"`
FinishedAt int64 `json:"finished_at"`
ResetTime int64 `json:"reset_time"`
Traffic int64 `json:"traffic"`
Download int64 `json:"download"`
Upload int64 `json:"upload"`
Token string `json:"token"`
Status uint8 `json:"status"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
IsTryOut bool `json:"is_try_out"`
Nodes []*UserSubscribeNodeInfo `json:"nodes"`
}
UserSubscribeNodeInfo{
Id int64 `json:"id"`
Name string `json:"name"`
Uuid string `json:"uuid"`
Protocol string `json:"protocol"`
Port uint16 `json:"port"`
Address string `json:"address"`
Tags []string `json:"tags"`
Country string `json:"country"`
City string `json:"city"`
CreatedAt int64 `json:"created_at"`
}
)
@server (
prefix: v1/public/subscribe
group: public/subscribe
middleware: AuthMiddleware,DeviceMiddleware
middleware: AuthMiddleware
)
service ppanel {
@doc "Get subscribe list"
@handler QuerySubscribeList
get /list (QuerySubscribeListRequest) returns (QuerySubscribeListResponse)
@doc "Get user subscribe node info"
@handler QueryUserSubscribeNodeList
get /node/list returns (QueryUserSubscribeNodeListResponse)
}
+1 -1
View File
@@ -43,7 +43,7 @@ type (
@server (
prefix: v1/public/ticket
group: public/ticket
middleware: AuthMiddleware,DeviceMiddleware
middleware: AuthMiddleware
)
service ppanel {
@doc "Get ticket list"
+1 -18
View File
@@ -97,21 +97,12 @@ type (
Email string `json:"email" validate:"required"`
Code string `json:"code" validate:"required"`
}
GetDeviceListResponse {
List []UserDevice `json:"list"`
Total int64 `json:"total"`
}
UnbindDeviceRequest {
Id int64 `json:"id" validate:"required"`
}
)
@server (
prefix: v1/public/user
group: public/user
middleware: AuthMiddleware,DeviceMiddleware
middleware: AuthMiddleware
)
service ppanel {
@doc "Query User Info"
@@ -201,13 +192,5 @@ service ppanel {
@doc "Update Bind Email"
@handler UpdateBindEmail
put /bind_email (UpdateBindEmailRequest)
@doc "Get Device List"
@handler GetDeviceList
get /devices returns (GetDeviceListResponse)
@doc "Unbind Device"
@handler UnbindDevice
put /unbind_device (UnbindDeviceRequest)
}
+3 -14
View File
@@ -115,7 +115,6 @@ type (
AuthConfig {
Mobile MobileAuthenticateConfig `json:"mobile"`
Email EmailAuthticateConfig `json:"email"`
Device DeviceAuthticateConfig `json:"device"`
Register PubilcRegisterConfig `json:"register"`
}
PubilcRegisterConfig {
@@ -135,14 +134,6 @@ type (
EnableDomainSuffix bool `json:"enable_domain_suffix"`
DomainSuffixList string `json:"domain_suffix_list"`
}
DeviceAuthticateConfig {
Enable bool `json:"enable"`
ShowAds bool `json:"show_ads"`
EnableSecurity bool `json:"enable_security"`
OnlyRealDevice bool `json:"only_real_device"`
}
RegisterConfig {
StopRegister bool `json:"stop_register"`
EnableTrial bool `json:"enable_trial"`
@@ -187,7 +178,6 @@ type (
ForcedInvite bool `json:"forced_invite"`
ReferralPercentage int64 `json:"referral_percentage"`
OnlyFirstPurchase bool `json:"only_first_purchase"`
GiftDays int64 `json:"gift_days"`
}
TelegramConfig {
TelegramBotToken string `json:"telegram_bot_token"`
@@ -207,8 +197,8 @@ type (
CurrencySymbol string `json:"currency_symbol"`
}
SubscribeDiscount {
Quantity int64 `json:"quantity"`
Discount float64 `json:"discount"`
Quantity int64 `json:"quantity"`
Discount int64 `json:"discount"`
}
Subscribe {
Id int64 `json:"id"`
@@ -657,7 +647,7 @@ type (
// public announcement
QueryAnnouncementRequest {
Page int `form:"page"`
Size int `form:"size,default=15"`
Size int `form:"size"`
Pinned *bool `form:"pinned"`
Popup *bool `form:"popup"`
}
@@ -674,7 +664,6 @@ type (
List []SubscribeGroup `json:"list"`
Total int64 `json:"total"`
}
GetUserSubscribeTrafficLogsRequest {
Page int `form:"page"`
Size int `form:"size"`
-4
View File
@@ -1,4 +0,0 @@
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build -o ppanel .\ppanel.go
-26
View File
@@ -1,26 +0,0 @@
package initialize
import (
"context"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/internal/config"
"github.com/perfect-panel/server/internal/model/auth"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/tool"
)
func Device(ctx *svc.ServiceContext) {
logger.Debug("device config initialization")
method, err := ctx.AuthModel.FindOneByMethod(context.Background(), "device")
if err != nil {
panic(err)
}
var cfg config.DeviceConfig
var deviceConfig auth.DeviceConfig
deviceConfig.Unmarshal(method.Config)
tool.DeepCopy(&cfg, deviceConfig)
cfg.Enable = *method.Enabled
ctx.Config.Device = cfg
}
-1
View File
@@ -9,7 +9,6 @@ func StartInitSystemConfig(svc *svc.ServiceContext) {
Site(svc)
Node(svc)
Email(svc)
Device(svc)
Invite(svc)
Verify(svc)
Subscribe(svc)
@@ -1,2 +0,0 @@
ALTER TABLE `ads`
ADD COLUMN `description` VARCHAR(255) DEFAULT '' COMMENT 'Description';
@@ -1,7 +0,0 @@
INSERT INTO `ppanel`.`system` (`category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
SELECT 'site', 'CustomData', '{
"kr_website_id": ""
}', 'string', 'Custom Data', '2025-04-22 14:25:16.637', '2025-10-14 15:47:19.187'
WHERE NOT EXISTS (
SELECT 1 FROM `ppanel`.`system` WHERE `category` = 'site' AND `key` = 'CustomData'
);
@@ -1,7 +0,0 @@
INSERT INTO `ppanel`.`system` (`category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
SELECT 'site', 'CustomData', '{
"kr_website_id": ""
}', 'string', 'Custom Data', '2025-04-22 14:25:16.637', '2025-10-14 15:47:19.187'
WHERE NOT EXISTS (
SELECT 1 FROM `ppanel`.`system` WHERE `category` = 'site' AND `key` = 'CustomData'
);
-11
View File
@@ -2,7 +2,6 @@ package config
import (
"encoding/json"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/orm"
)
@@ -21,7 +20,6 @@ type Config struct {
Node NodeConfig `yaml:"Node"`
Mobile MobileConfig `yaml:"Mobile"`
Email EmailConfig `yaml:"Email"`
Device DeviceConfig `yaml:"device"`
Verify Verify `yaml:"Verify"`
VerifyCode VerifyCode `yaml:"VerifyCode"`
Register RegisterConfig `yaml:"Register"`
@@ -97,14 +95,6 @@ type MobileConfig struct {
Whitelist []string `yaml:"whitelist"`
}
type DeviceConfig struct {
Enable bool `yaml:"enable" default:"true"`
ShowAds bool `yaml:"show_ads"`
EnableSecurity bool `yaml:"enable_security"`
OnlyRealDevice bool `yaml:"only_real_device"`
SecuritySecret string `yaml:"security_secret"`
}
type SiteConfig struct {
Host string `yaml:"Host" default:""`
SiteName string `yaml:"SiteName" default:""`
@@ -203,7 +193,6 @@ type InviteConfig struct {
ForcedInvite bool `yaml:"ForcedInvite" default:"false"`
ReferralPercentage int64 `yaml:"ReferralPercentage" default:"0"`
OnlyFirstPurchase bool `yaml:"OnlyFirstPurchase" default:"false"`
GiftDays int64 `yaml:"GiftDays" default:"3"`
}
type Telegram struct {
@@ -1,26 +0,0 @@
package auth
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/auth"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result"
)
// Device Login
func DeviceLoginHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
var req types.DeviceLoginRequest
_ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req)
if validateErr != nil {
result.ParamErrorResult(c, validateErr)
return
}
l := auth.NewDeviceLoginLogic(c.Request.Context(), svcCtx)
resp, err := l.DeviceLogin(&req)
result.HttpResult(c, resp, err)
}
}
@@ -1,18 +0,0 @@
package subscribe
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/public/subscribe"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/result"
)
// Get user subscribe node info
func QueryUserSubscribeNodeListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
l := subscribe.NewQueryUserSubscribeNodeListLogic(c.Request.Context(), svcCtx)
resp, err := l.QueryUserSubscribeNodeList()
result.HttpResult(c, resp, err)
}
}
@@ -1,18 +0,0 @@
package user
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/public/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/result"
)
// Get Device List
func GetDeviceListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
l := user.NewGetDeviceListLogic(c.Request.Context(), svcCtx)
resp, err := l.GetDeviceList()
result.HttpResult(c, resp, err)
}
}
@@ -1,26 +0,0 @@
package user
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/public/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result"
)
// Unbind Device
func UnbindDeviceHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
var req types.UnbindDeviceRequest
_ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req)
if validateErr != nil {
result.ParamErrorResult(c, validateErr)
return
}
l := user.NewUnbindDeviceLogic(c.Request.Context(), svcCtx)
err := l.UnbindDevice(&req)
result.HttpResult(c, nil, err)
}
}
+9 -24
View File
@@ -578,7 +578,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
}
authGroupRouter := router.Group("/v1/auth")
authGroupRouter.Use(middleware.DeviceMiddleware(serverCtx))
{
// Check user is exist
@@ -590,9 +589,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
// User login
authGroupRouter.POST("/login", auth.UserLoginHandler(serverCtx))
// Device Login
authGroupRouter.POST("/login/device", auth.DeviceLoginHandler(serverCtx))
// User Telephone login
authGroupRouter.POST("/login/telephone", auth.TelephoneLoginHandler(serverCtx))
@@ -623,7 +619,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
}
commonGroupRouter := router.Group("/v1/common")
commonGroupRouter.Use(middleware.DeviceMiddleware(serverCtx))
{
// Get Ads
@@ -655,7 +650,7 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
}
publicAnnouncementGroupRouter := router.Group("/v1/public/announcement")
publicAnnouncementGroupRouter.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))
publicAnnouncementGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{
// Query announcement
@@ -663,7 +658,7 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
}
publicDocumentGroupRouter := router.Group("/v1/public/document")
publicDocumentGroupRouter.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))
publicDocumentGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{
// Get document detail
@@ -674,7 +669,7 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
}
publicOrderGroupRouter := router.Group("/v1/public/order")
publicOrderGroupRouter.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))
publicOrderGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{
// Close order
@@ -703,7 +698,7 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
}
publicPaymentGroupRouter := router.Group("/v1/public/payment")
publicPaymentGroupRouter.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))
publicPaymentGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{
// Get available payment methods
@@ -711,7 +706,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
}
publicPortalGroupRouter := router.Group("/v1/public/portal")
publicPortalGroupRouter.Use(middleware.DeviceMiddleware(serverCtx))
{
// Purchase Checkout
@@ -734,18 +728,15 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
}
publicSubscribeGroupRouter := router.Group("/v1/public/subscribe")
publicSubscribeGroupRouter.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))
publicSubscribeGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{
// Get subscribe list
publicSubscribeGroupRouter.GET("/list", publicSubscribe.QuerySubscribeListHandler(serverCtx))
// Get user subscribe node info
publicSubscribeGroupRouter.GET("/node/list", publicSubscribe.QueryUserSubscribeNodeListHandler(serverCtx))
}
publicTicketGroupRouter := router.Group("/v1/public/ticket")
publicTicketGroupRouter.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))
publicTicketGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{
// Update ticket status
@@ -765,7 +756,7 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
}
publicUserGroupRouter := router.Group("/v1/public/user")
publicUserGroupRouter.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))
publicUserGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{
// Query User Affiliate Count
@@ -795,9 +786,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
// Query User Commission Log
publicUserGroupRouter.GET("/commission_log", publicUser.QueryUserCommissionLogHandler(serverCtx))
// Get Device List
publicUserGroupRouter.GET("/devices", publicUser.GetDeviceListHandler(serverCtx))
// Query User Info
publicUserGroupRouter.GET("/info", publicUser.QueryUserInfoHandler(serverCtx))
@@ -822,9 +810,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
// Reset User Subscribe Token
publicUserGroupRouter.PUT("/subscribe_token", publicUser.ResetUserSubscribeTokenHandler(serverCtx))
// Unbind Device
publicUserGroupRouter.PUT("/unbind_device", publicUser.UnbindDeviceHandler(serverCtx))
// Unbind OAuth
publicUserGroupRouter.POST("/unbind_oauth", publicUser.UnbindOAuthHandler(serverCtx))
@@ -861,10 +846,10 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
serverGroupRouter.GET("/user", server.GetServerUserListHandler(serverCtx))
}
serverGroupRouterV2 := router.Group("/v2/server")
serverV2GroupRouter := router.Group("/v2/server")
{
// Get Server Protocol Config
serverGroupRouterV2.GET("/:server_id", server.QueryServerProtocolConfigHandler(serverCtx))
serverV2GroupRouter.GET("/:server_id", server.QueryServerProtocolConfigHandler(serverCtx))
}
}
@@ -29,12 +29,10 @@ func NewPreviewSubscribeTemplateLogic(ctx context.Context, svcCtx *svc.ServiceCo
}
func (l *PreviewSubscribeTemplateLogic) PreviewSubscribeTemplate(req *types.PreviewSubscribeTemplateRequest) (resp *types.PreviewSubscribeTemplateResponse, err error) {
enable := true
_, servers, err := l.svcCtx.NodeModel.FilterNodeList(l.ctx, &node.FilterNodeParams{
Page: 1,
Size: 1000,
Preload: true,
Enabled: &enable,
})
if err != nil {
l.Errorf("[PreviewSubscribeTemplateLogic] FindAllServer error: %v", err.Error())
@@ -92,9 +92,6 @@ func (l *UpdateAuthMethodConfigLogic) UpdateGlobal(method string) {
if method == "mobile" {
initialize.Mobile(l.svcCtx)
}
if method == "device" {
initialize.Device(l.svcCtx)
}
}
func validatePlatformConfig(platform string, cfg map[string]interface{}) (interface{}, error) {
@@ -230,7 +230,7 @@ func (l *MigrateServerNodeLogic) adapterServer(info *server.Server) (*node.Serve
return nil, err
}
protocol := node.Protocol{
Type: "hysteria",
Type: "hysteria2",
Port: uint16(src.Port),
HopPorts: src.HopPorts,
HopInterval: src.HopInterval,
-314
View File
@@ -1,314 +0,0 @@
package auth
import (
"context"
"github.com/perfect-panel/server/internal/model/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
"gorm.io/gorm"
)
type BindDeviceLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewBindDeviceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BindDeviceLogic {
return &BindDeviceLogic{
Logger: logger.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// BindDeviceToUser binds a device to a user
// If the device is already bound to another user, it will disable that user and bind the device to the current user
func (l *BindDeviceLogic) BindDeviceToUser(identifier, ip, userAgent string, currentUserId int64) error {
if identifier == "" {
// No device identifier provided, skip binding
return nil
}
l.Infow("binding device to user",
logger.Field("identifier", identifier),
logger.Field("user_id", currentUserId),
logger.Field("ip", ip),
)
// Check if device exists
deviceInfo, err := l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, identifier)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
// Device not found, create new device record
return l.createDeviceForUser(identifier, ip, userAgent, currentUserId)
}
l.Errorw("failed to query device",
logger.Field("identifier", identifier),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query device failed: %v", err.Error())
}
// Device exists, check if it's bound to current user
if deviceInfo.UserId == currentUserId {
// Already bound to current user, just update IP and UserAgent
l.Infow("device already bound to current user, updating info",
logger.Field("identifier", identifier),
logger.Field("user_id", currentUserId),
)
deviceInfo.Ip = ip
deviceInfo.UserAgent = userAgent
if err := l.svcCtx.UserModel.UpdateDevice(l.ctx, deviceInfo); err != nil {
l.Errorw("failed to update device",
logger.Field("identifier", identifier),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update device failed: %v", err.Error())
}
return nil
}
// Device is bound to another user, need to disable old user and rebind
l.Infow("device bound to another user, rebinding",
logger.Field("identifier", identifier),
logger.Field("old_user_id", deviceInfo.UserId),
logger.Field("new_user_id", currentUserId),
)
return l.rebindDeviceToNewUser(deviceInfo, ip, userAgent, currentUserId)
}
func (l *BindDeviceLogic) createDeviceForUser(identifier, ip, userAgent string, userId int64) error {
l.Infow("creating new device for user",
logger.Field("identifier", identifier),
logger.Field("user_id", userId),
)
err := l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
// Create device auth method
authMethod := &user.AuthMethods{
UserId: userId,
AuthType: "device",
AuthIdentifier: identifier,
Verified: true,
}
if err := db.Create(authMethod).Error; err != nil {
l.Errorw("failed to create device auth method",
logger.Field("user_id", userId),
logger.Field("identifier", identifier),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create device auth method failed: %v", err)
}
// Create device record
deviceInfo := &user.Device{
Ip: ip,
UserId: userId,
UserAgent: userAgent,
Identifier: identifier,
Enabled: true,
Online: false,
}
if err := db.Create(deviceInfo).Error; err != nil {
l.Errorw("failed to create device",
logger.Field("user_id", userId),
logger.Field("identifier", identifier),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create device failed: %v", err)
}
return nil
})
if err != nil {
l.Errorw("device creation failed",
logger.Field("identifier", identifier),
logger.Field("user_id", userId),
logger.Field("error", err.Error()),
)
return err
}
l.Infow("device created successfully",
logger.Field("identifier", identifier),
logger.Field("user_id", userId),
)
return nil
}
func (l *BindDeviceLogic) rebindDeviceToNewUser(deviceInfo *user.Device, ip, userAgent string, newUserId int64) error {
oldUserId := deviceInfo.UserId
err := l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
// Check if old user has other auth methods besides device
var authMethods []user.AuthMethods
if err := db.Where("user_id = ?", oldUserId).Find(&authMethods).Error; err != nil {
l.Errorw("failed to query auth methods for old user",
logger.Field("old_user_id", oldUserId),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query auth methods failed: %v", err)
}
// Count non-device auth methods
nonDeviceAuthCount := 0
for _, auth := range authMethods {
if auth.AuthType != "device" {
nonDeviceAuthCount++
}
}
// Only disable old user if they have no other auth methods
if nonDeviceAuthCount == 0 {
// Migrate user data from old user to new user before disabling
if err := l.migrateUserData(db, oldUserId, newUserId); err != nil {
l.Errorw("failed to migrate user data",
logger.Field("old_user_id", oldUserId),
logger.Field("new_user_id", newUserId),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "migrate user data failed: %v", err)
}
falseVal := false
if err := db.Model(&user.User{}).Where("id = ?", oldUserId).Update("enable", &falseVal).Error; err != nil {
l.Errorw("failed to disable old user",
logger.Field("old_user_id", oldUserId),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "disable old user failed: %v", err)
}
l.Infow("disabled old user after data migration (no other auth methods)",
logger.Field("old_user_id", oldUserId),
logger.Field("new_user_id", newUserId),
)
} else {
l.Infow("old user has other auth methods, not disabling",
logger.Field("old_user_id", oldUserId),
logger.Field("non_device_auth_count", nonDeviceAuthCount),
)
}
// Update device auth method to new user
if err := db.Model(&user.AuthMethods{}).
Where("auth_type = ? AND auth_identifier = ?", "device", deviceInfo.Identifier).
Update("user_id", newUserId).Error; err != nil {
l.Errorw("failed to update device auth method",
logger.Field("identifier", deviceInfo.Identifier),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update device auth method failed: %v", err)
}
// Update device record
deviceInfo.UserId = newUserId
deviceInfo.Ip = ip
deviceInfo.UserAgent = userAgent
deviceInfo.Enabled = true
if err := db.Save(deviceInfo).Error; err != nil {
l.Errorw("failed to update device",
logger.Field("identifier", deviceInfo.Identifier),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update device failed: %v", err)
}
return nil
})
if err != nil {
l.Errorw("device rebinding failed",
logger.Field("identifier", deviceInfo.Identifier),
logger.Field("old_user_id", oldUserId),
logger.Field("new_user_id", newUserId),
logger.Field("error", err.Error()),
)
return err
}
l.Infow("device rebound successfully",
logger.Field("identifier", deviceInfo.Identifier),
logger.Field("old_user_id", oldUserId),
logger.Field("new_user_id", newUserId),
)
return nil
}
// migrateUserData migrates user data from old user to new user
// This includes orders, subscriptions, balance, and other user-related data
func (l *BindDeviceLogic) migrateUserData(db *gorm.DB, oldUserId, newUserId int64) error {
l.Infow("starting user data migration",
logger.Field("old_user_id", oldUserId),
logger.Field("new_user_id", newUserId),
)
// Migrate orders - using table name directly
if err := db.Table("order").Where("user_id = ?", oldUserId).Update("user_id", newUserId).Error; err != nil {
l.Errorw("failed to migrate orders",
logger.Field("old_user_id", oldUserId),
logger.Field("new_user_id", newUserId),
logger.Field("error", err.Error()),
)
return err
}
// Migrate user subscriptions - using Subscribe model
if err := db.Model(&user.Subscribe{}).Where("user_id = ?", oldUserId).Update("user_id", newUserId).Error; err != nil {
l.Errorw("failed to migrate user subscriptions",
logger.Field("old_user_id", oldUserId),
logger.Field("new_user_id", newUserId),
logger.Field("error", err.Error()),
)
return err
}
// Migrate user balance and gift amount
var oldUser user.User
if err := db.Where("id = ?", oldUserId).First(&oldUser).Error; err != nil {
l.Errorw("failed to get old user data",
logger.Field("old_user_id", oldUserId),
logger.Field("error", err.Error()),
)
return err
}
// Add old user's balance and gift to new user
if oldUser.Balance > 0 || oldUser.GiftAmount > 0 {
if err := db.Model(&user.User{}).Where("id = ?", newUserId).Updates(map[string]interface{}{
"balance": gorm.Expr("balance + ?", oldUser.Balance),
"gift_amount": gorm.Expr("gift_amount + ?", oldUser.GiftAmount),
}).Error; err != nil {
l.Errorw("failed to migrate user balance and gift",
logger.Field("old_user_id", oldUserId),
logger.Field("new_user_id", newUserId),
logger.Field("old_balance", oldUser.Balance),
logger.Field("old_gift", oldUser.GiftAmount),
logger.Field("error", err.Error()),
)
return err
}
}
// Migrate other user-related tables if needed
// Note: We don't migrate auth methods as they are handled separately
// Note: Traffic usage (Upload/Download) is tracked at subscription level, not user level
l.Infow("user data migration completed",
logger.Field("old_user_id", oldUserId),
logger.Field("new_user_id", newUserId),
logger.Field("migrated_balance", oldUser.Balance),
logger.Field("migrated_gift", oldUser.GiftAmount),
)
return nil
}
-293
View File
@@ -1,293 +0,0 @@
package auth
import (
"context"
"fmt"
"time"
"github.com/perfect-panel/server/internal/config"
"github.com/perfect-panel/server/internal/model/log"
"github.com/perfect-panel/server/internal/model/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/jwt"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/tool"
"github.com/perfect-panel/server/pkg/uuidx"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
"gorm.io/gorm"
)
type DeviceLoginLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// Device Login
func NewDeviceLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeviceLoginLogic {
return &DeviceLoginLogic{
Logger: logger.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *types.LoginResponse, err error) {
if !l.svcCtx.Config.Device.Enable {
return nil, xerr.NewErrMsg("Device login is disabled")
}
loginStatus := false
var userInfo *user.User
// Record login status
defer func() {
if userInfo != nil && userInfo.Id != 0 {
loginLog := log.Login{
Method: "device",
LoginIP: req.IP,
UserAgent: req.UserAgent,
Success: loginStatus,
Timestamp: time.Now().UnixMilli(),
}
content, _ := loginLog.Marshal()
if err := l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
Type: log.TypeLogin.Uint8(),
Date: time.Now().Format("2006-01-02"),
ObjectID: userInfo.Id,
Content: string(content),
}); err != nil {
l.Errorw("failed to insert login log",
logger.Field("user_id", userInfo.Id),
logger.Field("ip", req.IP),
logger.Field("error", err.Error()),
)
}
}
}()
// Check if device exists by identifier
deviceInfo, err := l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, req.Identifier)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
// Device not found, create new user and device
userInfo, err = l.registerUserAndDevice(req)
if err != nil {
return nil, err
}
} else {
l.Errorw("query device failed",
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query device failed: %v", err.Error())
}
} else {
// Device found, get user info
userInfo, err = l.svcCtx.UserModel.FindOne(l.ctx, deviceInfo.UserId)
if err != nil {
l.Errorw("query user failed",
logger.Field("user_id", deviceInfo.UserId),
logger.Field("error", err.Error()),
)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query user failed: %v", err.Error())
}
}
// Generate session id
sessionId := uuidx.NewUUID().String()
// Generate token
token, err := jwt.NewJwtToken(
l.svcCtx.Config.JwtAuth.AccessSecret,
time.Now().Unix(),
l.svcCtx.Config.JwtAuth.AccessExpire,
jwt.WithOption("UserId", userInfo.Id),
jwt.WithOption("SessionId", sessionId),
jwt.WithOption("LoginType", "device"),
)
if err != nil {
l.Errorw("token generate error",
logger.Field("user_id", userInfo.Id),
logger.Field("error", err.Error()),
)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "token generate error: %v", err.Error())
}
// Store session id in redis
sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId)
if err = l.svcCtx.Redis.Set(l.ctx, sessionIdCacheKey, userInfo.Id, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err(); err != nil {
l.Errorw("set session id error",
logger.Field("user_id", userInfo.Id),
logger.Field("error", err.Error()),
)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "set session id error: %v", err.Error())
}
loginStatus = true
return &types.LoginResponse{
Token: token,
}, nil
}
func (l *DeviceLoginLogic) registerUserAndDevice(req *types.DeviceLoginRequest) (*user.User, error) {
l.Infow("device not found, creating new user and device",
logger.Field("identifier", req.Identifier),
logger.Field("ip", req.IP),
)
var userInfo *user.User
err := l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
// Create new user
userInfo = &user.User{
OnlyFirstPurchase: &l.svcCtx.Config.Invite.OnlyFirstPurchase,
}
if err := db.Create(userInfo).Error; err != nil {
l.Errorw("failed to create user",
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create user failed: %v", err)
}
// Update refer code
userInfo.ReferCode = uuidx.UserInviteCode(userInfo.Id)
if err := db.Model(&user.User{}).Where("id = ?", userInfo.Id).Update("refer_code", userInfo.ReferCode).Error; err != nil {
l.Errorw("failed to update refer code",
logger.Field("user_id", userInfo.Id),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update refer code failed: %v", err)
}
// Create device auth method
authMethod := &user.AuthMethods{
UserId: userInfo.Id,
AuthType: "device",
AuthIdentifier: req.Identifier,
Verified: true,
}
if err := db.Create(authMethod).Error; err != nil {
l.Errorw("failed to create device auth method",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create device auth method failed: %v", err)
}
// Insert device record
deviceInfo := &user.Device{
Ip: req.IP,
UserId: userInfo.Id,
UserAgent: req.UserAgent,
Identifier: req.Identifier,
Enabled: true,
Online: false,
}
if err := db.Create(deviceInfo).Error; err != nil {
l.Errorw("failed to insert device",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "insert device failed: %v", err)
}
// Activate trial if enabled
if l.svcCtx.Config.Register.EnableTrial {
if err := l.activeTrial(userInfo.Id, db); err != nil {
return err
}
}
return nil
})
if err != nil {
l.Errorw("device registration failed",
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
return nil, err
}
l.Infow("device registration completed successfully",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", req.Identifier),
logger.Field("refer_code", userInfo.ReferCode),
)
// Register log
registerLog := log.Register{
AuthMethod: "device",
Identifier: req.Identifier,
RegisterIP: req.IP,
UserAgent: req.UserAgent,
Timestamp: time.Now().UnixMilli(),
}
content, _ := registerLog.Marshal()
if err := l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
Type: log.TypeRegister.Uint8(),
Date: time.Now().Format("2006-01-02"),
ObjectID: userInfo.Id,
Content: string(content),
}); err != nil {
l.Errorw("failed to insert register log",
logger.Field("user_id", userInfo.Id),
logger.Field("ip", req.IP),
logger.Field("error", err.Error()),
)
}
return userInfo, nil
}
func (l *DeviceLoginLogic) activeTrial(userId int64, db *gorm.DB) error {
sub, err := l.svcCtx.SubscribeModel.FindOne(l.ctx, l.svcCtx.Config.Register.TrialSubscribe)
if err != nil {
l.Errorw("failed to find trial subscription template",
logger.Field("user_id", userId),
logger.Field("trial_subscribe_id", l.svcCtx.Config.Register.TrialSubscribe),
logger.Field("error", err.Error()),
)
return err
}
startTime := time.Now()
expireTime := tool.AddTime(l.svcCtx.Config.Register.TrialTimeUnit, l.svcCtx.Config.Register.TrialTime, startTime)
subscribeToken := uuidx.SubscribeToken(fmt.Sprintf("Trial-%v", userId))
subscribeUUID := uuidx.NewUUID().String()
userSub := &user.Subscribe{
UserId: userId,
OrderId: 0,
SubscribeId: sub.Id,
StartTime: startTime,
ExpireTime: expireTime,
Traffic: sub.Traffic,
Download: 0,
Upload: 0,
Token: subscribeToken,
UUID: subscribeUUID,
Status: 1,
}
if err := db.Create(userSub).Error; err != nil {
l.Errorw("failed to insert trial subscription",
logger.Field("user_id", userId),
logger.Field("error", err.Error()),
)
return err
}
l.Infow("trial subscription activated successfully",
logger.Field("user_id", userId),
logger.Field("subscribe_id", sub.Id),
logger.Field("expire_time", expireTime),
logger.Field("traffic", sub.Traffic),
)
return nil
}
-17
View File
@@ -107,22 +107,6 @@ func (l *ResetPasswordLogic) ResetPassword(req *types.ResetPasswordRequest) (res
if err := l.svcCtx.UserModel.Update(l.ctx, userInfo); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update user info failed: %v", err.Error())
}
// Bind device to user if identifier is provided
if req.Identifier != "" {
bindLogic := NewBindDeviceLogic(l.ctx, l.svcCtx)
if err := bindLogic.BindDeviceToUser(req.Identifier, req.IP, req.UserAgent, userInfo.Id); err != nil {
l.Errorw("failed to bind device to user",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
// Don't fail register if device binding fails, just log the error
}
}
if l.ctx.Value(constant.LoginType) != nil {
req.LoginType = l.ctx.Value(constant.LoginType).(string)
}
// Generate session id
sessionId := uuidx.NewUUID().String()
// Generate token
@@ -132,7 +116,6 @@ func (l *ResetPasswordLogic) ResetPassword(req *types.ResetPasswordRequest) (res
l.svcCtx.Config.JwtAuth.AccessExpire,
jwt.WithOption("UserId", userInfo.Id),
jwt.WithOption("SessionId", sessionId),
jwt.WithOption("LoginType", req.LoginType),
)
if err != nil {
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
@@ -124,23 +124,6 @@ func (l *TelephoneLoginLogic) TelephoneLogin(req *types.TelephoneLoginRequest, r
l.svcCtx.Redis.Del(l.ctx, cacheKey)
}
// Bind device to user if identifier is provided
if req.Identifier != "" {
bindLogic := NewBindDeviceLogic(l.ctx, l.svcCtx)
if err := bindLogic.BindDeviceToUser(req.Identifier, req.IP, req.UserAgent, userInfo.Id); err != nil {
l.Errorw("failed to bind device to user",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
// Don't fail login if device binding fails, just log the error
}
}
if l.ctx.Value(constant.LoginType) != nil {
req.LoginType = l.ctx.Value(constant.LoginType).(string)
}
// Generate session id
sessionId := uuidx.NewUUID().String()
// Generate token
@@ -150,7 +133,6 @@ func (l *TelephoneLoginLogic) TelephoneLogin(req *types.TelephoneLoginRequest, r
l.svcCtx.Config.JwtAuth.AccessExpire,
jwt.WithOption("UserId", userInfo.Id),
jwt.WithOption("SessionId", sessionId),
jwt.WithOption("LoginType", req.LoginType),
)
if err != nil {
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
@@ -83,21 +83,6 @@ func (l *TelephoneResetPasswordLogic) TelephoneResetPassword(req *types.Telephon
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "update user password failed: %v", err.Error())
}
// Bind device to user if identifier is provided
if req.Identifier != "" {
bindLogic := NewBindDeviceLogic(l.ctx, l.svcCtx)
if err := bindLogic.BindDeviceToUser(req.Identifier, req.IP, req.UserAgent, userInfo.Id); err != nil {
l.Errorw("failed to bind device to user",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
// Don't fail register if device binding fails, just log the error
}
}
if l.ctx.Value(constant.LoginType) != nil {
req.LoginType = l.ctx.Value(constant.LoginType).(string)
}
// Generate session id
sessionId := uuidx.NewUUID().String()
// Generate token
@@ -107,7 +92,6 @@ func (l *TelephoneResetPasswordLogic) TelephoneResetPassword(req *types.Telephon
l.svcCtx.Config.JwtAuth.AccessExpire,
jwt.WithOption("UserId", userInfo.Id),
jwt.WithOption("SessionId", sessionId),
jwt.WithOption("LoginType", req.LoginType),
)
if err != nil {
l.Errorw("[UserLogin] token generate error", logger.Field("error", err.Error()))
@@ -138,22 +138,6 @@ func (l *TelephoneUserRegisterLogic) TelephoneUserRegister(req *types.TelephoneR
}
return nil
})
// Bind device to user if identifier is provided
if req.Identifier != "" {
bindLogic := NewBindDeviceLogic(l.ctx, l.svcCtx)
if err := bindLogic.BindDeviceToUser(req.Identifier, req.IP, req.UserAgent, userInfo.Id); err != nil {
l.Errorw("failed to bind device to user",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
// Don't fail register if device binding fails, just log the error
}
}
if l.ctx.Value(constant.LoginType) != nil {
req.LoginType = l.ctx.Value(constant.LoginType).(string)
}
// Generate session id
sessionId := uuidx.NewUUID().String()
// Generate token
@@ -163,7 +147,6 @@ func (l *TelephoneUserRegisterLogic) TelephoneUserRegister(req *types.TelephoneR
l.svcCtx.Config.JwtAuth.AccessExpire,
jwt.WithOption("UserId", userInfo.Id),
jwt.WithOption("SessionId", sessionId),
jwt.WithOption("LoginType", req.LoginType),
)
if err != nil {
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
-18
View File
@@ -6,7 +6,6 @@ import (
"time"
"github.com/perfect-panel/server/internal/model/log"
"github.com/perfect-panel/server/pkg/constant"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/internal/config"
@@ -80,22 +79,6 @@ func (l *UserLoginLogic) UserLogin(req *types.UserLoginRequest) (resp *types.Log
if !tool.VerifyPassWord(req.Password, userInfo.Password) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserPasswordError), "user password")
}
// Bind device to user if identifier is provided
if req.Identifier != "" {
bindLogic := NewBindDeviceLogic(l.ctx, l.svcCtx)
if err := bindLogic.BindDeviceToUser(req.Identifier, req.IP, req.UserAgent, userInfo.Id); err != nil {
l.Errorw("failed to bind device to user",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
// Don't fail login if device binding fails, just log the error
}
}
if l.ctx.Value(constant.LoginType) != nil {
req.LoginType = l.ctx.Value(constant.LoginType).(string)
}
// Generate session id
sessionId := uuidx.NewUUID().String()
// Generate token
@@ -105,7 +88,6 @@ func (l *UserLoginLogic) UserLogin(req *types.UserLoginRequest) (resp *types.Log
l.svcCtx.Config.JwtAuth.AccessExpire,
jwt.WithOption("UserId", userInfo.Id),
jwt.WithOption("SessionId", sessionId),
jwt.WithOption("LoginType", req.LoginType),
)
if err != nil {
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
-16
View File
@@ -125,21 +125,6 @@ func (l *UserRegisterLogic) UserRegister(req *types.UserRegisterRequest) (resp *
}
return nil
})
// Bind device to user if identifier is provided
if req.Identifier != "" {
bindLogic := NewBindDeviceLogic(l.ctx, l.svcCtx)
if err := bindLogic.BindDeviceToUser(req.Identifier, req.IP, req.UserAgent, userInfo.Id); err != nil {
l.Errorw("failed to bind device to user",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", req.Identifier),
logger.Field("error", err.Error()),
)
// Don't fail register if device binding fails, just log the error
}
}
if l.ctx.Value(constant.LoginType) != nil {
req.LoginType = l.ctx.Value(constant.LoginType).(string)
}
// Generate session id
sessionId := uuidx.NewUUID().String()
// Generate token
@@ -149,7 +134,6 @@ func (l *UserRegisterLogic) UserRegister(req *types.UserRegisterRequest) (resp *
l.svcCtx.Config.JwtAuth.AccessExpire,
jwt.WithOption("UserId", userInfo.Id),
jwt.WithOption("SessionId", sessionId),
jwt.WithOption("LoginType", req.LoginType),
)
if err != nil {
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
@@ -2,7 +2,6 @@ package common
import (
"context"
"encoding/json"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
@@ -68,10 +67,6 @@ func (l *GetGlobalConfigLogic) GetGlobalConfig() (resp *types.GetGlobalConfigRes
for _, method := range authMethods {
if *method.Enabled {
methods = append(methods, method.Method)
if method.Method == "device" {
_ = json.Unmarshal([]byte(method.Config), &resp.Auth.Device)
resp.Auth.Device.Enable = true
}
}
}
resp.OAuthMethods = methods
+12 -1
View File
@@ -61,7 +61,18 @@ func (l *CloseOrderLogic) CloseOrder(req *types.CloseOrderRequest) error {
)
return err
}
// All orders now have associated users, no special handling needed for guest orders
// If User ID is 0, it means that the order is a guest order and does not need to be refunded, the order can be deleted directly
if orderInfo.UserId == 0 {
err = tx.Model(&order.Order{}).Where("order_no = ?", req.OrderNo).Delete(&order.Order{}).Error
if err != nil {
l.Errorw("[CloseOrder] Delete order failed",
logger.Field("error", err.Error()),
logger.Field("orderNo", req.OrderNo),
)
return err
}
return nil
}
// refund deduction amount to user deduction balance
if orderInfo.GiftAmount > 0 {
userInfo, err := l.svcCtx.UserModel.FindOne(l.ctx, orderInfo.UserId)
+2 -2
View File
@@ -3,7 +3,7 @@ package order
import "github.com/perfect-panel/server/internal/types"
func getDiscount(discounts []types.SubscribeDiscount, inputMonths int64) float64 {
var finalDiscount float64 = 1.0
var finalDiscount int64 = 100
for _, discount := range discounts {
if inputMonths >= discount.Quantity && discount.Discount < finalDiscount {
@@ -11,5 +11,5 @@ func getDiscount(discounts []types.SubscribeDiscount, inputMonths int64) float64
}
}
return finalDiscount
return float64(finalDiscount) / float64(100)
}
+2 -2
View File
@@ -7,14 +7,14 @@ import (
)
func getDiscount(discounts []types.SubscribeDiscount, inputMonths int64) float64 {
var finalDiscount float64 = 1.0
var finalDiscount int64 = 100
for _, discount := range discounts {
if inputMonths >= discount.Quantity && discount.Discount < finalDiscount {
finalDiscount = discount.Discount
}
}
return finalDiscount
return float64(finalDiscount) / float64(100)
}
func calculateCoupon(amount int64, couponInfo *coupon.Coupon) int64 {
@@ -1,195 +0,0 @@
package subscribe
import (
"context"
"strings"
"time"
"github.com/perfect-panel/server/internal/model/node"
"github.com/perfect-panel/server/internal/model/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/constant"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/tool"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
)
type QueryUserSubscribeNodeListLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// Get user subscribe node info
func NewQueryUserSubscribeNodeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryUserSubscribeNodeListLogic {
return &QueryUserSubscribeNodeListLogic{
Logger: logger.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *QueryUserSubscribeNodeListLogic) QueryUserSubscribeNodeList() (resp *types.QueryUserSubscribeNodeListResponse, err error) {
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
if !ok {
logger.Error("current user is not found in context")
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
}
userSubscribes, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, u.Id, 1, 2)
if err != nil {
logger.Errorw("failed to query user subscribe", logger.Field("error", err.Error()), logger.Field("user_id", u.Id))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "DB_ERROR")
}
resp = &types.QueryUserSubscribeNodeListResponse{}
for _, us := range userSubscribes {
userSubscribe, err := l.getUserSubscribe(us.Token)
if err != nil {
l.Errorw("[SubscribeLogic] Get user subscribe failed", logger.Field("error", err.Error()), logger.Field("token", userSubscribe.Token))
return nil, err
}
nodes, err := l.getServers(userSubscribe)
if err != nil {
return nil, err
}
userSubscribeInfo := types.UserSubscribeInfo{
Id: userSubscribe.Id,
Nodes: nodes,
Traffic: userSubscribe.Traffic,
Upload: userSubscribe.Upload,
Download: userSubscribe.Download,
Token: userSubscribe.Token,
UserId: userSubscribe.UserId,
OrderId: userSubscribe.OrderId,
SubscribeId: userSubscribe.SubscribeId,
StartTime: userSubscribe.StartTime.Unix(),
ExpireTime: userSubscribe.ExpireTime.Unix(),
Status: userSubscribe.Status,
CreatedAt: userSubscribe.CreatedAt.Unix(),
UpdatedAt: userSubscribe.UpdatedAt.Unix(),
}
if userSubscribe.FinishedAt != nil {
userSubscribeInfo.FinishedAt = userSubscribe.FinishedAt.Unix()
}
if l.svcCtx.Config.Register.EnableTrial && l.svcCtx.Config.Register.TrialSubscribe == userSubscribe.SubscribeId {
userSubscribeInfo.IsTryOut = true
}
resp.List = append(resp.List, userSubscribeInfo)
}
return
}
func (l *QueryUserSubscribeNodeListLogic) getServers(userSub *user.Subscribe) (userSubscribeNodes []*types.UserSubscribeNodeInfo, err error) {
userSubscribeNodes = make([]*types.UserSubscribeNodeInfo, 0)
if l.isSubscriptionExpired(userSub) {
return l.createExpiredServers(), nil
}
subDetails, err := l.svcCtx.SubscribeModel.FindOne(l.ctx, userSub.SubscribeId)
if err != nil {
l.Errorw("[Generate Subscribe]find subscribe details error: %v", logger.Field("error", err.Error()))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find subscribe details error: %v", err.Error())
}
nodeIds := tool.StringToInt64Slice(subDetails.Nodes)
tags := strings.Split(subDetails.NodeTags, ",")
l.Debugf("[Generate Subscribe]nodes: %v, NodeTags: %v", nodeIds, tags)
enable := true
_, nodes, err := l.svcCtx.NodeModel.FilterNodeList(l.ctx, &node.FilterNodeParams{
Page: 0,
Size: 1000,
NodeId: nodeIds,
Enabled: &enable, // Only get enabled nodes
})
if len(nodes) > 0 {
var serverMapIds = make(map[int64]*node.Server)
for _, n := range nodes {
serverMapIds[n.ServerId] = nil
}
var serverIds []int64
for k := range serverMapIds {
serverIds = append(serverIds, k)
}
servers, err := l.svcCtx.NodeModel.QueryServerList(l.ctx, serverIds)
if err != nil {
l.Errorw("[Generate Subscribe]find server details error: %v", logger.Field("error", err.Error()))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find server details error: %v", err.Error())
}
for _, s := range servers {
serverMapIds[s.Id] = s
}
for _, n := range nodes {
server := serverMapIds[n.ServerId]
if server == nil {
continue
}
userSubscribeNode := &types.UserSubscribeNodeInfo{
Id: n.Id,
Name: n.Name,
Uuid: userSub.UUID,
Protocol: n.Protocol,
Port: n.Port,
Address: n.Address,
Tags: strings.Split(n.Tags, ","),
Country: server.Country,
City: server.City,
CreatedAt: n.CreatedAt.Unix(),
}
userSubscribeNodes = append(userSubscribeNodes, userSubscribeNode)
}
}
l.Debugf("[Query Subscribe]found servers: %v", len(nodes))
if err != nil {
l.Errorw("[Generate Subscribe]find server details error: %v", logger.Field("error", err.Error()))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find server details error: %v", err.Error())
}
logger.Debugf("[Generate Subscribe]found servers: %v", len(nodes))
return userSubscribeNodes, nil
}
func (l *QueryUserSubscribeNodeListLogic) isSubscriptionExpired(userSub *user.Subscribe) bool {
return userSub.ExpireTime.Unix() < time.Now().Unix() && userSub.ExpireTime.Unix() != 0
}
func (l *QueryUserSubscribeNodeListLogic) createExpiredServers() []*types.UserSubscribeNodeInfo {
return nil
}
func (l *QueryUserSubscribeNodeListLogic) getFirstHostLine() string {
host := l.svcCtx.Config.Host
lines := strings.Split(host, "\n")
if len(lines) > 0 {
return lines[0]
}
return host
}
func (l *QueryUserSubscribeNodeListLogic) getUserSubscribe(token string) (*user.Subscribe, error) {
userSub, err := l.svcCtx.UserModel.FindOneSubscribeByToken(l.ctx, token)
if err != nil {
l.Infow("[Generate Subscribe]find subscribe error: %v", logger.Field("error", err.Error()), logger.Field("token", token))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find subscribe error: %v", err.Error())
}
// Ignore expiration check
//if userSub.Status > 1 {
// l.Infow("[Generate Subscribe]subscribe is not available", logger.Field("status", int(userSub.Status)), logger.Field("token", token))
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SubscribeNotAvailable), "subscribe is not available")
//}
return userSub, nil
}
@@ -1,39 +0,0 @@
package user
import (
"context"
"github.com/perfect-panel/server/internal/model/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/constant"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/tool"
)
type GetDeviceListLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// Get Device List
func NewGetDeviceListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetDeviceListLogic {
return &GetDeviceListLogic{
Logger: logger.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetDeviceListLogic) GetDeviceList() (resp *types.GetDeviceListResponse, err error) {
userInfo := l.ctx.Value(constant.CtxKeyUser).(*user.User)
list, count, err := l.svcCtx.UserModel.QueryDeviceList(l.ctx, userInfo.Id)
userRespList := make([]types.UserDevice, 0)
tool.DeepCopy(&userRespList, list)
resp = &types.GetDeviceListResponse{
Total: count,
List: userRespList,
}
return
}
@@ -1,72 +0,0 @@
package user
import (
"context"
"fmt"
"github.com/perfect-panel/server/internal/config"
"github.com/perfect-panel/server/internal/model/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/constant"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
"gorm.io/gorm"
)
type UnbindDeviceLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// Unbind Device
func NewUnbindDeviceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UnbindDeviceLogic {
return &UnbindDeviceLogic{
Logger: logger.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *UnbindDeviceLogic) UnbindDevice(req *types.UnbindDeviceRequest) error {
userInfo := l.ctx.Value(constant.CtxKeyUser).(*user.User)
device, err := l.svcCtx.UserModel.FindOneDevice(l.ctx, req.Id)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DeviceNotExist), "find device")
}
if device.UserId != userInfo.Id {
return errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "device not belong to user")
}
return l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
var deleteDevice user.Device
err = tx.Model(&deleteDevice).Where("id = ?", req.Id).First(&deleteDevice).Error
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.QueueEnqueueError), "find device err: %v", err)
}
err = tx.Delete(deleteDevice).Error
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "delete device err: %v", err)
}
var userAuth user.AuthMethods
err = tx.Model(&userAuth).Where("auth_identifier = ? and auth_type = ?", deleteDevice.Identifier, "device").First(&userAuth).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find device online record err: %v", err)
}
err = tx.Delete(&userAuth).Error
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "delete device online record err: %v", err)
}
sessionId := l.ctx.Value(constant.CtxKeySessionID)
sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId)
l.svcCtx.Redis.Del(l.ctx, sessionIdCacheKey)
return nil
})
}
@@ -48,47 +48,22 @@ func (l *UpdateBindEmailLogic) UpdateBindEmail(req *types.UpdateBindEmailRequest
if m.Id > 0 {
return errors.Wrapf(xerr.NewErrCode(xerr.UserExist), "email already bind")
}
// Use transaction to safely handle insert or update
err = l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
if method.Id == 0 {
// Check if record exists in current transaction
var existingMethod user.AuthMethods
err := db.Model(&user.AuthMethods{}).Where("user_id = ? AND auth_type = ?", u.Id, "email").First(&existingMethod).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
// Create new record
method = &user.AuthMethods{
UserId: u.Id,
AuthType: "email",
AuthIdentifier: req.Email,
Verified: false,
}
if err := db.Create(method).Error; err != nil {
return err
}
} else {
return err
}
} else {
// Record exists, update it
existingMethod.AuthIdentifier = req.Email
existingMethod.Verified = false
if err := db.Save(&existingMethod).Error; err != nil {
return err
}
}
} else {
// Update existing record
method.Verified = false
method.AuthIdentifier = req.Email
if err := db.Save(method).Error; err != nil {
return err
}
if method.Id == 0 {
method = &user.AuthMethods{
UserId: u.Id,
AuthType: "email",
AuthIdentifier: req.Email,
Verified: false,
}
if err := l.svcCtx.UserModel.InsertUserAuthMethods(l.ctx, method); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "InsertUserAuthMethods error")
}
} else {
method.Verified = false
method.AuthIdentifier = req.Email
if err := l.svcCtx.UserModel.UpdateUserAuthMethods(l.ctx, method); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "UpdateUserAuthMethods error")
}
return nil
})
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "UpdateBindEmail transaction error")
}
return nil
}
+1 -4
View File
@@ -8,10 +8,7 @@ const (
Trojan = "trojan"
AnyTLS = "anytls"
Tuic = "tuic"
Hysteria = "hysteria"
// Deprecated: Hysteria2 is deprecated, use Hysteria instead
// TODO: remove in future versions
Hysteria2 = "hysteria2"
Hysteria2 = "hysteria2"
)
type SecurityConfig struct {
@@ -57,19 +57,13 @@ func (l *GetServerConfigLogic) GetServerConfig(req *types.GetServerConfigRequest
return nil, err
}
// compatible hysteria2, remove in future versions
protocolRequest := req.Protocol
if protocolRequest == Hysteria2 {
protocolRequest = Hysteria
}
protocols, err := data.UnmarshalProtocols()
if err != nil {
return nil, err
}
var cfg map[string]interface{}
for _, protocol := range protocols {
if protocol.Type == protocolRequest {
if protocol.Type == req.Protocol {
cfg = l.compatible(protocol)
break
}
@@ -215,7 +209,7 @@ func (l *GetServerConfigLogic) compatible(config node.Protocol) map[string]inter
RealityShortId: config.RealityShortId,
},
}
case Hysteria:
case Hysteria2:
result = Hysteria2Node{
Port: config.Port,
HopPorts: config.HopPorts,
+2 -4
View File
@@ -249,9 +249,8 @@ func (l *SubscribeLogic) createExpiredServers() []*node.Node {
Port: 18080,
Address: "127.0.0.1",
Server: &node.Server{
Id: 1,
Name: "Subscribe Expired",
Protocols: "[{\"type\":\"shadowsocks\",\"cipher\":\"aes-256-gcm\",\"port\":1}]",
Protocols: "[{\"type:\"\"shadowsocks\",\"cipher\":\"aes-256-gcm\",\"port\":1}]",
},
Protocol: "shadowsocks",
Enabled: &enable,
@@ -262,9 +261,8 @@ func (l *SubscribeLogic) createExpiredServers() []*node.Node {
Port: 18080,
Address: "127.0.0.1",
Server: &node.Server{
Id: 1,
Name: "Subscribe Expired",
Protocols: "[{\"type\":\"shadowsocks\",\"cipher\":\"aes-256-gcm\",\"port\":1}]",
Protocols: "[{\"type:\"\"shadowsocks\",\"cipher\":\"aes-256-gcm\",\"port\":1}]",
},
Protocol: "shadowsocks",
Enabled: &enable,
-6
View File
@@ -40,11 +40,6 @@ func AuthMiddleware(svc *svc.ServiceContext) func(c *gin.Context) {
c.Abort()
return
}
loginType := ""
if claims["LoginType"] != nil {
loginType = claims["LoginType"].(string)
}
// get user id from token
userId := int64(claims["UserId"].(float64))
// get session id from token
@@ -82,7 +77,6 @@ func AuthMiddleware(svc *svc.ServiceContext) func(c *gin.Context) {
c.Abort()
return
}
ctx = context.WithValue(ctx, constant.LoginType, loginType)
ctx = context.WithValue(ctx, constant.CtxKeyUser, userInfo)
ctx = context.WithValue(ctx, constant.CtxKeySessionID, sessionId)
c.Request = c.Request.WithContext(ctx)
-295
View File
@@ -1,295 +0,0 @@
package middleware
import (
"bufio"
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"strings"
"github.com/perfect-panel/server/internal/svc"
pkgaes "github.com/perfect-panel/server/pkg/aes"
"github.com/perfect-panel/server/pkg/constant"
"github.com/perfect-panel/server/pkg/result"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
"github.com/gin-gonic/gin"
)
const (
noWritten = -1
defaultStatus = http.StatusOK
)
func DeviceMiddleware(srvCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
if !srvCtx.Config.Device.Enable {
c.Next()
return
}
if srvCtx.Config.Device.SecuritySecret == "" {
result.HttpResult(c, nil, errors.Wrapf(xerr.NewErrCode(xerr.SecretIsEmpty), "Secret is empty"))
c.Abort()
return
}
ctx := c.Request.Context()
if ctx.Value(constant.CtxKeyUser) == nil && c.GetHeader("Login-Type") != "" {
ctx = context.WithValue(ctx, constant.LoginType, c.GetHeader("Login-Type"))
c.Request = c.Request.WithContext(ctx)
}
loginType, ok := ctx.Value(constant.LoginType).(string)
if !ok || loginType != "device" {
c.Next()
return
}
rw := NewResponseWriter(c, srvCtx)
if !rw.Decrypt() {
result.HttpResult(c, nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidCiphertext), "Invalid ciphertext"))
c.Abort()
return
}
c.Writer = rw
c.Next()
rw.FlushAbort()
}
}
func NewResponseWriter(c *gin.Context, srvCtx *svc.ServiceContext) (rw *ResponseWriter) {
rw = &ResponseWriter{
c: c,
body: new(bytes.Buffer),
ResponseWriter: c.Writer,
}
rw.encryptionKey = srvCtx.Config.Device.SecuritySecret
rw.encryptionMethod = "AES"
rw.encryption = true
return rw
}
func (rw *ResponseWriter) Encrypt() {
if !rw.encryption {
return
}
buf := rw.body.Bytes()
params := map[string]interface{}{}
err := json.Unmarshal(buf, &params)
if err != nil {
return
}
data := params["data"]
if data != nil {
var jsonData []byte
str, ok := data.(string)
if ok {
jsonData = []byte(str)
} else {
jsonData, _ = json.Marshal(data)
}
encrypt, iv, err := pkgaes.Encrypt(jsonData, rw.encryptionKey)
if err != nil {
return
}
params["data"] = map[string]interface{}{
"data": encrypt,
"time": iv,
}
}
marshal, _ := json.Marshal(params)
rw.body.Reset()
rw.body.Write(marshal)
}
func (rw *ResponseWriter) Decrypt() bool {
if !rw.encryption {
return true
}
//判断url链接中是否存在data和iv数据,存在就进行解密并设置回去
query := rw.c.Request.URL.Query()
dataStr := query.Get("data")
timeStr := query.Get("time")
if dataStr != "" && timeStr != "" {
decrypt, err := pkgaes.Decrypt(dataStr, rw.encryptionKey, timeStr)
if err == nil {
params := map[string]interface{}{}
err = json.Unmarshal([]byte(decrypt), &params)
if err == nil {
for k, v := range params {
query.Set(k, fmt.Sprintf("%v", v))
}
query.Del("data")
query.Del("time")
rw.c.Request.RequestURI = fmt.Sprintf("%s?%s", rw.c.Request.RequestURI[:strings.Index(rw.c.Request.RequestURI, "?")], query.Encode())
rw.c.Request.URL.RawQuery = query.Encode()
}
}
}
//判断body是否存在数据,存在就尝试解密,并设置回去
body, err := io.ReadAll(rw.c.Request.Body)
if err != nil {
return true
}
if len(body) == 0 {
return true
}
params := map[string]interface{}{}
err = json.Unmarshal(body, &params)
data := params["data"]
nonce := params["time"]
if err != nil || data == nil {
return false
}
str, ok := data.(string)
if !ok {
return false
}
iv, ok := nonce.(string)
if !ok {
return false
}
decrypt, err := pkgaes.Decrypt(str, rw.encryptionKey, iv)
if err != nil {
return false
}
rw.c.Request.Body = io.NopCloser(bytes.NewBuffer([]byte(decrypt)))
return true
}
func (rw *ResponseWriter) FlushAbort() {
defer rw.c.Abort()
responseBody := rw.body.String()
fmt.Println("Original Response Body:", responseBody)
rw.flush = true
if rw.encryption {
rw.Encrypt()
}
_, err := rw.Write(rw.body.Bytes())
if err != nil {
return
}
}
type ResponseWriter struct {
http.ResponseWriter
size int
status int
flush bool
body *bytes.Buffer
c *gin.Context
encryption bool
encryptionKey string
encryptionMethod string
}
func (rw *ResponseWriter) Unwrap() http.ResponseWriter {
return rw.ResponseWriter
}
//nolint:unused
func (rw *ResponseWriter) reset(writer http.ResponseWriter) {
rw.ResponseWriter = writer
rw.size = noWritten
rw.status = defaultStatus
}
func (rw *ResponseWriter) WriteHeader(code int) {
if code > 0 && rw.status != code {
if rw.Written() {
return
}
rw.status = code
}
}
func (rw *ResponseWriter) WriteHeaderNow() {
if !rw.Written() {
rw.size = 0
rw.ResponseWriter.WriteHeader(rw.status)
}
}
func (rw *ResponseWriter) Write(data []byte) (n int, err error) {
if rw.flush {
rw.WriteHeaderNow()
n, err = rw.ResponseWriter.Write(data)
rw.size += n
} else {
rw.body.Write(data)
}
return
}
func (rw *ResponseWriter) WriteString(s string) (n int, err error) {
if rw.flush {
rw.WriteHeaderNow()
n, err = rw.ResponseWriter.Write([]byte(s))
rw.size += n
} else {
rw.body.Write([]byte(s))
}
return
}
func (rw *ResponseWriter) Status() int {
return rw.status
}
func (rw *ResponseWriter) Size() int {
return rw.size
}
func (rw *ResponseWriter) Written() bool {
return rw.size != noWritten
}
// Hijack implements the http.Hijacker interface.
func (rw *ResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
if rw.size < 0 {
rw.size = 0
}
return rw.ResponseWriter.(http.Hijacker).Hijack()
}
// CloseNotify implements the http.CloseNotifier interface.
func (rw *ResponseWriter) CloseNotify() <-chan bool {
// 通过 r.Context().Done() 来监听请求的取消
done := rw.c.Request.Context().Done()
closed := make(chan bool)
// 当上下文被取消时,通过 closed channel 发送通知
go func() {
<-done
closed <- true
}()
return closed
}
// Flush implements the http.Flusher interface.
func (rw *ResponseWriter) Flush() {
rw.WriteHeaderNow()
rw.ResponseWriter.(http.Flusher).Flush()
}
func (rw *ResponseWriter) Pusher() (pusher http.Pusher) {
if pusher, ok := rw.ResponseWriter.(http.Pusher); ok {
return pusher
}
return nil
}
+1 -1
View File
@@ -43,7 +43,7 @@ func (m *customAnnouncementModel) GetAnnouncementListByPage(ctx context.Context,
if filter.Search != "" {
conn = conn.Where("`title` LIKE ? OR `content` LIKE ?", "%"+filter.Search+"%", "%"+filter.Search+"%")
}
return conn.Count(&total).Offset((page - 1) * size).Limit(size).Find(&list).Error
return conn.Count(&total).Offset((page - 1) * size).Limit(size).Find(v).Error
})
return total, list, err
}
-1
View File
@@ -23,7 +23,6 @@ type (
UpdateServer(ctx context.Context, data *Server, tx ...*gorm.DB) error
DeleteServer(ctx context.Context, id int64, tx ...*gorm.DB) error
Transaction(ctx context.Context, fn func(db *gorm.DB) error) error
QueryServerList(ctx context.Context, ids []int64) (servers []*Server, err error)
}
NodeModel interface {
+4 -28
View File
@@ -3,10 +3,8 @@ package node
import (
"context"
"fmt"
"strings"
"github.com/perfect-panel/server/pkg/tool"
"gorm.io/gorm"
)
type customServerLogicModel interface {
@@ -65,12 +63,6 @@ func (m *customServerModel) FilterServerList(ctx context.Context, params *Filter
return total, servers, err
}
func (m *customServerModel) QueryServerList(ctx context.Context, ids []int64) (servers []*Server, err error) {
query := m.WithContext(ctx).Model(&Server{})
err = query.Where("id IN (?)", ids).Find(&servers).Error
return
}
// FilterNodeList Filter Node List
func (m *customServerModel) FilterNodeList(ctx context.Context, params *FilterNodeParams) (int64, []*Node, error) {
var nodes []*Node
@@ -93,7 +85,10 @@ func (m *customServerModel) FilterNodeList(ctx context.Context, params *FilterNo
query = query.Where("server_id IN ?", params.ServerId)
}
if len(params.Tag) > 0 {
query = query.Scopes(InSet("tags", params.Tag))
query = query.Where("1 = 0")
for _, tag := range params.Tag {
query = query.Or("FIND_IN_SET(?,tags)", tag)
}
}
if params.Protocol != "" {
query = query.Where("protocol = ?", params.Protocol)
@@ -170,22 +165,3 @@ func (m *customServerModel) ClearServerCache(ctx context.Context, serverId int64
}
return nil
}
// InSet 支持多值 OR 查询
func InSet(field string, values []string) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
if len(values) == 0 {
return db
}
conds := make([]string, len(values))
args := make([]interface{}, len(values))
for i, v := range values {
conds[i] = "FIND_IN_SET(?, " + field + ")"
args[i] = v
}
// 用括号包裹 OR 条件,保证外层 AND 不受影响
return db.Where("("+strings.Join(conds, " OR ")+")", args...)
}
}
+2 -2
View File
@@ -71,8 +71,8 @@ func (s *Subscribe) BeforeUpdate(tx *gorm.DB) error {
}
type Discount struct {
Months int64 `json:"months"`
Discount float64 `json:"discount"`
Months int64 `json:"months"`
Discount int64 `json:"discount"`
}
type Group struct {
-25
View File
@@ -46,16 +46,6 @@ func (m *customUserModel) QueryDevicePageList(ctx context.Context, userId, subsc
return list, total, err
}
// QueryDeviceList returns a list of records that meet the conditions.
func (m *customUserModel) QueryDeviceList(ctx context.Context, userId int64) ([]*Device, int64, error) {
var list []*Device
var total int64
err := m.QueryNoCacheCtx(ctx, &list, func(conn *gorm.DB, v interface{}) error {
return conn.Model(&Device{}).Where("`user_id` = ?", userId).Count(&total).Find(&list).Error
})
return list, total, err
}
func (m *customUserModel) UpdateDevice(ctx context.Context, data *Device, tx ...*gorm.DB) error {
old, err := m.FindOneDevice(ctx, data.Id)
if err != nil {
@@ -86,18 +76,3 @@ func (m *customUserModel) DeleteDevice(ctx context.Context, id int64, tx ...*gor
}, data.GetCacheKeys()...)
return err
}
func (m *customUserModel) InsertDevice(ctx context.Context, data *Device, tx ...*gorm.DB) error {
defer func() {
if clearErr := m.ClearDeviceCache(ctx, data); clearErr != nil {
// log cache clear error
}
}()
return m.ExecNoCacheCtx(ctx, func(conn *gorm.DB) error {
if len(tx) > 0 {
conn = tx[0]
}
return conn.Create(data).Error
})
}
-3
View File
@@ -77,7 +77,6 @@ type customUserLogicModel interface {
QueryUserSubscribe(ctx context.Context, userId int64, status ...int64) ([]*SubscribeDetails, error)
FindOneSubscribeDetailsById(ctx context.Context, id int64) (*SubscribeDetails, error)
FindOneUserSubscribe(ctx context.Context, id int64) (*SubscribeDetails, error)
FindActiveSubscribe(ctx context.Context, userId int64) (*Subscribe, error)
FindUsersSubscribeBySubscribeId(ctx context.Context, subscribeId int64) ([]*Subscribe, error)
UpdateUserSubscribeWithTraffic(ctx context.Context, id, download, upload int64, tx ...*gorm.DB) error
QueryResisterUserTotalByDate(ctx context.Context, date time.Time) (int64, error)
@@ -96,12 +95,10 @@ type customUserLogicModel interface {
FindUserAuthMethodByPlatform(ctx context.Context, userId int64, platform string) (*AuthMethods, error)
FindOneByEmail(ctx context.Context, email string) (*User, error)
FindOneDevice(ctx context.Context, id int64) (*Device, error)
QueryDeviceList(ctx context.Context, userid int64) ([]*Device, int64, error)
QueryDevicePageList(ctx context.Context, userid, subscribeId int64, page, size int) ([]*Device, int64, error)
UpdateDevice(ctx context.Context, data *Device, tx ...*gorm.DB) error
FindOneDeviceByIdentifier(ctx context.Context, id string) (*Device, error)
DeleteDevice(ctx context.Context, id int64, tx ...*gorm.DB) error
InsertDevice(ctx context.Context, data *Device, tx ...*gorm.DB) error
ClearSubscribeCache(ctx context.Context, data ...*Subscribe) error
ClearUserCache(ctx context.Context, data ...*User) error
-21
View File
@@ -198,24 +198,3 @@ func (m *defaultUserModel) DeleteSubscribeById(ctx context.Context, id int64, tx
func (m *defaultUserModel) ClearSubscribeCache(ctx context.Context, data ...*Subscribe) error {
return m.ClearSubscribeCacheByModels(ctx, data...)
}
// FindActiveSubscribe finds the user's active subscription
func (m *defaultUserModel) FindActiveSubscribe(ctx context.Context, userId int64) (*Subscribe, error) {
var data Subscribe
err := m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, v interface{}) error {
now := time.Now()
return conn.Model(&Subscribe{}).
Where("user_id = ? AND status = ? AND expire_time > ?", userId, 1, now).
Order("expire_time DESC").
First(&data).Error
})
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, err
}
return &data, nil
}
+21 -95
View File
@@ -118,7 +118,6 @@ type ApplicationVersion struct {
type AuthConfig struct {
Mobile MobileAuthenticateConfig `json:"mobile"`
Email EmailAuthticateConfig `json:"email"`
Device DeviceAuthticateConfig `json:"device"`
Register PubilcRegisterConfig `json:"register"`
}
@@ -518,20 +517,6 @@ type DeleteUserSubscribeRequest struct {
UserSubscribeId int64 `json:"user_subscribe_id"`
}
type DeviceAuthticateConfig struct {
Enable bool `json:"enable"`
ShowAds bool `json:"show_ads"`
EnableSecurity bool `json:"enable_security"`
OnlyRealDevice bool `json:"only_real_device"`
}
type DeviceLoginRequest struct {
Identifier string `json:"identifier" validate:"required"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `json:"user_agent" validate:"required"`
CfToken string `json:"cf_token,optional"`
}
type Document struct {
Id int64 `json:"id"`
Title string `json:"title"`
@@ -817,11 +802,6 @@ type GetDetailRequest struct {
Id int64 `form:"id" validate:"required"`
}
type GetDeviceListResponse struct {
List []UserDevice `json:"list"`
Total int64 `json:"total"`
}
type GetDocumentDetailRequest struct {
Id int64 `json:"id" validate:"required"`
}
@@ -1170,7 +1150,6 @@ type InviteConfig struct {
ForcedInvite bool `json:"forced_invite"`
ReferralPercentage int64 `json:"referral_percentage"`
OnlyFirstPurchase bool `json:"only_first_purchase"`
GiftDays int64 `json:"gift_days"`
}
type KickOfflineRequest struct {
@@ -1541,7 +1520,7 @@ type PurchaseOrderResponse struct {
type QueryAnnouncementRequest struct {
Page int `form:"page"`
Size int `form:"size,default=15"`
Size int `form:"size"`
Pinned *bool `form:"pinned"`
Popup *bool `form:"popup"`
}
@@ -1698,10 +1677,6 @@ type QueryUserSubscribeListResponse struct {
Total int64 `json:"total"`
}
type QueryUserSubscribeNodeListResponse struct {
List []UserSubscribeInfo `json:"list"`
}
type QuotaTask struct {
Id int64 `json:"id"`
Subscribers []int64 `json:"subscribers"`
@@ -1762,14 +1737,12 @@ type RenewalOrderResponse struct {
}
type ResetPasswordRequest struct {
Identifier string `json:"identifier"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
CfToken string `json:"cf_token,optional"`
}
type ResetSortRequest struct {
@@ -2066,8 +2039,8 @@ type SubscribeConfig struct {
}
type SubscribeDiscount struct {
Quantity int64 `json:"quantity"`
Discount float64 `json:"discount"`
Quantity int64 `json:"quantity"`
Discount int64 `json:"discount"`
}
type SubscribeGroup struct {
@@ -2117,19 +2090,16 @@ type TelephoneCheckUserResponse struct {
}
type TelephoneLoginRequest struct {
Identifier string `json:"identifier"`
Telephone string `json:"telephone" validate:"required"`
TelephoneCode string `json:"telephone_code"`
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
Password string `json:"password"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
}
type TelephoneRegisterRequest struct {
Identifier string `json:"identifier"`
Telephone string `json:"telephone" validate:"required"`
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
Password string `json:"password" validate:"required"`
@@ -2137,19 +2107,16 @@ type TelephoneRegisterRequest struct {
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type,optional"`
CfToken string `json:"cf_token,optional"`
}
type TelephoneResetPasswordRequest struct {
Identifier string `json:"identifier"`
Telephone string `json:"telephone" validate:"required"`
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
Password string `json:"password" validate:"required"`
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type,optional"`
CfToken string `json:"cf_token,optional"`
}
@@ -2244,10 +2211,6 @@ type Tuic struct {
SecurityConfig SecurityConfig `json:"security_config"`
}
type UnbindDeviceRequest struct {
Id int64 `json:"id" validate:"required"`
}
type UnbindOAuthRequest struct {
Method string `json:"method"`
}
@@ -2527,25 +2490,21 @@ type UserLoginLog struct {
}
type UserLoginRequest struct {
Identifier string `json:"identifier"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
CfToken string `json:"cf_token,optional"`
}
type UserRegisterRequest struct {
Identifier string `json:"identifier"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Invite string `json:"invite,optional"`
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Invite string `json:"invite,optional"`
Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
CfToken string `json:"cf_token,optional"`
}
type UserStatistics struct {
@@ -2600,26 +2559,6 @@ type UserSubscribeDetail struct {
UpdatedAt int64 `json:"updated_at"`
}
type UserSubscribeInfo struct {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
OrderId int64 `json:"order_id"`
SubscribeId int64 `json:"subscribe_id"`
StartTime int64 `json:"start_time"`
ExpireTime int64 `json:"expire_time"`
FinishedAt int64 `json:"finished_at"`
ResetTime int64 `json:"reset_time"`
Traffic int64 `json:"traffic"`
Download int64 `json:"download"`
Upload int64 `json:"upload"`
Token string `json:"token"`
Status uint8 `json:"status"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
IsTryOut bool `json:"is_try_out"`
Nodes []*UserSubscribeNodeInfo `json:"nodes"`
}
type UserSubscribeLog struct {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
@@ -2630,19 +2569,6 @@ type UserSubscribeLog struct {
Timestamp int64 `json:"timestamp"`
}
type UserSubscribeNodeInfo struct {
Id int64 `json:"id"`
Name string `json:"name"`
Uuid string `json:"uuid"`
Protocol string `json:"protocol"`
Port uint16 `json:"port"`
Address string `json:"address"`
Tags []string `json:"tags"`
Country string `json:"country"`
City string `json:"city"`
CreatedAt int64 `json:"created_at"`
}
type UserSubscribeTrafficLog struct {
SubscribeId int64 `json:"subscribe_id"` // Subscribe ID
UserId int64 `json:"user_id"` // User ID
-648
View File
@@ -1,648 +0,0 @@
{"caller":"queue/queue.go:23","content":"start consumer service","level":"info","timestamp":"2025-10-17 09:32:30.652"}
{"caller":"scheduler/scheduler.go:26","content":"start scheduler service","level":"info","timestamp":"2025-10-17 09:32:30.652"}
{"caller":"initialize/version.go:21","content":"[Migrate] database not change","level":"info","timestamp":"2025-10-17 09:32:30.656"}
{"caller":"initialize/site.go:15","content":"[GORM] SQL Executed","duration":"0.3ms","level":"info","rows":7,"sql":"SELECT * FROM `system` WHERE `category` = 'site'","timestamp":"2025-10-17 09:32:30.656"}
{"caller":"initialize/node.go:17","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":9,"sql":"SELECT * FROM `system` WHERE `category` = 'server'","timestamp":"2025-10-17 09:32:30.657"}
{"caller":"internal/server.go:69","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":1,"sql":"SELECT * FROM `system` WHERE `key` = 'NodeMultiplierConfig'","timestamp":"2025-10-17 09:32:30.657"}
{"caller":"initialize/node.go:70","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":1,"sql":"SELECT * FROM `system` WHERE `category` = 'server' AND `key` = 'NodeMultiplierConfig'","timestamp":"2025-10-17 09:32:30.657"}
{"caller":"initialize/email.go:18","content":"[GORM] SQL Executed","duration":"0.3ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'email' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:32:30.657"}
{"caller":"initialize/device.go:16","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'device' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:32:30.658"}
{"caller":"initialize/invite.go:15","content":"[GORM] SQL Executed","duration":"0.3ms","level":"info","rows":3,"sql":"SELECT * FROM `system` WHERE `category` = 'invite'","timestamp":"2025-10-17 09:32:30.659"}
{"caller":"initialize/verify.go:23","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":5,"sql":"SELECT * FROM `system` WHERE `category` = 'verify'","timestamp":"2025-10-17 09:32:30.659"}
{"caller":"initialize/verify.go:41","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":3,"sql":"SELECT * FROM `system` WHERE `category` = 'verify_code'","timestamp":"2025-10-17 09:32:30.660"}
{"caller":"initialize/subscribe.go:15","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":6,"sql":"SELECT * FROM `system` WHERE `category` = 'subscribe'","timestamp":"2025-10-17 09:32:30.660"}
{"caller":"initialize/register.go:15","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":8,"sql":"SELECT * FROM `system` WHERE `category` = 'register'","timestamp":"2025-10-17 09:32:30.660"}
{"caller":"initialize/mobile.go:17","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'mobile' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:32:30.661"}
{"caller":"initialize/telegram.go:19","content":"[GORM] SQL Executed","duration":"0.2ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'telegram' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:32:30.661"}
{"caller":"trace/agent.go:46","content":"Starting agent","level":"info","timestamp":"2025-10-17 09:32:30.661"}
{"caller":"internal/server.go:87","content":"server start at 0.0.0.0:8888","level":"info","timestamp":"2025-10-17 09:32:30.662"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:33:30","level":"info","timestamp":"2025-10-17 09:33:30.781"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:33:30.786"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:33:30.786"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:33:30.787' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:33:30.788"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:33:30.788"}
{"caller":"scheduler/scheduler.go:55","content":"stop scheduler service","level":"info","timestamp":"2025-10-17 09:34:09.417"}
{"caller":"queue/queue.go:36","content":"stop consumer service","level":"info","timestamp":"2025-10-17 09:34:09.417"}
{"caller":"internal/server.go:108","content":"server shutdown","level":"info","timestamp":"2025-10-17 09:34:09.417"}
{"caller":"queue/queue.go:23","content":"start consumer service","level":"info","timestamp":"2025-10-17 09:34:24.620"}
{"caller":"scheduler/scheduler.go:26","content":"start scheduler service","level":"info","timestamp":"2025-10-17 09:34:24.620"}
{"caller":"initialize/version.go:21","content":"[Migrate] database not change","level":"info","timestamp":"2025-10-17 09:34:24.632"}
{"caller":"initialize/site.go:15","content":"[GORM] SQL Executed","duration":"0.6ms","level":"info","rows":7,"sql":"SELECT * FROM `system` WHERE `category` = 'site'","timestamp":"2025-10-17 09:34:24.632"}
{"caller":"initialize/node.go:17","content":"[GORM] SQL Executed","duration":"0.4ms","level":"info","rows":9,"sql":"SELECT * FROM `system` WHERE `category` = 'server'","timestamp":"2025-10-17 09:34:24.633"}
{"caller":"internal/server.go:69","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":1,"sql":"SELECT * FROM `system` WHERE `key` = 'NodeMultiplierConfig'","timestamp":"2025-10-17 09:34:24.634"}
{"caller":"initialize/node.go:70","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":1,"sql":"SELECT * FROM `system` WHERE `category` = 'server' AND `key` = 'NodeMultiplierConfig'","timestamp":"2025-10-17 09:34:24.634"}
{"caller":"initialize/email.go:18","content":"[GORM] SQL Executed","duration":"0.9ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'email' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:34:24.635"}
{"caller":"initialize/device.go:16","content":"[GORM] SQL Executed","duration":"1.5ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'device' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:34:24.637"}
{"caller":"initialize/invite.go:15","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":3,"sql":"SELECT * FROM `system` WHERE `category` = 'invite'","timestamp":"2025-10-17 09:34:24.638"}
{"caller":"initialize/verify.go:23","content":"[GORM] SQL Executed","duration":"0.4ms","level":"info","rows":5,"sql":"SELECT * FROM `system` WHERE `category` = 'verify'","timestamp":"2025-10-17 09:34:24.639"}
{"caller":"initialize/verify.go:41","content":"[GORM] SQL Executed","duration":"0.4ms","level":"info","rows":3,"sql":"SELECT * FROM `system` WHERE `category` = 'verify_code'","timestamp":"2025-10-17 09:34:24.640"}
{"caller":"initialize/subscribe.go:15","content":"[GORM] SQL Executed","duration":"0.4ms","level":"info","rows":6,"sql":"SELECT * FROM `system` WHERE `category` = 'subscribe'","timestamp":"2025-10-17 09:34:24.640"}
{"caller":"initialize/register.go:15","content":"[GORM] SQL Executed","duration":"0.4ms","level":"info","rows":8,"sql":"SELECT * FROM `system` WHERE `category` = 'register'","timestamp":"2025-10-17 09:34:24.641"}
{"caller":"initialize/mobile.go:17","content":"[GORM] SQL Executed","duration":"0.4ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'mobile' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:34:24.642"}
{"caller":"initialize/telegram.go:19","content":"[GORM] SQL Executed","duration":"0.3ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'telegram' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:34:24.642"}
{"caller":"trace/agent.go:46","content":"Starting agent","level":"info","timestamp":"2025-10-17 09:34:24.643"}
{"caller":"internal/server.go:87","content":"server start at 0.0.0.0:8888","level":"info","timestamp":"2025-10-17 09:34:24.643"}
{"caller":"scheduler/scheduler.go:55","content":"stop scheduler service","level":"info","timestamp":"2025-10-17 09:34:38.883"}
{"caller":"queue/queue.go:36","content":"stop consumer service","level":"info","timestamp":"2025-10-17 09:34:38.883"}
{"caller":"internal/server.go:108","content":"server shutdown","level":"info","timestamp":"2025-10-17 09:34:38.884"}
{"caller":"queue/queue.go:23","content":"start consumer service","level":"info","timestamp":"2025-10-17 09:35:25.934"}
{"caller":"scheduler/scheduler.go:26","content":"start scheduler service","level":"info","timestamp":"2025-10-17 09:35:25.934"}
{"caller":"initialize/version.go:21","content":"[Migrate] database not change","level":"info","timestamp":"2025-10-17 09:35:25.941"}
{"caller":"initialize/site.go:15","content":"[GORM] SQL Executed","duration":"0.9ms","level":"info","rows":7,"sql":"SELECT * FROM `system` WHERE `category` = 'site'","timestamp":"2025-10-17 09:35:25.942"}
{"caller":"initialize/node.go:17","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":9,"sql":"SELECT * FROM `system` WHERE `category` = 'server'","timestamp":"2025-10-17 09:35:25.943"}
{"caller":"internal/server.go:69","content":"[GORM] SQL Executed","duration":"0.6ms","level":"info","rows":1,"sql":"SELECT * FROM `system` WHERE `key` = 'NodeMultiplierConfig'","timestamp":"2025-10-17 09:35:25.944"}
{"caller":"initialize/node.go:70","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":1,"sql":"SELECT * FROM `system` WHERE `category` = 'server' AND `key` = 'NodeMultiplierConfig'","timestamp":"2025-10-17 09:35:25.944"}
{"caller":"initialize/email.go:18","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'email' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:35:25.945"}
{"caller":"initialize/device.go:16","content":"[GORM] SQL Executed","duration":"0.6ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'device' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:35:25.946"}
{"caller":"initialize/invite.go:15","content":"[GORM] SQL Executed","duration":"0.8ms","level":"info","rows":3,"sql":"SELECT * FROM `system` WHERE `category` = 'invite'","timestamp":"2025-10-17 09:35:25.947"}
{"caller":"initialize/verify.go:23","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":5,"sql":"SELECT * FROM `system` WHERE `category` = 'verify'","timestamp":"2025-10-17 09:35:25.949"}
{"caller":"initialize/verify.go:41","content":"[GORM] SQL Executed","duration":"0.6ms","level":"info","rows":3,"sql":"SELECT * FROM `system` WHERE `category` = 'verify_code'","timestamp":"2025-10-17 09:35:25.950"}
{"caller":"initialize/subscribe.go:15","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":6,"sql":"SELECT * FROM `system` WHERE `category` = 'subscribe'","timestamp":"2025-10-17 09:35:25.951"}
{"caller":"initialize/register.go:15","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":8,"sql":"SELECT * FROM `system` WHERE `category` = 'register'","timestamp":"2025-10-17 09:35:25.952"}
{"caller":"initialize/mobile.go:17","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'mobile' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:35:25.953"}
{"caller":"initialize/telegram.go:19","content":"[GORM] SQL Executed","duration":"0.4ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'telegram' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:35:25.954"}
{"caller":"trace/agent.go:46","content":"Starting agent","level":"info","timestamp":"2025-10-17 09:35:25.954"}
{"caller":"internal/server.go:87","content":"server start at 0.0.0.0:8888","level":"info","timestamp":"2025-10-17 09:35:25.954"}
{"caller":"common/getGlobalConfigLogic.go:33","content":"[GORM] SQL Executed","duration":"3.5ms","level":"info","rows":4,"span":"23ea0d3dd45bef4b","sql":"SELECT * FROM `system` WHERE `category` = 'currency'","timestamp":"2025-10-17 09:35:51.484","trace":"f44ddbb808543a1db0e36ac991c5fbc6"}
{"caller":"common/getGlobalConfigLogic.go:63","content":"[GORM] SQL Executed","duration":"0.9ms","level":"info","rows":8,"span":"23ea0d3dd45bef4b","sql":"SELECT * FROM `auth_method`","timestamp":"2025-10-17 09:35:51.485","trace":"f44ddbb808543a1db0e36ac991c5fbc6"}
{"caller":"common/getGlobalConfigLogic.go:79","content":"[GORM] SQL Executed","duration":"1.6ms","level":"info","rows":1,"span":"23ea0d3dd45bef4b","sql":"SELECT * FROM `system` WHERE `key` = 'WebAD' ORDER BY `system`.`id` LIMIT 1","timestamp":"2025-10-17 09:35:51.487","trace":"f44ddbb808543a1db0e36ac991c5fbc6"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"8.180333ms","ip":"::1","level":"info","query":"","request":"GET localhost:8888/v1/common/site/config","span":"23ea0d3dd45bef4b","status":200,"timestamp":"2025-10-17 09:35:51.488","trace":"f44ddbb808543a1db0e36ac991c5fbc6","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"2.417µs","ip":"::1","level":"info","query":"","request":"GET localhost:8888/favicon.ico","span":"765789945009392c","status":404,"timestamp":"2025-10-17 09:35:51.505","trace":"83524d5ade65a4e5de8598c8629ed226","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"}
{"caller":"scheduler/scheduler.go:55","content":"stop scheduler service","level":"info","timestamp":"2025-10-17 09:36:17.890"}
{"caller":"queue/queue.go:36","content":"stop consumer service","level":"info","timestamp":"2025-10-17 09:36:17.892"}
{"caller":"queue/queue.go:23","content":"start consumer service","level":"info","timestamp":"2025-10-17 09:36:19.449"}
{"caller":"scheduler/scheduler.go:26","content":"start scheduler service","level":"info","timestamp":"2025-10-17 09:36:19.449"}
{"caller":"initialize/version.go:21","content":"[Migrate] database not change","level":"info","timestamp":"2025-10-17 09:36:19.457"}
{"caller":"initialize/site.go:15","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":7,"sql":"SELECT * FROM `system` WHERE `category` = 'site'","timestamp":"2025-10-17 09:36:19.458"}
{"caller":"initialize/node.go:17","content":"[GORM] SQL Executed","duration":"1.2ms","level":"info","rows":9,"sql":"SELECT * FROM `system` WHERE `category` = 'server'","timestamp":"2025-10-17 09:36:19.460"}
{"caller":"internal/server.go:69","content":"[GORM] SQL Executed","duration":"0.8ms","level":"info","rows":1,"sql":"SELECT * FROM `system` WHERE `key` = 'NodeMultiplierConfig'","timestamp":"2025-10-17 09:36:19.461"}
{"caller":"initialize/node.go:70","content":"[GORM] SQL Executed","duration":"0.9ms","level":"info","rows":1,"sql":"SELECT * FROM `system` WHERE `category` = 'server' AND `key` = 'NodeMultiplierConfig'","timestamp":"2025-10-17 09:36:19.462"}
{"caller":"initialize/email.go:18","content":"[GORM] SQL Executed","duration":"0.6ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'email' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:36:19.463"}
{"caller":"initialize/device.go:16","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'device' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:36:19.463"}
{"caller":"initialize/invite.go:15","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":3,"sql":"SELECT * FROM `system` WHERE `category` = 'invite'","timestamp":"2025-10-17 09:36:19.464"}
{"caller":"initialize/verify.go:23","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":5,"sql":"SELECT * FROM `system` WHERE `category` = 'verify'","timestamp":"2025-10-17 09:36:19.465"}
{"caller":"initialize/verify.go:41","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":3,"sql":"SELECT * FROM `system` WHERE `category` = 'verify_code'","timestamp":"2025-10-17 09:36:19.466"}
{"caller":"initialize/subscribe.go:15","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":6,"sql":"SELECT * FROM `system` WHERE `category` = 'subscribe'","timestamp":"2025-10-17 09:36:19.466"}
{"caller":"initialize/register.go:15","content":"[GORM] SQL Executed","duration":"0.6ms","level":"info","rows":8,"sql":"SELECT * FROM `system` WHERE `category` = 'register'","timestamp":"2025-10-17 09:36:19.467"}
{"caller":"initialize/mobile.go:17","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'mobile' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:36:19.469"}
{"caller":"initialize/telegram.go:19","content":"[GORM] SQL Executed","duration":"0.5ms","level":"info","rows":1,"sql":"SELECT * FROM `auth_method` WHERE method = 'telegram' ORDER BY `auth_method`.`id` LIMIT 1","timestamp":"2025-10-17 09:36:19.469"}
{"caller":"trace/agent.go:46","content":"Starting agent","level":"info","timestamp":"2025-10-17 09:36:19.470"}
{"caller":"internal/server.go:87","content":"server start at 0.0.0.0:8080","level":"info","timestamp":"2025-10-17 09:36:19.470"}
{"caller":"common/getGlobalConfigLogic.go:33","content":"[GORM] SQL Executed","duration":"2.4ms","level":"info","rows":4,"span":"e3720526d2c6bebd","sql":"SELECT * FROM `system` WHERE `category` = 'currency'","timestamp":"2025-10-17 09:36:23.372","trace":"7a72be23eb1f252558c027732d1a15b1"}
{"caller":"common/getGlobalConfigLogic.go:63","content":"[GORM] SQL Executed","duration":"0.8ms","level":"info","rows":8,"span":"e3720526d2c6bebd","sql":"SELECT * FROM `auth_method`","timestamp":"2025-10-17 09:36:23.374","trace":"7a72be23eb1f252558c027732d1a15b1"}
{"caller":"common/getGlobalConfigLogic.go:79","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":1,"span":"e3720526d2c6bebd","sql":"SELECT * FROM `system` WHERE `key` = 'WebAD' ORDER BY `system`.`id` LIMIT 1","timestamp":"2025-10-17 09:36:23.376","trace":"7a72be23eb1f252558c027732d1a15b1"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"8.298417ms","ip":"::1","level":"info","query":"","request":"GET localhost:8080/v1/common/site/config","span":"e3720526d2c6bebd","status":200,"timestamp":"2025-10-17 09:36:23.377","trace":"7a72be23eb1f252558c027732d1a15b1","user-agent":"Go-http-client/1.1"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"391.583µs","ip":"192.168.1.100","level":"info","query":"","request":"POST localhost:8080/v1/auth/login/device","request_body":"{\"identifier\":\"device-001\",\"user_agent\":\"TestAgent/1.0\"}","response_body":"{\"code\":500,\"msg\":\"Device login is disabled\"}","span":"4824a79c0640edee","status":200,"timestamp":"2025-10-17 09:36:23.379","trace":"a852e5e4ac87ab817310e695aade6c8a","user-agent":"Go-http-client/1.1"}
{"caller":"common/getGlobalConfigLogic.go:63","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":8,"span":"d06ea00d90ad1c47","sql":"SELECT * FROM `auth_method`","timestamp":"2025-10-17 09:36:29.384","trace":"73f36f8cadf14346785ce6b9f73711bd"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"1.671166ms","ip":"::1","level":"info","query":"","request":"GET localhost:8080/v1/common/site/config","span":"d06ea00d90ad1c47","status":200,"timestamp":"2025-10-17 09:36:29.384","trace":"73f36f8cadf14346785ce6b9f73711bd","user-agent":"curl/8.7.1"}
{"caller":"common/getGlobalConfigLogic.go:63","content":"[GORM] SQL Executed","duration":"8.2ms","level":"info","rows":8,"span":"4986cbc59b822fc5","sql":"SELECT * FROM `auth_method`","timestamp":"2025-10-17 09:36:37.414","trace":"a2b8f7ee63d9e0d38b54d59a3d736071"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"9.138042ms","ip":"::1","level":"info","query":"","request":"GET localhost:8080/v1/common/site/config","span":"4986cbc59b822fc5","status":200,"timestamp":"2025-10-17 09:36:37.414","trace":"a2b8f7ee63d9e0d38b54d59a3d736071","user-agent":"curl/8.7.1"}
{"caller":"common/getGlobalConfigLogic.go:63","content":"[GORM] SQL Executed","duration":"0.8ms","level":"info","rows":8,"span":"dd41f835e4cfedd6","sql":"SELECT * FROM `auth_method`","timestamp":"2025-10-17 09:36:41.131","trace":"f854a0e96eebb1c50b355c3224599d72"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"1.6465ms","ip":"::1","level":"info","query":"","request":"GET localhost:8080/v1/common/site/config","span":"dd41f835e4cfedd6","status":200,"timestamp":"2025-10-17 09:36:41.131","trace":"f854a0e96eebb1c50b355c3224599d72","user-agent":"Go-http-client/1.1"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"104.916µs","ip":"192.168.1.100","level":"info","query":"","request":"POST localhost:8080/v1/auth/login/device","request_body":"{\"identifier\":\"device-001\",\"user_agent\":\"TestAgent/1.0\"}","response_body":"{\"code\":500,\"msg\":\"Device login is disabled\"}","span":"83a85bacb229a286","status":200,"timestamp":"2025-10-17 09:36:41.132","trace":"ee8e5f35edf0f3a0534980f842feaae6","user-agent":"Go-http-client/1.1"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:37:19","level":"info","timestamp":"2025-10-17 09:37:19.595"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"10.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:37:19.612"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:37:19.612"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:37:19.613' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:37:19.617"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:37:19.617"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"847.75µs","error":"UserAgent is a required field","ip":"::1","level":"info","query":"","request":"POST localhost:8080/v1/auth/login/device","request_body":"{\"identifier\":\"device-001\"}","response_body":"{\"code\":400,\"msg\":\"UserAgent is a required field\"}","span":"806eee7134c85656","status":200,"timestamp":"2025-10-17 09:37:37.117","trace":"147a42ddb57fec3df54d2be5ce791020","user-agent":"TestAgent/1.0"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:38:19","level":"info","timestamp":"2025-10-17 09:38:19.733"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:38:19.745"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:38:19.745"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:38:19.747' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:38:19.749"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:38:19.749"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:39:19","level":"info","timestamp":"2025-10-17 09:39:19.879"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:39:19.887"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:39:19.888"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:39:19.889' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:39:19.890"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:39:19.890"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:40:19","level":"info","timestamp":"2025-10-17 09:40:19.022"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:40:19.042"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:40:19.042"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:40:19.044' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:40:19.046"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:40:19.046"}
{"caller":"common/getGlobalConfigLogic.go:63","content":"[GORM] SQL Executed","duration":"4.6ms","level":"info","rows":8,"span":"23bd7b723e08cddd","sql":"SELECT * FROM `auth_method`","timestamp":"2025-10-17 09:41:16.399","trace":"a0d2b8d305804b3795020e8e52d693d8"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"6.011917ms","ip":"::1","level":"info","query":"","request":"GET localhost:8080/v1/common/site/config","span":"23bd7b723e08cddd","status":200,"timestamp":"2025-10-17 09:41:16.399","trace":"a0d2b8d305804b3795020e8e52d693d8","user-agent":"Go-http-client/1.1"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"1.458µs","ip":"::1","level":"info","query":"","request":"POST localhost:8080/v1/auth/v1/auth/login/device","request_body":"{\"identifier\":\"device-001\"}","response_body":"","span":"1c950034b1268b62","status":404,"timestamp":"2025-10-17 09:41:16.400","trace":"152890c268ed39bed7aa0341587345a5","user-agent":"TestAgent/1.0"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:41:19","level":"info","timestamp":"2025-10-17 09:41:19.167"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:41:19.171"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:41:19.171"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:41:19.173' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:41:19.175"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:41:19.175"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:42:19","level":"info","timestamp":"2025-10-17 09:42:19.320"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:42:19.328"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:42:19.328"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:42:19.331' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:42:19.334"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:42:19.334"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:43:19","level":"info","timestamp":"2025-10-17 09:43:19.473"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:43:19.486"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:43:19.486"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:43:19.488' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:43:19.490"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:43:19.490"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:44:19","level":"info","timestamp":"2025-10-17 09:44:19.625"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:44:19.631"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:44:19.631"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:44:19.637' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:44:19.641"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:44:19.642"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:45:19","level":"info","timestamp":"2025-10-17 09:45:19.774"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:45:19.780"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:45:19.780"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:45:19.78' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:45:19.782"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:45:19.782"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:46:19","level":"info","timestamp":"2025-10-17 09:46:19.921"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:46:19.936"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:46:19.936"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:46:19.937' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:46:19.938"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:46:19.938"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:47:19","level":"info","timestamp":"2025-10-17 09:47:19.081"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:47:19.083"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:47:19.083"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:47:19.084' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:47:19.085"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:47:19.085"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:48:19","level":"info","timestamp":"2025-10-17 09:48:19.266"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:48:19.275"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:48:19.275"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:48:19.277' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:48:19.279"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:48:19.279"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:49:19","level":"info","timestamp":"2025-10-17 09:49:19.467"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:49:19.482"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:49:19.482"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:49:19.484' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:49:19.486"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:49:19.486"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:50:19","level":"info","timestamp":"2025-10-17 09:50:19.667"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:50:19.670"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:50:19.670"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:50:19.672' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:50:19.674"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:50:19.674"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"105.25µs","error":"UserAgent is a required field","ip":"::1","level":"info","query":"","request":"POST localhost:8080/v1/auth/login/device","request_body":"{\"identifier\":\"device-001\"}","response_body":"{\"code\":400,\"msg\":\"UserAgent is a required field\"}","span":"5b74d72a7c93dec9","status":200,"timestamp":"2025-10-17 09:51:17.738","trace":"a07177cb7dbc846fe572075764154cef","user-agent":"TestAgent/1.0"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:51:19","level":"info","timestamp":"2025-10-17 09:51:19.857"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"8.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:51:19.867"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:51:19.867"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:51:19.869' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:51:19.872"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:51:19.872"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:52:20","level":"info","timestamp":"2025-10-17 09:52:20.005"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:52:20.022"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:52:20.022"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:52:20.024' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:52:20.027"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:52:20.027"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:53:19","level":"info","timestamp":"2025-10-17 09:53:19.151"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:53:19.155"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:53:19.155"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:53:19.157' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:53:19.159"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:53:19.159"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:54:19","level":"info","timestamp":"2025-10-17 09:54:19.296"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:54:19.306"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:54:19.306"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:54:19.308' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:54:19.311"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:54:19.311"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:55:19","level":"info","timestamp":"2025-10-17 09:55:19.434"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:55:19.449"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:55:19.449"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:55:19.451' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:55:19.453"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:55:19.453"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:56:19","level":"info","timestamp":"2025-10-17 09:56:19.581"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:56:19.585"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:56:19.585"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:56:19.588' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:56:19.590"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:56:19.590"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:57:19","level":"info","timestamp":"2025-10-17 09:57:19.780"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"10.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:57:19.792"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:57:19.793"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:57:19.794' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:57:19.798"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:57:19.798"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:58:19","level":"info","timestamp":"2025-10-17 09:58:19.983"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:58:19.998"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:58:19.999"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:58:20.001' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:58:20.003"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:58:20.003"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 09:59:19","level":"info","timestamp":"2025-10-17 09:59:19.167"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 09:59:19.171"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:59:19.171"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 00:59:19.173' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 09:59:19.176"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 09:59:19.176"}
{"caller":"common/getGlobalConfigLogic.go:63","content":"[GORM] SQL Executed","duration":"26.3ms","level":"info","rows":8,"span":"f6ae781646a62766","sql":"SELECT * FROM `auth_method`","timestamp":"2025-10-17 09:59:55.005","trace":"d850ac206b9f71411ad2290fed1b909b"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"29.533458ms","ip":"::1","level":"info","query":"","request":"GET localhost:8080/v1/common/site/config","span":"f6ae781646a62766","status":200,"timestamp":"2025-10-17 09:59:55.006","trace":"d850ac206b9f71411ad2290fed1b909b","user-agent":"Go-http-client/1.1"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"1.833µs","ip":"::1","level":"info","query":"","request":"POST localhost:8080/v1/auth/v1/auth/login/device","request_body":"{\"identifier\":\"device-001\",\"user_agent\":\"TestAgent/1.0\"}","response_body":"","span":"440b193d1228926f","status":404,"timestamp":"2025-10-17 09:59:55.007","trace":"76718a7641d7c60bc470a2d545af0954","user-agent":"TestAgent/1.0"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"134.708µs","ip":"::1","level":"info","query":"","request":"POST localhost:8080/v1/auth/login/device","request_body":"{\"identifier\":\"device-001\",\"user_agent\":\"TestAgent/1.0\"}","response_body":"{\"code\":500,\"msg\":\"Device login is disabled\"}","span":"af587e583111e034","status":200,"timestamp":"2025-10-17 10:00:10.476","trace":"17202798a9b492c1305ffa9b20b98cf0","user-agent":"curl/8.7.1"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:00:19","level":"info","timestamp":"2025-10-17 10:00:19.327"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:00:19.330"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:00:19.330"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:00:19.331' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:00:19.332"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:00:19.332"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:01:19","level":"info","timestamp":"2025-10-17 10:01:19.466"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:01:19.478"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:01:19.478"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:01:19.479' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:01:19.480"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:01:19.480"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:02:19","level":"info","timestamp":"2025-10-17 10:02:19.612"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:02:19.615"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:02:19.616"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:02:19.617' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:02:19.619"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:02:19.619"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:03:19","level":"info","timestamp":"2025-10-17 10:03:19.763"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:03:19.766"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:03:19.766"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:03:19.767' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:03:19.770"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:03:19.770"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:04:19","level":"info","timestamp":"2025-10-17 10:04:19.901"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:04:19.911"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:04:19.911"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:04:19.912' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:04:19.913"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:04:19.913"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:05:19","level":"info","timestamp":"2025-10-17 10:05:19.034"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:05:19.038"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:05:19.038"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:05:19.04' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:05:19.044"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:05:19.044"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:06:19","level":"info","timestamp":"2025-10-17 10:06:19.187"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:06:19.193"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:06:19.194"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:06:19.195' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:06:19.198"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:06:19.198"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:07:19","level":"info","timestamp":"2025-10-17 10:07:19.329"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:07:19.339"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:07:19.340"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:07:19.341' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:07:19.342"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:07:19.342"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:08:19","level":"info","timestamp":"2025-10-17 10:08:19.474"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:08:19.478"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:08:19.479"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:08:19.481' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:08:19.483"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:08:19.483"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:09:19","level":"info","timestamp":"2025-10-17 10:09:19.632"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:09:19.638"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:09:19.638"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:09:19.639' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:09:19.641"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:09:19.641"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:10:19","level":"info","timestamp":"2025-10-17 10:10:19.788"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:10:19.792"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:10:19.792"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:10:19.793' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:10:19.795"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:10:19.795"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:11:19","level":"info","timestamp":"2025-10-17 10:11:19.930"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:11:19.934"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:11:19.934"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:11:19.936' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:11:19.939"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:11:19.939"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:12:19","level":"info","timestamp":"2025-10-17 10:12:19.066"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:12:19.075"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:12:19.075"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:12:19.077' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:12:19.080"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:12:19.080"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:13:19","level":"info","timestamp":"2025-10-17 10:13:19.233"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:13:19.242"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:13:19.242"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:13:19.243' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:13:19.246"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:13:19.246"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:14:19","level":"info","timestamp":"2025-10-17 10:14:19.405"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:14:19.409"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:14:19.409"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:14:19.411' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:14:19.414"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:14:19.414"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:15:19","level":"info","timestamp":"2025-10-17 10:15:19.573"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:15:19.579"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:15:19.579"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:15:19.581' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:15:19.582"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:15:19.583"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:16:19","level":"info","timestamp":"2025-10-17 10:16:19.745"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:16:19.752"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:16:19.752"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:16:19.755' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:16:19.758"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:16:19.759"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:17:19","level":"info","timestamp":"2025-10-17 10:17:19.918"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:17:19.919"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:17:19.919"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:17:19.919' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:17:19.920"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:17:19.920"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:18:19","level":"info","timestamp":"2025-10-17 10:18:19.056"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:18:19.060"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:18:19.060"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:18:19.061' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:18:19.062"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:18:19.062"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:19:19","level":"info","timestamp":"2025-10-17 10:19:19.202"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:19:19.215"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:19:19.216"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:19:19.218' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:19:19.223"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:19:19.223"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:20:19","level":"info","timestamp":"2025-10-17 10:20:19.349"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:20:19.353"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:20:19.353"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:20:19.355' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:20:19.358"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:20:19.358"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:21:19","level":"info","timestamp":"2025-10-17 10:21:19.489"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:21:19.495"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:21:19.495"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:21:19.496' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:21:19.497"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:21:19.498"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:22:19","level":"info","timestamp":"2025-10-17 10:22:19.633"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:22:19.637"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:22:19.637"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:22:19.638' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:22:19.639"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:22:19.639"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:23:19","level":"info","timestamp":"2025-10-17 10:23:19.797"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:23:19.801"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:23:19.801"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:23:19.804' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:23:19.806"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:23:19.806"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:24:19","level":"info","timestamp":"2025-10-17 10:24:19.972"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:24:19.979"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:24:19.979"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:24:19.981' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:24:19.983"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:24:19.983"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:25:19","level":"info","timestamp":"2025-10-17 10:25:19.165"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:25:19.179"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:25:19.179"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:25:19.181' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:25:19.184"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:25:19.184"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:26:19","level":"info","timestamp":"2025-10-17 10:26:19.352"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:26:19.356"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:26:19.356"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:26:19.358' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:26:19.360"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:26:19.360"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:27:19","level":"info","timestamp":"2025-10-17 10:27:19.528"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:27:19.538"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:27:19.538"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:27:19.54' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:27:19.543"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:27:19.543"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 10:44:27","level":"info","timestamp":"2025-10-17 10:44:27.766"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 10:44:27.771"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:44:27.771"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 01:44:27.772' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 10:44:27.773"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 10:44:27.773"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:01:10","level":"info","timestamp":"2025-10-17 19:01:10.775"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:01:10.783"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:01:10.783"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:01:10.786' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:01:10.789"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:01:10.789"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:02:10","level":"info","timestamp":"2025-10-17 19:02:10.910"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:02:10.917"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:02:10.917"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:02:10.919' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:02:10.921"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:02:10.922"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:03:10","level":"info","timestamp":"2025-10-17 19:03:10.041"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:03:10.047"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:03:10.047"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:03:10.048' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:03:10.050"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:03:10.050"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:04:10","level":"info","timestamp":"2025-10-17 19:04:10.185"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:04:10.190"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:04:10.190"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:04:10.191' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:04:10.192"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:04:10.192"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:05:10","level":"info","timestamp":"2025-10-17 19:05:10.305"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"10.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:05:10.321"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:05:10.321"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:05:10.323' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:05:10.326"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:05:10.326"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:06:10","level":"info","timestamp":"2025-10-17 19:06:10.454"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:06:10.461"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:06:10.461"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:06:10.463' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:06:10.465"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:06:10.466"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:07:10","level":"info","timestamp":"2025-10-17 19:07:10.604"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:07:10.619"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:07:10.619"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:07:10.621' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:07:10.624"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:07:10.624"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:08:10","level":"info","timestamp":"2025-10-17 19:08:10.750"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:08:10.755"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:08:10.755"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:08:10.758' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:08:10.762"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:08:10.762"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:09:10","level":"info","timestamp":"2025-10-17 19:09:10.903"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:09:10.907"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:09:10.907"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:09:10.91' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:09:10.913"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:09:10.913"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:10:10","level":"info","timestamp":"2025-10-17 19:10:10.056"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:10:10.075"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:10:10.075"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:10:10.082' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:10:10.083"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:10:10.083"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:11:10","level":"info","timestamp":"2025-10-17 19:11:10.255"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:11:10.260"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:11:10.260"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:11:10.262' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:11:10.265"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:11:10.265"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:12:10","level":"info","timestamp":"2025-10-17 19:12:10.438"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:12:10.446"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:12:10.446"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:12:10.448' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:12:10.450"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:12:10.450"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:13:10","level":"info","timestamp":"2025-10-17 19:13:10.633"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:13:10.648"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:13:10.648"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:13:10.649' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:13:10.651"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:13:10.652"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:14:10","level":"info","timestamp":"2025-10-17 19:14:10.831"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:14:10.835"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:14:10.835"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:14:10.838' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:14:10.841"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:14:10.841"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:15:10","level":"info","timestamp":"2025-10-17 19:15:10.996"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:15:11.005"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:15:11.005"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:15:11.007' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:15:11.010"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:15:11.010"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:16:10","level":"info","timestamp":"2025-10-17 19:16:10.137"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:16:10.154"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:16:10.154"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:16:10.156' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:16:10.159"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:16:10.159"}
{"caller":"common/getGlobalConfigLogic.go:63","content":"[GORM] SQL Executed","duration":"10.1ms","level":"info","rows":8,"span":"45d6f5732ebdebfb","sql":"SELECT * FROM `auth_method`","timestamp":"2025-10-17 19:16:18.696","trace":"5819489c3278b121ef85e2e69170978f"}
{"caller":"middleware/loggerMiddleware.go:92","content":"HTTP Request","duration":"13.2645ms","ip":"::1","level":"info","query":"","request":"GET localhost:8080/v1/common/site/config","span":"45d6f5732ebdebfb","status":200,"timestamp":"2025-10-17 19:16:18.696","trace":"5819489c3278b121ef85e2e69170978f","user-agent":"Go-http-client/1.1"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:17:10","level":"info","timestamp":"2025-10-17 19:17:10.280"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:17:10.288"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:17:10.288"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:17:10.296' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:17:10.298"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:17:10.298"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:18:10","level":"info","timestamp":"2025-10-17 19:18:10.409"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:18:10.416"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:18:10.416"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:18:10.418' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:18:10.420"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:18:10.420"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:19:10","level":"info","timestamp":"2025-10-17 19:19:10.467"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:19:10.482"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:19:10.482"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:19:10.483' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:19:10.485"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:19:10.485"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:20:10","level":"info","timestamp":"2025-10-17 19:20:10.627"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:20:10.628"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:20:10.628"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:20:10.629' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:20:10.630"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:20:10.630"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:21:10","level":"info","timestamp":"2025-10-17 19:21:10.773"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:21:10.781"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:21:10.781"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:21:10.782' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:21:10.784"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:21:10.784"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:22:10","level":"info","timestamp":"2025-10-17 19:22:10.919"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:22:10.924"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:22:10.924"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:22:10.925' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:22:10.926"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:22:10.926"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:23:10","level":"info","timestamp":"2025-10-17 19:23:10.042"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:23:10.044"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:23:10.044"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:23:10.046' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:23:10.047"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:23:10.047"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:24:10","level":"info","timestamp":"2025-10-17 19:24:10.191"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"9.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:24:10.202"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:24:10.202"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:24:10.203' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:24:10.204"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:24:10.205"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:25:10","level":"info","timestamp":"2025-10-17 19:25:10.318"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:25:10.325"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:25:10.325"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:25:10.327' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:25:10.329"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:25:10.329"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:26:10","level":"info","timestamp":"2025-10-17 19:26:10.457"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:26:10.459"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:26:10.459"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:26:10.461' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:26:10.462"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:26:10.462"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:27:10","level":"info","timestamp":"2025-10-17 19:27:10.570"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:27:10.575"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:27:10.575"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:27:10.577' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:27:10.579"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:27:10.579"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:28:10","level":"info","timestamp":"2025-10-17 19:28:10.713"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:28:10.719"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:28:10.719"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:28:10.72' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:28:10.721"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:28:10.721"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:29:10","level":"info","timestamp":"2025-10-17 19:29:10.854"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:29:10.857"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:29:10.857"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:29:10.858' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:29:10.860"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:29:10.860"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:30:10","level":"info","timestamp":"2025-10-17 19:30:10.995"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:30:11.000"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:30:11.000"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:30:11.002' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:30:11.005"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:30:11.005"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:31:10","level":"info","timestamp":"2025-10-17 19:31:10.141"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:31:10.144"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:31:10.144"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:31:10.145' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:31:10.147"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:31:10.147"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:32:10","level":"info","timestamp":"2025-10-17 19:32:10.259"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:32:10.265"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:32:10.265"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:32:10.267' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:32:10.270"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:32:10.270"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:33:10","level":"info","timestamp":"2025-10-17 19:33:10.409"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:33:10.417"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:33:10.417"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:33:10.421' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:33:10.424"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:33:10.424"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:34:10","level":"info","timestamp":"2025-10-17 19:34:10.648"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:34:10.653"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:34:10.653"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:34:10.654' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:34:10.655"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:34:10.655"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:35:10","level":"info","timestamp":"2025-10-17 19:35:10.787"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:35:10.789"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:35:10.789"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:35:10.79' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:35:10.791"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:35:10.791"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:36:10","level":"info","timestamp":"2025-10-17 19:36:10.952"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:36:10.957"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:36:10.957"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:36:10.958' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:36:10.959"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:36:10.959"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:37:10","level":"info","timestamp":"2025-10-17 19:37:10.113"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:37:10.123"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:37:10.124"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:37:10.126' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:37:10.130"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:37:10.130"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:38:10","level":"info","timestamp":"2025-10-17 19:38:10.281"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:38:10.286"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:38:10.286"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:38:10.288' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:38:10.291"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:38:10.291"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:39:10","level":"info","timestamp":"2025-10-17 19:39:10.444"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:39:10.449"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:39:10.449"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:39:10.45' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:39:10.451"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:39:10.451"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:40:10","level":"info","timestamp":"2025-10-17 19:40:10.624"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:40:10.635"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:40:10.635"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:40:10.638' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:40:10.640"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:40:10.640"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:41:10","level":"info","timestamp":"2025-10-17 19:41:10.833"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:41:10.839"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:41:10.839"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:41:10.841' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:41:10.846"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:41:10.846"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:42:10","level":"info","timestamp":"2025-10-17 19:42:10.050"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:42:10.057"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:42:10.057"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:42:10.06' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:42:10.063"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:42:10.063"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:43:10","level":"info","timestamp":"2025-10-17 19:43:10.271"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:43:10.281"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:43:10.281"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:43:10.283' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:43:10.286"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:43:10.286"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:44:10","level":"info","timestamp":"2025-10-17 19:44:10.479"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:44:10.483"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:44:10.483"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:44:10.486' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:44:10.488"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:44:10.488"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:45:10","level":"info","timestamp":"2025-10-17 19:45:10.695"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:45:10.705"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:45:10.705"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:45:10.707' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:45:10.711"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:45:10.711"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:46:10","level":"info","timestamp":"2025-10-17 19:46:10.906"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"8.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:46:10.916"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:46:10.916"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:46:10.919' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:46:10.921"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:46:10.921"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:47:10","level":"info","timestamp":"2025-10-17 19:47:10.128"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:47:10.132"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:47:10.132"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:47:10.135' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:47:10.138"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:47:10.138"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:48:10","level":"info","timestamp":"2025-10-17 19:48:10.340"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"9.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:48:10.352"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:48:10.352"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:48:10.355' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:48:10.358"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:48:10.358"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:49:10","level":"info","timestamp":"2025-10-17 19:49:10.547"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:49:10.553"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:49:10.553"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:49:10.554' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:49:10.555"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:49:10.555"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:50:10","level":"info","timestamp":"2025-10-17 19:50:10.726"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:50:10.731"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:50:10.731"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:50:10.733' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:50:10.737"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:50:10.737"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:51:10","level":"info","timestamp":"2025-10-17 19:51:10.918"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:51:10.926"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:51:10.926"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:51:10.929' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:51:10.932"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:51:10.932"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:52:10","level":"info","timestamp":"2025-10-17 19:52:10.118"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:52:10.132"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:52:10.132"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"9.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:52:10.134' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:52:10.143"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:52:10.143"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:53:10","level":"info","timestamp":"2025-10-17 19:53:10.333"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:53:10.338"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:53:10.338"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:53:10.341' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:53:10.345"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:53:10.345"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:54:10","level":"info","timestamp":"2025-10-17 19:54:10.526"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:54:10.536"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:54:10.537"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:54:10.539' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:54:10.542"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:54:10.542"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-17 19:59:38","level":"info","timestamp":"2025-10-17 19:59:38.965"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-17 19:59:38.981"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:59:38.981"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 10:59:38.983' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-17 19:59:38.989"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-17 19:59:38.989"}
-235
View File
@@ -1,235 +0,0 @@
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:48:13","level":"info","timestamp":"2025-10-18 03:48:13.806"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:48:13.819"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:48:13.819"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:48:13.821' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:48:13.826"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:48:13.826"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:49:13","level":"info","timestamp":"2025-10-18 03:49:13.983"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:49:13.991"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:49:13.991"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:49:13.994' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:49:13.997"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:49:13.997"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:50:13","level":"info","timestamp":"2025-10-18 03:50:13.159"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:50:13.163"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:50:13.163"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:50:13.165' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:50:13.168"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:50:13.169"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:51:13","level":"info","timestamp":"2025-10-18 03:51:13.323"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:51:13.333"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:51:13.333"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:51:13.334' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:51:13.336"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:51:13.336"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:52:13","level":"info","timestamp":"2025-10-18 03:52:13.464"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:52:13.472"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:52:13.473"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:52:13.473' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:52:13.474"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:52:13.474"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:53:13","level":"info","timestamp":"2025-10-18 03:53:13.665"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:53:13.668"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:53:13.668"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:53:13.669' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:53:13.670"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:53:13.670"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:54:13","level":"info","timestamp":"2025-10-18 03:54:13.815"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:54:13.840"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:54:13.840"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"0.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:54:13.843' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:54:13.843"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:54:13.843"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:55:13","level":"info","timestamp":"2025-10-18 03:55:13.978"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:55:13.981"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:55:13.981"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:55:13.983' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:55:13.985"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:55:13.985"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:56:13","level":"info","timestamp":"2025-10-18 03:56:13.142"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:56:13.147"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:56:13.147"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:56:13.15' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:56:13.153"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:56:13.153"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:57:13","level":"info","timestamp":"2025-10-18 03:57:13.306"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"6.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:57:13.334"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:57:13.334"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:57:13.336' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:57:13.337"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:57:13.337"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:58:13","level":"info","timestamp":"2025-10-18 03:58:13.484"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:58:13.489"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:58:13.489"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:58:13.49' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:58:13.492"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:58:13.492"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 03:59:13","level":"info","timestamp":"2025-10-18 03:59:13.702"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 03:59:13.707"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:59:13.707"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 18:59:13.711' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 03:59:13.714"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 03:59:13.714"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:00:13","level":"info","timestamp":"2025-10-18 04:00:13.936"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:00:13.965"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:00:13.965"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:00:13.966' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:00:13.967"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:00:13.967"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:01:13","level":"info","timestamp":"2025-10-18 04:01:13.145"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:01:13.149"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:01:13.149"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:01:13.152' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:01:13.153"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:01:13.153"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:02:13","level":"info","timestamp":"2025-10-18 04:02:13.353"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:02:13.357"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:02:13.357"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:02:13.361' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:02:13.363"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:02:13.363"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:03:13","level":"info","timestamp":"2025-10-18 04:03:13.563"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:03:13.570"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:03:13.570"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:03:13.574' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:03:13.577"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:03:13.577"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:04:13","level":"info","timestamp":"2025-10-18 04:04:13.773"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:04:13.778"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:04:13.778"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:04:13.781' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:04:13.784"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:04:13.784"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:05:13","level":"info","timestamp":"2025-10-18 04:05:13.943"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:05:13.948"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:05:13.948"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:05:13.951' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:05:13.955"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:05:13.955"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:06:13","level":"info","timestamp":"2025-10-18 04:06:13.119"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:06:13.129"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:06:13.129"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:06:13.132' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:06:13.136"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:06:13.136"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:07:13","level":"info","timestamp":"2025-10-18 04:07:13.285"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:07:13.287"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:07:13.287"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:07:13.288' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:07:13.289"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:07:13.289"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:08:13","level":"info","timestamp":"2025-10-18 04:08:13.467"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:08:13.472"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:08:13.472"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:08:13.475' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:08:13.478"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:08:13.478"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:09:13","level":"info","timestamp":"2025-10-18 04:09:13.669"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:09:13.681"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:09:13.681"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:09:13.685' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:09:13.689"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:09:13.689"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:10:13","level":"info","timestamp":"2025-10-18 04:10:13.879"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:10:13.882"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:10:13.882"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:10:13.885' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:10:13.889"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:10:13.889"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:11:13","level":"info","timestamp":"2025-10-18 04:11:13.083"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:11:13.088"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:11:13.088"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:11:13.091' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:11:13.094"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:11:13.094"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:12:13","level":"info","timestamp":"2025-10-18 04:12:13.295"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"11.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:12:13.327"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:12:13.328"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:12:13.329' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:12:13.330"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:12:13.330"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:13:13","level":"info","timestamp":"2025-10-18 04:13:13.507"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:13:13.513"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:13:13.513"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:13:13.516' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:13:13.519"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:13:13.519"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:14:13","level":"info","timestamp":"2025-10-18 04:14:13.734"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:14:13.740"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:14:13.740"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:14:13.743' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:14:13.747"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:14:13.747"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:15:13","level":"info","timestamp":"2025-10-18 04:15:13.947"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:15:13.973"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:15:13.973"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:15:13.974' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:15:13.976"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:15:13.976"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:16:13","level":"info","timestamp":"2025-10-18 04:16:13.159"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:16:13.163"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:16:13.163"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:16:13.165' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:16:13.169"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:16:13.169"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:17:13","level":"info","timestamp":"2025-10-18 04:17:13.384"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:17:13.389"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:17:13.389"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:17:13.392' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:17:13.395"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:17:13.395"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:18:13","level":"info","timestamp":"2025-10-18 04:18:13.604"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:18:13.633"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:18:13.634"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:18:13.635' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:18:13.637"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:18:13.637"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:19:13","level":"info","timestamp":"2025-10-18 04:19:13.808"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:19:13.812"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:19:13.812"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:19:13.816' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:19:13.819"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:19:13.819"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:20:14","level":"info","timestamp":"2025-10-18 04:20:14.010"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:20:14.015"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:20:14.015"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:20:14.019' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:20:14.022"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:20:14.022"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:21:13","level":"info","timestamp":"2025-10-18 04:21:13.212"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"5.1ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:21:13.241"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:21:13.241"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:21:13.243' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:21:13.244"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:21:13.244"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:22:13","level":"info","timestamp":"2025-10-18 04:22:13.425"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:22:13.429"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:22:13.430"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.4ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:22:13.432' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:22:13.435"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:22:13.435"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:23:13","level":"info","timestamp":"2025-10-18 04:23:13.651"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:23:13.657"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:23:13.657"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:23:13.66' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:23:13.664"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:23:13.664"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 04:24:13","level":"info","timestamp":"2025-10-18 04:24:13.852"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"7.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 04:24:13.879"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:24:13.879"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 19:24:13.881' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 04:24:13.884"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 04:24:13.884"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 06:10:31","level":"info","timestamp":"2025-10-18 06:10:31.049"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 06:10:31.056"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 06:10:31.056"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 21:10:31.058' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 06:10:31.061"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 06:10:31.061"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 06:11:30","level":"info","timestamp":"2025-10-18 06:11:30.219"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 06:11:30.225"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 06:11:30.225"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 21:11:30.227' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 06:11:30.230"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 06:11:30.230"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 06:17:12","level":"info","timestamp":"2025-10-18 06:17:12.393"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 06:17:12.399"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 06:17:12.399"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-18 21:17:12.4' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 06:17:12.401"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 06:17:12.401"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 18:00:51","level":"info","timestamp":"2025-10-18 18:00:51.432"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 18:00:51.438"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 18:00:51.438"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-19 09:00:51.439' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 18:00:51.441"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 18:00:51.441"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 18:01:51","level":"info","timestamp":"2025-10-18 18:01:51.599"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 18:01:51.603"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 18:01:51.603"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.8ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-19 09:01:51.605' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 18:01:51.606"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 18:01:51.606"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 18:07:27","level":"info","timestamp":"2025-10-18 18:07:27.842"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 18:07:27.848"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 18:07:27.848"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.5ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-19 09:07:27.851' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 18:07:27.853"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 18:07:27.853"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 21:23:51","level":"info","timestamp":"2025-10-18 21:23:51.591"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 21:23:51.596"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 21:23:51.596"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.0ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-19 12:23:51.608' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 21:23:51.609"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 21:23:51.609"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 23:03:17","level":"info","timestamp":"2025-10-18 23:03:17.708"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"4.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 23:03:17.716"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 23:03:17.716"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.2ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-19 14:03:17.718' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 23:03:17.720"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 23:03:17.720"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 23:04:16","level":"info","timestamp":"2025-10-18 23:04:16.864"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"3.3ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 23:04:16.871"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 23:04:16.871"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"2.7ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-19 14:04:16.873' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 23:04:16.876"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 23:04:16.876"}
{"caller":"subscription/checkSubscriptionLogic.go:29","content":"[CheckSubscription] Start check subscription: 2025-10-18 23:20:22","level":"info","timestamp":"2025-10-18 23:20:22.736"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.6ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ","timestamp":"2025-10-18 23:20:22.738"}
{"caller":"subscription/checkSubscriptionLogic.go:67","content":"[Check Subscription Traffic] No subscribe need to update","level":"info","timestamp":"2025-10-18 23:20:22.738"}
{"caller":"user/default.go:156","content":"[GORM] SQL Executed","duration":"1.9ms","level":"info","rows":0,"sql":"SELECT * FROM `user_subscribe` WHERE `status` IN (0, 1) AND `expire_time` < '2025-10-19 14:20:22.74' AND `expire_time` != '1970-01-01 08:00:00' and `finished_at` IS NULL","timestamp":"2025-10-18 23:20:22.742"}
{"caller":"subscription/checkSubscriptionLogic.go:109","content":"[Check Subscription Expire] No subscribe need to update","level":"info","timestamp":"2025-10-18 23:20:22.742"}
-1
View File
@@ -8,5 +8,4 @@ const (
CtxKeyRequestHost CtxKey = "requestHost"
CtxKeyPlatform CtxKey = "platform"
CtxKeyPayment CtxKey = "payment"
LoginType CtxKey = "loginType"
)
+1 -1
View File
@@ -3,5 +3,5 @@ package tool
import "testing"
func TestEncodePassWord(t *testing.T) {
t.Logf("EncodePassWord: %v", EncodePassWord("password"))
t.Logf("EncodePassWord: %v", EncodePassWord(""))
}
-1
View File
@@ -47,7 +47,6 @@ const (
ErrorTokenExpire uint32 = 40004
InvalidAccess uint32 = 40005
InvalidCiphertext uint32 = 40006
SecretIsEmpty uint32 = 40007
)
//coupon error
-1
View File
@@ -14,7 +14,6 @@ func init() {
ErrorTokenEmpty: "User token is empty",
ErrorTokenInvalid: "User token is invalid",
ErrorTokenExpire: "User token is expired",
SecretIsEmpty: "Secret is empty",
InvalidAccess: "Invalid access",
InvalidCiphertext: "Invalid ciphertext",
// Database error
BIN
View File
Binary file not shown.
View File
+31 -98
View File
@@ -7,9 +7,11 @@ import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"github.com/perfect-panel/server/internal/model/log"
"github.com/perfect-panel/server/internal/model/node"
"github.com/perfect-panel/server/pkg/constant"
"github.com/perfect-panel/server/pkg/logger"
@@ -179,8 +181,8 @@ func (l *ActivateOrderLogic) NewPurchase(ctx context.Context, orderInfo *order.O
return err
}
// Handle referral reward in separate goroutine to avoid blocking
go l.handleReferralReward(context.Background(), userInfo, orderInfo)
// Handle commission in separate goroutine to avoid blocking
go l.handleCommission(context.Background(), userInfo, orderInfo)
// Clear cache
l.clearServerCache(ctx, sub)
@@ -192,12 +194,12 @@ func (l *ActivateOrderLogic) NewPurchase(ctx context.Context, orderInfo *order.O
return nil
}
// getUserOrCreate retrieves an existing user or creates a new user based on order details
// getUserOrCreate retrieves an existing user or creates a new guest user based on order details
func (l *ActivateOrderLogic) getUserOrCreate(ctx context.Context, orderInfo *order.Order) (*user.User, error) {
if orderInfo.UserId != 0 {
return l.getExistingUser(ctx, orderInfo.UserId)
}
return l.createUserFromTempOrder(ctx, orderInfo)
return l.createGuestUser(ctx, orderInfo)
}
// getExistingUser retrieves user information by user ID
@@ -213,9 +215,9 @@ func (l *ActivateOrderLogic) getExistingUser(ctx context.Context, userId int64)
return userInfo, nil
}
// createUserFromTempOrder creates a new user account using temporary order information
// stored in Redis cache. All users created this way are formal users, not guests.
func (l *ActivateOrderLogic) createUserFromTempOrder(ctx context.Context, orderInfo *order.Order) (*user.User, error) {
// createGuestUser creates a new user account for guest orders using temporary order information
// stored in Redis cache
func (l *ActivateOrderLogic) createGuestUser(ctx context.Context, orderInfo *order.Order) (*user.User, error) {
tempOrder, err := l.getTempOrderInfo(ctx, orderInfo.OrderNo)
if err != nil {
return nil, err
@@ -253,7 +255,7 @@ func (l *ActivateOrderLogic) createUserFromTempOrder(ctx context.Context, orderI
// Handle referrer relationship
l.handleReferrer(ctx, userInfo, tempOrder.InviteCode)
logger.WithContext(ctx).Info("Create user success",
logger.WithContext(ctx).Info("Create guest user success",
logger.Field("user_id", userInfo.Id),
logger.Field("identifier", tempOrder.Identifier),
logger.Field("auth_type", tempOrder.AuthType),
@@ -349,12 +351,10 @@ func (l *ActivateOrderLogic) createUserSubscription(ctx context.Context, orderIn
return userSub, nil
}
// handleReferralReward processes referral rewards for the referrer if applicable.
// handleCommission processes referral commission for the referrer if applicable.
// This runs asynchronously to avoid blocking the main order processing flow.
// If referral percentage > 0: commission reward
// If referral percentage = 0: gift days to both parties
func (l *ActivateOrderLogic) handleReferralReward(ctx context.Context, userInfo *user.User, orderInfo *order.Order) {
if !l.shouldProcessReferralReward(userInfo, orderInfo.IsNew) {
func (l *ActivateOrderLogic) handleCommission(ctx context.Context, userInfo *user.User, orderInfo *order.Order) {
if !l.shouldProcessCommission(userInfo, orderInfo.IsNew) {
return
}
@@ -374,25 +374,13 @@ func (l *ActivateOrderLogic) handleReferralReward(ctx context.Context, userInfo
referralPercentage = uint8(l.svc.Config.Invite.ReferralPercentage)
}
// Check if this is commission reward or gift days reward
if referralPercentage > 0 {
// Commission reward mode
l.processCommissionReward(ctx, referer, orderInfo, referralPercentage)
} else {
// Gift days reward mode
l.processGiftDaysReward(ctx, referer, userInfo, orderInfo)
}
}
// processCommissionReward handles commission-based rewards
func (l *ActivateOrderLogic) processCommissionReward(ctx context.Context, referer *user.User, orderInfo *order.Order, percentage uint8) {
// Order commission calculation (Order Amount - Order Fee) * Referral Percentage
amount := l.calculateCommission(orderInfo.Amount-orderInfo.FeeAmount, percentage)
amount := l.calculateCommission(orderInfo.Amount-orderInfo.FeeAmount, referralPercentage)
// Use transaction for commission updates
err := l.svc.DB.Transaction(func(tx *gorm.DB) error {
err = l.svc.DB.Transaction(func(tx *gorm.DB) error {
referer.Commission += amount
if err := l.svc.UserModel.Update(ctx, referer, tx); err != nil {
if err = l.svc.UserModel.Update(ctx, referer, tx); err != nil {
return err
}
@@ -434,73 +422,9 @@ func (l *ActivateOrderLogic) processCommissionReward(ctx context.Context, refere
}
}
// processGiftDaysReward handles gift days rewards for both parties
func (l *ActivateOrderLogic) processGiftDaysReward(ctx context.Context, referer *user.User, referee *user.User, orderInfo *order.Order) {
giftDays := l.svc.Config.Invite.GiftDays
if giftDays <= 0 {
giftDays = 3 // Default to 3 days
}
// Get the subscription info to determine the unit time
sub, err := l.getSubscribeInfo(ctx, orderInfo.SubscribeId)
if err != nil {
logger.WithContext(ctx).Error("Get subscribe info failed for gift days",
logger.Field("error", err.Error()),
logger.Field("subscribe_id", orderInfo.SubscribeId),
)
return
}
// Grant gift days to both referer and referee
l.grantGiftDays(ctx, referer, giftDays, sub.UnitTime, "referer")
l.grantGiftDays(ctx, referee, giftDays, sub.UnitTime, "referee")
}
// grantGiftDays grants gift days to a user by extending their subscription
func (l *ActivateOrderLogic) grantGiftDays(ctx context.Context, user *user.User, days int64, unitTime string, role string) {
// Find user's active subscription
userSub, err := l.svc.UserModel.FindActiveSubscribe(ctx, user.Id)
if err != nil {
logger.WithContext(ctx).Error("Find user active subscription failed for gift days",
logger.Field("error", err.Error()),
logger.Field("user_id", user.Id),
logger.Field("role", role),
)
return
}
if userSub == nil {
logger.WithContext(ctx).Info("User has no active subscription for gift days",
logger.Field("user_id", user.Id),
logger.Field("role", role),
)
return
}
// Extend subscription by gift days
userSub.ExpireTime = tool.AddTime("day", days, userSub.ExpireTime)
err = l.svc.UserModel.UpdateSubscribe(ctx, userSub)
if err != nil {
logger.WithContext(ctx).Error("Update user subscription for gift days failed",
logger.Field("error", err.Error()),
logger.Field("user_id", user.Id),
logger.Field("role", role),
)
return
}
logger.WithContext(ctx).Info("Gift days granted successfully",
logger.Field("user_id", user.Id),
logger.Field("role", role),
logger.Field("days", days),
logger.Field("new_expire_time", userSub.ExpireTime),
)
}
// shouldProcessReferralReward determines if referral reward should be processed based on
// shouldProcessCommission determines if commission should be processed based on
// referrer existence, commission settings, and order type
func (l *ActivateOrderLogic) shouldProcessReferralReward(userInfo *user.User, isFirstPurchase bool) bool {
func (l *ActivateOrderLogic) shouldProcessCommission(userInfo *user.User, isFirstPurchase bool) bool {
if userInfo == nil || userInfo.RefererId == 0 {
return false
}
@@ -542,8 +466,17 @@ func (l *ActivateOrderLogic) calculateCommission(price int64, percentage uint8)
// clearServerCache clears user list cache for all servers associated with the subscription
func (l *ActivateOrderLogic) clearServerCache(ctx context.Context, sub *subscribe.Subscribe) {
if err := l.svc.SubscribeModel.ClearCache(ctx, sub.Id); err != nil {
logger.WithContext(ctx).Error("[Order Queue] Clear subscribe cache failed", logger.Field("error", err.Error()))
nodeIds := tool.StringToInt64Slice(sub.Nodes)
tags := strings.Split(sub.NodeTags, ",")
err := l.svc.NodeModel.ClearNodeCache(ctx, &node.FilterNodeParams{
Page: 1,
Size: 1000,
NodeId: nodeIds,
Tag: tags,
})
if err != nil {
logger.WithContext(ctx).Error("[Order Queue] Clear node cache failed", logger.Field("error", err.Error()))
}
}
@@ -582,8 +515,8 @@ func (l *ActivateOrderLogic) Renewal(ctx context.Context, orderInfo *order.Order
// Clear cache
l.clearServerCache(ctx, sub)
// Handle referral reward
go l.handleReferralReward(context.Background(), userInfo, orderInfo)
// Handle commission
go l.handleCommission(context.Background(), userInfo, orderInfo)
// Send notifications
l.sendNotifications(ctx, orderInfo, userInfo, sub, userSub, telegram.RenewalNotify)
@@ -3,8 +3,11 @@ package subscription
import (
"context"
"encoding/json"
"strings"
"time"
"github.com/perfect-panel/server/internal/model/node"
"github.com/perfect-panel/server/pkg/tool"
queue "github.com/perfect-panel/server/queue/types"
"github.com/perfect-panel/server/pkg/logger"
@@ -30,7 +33,7 @@ func (l *CheckSubscriptionLogic) ProcessTask(ctx context.Context, _ *asynq.Task)
// Check subscription traffic
err := l.svc.UserModel.Transaction(ctx, func(db *gorm.DB) error {
var list []*user.Subscribe
err := db.Model(&user.Subscribe{}).Where("upload + download >= traffic AND status IN (0, 1) AND traffic > 0 ").Find(&list).Error
err := db.Model(&user.Subscribe{}).Where("upload + download >= traffic AND status = 1 AND traffic > 0 ").Find(&list).Error
if err != nil {
logger.Errorw("[Check Subscription Traffic] Query subscribe failed", logger.Field("error", err.Error()))
return err
@@ -75,7 +78,7 @@ func (l *CheckSubscriptionLogic) ProcessTask(ctx context.Context, _ *asynq.Task)
// Check subscription expire
err = l.svc.UserModel.Transaction(ctx, func(db *gorm.DB) error {
var list []*user.Subscribe
err = db.Model(&user.Subscribe{}).Where("`status` IN (0, 1) AND `expire_time` < ? AND `expire_time` != ? and `finished_at` IS NULL", time.Now(), time.UnixMilli(0)).Find(&list).Error
err = db.Model(&user.Subscribe{}).Where("`status` = 1 AND `expire_time` < ? AND `expire_time` != ? and `finished_at` IS NULL", time.Now(), time.UnixMilli(0)).Find(&list).Error
if err != nil {
logger.Error("[Check Subscription] Find subscribe failed", logger.Field("error", err.Error()))
return err
@@ -204,8 +207,31 @@ func (l *CheckSubscriptionLogic) clearServerCache(ctx context.Context, userSubs
}
for sub, _ := range subs {
if err := l.svc.SubscribeModel.ClearCache(ctx, sub); err != nil {
logger.Errorw("[CheckSubscription] ClearCache failed", logger.Field("error", err.Error()), logger.Field("subscribe_id", sub))
info, err := l.svc.SubscribeModel.FindOne(ctx, sub)
if err != nil {
logger.Errorw("[CheckSubscription] FindOne subscribe failed", logger.Field("error", err.Error()), logger.Field("subscribe_id", sub))
continue
}
if info != nil && info.Id == sub {
var nodes []int64
if info.Nodes != "" {
nodes = tool.StringToInt64Slice(info.Nodes)
}
var tag []string
if info.NodeTags != "" {
tag = strings.Split(info.NodeTags, ",")
}
err = l.svc.NodeModel.ClearNodeCache(ctx, &node.FilterNodeParams{
Page: 1,
Size: 1000,
Tag: tag,
ServerId: nodes,
})
if err != nil {
logger.Errorw("[CheckSubscription] ClearNodeCache failed", logger.Field("error", err.Error()), logger.Field("subscribe_id", sub))
continue
}
}
}
}
+27 -5
View File
@@ -9,10 +9,12 @@ import (
"time"
"github.com/perfect-panel/server/internal/model/log"
"github.com/perfect-panel/server/internal/model/node"
"github.com/perfect-panel/server/internal/model/subscribe"
"github.com/perfect-panel/server/internal/model/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/tool"
"github.com/perfect-panel/server/queue/types"
"github.com/hibiken/asynq"
@@ -596,11 +598,31 @@ func (l *ResetTrafficLogic) clearCache(ctx context.Context, list []*user.Subscri
}
for sub, _ := range subs {
if err := l.svc.SubscribeModel.ClearCache(ctx, sub); err != nil {
logger.Errorw("[ResetTraffic] Failed to clear subscription cache",
logger.Field("subscribeId", sub),
logger.Field("error", err.Error()),
)
info, err := l.svc.SubscribeModel.FindOne(ctx, sub)
if err != nil {
logger.Errorw("[CheckSubscription] FindOne subscribe failed", logger.Field("error", err.Error()), logger.Field("subscribe_id", sub))
continue
}
if info != nil && info.Id == sub {
var nodes []int64
if info.Nodes != "" {
nodes = tool.StringToInt64Slice(info.Nodes)
}
var tag []string
if info.NodeTags != "" {
tag = strings.Split(info.NodeTags, ",")
}
err = l.svc.NodeModel.ClearNodeCache(ctx, &node.FilterNodeParams{
Page: 1,
Size: 1000,
Tag: tag,
ServerId: nodes,
})
if err != nil {
logger.Errorw("[CheckSubscription] ClearNodeCache failed", logger.Field("error", err.Error()), logger.Field("subscribe_id", sub))
continue
}
}
}
}
+2 -2
View File
@@ -113,8 +113,8 @@ PPanel 服务端是 PPanel 项目的后端组件,为代理服务提供强大
4. **从 Docker Hub 拉取**CI/CD 发布后):
```bash
docker pull ppanel/ppanel-server:latest
docker run --rm -p 8080:8080 ppanel/ppanel-server:latest
docker pull yourusername/ppanel-server:latest
docker run --rm -p 8080:8080 yourusername/ppanel-server:latest
```
## 📖 API 文档
-30
View File
@@ -1,30 +0,0 @@
#!/bin/bash
# build-and-push.sh
set -e
cd /Users/Apple/vpn/ppanel-server
# 固定版本号为latest
VERSION=v1.0
# 构建镜像
echo "Building image with version: $VERSION"
docker build -f Dockerfile --platform linux/amd64 --build-arg TARGETARCH=amd64 -t registry.kxsw.us/ppanel/ario-server:$VERSION .
docker tag registry.kxsw.us/ppanel/ario-server:$VERSION registry.kxsw.us/ppanel/ario-server:$VERSION
# 推送镜像
echo "Pushing image to registry.kxsw.us"
docker push registry.kxsw.us/ppanel/ario-server:$VERSION
docker push registry.kxsw.us/ppanel/ario-server:$VERSION
echo "Build and push completed successfully!"
# docker-compose exec certbot certbot certonly --webroot --webroot-path=/etc/letsencrypt -d api-dev.kxsw.us
docker run -d -p 3001:3000 \
-e NEXT_PUBLIC_DEFAULT_LANGUAGE=en-US \
-e NEXT_PUBLIC_SITE_URL=https://4d3vsw8.88xgaen.hifast.biz \
-e NEXT_PUBLIC_API_URL=https://api.hifast.biz \
-e NEXT_PUBLIC_DEFAULT_USER_EMAIL=admin@ppanel.dev \
-e NEXT_PUBLIC_DEFAULT_USER_PASSWORD=password \
--name ppanel-admin-web \
ppanel/ppanel-admin-web:latest
BIN
View File
Binary file not shown.