Improve UI
parent
0a2fe2a0b1
commit
0b77a88e72
|
@ -31,7 +31,7 @@ class API:
|
||||||
Main HTTP API (Flask)
|
Main HTTP API (Flask)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
callbacks = {'public' : {}, 'private' : {}, 'ui' : {}}
|
callbacks = {'public' : {}, 'private' : {}}
|
||||||
|
|
||||||
def validateToken(self, token):
|
def validateToken(self, token):
|
||||||
'''
|
'''
|
||||||
|
@ -45,6 +45,30 @@ class API:
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def guessMime(path):
|
||||||
|
'''
|
||||||
|
Guesses the mime type from the input filename
|
||||||
|
'''
|
||||||
|
|
||||||
|
mimetypes = {
|
||||||
|
'html' : 'text/html',
|
||||||
|
'js' : 'application/javascript',
|
||||||
|
'css' : 'text/css',
|
||||||
|
'png' : 'image/png',
|
||||||
|
'jpg' : 'image/jpeg'
|
||||||
|
}
|
||||||
|
|
||||||
|
for mimetype in mimetypes:
|
||||||
|
logger.debug(path + ' endswith .' + mimetype + '?')
|
||||||
|
if path.endswith('.%s' % mimetype):
|
||||||
|
logger.debug('- True!')
|
||||||
|
return mimetypes[mimetype]
|
||||||
|
else:
|
||||||
|
logger.debug('- no')
|
||||||
|
|
||||||
|
logger.debug('%s not in %s' % (path, mimetypes))
|
||||||
|
return 'text/plain'
|
||||||
|
|
||||||
def __init__(self, debug):
|
def __init__(self, debug):
|
||||||
'''
|
'''
|
||||||
Initialize the api server, preping variables for later use
|
Initialize the api server, preping variables for later use
|
||||||
|
@ -76,6 +100,7 @@ class API:
|
||||||
self.i2pEnabled = config.get('i2p.host', False)
|
self.i2pEnabled = config.get('i2p.host', False)
|
||||||
|
|
||||||
self.mimeType = 'text/plain'
|
self.mimeType = 'text/plain'
|
||||||
|
self.overrideCSP = False
|
||||||
|
|
||||||
with open('data/time-bypass.txt', 'w') as bypass:
|
with open('data/time-bypass.txt', 'w') as bypass:
|
||||||
bypass.write(self.timeBypassToken)
|
bypass.write(self.timeBypassToken)
|
||||||
|
@ -106,14 +131,15 @@ class API:
|
||||||
#else:
|
#else:
|
||||||
# resp.headers['server'] = 'Onionr'
|
# resp.headers['server'] = 'Onionr'
|
||||||
resp.headers['Content-Type'] = self.mimeType
|
resp.headers['Content-Type'] = self.mimeType
|
||||||
resp.headers["Content-Security-Policy"] = "default-src 'none'; script-src 'none'; object-src 'none'; style-src data: 'unsafe-inline'; img-src data:; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'none'"
|
if not self.overrideCSP:
|
||||||
|
resp.headers["Content-Security-Policy"] = "default-src 'none'; script-src 'none'; object-src 'none'; style-src data: 'unsafe-inline'; img-src data:; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'none'"
|
||||||
resp.headers['X-Frame-Options'] = 'deny'
|
resp.headers['X-Frame-Options'] = 'deny'
|
||||||
resp.headers['X-Content-Type-Options'] = "nosniff"
|
resp.headers['X-Content-Type-Options'] = "nosniff"
|
||||||
resp.headers['server'] = 'Onionr'
|
resp.headers['server'] = 'Onionr'
|
||||||
|
|
||||||
# reset to text/plain to help prevent browser attacks
|
# reset to text/plain to help prevent browser attacks
|
||||||
if self.mimeType != 'text/plain':
|
self.mimeType = 'text/plain'
|
||||||
self.mimeType = 'text/plain'
|
self.overrideCSP = False
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
@ -153,10 +179,12 @@ class API:
|
||||||
def ui_private(path):
|
def ui_private(path):
|
||||||
startTime = math.floor(time.time())
|
startTime = math.floor(time.time())
|
||||||
|
|
||||||
|
'''
|
||||||
if request.args.get('timingToken') is None:
|
if request.args.get('timingToken') is None:
|
||||||
timingToken = ''
|
timingToken = ''
|
||||||
else:
|
else:
|
||||||
timingToken = request.args.get('timingToken')
|
timingToken = request.args.get('timingToken')
|
||||||
|
'''
|
||||||
|
|
||||||
if not config.get("www.ui.run", True):
|
if not config.get("www.ui.run", True):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
@ -166,14 +194,21 @@ class API:
|
||||||
else:
|
else:
|
||||||
self.validateHost('public')
|
self.validateHost('public')
|
||||||
|
|
||||||
|
'''
|
||||||
endTime = math.floor(time.time())
|
endTime = math.floor(time.time())
|
||||||
elapsed = endTime - startTime
|
elapsed = endTime - startTime
|
||||||
|
|
||||||
if not hmac.compare_digest(timingToken, self.timeBypassToken):
|
if not hmac.compare_digest(timingToken, self.timeBypassToken):
|
||||||
if elapsed < self._privateDelayTime:
|
if elapsed < self._privateDelayTime:
|
||||||
time.sleep(self._privateDelayTime - elapsed)
|
time.sleep(self._privateDelayTime - elapsed)
|
||||||
|
'''
|
||||||
|
|
||||||
return send_from_directory('static-data/www/ui/dist/', path)
|
logger.debug('Serving %s' % path)
|
||||||
|
|
||||||
|
self.mimeType = API.guessMime(path)
|
||||||
|
self.overrideCSP = True
|
||||||
|
|
||||||
|
return send_from_directory('static-data/www/ui/dist/', path, mimetype = API.guessMime(path))
|
||||||
|
|
||||||
@app.route('/client/')
|
@app.route('/client/')
|
||||||
def private_handler():
|
def private_handler():
|
||||||
|
|
|
@ -647,7 +647,7 @@ class Core:
|
||||||
def updateBlockInfo(self, hash, key, data):
|
def updateBlockInfo(self, hash, key, data):
|
||||||
'''
|
'''
|
||||||
sets info associated with a block
|
sets info associated with a block
|
||||||
|
|
||||||
hash - the hash of a block
|
hash - the hash of a block
|
||||||
dateReceived - the date the block was recieved, not necessarily when it was created
|
dateReceived - the date the block was recieved, not necessarily when it was created
|
||||||
decrypted - if we can successfully decrypt the block (does not describe its current state)
|
decrypted - if we can successfully decrypt the block (does not describe its current state)
|
||||||
|
@ -729,7 +729,7 @@ class Core:
|
||||||
signer = self._crypto.pubKeyEncrypt(signer, asymPeer, encodedData=True, anonymous=True).decode()
|
signer = self._crypto.pubKeyEncrypt(signer, asymPeer, encodedData=True, anonymous=True).decode()
|
||||||
else:
|
else:
|
||||||
raise onionrexceptions.InvalidPubkey(asymPeer + ' is not a valid base32 encoded ed25519 key')
|
raise onionrexceptions.InvalidPubkey(asymPeer + ' is not a valid base32 encoded ed25519 key')
|
||||||
|
|
||||||
# compile metadata
|
# compile metadata
|
||||||
metadata['meta'] = jsonMeta
|
metadata['meta'] = jsonMeta
|
||||||
metadata['sig'] = signature
|
metadata['sig'] = signature
|
||||||
|
|
|
@ -198,6 +198,9 @@ class Onionr:
|
||||||
'kex': self.doKEX,
|
'kex': self.doKEX,
|
||||||
'pex': self.doPEX,
|
'pex': self.doPEX,
|
||||||
|
|
||||||
|
'ui' : self.openUI,
|
||||||
|
'gui' : self.openUI,
|
||||||
|
|
||||||
'getpassword': self.printWebPassword
|
'getpassword': self.printWebPassword
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,5 +708,12 @@ class Onionr:
|
||||||
else:
|
else:
|
||||||
logger.error('%s add-file <filename>' % sys.argv[0], timestamp = False)
|
logger.error('%s add-file <filename>' % sys.argv[0], timestamp = False)
|
||||||
|
|
||||||
|
def openUI(self):
|
||||||
|
import webbrowser
|
||||||
|
url = 'http://127.0.0.1:%s/ui/index.html?timingToken=%s' % (config.get('client.port', 59496), self.onionrUtils.getTimeBypassToken())
|
||||||
|
|
||||||
|
print('Opening %s ...' % url)
|
||||||
|
webbrowser.open(url, new = 1, autoraise = True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
Onionr()
|
Onionr()
|
||||||
|
|
|
@ -52,7 +52,9 @@ class OnionrUtils:
|
||||||
with open('data/time-bypass.txt', 'r') as bypass:
|
with open('data/time-bypass.txt', 'r') as bypass:
|
||||||
self.timingToken = bypass.read()
|
self.timingToken = bypass.read()
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error('Failed to fetch time bypass token.', error=error)
|
logger.error('Failed to fetch time bypass token.', error = error)
|
||||||
|
|
||||||
|
return self.timingToken
|
||||||
|
|
||||||
def getRoundedEpoch(self, roundS=60):
|
def getRoundedEpoch(self, roundS=60):
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -7,19 +7,20 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-10">
|
<div class="col-10">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col col-auto">
|
||||||
<a class="onionr-post-user-name" href="#!" onclick="viewProfile('$user-id-url', '$user-name-url')">$user-name</a>
|
<a class="onionr-post-user-name" href="#!" onclick="viewProfile('$user-id-url', '$user-name-url')">$user-name</a>
|
||||||
<a class="onionr-post-user-id" href="#!" onclick="viewProfile('$user-id-url', '$user-name-url')" data-placement="top" data-toggle="tooltip" title="$user-id">$user-id-truncated</a>
|
<a class="onionr-post-user-id" href="#!" onclick="viewProfile('$user-id-url', '$user-name-url')" data-placement="top" data-toggle="tooltip" title="$user-id">$user-id-truncated</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right pl-3 pr-3">
|
|
||||||
<div class="onionr-post-date" data-placement="top" data-toggle="tooltip" title="$date">$date-relative</div>
|
<div class="col col-auto text-right ml-auto pl-0">
|
||||||
|
<div class="onionr-post-date text-right" data-placement="top" data-toggle="tooltip" title="$date">$date-relative</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="onionr-post-content">
|
<div class="onionr-post-content">
|
||||||
$content
|
$content
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="onionr-post-controls pt-2">
|
<div class="onionr-post-controls pt-2">
|
||||||
<a href="#!" class="glyphicon glyphicon-heart mr-2">like</a>
|
<a href="#!" class="glyphicon glyphicon-heart mr-2">like</a>
|
||||||
<a href="#!" class="glyphicon glyphicon-comment mr-2">comment</a>
|
<a href="#!" class="glyphicon glyphicon-comment mr-2">comment</a>
|
||||||
|
|
|
@ -60,6 +60,12 @@ body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-divider {
|
||||||
|
margin: 5px 15px;
|
||||||
|
height: 1px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
/* profile */
|
/* profile */
|
||||||
|
|
||||||
.onionr-profile-user-icon {
|
.onionr-profile-user-icon {
|
||||||
|
@ -68,7 +74,6 @@ body {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.onionr-profile-username {
|
.onionr-profile-username {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ body {
|
||||||
.onionr-post {
|
.onionr-post {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
|
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,3 +30,7 @@ body {
|
||||||
border-top: 1px solid black;
|
border-top: 1px solid black;
|
||||||
font-size: 15pt;
|
font-size: 15pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-divider {
|
||||||
|
border-top:1px solid gray;
|
||||||
|
}
|
||||||
|
|
|
@ -36,22 +36,24 @@
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="d-none d-lg-block col-lg-3">
|
<div class="col-12 col-lg-3">
|
||||||
<div class="onionr-profile">
|
<div class="onionr-profile">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-4 col-lg-12">
|
||||||
<img id="onionr-profile-user-icon" class="onionr-profile-user-icon" src="img/default.png">
|
<img id="onionr-profile-user-icon" class="onionr-profile-user-icon" src="img/default.png">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-8 col-lg-12">
|
||||||
<h2 id="onionr-profile-username" class="onionr-profile-username">arinerron</h2>
|
<h2 id="onionr-profile-username" class="onionr-profile-username text-left text-lg-center text-sm-left">arinerron</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="h-divider d-block d-lg-none pb-3"></div>
|
||||||
|
|
||||||
<div class="col-sm-12 col-lg-6">
|
<div class="col-sm-12 col-lg-6">
|
||||||
<div class="row" id="onionr-timeline-posts">
|
<div class="row" id="onionr-timeline-posts">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,91 @@
|
||||||
|
|
||||||
|
/* handy localstorage functions for quick usage */
|
||||||
|
|
||||||
|
function set(key, val) {
|
||||||
|
return localStorage.setItem(key, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get(key, df) { // df is default
|
||||||
|
value = localStorage.getItem(key);
|
||||||
|
if(value == null)
|
||||||
|
value = df;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove(key) {
|
||||||
|
return localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
var usermap = JSON.parse(get('usermap', '{}'));
|
||||||
|
|
||||||
|
function getUserMap() {
|
||||||
|
return usermap;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deserializeUser(id) {
|
||||||
|
var serialized = getUserMap()[id]
|
||||||
|
var user = new User();
|
||||||
|
user.setName(serialized['name']);
|
||||||
|
user.setID(serialized['id']);
|
||||||
|
user.setIcon(serialized['icon']);
|
||||||
|
}
|
||||||
|
|
||||||
/* returns a relative date format, e.g. "5 minutes" */
|
/* returns a relative date format, e.g. "5 minutes" */
|
||||||
function timeSince(date) {
|
function timeSince(date, size) {
|
||||||
// taken from https://stackoverflow.com/a/3177838/3678023
|
// taken from https://stackoverflow.com/a/3177838/3678023
|
||||||
|
|
||||||
var seconds = Math.floor((new Date() - date) / 1000);
|
var seconds = Math.floor((new Date() - date) / 1000);
|
||||||
var interval = Math.floor(seconds / 31536000);
|
var interval = Math.floor(seconds / 31536000);
|
||||||
|
|
||||||
|
if (size === null)
|
||||||
|
size = 'desktop';
|
||||||
|
|
||||||
|
var dates = {
|
||||||
|
'mobile' : {
|
||||||
|
'yr' : 'yrs',
|
||||||
|
'mo' : 'mo',
|
||||||
|
'd' : 'd',
|
||||||
|
'hr' : 'h',
|
||||||
|
'min' : 'm',
|
||||||
|
'secs' : 's',
|
||||||
|
'sec' : 's',
|
||||||
|
},
|
||||||
|
|
||||||
|
'desktop' : {
|
||||||
|
'yr' : ' years',
|
||||||
|
'mo' : ' months',
|
||||||
|
'd' : ' days',
|
||||||
|
'hr' : ' hours',
|
||||||
|
'min' : ' minutes',
|
||||||
|
'secs' : ' seconds',
|
||||||
|
'sec' : ' second',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " years";
|
return interval + dates[size]['yr'];
|
||||||
interval = Math.floor(seconds / 2592000);
|
interval = Math.floor(seconds / 2592000);
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " months";
|
return interval + dates[size]['mo'];
|
||||||
interval = Math.floor(seconds / 86400);
|
interval = Math.floor(seconds / 86400);
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " days";
|
return interval + dates[size]['d'];
|
||||||
interval = Math.floor(seconds / 3600);
|
interval = Math.floor(seconds / 3600);
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " hours";
|
return interval + dates[size]['hr'];
|
||||||
interval = Math.floor(seconds / 60);
|
interval = Math.floor(seconds / 60);
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " minutes";
|
return interval + dates[size]['min'];
|
||||||
|
|
||||||
return Math.floor(seconds) + " seconds";
|
if(Math.floor(seconds) !== 1)
|
||||||
|
return Math.floor(seconds) + dates[size]['secs'];
|
||||||
|
|
||||||
|
return '1' + dates[size]['sec'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* replace all instances of string */
|
/* replace all instances of string */
|
||||||
|
@ -41,7 +106,7 @@ function encodeURL(url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* user class */
|
/* user class */
|
||||||
class User {
|
class User {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.name = 'Unknown';
|
this.name = 'Unknown';
|
||||||
this.id = 'unknown';
|
this.id = 'unknown';
|
||||||
|
@ -55,22 +120,35 @@ class User {
|
||||||
getName() {
|
getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
setID(id) {
|
setID(id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
getID() {
|
getID() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIcon(image) {
|
setIcon(image) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
getIcon() {
|
getIcon() {
|
||||||
return this.image;
|
return this.image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serialize() {
|
||||||
|
return {
|
||||||
|
'name' : this.getName(),
|
||||||
|
'id' : this.getID(),
|
||||||
|
'icon' : this.getIcon()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
remember() {
|
||||||
|
usermap[this.getID()] = this.serialize();
|
||||||
|
set('usermap', JSON.stringify(usermap));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* post class */
|
/* post class */
|
||||||
|
@ -86,19 +164,20 @@ class Post {
|
||||||
</div>\
|
</div>\
|
||||||
<div class="col-10">\
|
<div class="col-10">\
|
||||||
<div class="row">\
|
<div class="row">\
|
||||||
<div class="col">\
|
<div class="col col-auto">\
|
||||||
<a class="onionr-post-user-name" href="#!" onclick="viewProfile(\'$user-id-url\', \'$user-name-url\')">$user-name</a>\
|
<a class="onionr-post-user-name" href="#!" onclick="viewProfile(\'$user-id-url\', \'$user-name-url\')">$user-name</a>\
|
||||||
<a class="onionr-post-user-id" href="#!" onclick="viewProfile(\'$user-id-url\', \'$user-name-url\')" data-placement="top" data-toggle="tooltip" title="$user-id">$user-id-truncated</a>\
|
<a class="onionr-post-user-id" href="#!" onclick="viewProfile(\'$user-id-url\', \'$user-name-url\')" data-placement="top" data-toggle="tooltip" title="$user-id">$user-id-truncated</a>\
|
||||||
</div>\
|
</div>\
|
||||||
<div class="text-right pl-3 pr-3">\
|
\
|
||||||
<div class="onionr-post-date" data-placement="top" data-toggle="tooltip" title="$date">$date-relative</div>\
|
<div class="col col-auto text-right ml-auto pl-0">\
|
||||||
|
<div class="onionr-post-date text-right" data-placement="top" data-toggle="tooltip" title="$date">$date-relative</div>\
|
||||||
</div>\
|
</div>\
|
||||||
</div>\
|
</div>\
|
||||||
\
|
\
|
||||||
<div class="onionr-post-content">\
|
<div class="onionr-post-content">\
|
||||||
$content\
|
$content\
|
||||||
</div>\
|
</div>\
|
||||||
\
|
\
|
||||||
<div class="onionr-post-controls pt-2">\
|
<div class="onionr-post-controls pt-2">\
|
||||||
<a href="#!" class="glyphicon glyphicon-heart mr-2">like</a>\
|
<a href="#!" class="glyphicon glyphicon-heart mr-2">like</a>\
|
||||||
<a href="#!" class="glyphicon glyphicon-comment mr-2">comment</a>\
|
<a href="#!" class="glyphicon glyphicon-comment mr-2">comment</a>\
|
||||||
|
@ -109,7 +188,9 @@ class Post {
|
||||||
</div>\
|
</div>\
|
||||||
<!-- END POST -->\
|
<!-- END POST -->\
|
||||||
';
|
';
|
||||||
|
|
||||||
|
var device = (jQuery(document).width() < 768 ? 'mobile' : 'desktop');
|
||||||
|
|
||||||
postTemplate = postTemplate.replaceAll('$user-name-url', encodeHTML(encodeURL(this.getUser().getName())));
|
postTemplate = postTemplate.replaceAll('$user-name-url', encodeHTML(encodeURL(this.getUser().getName())));
|
||||||
postTemplate = postTemplate.replaceAll('$user-name', encodeHTML(this.getUser().getName()));
|
postTemplate = postTemplate.replaceAll('$user-name', encodeHTML(this.getUser().getName()));
|
||||||
postTemplate = postTemplate.replaceAll('$user-id-url', encodeHTML(encodeURL(this.getUser().getID())));
|
postTemplate = postTemplate.replaceAll('$user-id-url', encodeHTML(encodeURL(this.getUser().getID())));
|
||||||
|
@ -117,54 +198,36 @@ class Post {
|
||||||
postTemplate = postTemplate.replaceAll('$user-id', encodeHTML(this.getUser().getID()));
|
postTemplate = postTemplate.replaceAll('$user-id', encodeHTML(this.getUser().getID()));
|
||||||
postTemplate = postTemplate.replaceAll('$user-image', encodeHTML(this.getUser().getIcon()));
|
postTemplate = postTemplate.replaceAll('$user-image', encodeHTML(this.getUser().getIcon()));
|
||||||
postTemplate = postTemplate.replaceAll('$content', encodeHTML(this.getContent()));
|
postTemplate = postTemplate.replaceAll('$content', encodeHTML(this.getContent()));
|
||||||
postTemplate = postTemplate.replaceAll('$date-relative', timeSince(this.getPostDate()) + ' ago');
|
postTemplate = postTemplate.replaceAll('$date-relative', timeSince(this.getPostDate(), device) + (device === 'desktop' ? ' ago' : ''));
|
||||||
postTemplate = postTemplate.replaceAll('$date', this.getPostDate().toLocaleString());
|
postTemplate = postTemplate.replaceAll('$date', this.getPostDate().toLocaleString());
|
||||||
|
|
||||||
return postTemplate;
|
return postTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
setUser(user) {
|
setUser(user) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
getUser() {
|
getUser() {
|
||||||
return this.user;
|
return this.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
setContent(content) {
|
setContent(content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
getContent() {
|
getContent() {
|
||||||
return this.content;
|
return this.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPostDate(date) { // unix timestamp input
|
setPostDate(date) { // unix timestamp input
|
||||||
if(date instanceof Date)
|
if(date instanceof Date)
|
||||||
this.date = date;
|
this.date = date;
|
||||||
else
|
else
|
||||||
this.date = new Date(date * 1000);
|
this.date = new Date(date * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPostDate() {
|
getPostDate() {
|
||||||
return this.date;
|
return this.date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handy localstorage functions for quick usage */
|
|
||||||
|
|
||||||
function set(key, val) {
|
|
||||||
return localStorage.setItem(key, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
function get(key, df) { // df is default
|
|
||||||
value = localStorage.getItem(key);
|
|
||||||
if(value == null)
|
|
||||||
value = df;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove(key) {
|
|
||||||
return localStorage.removeItem(key);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,20 +1,96 @@
|
||||||
/* write a random post to the page, for testing */
|
/* write a random post to the page, for testing */
|
||||||
|
|
||||||
|
var verbs =
|
||||||
|
[
|
||||||
|
["go to", "goes to", "going to", "went to", "gone to"],
|
||||||
|
["look at", "looks at", "looking at", "looked at", "looked at"],
|
||||||
|
["choose", "chooses", "choosing", "chose", "chosen"],
|
||||||
|
["torrent", "downloads", "downloading", "torrented", "downloaded"],
|
||||||
|
["detonate", "detonates", "detonating", "detonated", "detonated"],
|
||||||
|
["run", "runs", "running", "ran", "running"],
|
||||||
|
["program", "programs", "programming", "coded", "programmed"],
|
||||||
|
["start", "starts", "starting", "started", "started"]
|
||||||
|
];
|
||||||
|
var tenses =
|
||||||
|
[
|
||||||
|
{name:"Present", singular:1, plural:0, format:"%subject %verb %complement"},
|
||||||
|
{name:"Present", singular:1, plural:0, format:"%subject %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
||||||
|
{name:"Present Continues", singular:2, plural:2, format:"%subject %be %verb %complement"}
|
||||||
|
];
|
||||||
|
var subjects =
|
||||||
|
[
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"My cat", be:"is", singular:0},
|
||||||
|
{name:"My cat", be:"is", singular:0},
|
||||||
|
{name:"My dog", be:"is", singular:0},
|
||||||
|
{name:"My dog", be:"is", singular:0},
|
||||||
|
{name:"My mom", be:"is", singular:0},
|
||||||
|
{name:"My dad", be:"is", singular:0},
|
||||||
|
{name:"You", be:"are", singular:0},
|
||||||
|
{name:"He", be:"is", singular:1}
|
||||||
|
];
|
||||||
|
var complementsForVerbs =
|
||||||
|
[
|
||||||
|
["cinema", "Egypt", "home", "concert"],
|
||||||
|
["for a map", "them", "the stars", "the lake"],
|
||||||
|
["a book for reading", "a dvd for tonight"],
|
||||||
|
["the virus", "the malware", "that 0day", "Onionr"],
|
||||||
|
["a bomb", "a nuke", "some C4", "some ammonium nitrate"],
|
||||||
|
["the race", "towards someone", "to the stars", "on top of your roof"],
|
||||||
|
["Onionr", "the malware", "some software", "Onionr"],
|
||||||
|
["Onionr", "Onionr", "the race", "the timer"],
|
||||||
|
]
|
||||||
|
|
||||||
|
Array.prototype.random = function(){return this[Math.floor(Math.random() * this.length)];};
|
||||||
|
|
||||||
|
function generate(){
|
||||||
|
var index = Math.floor(verbs.length * Math.random());
|
||||||
|
var tense = tenses.random();
|
||||||
|
var subject = subjects.random();
|
||||||
|
var verb = verbs[index];
|
||||||
|
var complement = complementsForVerbs[index];
|
||||||
|
var str = tense.format;
|
||||||
|
str = str.replace("%subject", subject.name).replace("%be", subject.be);
|
||||||
|
str = str.replace("%verb", verb[subject.singular ? tense.singular : tense.plural]);
|
||||||
|
str = str.replace("%complement", complement.random());
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
var curDate = new Date()
|
||||||
function addRandomPost() {
|
function addRandomPost() {
|
||||||
var post = new Post();
|
var post = new Post();
|
||||||
var user = new User();
|
var user = new User();
|
||||||
var items = ['arinerron', 'beardog108', 'samyk', 'snowden', 'aaronswartz'];
|
var items = ['arinerron', 'beardog108', 'samyk', 'snowden', 'aaronswartz'];
|
||||||
user.setName(items[Math.floor(Math.random()*items.length)]);
|
user.setName(items[Math.floor(Math.random()*items.length)]);
|
||||||
user.setID('i-eat-waffles-often-its-actually-crazy-like-i-dont-know-wow');
|
user.setID('i-eat-waffles-often-its-actually-crazy-like-i-dont-know-wow');
|
||||||
post.setContent('spammm ' + btoa(Math.random() + ' wow'));
|
post.setContent(generate());
|
||||||
post.setUser(user);
|
post.setUser(user);
|
||||||
post.setPostDate(new Date(new Date() - (Math.random() * 1000000)));
|
|
||||||
|
curDate = new Date(curDate - (Math.random() * 1000000));
|
||||||
|
post.setPostDate(curDate);
|
||||||
|
|
||||||
document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
|
document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0; i < Math.round(50 * Math.random()); i++)
|
for(var i = 0; i < Math.round(50 * Math.random()); i++)
|
||||||
addRandomPost();
|
addRandomPost();
|
||||||
|
|
||||||
function viewProfile(id, name) {
|
function viewProfile(id, name) {
|
||||||
document.getElementById("onionr-profile-username").innerHTML = encodeHTML(decodeURIComponent(name));
|
document.getElementById("onionr-profile-username").innerHTML = encodeHTML(decodeURIComponent(name));
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,12 @@ body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-divider {
|
||||||
|
margin: 5px 15px;
|
||||||
|
height: 1px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
/* profile */
|
/* profile */
|
||||||
|
|
||||||
.onionr-profile-user-icon {
|
.onionr-profile-user-icon {
|
||||||
|
@ -68,7 +74,6 @@ body {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.onionr-profile-username {
|
.onionr-profile-username {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ body {
|
||||||
.onionr-post {
|
.onionr-post {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
|
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,3 +30,7 @@ body {
|
||||||
border-top: 1px solid black;
|
border-top: 1px solid black;
|
||||||
font-size: 15pt;
|
font-size: 15pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-divider {
|
||||||
|
border-top:1px solid gray;
|
||||||
|
}
|
||||||
|
|
|
@ -6,22 +6,24 @@
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="d-none d-lg-block col-lg-3">
|
<div class="col-12 col-lg-3">
|
||||||
<div class="onionr-profile">
|
<div class="onionr-profile">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-4 col-lg-12">
|
||||||
<img id="onionr-profile-user-icon" class="onionr-profile-user-icon" src="img/default.png">
|
<img id="onionr-profile-user-icon" class="onionr-profile-user-icon" src="img/default.png">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-8 col-lg-12">
|
||||||
<h2 id="onionr-profile-username" class="onionr-profile-username">arinerron</h2>
|
<h2 id="onionr-profile-username" class="onionr-profile-username text-left text-lg-center text-sm-left">arinerron</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="h-divider d-block d-lg-none pb-3"></div>
|
||||||
|
|
||||||
<div class="col-sm-12 col-lg-6">
|
<div class="col-sm-12 col-lg-6">
|
||||||
<div class="row" id="onionr-timeline-posts">
|
<div class="row" id="onionr-timeline-posts">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ function get(key, df) { // df is default
|
||||||
value = localStorage.getItem(key);
|
value = localStorage.getItem(key);
|
||||||
if(value == null)
|
if(value == null)
|
||||||
value = df;
|
value = df;
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,28 +32,60 @@ function deserializeUser(id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns a relative date format, e.g. "5 minutes" */
|
/* returns a relative date format, e.g. "5 minutes" */
|
||||||
function timeSince(date) {
|
function timeSince(date, size) {
|
||||||
// taken from https://stackoverflow.com/a/3177838/3678023
|
// taken from https://stackoverflow.com/a/3177838/3678023
|
||||||
|
|
||||||
var seconds = Math.floor((new Date() - date) / 1000);
|
var seconds = Math.floor((new Date() - date) / 1000);
|
||||||
var interval = Math.floor(seconds / 31536000);
|
var interval = Math.floor(seconds / 31536000);
|
||||||
|
|
||||||
|
if (size === null)
|
||||||
|
size = 'desktop';
|
||||||
|
|
||||||
|
var dates = {
|
||||||
|
'mobile' : {
|
||||||
|
'yr' : 'yrs',
|
||||||
|
'mo' : 'mo',
|
||||||
|
'd' : 'd',
|
||||||
|
'hr' : 'h',
|
||||||
|
'min' : 'm',
|
||||||
|
'secs' : 's',
|
||||||
|
'sec' : 's',
|
||||||
|
},
|
||||||
|
|
||||||
|
'desktop' : {
|
||||||
|
'yr' : ' years',
|
||||||
|
'mo' : ' months',
|
||||||
|
'd' : ' days',
|
||||||
|
'hr' : ' hours',
|
||||||
|
'min' : ' minutes',
|
||||||
|
'secs' : ' seconds',
|
||||||
|
'sec' : ' second',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " years";
|
return interval + dates[size]['yr'];
|
||||||
interval = Math.floor(seconds / 2592000);
|
interval = Math.floor(seconds / 2592000);
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " months";
|
return interval + dates[size]['mo'];
|
||||||
interval = Math.floor(seconds / 86400);
|
interval = Math.floor(seconds / 86400);
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " days";
|
return interval + dates[size]['d'];
|
||||||
interval = Math.floor(seconds / 3600);
|
interval = Math.floor(seconds / 3600);
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " hours";
|
return interval + dates[size]['hr'];
|
||||||
interval = Math.floor(seconds / 60);
|
interval = Math.floor(seconds / 60);
|
||||||
|
|
||||||
if (interval > 1)
|
if (interval > 1)
|
||||||
return interval + " minutes";
|
return interval + dates[size]['min'];
|
||||||
|
|
||||||
return Math.floor(seconds) + " seconds";
|
if(Math.floor(seconds) !== 1)
|
||||||
|
return Math.floor(seconds) + dates[size]['secs'];
|
||||||
|
|
||||||
|
return '1' + dates[size]['sec'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* replace all instances of string */
|
/* replace all instances of string */
|
||||||
|
@ -74,7 +106,7 @@ function encodeURL(url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* user class */
|
/* user class */
|
||||||
class User {
|
class User {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.name = 'Unknown';
|
this.name = 'Unknown';
|
||||||
this.id = 'unknown';
|
this.id = 'unknown';
|
||||||
|
@ -88,23 +120,23 @@ class User {
|
||||||
getName() {
|
getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
setID(id) {
|
setID(id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
getID() {
|
getID() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIcon(image) {
|
setIcon(image) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
getIcon() {
|
getIcon() {
|
||||||
return this.image;
|
return this.image;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize() {
|
serialize() {
|
||||||
return {
|
return {
|
||||||
'name' : this.getName(),
|
'name' : this.getName(),
|
||||||
|
@ -112,7 +144,7 @@ class User {
|
||||||
'icon' : this.getIcon()
|
'icon' : this.getIcon()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
remember() {
|
remember() {
|
||||||
usermap[this.getID()] = this.serialize();
|
usermap[this.getID()] = this.serialize();
|
||||||
set('usermap', JSON.stringify(usermap));
|
set('usermap', JSON.stringify(usermap));
|
||||||
|
@ -124,7 +156,9 @@ class Post {
|
||||||
/* returns the html content of a post */
|
/* returns the html content of a post */
|
||||||
getHTML() {
|
getHTML() {
|
||||||
var postTemplate = '<$= jsTemplate('onionr-timeline-post') $>';
|
var postTemplate = '<$= jsTemplate('onionr-timeline-post') $>';
|
||||||
|
|
||||||
|
var device = (jQuery(document).width() < 768 ? 'mobile' : 'desktop');
|
||||||
|
|
||||||
postTemplate = postTemplate.replaceAll('$user-name-url', encodeHTML(encodeURL(this.getUser().getName())));
|
postTemplate = postTemplate.replaceAll('$user-name-url', encodeHTML(encodeURL(this.getUser().getName())));
|
||||||
postTemplate = postTemplate.replaceAll('$user-name', encodeHTML(this.getUser().getName()));
|
postTemplate = postTemplate.replaceAll('$user-name', encodeHTML(this.getUser().getName()));
|
||||||
postTemplate = postTemplate.replaceAll('$user-id-url', encodeHTML(encodeURL(this.getUser().getID())));
|
postTemplate = postTemplate.replaceAll('$user-id-url', encodeHTML(encodeURL(this.getUser().getID())));
|
||||||
|
@ -132,35 +166,35 @@ class Post {
|
||||||
postTemplate = postTemplate.replaceAll('$user-id', encodeHTML(this.getUser().getID()));
|
postTemplate = postTemplate.replaceAll('$user-id', encodeHTML(this.getUser().getID()));
|
||||||
postTemplate = postTemplate.replaceAll('$user-image', encodeHTML(this.getUser().getIcon()));
|
postTemplate = postTemplate.replaceAll('$user-image', encodeHTML(this.getUser().getIcon()));
|
||||||
postTemplate = postTemplate.replaceAll('$content', encodeHTML(this.getContent()));
|
postTemplate = postTemplate.replaceAll('$content', encodeHTML(this.getContent()));
|
||||||
postTemplate = postTemplate.replaceAll('$date-relative', timeSince(this.getPostDate()) + ' ago');
|
postTemplate = postTemplate.replaceAll('$date-relative', timeSince(this.getPostDate(), device) + (device === 'desktop' ? ' ago' : ''));
|
||||||
postTemplate = postTemplate.replaceAll('$date', this.getPostDate().toLocaleString());
|
postTemplate = postTemplate.replaceAll('$date', this.getPostDate().toLocaleString());
|
||||||
|
|
||||||
return postTemplate;
|
return postTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
setUser(user) {
|
setUser(user) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
getUser() {
|
getUser() {
|
||||||
return this.user;
|
return this.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
setContent(content) {
|
setContent(content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
getContent() {
|
getContent() {
|
||||||
return this.content;
|
return this.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPostDate(date) { // unix timestamp input
|
setPostDate(date) { // unix timestamp input
|
||||||
if(date instanceof Date)
|
if(date instanceof Date)
|
||||||
this.date = date;
|
this.date = date;
|
||||||
else
|
else
|
||||||
this.date = new Date(date * 1000);
|
this.date = new Date(date * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPostDate() {
|
getPostDate() {
|
||||||
return this.date;
|
return this.date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,96 @@
|
||||||
/* write a random post to the page, for testing */
|
/* write a random post to the page, for testing */
|
||||||
|
|
||||||
|
var verbs =
|
||||||
|
[
|
||||||
|
["go to", "goes to", "going to", "went to", "gone to"],
|
||||||
|
["look at", "looks at", "looking at", "looked at", "looked at"],
|
||||||
|
["choose", "chooses", "choosing", "chose", "chosen"],
|
||||||
|
["torrent", "downloads", "downloading", "torrented", "downloaded"],
|
||||||
|
["detonate", "detonates", "detonating", "detonated", "detonated"],
|
||||||
|
["run", "runs", "running", "ran", "running"],
|
||||||
|
["program", "programs", "programming", "coded", "programmed"],
|
||||||
|
["start", "starts", "starting", "started", "started"]
|
||||||
|
];
|
||||||
|
var tenses =
|
||||||
|
[
|
||||||
|
{name:"Present", singular:1, plural:0, format:"%subject %verb %complement"},
|
||||||
|
{name:"Present", singular:1, plural:0, format:"%subject %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
||||||
|
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
||||||
|
{name:"Present Continues", singular:2, plural:2, format:"%subject %be %verb %complement"}
|
||||||
|
];
|
||||||
|
var subjects =
|
||||||
|
[
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"I", be:"am", singular:0},
|
||||||
|
{name:"My cat", be:"is", singular:0},
|
||||||
|
{name:"My cat", be:"is", singular:0},
|
||||||
|
{name:"My dog", be:"is", singular:0},
|
||||||
|
{name:"My dog", be:"is", singular:0},
|
||||||
|
{name:"My mom", be:"is", singular:0},
|
||||||
|
{name:"My dad", be:"is", singular:0},
|
||||||
|
{name:"You", be:"are", singular:0},
|
||||||
|
{name:"He", be:"is", singular:1}
|
||||||
|
];
|
||||||
|
var complementsForVerbs =
|
||||||
|
[
|
||||||
|
["the cinema", "Egypt", "the house", "the concert"],
|
||||||
|
["for a map", "them", "the stars", "the lake"],
|
||||||
|
["a book for reading", "a dvd for tonight"],
|
||||||
|
["the virus", "the malware", "that 0day", "Onionr"],
|
||||||
|
["a bomb", "a nuke", "some C4", "some ammonium nitrate"],
|
||||||
|
["the race", "towards someone", "to the stars", "on top of your roof"],
|
||||||
|
["Onionr", "the malware", "some software", "Onionr"],
|
||||||
|
["Onionr", "Onionr", "the race", "the timer"],
|
||||||
|
]
|
||||||
|
|
||||||
|
Array.prototype.random = function(){return this[Math.floor(Math.random() * this.length)];};
|
||||||
|
|
||||||
|
function generate(){
|
||||||
|
var index = Math.floor(verbs.length * Math.random());
|
||||||
|
var tense = tenses.random();
|
||||||
|
var subject = subjects.random();
|
||||||
|
var verb = verbs[index];
|
||||||
|
var complement = complementsForVerbs[index];
|
||||||
|
var str = tense.format;
|
||||||
|
str = str.replace("%subject", subject.name).replace("%be", subject.be);
|
||||||
|
str = str.replace("%verb", verb[subject.singular ? tense.singular : tense.plural]);
|
||||||
|
str = str.replace("%complement", complement.random());
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
var curDate = new Date()
|
||||||
function addRandomPost() {
|
function addRandomPost() {
|
||||||
var post = new Post();
|
var post = new Post();
|
||||||
var user = new User();
|
var user = new User();
|
||||||
var items = ['arinerron', 'beardog108', 'samyk', 'snowden', 'aaronswartz'];
|
var items = ['arinerron', 'beardog108', 'samyk', 'snowden', 'aaronswartz'];
|
||||||
user.setName(items[Math.floor(Math.random()*items.length)]);
|
user.setName(items[Math.floor(Math.random()*items.length)]);
|
||||||
user.setID('i-eat-waffles-often-its-actually-crazy-like-i-dont-know-wow');
|
user.setID('i-eat-waffles-often-its-actually-crazy-like-i-dont-know-wow');
|
||||||
post.setContent('spammm ' + btoa(Math.random() + ' wow'));
|
post.setContent(generate());
|
||||||
post.setUser(user);
|
post.setUser(user);
|
||||||
post.setPostDate(new Date(new Date() - (Math.random() * 1000000)));
|
|
||||||
|
curDate = new Date(curDate - (Math.random() * 1000000));
|
||||||
|
post.setPostDate(curDate);
|
||||||
|
|
||||||
document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
|
document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0; i < Math.round(50 * Math.random()); i++)
|
for(var i = 0; i < Math.round(50 * Math.random()); i++)
|
||||||
addRandomPost();
|
addRandomPost();
|
||||||
|
|
||||||
function viewProfile(id, name) {
|
function viewProfile(id, name) {
|
||||||
document.getElementById("onionr-profile-username").innerHTML = encodeHTML(decodeURIComponent(name));
|
document.getElementById("onionr-profile-username").innerHTML = encodeHTML(decodeURIComponent(name));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue