onionshare_cli 2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- onionshare_cli/__init__.py +522 -0
- onionshare_cli/common.py +296 -0
- onionshare_cli/mode_settings.py +146 -0
- onionshare_cli/onion.py +845 -0
- onionshare_cli/onionshare.py +110 -0
- onionshare_cli/resources/static/css/style.css +393 -0
- onionshare_cli/resources/static/img/ajax.gif +0 -0
- onionshare_cli/resources/static/img/favicon.ico +0 -0
- onionshare_cli/resources/static/img/logo.png +0 -0
- onionshare_cli/resources/static/img/logo_large.png +0 -0
- onionshare_cli/resources/static/img/web_file.png +0 -0
- onionshare_cli/resources/static/img/web_folder.png +0 -0
- onionshare_cli/resources/static/js/chat.js +173 -0
- onionshare_cli/resources/static/js/jquery-3.5.1.min.js +2 -0
- onionshare_cli/resources/static/js/receive.js +130 -0
- onionshare_cli/resources/static/js/send.js +75 -0
- onionshare_cli/resources/static/js/socket.io.min.js +3 -0
- onionshare_cli/resources/templates/401.html +21 -0
- onionshare_cli/resources/templates/403.html +21 -0
- onionshare_cli/resources/templates/404.html +21 -0
- onionshare_cli/resources/templates/405.html +21 -0
- onionshare_cli/resources/templates/chat.html +46 -0
- onionshare_cli/resources/templates/denied.html +14 -0
- onionshare_cli/resources/templates/listing.html +59 -0
- onionshare_cli/resources/templates/receive.html +46 -0
- onionshare_cli/resources/templates/send.html +69 -0
- onionshare_cli/resources/templates/thankyou.html +27 -0
- onionshare_cli/resources/torrc_template +8 -0
- onionshare_cli/resources/torrc_template-meek_lite_amazon +2 -0
- onionshare_cli/resources/torrc_template-meek_lite_azure +2 -0
- onionshare_cli/resources/torrc_template-obfs4 +27 -0
- onionshare_cli/resources/version.txt +1 -0
- onionshare_cli/resources/wordlist.txt +7776 -0
- onionshare_cli/settings.py +201 -0
- onionshare_cli/web/__init__.py +21 -0
- onionshare_cli/web/chat_mode.py +169 -0
- onionshare_cli/web/receive_mode.py +488 -0
- onionshare_cli/web/send_base_mode.py +338 -0
- onionshare_cli/web/share_mode.py +406 -0
- onionshare_cli/web/web.py +424 -0
- onionshare_cli/web/website_mode.py +123 -0
- onionshare_cli-2.3.dist-info/METADATA +34 -0
- onionshare_cli-2.3.dist-info/RECORD +45 -0
- onionshare_cli-2.3.dist-info/WHEEL +4 -0
- onionshare_cli-2.3.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
OnionShare | https://onionshare.org/
|
|
4
|
+
|
|
5
|
+
Copyright (C) 2014-2020 Micah Lee, et al. <micah@micahflee.com>
|
|
6
|
+
|
|
7
|
+
This program is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU General Public License as published by
|
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
This program is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU General Public License
|
|
18
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import os, shutil
|
|
22
|
+
|
|
23
|
+
from . import common
|
|
24
|
+
from .common import AutoStopTimer
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class OnionShare(object):
|
|
28
|
+
"""
|
|
29
|
+
OnionShare is the main application class. Pass in options and run
|
|
30
|
+
start_onion_service and it will do the magic.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, common, onion, local_only=False, autostop_timer=0):
|
|
34
|
+
self.common = common
|
|
35
|
+
|
|
36
|
+
self.common.log("OnionShare", "__init__")
|
|
37
|
+
|
|
38
|
+
# The Onion object
|
|
39
|
+
self.onion = onion
|
|
40
|
+
|
|
41
|
+
self.hidserv_dir = None
|
|
42
|
+
self.onion_host = None
|
|
43
|
+
self.port = None
|
|
44
|
+
|
|
45
|
+
# files and dirs to delete on shutdown
|
|
46
|
+
self.cleanup_filenames = []
|
|
47
|
+
|
|
48
|
+
# do not use tor -- for development
|
|
49
|
+
self.local_only = local_only
|
|
50
|
+
|
|
51
|
+
# optionally shut down after N hours
|
|
52
|
+
self.autostop_timer = autostop_timer
|
|
53
|
+
# init auto-stop timer thread
|
|
54
|
+
self.autostop_timer_thread = None
|
|
55
|
+
|
|
56
|
+
def choose_port(self):
|
|
57
|
+
"""
|
|
58
|
+
Choose a random port.
|
|
59
|
+
"""
|
|
60
|
+
try:
|
|
61
|
+
self.port = self.common.get_available_port(17600, 17650)
|
|
62
|
+
except:
|
|
63
|
+
raise OSError("Cannot find an available OnionShare port")
|
|
64
|
+
|
|
65
|
+
def start_onion_service(self, mode, mode_settings, await_publication=True):
|
|
66
|
+
"""
|
|
67
|
+
Start the onionshare onion service.
|
|
68
|
+
"""
|
|
69
|
+
self.common.log("OnionShare", "start_onion_service")
|
|
70
|
+
|
|
71
|
+
if not self.port:
|
|
72
|
+
self.choose_port()
|
|
73
|
+
|
|
74
|
+
if self.autostop_timer > 0:
|
|
75
|
+
self.autostop_timer_thread = AutoStopTimer(self.common, self.autostop_timer)
|
|
76
|
+
|
|
77
|
+
if self.local_only:
|
|
78
|
+
self.onion_host = f"127.0.0.1:{self.port}"
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
self.onion_host = self.onion.start_onion_service(
|
|
82
|
+
mode, mode_settings, self.port, await_publication
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if mode_settings.get("general", "client_auth"):
|
|
86
|
+
self.auth_string = self.onion.auth_string
|
|
87
|
+
|
|
88
|
+
def stop_onion_service(self, mode_settings):
|
|
89
|
+
"""
|
|
90
|
+
Stop the onion service
|
|
91
|
+
"""
|
|
92
|
+
self.onion.stop_onion_service(mode_settings)
|
|
93
|
+
|
|
94
|
+
def cleanup(self):
|
|
95
|
+
"""
|
|
96
|
+
Shut everything down and clean up temporary files, etc.
|
|
97
|
+
"""
|
|
98
|
+
self.common.log("OnionShare", "cleanup")
|
|
99
|
+
|
|
100
|
+
# Cleanup files
|
|
101
|
+
try:
|
|
102
|
+
for filename in self.cleanup_filenames:
|
|
103
|
+
if os.path.isfile(filename):
|
|
104
|
+
os.remove(filename)
|
|
105
|
+
elif os.path.isdir(filename):
|
|
106
|
+
shutil.rmtree(filename)
|
|
107
|
+
except:
|
|
108
|
+
# Don't crash if file is still in use
|
|
109
|
+
pass
|
|
110
|
+
self.cleanup_filenames = []
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
.clearfix:after {
|
|
2
|
+
content: ".";
|
|
3
|
+
display: block;
|
|
4
|
+
clear: both;
|
|
5
|
+
visibility: hidden;
|
|
6
|
+
line-height: 0;
|
|
7
|
+
height: 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
margin: 0;
|
|
12
|
+
font-family: Helvetica, sans-serif;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.d-flex {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-wrap: wrap;
|
|
18
|
+
justify-content: space-between;
|
|
19
|
+
align-items: center;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
header {
|
|
23
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
|
24
|
+
background: #fcfcfc;
|
|
25
|
+
background: -webkit-linear-gradient(top, #fcfcfc 0%, #f2f2f2 100%);
|
|
26
|
+
padding: 0.8rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
header .logo {
|
|
30
|
+
vertical-align: middle;
|
|
31
|
+
width: 45px;
|
|
32
|
+
height: 45px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
header h1 {
|
|
36
|
+
display: inline-block;
|
|
37
|
+
margin: 0 0 0 0.5rem;
|
|
38
|
+
vertical-align: middle;
|
|
39
|
+
font-weight: normal;
|
|
40
|
+
font-size: 1.5rem;
|
|
41
|
+
color: #666666;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
header .information {
|
|
45
|
+
font-size: 1rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.button {
|
|
49
|
+
color: #ffffff;
|
|
50
|
+
background-color: #4e064f;
|
|
51
|
+
padding: 10px;
|
|
52
|
+
border: 0;
|
|
53
|
+
border-radius: 5px;
|
|
54
|
+
text-decoration: none;
|
|
55
|
+
margin-left: 1rem;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
a.button:visited {
|
|
60
|
+
color: #ffffff;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.close-button {
|
|
64
|
+
color: #ffffff;
|
|
65
|
+
background-color: #c90c0c;
|
|
66
|
+
padding: 10px;
|
|
67
|
+
border: 0;
|
|
68
|
+
border-radius: 5px;
|
|
69
|
+
text-decoration: none;
|
|
70
|
+
margin-left: 1rem;
|
|
71
|
+
cursor: pointer;
|
|
72
|
+
position: absolute;
|
|
73
|
+
right: 10px;
|
|
74
|
+
bottom: 10px;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
ul.breadcrumbs {
|
|
78
|
+
display: block;
|
|
79
|
+
list-style: none;
|
|
80
|
+
margin: 10px 0;
|
|
81
|
+
padding: 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
ul.breadcrumbs li {
|
|
85
|
+
display: inline-block;
|
|
86
|
+
list-style: none;
|
|
87
|
+
margin: 0;
|
|
88
|
+
padding: 5px;
|
|
89
|
+
color: #999999;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
ul.breadcrumbs li span.sep {
|
|
93
|
+
padding-left: 5px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
ul.breadcrumbs li a:link, ul.breadcrumbs li a:visited {
|
|
97
|
+
color: #666666;
|
|
98
|
+
border-bottom: 1px solid #666666;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.file-list {
|
|
102
|
+
width: 100%;
|
|
103
|
+
margin: 0 auto;
|
|
104
|
+
border-collapse: collapse;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.file-list .heading {
|
|
108
|
+
text-align: left;
|
|
109
|
+
text-transform: uppercase;
|
|
110
|
+
font-weight: normal;
|
|
111
|
+
color: #666666;
|
|
112
|
+
padding: 0.5rem;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.file-list div.d-flex {
|
|
116
|
+
border-bottom: 1px solid #e0e0e0;
|
|
117
|
+
justify-content: flex-start;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.file-list div.d-flex div {
|
|
121
|
+
white-space: nowrap;
|
|
122
|
+
padding: 0.5rem 0.8rem 0.5rem 0.8rem;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.file-list div.d-flex div img {
|
|
126
|
+
vertical-align: middle;
|
|
127
|
+
margin-right: 0.5rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.file-list div.d-flex div:last-child {
|
|
131
|
+
padding-right: 0.8rem;
|
|
132
|
+
flex-basis: 0;
|
|
133
|
+
flex-grow: 1;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.file-list div.d-flex div:first-child {
|
|
137
|
+
flex-basis: 0;
|
|
138
|
+
flex-grow: 2;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@media (max-width: 950px) {
|
|
142
|
+
.file-list div.d-flex div:last-child {
|
|
143
|
+
flex-basis: auto;
|
|
144
|
+
flex-grow: 0;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@media (max-width: 655px) {
|
|
149
|
+
.file-list div.d-flex {
|
|
150
|
+
display: block;
|
|
151
|
+
}
|
|
152
|
+
.file-list div.d-flex span {
|
|
153
|
+
max-width: 100%;
|
|
154
|
+
word-break: break-all;
|
|
155
|
+
white-space: normal;
|
|
156
|
+
}
|
|
157
|
+
.file-list div.d-flex #size-header {
|
|
158
|
+
display: none;
|
|
159
|
+
}
|
|
160
|
+
.file-list div.d-flex div:last-child {
|
|
161
|
+
padding-left: 3.5rem;
|
|
162
|
+
font-size: 0.85rem;
|
|
163
|
+
padding-top: 0;
|
|
164
|
+
}
|
|
165
|
+
header .information {
|
|
166
|
+
padding: 1rem 0;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.chat-container {
|
|
171
|
+
display: flex;
|
|
172
|
+
font-family: monospace;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.chat-users {
|
|
176
|
+
width: 20%;
|
|
177
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
178
|
+
border-radius: 2px;
|
|
179
|
+
overflow: auto;
|
|
180
|
+
background: #f2f2f2;
|
|
181
|
+
margin: 1rem 0 1rem 1rem;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.chat-users .editable-username {
|
|
185
|
+
display: flex;
|
|
186
|
+
padding: 1rem;
|
|
187
|
+
flex-direction: column;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.chat-users .editable-username input {
|
|
191
|
+
font-family: monospace;
|
|
192
|
+
font-size: 1em;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.chat-users .editable-username #username-error {
|
|
196
|
+
color: #c90c0c;
|
|
197
|
+
margin: 0.5rem;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.chat-users #user-list li {
|
|
201
|
+
margin-bottom: 1em;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.chat-wrapper {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex-direction: column;
|
|
207
|
+
flex: 1;
|
|
208
|
+
margin: 1rem 1rem 0 1rem;
|
|
209
|
+
height: calc(100vh - (65px + 2em));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.chat-wrapper #chat {
|
|
213
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
214
|
+
border-radius: 2px;
|
|
215
|
+
flex: 1;
|
|
216
|
+
overflow: auto;
|
|
217
|
+
background: #f2f2f2;
|
|
218
|
+
padding: 0 1rem;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.chat-wrapper .status {
|
|
222
|
+
font-style: italic;
|
|
223
|
+
font-size: 0.8em;
|
|
224
|
+
color: #666666;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.chat-wrapper .username {
|
|
228
|
+
font-weight: bold;
|
|
229
|
+
display: block;
|
|
230
|
+
}
|
|
231
|
+
.chat-wrapper .message {
|
|
232
|
+
font-weight: normal;
|
|
233
|
+
display: block;
|
|
234
|
+
margin-bottom: 0.3em;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.chat-wrapper .chat-form {
|
|
238
|
+
display: block;
|
|
239
|
+
margin: 0.2rem 1rem 1rem 0;
|
|
240
|
+
padding: -0.5em;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.chat-wrapper input#new-message {
|
|
244
|
+
height: 100%;
|
|
245
|
+
width: 100%;
|
|
246
|
+
font-family: monospace;
|
|
247
|
+
font-size: 1em;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
@media (max-width: 992px) {
|
|
251
|
+
.chat-users .editable-username {
|
|
252
|
+
display: block;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.chat-users input#username {
|
|
256
|
+
width: 90%;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.no-js {
|
|
261
|
+
display: none;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.upload-wrapper {
|
|
265
|
+
align-items: center;
|
|
266
|
+
justify-content: center;
|
|
267
|
+
min-height: 400px;
|
|
268
|
+
text-align: center;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.upload-wrapper img.logo {
|
|
272
|
+
width: 120px;
|
|
273
|
+
height: 120px;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.upload-wrapper .upload-header {
|
|
277
|
+
font-size: 30px;
|
|
278
|
+
font-weight: normal;
|
|
279
|
+
color: #666666;
|
|
280
|
+
margin: 0 0 10px 0;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.upload-wrapper .upload-description {
|
|
284
|
+
color: #666666;
|
|
285
|
+
margin: 0 0 20px 0;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
div#uploads {
|
|
289
|
+
width: 800px;
|
|
290
|
+
max-width: 90%;
|
|
291
|
+
margin: 0 auto;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
div#uploads .upload {
|
|
295
|
+
border: 1px solid #DDDDDD;
|
|
296
|
+
margin: 20px 0;
|
|
297
|
+
padding: 10px;
|
|
298
|
+
text-align: left;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
div#uploads .upload .upload-filename {
|
|
302
|
+
font-weight: bold;
|
|
303
|
+
font-family: monospace;
|
|
304
|
+
font-size: 1.1em;
|
|
305
|
+
margin-bottom: 5px;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
div#uploads .upload .upload-status {
|
|
309
|
+
color: #999999;
|
|
310
|
+
font-size: 0.9em;
|
|
311
|
+
margin-bottom: 5px;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
div#uploads .upload input.cancel {
|
|
315
|
+
color: #d0011b;
|
|
316
|
+
border: 0;
|
|
317
|
+
background: none;
|
|
318
|
+
box-shadow: none;
|
|
319
|
+
border-radius: 0px;
|
|
320
|
+
cursor: pointer;
|
|
321
|
+
font-family: sans-serif;
|
|
322
|
+
font-size: 12px;
|
|
323
|
+
text-decoration: none;
|
|
324
|
+
display: inline-block;
|
|
325
|
+
float:right;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
div#uploads .upload progress {
|
|
329
|
+
width: 100%;
|
|
330
|
+
height: 20px;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
ul.flashes {
|
|
334
|
+
list-style: none;
|
|
335
|
+
margin: 0;
|
|
336
|
+
padding: 0;
|
|
337
|
+
width: 800px;
|
|
338
|
+
max-width: 100%;
|
|
339
|
+
margin: 0 auto;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
ul.flashes li {
|
|
343
|
+
margin: 0 0 5px 0;
|
|
344
|
+
padding: 5px;
|
|
345
|
+
list-style: none;
|
|
346
|
+
text-align: center;
|
|
347
|
+
word-break: break-word;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
li.error {
|
|
351
|
+
color: #d0011b;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
li.info {
|
|
355
|
+
color: #5fa416;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.closed-wrapper {
|
|
359
|
+
display: flex;
|
|
360
|
+
align-items: center;
|
|
361
|
+
justify-content: center;
|
|
362
|
+
min-height: 400px;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.info {
|
|
366
|
+
text-align: center;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.info img {
|
|
370
|
+
width: 120px;
|
|
371
|
+
height: 120px;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.info .info-header {
|
|
375
|
+
font-size: 30px;
|
|
376
|
+
font-weight: normal;
|
|
377
|
+
color: #666666;
|
|
378
|
+
margin: 0 0 10px 0;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.info .info-description {
|
|
382
|
+
color: #666666;
|
|
383
|
+
margin: 0 0 20px 0;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
a {
|
|
387
|
+
text-decoration: none;
|
|
388
|
+
color: #1c1ca0;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
a:visited {
|
|
392
|
+
color: #601ca0;
|
|
393
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
$(function () {
|
|
2
|
+
$(document).ready(function () {
|
|
3
|
+
$('.chat-container').removeClass('no-js');
|
|
4
|
+
var socket = io.connect(
|
|
5
|
+
'http://' + document.domain + ':' + location.port + '/chat',
|
|
6
|
+
{
|
|
7
|
+
transports: ['websocket']
|
|
8
|
+
}
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
// Store current username received from app context
|
|
12
|
+
var current_username = $('#username').val();
|
|
13
|
+
|
|
14
|
+
// On browser connect, emit a socket event to be added to
|
|
15
|
+
// room and assigned random username
|
|
16
|
+
socket.on('connect', function () {
|
|
17
|
+
socket.emit('joined', {});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Triggered on any status change by any user, such as some
|
|
21
|
+
// user joined, or changed username, or left, etc.
|
|
22
|
+
socket.on('status', function (data) {
|
|
23
|
+
addMessageToRoom(data, current_username, 'status');
|
|
24
|
+
console.log(data, current_username);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Triggered when message is received from a user. Even when sent
|
|
28
|
+
// by self, it get triggered after the server sends back the emit.
|
|
29
|
+
socket.on('message', function (data) {
|
|
30
|
+
addMessageToRoom(data, current_username, 'chat');
|
|
31
|
+
console.log(data, current_username);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Triggered when disconnected either by server stop or timeout
|
|
35
|
+
socket.on('disconnect', function (data) {
|
|
36
|
+
addMessageToRoom({ 'msg': 'The chat server is disconnected.' }, current_username, 'status');
|
|
37
|
+
})
|
|
38
|
+
socket.on('connect_error', function (error) {
|
|
39
|
+
console.log("error");
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Trigger new message on enter or click of send message button.
|
|
43
|
+
$('#new-message').on('keypress', function (e) {
|
|
44
|
+
var code = e.keyCode || e.which;
|
|
45
|
+
if (code == 13) {
|
|
46
|
+
emitMessage(socket);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Keep buttons disabled unless changed or not empty
|
|
51
|
+
$('#username').on('keyup', function (event) {
|
|
52
|
+
if ($('#username').val() !== '' && $('#username').val() !== current_username) {
|
|
53
|
+
if (event.keyCode == 13 || event.which == 13) {
|
|
54
|
+
this.blur();
|
|
55
|
+
current_username = updateUsername(socket) || current_username;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Show warning of losing data
|
|
61
|
+
$(window).on('beforeunload', function (e) {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
e.returnValue = '';
|
|
64
|
+
return '';
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
var addMessageToRoom = function (data, current_username, messageType) {
|
|
70
|
+
var scrollDiff = getScrollDiffBefore();
|
|
71
|
+
if (messageType === 'status') {
|
|
72
|
+
addStatusMessage(data.msg);
|
|
73
|
+
if (data.connected_users) {
|
|
74
|
+
addUserList(data.connected_users, current_username);
|
|
75
|
+
}
|
|
76
|
+
} else if (messageType === 'chat') {
|
|
77
|
+
addChatMessage(data.username, data.msg)
|
|
78
|
+
}
|
|
79
|
+
scrollBottomMaybe(scrollDiff);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
var emitMessage = function (socket) {
|
|
83
|
+
var text = $('#new-message').val();
|
|
84
|
+
$('#new-message').val('');
|
|
85
|
+
$('#chat').scrollTop($('#chat')[0].scrollHeight);
|
|
86
|
+
socket.emit('text', { msg: text });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var updateUsername = function (socket) {
|
|
90
|
+
var username = $('#username').val();
|
|
91
|
+
if (!checkUsernameExists(username)) {
|
|
92
|
+
$.ajax({
|
|
93
|
+
method: 'POST',
|
|
94
|
+
url: `http://${document.domain}:${location.port}/update-session-username`,
|
|
95
|
+
contentType: 'application/json',
|
|
96
|
+
dataType: 'json',
|
|
97
|
+
data: JSON.stringify({ 'username': username })
|
|
98
|
+
}).done(function (response) {
|
|
99
|
+
console.log(response);
|
|
100
|
+
if (response.success && response.username == username) {
|
|
101
|
+
socket.emit('update_username', { username: username });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
return username;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/************************************/
|
|
110
|
+
/********* Util Functions ***********/
|
|
111
|
+
/************************************/
|
|
112
|
+
|
|
113
|
+
var createUserListHTML = function (connected_users, current_user) {
|
|
114
|
+
var userListHTML = '';
|
|
115
|
+
connected_users.sort();
|
|
116
|
+
connected_users.forEach(function (username) {
|
|
117
|
+
if (username !== current_user) {
|
|
118
|
+
userListHTML += `<li>${sanitizeHTML(username)}</li>`;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return userListHTML;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
var checkUsernameExists = function (username) {
|
|
125
|
+
$('#username-error').text('');
|
|
126
|
+
var userMatches = $('#user-list li').filter(function () {
|
|
127
|
+
return $(this).text() === username;
|
|
128
|
+
});
|
|
129
|
+
if (userMatches.length) {
|
|
130
|
+
$('#username-error').text('User with that username exists!');
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
var getScrollDiffBefore = function () {
|
|
137
|
+
return $('#chat').scrollTop() - ($('#chat')[0].scrollHeight - $('#chat')[0].offsetHeight);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
var scrollBottomMaybe = function (scrollDiff) {
|
|
141
|
+
// Scrolls to bottom if the user is scrolled at bottom
|
|
142
|
+
// if the user has scrolled upp, it wont scroll at bottom.
|
|
143
|
+
// Note: when a user themselves send a message, it will still
|
|
144
|
+
// scroll to the bottom even if they had scrolled up before.
|
|
145
|
+
if (scrollDiff > 0) {
|
|
146
|
+
$('#chat').scrollTop($('#chat')[0].scrollHeight);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
var addStatusMessage = function (message) {
|
|
151
|
+
$('#chat').append(
|
|
152
|
+
`<p class="status">${sanitizeHTML(message)}</p>`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
var addChatMessage = function (username, message) {
|
|
157
|
+
$('#chat').append(`<p><span class="username">${sanitizeHTML(username)}</span><span class="message">${sanitizeHTML(message)}</span></p>`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
var addUserList = function (connected_users, current_username) {
|
|
161
|
+
$('#user-list').html(
|
|
162
|
+
createUserListHTML(
|
|
163
|
+
connected_users,
|
|
164
|
+
current_username
|
|
165
|
+
)
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
var sanitizeHTML = function (str) {
|
|
170
|
+
var temp = document.createElement('span');
|
|
171
|
+
temp.textContent = str;
|
|
172
|
+
return temp.innerHTML;
|
|
173
|
+
};
|