diff --git a/auto-bid-admin/src/components/bid/show-histories-modal.tsx b/auto-bid-admin/src/components/bid/show-histories-modal.tsx
index 3cddae8..1d89d1a 100644
--- a/auto-bid-admin/src/components/bid/show-histories-modal.tsx
+++ b/auto-bid-admin/src/components/bid/show-histories-modal.tsx
@@ -1,44 +1,60 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
-import { Modal, ModalProps, Table } from '@mantine/core';
-import { IBid } from '../../system/type';
-import { formatTime } from '../../utils';
+import { Modal, ModalProps, Table } from "@mantine/core";
+import { IBid } from "../../system/type";
+import { formatTime } from "../../utils";
+import _ from "lodash";
export interface IShowHistoriesModalModalProps extends ModalProps {
- data: IBid | null;
- onUpdated?: () => void;
+ data: IBid | null;
+ onUpdated?: () => void;
}
-export default function ShowHistoriesModal({ data, onUpdated, ...props }: IShowHistoriesModalModalProps) {
- const rows = data?.histories.map((element) => (
-
- {element.id}
- {element.price}
- {formatTime(new Date(element.created_at).toUTCString(), 'HH:mm:ss DD/MM/YYYY')}
-
- ));
+export default function ShowHistoriesModal({
+ data,
+ onUpdated,
+ ...props
+}: IShowHistoriesModalModalProps) {
+ const sortedHistories = _.orderBy(data?.histories || [], ["price"], ["desc"]);
- return (
- Histories} centered>
-
-
-
- ID
- Price
- Created at
-
-
-
- {data && data.histories.length <= 0 ? (
-
-
- None
-
-
- ) : (
- rows
- )}
-
-
-
- );
+ const rows = sortedHistories.map((element) => (
+
+ {element.id}
+ {element.price}
+
+ {formatTime(
+ new Date(element.created_at).toUTCString(),
+ "HH:mm:ss DD/MM/YYYY",
+ )}
+
+
+ ));
+ return (
+ Histories}
+ centered
+ >
+
+
+
+ ID
+ Price
+ Created at
+
+
+
+ {data && data.histories.length <= 0 ? (
+
+
+ None
+
+
+ ) : (
+ rows
+ )}
+
+
+
+ );
}
diff --git a/auto-bid-server/src/modules/bids/entities/send-message-histories.entity.ts b/auto-bid-server/src/modules/bids/entities/send-message-histories.entity.ts
index a1317d5..ec5889a 100644
--- a/auto-bid-server/src/modules/bids/entities/send-message-histories.entity.ts
+++ b/auto-bid-server/src/modules/bids/entities/send-message-histories.entity.ts
@@ -1,16 +1,14 @@
import {
Column,
Entity,
- JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
Unique,
} from 'typeorm';
-import { Timestamp } from './timestamp';
import { Bid } from './bid.entity';
+import { Timestamp } from './timestamp';
@Entity('send_message_histories')
-@Unique(['max_price', 'type', 'reserve_price', 'bid'])
export class SendMessageHistory extends Timestamp {
@PrimaryGeneratedColumn('increment')
id: number;
diff --git a/auto-bid-server/src/modules/bids/services/bid-histories.service.ts b/auto-bid-server/src/modules/bids/services/bid-histories.service.ts
index 438cce7..d89e2bc 100644
--- a/auto-bid-server/src/modules/bids/services/bid-histories.service.ts
+++ b/auto-bid-server/src/modules/bids/services/bid-histories.service.ts
@@ -100,8 +100,15 @@ export class BidHistoriesService {
});
// Nếu đây là lần đặt giá đầu tiên, cập nhật cờ `first_bid` thành false
+ // Nếu là web all bids thì không cần set về false
if (response.length === 1) {
- this.bidsService.bidsRepo.update(bid_id, { first_bid: false });
+ this.bidsService.bidsRepo.update(bid_id, {
+ first_bid: ['https://www.allbids.com.au'].includes(
+ bid.web_bid.origin_url,
+ )
+ ? true
+ : false,
+ });
}
// Gửi thông tin bid đến bot telegram
@@ -112,10 +119,14 @@ export class BidHistoriesService {
this.eventEmitter.emit(Event.BID_SUBMITED, botData);
// Lưu message đã gửi để theo dõi
- this.sendMessageHistoriesService.sendMessageRepo.save({
- message: this.botTelegramApi.formatBidMessage(botData),
- bid,
- });
+ try {
+ this.sendMessageHistoriesService.sendMessageRepo.save({
+ message: this.botTelegramApi.formatBidMessage(botData),
+ bid,
+ });
+ } catch (error) {
+ console.log(`BidHistoriesService - create: ${error?.message}`);
+ }
// Kiểm tra nếu trạng thái bid thay đổi sau khi lưu, phát sự kiện cập nhật tất cả bid
const bidUpdated = await this.bidsService.bidsRepo.findOne({
diff --git a/auto-bid-tool/index.js b/auto-bid-tool/index.js
index e420ed3..2d9dae8 100644
--- a/auto-bid-tool/index.js
+++ b/auto-bid-tool/index.js
@@ -77,7 +77,7 @@ const addProductTab = (data) => {
if (children.length === 0) {
console.warn(
- `⚠️ No children found for bid id ${web.id}, skipping addProductTab`
+ `⚠️ No children found for bid id ${web.id}, skipping addProductTab`,
);
return;
}
@@ -91,7 +91,7 @@ const addProductTab = (data) => {
children.forEach((newChild) => {
const existingChildIndex = updatedChildren.findIndex(
- (c) => c.id === newChild.id
+ (c) => c.id === newChild.id,
);
if (existingChildIndex !== -1) {
@@ -128,7 +128,7 @@ const tracking = async () => {
MANAGER_BIDS.filter((bid) => !bid.page_context).map((apiBid) => {
console.log(`🎧 Listening to events for API Bid ID: ${apiBid.id}`);
return apiBid.listen_events();
- })
+ }),
);
await Promise.allSettled(
@@ -137,12 +137,12 @@ const tracking = async () => {
return (apiBid.onCloseLogin = (data) => {
// Loại bỏ class hiện có. Tạo tiền đề cho việc tạo đối tượng mới lại
MANAGER_BIDS = MANAGER_BIDS.filter(
- (item) => item.id !== data.id && item.type !== data.type
+ (item) => item.id !== data.id && item.type !== data.type,
);
addProductTab(data);
});
- })
+ }),
);
Promise.allSettled(
@@ -151,7 +151,7 @@ const tracking = async () => {
console.log(
`🔍 [${
productTab.id
- }] Current URL: ${await productTab.page_context?.url?.()}`
+ }] Current URL: ${await productTab.page_context?.url?.()}`,
);
// Xác định parent context
@@ -160,7 +160,7 @@ const tracking = async () => {
productTab.parent_browser_context = parent?.browser_context;
if (!productTab.parent_browser_context) {
console.log(
- `⏳ Waiting for parent process... (Product ID: ${productTab.id})`
+ `⏳ Waiting for parent process... (Product ID: ${productTab.id})`,
);
return;
}
@@ -169,14 +169,14 @@ const tracking = async () => {
// Thời điểm tracking liên tục
const earlyTrackingTime = subtractSeconds(
productTab.close_time,
- productTab.getEarlyTrackingSeconds() || 0
+ productTab.getEarlyTrackingSeconds() || 0,
);
// Check không mở tab nếu chưa đến giờ
if (productTab.close_time && !isTimeReached(earlyTrackingTime)) {
console.log(
`⏳ [${productTab.id}] Early tracking time not reached yet. ` +
- `Waiting until ${earlyTrackingTime} (current time: ${new Date().toISOString()})`
+ `Waiting until ${earlyTrackingTime} (current time: ${new Date().toISOString()})`,
);
return;
}
@@ -184,7 +184,7 @@ const tracking = async () => {
// Kết nối Puppeteer nếu chưa có page_context
if (!productTab.page_context) {
console.log(
- `🔌 Connecting to page for Product ID: ${productTab.id}`
+ `🔌 Connecting to page for Product ID: ${productTab.id}`,
);
await productTab.puppeteer_connect();
}
@@ -194,7 +194,7 @@ const tracking = async () => {
if (global[`IS_PLACE_BID-${productTab.id}`]) return;
console.log(
- `🔄 Redirecting to new URL for Product ID: ${productTab.id}`
+ `🔄 Redirecting to new URL for Product ID: ${productTab.id}`,
);
await productTab.gotoLink();
}
@@ -205,14 +205,14 @@ const tracking = async () => {
await productTab.update();
} else {
console.log(
- `⏳ Product ID: ${productTab.id} was updated recently. Skipping update.`
+ `⏳ Product ID: ${productTab.id} was updated recently. Skipping update.`,
);
}
// Chờ first bid
if (!productTab.first_bid) {
console.log(
- `🎯 Waiting for first bid for Product ID: ${productTab.id}`
+ `🎯 Waiting for first bid for Product ID: ${productTab.id}`,
);
return;
}
@@ -223,13 +223,13 @@ const tracking = async () => {
!isTimeReached(productTab.start_bid_time)
) {
console.log(
- `⏳ Not yet time to bid. Skipping Product ID: ${productTab.id}`
+ `⏳ Not yet time to bid. Skipping Product ID: ${productTab.id}`,
);
return;
}
await productTab.action();
- })
+ }),
);
// Dọn dẹp tab không dùng
@@ -250,7 +250,7 @@ const tracking = async () => {
console.log(
`⏳ Waiting ${
configs.AUTO_TRACKING_DELAY / 1000
- } seconds before the next iteration...`
+ } seconds before the next iteration...`,
);
await delay(configs.AUTO_TRACKING_DELAY);
}
@@ -294,7 +294,7 @@ const clearLazyTab = async () => {
const earlyTrackingTime = subtractSeconds(
productTab.close_time,
- productTab.getEarlyTrackingSeconds() || 0
+ productTab.getEarlyTrackingSeconds() || 0,
);
if (!isTimeReached(earlyTrackingTime)) {
@@ -314,7 +314,7 @@ const clearLazyTab = async () => {
(item) =>
item.model === modelProductTab &&
isTimeReached(item.close_time) &&
- item.status === "biding"
+ item.status === "biding",
);
if (productWatingUpdate) {
@@ -347,12 +347,12 @@ const clearLazyTab = async () => {
await Promise.race([
page.close(),
new Promise((_, reject) =>
- setTimeout(() => reject(new Error("Close timeout")), 3000)
+ setTimeout(() => reject(new Error("Close timeout")), 3000),
),
]);
} catch (closeErr) {
console.warn(
- `⚠️ Error closing page ${pageUrl}: ${closeErr.message}`
+ `⚠️ Error closing page ${pageUrl}: ${closeErr.message}`,
);
}
}
@@ -369,7 +369,7 @@ const clearLazyTab = async () => {
if (await item.isLazy()) {
safeClosePage(item);
}
- })
+ }),
);
} catch (err) {
console.error("❌ Error in clearLazyTab:", err.message);
@@ -396,18 +396,18 @@ const workTracking = async () => {
} catch (error) {
console.error(
`[❌ ERROR] Snapshot failed for Product ID: ${item.id}`,
- error
+ error,
);
} finally {
activeTasks.delete(item.id);
}
- })
- )
+ }),
+ ),
);
} catch (error) {
console.error(
`[❌ ERROR] Work tracking failed: ${error.message}\n`,
- error.stack
+ error.stack,
);
}
};
@@ -441,10 +441,10 @@ const trackingLoginStatus = async () => {
console.warn(
`[⚠️ WARN] Failed to check login for bid ${
item?.id || "unknown"
- }: ${err.message}`
+ }: ${err.message}`,
);
}
- })
+ }),
);
// Optional: log summary
@@ -455,7 +455,7 @@ const trackingLoginStatus = async () => {
} catch (error) {
console.error(
`[❌ ERROR] Login status tracking failed: ${error.message}\n`,
- error.stack
+ error.stack,
);
}
};
diff --git a/auto-bid-tool/models/allbids.com.au/allbids-product-bid.js b/auto-bid-tool/models/allbids.com.au/allbids-product-bid.js
index 703872d..2175bed 100644
--- a/auto-bid-tool/models/allbids.com.au/allbids-product-bid.js
+++ b/auto-bid-tool/models/allbids.com.au/allbids-product-bid.js
@@ -11,6 +11,8 @@ import {
import { ProductBid } from "../product-bid.js";
export class AllbidsProductBid extends ProductBid {
+ price_to_bid = 0;
+
constructor({ ...prev }) {
super(prev);
}
@@ -20,7 +22,7 @@ export class AllbidsProductBid extends ProductBid {
try {
// Chờ cho Angular load (có thể tùy chỉnh thời gian nếu cần)
await this.page_context.waitForFunction(
- () => window.angular !== undefined
+ () => window.angular !== undefined,
);
const auctionData = await this.page_context.evaluate(() => {
@@ -56,7 +58,7 @@ export class AllbidsProductBid extends ProductBid {
return auctionData;
} catch (error) {
console.log(
- `[${this.id}] Error in waitForApiResponse: ${error?.message}`
+ `[${this.id}] Error in waitForApiResponse: ${error?.message}`,
);
}
}
@@ -66,7 +68,7 @@ export class AllbidsProductBid extends ProductBid {
try {
// Chờ cho Angular load (có thể tùy chỉnh thời gian nếu cần)
await this.page_context.waitForFunction(
- () => window.angular !== undefined
+ () => window.angular !== undefined,
);
const historiesData = await this.page_context.evaluate((model) => {
@@ -103,7 +105,7 @@ export class AllbidsProductBid extends ProductBid {
return historiesData;
} catch (error) {
console.log(
- `[${this.id}] Error in waitForApiResponse: ${error?.message}`
+ `[${this.id}] Error in waitForApiResponse: ${error?.message}`,
);
}
}
@@ -158,8 +160,8 @@ export class AllbidsProductBid extends ProductBid {
}
},
this.model,
- this.max_price,
- configs.WEB_CONFIGS.ALLBIDS.PLACE_BID
+ this.price_to_bid,
+ configs.WEB_CONFIGS.ALLBIDS.PLACE_BID,
);
return response;
@@ -189,7 +191,7 @@ export class AllbidsProductBid extends ProductBid {
}
},
this.model,
- configs.WEB_CONFIGS.ALLBIDS.PLACE_BID
+ configs.WEB_CONFIGS.ALLBIDS.PLACE_BID,
);
return response;
@@ -200,20 +202,20 @@ export class AllbidsProductBid extends ProductBid {
console.log(`🔄 [${this.id}] Call update for ID: ${this.id}`);
- // 📌 Chờ phản hồi API từ trang, tối đa 10 giây
+ // Chờ phản hồi API từ trang, tối đa 10 giây
const result = await this.waitForApiResponse();
const historiesData = await this.getHistoriesData();
console.log({ historiesData });
- // 📌 Nếu không có dữ liệu trả về thì dừng
+ // Nếu không có dữ liệu trả về thì dừng
if (!result) {
console.log(`⚠️ [${this.id}] No valid data received, skipping update.`);
return;
}
- // 📌 Loại bỏ các giá trị không hợp lệ và bổ sung thông tin cần thiết
+ // Loại bỏ các giá trị không hợp lệ và bổ sung thông tin cần thiết
const data = removeFalsyValues(
{
// model: result?.pid || null,
@@ -231,12 +233,12 @@ export class AllbidsProductBid extends ProductBid {
competor_histories: historiesData,
},
},
- ["close_time"]
+ ["close_time"],
);
console.log(`🚀 [${this.id}] Processed data ready for update`);
- // 📌 Gửi dữ liệu cập nhật lên hệ thống
+ // Gửi dữ liệu cập nhật lên hệ thống
await this.handleUpdateBid(data);
console.log("✅ Update successful!");
@@ -251,7 +253,7 @@ export class AllbidsProductBid extends ProductBid {
currentHigherBid?.amount >= this.max_price
) {
console.log(
- `⚠️ [${this.id}] ${currentHigherBid?.userName} is highter price`
+ `⚠️ [${this.id}] ${currentHigherBid?.userName} is highter price`,
);
outBid(this.id);
@@ -263,7 +265,7 @@ export class AllbidsProductBid extends ProductBid {
async handlePlaceBid() {
if (!this.page_context) {
console.log(
- `⚠️ [${this.id}] No page context found, aborting bid process.`
+ `⚠️ [${this.id}] No page context found, aborting bid process.`,
);
return;
}
@@ -286,14 +288,14 @@ export class AllbidsProductBid extends ProductBid {
isTimeReached(new Date(response.aucCloseUtc).toUTCString())
) {
console.log(
- `⚠️ [${this.id}] Outbid detected, calling outBid function.`
+ `⚠️ [${this.id}] Outbid detected, calling outBid function.`,
);
await outBid(this.id);
return;
}
// Kiểm tra nếu giá hiện tại lớn hơn giá tối đa cộng thêm giá cộng thêm
- if (this.current_price > this.max_price + this.plus_price) {
+ if (this.current_price > this.max_price) {
console.log(`⚠️ [${this.id}] Outbid bid`); // Ghi log cảnh báo nếu giá hiện tại vượt quá mức tối đa cho phép
return; // Dừng hàm nếu giá đã vượt qua giới hạn
}
@@ -303,7 +305,7 @@ export class AllbidsProductBid extends ProductBid {
console.log(
`⏳ [${this.id}] Not yet time to bid. Skipping Product: ${
this.name || "None"
- }`
+ }`,
);
return;
}
@@ -316,8 +318,19 @@ export class AllbidsProductBid extends ProductBid {
) {
console.log(
`⚠️ [${this.id}] No response or myBid equals max_price:`,
- response
+ response,
); // Ghi log nếu không có phản hồi hoặc giá đấu của người dùng bằng giá tối đa
+
+ if (
+ response?.aucCurrentBidder != this.web_bid.display_name &&
+ this.max_price >= response.aucCurrentBid
+ ) {
+ console.log(
+ `[${this.id}] The ${response?.aucCurrentBidder} bidded higher price ${response.aucCurrentBid}`,
+ );
+ outBid(this.id);
+ return;
+ }
return; // Nếu không có phản hồi hoặc giá đấu bằng giá tối đa thì dừng hàm
}
@@ -325,16 +338,28 @@ export class AllbidsProductBid extends ProductBid {
console.log(`📜 [${this.id}] Current bid history:`, this.histories);
if (
- bidHistoriesItem &&
- bidHistoriesItem?.price === this.current_price &&
- this.max_price == response?.aucUserMaxBid
+ (bidHistoriesItem &&
+ bidHistoriesItem?.price === this.current_price &&
+ this.max_price == response?.aucUserMaxBid) ||
+ response?.aucCurrentBidder === this.web_bid.display_name
) {
console.log(
- `🔄 [${this.id}] You have already bid on this item! (Bid Price: ${bidHistoriesItem.price})`
+ `🔄 [${this.id}] You have already bid on this item! (Bid Price: ${bidHistoriesItem.price})`,
);
return;
}
+ this.price_to_bid =
+ (response.aucCurrentBid || this.current_price) + this.plus_price + 1;
+
+ if (this.price_to_bid > this.max_price) {
+ console.log(
+ `[${this.id}] The ${response?.aucCurrentBidder} bidded higher price ${response.aucCurrentBid}`,
+ );
+ outBid(this.id);
+ return;
+ }
+
console.log("---------------------BIDDING--------------------");
if (this.isSandbox()) {
@@ -358,12 +383,13 @@ export class AllbidsProductBid extends ProductBid {
// const { aucUserMaxBid } = await this.waitForApiResponse();
console.log(`📡 [${this.id}] API Response received:`, {
aucUserMaxBid: this.max_price,
+ priceToBid: this.price_to_bid,
});
// 📌 Kiểm tra trạng thái đấu giá từ API
if (
data?.bidResult?.result ||
- data?.bidResult?.bidAmount == this.max_price
+ data?.bidResult?.bidAmount <= this.max_price
) {
console.log(`📸 [${this.id}] Taking bid success snapshot...`);
@@ -371,14 +397,14 @@ export class AllbidsProductBid extends ProductBid {
pushPrice({
bid_id: this.id,
- price: this.max_price,
+ price: this.price_to_bid,
});
await takeSnapshot(
this.page_context,
this,
"bid-success",
- CONSTANTS.TYPE_IMAGE.SUCCESS
+ CONSTANTS.TYPE_IMAGE.SUCCESS,
);
console.log(`✅ [${this.id}] Bid placed successfully!`);
@@ -386,7 +412,7 @@ export class AllbidsProductBid extends ProductBid {
}
console.log(
- `⚠️ [${this.id}] Bid action completed, but status is still "None".`
+ `⚠️ [${this.id}] Bid action completed, but status is still "None".`,
);
}