-
-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathflickgame_share.js
More file actions
190 lines (177 loc) · 6.6 KB
/
Copy pathflickgame_share.js
File metadata and controls
190 lines (177 loc) · 6.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Shared share/import/export helpers for Flickgame.
(function () {
'use strict';
var OAUTH_CLIENT_ID = 'eb2aad12c63aec0136b1';
var templatePromise = null;
function getPlayTemplate() {
if (templatePromise) return templatePromise;
if (typeof window.FLICKGAME_STANDALONE_PLAY_HTML_B64 === 'string' && window.FLICKGAME_STANDALONE_PLAY_HTML_B64.length > 0) {
templatePromise = new Promise(function (resolve, reject) {
try {
var b64bin = atob(window.FLICKGAME_STANDALONE_PLAY_HTML_B64);
var b64bytes = new Uint8Array(b64bin.length);
for (var i = 0; i < b64bin.length; i++) {
b64bytes[i] = b64bin.charCodeAt(i) & 0xff;
}
resolve(new TextDecoder('utf-8').decode(b64bytes));
} catch (e) {
reject(e);
}
});
return templatePromise;
}
templatePromise = new Promise(function (resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', 'play.html');
req.onreadystatechange = function () {
if (req.readyState !== 4) return;
if (req.status >= 200 && req.status < 400) resolve(req.responseText);
else reject(new Error('Failed to load play.html template (HTTP ' + req.status + ')'));
};
req.onerror = function () {
reject(new Error('Network error loading play.html template'));
};
req.send();
});
return templatePromise;
}
function buildStandaloneHtmlString(stateString) {
return getPlayTemplate().then(function (template) {
var encoded = encodeURI(stateString);
return '<!--Save as html file-->\n ' + template.replace(/__EMBED__/g, encoded);
});
}
function downloadStandaloneHtml(stateString, filename) {
return buildStandaloneHtmlString(stateString).then(function (html) {
if (window.FLICKGAME_IOS_APP && window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.flickExport) {
var enc = new TextEncoder();
var u8 = enc.encode(html);
var bin = '';
for (var j = 0; j < u8.length; j++) {
bin += String.fromCharCode(u8[j]);
}
window.webkit.messageHandlers.flickExport.postMessage({
filename: filename || 'flickgame.html',
dataBase64: btoa(bin)
});
return true;
}
var blob = new Blob([html], { type: 'text/html;charset=utf-8' });
if (typeof saveAs !== 'function') throw new Error('FileSaver (saveAs) not available');
saveAs(blob, filename || 'flickgame.html');
return true;
});
}
function shareStateAsGist(stateString, callbacks) {
callbacks = callbacks || {};
var onSuccess = callbacks.onSuccess || function () {};
var onError = callbacks.onError || function () {};
var onUnauthorized = callbacks.onUnauthorized || onError;
var token = window.localStorage.getItem('oauth_access_token');
if (typeof token !== 'string') {
onUnauthorized();
return;
}
var gist = {
description: 'flickgame',
public: true,
files: {
'readme.txt': { content: 'A game made with www.flickgame.org. You can import game.txt there to play the game.' },
'game.txt': { content: stateString }
}
};
var req = new XMLHttpRequest();
req.open('POST', 'https://api.github.com/gists');
req.onreadystatechange = function () {
if (req.readyState !== 4) return;
var result;
try {
result = JSON.parse(req.responseText);
} catch (e) {
result = null;
}
if (req.status === 403) {
onError((result && result.message) || 'Forbidden');
return;
}
if (req.status !== 200 && req.status !== 201) {
if (req.statusText === 'Unauthorized') {
window.localStorage.removeItem('oauth_access_token');
onUnauthorized();
} else {
onError('HTTP Error ' + req.status + ' - ' + req.statusText);
}
return;
}
onSuccess({ id: result.id, playUrl: 'play.html?p=' + result.id });
};
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
req.setRequestHeader('Authorization', 'token ' + token);
req.send(JSON.stringify(gist));
}
function getAuthUrl() {
// URL-safe hex state, persisted so the OAuth callback (auth.html) can verify it (CSRF protection).
var bytes = window.crypto.getRandomValues(new Uint8Array(24));
var randomState = Array.prototype.map.call(bytes, function (x) {
return ('0' + x.toString(16)).slice(-2);
}).join('');
try {
window.localStorage.setItem('oauth_state', randomState);
} catch (e) {}
return 'https://github.com/login/oauth/authorize'
+ '?client_id=' + OAUTH_CLIENT_ID
+ '&scope=gist'
+ '&state=' + randomState
+ '&allow_signup=true';
}
function extractStateFromStandaloneHtml(contents) {
var fromToken = '<!--__EmbedBegin__-->';
var endToken = '<!--__EmbedEnd__-->';
var fromIndex = contents.indexOf(fromToken);
var endIndex = contents.indexOf(endToken);
if (fromIndex < 0 || endIndex < 0 || endIndex <= fromIndex) {
throw new Error("Couldn't find embedded flickgame data in this HTML file.");
}
var ss1 = contents.substr(fromIndex + fromToken.length, endIndex - fromIndex - fromToken.length);
var firstQuoteIndex = ss1.indexOf('"');
if (firstQuoteIndex < 0) {
throw new Error('Embedded flickgame data is malformed.');
}
var ss2 = ss1.substr(firstQuoteIndex + 1);
var leftRemoved = decodeURI(ss2);
var finalQuoteIndex = leftRemoved.lastIndexOf('"');
if (finalQuoteIndex < 0) {
throw new Error('Embedded flickgame data is malformed.');
}
return leftRemoved.substring(0, finalQuoteIndex);
}
function extractStateFromImportText(text) {
try {
return extractStateFromStandaloneHtml(text);
} catch (htmlError) {
var parsed;
try {
parsed = JSON.parse(text);
} catch (jsonError) {
throw htmlError;
}
if (!parsed || !parsed.canvasses || !parsed.hyperlinks) {
throw htmlError;
}
return text;
}
}
function resolvePlayUrl(playPath) {
var base = window.location.protocol === 'file:' ? 'https://www.flickgame.org/' : window.location.href;
return new URL(playPath, base).href;
}
window.FlickgameShare = {
buildStandaloneHtmlString: buildStandaloneHtmlString,
downloadStandaloneHtml: downloadStandaloneHtml,
shareStateAsGist: shareStateAsGist,
getAuthUrl: getAuthUrl,
extractStateFromStandaloneHtml: extractStateFromStandaloneHtml,
extractStateFromImportText: extractStateFromImportText,
resolvePlayUrl: resolvePlayUrl
};
})();