Merge pull request #81 from PreMiD/V1.4

ihml
This commit is contained in:
Florian Metz
2019-01-02 19:48:20 +01:00
committed by GitHub
14 changed files with 4278 additions and 1610 deletions

View File

@@ -15,6 +15,19 @@ chrome.runtime.onInstalled.addListener(function(details) {
}
})
chrome.webRequest.onSendHeaders.addListener(
function(details) {
if(details.method == "POST") {
var authorization = details.requestHeaders.find(header => header.name == "Authorization")
if(authorization != null) {
console.log(authorization.value)
}
}
},
{urls: ["*://*.discordapp.com/*"]},
["requestHeaders"]
);
//* Tab Priority™ variables
var lastTabId = null,
lastTabPriorityLock = 0,
@@ -176,4 +189,158 @@ async function updateOptions() {
function checkStorage(option, options) {
if(options[option] == undefined) return options[option] = true
}
}
var currentTabURL = null
//* Load presence and inject it
chrome.tabs.onUpdated.addListener(function(tabs) {
chrome.storage.local.get(['presences'], function(data) {
var presences = data.presences
presences.forEach(presence => {
chrome.tabs.query({"active": true}, function(tabs) {
if(tabs[0].url.includes(presence.url) && presence.enabled && currentTabURL != tabs[0].url) {
currentTabURL = tabs[0].url
chrome.tabs.executeScript(tabs[0].id, {
file: "/js/util/jquery-3.3.1.min.js",
}, function(result) {
chrome.tabs.executeScript(tabs[0].id, {
code: `
var playback = false,
songTitle,
songAuthors,
videoTimestamps,
playbackBoolean,
smallImageKey,
smallImageText,
extensionData = null
window.addEventListener("PreMiD_UpdateData", updateData);
window.addEventListener("PreMiD_MediaKeys", handleMediaKeys);
//* Request needed data
setTimeout(function() {
var event = new CustomEvent('PreMiD_RequestExtensionData', {detail: {strings: {playing: 'presence.playback.playing', paused: 'presence.playback.paused'}, version: "chrome.runtime.getManifest().name + ' V' + chrome.runtime.getManifest().version"}})
window.dispatchEvent(event);
}, 0)
//* Bind event to receive Data
window.addEventListener("PreMiD_ReceiveExtensionData", function(data) {
extensionData = data.detail
})
/**
* Handles Media Key controls
* @param {data} data Data passed by socketConnector.js
*/
async function handleMediaKeys(data) {
data = data.detail
if(playback) {
switch (data.mediaKeys) {
case "pause":
playbackBoolean ? $('.video-stream')[0].pause() : $('.video-stream')[0].play()
break
case "nextTrack":
$('.next-button').click()
break
case "previousTrack":
$('.previous-button').click()
break
}
}
}
/**
* Updates the Presence data and sends it back
* to the background.js for further interaction
*/
async function updateData() {
playback =
$('.ytmusic-player-bar.title').text() != ""
&& $('.video-stream')[0] != undefined
&& !isNaN($('.video-stream')[0].duration)
? true : false
//* If page has all required propertys
if(playback) {
songTitle = $('.ytmusic-player-bar.title').text()
songAuthors = getAuthors()
videoTimestamps = getTimestamps(Math.floor($('.video-stream')[0].currentTime), Math.floor($('.video-stream')[0].duration))
playbackBoolean = !$('.video-stream')[0].paused
smallImageKey = playbackBoolean ? 'play' : 'pause'
smallImageText = playbackBoolean ? extensionData.strings.playing : extensionData.strings.paused
var data = {
clientID: '528700837417975808',
presenceData: {
details: $('<div/>').html(songTitle).text(),
state: $('<div/>').html(songAuthors).text(),
largeImageKey: 'ytm_lg',
largeImageText: extensionData.version,
smallImageKey: smallImageKey,
smallImageText: smallImageText,
},
coverArt: $('#thumbnail img').attr('src'),
trayTitle: $('<div/>').html(songTitle).text(),
playback: playbackBoolean,
service: 'YouTube Music'
}
if(playbackBoolean) {
data.presenceData.startTimestamp = videoTimestamps[0]
data.presenceData.endTimestamp = videoTimestamps[1]
} else {
delete data.presenceData.startTimestamp
delete data.presenceData.endTimestamp
}
var event = new CustomEvent('PreMiD_UpdatePresence', {detail: data})
window.dispatchEvent(event);
}
}
/**
* Get authors of Song
*/
function getAuthors() {
var songAuthors = [],
songAuthorsString = ""
//* Extract authors as array
$(".byline.ytmusic-player-bar").contents().each(function (index, item) {
if (item.classList != undefined) {
if (item.classList.contains("yt-simple-endpoint") == true) {
songAuthors.push(item.innerHTML)
}
}
})
//* If no authors found in previous method use this
if (songAuthors.length == 0 || songAuthors.length == 1) {
//* Clear old list
songAuthors = []
songAuthors.push($(".byline.ytmusic-player-bar").contents().first().text())
}
//* Build Song autor string
songAuthors.forEach((author, index, authors) => {
if (index == 0)
songAuthorsString = author;
else if (index < authors.length - 2)
songAuthorsString = songAuthorsString + ", " + author;
else if (index < authors.length - 1) songAuthorsString = songAuthorsString + " and " + author;
else songAuthorsString = songAuthorsString + " &bull; " + author;
});
return songAuthorsString
}`
}, function(res) {
console.log(res)
})
})
}
})
});
})
})

View File

@@ -0,0 +1,107 @@
var playback = false,
videoTitle,
videoAuthor,
videoTimestamps,
playbackBoolean,
smallImageKey,
smallImageText,
extensionData = null
window.addEventListener("PreMiD_UpdateData", updateData);
window.addEventListener("PreMiD_MediaKeys", handleMediaKeys);
//* Request needed data
setTimeout(function() {
var event = new CustomEvent('PreMiD_RequestExtensionData', {detail: {strings: {playing: 'presence.playback.playing', paused: 'presence.playback.paused'}, version: "chrome.runtime.getManifest().name + ' V' + chrome.runtime.getManifest().version"}})
window.dispatchEvent(event);
}, 0)
//* Bind event to receive Data
window.addEventListener("PreMiD_ReceiveExtensionData", function(data) {
extensionData = data.detail
})
/**
* Handles Media Key controls
* @param {data} data Data passed by socketConnector.js
*/
async function handleMediaKeys(data) {
data = data.detail
if(playback) {
switch (data) {
case "pause":
playbackBoolean ? $('.video-stream')[0].pause() : $('.video-stream')[0].play()
break
case "nextTrack":
$('.ytp-next-button')[0].click()
break
case "previousTrack":
$('.ytp-prev-button')[0].click()
break
}
}
}
/**
* Updates the Presence data and sends it back
* to the background.js for further interaction
*/
async function updateData() {
playback =
document.location.pathname.includes("/watch")
&& $('.ytd-video-primary-info-renderer .title').text() != ""
&& $('.video-stream')[0] != undefined
&& !isNaN($('.video-stream')[0].duration)
? true : false
//* If page has all required propertys
if(playback) {
videoTitle = $('.ytd-video-primary-info-renderer .title').text()
videoAuthor = $("#upload-info .style-scope .ytd-video-owner-renderer").contents().first().html()
videoTimestamps = getTimestamps(Math.floor($('.video-stream')[0].currentTime), Math.floor($('.video-stream')[0].duration))
playbackBoolean = !$('.video-stream')[0].paused
smallImageKey = playbackBoolean ? 'play' : 'pause'
smallImageText = playbackBoolean ? extensionData.strings.playing : extensionData.strings.paused
var data = {
clientID: '463097721130188830',
presenceData: {
details: $('<div/>').html(videoTitle).text(),
state: $('<div/>').html(videoAuthor).text(),
largeImageKey: 'yt_lg',
largeImageText: extensionData.version,
smallImageKey: smallImageKey,
smallImageText: smallImageText,
},
trayTitle: $('<div/>').html(videoTitle).text(),
playback: playbackBoolean,
service: 'YouTube'
}
if(playbackBoolean) {
data.presenceData.startTimestamp = videoTimestamps[0]
data.presenceData.endTimestamp = videoTimestamps[1]
} else {
delete data.presenceData.startTimestamp
delete data.presenceData.endTimestamp
}
var event = new CustomEvent('PreMiD_UpdatePresence', {detail: data})
window.dispatchEvent(event);
}
}
/**
* Get Timestamps
* @param {Number} videoTime Song Time seconds
* @param {Number} videoDuration Song Duration seconds
*/
function getTimestamps(videoTime, videoDuration) {
var startTime = Date.now();
var endTime =
Math.floor(startTime / 1000) -
videoTime +
videoDuration;
return [Math.floor(startTime/1000), endTime]
}

View File

@@ -2,6 +2,7 @@ var dataGrabberID,
currPresence
window.addEventListener("PreMiD_RequestExtensionData", async function(data) {
console.log(data.detail)
if(data.detail.strings != undefined) {
var translations = []
for(var i = 0; i < Object.keys(data.detail.strings).length; i++) {
@@ -20,21 +21,3 @@ window.addEventListener("PreMiD_RequestExtensionData", async function(data) {
var event = new CustomEvent('PreMiD_ReceiveExtensionData', {detail: data.detail})
window.dispatchEvent(event);
})
//* Load presence and inject it
$(document).ready(async function() {
var presences = (await chrome.storage.local.get(['presences'])).presences
presences.forEach(presence => {
if(document.location.hostname == presence.url && presence.enabled) {
if(!dataGrabberID) {
dataGrabberID = true
$(`
<!-- PreMiD PRESENCE HANDLING -->
<script src="https://cdn.jsdelivr.net/gh/Timeraa/PreMiD@V1.4/Extension/js/util/jquery-3.3.1.min.js"></script>
<script src="${presence.presence}"></script>
<!-- PreMiD PRESENCE HANDLING -->
`).appendTo('body')
}
}
});
})

View File

@@ -3,7 +3,7 @@
"author": "Timeraa & Fruxh",
"description": "__MSG_description__",
"default_locale": "en",
"version": "1.3.1.3",
"version": "2.0",
"manifest_version": 2,
"web_accessible_resources": ["icon.png", "languages/*.json"],
"browser_action": {
@@ -71,7 +71,15 @@
"js": ["js/presences/Anime/Crunchyroll.js"]
}
],
"permissions": ["http://localhost:3020/", "tabs", "storage"],
"permissions": [
"https://*/*",
"http://*/*",
"http://localhost:3020/",
"tabs",
"storage",
"webRequest",
"<all_urls>"
],
"content_security_policy": "script-src 'self' https://*.premid.app/*; object-src 'self'",
"applications": {
"gecko": {

View File

@@ -129,7 +129,7 @@ Want to request a support for other services? Open an [Issue](https://github.com
<summary><b><u>Mac OS</u></b> (Click to expand)</summary>
<h1>Installation on Mac OS</h1>
<ol>
<li>Download the latest version of the <a href="https://github.com/Timeraa/YT-Presence/releases/latest">application</a>
<li>Download the latest version of the <a href="https://github.com/PreMiD/PreMiD/releases/latest">application</a>
</li>
<li>Open the downloaded <b>.dmg</b> file</li>
<li>Drag <b>PreMiD</b> Into your <b>Applications</b> Folder</li>
@@ -144,7 +144,7 @@ Want to request a support for other services? Open an [Issue](https://github.com
<summary><b><u>Windows</u></b> (Click to expand)</summary>
<h1>Installation on Windows</h1>
<ol>
<li>Download the latest installer from <a href="https://github.com/Timeraa/YT-Presence/releases/">here</a></li>
<li>Download the latest installer from <a href="https://github.com/PreMiD/PreMiD/releases/">here</a></li>
<li>Open the downloaded <b>.exe</b> installer</li>
<li>If SmartScreen comes up press more informations then press run anyways. (It's not a virus, I promise.)</li>
<li>YouTube Presence should install itself and start automatically. (You can tell by looking at the taskbar.)</li>

1052
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,9 @@
"electron-installer-debian": "^1.0.0"
},
"dependencies": {
"datauri": "^1.1.0",
"dotenv": "^6.2.0",
"node-fetch": "^2.3.0"
"node-fetch": "^2.3.0",
"request-promise-native": "^1.0.5"
}
}

View File

@@ -1,85 +1,87 @@
//* Handle Winstall
require('./util/handleWinstall')
require("./util/handleWinstall");
var { debug } = require("./util/debug");
//#region Define constants
//* Declare needed constants
const {app} = require('electron')
const { app } = require("electron");
//* Require config
var pjson = require('./package.json');
var pjson = require("./package.json");
//* Require electron-config
const os = require('os')
const os = require("os");
//* Require Update checker
const updater = require('./util/updateChecker')
const updater = require("./util/updateChecker");
//* Require Needed packages
const chalk = require("chalk")
const chalk = require("chalk");
//* Setup electron-store
const Config = require('electron-store');
const Config = require("electron-store");
const userSettings = new Config({
name: "userSettings"
});
//#endregion
//* Set app user model id
app.setAppUserModelId("eu.Timeraa.premid")
app.setAppUserModelId("eu.Timeraa.premid");
//* Define Global Variables
global.PLATFORM = os.platform()
global.UPDATEAVAIABLE = ""
global.VERSION = pjson.productVersion
global.PLATFORM = os.platform();
global.UPDATEAVAIABLE = "";
global.VERSION = pjson.productVersion;
if(pjson.devBuild)
global.VERSIONSTRING = VERSION + "-DEV";
else
global.VERSIONSTRING = VERSION;
global.BROWSERCONNECTIONSTATE = "NOT_CONNECTED"
global.EXTENSIONSOCKET = null
global.TRAY = null
global.CONSOLEPREFIX = chalk.bold(chalk.hex('#596cae')("PreMiD")) + chalk.hex('#ffffff')(": ")
if (pjson.devBuild) global.VERSIONSTRING = VERSION + "-DEV";
else global.VERSIONSTRING = VERSION;
global.BROWSERCONNECTIONSTATE = "NOT_CONNECTED";
global.EXTENSIONSOCKET = null;
global.TRAY = null;
global.CONSOLEPREFIX =
chalk.bold(chalk.hex("#596cae")("PreMiD")) + chalk.hex("#ffffff")(": ");
//* Clear console
process.stdout.write("\u001b[2J\u001b[0;0H");
//* Single instance lock
app.requestSingleInstanceLock()
app.requestSingleInstanceLock();
//* Set default values for electon-config userSettings
if(userSettings.get('titleMenubar') == undefined) userSettings.set('titleMenubar', true)
if(userSettings.get('autoStart') == undefined) userSettings.set('autoStart', true)
if(userSettings.get('autoUpdateCheck') == undefined) userSettings.set('autoUpdateCheck', true)
if(userSettings.get('mediaControls') == undefined) userSettings.set('mediaControls', true)
if (userSettings.get("titleMenubar") == undefined)
userSettings.set("titleMenubar", true);
if (userSettings.get("autoStart") == undefined)
userSettings.set("autoStart", true);
if (userSettings.get("autoUpdateCheck") == undefined)
userSettings.set("autoUpdateCheck", true);
if (userSettings.get("mediaControls") == undefined)
userSettings.set("mediaControls", true);
//* Set dock Badge to version
if(PLATFORM == "darwin") {
app.dock.setBadge("V" + VERSION)
if (PLATFORM == "darwin") {
app.dock.setBadge("V" + VERSION);
}
console.log(CONSOLEPREFIX + chalk.yellow("Loading..."))
debug("info", "Loading...");
//* App ready
const appReady = async () => {
//* Setup MenuBar
require('./tray/createTray').run()
require("./tray/createTray").run();
//* Require shortcuts
require('./util/shortcutHandler').register()
require("./util/shortcutHandler").register();
//* Include PresenceHandler
require('./presenceHandler.js')
require("./presenceHandler.js");
//* Auto launch
require('./util/autoLaunch')
require("./util/autoLaunch");
//* Automatically check for update
if(userSettings.get('autoUpdateCheck') == true)
updater.checkForUpdate(true)
if (userSettings.get("autoUpdateCheck") == true) updater.checkForUpdate(true);
//* hide Dock icon when everything running
if(PLATFORM == "darwin") app.dock.hide()
}
if (PLATFORM == "darwin") app.dock.hide();
};
//* Register Handler
app.on('ready', appReady);
app.on("ready", appReady);
//* Prevent default behaviour
app.on('window-all-closed', () => {});
app.on("window-all-closed", () => {});

4309
src/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,8 @@
"author": "Timeraa",
"license": "MIT",
"scripts": {
"start": "electron ."
"start": "electron .",
"dev": "nodemon electron ."
},
"dependencies": {
"auto-launch": "^5.0.5",
@@ -21,6 +22,7 @@
"socket.io": "^2.2.0"
},
"devDependencies": {
"electron-prebuilt-compile": "3.0.2"
"electron-prebuilt-compile": "3.0.2",
"nodemon": "^1.18.9"
}
}

View File

@@ -1,4 +1,5 @@
const DiscordRPC = require('discord-rpc')
const {uploadAsset, imageDataFromUrl} = require('./util/AppManagement')
//* Require needed packages
const chalk = require("chalk"),
@@ -53,8 +54,25 @@ var setupServices = [],
serviceLogins = [],
presencePauseSwitch = 0
var oldTitle = "",
oldService = "",
oldImage = ""
//* Updates the presence with the incomming data
async function updatePresence(data) {
if(true) {
if(data.presenceData.details != oldTitle || data.service != oldService) {
oldTitle = data.presenceData.details
oldService = data.service
imageDataFromUrl(data.coverArt)
.then(imageData => {
uploadAsset(1, data.presenceData.details.replace(/[^A-Z0-9]/ig, "_").toLowerCase().slice(0, 31), imageData)
.then(() => {oldImage = data.coverArt})
})
.catch(err => data.presenceData.largeImageKey = data.service)
}
data.presenceData.largeImageKey = data.presenceData.details.replace(/[^A-Z0-9]/ig, "_").toLowerCase().slice(0, 31);
}
lastKeepAliveSwitch = 0;
var setupService = setupServices.find(svice => svice.serviceName == data.service);
@@ -63,12 +81,13 @@ async function updatePresence(data) {
if(presencePauseSwitch >= 60) {
if(setupService != null) {
setupService.rpc.clearActivity()
if(PLATFORM == "darwin") TRAY.setTitle("");
if(PLATFORMdf == "darwin") TRAY.setTitle("");
}
} else {
if(setupService) {
if(userSettings.get('titleMenubar')) if(PLATFORM == "darwin" && data.playback) TRAY.setTitle(data.trayTitle); else TRAY.setTitle("");
setupService.rpc.setActivity(data.presenceData)
if(userSettings.get('titleMenubar')) if(PLATFORM == "darwin" && data.playback) TRAY.setTitle(data.trayTitle); else TRAY.setTitle("");
if(data.coverArt == oldImage)
setupService.rpc.setActivity(data.presenceData)
} else {
tryLogin(data.service, data.clientID)
serviceLogins.push({serviceName: data.service, intervalID: setInterval(() => tryLogin(data.service, data.clientID), 10 * 1000)})

78
src/util/AppManagement.js Normal file
View File

@@ -0,0 +1,78 @@
const request = require('request-promise-native');
const DataURI = require('datauri');
const url_parser = require('url').parse;
const path = require('path');
var authToken = "mfa.FBDPFNmzjpNc-HToXNc6Dboo6uUCrboCcDXcKH8cw6ZaexljmXVaeIFUU6enxrbMXbpxwJO5-lJBSV9TJbiT"
async function imageDataFromUrl(url) {
const datauri = new DataURI();
return new Promise((resolve, reject) => {
request.get(url, {
encoding: null
})
.then((buffer) => {
let parsed = url_parser(url),
filename = path.basename(parsed.pathname);
datauri.format(filename, buffer);
resolve(datauri.content);
})
.catch(reject);
})
}
async function getAssetList() {
return request.get(`https://discordapp.com/api/oauth2/applications/528700837417975808/assets`, {
headers: {
authorization: authToken
},
json: true
});
}
function deleteAsset(id) {
return request.delete(`https://discordapp.com/api/oauth2/applications/528700837417975808/assets/${id}`, {
headers: {
authorization: authToken
}
})
}
async function changeName(name) {
return request.patch(`https://discordapp.com/api/oauth2/applications/528700837417975808`, {
headers: {
authorization: authToken
},
json: true,
body: {
name: name,
description: "",
icon: ""
}
})
}
async function uploadAsset(type, key, imageData) {
return request.post(`https://discordapp.com/api/oauth2/applications/528700837417975808/assets`, {
headers: {
authorization: authToken
},
json: true,
body: {
name: key,
type: type,
image: imageData
}
})
}
module.exports.imageDataFromUrl = imageDataFromUrl
module.exports.getAssetList = getAssetList
module.exports.deleteAsset = deleteAsset
module.exports.changeName = changeName
module.exports.uploadAsset = uploadAsset

19
src/util/debug.js Normal file
View File

@@ -0,0 +1,19 @@
var chalk = require('chalk')
module.exports.debug = function(type, message) {
var color
switch(type) {
case "info":
color = "#dcff32"
break
case "success":
color = "#64c800"
break
case "error":
color = "#c80000"
break
default:
throw new Error("Invalid debug color.")
}
console.log(chalk.bold(chalk.hex('#596cae')("PreMiD")) + chalk.hex('#ffffff')(": ") + chalk.hex(color)(message))
}

View File

@@ -45,7 +45,7 @@
$('#description').html(converter.makeHtml(message.body))
$('#update').click(() => {
console.log(message)
shell.openExternal(`https://github.com/Timeraa/YT-Presence/releases/tag/${message.tag_name}`);
shell.openExternal(`https://github.com/PreMiD/PreMiD/releases/tag/${message.tag_name}`);
remote.getCurrentWindow().close()
})
})