6

我维护了一个greasemonkey 脚本,用于监控当前曲目的播放以及Soundcloud 上的进度。以前,我可以require("lib/audiomanager")访问一个对象,该对象允许我查看整个页面的状态,例如播放曲目信息。

问题是,Soundcloud 已经开始使用 webpack 作为客户端 Javascript。据我了解,这会将所有这些类作为特定数字存储在一个包中。每次更新和重新编译客户端 JS 时,它们存储的数字似乎都会发生变化。

访问存储在 webpack 中的对象的唯一方法似乎是通过全局 webpackJsonp,如下所示。包的编号只需要唯一。

webpackJsonp([6060], {
    0: function (e, t, n) {
        window.aman = n(726);
        e.exports = function (abc) {
            console.log("Exports called");
        };
    }
});

该代码将执行并允许我访问 webpack 中该编号的对象。客户端 webpack 的 JS 中定义的对象是:

726: function (e, t, n) {
    (function (t) {
        function i(e) {
            var n = t(e.getContainerElement()),
                i = e.getState() === r.States.ERROR;
            n.toggleClass('blocked', i)
        }
        var r,
            s = n(53),
            o = n(14),
            a = 1000 / 60;
        e.exports = r = new s({
                flashAudioPath: n(2181),
                flashObjectID: 'flashAudioObject',
                updateInterval: a,
                debug: !1
            }),
            r.Errors = s.Errors,
            r.States = s.States,
            r.UPDATE_INTERVAL = a,
            o.once('audio:flash_block audio:flash_unblock', i)
    })
    .call(t, n(1))
},

所以,我能想到的解决方案:

  • 找到一个 webpack 编号不变的对象,我可以用它来获取该对象的句柄
  • 迭代每个 webpack 编号并寻找一个与这个具有相同方法集的对象。

后者看起来很乱,而第一个似乎不可能。有任何想法吗?

我尝试过的事情:

  • 制作一个新的 n(53) 就像所需的对象一样,因为它似乎在更新时保持不变。给我一个音频管理器,但绝对与页面的普通音频管理器分开,所以我看不到正在播放什么。
4

2 回答 2

3

我们也在客户端脚本中使用 SoundCloud API,所以我们最终得到了一些“更干净”的代码。这是它的主要部分(请注意,它不包含 try-catch 块,因为所有模块都存在):

var playManager, libAudio, eventBus;

webpackJsonp([], {0: function(a, b, require) 
{ 
    var modules = require.c;

    for (var moduleid in modules)
    {
        var el = require(moduleid);

        if (typeof el["playCurrent"] == "function")
        {
            playManager = el;
        }
        else if (typeof el["getSettings"] == "function")
        {
            libAudio = el;
        }
        else if (typeof el["trigger"] == "function" 
               && typeof el["bind"] == "function"
               && typeof el["listenToOnce"] == "function" &&
               typeof el["$"] != "function" &&
               typeof el["broadcast"] == "function")
        {
            eventBus = el;
        }
}     
于 2015-01-20T08:32:03.787 回答
1

Afaik 你只能从另一个包访问包。Soundcloud 不使用 ProvidePlugin,因此全局空间中没有可用的库和模块。

更新:

我知道这是一个丑陋的黑客,但它有效:

webpackJsonp([6060], {
    0: function (e, t, n) {
        var i = 0,
        found = false,
        lib;
        while (i < 2000 && !found) {
            try {
                lib = n(i);
            }
            catch (err) {
                lib = null;
            }

            if (lib && typeof lib._mute !== 'undefined') {
                found = true;
                console.log('found', lib, i);
            }
            console.log(i, lib);
            i++;
        }
        window.aman = lib;
    }
});

于 2014-11-03T03:48:52.067 回答