tinify webpacks (#1975)

* tinify webpack

* meme

* fix long version

* more changes

* even smoler

* fix up logic

* fix build

* undo changes to user agent manager because its not webpack'd anymore

* the heck

* fix stupid

* clean up browser rules

* typo
This commit is contained in:
Gus Caplan
2017-09-26 00:18:12 -05:00
committed by Crawl
parent 4d4d2f2db7
commit 27ccad1f1c
21 changed files with 85 additions and 80 deletions

View File

@@ -69,9 +69,14 @@
"node-opus": false,
"tweetnacl": false,
"sodium": false,
"src/rest/UserAgentManager.js": false,
"src/sharding/Shard.js": false,
"src/sharding/ShardClientUtil.js": false,
"src/sharding/ShardingManager.js": false,
"src/client/voice/ClientVoiceManager.js": false,
"src/client/voice/VoiceConnection.js": false,
"src/client/voice/VoiceUDPClient.js": false,
"src/client/voice/VoiceWebSocket.js": false,
"src/client/voice/dispatcher/StreamDispatcher.js": false,
"src/client/voice/opus/BaseOpusEngine.js": false,
"src/client/voice/opus/NodeOpusEngine.js": false,
@@ -86,10 +91,6 @@
"src/client/voice/util/Secretbox.js": false,
"src/client/voice/util/SecretKey.js": false,
"src/client/voice/util/VolumeInterface.js": false,
"src/client/voice/ClientVoiceManager.js": false,
"src/client/voice/VoiceBroadcast.js": false,
"src/client/voice/VoiceConnection.js": false,
"src/client/voice/VoiceUDPClient.js": false,
"src/client/voice/VoiceWebSocket.js": false
"src/client/voice/VoiceBroadcast.js": false
}
}

View File

@@ -1,4 +1,4 @@
const browser = typeof window !== 'undefined';
const { browser } = require('./util/Constants');
const zlib = require('zlib');
const querystring = require('querystring');
@@ -23,16 +23,21 @@ exports.pack = erlpack ? erlpack.pack : JSON.stringify;
exports.unpack = data => {
if (Array.isArray(data)) data = Buffer.concat(data);
if (data instanceof ArrayBuffer) data = Buffer.from(new Uint8Array(data));
if (!browser && data instanceof ArrayBuffer) data = Buffer.from(new Uint8Array(data));
if (erlpack && typeof data !== 'string') return erlpack.unpack(data);
else if (data instanceof Buffer) data = zlib.inflateSync(data).toString();
if (erlpack && typeof data !== 'string') {
return erlpack.unpack(data);
} else if (data instanceof ArrayBuffer || (!browser && data instanceof Buffer)) {
data = zlib.inflateSync(data).toString();
}
return JSON.parse(data);
};
exports.create = (gateway, query = {}, ...args) => {
const [g, q] = gateway.split('?');
query.encoding = exports.encoding;
const ws = new exports.WebSocket(`${gateway}?${querystring.stringify(query)}`, ...args);
if (q) query = Object.assign(querystring.parse(q), query);
const ws = new exports.WebSocket(`${g}?${querystring.stringify(query)}`, ...args);
if (browser) ws.binaryType = 'arraybuffer';
return ws;
};

View File

@@ -39,15 +39,6 @@ class BaseClient extends EventEmitter {
this._intervals = new Set();
}
/**
* Whether the client is in a browser environment
* @type {boolean}
* @readonly
*/
get browser() {
return typeof window !== 'undefined';
}
/**
* API shortcut
* @type {Object}

View File

@@ -17,7 +17,7 @@ const ChannelStore = require('../stores/ChannelStore');
const GuildStore = require('../stores/GuildStore');
const ClientPresenceStore = require('../stores/ClientPresenceStore');
const EmojiStore = require('../stores/EmojiStore');
const { Events } = require('../util/Constants');
const { Events, browser } = require('../util/Constants');
const DataResolver = require('../util/DataResolver');
const { Error, TypeError, RangeError } = require('../errors');
@@ -33,8 +33,10 @@ class Client extends BaseClient {
super(Object.assign({ _tokenType: 'Bot' }, options));
// Obtain shard details from environment
if (!this.options.shardId && 'SHARD_ID' in process.env) this.options.shardId = Number(process.env.SHARD_ID);
if (!this.options.shardCount && 'SHARD_COUNT' in process.env) {
if (!browser && !this.options.shardId && 'SHARD_ID' in process.env) {
this.options.shardId = Number(process.env.SHARD_ID);
}
if (!browser && !this.options.shardCount && 'SHARD_COUNT' in process.env) {
this.options.shardCount = Number(process.env.SHARD_COUNT);
}
@@ -73,14 +75,14 @@ class Client extends BaseClient {
* @type {?ClientVoiceManager}
* @private
*/
this.voice = !this.browser ? new ClientVoiceManager(this) : null;
this.voice = !browser ? new ClientVoiceManager(this) : null;
/**
* The shard helpers for the client
* (only if the process was spawned as a child, such as from a {@link ShardingManager})
* @type {?ShardClientUtil}
*/
this.shard = process.send ? ShardClientUtil.singleton(this) : null;
this.shard = !browser && process.send ? ShardClientUtil.singleton(this) : null;
/**
* All of the {@link User} objects that have been cached at any point, mapped by their IDs
@@ -110,7 +112,7 @@ class Client extends BaseClient {
this.presences = new ClientPresenceStore(this);
Object.defineProperty(this, 'token', { writable: true });
if (!this.token && 'CLIENT_TOKEN' in process.env) {
if (!browser && !this.token && 'CLIENT_TOKEN' in process.env) {
/**
* Authorization token for the logged in user/bot
* <warn>This should be kept private at all times.</warn>
@@ -207,7 +209,7 @@ class Client extends BaseClient {
* @readonly
*/
get voiceConnections() {
if (this.browser) return new Collection();
if (browser) return new Collection();
return this.voice.connections;
}

View File

@@ -247,7 +247,7 @@ class WebSocketConnection extends EventEmitter {
try {
data = WebSocket.unpack(event.data);
} catch (err) {
this.emit('debug', err);
this.client.emit('debug', err);
}
const ret = this.onPacket(data);
this.client.emit('raw', data);

View File

@@ -2,8 +2,6 @@
const kCode = Symbol('code');
const messages = new Map();
const assert = require('assert');
const util = require('util');
/**
* Extend an error of some sort into a DiscordjsError.
@@ -35,17 +33,13 @@ function makeDiscordjsError(Base) {
* @returns {string} Formatted string
*/
function message(key, args) {
assert.strictEqual(typeof key, 'string');
if (typeof key !== 'string') throw new Error('Error message key must be a string');
const msg = messages.get(key);
assert(msg, `An invalid error message key was used: ${key}.`);
let fmt = util.format;
if (typeof msg === 'function') {
fmt = msg;
} else {
if (args === undefined || args.length === 0) return msg;
args.unshift(msg);
}
return String(fmt(...args));
if (!msg) throw new Error(`An invalid error message key was used: ${key}.`);
if (typeof msg === 'function') return msg(...args);
if (args === undefined || args.length === 0) return msg;
args.unshift(msg);
return String(...args);
}
/**

View File

@@ -1,6 +1,7 @@
const querystring = require('querystring');
const snekfetch = require('snekfetch');
const https = require('https');
const { browser } = require('../util/Constants');
if (https.Agent) var agent = new https.Agent({ keepAlive: true });
@@ -27,7 +28,7 @@ class APIRequest {
if (this.options.auth !== false) request.set('Authorization', this.rest.getAuth());
if (this.options.reason) request.set('X-Audit-Log-Reason', encodeURIComponent(this.options.reason));
if (!this.rest.client.browser) request.set('User-Agent', this.rest.userAgentManager.userAgent);
if (!browser) request.set('User-Agent', this.rest.userAgentManager.userAgent);
if (this.options.headers) request.set(this.options.headers);
if (this.options.files) {

View File

@@ -1,10 +1,8 @@
const util = require('util');
const noop = () => {}; // eslint-disable-line no-empty-function
const methods = ['get', 'post', 'delete', 'patch', 'put'];
const reflectors = [
'toString', 'valueOf', 'inspect', 'constructor',
Symbol.toPrimitive, util.inspect.custom,
Symbol.toPrimitive, Symbol.for('util.inspect.custom'),
];
function buildRoute(manager) {

View File

@@ -3,13 +3,13 @@ const handlers = require('./handlers');
const APIRequest = require('./APIRequest');
const routeBuilder = require('./APIRouter');
const { Error } = require('../errors');
const { Endpoints } = require('../util/Constants');
const { Endpoints, browser } = require('../util/Constants');
class RESTManager {
constructor(client, tokenPrefix = 'Bot') {
this.client = client;
this.handlers = {};
this.userAgentManager = new UserAgentManager(this);
if (!browser) this.userAgentManager = new UserAgentManager(this);
this.rateLimitedEndpoints = {};
this.globallyRateLimited = false;
this.tokenPrefix = tokenPrefix;

View File

@@ -178,7 +178,7 @@ class ClientUser extends User {
* .catch(console.error);
*/
async setAvatar(avatar) {
return this.edit({ avatar: await DataResolver.resolveImage(avatar, this.client.browser) });
return this.edit({ avatar: await DataResolver.resolveImage(avatar) });
}
/**
@@ -294,7 +294,7 @@ class ClientUser extends User {
);
}
return DataResolver.resolveImage(icon, this.client.browser)
return DataResolver.resolveImage(icon)
.then(data => this.createGuild(name, { region, icon: data || null }));
}

View File

@@ -161,7 +161,7 @@ class GroupDMChannel extends Channel {
* @returns {Promise<GroupDMChannel>}
*/
async setIcon(icon) {
return this.edit({ icon: await DataResolver.resolveImage(icon, this.client.browser) });
return this.edit({ icon: await DataResolver.resolveImage(icon) });
}
/**

View File

@@ -3,7 +3,7 @@ const GuildAuditLogs = require('./GuildAuditLogs');
const Webhook = require('./Webhook');
const GuildMember = require('./GuildMember');
const VoiceRegion = require('./VoiceRegion');
const { ChannelTypes, Events } = require('../util/Constants');
const { ChannelTypes, Events, browser } = require('../util/Constants');
const Collection = require('../util/Collection');
const Util = require('../util/Util');
const DataResolver = require('../util/DataResolver');
@@ -315,7 +315,7 @@ class Guild extends Base {
* @readonly
*/
get voiceConnection() {
if (this.client.browser) return null;
if (browser) return null;
return this.client.voice.connections.get(this.id) || null;
}
@@ -717,7 +717,7 @@ class Guild extends Base {
* .catch(console.error);
*/
async setIcon(icon, reason) {
return this.edit({ icon: await DataResolver.resolveImage(icon, this.client.browser), reason });
return this.edit({ icon: await DataResolver.resolveImage(icon), reason });
}
/**
@@ -747,7 +747,7 @@ class Guild extends Base {
* .catch(console.error);
*/
async setSplash(splash, reason) {
return this.edit({ splash: await DataResolver.resolveImage(splash, this.client.browser), reason });
return this.edit({ splash: await DataResolver.resolveImage(splash), reason });
}
/**
@@ -1036,7 +1036,7 @@ class Guild extends Base {
.then(emoji => this.client.actions.GuildEmojiCreate.handle(this, emoji).emoji);
}
return DataResolver.resolveImage(attachment, this.client.browser)
return DataResolver.resolveImage(attachment)
.then(image => this.createEmoji(image, name, { roles, reason }));
}

View File

@@ -64,7 +64,7 @@ class TextChannel extends GuildChannel {
*/
async createWebhook(name, { avatar, reason } = {}) {
if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
avatar = await DataResolver.resolveImage(avatar, this.client.browser);
avatar = await DataResolver.resolveImage(avatar);
}
return this.client.api.channels[this.id].webhooks.post({ data: {
name, avatar,

View File

@@ -1,5 +1,6 @@
const GuildChannel = require('./GuildChannel');
const Collection = require('../util/Collection');
const { browser } = require('../util/Constants');
const { Error } = require('../errors');
/**
@@ -59,7 +60,7 @@ class VoiceChannel extends GuildChannel {
* @readonly
*/
get joinable() {
if (this.client.browser) return false;
if (browser) return false;
if (!this.permissionsFor(this.client.user).has('CONNECT')) return false;
if (this.full && !this.permissionsFor(this.client.user).has('MOVE_MEMBERS')) return false;
return true;
@@ -115,7 +116,7 @@ class VoiceChannel extends GuildChannel {
* .catch(console.error);
*/
join() {
if (this.client.browser) return Promise.reject(new Error('VOICE_NO_BROWSER'));
if (browser) return Promise.reject(new Error('VOICE_NO_BROWSER'));
return this.client.voice.joinChannel(this);
}
@@ -126,7 +127,7 @@ class VoiceChannel extends GuildChannel {
* voiceChannel.leave();
*/
leave() {
if (this.client.browser) return;
if (browser) return;
const connection = this.client.voice.connections.get(this.guild.id);
if (connection && connection.channel.id === this.id) connection.disconnect();
}

View File

@@ -1,9 +1,9 @@
const path = require('path');
const Util = require('../util/Util');
const DataResolver = require('../util/DataResolver');
const Embed = require('./MessageEmbed');
const MessageAttachment = require('./MessageAttachment');
const MessageEmbed = require('./MessageEmbed');
const { browser } = require('../util/Constants');
/**
* Represents a webhook.
@@ -151,14 +151,14 @@ class Webhook {
if (options.files) {
for (let i = 0; i < options.files.length; i++) {
let file = options.files[i];
if (typeof file === 'string' || Buffer.isBuffer(file)) file = { attachment: file };
if (typeof file === 'string' || (!browser && Buffer.isBuffer(file))) file = { attachment: file };
if (!file.name) {
if (typeof file.attachment === 'string') {
file.name = path.basename(file.attachment);
file.name = Util.basename(file.attachment);
} else if (file.attachment && file.attachment.path) {
file.name = path.basename(file.attachment.path);
file.name = Util.basename(file.attachment.path);
} else if (file instanceof MessageAttachment) {
file = { attachment: file.file, name: path.basename(file.file) || 'file.jpg' };
file = { attachment: file.file, name: Util.basename(file.file) || 'file.jpg' };
} else {
file.name = 'file.jpg';
}
@@ -169,7 +169,7 @@ class Webhook {
}
return Promise.all(options.files.map(file =>
DataResolver.resolveFile(file.attachment, this.client.browser).then(resource => {
DataResolver.resolveFile(file.attachment).then(resource => {
file.file = resource;
return file;
})
@@ -249,9 +249,7 @@ class Webhook {
*/
edit({ name = this.name, avatar }, reason) {
if (avatar && (typeof avatar === 'string' && !avatar.startsWith('data:'))) {
return DataResolver.resolveImage(avatar, this.client.browser).then(image =>
this.edit({ name, avatar: image }, reason)
);
return DataResolver.resolveImage(avatar).then(image => this.edit({ name, avatar: image }, reason));
}
return this.client.api.webhooks(this.id, this.token).patch({
data: { name, avatar },

View File

@@ -1,6 +1,7 @@
const path = require('path');
const MessageCollector = require('../MessageCollector');
const Shared = require('../shared');
const Util = require('../../util/Util');
const { browser } = require('../../util/Constants');
const Snowflake = require('../../util/Snowflake');
const Collection = require('../../util/Collection');
const DataResolver = require('../../util/DataResolver');
@@ -106,14 +107,14 @@ class TextBasedChannel {
if (options.files) {
for (let i = 0; i < options.files.length; i++) {
let file = options.files[i];
if (typeof file === 'string' || Buffer.isBuffer(file)) file = { attachment: file };
if (typeof file === 'string' || (!browser && Buffer.isBuffer(file))) file = { attachment: file };
if (!file.name) {
if (typeof file.attachment === 'string') {
file.name = path.basename(file.attachment);
file.name = Util.basename(file.attachment);
} else if (file.attachment && file.attachment.path) {
file.name = path.basename(file.attachment.path);
file.name = Util.basename(file.attachment.path);
} else if (file instanceof MessageAttachment) {
file = { attachment: file.file, name: path.basename(file.file) || 'file.jpg' };
file = { attachment: file.file, name: Util.basename(file.file) || 'file.jpg' };
} else {
file.name = 'file.jpg';
}
@@ -124,7 +125,7 @@ class TextBasedChannel {
}
return Promise.all(options.files.map(file =>
DataResolver.resolveFile(file.attachment, this.client.browser).then(resource => {
DataResolver.resolveFile(file.attachment).then(resource => {
file.file = resource;
return file;
})

View File

@@ -1,5 +1,6 @@
exports.Package = require('../../package.json');
const { Error, RangeError } = require('../errors');
exports.browser = typeof window !== 'undefined';
/**
* Options for a client.
@@ -56,9 +57,9 @@ exports.DefaultOptions = {
*/
ws: {
large_threshold: 250,
compress: require('os').platform() !== 'browser',
compress: !exports.browser,
properties: {
$os: process ? process.platform : 'discord.js',
$os: exports.browser ? 'browser' : process.platform,
$browser: 'discord.js',
$device: 'discord.js',
},

View File

@@ -3,6 +3,7 @@ const fs = require('fs');
const snekfetch = require('snekfetch');
const Util = require('../util/Util');
const { Error, TypeError } = require('../errors');
const { browser } = require('../util/Constants');
/**
* The DataResolver identifies different objects and tries to resolve a specific piece of information from them.
@@ -35,15 +36,14 @@ class DataResolver {
/**
* Resolves a Base64Resolvable, a string, or a BufferResolvable to a Base 64 image.
* @param {BufferResolvable|Base64Resolvable} image The image to be resolved
* @param {boolean} browser Whether this should resolve for a browser
* @returns {Promise<?string>}
*/
static async resolveImage(image, browser) {
static async resolveImage(image) {
if (!image) return null;
if (typeof image === 'string' && image.startsWith('data:')) {
return image;
}
const file = await this.resolveFile(image, browser);
const file = await this.resolveFile(image);
return DataResolver.resolveBase64(file);
}
@@ -80,10 +80,9 @@ class DataResolver {
/**
* Resolves a BufferResolvable to a Buffer.
* @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve
* @param {boolean} browser Whether this should resolve for a browser
* @returns {Promise<Buffer>}
*/
static resolveFile(resource, browser) {
static resolveFile(resource) {
if (resource instanceof Buffer) return Promise.resolve(resource);
if (browser && resource instanceof ArrayBuffer) return Promise.resolve(Util.convertToBuffer(resource));
@@ -97,7 +96,7 @@ class DataResolver {
return resolve(res.body);
});
} else {
const file = path.resolve(resource);
const file = browser ? resource : path.resolve(resource);
fs.stat(file, (err, stats) => {
if (err) return reject(err);
if (!stats || !stats.isFile()) return reject(new Error('FILE_NOT_FOUND', file));

View File

@@ -3,6 +3,7 @@ const snekfetch = require('snekfetch');
const { Colors, DefaultOptions, Endpoints } = require('./Constants');
const { Error: DiscordError, RangeError, TypeError } = require('../errors');
const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
const splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^/]+?|)(\.[^./]*|))(?:[/]*)$/;
/**
* Contains various general-purpose utility methods. These functions are also available on the base `Discord` object.
@@ -307,6 +308,14 @@ class Util {
updatedItems = updatedItems.map((r, i) => ({ id: r.id, position: i }));
return route.patch({ data: updatedItems, reason });
}
static basename(path, ext) {
let f = splitPathRe.exec(path).slice(1)[2];
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
}
return f;
}
}
module.exports = Util;

View File

@@ -18,6 +18,7 @@
client.on('debug', console.log);
client.on('error', console.error);
client.on('debug', console.info);
client.ws.on('close', (event) => console.log('[CLIENT] Disconnect!', event));

View File

@@ -46,6 +46,9 @@ const createConfig = options => {
dgram: 'empty',
zlib: 'empty',
__dirname: true,
process: false,
path: 'empty',
Buffer: false,
},
plugins,
};