您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A userscript to Enhance the User experience on Snapchat Web
当前为
- // ==UserScript==
- // @name SnapEnhance Web
- // @description A userscript to Enhance the User experience on Snapchat Web
- // @version 1.0.1
- // @author SnapEnhance
- // @source https://github.com/SnapEnhance/web/
- // @license GPLv3
- // @match *://web.snapchat.com/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=snapchat.com
- // @grant unsafeWindow
- // @run-at document-start
- // @namespace https://greasyfork.org/users/1242486
- // ==/UserScript==
- (function (window) {
- function simpleHook(object, name, proxy) {
- const old = object[name];
- object[name] = proxy(old, object);
- }
- // Bypass upload size
- Object.defineProperty(File.prototype, "size", {
- get: function () {
- return 500;
- }
- });
- // Inject into worker
- function workerInjected() {
- function hookPreRequest(request) {
- if (request.url.endsWith("messagingcoreservice.MessagingCoreService/SendTypingNotification")) {
- console.log("bypassed typing notification");
- return null;
- }
- if (request.url.endsWith("messagingcoreservice.MessagingCoreService/UpdateConversation")) {
- console.log("bypassed read receipt");
- return null;
- }
- return request;
- }
- function _arrayBufferToBase64(buffer) {
- const binary = new Uint8Array(buffer).reduce((acc, byte) => acc + String.fromCharCode(byte), '');
- return btoa(binary);
- }
- async function hookPostRequest(request, response) {
- if (request.headers && request.headers.get("content-type") === "application/grpc-web+proto") {
- const arrayBuffer = await response.arrayBuffer();
- console.log("Response", response.url, _arrayBufferToBase64(arrayBuffer));
- response.arrayBuffer = async () => arrayBuffer;
- }
- return response;
- }
- // Hook websocket (hide bitmoji)
- WebSocket.prototype.send = new Proxy(WebSocket.prototype.send, {
- apply: function (target, thisArg, argumentsList) {
- console.log("WebSocket send", argumentsList[0]);
- // return target.apply(thisArg, argumentsList);
- }
- });
- // Hook worker web requests
- const oldFetch = fetch;
- // @ts-ignore
- // eslint-disable-next-line no-implicit-globals
- fetch = async (...args) => {
- args[0] = hookPreRequest(args[0]);
- if (args[0] == null) {
- throw new Error();
- }
- const requestBody = args[0].body;
- console.log(args[0]);
- if (requestBody && !requestBody.locked) {
- const buffer = await requestBody.getReader().read();
- if (buffer.value) {
- console.log("Request", args[0].url, _arrayBufferToBase64(buffer.value));
- }
- args[0] = new Request(args[0], {
- body: buffer.value,
- headers: args[0].headers
- });
- }
- // @ts-ignore
- const result = oldFetch(...args);
- return new Promise(async (resolve, reject) => {
- try {
- resolve(await hookPostRequest(args[0], await result));
- }
- catch (e) {
- console.info("Fetch error", e);
- reject(e);
- }
- });
- };
- }
- const oldBlobClass = window.Blob;
- window.Blob = class HookedBlob extends Blob {
- constructor(...args) {
- const data = args[0][0];
- if (typeof data === "string" && data.startsWith("importScripts")) {
- args[0][0] += `${workerInjected.toString()};workerInjected();`;
- window.Blob = oldBlobClass;
- }
- super(...args);
- }
- };
- simpleHook(document, "createElement", (proxy, instance) => (...args) => {
- const result = proxy.call(instance, ...args);
- // Allow audio note and image download
- if (args[0] === "audio" || args[0] === "video" || args[0] === "img") {
- simpleHook(result, "setAttribute", (proxy2, instance2) => (...args2) => {
- if (args2[0] === "controlsList")
- return;
- proxy2.call(instance2, ...args2);
- });
- result.addEventListener("contextmenu", (event) => {
- event.stopImmediatePropagation();
- });
- }
- return result;
- });
- // Always focused
- simpleHook(document, "hasFocus", () => () => true);
- const oldAddEventListener = EventTarget.prototype.addEventListener;
- Object.defineProperty(EventTarget.prototype, "addEventListener", {
- value: function (...args) {
- const eventName = args[0];
- if (eventName === "keydown")
- return;
- if (eventName === "focus")
- return;
- return oldAddEventListener.call(this, ...args);
- }
- });
- })(window.unsafeWindow || window);