yetty 0.0.1 → 0.1.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/LICENSE +0 -0
- data/README.md +66 -0
- data/bin/yetty +9 -4
- data/lib/yetty.rb +15 -0
- data/lib/yetty/command.rb +136 -0
- data/lib/yetty/play.rb +23 -0
- data/lib/yetty/push.rb +44 -0
- data/lib/yetty/record.rb +73 -0
- data/lib/yetty/site.rb +23 -0
- data/lib/yetty/site/app.rb +91 -0
- data/lib/yetty/site/static/assets/term/bg-gradient.png +0 -0
- data/lib/yetty/site/static/config.rb +26 -0
- data/lib/yetty/site/static/css/fd-slider.css +1004 -0
- data/lib/yetty/site/static/css/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
- data/lib/yetty/site/static/css/fonts/bootstrap/glyphicons-halflings-regular.svg +229 -0
- data/lib/yetty/site/static/css/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
- data/lib/yetty/site/static/css/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
- data/lib/yetty/site/static/css/player.css +165 -0
- data/lib/yetty/site/static/css/styles.css +8035 -0
- data/lib/yetty/site/static/js/bootstrap.js +2323 -0
- data/lib/yetty/site/static/js/bootstrap.min.js +12 -0
- data/lib/yetty/site/static/js/config.json +429 -0
- data/lib/yetty/site/static/js/jquery-2.1.1.min.js +4 -0
- data/lib/yetty/site/static/js/nyan/runner.js +92 -0
- data/lib/yetty/site/static/js/nyan/three.min.js +724 -0
- data/lib/yetty/site/static/js/nyan/threex.nyancat.js +193 -0
- data/lib/yetty/site/static/js/nyan/threex.nyancatrainbow.js +89 -0
- data/lib/yetty/site/static/js/nyan/threex.nyancatsound.js +33 -0
- data/lib/yetty/site/static/js/nyan/threex.nyancatstars.js +116 -0
- data/lib/yetty/site/static/js/player/fd-slider.min.js +2 -0
- data/lib/yetty/site/static/js/player/player.js +371 -0
- data/lib/yetty/site/static/js/player/term.js +4177 -0
- data/lib/yetty/site/static/sass/_bootstrap-variables.scss +818 -0
- data/lib/yetty/site/static/sass/player.scss +139 -0
- data/lib/yetty/site/static/sass/styles.scss +3 -0
- data/lib/yetty/site/static/sounds/nyanlooped.mp3 +0 -0
- data/lib/yetty/site/static/sounds/nyanslow.mp3 +0 -0
- data/lib/yetty/site/views/about.haml +8 -0
- data/lib/yetty/site/views/index.haml +13 -0
- data/lib/yetty/site/views/layout.haml +33 -0
- data/lib/yetty/site/views/recording.haml +34 -0
- data/lib/yetty/site/views/recordings.haml +7 -0
- data/lib/yetty/site/views/user.haml +28 -0
- data/lib/yetty/site/views/users.haml +16 -0
- data/lib/yetty/ui.rb +103 -0
- data/lib/yetty/user.rb +42 -0
- data/lib/yetty/version.rb +4 -0
- data/yetty.gemspec +21 -0
- metadata +49 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f45bd672b89d1030a4d3dc6c661c9509feb07d0
|
4
|
+
data.tar.gz: 8e357c6886ad138f1c56cd727ac340d62fcad281
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a98db022addf0ad2ff0ad3fc2864454e9ad365b666620331cd73b665b23358a8aad67855a907fe2c132434392f1992540d0a1a1511fee92158cd3a1ab9cc97b6
|
7
|
+
data.tar.gz: 21bad94340f8d3769204c587cdc4f0678aac9c87160f1b6aed8af17d7cbc24784fcd9f755dc8d6be4b2c9bea6caba2f5605d1ac0d889171112f86266c829bae8
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
File without changes
|
data/README.md
CHANGED
@@ -0,0 +1,66 @@
|
|
1
|
+
## Yetty
|
2
|
+
|
3
|
+
With shelr.tv[1] now defunct, I wanted an easy way to spin out
|
4
|
+
my own to easily share terminal recordings. Yetty is a wrapper
|
5
|
+
around shelr[2] that removes some of the extra features it
|
6
|
+
provids. It also has a very simple web UI builtin that hooks into
|
7
|
+
an object store to persist dump files.
|
8
|
+
|
9
|
+
### Is it secure?
|
10
|
+
|
11
|
+
No, not at all. This is configuration based and user uploads are
|
12
|
+
simply prefixed within the bucket. But this is just a friendly
|
13
|
+
tool, so if bad things happen, maybe your friends aren't so friendly.
|
14
|
+
|
15
|
+
### Web UI?
|
16
|
+
|
17
|
+
Yep. It's a very simple sinatra application. It pulls information
|
18
|
+
directly from the object store. So not built for speed or scale.
|
19
|
+
|
20
|
+
### Private?
|
21
|
+
|
22
|
+
Kinda. Private pushes are simply not listed publicly. So you'll need
|
23
|
+
the direct link to access them (much like private gists).
|
24
|
+
|
25
|
+
### Configuration
|
26
|
+
|
27
|
+
Configuration is a JSON file. Locations checked in order of precedence:
|
28
|
+
|
29
|
+
* ./yetty
|
30
|
+
* ~/.yetty
|
31
|
+
* /etc/yetty/config.json
|
32
|
+
|
33
|
+
File contents:
|
34
|
+
|
35
|
+
```json
|
36
|
+
{
|
37
|
+
"site": {
|
38
|
+
"url": "http://localhost:4000"
|
39
|
+
},
|
40
|
+
"user": {
|
41
|
+
"username": "YOUR_USERNAME",
|
42
|
+
"storage": {
|
43
|
+
"provider": "aws",
|
44
|
+
"bucket": "my-yetty-bucket",
|
45
|
+
"credentials": {
|
46
|
+
"aws_access_key_id": "...",
|
47
|
+
"aws_secret_access_key": "...",
|
48
|
+
"aws_bucket_region": "..."
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
```
|
54
|
+
|
55
|
+
The `credentials` section are the credentials expected
|
56
|
+
by miasma[3] based on the provider in use.
|
57
|
+
|
58
|
+
### Thanks!
|
59
|
+
|
60
|
+
A big thanks to @antono for the shelr[2] library. Also
|
61
|
+
to @jeromeetienne for the beautiful nyancat[4]
|
62
|
+
|
63
|
+
[1]: https://github.com/antono/shelr.tv "record you shell and publish it"
|
64
|
+
[2]: https://github.com/antono/shelr "Console screencasting tool"
|
65
|
+
[3]: https://github.com/chrisroberts/miasma "Cloud modeling library"
|
66
|
+
[4]: https://github.com/jeromeetienne/threex.nyancat "three.js extension to make nyancat"
|
data/bin/yetty
CHANGED
@@ -23,7 +23,6 @@ begin
|
|
23
23
|
description 'Push JSON recording'
|
24
24
|
on :c, :config=, 'JSON configuration file'
|
25
25
|
on :p, :private, 'Not publicly listed'
|
26
|
-
on :o, :overwrite, 'Overwrite if already exists'
|
27
26
|
run do |opts, args|
|
28
27
|
Yetty::Push.new({:push => opts.to_hash}, args).execute!
|
29
28
|
end
|
@@ -37,11 +36,17 @@ begin
|
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
39
|
+
command 'play' do
|
40
|
+
description 'Play terminal'
|
41
|
+
run do |opts, args|
|
42
|
+
Yetty::Play.new({:play => opts}, args).execute!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
40
46
|
command 'user' do
|
41
|
-
description '
|
42
|
-
on :c, :config=, 'JSON configuration file'
|
47
|
+
description 'Set user information'
|
43
48
|
run do |opts, args|
|
44
|
-
Yetty::
|
49
|
+
Yetty::User.new({:user => opts.to_hash}, args).execute!
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
data/lib/yetty.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'yetty/version'
|
2
|
+
|
3
|
+
# TTY utility
|
4
|
+
module Yetty
|
5
|
+
autoload :Command, 'yetty/command'
|
6
|
+
autoload :Play, 'yetty/play'
|
7
|
+
autoload :Push, 'yetty/push'
|
8
|
+
autoload :Record, 'yetty/record'
|
9
|
+
autoload :Site, 'yetty/site'
|
10
|
+
autoload :Ui, 'yetty/ui'
|
11
|
+
autoload :User, 'yetty/user'
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'miasma'
|
15
|
+
require 'miasma/utils/smash'
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'yetty'
|
2
|
+
|
3
|
+
module Yetty
|
4
|
+
# Abstract command class
|
5
|
+
class Command
|
6
|
+
|
7
|
+
# @return [Hash] options
|
8
|
+
attr_reader :options
|
9
|
+
# @return [Array] cli arguments
|
10
|
+
attr_reader :arguments
|
11
|
+
# @return [Ui]
|
12
|
+
attr_reader :ui
|
13
|
+
|
14
|
+
# Default configuration file locations
|
15
|
+
DEFAULT_CONFIGURATION_FILES = [
|
16
|
+
'./.yetty',
|
17
|
+
'~/.yetty',
|
18
|
+
'/etc/yetty/config.json'
|
19
|
+
]
|
20
|
+
|
21
|
+
# Build new command instance
|
22
|
+
#
|
23
|
+
# @return [self]
|
24
|
+
def initialize(opts, args)
|
25
|
+
@options = opts.to_smash
|
26
|
+
@arguments = args
|
27
|
+
@ui = Ui.new
|
28
|
+
load_config!
|
29
|
+
end
|
30
|
+
|
31
|
+
# Execute the command
|
32
|
+
#
|
33
|
+
# @return [TrueClass]
|
34
|
+
def execute!
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
# Command specific options
|
41
|
+
#
|
42
|
+
# @return [Hash]
|
43
|
+
def opts
|
44
|
+
options.fetch(self.class.name.split('::').last.downcase, {})
|
45
|
+
end
|
46
|
+
|
47
|
+
# User specific options
|
48
|
+
#
|
49
|
+
# @return [Smash]
|
50
|
+
def user
|
51
|
+
result = options[:user]
|
52
|
+
unless(result)
|
53
|
+
raise 'No user information defined!'
|
54
|
+
else
|
55
|
+
result = result.to_smash
|
56
|
+
unless(result[:username])
|
57
|
+
result[:username] = ENV['USER']
|
58
|
+
end
|
59
|
+
result
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Miasma::Models::Storage]
|
64
|
+
def storage
|
65
|
+
if(user[:storage])
|
66
|
+
Miasma.api(
|
67
|
+
:type => :storage,
|
68
|
+
:provider => user[:storage][:provider],
|
69
|
+
:credentials => user[:storage][:credentials]
|
70
|
+
)
|
71
|
+
else
|
72
|
+
raise 'No remote storage configuration found!'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [Miasma::Models::Storage::Bucket]
|
77
|
+
def bucket
|
78
|
+
unless(user.get(:storage, :bucket))
|
79
|
+
raise 'No bucket defined within storage configuration!'
|
80
|
+
end
|
81
|
+
bucket = storage.buckets.get(user[:storage][:bucket])
|
82
|
+
unless(bucket)
|
83
|
+
bucket = storage.buckets.build
|
84
|
+
bucket.name = user[:storage][:bucket]
|
85
|
+
bucket.save
|
86
|
+
bucket = storage.buckets.reload.get(user[:storage][:bucket])
|
87
|
+
end
|
88
|
+
bucket
|
89
|
+
end
|
90
|
+
|
91
|
+
# Load configuration file and merge opts
|
92
|
+
# on top of file values
|
93
|
+
#
|
94
|
+
# @return [Hash]
|
95
|
+
def load_config!
|
96
|
+
if(options[:config])
|
97
|
+
content = File.read(options[:config])
|
98
|
+
else
|
99
|
+
path = DEFAULT_CONFIGURATION_FILES.detect do |check|
|
100
|
+
full_check = File.expand_path(check)
|
101
|
+
File.exists?(full_check)
|
102
|
+
end
|
103
|
+
content = File.read(path) if path
|
104
|
+
end
|
105
|
+
if(content)
|
106
|
+
@options = MultiJson.load(content).to_smash.deep_merge(options)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Wrap action within nice text. Output resulting Hash if provided
|
111
|
+
#
|
112
|
+
# @param msg [String] message of action in progress
|
113
|
+
# @yieldblock action to execute
|
114
|
+
# @yieldreturn [Hash] result to output
|
115
|
+
# @return [TrueClass]
|
116
|
+
def run_action(msg)
|
117
|
+
ui.info("#{msg}... ", :nonewline)
|
118
|
+
begin
|
119
|
+
result = yield
|
120
|
+
ui.puts ui.color('complete!', :green, :bold)
|
121
|
+
if(result.is_a?(Hash))
|
122
|
+
ui.puts '---> Results:'
|
123
|
+
result.each do |k,v|
|
124
|
+
ui.puts " #{ui.color("#{k}:", :bold)} #{v}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
rescue => e
|
128
|
+
ui.puts ui.color('error!', :red, :bold)
|
129
|
+
ui.error "Reason - #{e}"
|
130
|
+
raise
|
131
|
+
end
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
data/lib/yetty/play.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'yetty'
|
2
|
+
require 'shelr'
|
3
|
+
|
4
|
+
module Yetty
|
5
|
+
class Player < Shelr::Player
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Yetty
|
10
|
+
# Play command class
|
11
|
+
class Play < Command
|
12
|
+
|
13
|
+
# Invoke shelr record
|
14
|
+
def execute!
|
15
|
+
if(arguments.first.start_with?('http'))
|
16
|
+
Yetty::Player.play_remote(arguments.first)
|
17
|
+
else
|
18
|
+
Yetty::Player.play_dump(arguments.first)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/yetty/push.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'yetty'
|
2
|
+
|
3
|
+
module Yetty
|
4
|
+
# Push command class
|
5
|
+
class Push < Command
|
6
|
+
|
7
|
+
# Push shelr json to storage
|
8
|
+
def execute!
|
9
|
+
run_action('Updating user list') do
|
10
|
+
file = bucket.files.get('userlist.json')
|
11
|
+
content = file ? MultiJson.load(file.body.readpartial).to_smash : Smash.new(:users => [])
|
12
|
+
unless(content[:users].include?(user[:username]))
|
13
|
+
content[:users].push(user[:username]).uniq!
|
14
|
+
file = bucket.files.build
|
15
|
+
file.name = 'userlist.json'
|
16
|
+
file.content_type = 'application/json'
|
17
|
+
file.body = MultiJson.dump(content)
|
18
|
+
file.save
|
19
|
+
end
|
20
|
+
end
|
21
|
+
filename = arguments.first
|
22
|
+
run_action("Pushing file #{filename}") do
|
23
|
+
key_name = File.basename(filename).sub(/\.[^\.]+$/, '')
|
24
|
+
file_content = File.read(filename)
|
25
|
+
data = MultiJson.load(file_content).to_smash
|
26
|
+
state = data[:private] || options[:push][:private] ? 'private' : 'public'
|
27
|
+
key_name = File.join(user[:username], state, "#{Time.now.to_i}-#{key_name}.json")
|
28
|
+
file = bucket.files.build
|
29
|
+
file.name = key_name
|
30
|
+
file.content_type = 'application/json'
|
31
|
+
file.body = file_content
|
32
|
+
file.save
|
33
|
+
encoded_key = Base64.urlsafe_encode64(file.name)
|
34
|
+
Smash.new(
|
35
|
+
:bucket => bucket.name,
|
36
|
+
:key => file.name,
|
37
|
+
:encoded_key => encoded_key,
|
38
|
+
:link => options.get(:site, :url) ? File.join(options[:site][:url], 'recording', encoded_key) : 'Not configured!'
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/lib/yetty/record.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'yetty'
|
2
|
+
require 'shelr'
|
3
|
+
|
4
|
+
module Yetty
|
5
|
+
|
6
|
+
class Publisher < Shelr::Publisher
|
7
|
+
|
8
|
+
attr_reader :file_name
|
9
|
+
|
10
|
+
def initialize(file_name='yetty.json')
|
11
|
+
@file_name = file_name
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
def prepare(id)
|
16
|
+
out = {}
|
17
|
+
['meta', 'timing', 'typescript'].each do |file|
|
18
|
+
out[file] = File.read(File.join(Shelr.data_dir(id), file))
|
19
|
+
end
|
20
|
+
|
21
|
+
meta = JSON.parse(out.delete('meta'))
|
22
|
+
meta.each { |k,v| out[k] = v }
|
23
|
+
STDOUT.print 'Description: '
|
24
|
+
out['description'] = STDIN.gets.strip
|
25
|
+
STDOUT.print 'Tags (ex: howto, linux): '
|
26
|
+
out['tags'] = STDIN.gets.strip
|
27
|
+
out['private'] = @private
|
28
|
+
return out.to_json
|
29
|
+
end
|
30
|
+
|
31
|
+
def dump_filename
|
32
|
+
file_name
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
class Recorder < Shelr::Recorder
|
38
|
+
|
39
|
+
def record!(options={})
|
40
|
+
ensure_terminal_has_good_size
|
41
|
+
check_record_dir
|
42
|
+
with_lock_file do
|
43
|
+
init_terminal
|
44
|
+
request_metadata
|
45
|
+
Shelr.terminal.puts_line
|
46
|
+
STDOUT.puts "=> Your session started"
|
47
|
+
STDOUT.puts "=> Please, do not resize your terminal while recording"
|
48
|
+
STDOUT.puts "=> Press Ctrl+D or 'exit' to finish recording"
|
49
|
+
Shelr.terminal.puts_line
|
50
|
+
start_sound_recording if options[:sound]
|
51
|
+
system(recorder_cmd)
|
52
|
+
stop_sound_recording if options[:sound]
|
53
|
+
save_as_typescript if Shelr.backend == 'ttyrec'
|
54
|
+
Shelr.terminal.puts_line
|
55
|
+
STDOUT.puts "=> Session finished"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module Yetty
|
63
|
+
# Record command class
|
64
|
+
class Record < Command
|
65
|
+
|
66
|
+
# Invoke shelr record
|
67
|
+
def execute!
|
68
|
+
Yetty::Recorder.record!(opts)
|
69
|
+
Yetty::Publisher.new(arguments.first || 'yetty.json').dump('last')
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
data/lib/yetty/site.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'yetty'
|
2
|
+
|
3
|
+
module Yetty
|
4
|
+
class Site < Yetty::Command
|
5
|
+
|
6
|
+
autoload :App, 'yetty/site/app'
|
7
|
+
|
8
|
+
# Start the web UI
|
9
|
+
#
|
10
|
+
# @return true
|
11
|
+
def execute!
|
12
|
+
if(opts[:port])
|
13
|
+
App.port = opts[:port]
|
14
|
+
end
|
15
|
+
if(opts[:bind])
|
16
|
+
App.bind = opts[:bind]
|
17
|
+
end
|
18
|
+
App.server = options.fetch(:server, 'webrick')
|
19
|
+
App.run!
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'sinatra/base'
|
3
|
+
|
4
|
+
module Yetty
|
5
|
+
class Site
|
6
|
+
# Web UI
|
7
|
+
class App < Sinatra::Base
|
8
|
+
|
9
|
+
def bucket
|
10
|
+
storage = Miasma.api(
|
11
|
+
:type => :storage,
|
12
|
+
:provider => :aws,
|
13
|
+
:credentials => {
|
14
|
+
:aws_access_key_id => ENV['MIASMA_AWS_ACCESS_KEY_ID'],
|
15
|
+
:aws_secret_access_key => ENV['MIASMA_AWS_SECRET_ACCESS_KEY'],
|
16
|
+
:aws_region => ENV['MIASMA_AWS_REGION'],
|
17
|
+
:aws_bucket_region => 'us-west-2'
|
18
|
+
}
|
19
|
+
)
|
20
|
+
bucket = storage.buckets.get('cr-test-00')
|
21
|
+
end
|
22
|
+
|
23
|
+
set :public_folder, File.join(File.dirname(__FILE__), 'static')
|
24
|
+
|
25
|
+
get '/' do
|
26
|
+
haml :index
|
27
|
+
end
|
28
|
+
|
29
|
+
get '/recordings' do
|
30
|
+
haml :recordings
|
31
|
+
end
|
32
|
+
|
33
|
+
get '/recording/:info' do
|
34
|
+
rec_path = Base64.urlsafe_decode64(params[:info])
|
35
|
+
user, state, name = rec_path.split('/')
|
36
|
+
rec_url = bucket.files.get(rec_path).url
|
37
|
+
haml(
|
38
|
+
:recording,
|
39
|
+
:locals => {
|
40
|
+
:user => user,
|
41
|
+
:state => state,
|
42
|
+
:name => name,
|
43
|
+
:url => rec_url
|
44
|
+
}
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
get '/users' do
|
49
|
+
file = bucket.files.get('userlist.json')
|
50
|
+
users = file ? MultiJson.load(file.body.readpartial).to_smash[:users] : []
|
51
|
+
haml(
|
52
|
+
:users,
|
53
|
+
:locals => {
|
54
|
+
:users => users
|
55
|
+
}
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
get '/users/:username' do
|
60
|
+
user_file = bucket.files.get(
|
61
|
+
File.join(params[:username], 'userinfo.json')
|
62
|
+
)
|
63
|
+
if(user_file)
|
64
|
+
user_info = MultiJson.load(user_file.read).to_smash
|
65
|
+
else
|
66
|
+
user_info = Smash.new
|
67
|
+
end
|
68
|
+
prefix = [params[:username], 'public'].join('/')
|
69
|
+
records = bucket.files.filter(
|
70
|
+
:prefix => [
|
71
|
+
params[:username],
|
72
|
+
'public'
|
73
|
+
].join('/')
|
74
|
+
)
|
75
|
+
haml(
|
76
|
+
:user,
|
77
|
+
:locals => {
|
78
|
+
:username => params[:username],
|
79
|
+
:user_info => user_info,
|
80
|
+
:records => records
|
81
|
+
}
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
get '/about' do
|
86
|
+
haml :about
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|