Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
plemont committed Dec 12, 2016
0 parents commit 91b8cd0
Show file tree
Hide file tree
Showing 5 changed files with 1,097 additions and 0 deletions.
97 changes: 97 additions & 0 deletions extension/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* @name Preso extension
*
* This script, as part of a Chrome extension, allows the refreshing and looping
* of Google Slides documents (without having to resort to "Publishing to web").
*
* See: https://plemont.github.io for details.
*/
const PRESO_REGEX = /^https:\/\/docs\.google\.com\/presentation\/d\/[^/]+\/present(.*)$/;

function fullscreenAndLoop(tab) {
chrome.windows.getCurrent(win =>
chrome.windows.update(win.id, {state: 'fullscreen'}));
let nextUrl = calculateNextSlideUrl(tab.url);
setTimeout(createReload(tab.id, nextUrl), 10000);
}

function calculateNextSlideUrl(url) {
let [hostPath, parts] = url.split('?');
let params = extractParamsDictionary(parts);
let slideId = params.slide;
let matches;
if (slideId) {
let idRegex = /^(id\..*)_(\d+)_(\d+)$/;
if ((matches = idRegex.exec(slideId)) !== null) {
let currentPage = +matches[2];
let totalPages = +matches[3];
let newSlide = [matches[1], (currentPage + 1) % totalPages,
totalPages].join('_');
return hostPath + '?loop=1&slide=' + newSlide;
}
}
return url;
}

function createReload(tabId, nextUrl) {
return function() {
chrome.tabs.query({
active: true,
lastFocusedWindow: true
}, function(tabs) {
let url = tabs[0].url;
let matches = PRESO_REGEX.exec(url);
if (matches) {
chrome.tabs.update(tabId, {url: nextUrl});
}
});
};
}

function extractParamsDictionary(parts) {
let params = {};
parts.split('&').forEach(part => {
let [key, value] = part.split('=');
params[key] = value;
});
return params;
}

function checkForValidUrl(tabId, changeInfo, tab) {
// Only process events that are completions, not loading events.
if (changeInfo.status !== 'complete') {
return;
}
let matches;
if ((matches = PRESO_REGEX.exec(tab.url)) !== null) {
let args = matches[1];
if (args.startsWith('?')) {
let parts = args.substr(1);
let params = extractParamsDictionary(parts);

// If there is a loop parameter, then just prepare for the next page.
if (params.loop) {
fullscreenAndLoop(tab);
} else {
// if no loop parameter, highlight the pageAction button.
chrome.pageAction.show(tab.id);
}
}
}
}

chrome.pageAction.onClicked.addListener(() => {
chrome.tabs.query({
active: true,
lastFocusedWindow: true
}, function(tabs) {
let url = tabs[0].url;
let matches = PRESO_REGEX.exec(url);
if (matches) {
fullscreenAndLoop(tabs[0]);
}
});
});

// Listen for any changes to the URL of any tab.
chrome.tabs.onUpdated.addListener(checkForValidUrl);
21 changes: 21 additions & 0 deletions extension/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "Preso",
"version": "0.0.1",
"manifest_version": 2,
"description": "Refresh'n'loop presentations",
"homepage_url": "https://plemont.github.io",
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
"page_action": {
"default_title": "Present'n'loop"
},
"permissions": [
"tabs",
"webNavigation",
"activeTab"
]
}
87 changes: 87 additions & 0 deletions generate_refresh.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
var CLIENT_ID = 'INSERT_CLIENT_ID';
var CLIENT_SECRET = 'INSERT_CLIENT_SECRET';

/**
* This script allows the stepping through of the Authorization Code Grant in
* order to obtain a refresh token.
*
* This script uses the out-of-band redirect URI, which is not part of the
* OAuth2 standard, to allow not redirecting the user. If this does not work
* with your API, try instead the OAuth playground:
* https://developers.google.com/oauthplayground/
*
* Execute script twice:
* Execution 1, will result in a URL, which when placed in the browser will
* issue a code.
* Execution 2: place the code in "CODE" below and execute. If successful a
* refresh token will be printed to the console.
*/

// Enter required scopes, e.g. ['https://www.googleapis.com/auth/drive']
var SCOPES = ['https://www.googleapis.com/auth/presentations',
'https://www.googleapis.com/auth/drive'];

// Auth URL, e.g. https://accounts.google.com/o/oauth2/auth
var AUTH_URL = 'https://accounts.google.com/o/oauth2/auth';
// Token URL, e.g. https://accounts.google.com/o/oauth2/token
var TOKEN_URL = 'https://accounts.google.com/o/oauth2/token';

var CODE = '';

function main() {
if (CODE) {
generateRefreshToken();
} else {
generateAuthUrl();
}
}

/**
* Creates the URL for pasting in the browser, which will generate the code
* to be placed in the CODE variable.
*/
function generateAuthUrl() {
var payload = {
scope: SCOPES.join(' '),
// Specify that no redirection should take place
// This is Google-specific and not part of the OAuth2 specification.
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
response_type: 'code',
access_type: 'offline',
client_id: CLIENT_ID
};
var options = {payload: payload};
var request = UrlFetchApp.getRequest(AUTH_URL, options);
Logger.log(
'Browse to the following URL: ' + AUTH_URL + '?' + request.payload);
}

/**
* Generates a refresh token given the authorization code.
*/
function generateRefreshToken() {
var payload = {
code: CODE,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
// Specify that no redirection should take place
// This is Google-specific and not part of the OAuth2 specification.
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
grant_type: 'authorization_code'
};
var options = {method: 'POST', payload: payload};
var response = UrlFetchApp.fetch(TOKEN_URL, options);
var data = JSON.parse(response.getContentText());
if (data.refresh_token) {
var msg = 'Success! Refresh token: ' + data.refresh_token +
'\n\nThe following may also be a useful format for pasting into your script:\n\n' +
'var CLIENT_ID = \'' + CLIENT_ID + '\';\n' +
'var CLIENT_SECRET = \'' + CLIENT_SECRET + '\';\n' +
'var REFRESH_TOKEN = \'' + data.refresh_token + '\';\n';
Logger.log(msg);
} else {
Logger.log(
'Error, failed to generate Refresh token: ' +
response.getContentText());
}
}
Loading

0 comments on commit 91b8cd0

Please sign in to comment.