diff options
author | Saptak S <saptak013@gmail.com> | 2020-03-08 14:51:43 +0530 |
---|---|---|
committer | Saptak S <saptak013@gmail.com> | 2020-03-08 14:51:43 +0530 |
commit | 2c938fd777d24687e38ff53a6d2e8c317cecef82 (patch) | |
tree | 83ce74538b2a97882c6dacc8d4a798941a27a680 /onionshare | |
parent | a217e54d28dd29ba1efc5314094f2b354320d69d (diff) | |
download | onionshare-2c938fd777d24687e38ff53a6d2e8c317cecef82.tar.gz onionshare-2c938fd777d24687e38ff53a6d2e8c317cecef82.zip |
Create web UI and socket code for the chat interface
Diffstat (limited to 'onionshare')
-rw-r--r-- | onionshare/__init__.py | 6 | ||||
-rw-r--r-- | onionshare/common.py | 10 | ||||
-rw-r--r-- | onionshare/mode_settings.py | 1 | ||||
-rw-r--r-- | onionshare/web/chat_mode.py | 75 | ||||
-rw-r--r-- | onionshare/web/web.py | 14 |
5 files changed, 105 insertions, 1 deletions
diff --git a/onionshare/__init__.py b/onionshare/__init__.py index 8d2077c2..fa58d859 100644 --- a/onionshare/__init__.py +++ b/onionshare/__init__.py @@ -63,6 +63,9 @@ def main(cwd=None): parser.add_argument( "--website", action="store_true", dest="website", help="Publish website" ) + parser.add_argument( + "--chat", action="store_true", dest="chat", help="Start chat server" + ) # Tor connection-related args parser.add_argument( "--local-only", @@ -172,6 +175,7 @@ def main(cwd=None): receive = bool(args.receive) website = bool(args.website) + chat = bool(args.chat) local_only = bool(args.local_only) connect_timeout = int(args.connect_timeout) config_filename = args.config @@ -190,6 +194,8 @@ def main(cwd=None): mode = "receive" elif website: mode = "website" + elif chat: + mode = "chat" else: mode = "share" diff --git a/onionshare/common.py b/onionshare/common.py index 7048c174..a4e2d8b6 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -215,6 +215,16 @@ class Common: r = random.SystemRandom() return "-".join(r.choice(wordlist) for _ in range(word_count)) + def build_username(self, word_count=2): + """ + Returns a random string made of words from the wordlist, such as "deter-trig". + """ + with open(self.get_resource_path("wordlist.txt")) as f: + wordlist = f.read().split() + + r = random.SystemRandom() + return "-".join(r.choice(wordlist) for _ in range(word_count)) + @staticmethod def random_string(num_bytes, output_len=None): """ diff --git a/onionshare/mode_settings.py b/onionshare/mode_settings.py index 9201721e..8216c1d8 100644 --- a/onionshare/mode_settings.py +++ b/onionshare/mode_settings.py @@ -49,6 +49,7 @@ class ModeSettings: "share": {"autostop_sharing": True, "filenames": []}, "receive": {"data_dir": self.build_default_receive_data_dir()}, "website": {"disable_csp": False, "filenames": []}, + "chat": {"room": "default"}, } self._settings = {} diff --git a/onionshare/web/chat_mode.py b/onionshare/web/chat_mode.py new file mode 100644 index 00000000..c81bd636 --- /dev/null +++ b/onionshare/web/chat_mode.py @@ -0,0 +1,75 @@ +import os +import tempfile +import json +from datetime import datetime +from flask import Request, request, render_template, make_response, flash, redirect, session +from werkzeug.utils import secure_filename +from flask_socketio import emit, join_room, leave_room + +from .. import strings + + +class ChatModeWeb: + """ + All of the web logic for chat mode + """ + + def __init__(self, common, web): + self.common = common + self.common.log("ChatModeWeb", "__init__") + + self.web = web + + self.can_upload = True + self.uploads_in_progress = [] + + # This tracks the history id + self.cur_history_id = 0 + + self.define_routes() + + def define_routes(self): + """ + The web app routes for chatting + """ + + @self.web.app.route("/") + def index(): + history_id = self.cur_history_id + self.cur_history_id += 1 + self.web.add_request( + self.web.REQUEST_INDIVIDUAL_FILE_STARTED, + request.path, + {"id": history_id, "status_code": 200}, + ) + + self.web.add_request(self.web.REQUEST_LOAD, request.path) + r = make_response( + render_template( + "chat.html", static_url_path=self.web.static_url_path + ) + ) + return self.web.add_security_headers(r) + + @self.web.socketio.on("joined", namespace="/chat") + def joined(message): + """Sent by clients when they enter a room. + A status message is broadcast to all people in the room.""" + session["name"] = self.common.build_username() + session["room"] = self.web.settings.default_settings["chat"]["room"] + join_room(session.get("room")) + emit( + "status", + {"msg": session.get("name") + " has entered the room."}, + room=session.get("room") + ) + + @self.web.socketio.on("text", namespace="/chat") + def text(message): + """Sent by a client when the user entered a new message. + The message is sent to all people in the room.""" + emit( + "message", + {"msg": session.get("name") + ": " + message["msg"]}, + room=session.get("room") + ) diff --git a/onionshare/web/web.py b/onionshare/web/web.py index 8582e694..3a22c789 100644 --- a/onionshare/web/web.py +++ b/onionshare/web/web.py @@ -20,12 +20,14 @@ from flask import ( __version__ as flask_version, ) from flask_httpauth import HTTPBasicAuth +from flask_socketio import SocketIO from .. import strings from .share_mode import ShareModeWeb from .receive_mode import ReceiveModeWeb, ReceiveModeWSGIMiddleware, ReceiveModeRequest from .website_mode import WebsiteModeWeb +from .chat_mode import ChatModeWeb # Stub out flask's show_server_banner function, to avoiding showing warnings that # are not applicable to OnionShare @@ -134,12 +136,17 @@ class Web: self.share_mode = None self.receive_mode = None self.website_mode = None + self.chat_mode = None if self.mode == "share": self.share_mode = ShareModeWeb(self.common, self) elif self.mode == "receive": self.receive_mode = ReceiveModeWeb(self.common, self) elif self.mode == "website": self.website_mode = WebsiteModeWeb(self.common, self) + elif self.mode == "chat": + self.socketio = SocketIO() + self.socketio.init_app(self.app) + self.chat_mode = ChatModeWeb(self.common, self) def get_mode(self): if self.mode == "share": @@ -148,6 +155,8 @@ class Web: return self.receive_mode elif self.mode == "website": return self.website_mode + elif self.mode == "chat": + return self.chat_mode else: return None @@ -366,7 +375,10 @@ class Web: host = "127.0.0.1" self.running = True - self.app.run(host=host, port=port, threaded=True) + if self.mode == "chat": + self.socketio.run(self.app, host=host, port=port) + else: + self.app.run(host=host, port=port, threaded=True) def stop(self, port): """ |