Skip to content

Commit

Permalink
Merge pull request #183 from hermanho/dev
Browse files Browse the repository at this point in the history
1. Update lint rules
2. Enrich error message display
3. Update README.md and INSTALL.md
  • Loading branch information
hermanho committed Jan 28, 2024
2 parents ebef283 + b970ae7 commit c832080
Show file tree
Hide file tree
Showing 15 changed files with 371 additions and 2,599 deletions.
14 changes: 9 additions & 5 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"root": true,
"extends": [
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:jsdoc/recommended"
"plugin:jsdoc/recommended",
"plugin:jsdoc/recommended-typescript-flavor"
],
"plugins": [
"prettier",
"jsdoc",
"jest"
],
Expand All @@ -30,10 +30,14 @@
}
},
"rules": {
"prettier/prettier": [
"comma-dangle": [
"error",
{
"endOfLine": "auto"
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "only-multiline"
}
],
"eqeqeq": "error",
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ credentials.json
token.json
node_modules/
cache/*
!cache/keep.txt
.idea
16 changes: 16 additions & 0 deletions Errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class ConfigFileError extends Error {
get name() {
return this.constructor.name;
}
}

class AuthError extends Error {
get name() {
return this.constructor.name;
}
}

module.exports = {
ConfigFileError,
AuthError,
};
65 changes: 23 additions & 42 deletions GPhotos.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"use strict";

const EventEmitter = require("events");
const opn = require("open");
const readline = require("readline");
const fs = require("fs");
const path = require("path");
const { mkdirp } = require("mkdirp");
Expand All @@ -15,6 +13,7 @@ const Axios = require("axios");
const moment = require("moment");
const { isAxiosError } = require("axios");
const { error_to_string } = require("./error_to_string");
const { ConfigFileError, AuthError } = require("./Errors");

/**
*
Expand All @@ -34,7 +33,10 @@ class Auth extends EventEmitter {
super();
this.#config = config;
this.#debug = debug;
this.init();
this.init().then(
() => {},
(err) => this.emit("error", err),
);
}

async init() {
Expand All @@ -45,14 +47,18 @@ class Auth extends EventEmitter {
: () => {};
if (this.#config === undefined) config = {};
if (this.#config.keyFilePath === undefined) {
throw new Error('Missing "keyFilePath" from config (This should be where your Credential file is)');
throw new ConfigFileError('Missing "keyFilePath" from config (This should be where your Credential file is)');
}
if (this.#config.savedTokensPath === undefined) {
throw new Error('Missing "savedTokensPath" from config (this should be where your OAuth2 access tokens will be saved)');
throw new ConfigFileError('Missing "savedTokensPath" from config (this should be where your OAuth2 access tokens will be saved)');
}
let file = path.resolve(__dirname, this.#config.savedTokensPath);
if (!fs.existsSync(file)) {
throw new AuthError("No OAuth token genreated. Please execute generate_token_v2.js before start.");
}
let creds = path.resolve(__dirname, this.#config.keyFilePath);
if (!fs.existsSync(creds)) {
throw new Error("Missing Credentials.");
throw new AuthError("Missing Credentials.");
}
const key = require(this.#config.keyFilePath).installed;
const oauthClient = new OAuth2Client(key.client_id, key.client_secret, key.redirect_uris[0]);
Expand All @@ -78,44 +84,16 @@ class Auth extends EventEmitter {
}
};

const getTokens = () => {
const url = oauthClient.generateAuthUrl({
access_type: "offline",
scope: [this.#config.scope],
});
log("Opening OAuth URL.\n\n" + url + "\n\nReturn here with your code.");
opn(url).catch(() => {
log("Failed to automatically open the URL. Copy/paste this in your browser:\n", url);
});
if (typeof this.#config.tokenInput === "function") {
this.#config.tokenInput(processTokens);
return;
}
const reader = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false,
});
reader.question("> Paste your code: ", processTokens);
};
const processTokens = async (oauthCode) => {
if (!oauthCode) process.exit(-1);
try {
const tkns = await oauthClient.getToken(oauthCode);
tokensCred = tkns;
await saveTokens(true);
} catch (error) {
throw new Error("Error getting tokens:", error);
}
};
process.nextTick(() => {
if (this.#config.savedTokensPath) {
try {
let file = path.resolve(__dirname, this.#config.savedTokensPath);
const tokensFile = fs.readFileSync(file);
tokensCred = JSON.parse(tokensFile);
if (fs.existsSync(file)) {
const tokensFile = fs.readFileSync(file);
tokensCred = JSON.parse(tokensFile);
}
} catch (error) {
getTokens();
console.error("[GPHOTOS:AUTH]", error);
} finally {
if (tokensCred !== undefined) saveTokens();
}
Expand Down Expand Up @@ -162,10 +140,13 @@ class GPhotos {
this.log(e.toString());
throw e;
}
return new Promise((resolve) => {
return new Promise((resolve, reject) => {
auth.on("ready", (client) => {
resolve(client);
});
auth.on("error", (error) => {
reject(error);
});
});
}

Expand Down Expand Up @@ -250,8 +231,8 @@ class GPhotos {
/**
*
* @param {number} pageSize
* @param {String} pageToken
* @returns {Promise<MediaItem[]>}
* @param {string} pageToken
* @returns {Promise<MediaItem[]>} MediaItem
*/
const getImage = async (pageSize = 50, pageToken = "") => {
this.log("Indexing photos now. total: ", list.length);
Expand Down
46 changes: 22 additions & 24 deletions INSTALL.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
## Installation

1. Install Module
```sh
git clone https://github.com/eouia/MMM-GooglePhotos.git
cd MMM-GooglePhotos
npm install
```

If you doubt errors are caused by different `node.JS` version, you can try to compile it by yourself.
In that case, you need to rebuild some binaries to match with Electron version.
```sh
cd ~/MagicMirror/modules/MMM-GooglePhotos
npm install --save-dev electron-rebuild
./node_modules/.bin/electron-rebuild # It could takes dozens sec.
```
```sh
cd ~/MagicMirror/modules
git clone https://github.com/hermanho/MMM-GooglePhotos.git
cd MMM-GooglePhotos
npm run install-prod
```

2. If you are using Docker
```sh
cd ~/magic_mirror/modules
git clone https://github.com/eouia/MMM-GooglePhotos.git
docker exec -it -w /opt/magic_mirror/modules/MMM-GooglePhotos magic_mirror npm install
```
If you are using Docker

```sh
cd ~/MagicMirror/modules
git clone https://github.com/hermanho/MMM-GooglePhotos.git
docker exec -it -w /opt/magic_mirror/modules/MMM-GooglePhotos magic_mirror npm run install-prod
```

1. Add MMM-GooglePhotos module config in ~/MagicMirror/config/config.js

## Authorise OAuth Token

### Get `token.json`
1. Clone this repo in your local pc and execute `npm install`
2. Go to [Google API Console](https://console.developers.google.com/)
3. From the menu bar, select a project or create a new project.
4. To open the Google API Library, from the Navigation menu, select `APIs & Services > Library`.
Don't forget to enble the Google API Services.
4. To open the Google API Library, from the Navigation menu, select `APIs & Services > Library`. Don't forget to enble the Google API Services.
5. Search for "Google Photos Library API". Select the correct result and click Enable. (You may need to enable "Google Plus" also.)
6. Then, from the menu, select `APIs & Services > Credentials`.
6. Then from the menu, select `APIs & Services > Credentials`.
7. On the Credentials page, click `Create Credentials > OAuth client ID`.
8. Select your Application type as **`Desktop app`**(IMPORTANT!!!) and submit. (Before or After that, you might be asked for making consent screen. do that.)
> Google might change the menu name. So current this would work; ![2022-09-18_18-49-03](https://user-images.githubusercontent.com/2337380/190921355-49162763-0fdd-4b7e-a361-d762046f844d.png)
Expand All @@ -44,11 +42,11 @@ node generate_token_v2.js
11. Authorize it and close the browser
12. Copy the file `token.json` and `credentials.json` to the folder `MMM-GooglePhotos` in the remote device

### stop token from expiring every week
-as of 2021, it appears tokens only last 1 week while in 'testing'. This led to users needing to get a new token.json every ~week to 10 days. To get your app out of testing mode, where the token will last indefinately:
### Stop token from expiring every week
as of 2021, it appears tokens only last 1 week while in 'testing'. This led to users needing to get a new token.json every ~week to 10 days. To get your app out of testing mode, where the token will last indefinately:

1. go to your google cloud console, select your magic mirror project. Then from the navigation menu(top left) -> APIs & Services -> Oath consent screen. This should get you to a site something like https://console.cloud.google.com/apis/credentials/consent?project=[PROJECT_ID] where [PROJECT_ID] is the project ID. This is where the publishing status. It looks like this:

![](https://raw.githubusercontent.com/eouia/MMM-GooglePhotos/master/PublishAppScreen.png)
![](https://raw.githubusercontent.com/eouia/MMM-GooglePhotos/master/PublishAppScreen.png)

2. click Publish app and review permissions as necessary.
12 changes: 12 additions & 0 deletions MMM-GooglePhotos.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Module.register("MMM-GooglePhotos", {
timeFormat: "YYYY/MM/DD HH:mm",
autoInfoPosition: false,
},
requiresVersion: "2.24.0",

suspended: false,

Expand Down Expand Up @@ -64,6 +65,16 @@ Module.register("MMM-GooglePhotos", {
this.updatePhotos(); //little faster starting
}
}
if (noti === "ERROR") {
const current = document.getElementById("GPHOTO_CURRENT");
const errMsgDiv = document.createElement("div");
errMsgDiv.style.textAlign = "center";
errMsgDiv.style.lineHeight = "80vh";
errMsgDiv.style.fontSize = "1.5em";
errMsgDiv.style.verticalAlign = "middle";
errMsgDiv.textContent = payload;
current.appendChild(errMsgDiv);
}
},

notificationReceived: function (noti, payload, sender) {
Expand Down Expand Up @@ -118,6 +129,7 @@ Module.register("MMM-GooglePhotos", {
hidden.onload = () => {
let back = document.getElementById("GPHOTO_BACK");
let current = document.getElementById("GPHOTO_CURRENT");
current.textContent = "";
//current.classList.remove("animated")
let dom = document.getElementById("GPHOTO");
back.style.backgroundImage = `url(${url})`;
Expand Down
Loading

0 comments on commit c832080

Please sign in to comment.