Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sunneydev committed Mar 15, 2022
0 parents commit 637147d
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
**/node_modules
**/build
.vscode
__pycache__
58 changes: 58 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# cookie-sync

## Description

## About

This is a simple extension that allows you to sync cookies between Chrome and Python using the [websocket](https://en.wikipedia.org/wiki/WebSocket) protocol.

## Requirements

- Python >= 3.7
- [aiohttp](https://docs.aiohttp.org/en/stable)

## Usage

1. `pip install cookie-sync`

2. Download the and unarchive the extension from [releases](https://github.com/sunney-x/cookie-sync/releases)

3. Set `host_permissions` for the target website in `manifest.json`

4. Load the extension in Chrome
- Go to `chrome://extensions`
- Click `Load unpacked` and locate the extension folder

5. Quickstart example
```python
import aiohttp
from cookie_sync import run_server

session = aiohttp.ClientSession()

run_server(
session=session,
domain='https://google.com'
)
```

## Documentation

### **run_server** configuration options

```py
session: aiohttp.ClientSession
- 'The session to keep cookies synced on'

domain: str
- 'The domain to sync cookies for'

cookies: Optional[list] # Default []
- 'List of cookies to sync, if empty, all cookies will be synced'

wait_for_cookies: Optional[bool] # Default True
- 'If `False`, will not wait for the cookies to be synced'

timeout: Optional[int] # Default 30
- 'Timeout in seconds to wait for `wait_for_cookies`'
```
1 change: 1 addition & 0 deletions cookie_sync/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .server import run_server
67 changes: 67 additions & 0 deletions cookie_sync/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import time
from aiohttp import web
from typing import Dict, List
import aiohttp
import json
import threading
import asyncio


def _run_server(
session: aiohttp.ClientSession,
cookie_names: List[str],
domain: str,
):
async def websocket_handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)

await ws.send_json({
'action': 'get',
'cookies': cookie_names,
'domain': domain,
})

async for msg in ws:
if msg.type != aiohttp.WSMsgType.TEXT:
continue

try:
cookies: List[Dict[str, str]] = msg.json()
except json.decoder.JSONDecodeError:
continue

for c in cookies:
session.cookie_jar.update_cookies(c)

return ws

app = web.Application()
app.add_routes([web.get('/ws', websocket_handler)])

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
web.run_app(app, host='localhost', port=3001)


def run_server(
session: aiohttp.ClientSession,
domain: str,
cookies: List[str] = [],
wait_for_cookies: bool = True,
timeout: int = 30,
):
threading.Thread(
target=_run_server,
args=(session, cookies, domain,),
daemon=True
).start()

if wait_for_cookies:
t = time.time()

while not len(session.cookie_jar):
if (time.time() - t) > timeout:
break

pass
11 changes: 11 additions & 0 deletions extension/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "Cookie Sync",
"description": "Synchronize cookies between chrome and Python",
"version": "0.1",
"manifest_version": 3,
"host_permissions": ["*://*.google.com/*"],
"permissions": ["cookies"],
"background": {
"service_worker": "build/sw.js"
}
}
15 changes: 15 additions & 0 deletions extension/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "cookie_sync",
"version": "0.1",
"description": "Synchronize cookies between chrome and Python",
"scripts": {
"dev": "tsc -p . --watch",
"build": "tsc -p ."
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@types/chrome": "0.0.179"
}
}
62 changes: 62 additions & 0 deletions extension/src/sw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
interface CookieRequest {
action: "get";
cookies: string[];
domain: string;
}

const neededCookies: string[] = [];
let ws: WebSocket;

const connect = () => {
const _ws = new WebSocket("ws://localhost:3001/ws");
ws = _ws;
ws.onopen = () => {
console.log("Connected! 👌");
};

ws.onmessage = async (event): Promise<void> => {
const cookieReq: CookieRequest = JSON.parse(event.data);

switch (cookieReq.action) {
case "get":
let retrievedCookies: { [key: string]: string }[] = [];

if (cookieReq.cookies.length) {
const promises = cookieReq.cookies.map((c) =>
chrome.cookies
.get({ name: c, url: cookieReq.domain })
.then((c) => c && retrievedCookies.push({ [c.name]: c.value }))
);

await Promise.all(promises);
} else {
retrievedCookies = (await chrome.cookies.getAll({})).map((c) => ({
[c.name]: c.value,
}));
}

ws.send(JSON.stringify(retrievedCookies));
}
};

ws.onclose = () => {
console.log("Disconnected! 👎");
setTimeout(connect, 10 * 1000);
};

ws.onerror = () => {
console.log("Error! 💩");
ws.close();
};
};

connect();

chrome.cookies.onChanged.addListener((c) => {
if (
c.cause === "overwrite" &&
(neededCookies.includes(c.cookie.name) || !neededCookies.length)
) {
ws.send(JSON.stringify({ [c.cookie.name]: c.cookie.value }));
}
});
14 changes: 14 additions & 0 deletions extension/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["ES2016", "DOM"],
"module": "commonjs",
"outDir": "./build",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aiohttp == 3.8.1
17 changes: 17 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from setuptools import setup


setup(
name='cookie-sync',
version='0.0.1',
description='Sync cookies between Chrome',
author='Sunney-X',
author_email='[email protected]',
url='https://github.com/Sunney-X/cookie-sync',
packages=['cookie_sync'],
long_description=open('README.md').read(),
long_description_content_type="text/markdown",
install_requires=[
"aiohttp"
],
)

0 comments on commit 637147d

Please sign in to comment.