Skip to content
This repository has been archived by the owner on Sep 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #10 from RoBlockHead/multiplayer
Browse files Browse the repository at this point in the history
Version 0.9.0! We're finally here!
  • Loading branch information
miroreo authored Jun 28, 2021
2 parents 0dbd691 + 1033677 commit 2cb4f50
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 49 deletions.
34 changes: 17 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 15 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "Replit for VSCode",
"description": "VS Code extension for connecting to repls",
"icon": "images/replit-vs-code-logo.png",
"version": "0.8.2",
"version": "0.9.0",
"publisher": "miroreo",
"repository": {
"type": "git",
Expand All @@ -19,7 +19,8 @@
"onFileSystem:replit",
"onCommand:replit.openrepl",
"onCommand:replit.apikey",
"onCommand:replit.captchakey"
"onCommand:replit.captchakey",
"oncommand:replit.refreshcaptcha"
],
"main": "./dist/extension.js",
"contributes": {
Expand All @@ -35,6 +36,16 @@
"title": "Open a repl",
"category": "Replit"
},
{
"command": "replit.refreshcaptcha",
"title": "Refresh the CAPTCHA verification for Replit",
"category": "Replit"
},
{
"command": "replit.openmptest",
"title": "Open the Multiplayer test (experimental, non-functional)",
"category": "Replit"
},
{
"command": "replit.shell",
"title": "Open a shell for a repl",
Expand Down Expand Up @@ -121,8 +132,8 @@
"webpack-cli": "^4.3.1"
},
"dependencies": {
"@replit/crosis": "^6.0.4",
"@replit/protocol": "^0.2.16",
"@replit/crosis": "^6.3.0",
"@replit/protocol": "^0.2.28",
"graphql": "^15.4.0",
"graphql-request": "^3.4.0",
"lodash.debounce": "^4.0.8",
Expand Down
52 changes: 47 additions & 5 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import fetch from 'node-fetch';
import { GraphQLClient, gql } from 'graphql-request';
import * as vscode from 'vscode';
import { ReplInfo } from './types';
import { renderCaptchaRefresh } from './captcha';

const gqlClient = new GraphQLClient('https://replit.com/graphql/', {});
gqlClient.setHeaders({
Expand Down Expand Up @@ -67,6 +69,23 @@ const ReplInfoFromIdDoc = gql`
}
`;

const ReplPerms = gql`
query SelfInfo($replId: String!) {
currentUser {
id
username
}
repl(id: $replId) {
... on Repl {
isOwner
multiplayers {
id
username
}
}
}
}
`;
// Get a user's own repls
export const getSelfRepls = async (userSid: string, count?: number): Promise<ReplInfo[]> => {
const result = await gqlClient.request(
Expand Down Expand Up @@ -97,6 +116,26 @@ export const getSelfRepls = async (userSid: string, count?: number): Promise<Rep
return repls;
};

export const canUserEditRepl = async (userSid: string, replId: string): Promise<boolean> => {
const result = await gqlClient.request(
ReplPerms,
{ replId },
{
cookie: `connect.sid=${userSid}`,
},
);
if (result.repl.isOwner) {
return true;
};
for (let i = 0; i < result.repl.multiplayers.length; i += 1) {
const multiplayer = result.repl.multiplayers[i];
if (result.currentUser.id === multiplayer.id) {
return true;
}
};
return false;
};

async function getReplInfoByUrl(url: string, userSid?: string): Promise<ReplInfo> {
const result = await gqlClient.request(
ReplInfoFromUrlDoc,
Expand Down Expand Up @@ -166,21 +205,20 @@ export async function getReplInfo(input: string, userSid?: string): Promise<Repl

export async function fetchToken(
replId: string,
userSid: string,
captchaKey?: string,
context: vscode.ExtensionContext,
): Promise<string> {
console.log(`fetching token for ${replId}`);
const r = await fetch(`https://replit.com/data/repls/${replId}/get_connection_metadata`, {
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'Crosis 2: Electric Boogaloo (replit/@RoBlockHead)',
cookie: `connect.sid=${userSid}`,
cookie: `connect.sid=${await context.secrets.get('userSid')}`,
origin: 'https://replit.com',
'User-Agent': 'Replit VSCode Revived (replit/@RoBlockHead)',
},
method: 'POST',
body: JSON.stringify({
captcha: captchaKey,
captcha: (await context.secrets.get('captchaKey')),
clientVersion: '7561851',
format: 'pbuf',
hCaptchaSiteKey: '473079ba-e99f-4e25-a635-e9b661c7dd3e',
Expand All @@ -190,7 +228,11 @@ export async function fetchToken(

if (r.status > 399) {
if (JSON.parse(text).message?.toLowerCase().indexOf('captcha failed') !== -1) {
throw new Error(`Captcha failed, please set a captcha key. error: ${text}`);
throw new Error('yeet');
console.log('captcha refreshing...');
if (await renderCaptchaRefresh(context)) {
// return fetchToken(replId, context);
}
} else {
throw new Error(
`Repl.it: ${r.status} Error Failed to open Repl. Error: ${JSON.parse(text).message}`,
Expand Down
51 changes: 51 additions & 0 deletions src/captcha.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* eslint-disable max-len */
import * as vscode from 'vscode';

export const renderCaptchaRefresh = async (context: vscode.ExtensionContext): Promise<boolean|void> => {
const captchaWebview = vscode.window.createWebviewPanel(
'captchaWebview',
'Replit CAPTCHA Refresh',
vscode.ViewColumn.One,
{
enableScripts: true,
},
);
captchaWebview.webview.onDidReceiveMessage((message) => {
context.secrets.store('captchaKey', message);
captchaWebview.dispose();
return true;
});
captchaWebview.webview.html = `
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'unsafe-inline' ${captchaWebview.webview.cspSource} https:;">
<style>
body {
margin: 0;
border: 0;
width: 100%
}
iframe {
margin: 0;
border: 0;
width: 100%
}
</style>
</head>
<body>
<h1>Refresh your Replit CAPTCHA verification</h1>
<h3>Click the box below to refresh your human verification. This window will close when you've completed the verification.</h3>
<iframe src="https://vsc-captcha.vscode.repl.co"></iframe>
<script>
const vscode = acquireVsCodeApi();
console.log(window);
function handleMessage(message){
vscode.postMessage(message.data);
}
window.addEventListener('message', handleMessage, false);
</script>
</body>
</html>
`;
};
58 changes: 37 additions & 21 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import {
} from '@replit/crosis';
import * as vscode from 'vscode';
import ws from 'ws';
import { fetchToken, getReplInfo } from './api';
import { FS } from './fs';
import { canUserEditRepl, fetchToken, getReplInfo } from './api';
import { renderCaptchaRefresh } from './captcha';
import { FS, initFs } from './fs';
// import MultiplayerTextDocumentProvider from './multi';
// import { runRepl } from './misc';
import { Options } from './options';
import ReplitOutput from './output';
Expand Down Expand Up @@ -51,7 +53,6 @@ const getUserSid = async (
}
if (storedSid) return storedSid;
}

const newSid = await vscode.window.showInputBox({
prompt: 'Session ID',
placeHolder: 'Enter your Replit Session ID (the value of the "connect.sid" cookie)',
Expand Down Expand Up @@ -110,7 +111,6 @@ function openReplClient(
replInfo: ReplInfo,
context: vscode.ExtensionContext,
userSid: string,
captchaKey?: string,
): CrosisClient {
statusBarItem.show();
statusBarItem.text = `$(sync~spin) Replit: @${replInfo.user}/${replInfo.slug}`;
Expand Down Expand Up @@ -139,7 +139,7 @@ function openReplClient(
let govalMeta: GovalMetadata;
let res: FetchConnectionMetadataResult;
try {
govalMeta = JSON.parse(await fetchToken(replInfo.id, userSid, captchaKey));
govalMeta = JSON.parse(await fetchToken(replInfo.id, context));
res = {
...govalMeta,
error: null,
Expand Down Expand Up @@ -268,15 +268,26 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
throw e;
}

return openReplClient(replInfo, context, apiKey, captchaKey);
return openReplClient(replInfo, context, apiKey);
});

// const mpTcP = new MultiplayerTextDocumentProvider();
context.subscriptions.push(
vscode.workspace.registerFileSystemProvider('replit', fs, {
isCaseSensitive: true,
}),
);

// context.subscriptions.push(
// vscode.workspace.onDidChangeTextDocument((changeEvent) => {
// console.log(`Did change: ${changeEvent.document.uri}`);
// for (const change of changeEvent.contentChanges) {
// console.log(change.range); // range of text being replaced
// console.log(change.text); // text replacement
// }
// }),
// );
// context.subscriptions.push(
// vscode.workspace.registerTextDocumentContentProvider('replit-mp', mpTcP),
// );
context.subscriptions.push(
vscode.workspace.onDidChangeWorkspaceFolders((ev) => {
ev.removed.forEach((folder) => {
Expand All @@ -289,7 +300,19 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
});
}),
);

context.subscriptions.push(
vscode.commands.registerCommand('replit.openmptest', async () => {
const doc = await vscode.workspace.openTextDocument(
vscode.Uri.parse('replit-mp:test-feature-please-ignore'),
);
await vscode.window.showTextDocument(doc, { preview: false });
}),
);
context.subscriptions.push(
vscode.commands.registerCommand('replit.refreshcaptcha', async () => {
renderCaptchaRefresh(context);
}),
);
context.subscriptions.push(
vscode.commands.registerCommand('replit.shell', async () => {
const r = Object.values(openedRepls);
Expand Down Expand Up @@ -405,19 +428,12 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>

return vscode.window.showErrorMessage(e.message || 'Error with no message, check console');
}

// Insert the workspace folder at the end of the workspace list
// otherwise the extension gets decativated and reactivated
const { workspaceFolders } = vscode.workspace;
let start = 0;
if (workspaceFolders?.length) {
start = workspaceFolders.length;
if (!canUserEditRepl(userSid, replInfo.id)) {
vscode.window.showWarningMessage(
"You don't have permission to edit this repl, changes won't be saved.",
);
}

vscode.workspace.updateWorkspaceFolders(start, 0, {
uri: vscode.Uri.parse(`replit://${replInfo.id}/`),
name: `@${replInfo.user}/${replInfo.slug}`,
});
initFs(replInfo);
}),
);
}
Expand Down
Loading

0 comments on commit 2cb4f50

Please sign in to comment.