diff --git a/src/platforms/kick/modules/chat-attachments/chat-attachments.module.ts b/src/platforms/kick/modules/chat-attachments/chat-attachments.module.ts
index 3df67b4e..1bb8519b 100644
--- a/src/platforms/kick/modules/chat-attachments/chat-attachments.module.ts
+++ b/src/platforms/kick/modules/chat-attachments/chat-attachments.module.ts
@@ -2,6 +2,7 @@ import KickModule from "$kick/kick.module.ts";
import { ImagePreview } from "$shared/components/image-preview/image-preview.component";
import { HttpClient } from "$shared/http/http-client.ts";
import type ChatAttachmentHandler from "$shared/module/chat-attachments/chat-attachment-handler.ts";
+import EmotesChatAttachmentHandler from "$shared/module/chat-attachments/emotes-chat-attachment-handler";
import ImageChatAttachmentHandler from "$shared/module/chat-attachments/image-chat-attachment-handler.ts";
import { ImageChatAttachmentConfig } from "$shared/module/chat-attachments/image-chat-attachment.config.ts";
import type { KickChatMessageEvent } from "$types/platforms/kick/kick.events.types.ts";
@@ -65,6 +66,7 @@ export default class ChatAttachmentsModule extends KickModule {
private readonly chatAttachmentHandlers: ChatAttachmentHandler[] = [
new ImageChatAttachmentHandler(this.logger, this.imageAttachmentConfig),
+ new EmotesChatAttachmentHandler(this.logger),
];
private async handleMessage(message: KickChatMessageEvent) {
@@ -126,11 +128,9 @@ export default class ChatAttachmentsModule extends KickModule {
private async getAttachmentData(url: URL) {
try {
- const { response } = await this.httpClient.request(url.href, {
- method: "HEAD",
- responseType: "text",
- });
- return { type: response.headers.get("Content-Type"), size: response.headers.get("Content-Length") };
+ const { response } = await this.httpClient.request(url.href);
+
+ return { type: response.headers.get("Content-Type"), size: "10" };
} catch (error) {
this.logger.warn("Couldn't get attachment data", error);
}
diff --git a/src/shared/components/emote-preview/emote-preview.component.tsx b/src/shared/components/emote-preview/emote-preview.component.tsx
new file mode 100644
index 00000000..6460db52
--- /dev/null
+++ b/src/shared/components/emote-preview/emote-preview.component.tsx
@@ -0,0 +1,16 @@
+import styled from "styled-components";
+
+export const EmotePreview = (src?: string) => {
+ return (
+
+ Test Test Test.
+
+ );
+};
+
+const Wrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 4px;
+`;
diff --git a/src/shared/module/chat-attachments/emotes-chat-attachment-handler.ts b/src/shared/module/chat-attachments/emotes-chat-attachment-handler.ts
new file mode 100644
index 00000000..5f53a230
--- /dev/null
+++ b/src/shared/module/chat-attachments/emotes-chat-attachment-handler.ts
@@ -0,0 +1,77 @@
+import type { Logger } from "$shared/logger/logger.ts";
+import type {
+ BaseChatAttachmentData,
+ ChatAttachmentData,
+} from "$types/shared/module/chat-attachment/chat-attachment.types.ts";
+import ChatAttachmentHandler from "./chat-attachment-handler";
+
+export default class EmotesChatAttachmentHandler extends ChatAttachmentHandler {
+ constructor(protected readonly logger: Logger) {
+ super(logger);
+ }
+
+ static readonly ALLOWED_HOSTS = ["7tv.app", "old.7tv.app"];
+
+ validate(baseData: BaseChatAttachmentData): boolean {
+ return EmotesChatAttachmentHandler.ALLOWED_HOSTS.some((host) => baseData.url.host === host);
+ }
+
+ async applies(data: ChatAttachmentData): Promise {
+ return true;
+ // throw new Error("Not implemented");
+ }
+
+ parseUrl(url: URL): URL {
+ // INPUT: https://7tv.app/emotes/01F6MDFCSR0000WDA7ERT623YT
+ // OUTPUT: https://7tv.io/v3/emotes/01F6MDFCSR0000WDA7ERT623YT
+ // TODO: Parse only single emotes for now
+
+ url.host = "7tv.io";
+ url.pathname = `/v3${url.pathname}`;
+
+ return url;
+ }
+
+ async handle(data: ChatAttachmentData) {
+ // ! Temporary, as alternative for not supported emote data fetching
+ const emoteData = await (await fetch(data.url.href)).json();
+
+ const element = data.messageElement as HTMLLinkElement;
+
+ element.classList.add("enhancer-emote-link");
+
+ const wrapper = document.createElement("div");
+ element.replaceChildren(wrapper);
+ wrapper.style.backgroundColor = "grey";
+ wrapper.style.borderRadius = "4px";
+ wrapper.style.padding = "8px";
+ wrapper.style.display = "flex";
+ wrapper.style.flexDirection = "row";
+ wrapper.style.gap = "8px";
+ wrapper.style.textDecoration = "none";
+
+ const emotePreview = document.createElement("img");
+ emotePreview.src = `https://cdn.7tv.app/emote/${emoteData.id}/${emoteData.host.files[0].name}`;
+ emotePreview.style.width = "48px";
+ emotePreview.style.height = "48px";
+ wrapper.append(emotePreview);
+
+ const emoteDataWrapper = document.createElement("div");
+ emoteDataWrapper.style.display = "flex";
+ emoteDataWrapper.style.flexDirection = "column";
+ emoteDataWrapper.style.justifyContent = "space-between";
+ wrapper.append(emoteDataWrapper);
+
+ const emoteName = document.createElement("span");
+ emoteName.textContent = emoteData.name || "Emote Name";
+ emoteName.style.color = "white";
+ emoteName.style.textDecoration = "none";
+ emoteDataWrapper.append(emoteName);
+
+ const emoteAuthor = document.createElement("span");
+ emoteAuthor.textContent = `Created by ${emoteData.owner.username || "unknown"}`;
+ emoteAuthor.style.color = "white";
+ emoteAuthor.style.textDecoration = "none";
+ emoteDataWrapper.append(emoteAuthor);
+ }
+}