├── .gitignore ├── favicon.ico ├── .readme-assets └── janus-logo.png ├── check_curl.sh ├── package.json ├── local-webrtc-backend ├── run-page.js └── page.html ├── README.md └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .*.swp 3 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crisdosaygo/janus/HEAD/favicon.ico -------------------------------------------------------------------------------- /.readme-assets/janus-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crisdosaygo/janus/HEAD/.readme-assets/janus-logo.png -------------------------------------------------------------------------------- /check_curl.sh: -------------------------------------------------------------------------------- 1 | curl -v -H "Authorization: token $GH_ACCESS_TOKEN" \ 2 | -H "Accept: application/vnd.github.v3+json" \ 3 | "https://api.github.com/repos/00000o1/janus/issues?since=$(date --utc +%Y-%m-%dT%H:%M:%SZ)&state=open" 4 | 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "playwright": "^1.39.0" 4 | }, 5 | "name": "janus", 6 | "description": "### Description:", 7 | "version": "1.0.0", 8 | "main": "local-webrtc-backend/run-page.js", 9 | "devDependencies": {}, 10 | "scripts": { 11 | "test": "node local-webrtc-backend/run-page.js", 12 | "postinstall": "npx playwright install" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/00000o1/janus.git" 17 | }, 18 | "keywords": [ 19 | "janues", 20 | "p2p", 21 | "blog", 22 | "p2p", 23 | "chat", 24 | "webrtc", 25 | "github", 26 | "develop" 27 | ], 28 | "author": "@dosy", 29 | "license": "Apache-2.0", 30 | "bugs": { 31 | "url": "https://github.com/00000o1/janus/issues" 32 | }, 33 | "homepage": "https://github.com/00000o1/janus#readme" 34 | } 35 | -------------------------------------------------------------------------------- /local-webrtc-backend/run-page.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const os = require('os'); 4 | const fs = require('fs').promises; 5 | const path = require('path'); 6 | const { chromium } = require('playwright'); 7 | const readline = require('readline'); 8 | 9 | // Set up readline interface 10 | const rl = readline.createInterface({ 11 | input: process.stdin, 12 | output: process.stdout, 13 | prompt: 'chat> ' 14 | }); 15 | 16 | (async () => { 17 | if ( ! process.env.GH_ACCESS_TOKEN || ! process.env.REPO_URL ) { 18 | console.error(`You need to set GH_ACCESS_TOKEN and REPO_URL environment variables so this script can poll for and write comments at your repo.`); 19 | return process.exit(1); 20 | } 21 | 22 | const tempDir = await createTempDir(); 23 | const browser = await chromium.launchPersistentContext(tempDir, { 24 | headless: true, 25 | args: [ 26 | `--disable-web-security`, // disable CORS to make requests to GH API to poll 27 | `--enable-local-file-access`, // enable file access to blog files 28 | ] 29 | }); 30 | const page = await browser.newPage(); 31 | 32 | page.on('console', message => { 33 | const text = message.text(); 34 | if (text.startsWith('CHAT_MSG')) { 35 | // Extracts the username and message from the formatted string 36 | const chatMessage = text.match(/^CHAT_MSG \[(.*?)\]: (.*)$/); 37 | if (chatMessage && chatMessage.length >= 3) { 38 | console.log(`${chatMessage[1]} says: ${chatMessage[2]}`); 39 | } 40 | } else { 41 | console.log('PAGE LOG:', text); 42 | } 43 | rl.prompt(); 44 | }); 45 | page.on('pageerror', error => { 46 | console.warn(`PAGE ERROR: `, error); 47 | }); 48 | 49 | const { 50 | GH_ACCESS_TOKEN, 51 | REPO_URL 52 | } = process.env; 53 | const filePath = path.resolve(process.cwd(), 'local-webrtc-backend', 'page.html'); 54 | const creds = JSON.stringify({GH_ACCESS_TOKEN, REPO_URL}); 55 | const fileUrl = `file://${filePath}?ghCreds=${encodeURIComponent(creds)}`; 56 | await page.goto(fileUrl); 57 | 58 | rl.prompt(); 59 | 60 | process.on('SIGINT', cleanupNow); 61 | 62 | // Listen to command line input 63 | rl.on('line', async (line) => { 64 | const trimmedLine = line.trim(); 65 | if (trimmedLine.startsWith('reply ') || trimmedLine.startsWith('@')) { 66 | const [command, ...messageParts] = trimmedLine.split(' '); 67 | let ghUsername; 68 | if ( command.startsWith('@') ) { 69 | ghUsername = command.slice(1); 70 | } else { 71 | ghUsername = messageParts.shift(); 72 | } 73 | const message = messageParts.join(' '); 74 | await page.evaluate(({ghUsername, message}) => globalThis.sendMessageToClient(ghUsername, message), {ghUsername, message}); 75 | } else if (trimmedLine === 'list') { 76 | const handles = await page.evaluate(() => Object.keys(clients)); 77 | console.log(`Connected clients: ${handles}`); 78 | } else if ( trimmedLine == 'quit' ) { 79 | await cleanupNow(); 80 | return; 81 | } else if ( trimmedLine.startsWith('kick') ) { 82 | const [command, handle] = trimmedLine.split(' '); 83 | await page.evaluate(handle => clients?.[handle]?.destroy?.(), handle); 84 | } else if ( trimmedLine.startsWith('ban') ) { 85 | const [command, handle] = trimmedLine.split(' '); 86 | await page.evaluate(handle => banList.add(handle), handle); 87 | await page.evaluate(handle => clients?.[handle]?.destroy?.(), handle); 88 | } else if ( trimmedLine == 'help' ) { 89 | console.log(`Available commands: help, reply | @, list, quit, kick, ban`); 90 | } else { 91 | console.log('Unknown command.'); 92 | } 93 | rl.prompt(); 94 | }); 95 | 96 | return await new Promise(resolve => 0); // Keep the script running 97 | 98 | async function cleanupNow() { 99 | console.log('Closing browser due to Ctrl+C'); 100 | setTimeout(() => rl.close(), 0); 101 | await browser.close(); 102 | await cleanupTempUserDataDir(tempDir); 103 | process.exit(0); 104 | } 105 | })(); 106 | 107 | async function cleanupTempUserDataDir(tempDir) { 108 | await fs.rm(tempDir, { 109 | recursive: true, 110 | force: true 111 | }); 112 | } 113 | 114 | async function createTempDir() { 115 | const tmpBaseDir = os.tmpdir(); 116 | const prefix = 'dosyago.janus_'; // Replace 'yourPrefix_' with your desired prefix 117 | 118 | try { 119 | const tmpDir = await fs.mkdtemp(path.join(tmpBaseDir, prefix)); 120 | return tmpDir; 121 | } catch (err) { 122 | console.error('Failed to create temporary directory:', err); 123 | throw err; // Re-throw the error if necessary 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **💎 Demo of WebRTC signalling occuring on GH comments:** https://github.com/00000o1/janus/issues/68 2 | 3 | Janus Logo 4 | 5 | ## Janus - Simple P2P Blog and Developer P2P Chat on GitHub 6 | 7 | Janus combines WebRTC's peer-to-peer capabilities with GitHub's API to create a unique platform for developer collaboration. This tool allows developers to host a P2P blog and chat from their terminal and engage in chat sessions directly from GitHub, offering a new approach to collaboration and real-time communication. 8 | 9 | It began as a crazy experiment to answer the question: *What about a P2P blog?* 10 | 11 | As it developed, interest also grew in the question: *How much can the friction of a human-mediated signaling channel in WebRTC be reduced?* 12 | 13 | Check it out. Many simple affordances have been provided to make establishing a P2P connection using issue comments as the signaling method as friction-free as possible. 14 | 15 | ### What is Janus? 16 | 17 | Apart from being [a Roman God associated with doors, gates, transitions, beginnings, time, duality, passages, frames, and endings](https://en.wikipedia.org/wiki/Janus), Janus serves blog content, and chat, over a P2P connection. You can add blog content to the blog section in `./local-webrtc-backend/page.html` 18 | 19 | Janus is all about facilitating direct, real-time interactions between developers. By running a simple HTML page (`page.html`) as a WebRTC server that handles a blog and chat, you can establish live chats with other developers who initiate contact through GitHub issues. 20 | 21 | If you run a Janus back-end chat messages reach you in the terminal and that's where you respond to them. For connecting clients, they chat through a static web interface on GitHub pages. 22 | 23 | This seamless integration with GitHub issues makes Janus a unique tool for developers looking for a decentralized, in-band method of collaboration. 24 | 25 | ### Features at a Glance: 26 | 27 | - **P2P Blog**: Share your thoughts and updates directly from your machine to your audience's browser. 28 | - **Developer Chat**: Engage in real-time chat with anyone who opens (or re-opens) an issue in your Janus-enabled repository when you're running the backend. 29 | - **GitHub API Integration**: Uses GitHub issues as a novel way to initiate and manage P2P connections. 30 | 31 | ### Getting Started with Janus: 32 | 33 | #### Setup 34 | 35 | 1. Clone the Janus repository, and switch on GitHub pages. 36 | 2. Locally set up environment variables `GH_ACCESS_TOKEN` and `REPO_URL`. 37 | 3. **[optional]** Add an **Office Hours: ** line to the top of your README (or to a pinned issue) indicating when you'll be online to chat (erm, unless it's always :laughing:) 38 | 39 | Please note, the access token should be a GitHub Personal Access Token scoped to the specific repo of your Janus fork and provided with repository read, and issues read & write access. You can create such tokens under the Developer Settings tab in your GitHub profile settings. 40 | 41 | #### Running Janus 42 | 43 | 1. Start the `./local-webrtc-backend/run-page.js` script. 44 | 2. The script polls your repository for new issues, facilitating P2P connections for chat and blog content sharing. Every open issue is treated as a chat request when you are running the janus backend. 45 | 46 | #### Interacting with Janus 47 | 48 | - **Blog Content**: Write and serve your blog content through `./local-webrtc-backend/page.html`. 49 | - **Chat Interface**: Access the chat through the command line interface provided by `run-page.js`. 50 | 51 | ### Chat Interface Commands 52 | 53 | - **`list`**: list connected clients 54 | - **`reply <... your message...>`**: reply to a connected user 55 | - **`@ <... your message...>`**: alias for reply 56 | - **`quit`**: exit and shutdown janus back-end. *Please note: sometimes you might need to combine `quit` with `Ctrl-C`* 57 | - **`help`**: display commands 58 | - **`kick `**: disconnect a user 59 | - **`ban `**: ban a user for this session 60 | 61 | *Note: for perma-bans we suggest using GitHub's block capability. That will prevent users from opening issues in your repository.* 62 | 63 | ### Hot Tips & Info: Maximizing Janus 64 | 65 | To help you make the most of Janus, here's a quick executive summary of key points: 66 | 67 | 1. **Running Janus**: As a project maintainer, simply run the backend following the instructions provided here. It's been tested on MacOS and Debian. It's basically just single file node app, check out the code to learn mode. For other developers seeking to chat with the maintainer, open (or re-open) an issue when the maintainer is available for chat. A chat post link will be generated in the issue, which, when clicked, opens the chat in your browser, connecting you with the maintainer. 68 | 69 | 2. **Practical Applications of Janus**: 70 | - **Project Office Hours**: Schedule regular times for open discussion, creating a personal and private environment for project-related conversations. 71 | - **Project Support Chat**: Offer an alternative to traditional issue tracking for private, ephemeral conversations regarding project support. 72 | - **Remote Pairing and GitHub Socializing**: Leverage Janus for remote collaboration or to connect with inspiring GitHub community members in a more personal and instantaneous manner. 73 | - **Secure, Non-cloud Hosted Communication**: Ideal for sensitive information exchange, like API keys or banking details, providing a secure channel beyond the reach of traditional cloud services. 74 | - **Anonymous Chat**: For those requiring a level of anonymity, Janus offers a platform where users can chat without revealing personal or organizational identities, while still tied to their GitHub accounts. 75 | 76 | 3. **Authentication and Security**: Janus is designed with security at its core. The connection is initiated exclusively by the account that opens the issue, preventing impersonation. Additionally, GitHub's blocking features are integrated, allowing repository owners to prevent unwanted chat requests. 77 | 78 | 4. **Troubleshooting**: Becuase of the nature of WebRTC in some cases (some networks, devices, OSes) it may not be possible to establish a P2P connection. In those cases Janus will not work! 79 | 80 | ### Exciting New Features on the Horizon for Janus! 81 | 82 | As we continue to innovate with Janus, our focus remains on enhancing the GitHub collaboration experience. We're thrilled to share a sneak peek into some of the potential features that might find their way into future versions of Janus: 83 | 84 | 1. **Namespaced Chat**: We're exploring the possibility of introducing namespaced chat. This feature would allow users to seamlessly transition into a dedicated chat namespace with another user, simplifying one-on-one communication. Just imagine, no more repetitive tagging in each message. Jump in and out of chat rooms with ease – a perfect blend of convenience and functionality. 85 | 86 | 2. **Multi-User Rooms**: While Janus primarily facilitates one-on-one interactions, akin to phone calls, we recognize the value of group discussions. Hence, we're considering the addition of multi-user rooms for those occasional 'conference calls' within the GitHub ecosystem. 87 | 88 | We're happy to review contributions in these areas for possible inclusion! Of course, you're free to modify your own version to suit your needs. 89 | 90 | ### What is P2P ? 91 | 92 | P2P means point-to-point, and it indicates a direct connection between parties, that avoids going through any intermediate servers like a regular centralized chat service. In Janus, P2P is enabled by WebRTC data channels. While there are some edge cases that go through servers that help to route the traffic, in most cases P2P via WebRTC is a direct message channel between the two parties. It's also worth remembering that WebRTC is encrypted and secure. 93 | 94 | ### Why Janus? An In-Band GitHub Solution: 95 | 96 | We've observed the frequent need for real-time collaboration in open-source projects, often leading developers off-site to external platforms. Janus seeks to eliminate this diversion, offering an on-site, in-band solution that's simple, empowering, and decentralized. 97 | 98 | Our vision extends beyond mere chatting. Imagine sending and receiving files, collaborating on code directly through this platform, or even integrating collaborative editors. The possibilities are limitless! 99 | 100 | Though we're unaffiliated with GitHub, we dream of a day when GitHub embraces Janus, providing a dedicated API endpoint to streamline the user experience. Imagine P2P developer chat as a first-class citizen on GitHub - enhancing productivity, happiness, and the overall developer experience. 101 | 102 | ### Dreaming Bigger 103 | 104 | Our vision for Janus extends into realms yet unexplored. From file transfers, direct code collaboration, to integrating collaborative editors – the potential is limitless. Unaffiliated with GitHub, we nonetheless aspire to a future where Janus and GitHub are more closely intertwined, with dedicated API support to enhance this unique developer experience. 105 | 106 | Stay tuned for more updates as we continue to shape the future of GitHub collaboration with Janus! 🚀💻🌐 107 | 108 | ### Future Directions: 109 | 110 | Janus is an evolving project with goals to expand its capabilities, including file sharing for code collaboration and broader repository support. We aim to streamline the developer experience on GitHub, making P2P interaction a natural part of the platform. 111 | 112 | ### Contributing to Janus 113 | 114 | Your contributions can help shape the future of Janus. Whether it's code, ideas, or feedback, we welcome your input. 115 | 116 | Janus is more than just a tool; it's a step towards a more connected and interactive open-source community. Join us in this exciting journey to reshape developer collaboration on GitHub. 117 | 118 | #### Cool Unaffiliated Projects also called Janus 119 | 120 | Serendipitously there is another pre-existing WebRTC project called Janus: [Janus-Gatway WebRTC Server is an open source, general purpose, WebRTC server designed and developed by Meetecho - the RTC experts.](https://github.com/meetecho/janus-gateway). While we don't know anything about them, they're popular and it's cool they use the same name. You should check them out! :) 121 | 122 | ----- 123 | 124 | **Like WebRTC? You might be interested in another project I work on that uses it: [BrowserBox/BrowserBox - a remote browser](https://github.com/BrowserBox/BrowserBox)** Reach out: [Email us](mailto:cris@dosyago.com) 125 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Janus - P2P Blog & Chat 8 | 9 | 100 | 101 | 102 |
Generating your p2p locator...
103 |
104 |
105 |
106 |
107 | 108 |
109 | 110 | 111 |
112 |
113 |
114 | 122 | 375 | 376 | 377 | 378 | -------------------------------------------------------------------------------- /local-webrtc-backend/page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebRTC Server Page 6 | 7 | 8 | 9 |

WebRTC 'Server'

10 |
11 | 12 | 29 |
30 |

Exploring the Mysteries of UFOs

31 |

Written by AI: Unidentified Flying Objects have always stirred the curiosity of humankind. Are we alone in the universe or is there life beyond our planet?...

32 |
33 |
34 |

The Joy of Cooking

35 |

Written by AI: Cooking is not just a necessity; it's an art. Exploring different cuisines opens up a world of flavors and experiences...

36 |
37 |
38 |

Latest Gadgets in Tech

39 |

Written by AI: The world of technology is ever-evolving, and the latest gadgets offer a glimpse into the future. From AI-driven devices to smart home systems...

40 |
41 |
42 |

Best Books to Read This Year

43 |

Written by AI: Whether you're into fiction, non-fiction, or anything in between, there's always a good book waiting to be read. Here are some top picks for the year...

44 |
45 |
46 |

Traveling the World

47 |

Written by AI: Traveling opens up new horizons, offering a glimpse into diverse cultures, landscapes, and experiences. Let's explore some must-visit destinations...

48 |
49 |
50 |

Developer Topics: Staying Ahead

51 |

Written by AI: In the ever-changing world of software development, staying updated with the latest trends and technologies is key. Let's dive into some important topics for developers...

52 |
53 |
54 | 353 | 354 | 355 | 356 | --------------------------------------------------------------------------------