update view message
This commit is contained in:
		
							parent
							
								
									a4298d444f
								
							
						
					
					
						commit
						c86acdaf3e
					
				
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
					@ -28,7 +28,6 @@ class MessageApiService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async createAndSendToZulip(messages: IMessage[]) {
 | 
					  async createAndSendToZulip(messages: IMessage[]) {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      console.log({ messages });
 | 
					 | 
				
			||||||
      const processedMessages = await Promise.all(
 | 
					      const processedMessages = await Promise.all(
 | 
				
			||||||
        messages.map(async (msg) => {
 | 
					        messages.map(async (msg) => {
 | 
				
			||||||
          // Nếu message là mảng
 | 
					          // Nếu message là mảng
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,3 +44,9 @@ contentService.startSyncConversations();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AUTO SYNC MESAGE PREFIX (INTERNAL)
 | 
					// AUTO SYNC MESAGE PREFIX (INTERNAL)
 | 
				
			||||||
contentService.autoSyncConversationPrefixMessages();
 | 
					contentService.autoSyncConversationPrefixMessages();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// setInterval(() => {
 | 
				
			||||||
 | 
					//   const a = new TeamsChatService();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   console.log({ messages: a.extractAllMessages() });
 | 
				
			||||||
 | 
					// }, 10000);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -407,7 +407,7 @@ export class ContentService {
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fixedHeightChatInput(retry = 20, interval = 1000) {
 | 
					  fixedHeightChatInput(retry = 20, interval = 2000) {
 | 
				
			||||||
    const tryFind = () => {
 | 
					    const tryFind = () => {
 | 
				
			||||||
      const el = document.querySelector(
 | 
					      const el = document.querySelector(
 | 
				
			||||||
        this.service.elTags.chat_input
 | 
					        this.service.elTags.chat_input
 | 
				
			||||||
| 
						 | 
					@ -557,7 +557,7 @@ export class ContentService {
 | 
				
			||||||
            for (const chat of data) {
 | 
					            for (const chat of data) {
 | 
				
			||||||
              this._clickToConversation(chat.id as string);
 | 
					              this._clickToConversation(chat.id as string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              await delay(2000);
 | 
					              await delay(5000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              const currentRoom = this.service.getCurrentRoomInfo();
 | 
					              const currentRoom = this.service.getCurrentRoomInfo();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
 | 
					/* eslint-disable @typescript-eslint/no-explicit-any */
 | 
				
			||||||
import { messageApi } from "@/api/message-api.service";
 | 
					import { messageApi } from "@/api/message-api.service";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class TeamsChatService {
 | 
					export class TeamsChatService {
 | 
				
			||||||
| 
						 | 
					@ -33,6 +34,13 @@ export class TeamsChatService {
 | 
				
			||||||
      ) as HTMLImageElement[];
 | 
					      ) as HTMLImageElement[];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    console.log({
 | 
				
			||||||
 | 
					      el,
 | 
				
			||||||
 | 
					      data_time: (el as any).date_time,
 | 
				
			||||||
 | 
					      text: (el.querySelector('[data-tid="overlay-count-text"]') as any)
 | 
				
			||||||
 | 
					        ?.innerText,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return sharedImages; // Luôn trả về array (có thể rỗng)
 | 
					    return sharedImages; // Luôn trả về array (có thể rỗng)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,35 +63,47 @@ export class TeamsChatService {
 | 
				
			||||||
  private _getMessageByEl(el: HTMLElement | null): string | string[] {
 | 
					  private _getMessageByEl(el: HTMLElement | null): string | string[] {
 | 
				
			||||||
    if (!el) return "";
 | 
					    if (!el) return "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Lấy text ban đầu (nếu có)
 | 
					    // Lấy text ban đầu và loại bỏ khoảng trắng dư
 | 
				
			||||||
    let message = el.innerText || "";
 | 
					    let message = el.innerText?.trim() || "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Nếu có ảnh gửi kèm (ảnh chia sẻ), thì ưu tiên trả về ảnh
 | 
					    // Lấy danh sách ảnh (nếu có)
 | 
				
			||||||
    const sharedImages = this._getImageFormEl(el);
 | 
					    const sharedImages = this._getImageFormEl(el) || [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (sharedImages.length) {
 | 
					    if (sharedImages.length > 0) {
 | 
				
			||||||
      const arrMessage = sharedImages.map(
 | 
					      const arrMessage = sharedImages.map(
 | 
				
			||||||
        (img) => img.getAttribute("src") || ""
 | 
					        (img) => img.getAttribute("src") || ""
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (message?.length) {
 | 
					      if (message.length > 0) {
 | 
				
			||||||
 | 
					        // Kiểm tra overlay
 | 
				
			||||||
 | 
					        const overlay = document
 | 
				
			||||||
 | 
					          .getElementById(`message-body-${(el as any)?.date_time}`)
 | 
				
			||||||
 | 
					          ?.querySelector('[data-tid="overlay-count-text"]');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Nếu overlay text === message gốc → chỉ trả về ảnh
 | 
				
			||||||
 | 
					        if (overlay && (overlay as HTMLElement).innerText === message) {
 | 
				
			||||||
 | 
					          return arrMessage;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Nếu không, thêm message vào cuối
 | 
				
			||||||
        arrMessage.push(message);
 | 
					        arrMessage.push(message);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return arrMessage;
 | 
					      return arrMessage;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Tìm tất cả emoji theo itemtype
 | 
					    // Tìm tất cả emoji trong element
 | 
				
			||||||
    const emojiImgs = Array.from(
 | 
					    const emojiImgs = Array.from(
 | 
				
			||||||
      el.querySelectorAll("img[itemtype]")
 | 
					      el.querySelectorAll("img[itemtype]")
 | 
				
			||||||
    ) as HTMLImageElement[];
 | 
					    ) as HTMLImageElement[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const emojiAlts = emojiImgs
 | 
					    const emojiAlts = emojiImgs
 | 
				
			||||||
      .map((img) => img.getAttribute("alt") || "")
 | 
					      .map((img) => img.getAttribute("alt") || "")
 | 
				
			||||||
      .filter(Boolean);
 | 
					      .filter(Boolean);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Nối emoji vào cuối chuỗi gốc (hoặc có thể chèn theo vị trí nâng cao)
 | 
					    // Nếu có emoji thì nối vào message
 | 
				
			||||||
    if (emojiAlts.length) {
 | 
					    if (emojiAlts.length > 0) {
 | 
				
			||||||
      message += emojiAlts.join("");
 | 
					      message = `${message}${emojiAlts.join("")}`;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return message.trim();
 | 
					    return message.trim();
 | 
				
			||||||
| 
						 | 
					@ -112,6 +132,8 @@ export class TeamsChatService {
 | 
				
			||||||
      `#content-${dateTime}`
 | 
					      `#content-${dateTime}`
 | 
				
			||||||
    ) as HTMLElement | null;
 | 
					    ) as HTMLElement | null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (contentEl as any)["date_time"] = dateTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { room_id, room_name } = this.getCurrentRoomInfo();
 | 
					    const { room_id, room_name } = this.getCurrentRoomInfo();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,14 +1,18 @@
 | 
				
			||||||
 | 
					import { isBase64 as a } from 'class-validator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function isBase64(str: string): boolean {
 | 
					export function isBase64(str: string): boolean {
 | 
				
			||||||
  if (!str || typeof str !== 'string') {
 | 
					  //   if (!str || typeof str !== 'string') {
 | 
				
			||||||
    return false;
 | 
					  //     return false;
 | 
				
			||||||
  }
 | 
					  //   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Bỏ phần prefix nếu có (ví dụ: data:image/png;base64,)
 | 
					  //   // Bỏ prefix nếu có, ví dụ: data:image/png;base64,
 | 
				
			||||||
  const cleanedStr = str.includes(',') ? str.split(',')[1] : str;
 | 
					  //   const cleanedStr = str.includes(',') ? str.split(',')[1] : str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Base64 chỉ chứa các ký tự A-Z, a-z, 0-9, +, / và có thể kết thúc bằng = hoặc ==
 | 
					  //   // Base64 chỉ chứa các ký tự A-Z, a-z, 0-9, +, /
 | 
				
			||||||
  const base64Regex =
 | 
					  //   const base64Regex = /^[A-Za-z0-9+/]+={0,2}$/;
 | 
				
			||||||
    /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/;
 | 
					
 | 
				
			||||||
 | 
					  //   // Kiểm tra: độ dài chia hết cho 4 và regex khớp
 | 
				
			||||||
  return base64Regex.test(cleanedStr);
 | 
					  //   return cleanedStr.length % 4 === 0 && base64Regex.test(cleanedStr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return a(str, { urlSafe: false }) && str.length > 100;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,6 +135,7 @@ export class MessagesService {
 | 
				
			||||||
    const existing = await this.repo.findOne({
 | 
					    const existing = await this.repo.findOne({
 | 
				
			||||||
      where: { time_raw: dto.time, room_id: dto.room_id },
 | 
					      where: { time_raw: dto.time, room_id: dto.room_id },
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (existing) {
 | 
					    if (existing) {
 | 
				
			||||||
      return { data: existing, exit: true };
 | 
					      return { data: existing, exit: true };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@ export class ZulipService {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 2. Lấy phần đuôi file từ MIME type
 | 
					    // 2. Lấy phần đuôi file từ MIME type
 | 
				
			||||||
    const extension = 'png';
 | 
					    const extension = 'jpg';
 | 
				
			||||||
    const filename = `${Date.now()}-${Math.random().toString(36).substring(7)}.${extension}`;
 | 
					    const filename = `${Date.now()}-${Math.random().toString(36).substring(7)}.${extension}`;
 | 
				
			||||||
    const filePath = path.join(tempDir, filename);
 | 
					    const filePath = path.join(tempDir, filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue