diff --git a/.github/upload-chrome-extension.yml b/.github/upload-chrome-extension.yml
new file mode 100644
index 0000000..9a85e0e
--- /dev/null
+++ b/.github/upload-chrome-extension.yml
@@ -0,0 +1,28 @@
+name: Upload Chrome Extension
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ zip_and_upload:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Create ZIP file
+ run: mkdir -p dist && zip -r dist/extension.zip manifest.json src/ _locales/ channels/ icons/ js/jquery/jquery.min.js
+
+ - name: Upload & release
+ uses: mnao305/chrome-extension-upload@v5.0.0
+ with:
+ file-path: dist/extension.zip
+ extension-id: ${{ secrets.EXTENSION_ID }}
+ client-id: ${{ secrets.CLIENT_ID }}
+ client-secret: ${{ secrets.CLIENT_SECRET }}
+ refresh-token: ${{ secrets.REFRESH_TOKEN }}
+ publish: false
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d26c746
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+dist/
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..0baf809
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+*.min.js
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..c3e0328
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "semi": true,
+ "singleQuote": true,
+ "trailingComma": "es5"
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..fe28845
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,19 @@
+
+# Change Log
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/)
+and this project adheres to [Semantic Versioning](http://semver.org/).
+
+
+## [0.1.0] - 2024-10-07
+
+### Added
+- This changelog.
+- A mapping of preset YouTube channels to their corresponding Twitch usernames to allow easy additions in the future without having to bump this extension.
+
+### Changed
+
+- Entered streamers are now saved to local storage to prevent having to re-enter each time.
+- Extension icon can now be double clicked to change chats.
+- Chat is now resized to match the height of YouTube video.
diff --git a/README.md b/README.md
index f63fdda..c6964ed 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-
@@ -12,4 +11,3 @@
-
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 0db3279..0967ef4 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -1,3 +1 @@
-{
-
-}
+{}
diff --git a/channels/stream_chat.json b/channels/stream_chat.json
index dc312f5..5dea613 100644
--- a/channels/stream_chat.json
+++ b/channels/stream_chat.json
@@ -1,11 +1,14 @@
{
- "tockerslol": "tockerslol",
- "oquequehouve": "brtt",
- "rangerlol": "rangerlol1",
- "cblol": "cblol",
- "arthurlanches": "arthur_lanches",
- "baianotv1": "baiano",
- "cazetv":"cazetv_",
- "inteligencialtda":"inteligencialimitada",
- "linustechtips":"linustech"
-}
\ No newline at end of file
+ "tockerslol": "tockerslol",
+ "oquequehouve": "brtt",
+ "rangerlol": "rangerlol1",
+ "cblol": "cblol",
+ "arthurlanches": "arthur_lanches",
+ "baianotv1": "baiano",
+ "cazetv": "cazetv_",
+ "inteligencialtda": "inteligencialimitada",
+ "linustechtips": "linustech",
+ "eslcs": "esl_csgo",
+ "blastpremier": "blastpremier",
+ "pgl": "pgl"
+}
diff --git a/manifest.json b/manifest.json
index b407214..3ad566c 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,6 +1,6 @@
{
"name": "Twitch Chat for YouTube™",
- "version": "0.0.5",
+ "version": "0.1.0",
"manifest_version": 3,
"description": "Click the extension to load Twitch chat onto YouTube live page, replacing YouTube chat.",
"icons": {
@@ -10,14 +10,10 @@
},
"default_locale": "en",
"action": {
- "default_title": "Get Twitch Chat on YouTube"
+ "default_title": "Get Twitch Chat on YouTube (double click to change chat)"
},
- "permissions": [
- "storage",
- "activeTab",
- "scripting"
- ],
+ "permissions": ["storage", "activeTab", "scripting"],
"background": {
"service_worker": "src/background/background.js"
}
-}
\ No newline at end of file
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..cffa2f2
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,28 @@
+{
+ "name": "Twitch-Chat-on-YouTube",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "devDependencies": {
+ "prettier": "^3.3.3"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
+ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..c2436a9
--- /dev/null
+++ b/package.json
@@ -0,0 +1,5 @@
+{
+ "devDependencies": {
+ "prettier": "^3.3.3"
+ }
+}
diff --git a/src/background/background.js b/src/background/background.js
index d120c9e..88e57e9 100644
--- a/src/background/background.js
+++ b/src/background/background.js
@@ -1,7 +1,6 @@
-
chrome.action.onClicked.addListener((tab) => {
- chrome.scripting.executeScript({
- target: {tabId: tab.id},
- files: ["js/jquery/jquery.min.js", "src/main.js"]
- });
- });
\ No newline at end of file
+ chrome.scripting.executeScript({
+ target: { tabId: tab.id },
+ files: ['js/jquery/jquery.min.js', 'src/main.js'],
+ });
+});
diff --git a/src/main.js b/src/main.js
index 34b1ef2..9517e8f 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,123 +1,122 @@
-async function fetchStreamerChatsFromGithub() {
- const response = await fetch(
- "https://raw.githubusercontent.com/koobzaar/Twitch-Chat-on-YouTube/refs/heads/master/channels/stream_chat.json",
- );
- if (!response.ok) {
- throw new Error("Error fetching data:");
- }
- return response.json();
+async function onlineFetchStreamerChats() {
+ const response = await fetch(
+ 'https://raw.githubusercontent.com/joshhoughton/Twitch-Chat-on-YouTube/refs/heads/master/channels/stream_chat.json'
+ );
+ if (!response.ok) {
+ throw new Error('Error fetching data:');
+ }
+ return response.json();
}
-
+
async function fetchTwitchUsernameFromGithub(youtubeChannelName) {
- try {
- const data = await fetchStreamerChatsFromGithub();
- return data[youtubeChannelName.toLowerCase()];
- } catch (error) {
- console.error("Error fetching data: ", error);
- return null;
- }
+ try {
+ const data = await fetchStreamerChatsFromGithub();
+ return data[youtubeChannelName.toLowerCase()];
+ } catch (error) {
+ console.error('Error fetching data: ', error);
+ return null;
+ }
}
-
+
function saveTwitchChatForYoutubeUser(twitchUsername, youtubeUserName) {
- chrome.storage.local.set({ [youtubeUserName]: twitchUsername });
+ chrome.storage.local.set({ [youtubeUserName]: twitchUsername });
}
-
+
function fetchYoutubeVideoHeight() {
- let youtubeVideo = document.querySelector("video");
- return youtubeVideo.clientHeight;
+ let youtubeVideo = document.querySelector('video');
+ return youtubeVideo.clientHeight;
}
-
+
function fetchYoutubeChannelId() {
- let anchorElement = "";
- anchorElement = document.querySelector(
- "ytd-video-owner-renderer a.yt-simple-endpoint.style-scope.yt-formatted-string",
- );
-
- if (anchorElement) {
- return anchorElement.href
- .replace("https://www.youtube.com/@", "")
- .toLowerCase();
- } else {
- return null;
- }
+ let anchorElement = '';
+ anchorElement = document.querySelector(
+ 'ytd-video-owner-renderer a.yt-simple-endpoint.style-scope.yt-formatted-string'
+ );
+
+ if (anchorElement) {
+ return anchorElement.href
+ .replace('https://www.youtube.com/@', '')
+ .toLowerCase();
+ } else {
+ return null;
+ }
}
-
+
function checkIfDarkMode() {
- return (
- window.matchMedia &&
- window.matchMedia("(prefers-color-scheme: dark)").matches
- );
+ return (
+ window.matchMedia &&
+ window.matchMedia('(prefers-color-scheme: dark)').matches
+ );
}
-
+
function fetchYoutubeChatFrame() {
- return $("ytd-live-chat-frame");
+ return $('ytd-live-chat-frame');
}
-
+
function displayTwitchChat(username) {
- let youtubeChatFrame = fetchYoutubeChatFrame();
-
- youtubeChatFrame.empty();
-
- youtubeChatFrame.css({
- "flex-direction": "row",
- "-webkit-flex-direction": "row",
- height: `${fetchYoutubeVideoHeight()}px`,
- });
-
- url = `https://www.twitch.tv/embed/${username}/chat?${checkIfDarkMode() ? "darkpopout" : ""}&parent=www.youtube.com"`;
-
- youtubeChatFrame.prepend(
- ``,
- );
+ let youtubeChatFrame = fetchYoutubeChatFrame();
+
+ youtubeChatFrame.empty();
+
+ youtubeChatFrame.css({
+ 'flex-direction': 'row',
+ '-webkit-flex-direction': 'row',
+ height: `${fetchYoutubeVideoHeight()}px`,
+ });
+
+ url = `https://www.twitch.tv/embed/${username}/chat?${checkIfDarkMode() ? 'darkpopout' : ''}&parent=www.youtube.com"`;
+
+ youtubeChatFrame.prepend(
+ ``
+ );
}
-
+
async function fetchUsernameFromLocalStorage(youtubeChannelName) {
- return new Promise((resolve) => {
- chrome.storage.local.get([youtubeChannelName], function (result) {
- resolve(result[youtubeChannelName]);
- });
+ return new Promise((resolve) => {
+ chrome.storage.local.get([youtubeChannelName], function (result) {
+ resolve(result[youtubeChannelName]);
});
+ });
}
-
+
function promptForTwitchUsername() {
- return prompt("Enter the streamer Twitch username:");
+ return prompt('Enter the streamer Twitch username:');
}
-
+
async function main() {
- let storedTimestamp = localStorage.getItem("storedTimestamp");
- let currentTimestamp = Date.now();
-
- if (currentTimestamp - storedTimestamp < 2000) {
- let username = promptForTwitchUsername();
- if (username) {
- saveTwitchChatForYoutubeUser(username, fetchYoutubeChannelId());
- displayTwitchChat(username);
- localStorage.setItem("storedTimestamp", currentTimestamp);
- return;
- }
- } else {
- localStorage.setItem("storedTimestamp", currentTimestamp);
- }
-
- let youtubeUserName = fetchYoutubeChannelId();
-
- let twitchUsername = await fetchUsernameFromLocalStorage(youtubeUserName);
-
- if (!twitchUsername) {
- twitchUsername = await fetchTwitchUsernameFromGithub(youtubeUserName);
+ let storedTimestamp = localStorage.getItem('storedTimestamp');
+ let currentTimestamp = Date.now();
+
+ if (currentTimestamp - storedTimestamp < 2000) {
+ let username = promptForTwitchUsername();
+ if (username) {
+ saveTwitchChatForYoutubeUser(username, fetchYoutubeChannelId());
+ displayTwitchChat(username);
+ localStorage.setItem('storedTimestamp', currentTimestamp);
+ return;
}
-
- if (!twitchUsername) {
- let username = promptForTwitchUsername();
- if (username) {
- saveTwitchChatForYoutubeUser(username, fetchYoutubeChannelId());
- displayTwitchChat(username);
- }
- } else {
- displayTwitchChat(twitchUsername);
+ } else {
+ localStorage.setItem('storedTimestamp', currentTimestamp);
+ }
+
+ let youtubeUserName = fetchYoutubeChannelId();
+
+ let twitchUsername = await fetchUsernameFromLocalStorage(youtubeUserName);
+
+ if (!twitchUsername) {
+ twitchUsername = await fetchTwitchUsernameFromGithub(youtubeUserName);
+ }
+
+ if (!twitchUsername) {
+ let username = promptForTwitchUsername();
+ if (username) {
+ saveTwitchChatForYoutubeUser(username, fetchYoutubeChannelId());
+ displayTwitchChat(username);
}
+ } else {
+ displayTwitchChat(twitchUsername);
+ }
}
-
+
main();
-
\ No newline at end of file