gridcli 0.0.5 → 0.0.6
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.
- data/README.rdoc +39 -3
- data/gridcli.gemspec +1 -0
- data/lib/gridcli/commands/base.rb +21 -0
- data/lib/gridcli/commands/dislike.rb +2 -1
- data/lib/gridcli/commands/friends.rb +1 -1
- data/lib/gridcli/commands/help.rb +1 -1
- data/lib/gridcli/commands/like.rb +2 -1
- data/lib/gridcli/commands/list.rb +2 -1
- data/lib/gridcli/commands/message.rb +19 -8
- data/lib/gridcli/commands/plugin.rb +28 -0
- data/lib/gridcli/commands/pprint.rb +3 -5
- data/lib/gridcli/commands/profile.rb +13 -1
- data/lib/gridcli/commands/search.rb +2 -1
- data/lib/gridcli/commands/signup.rb +2 -0
- data/lib/gridcli/commands/status.rb +3 -2
- data/lib/gridcli/commands/subgrid.rb +30 -0
- data/lib/gridcli/commands/update.rb +7 -5
- data/lib/gridcli/config.rb +2 -18
- data/lib/gridcli/hooks.rb +15 -0
- data/lib/gridcli/plugins.rb +39 -0
- data/lib/gridcli/pprinter.rb +117 -30
- data/lib/gridcli/resources/post.rb +26 -4
- data/lib/gridcli/resources/user.rb +4 -0
- data/lib/gridcli/stats.rb +13 -0
- data/lib/gridcli/storage/base.rb +2 -2
- data/lib/gridcli/storage/files.rb +6 -4
- data/lib/gridcli/subgrids.rb +35 -0
- data/lib/gridcli/version.rb +1 -1
- data/lib/gridcli/ymlhash.rb +28 -0
- data/lib/gridcli.rb +32 -12
- metadata +33 -11
- data/TODO +0 -13
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= gridcli -- A command line interface to The Grid
|
2
2
|
|
3
|
-
The Grid is a command line social network that is
|
3
|
+
The Grid is a command line social network that is fast, modular, and simple.
|
4
4
|
|
5
5
|
To install:
|
6
6
|
gem install gridcli
|
@@ -14,7 +14,9 @@ To show your profile:
|
|
14
14
|
grid profile
|
15
15
|
|
16
16
|
To update your profile:
|
17
|
-
grid profile [--github-username <username>] [--name <name>]
|
17
|
+
grid profile [--github-username <username>] [--name <name>] [--avatar <avatar text file>]
|
18
|
+
|
19
|
+
If you want a profile pic, use a program like jp2a to convert a jpeg image to ascii format first.
|
18
20
|
|
19
21
|
To show someone else's profile:
|
20
22
|
grid profile <username>
|
@@ -28,7 +30,7 @@ To list your friends:
|
|
28
30
|
|
29
31
|
== Messaging
|
30
32
|
To send a message to a list of users:
|
31
|
-
grid message <username>[,<username>,...] [<subject>] <body>
|
33
|
+
grid message <username>[,<username>,...] [-s <subject>] [-b <body>] [-f <body file>]
|
32
34
|
|
33
35
|
To send a status update, like, or dislike to your friends:
|
34
36
|
grid status <status message>
|
@@ -49,6 +51,9 @@ The <when> parameter is free form text and can be a range ("x to y"). For insta
|
|
49
51
|
grid search message "chronic" "two weeks ago to today"
|
50
52
|
grid search all "the grid" "1 month ago to last week"
|
51
53
|
|
54
|
+
You can see your messages in your ~/.grid directory. For instance, if you want to search all likes using grep:
|
55
|
+
grep -RiI ~/.grid/like "grid"
|
56
|
+
|
52
57
|
== Listing Posts
|
53
58
|
You can list any type (or all types) of posts.
|
54
59
|
grid list <like|dislike|message|status|all> [<when>]
|
@@ -65,6 +70,37 @@ To block another user:
|
|
65
70
|
|
66
71
|
This will "unfriend" them and they will no longer see your posts.
|
67
72
|
|
73
|
+
== Subgrids
|
74
|
+
Subgrids are groups that you manage and are defined in a local config file.
|
75
|
+
|
76
|
+
To create a subgrid, use:
|
77
|
+
grid subgrid @mygroup bob,john,snakeplisskin
|
78
|
+
|
79
|
+
To see what subgrids exist:
|
80
|
+
grid subgrid
|
81
|
+
|
82
|
+
To see what users are in a particular subgrid:
|
83
|
+
grid subgrid @mygroup
|
84
|
+
|
85
|
+
You can then use the group as though it were a user. For instance, to send a message to @mygroup:
|
86
|
+
grid message @mygroup -s "hey guys" -b "Let's go make a rum ham."
|
87
|
+
|
88
|
+
If you prefer to simply edit the config file, you can do so (the file is located at ~/.grid/subgrids).
|
89
|
+
|
90
|
+
== Plugins
|
91
|
+
Plugins are easy to create and can register hooks. To install/uninstall a plugin, use:
|
92
|
+
grid plugin install <name>
|
93
|
+
grid plugin uninstall <name>
|
94
|
+
|
95
|
+
To see a list of installed plugins:
|
96
|
+
grid plugin
|
68
97
|
|
98
|
+
An example plugin is the echo plugin:
|
99
|
+
grid plugin install echo
|
69
100
|
|
101
|
+
This command will install the gem "grid-plugin-echo" and load it each time the gridcli gem is loaded. It uses the available hooks:
|
102
|
+
* before_post_creation(post_hash)
|
103
|
+
* before_signup(username)
|
104
|
+
* before_update
|
70
105
|
|
106
|
+
and prints out a message whenever a user signs up, a post is created, or the update command is called. You can see the code for the echo module at https://github.com/bmuller/grid-plugin-echo.
|
data/gridcli.gemspec
CHANGED
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
s.add_dependency("activeresource", ">= 3.0.10")
|
18
|
+
s.add_dependency("activesupport", ">= 3.0.10")
|
18
19
|
s.add_dependency("chronic", ">= 0.6.4")
|
19
20
|
s.add_dependency("json", ">= 1.6.1")
|
20
21
|
s.add_dependency("colorize", ">= 0.5.8")
|
@@ -7,6 +7,7 @@ module GridCLI
|
|
7
7
|
|
8
8
|
def initialize(cmd, desc, default_opts = nil)
|
9
9
|
@config = GridCLI.config
|
10
|
+
@stats = GridCLI.stats
|
10
11
|
@cmd = cmd
|
11
12
|
@desc = desc
|
12
13
|
@opts = default_opts || {}
|
@@ -19,6 +20,21 @@ module GridCLI
|
|
19
20
|
@optp.on(*args) { |u| yield u }
|
20
21
|
end
|
21
22
|
|
23
|
+
def add_format_option
|
24
|
+
msg = "Specify output format (json, cmdcolor, cmd, textline)"
|
25
|
+
add_option("-o format", "--output-format format", msg) { |o|
|
26
|
+
@opts[:output_format] = o
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def output_format
|
31
|
+
@opts[:output_format] || "cmdcolor"
|
32
|
+
end
|
33
|
+
|
34
|
+
def pprint(json)
|
35
|
+
puts PrettyPrinter.new(json, output_format)
|
36
|
+
end
|
37
|
+
|
22
38
|
def usage(cmd_opts=nil)
|
23
39
|
cmd_opts ||= ""
|
24
40
|
@optp.banner = "Usage: grid #{@cmd} #{cmd_opts} [options]"
|
@@ -26,6 +42,11 @@ module GridCLI
|
|
26
42
|
exit
|
27
43
|
end
|
28
44
|
|
45
|
+
def error(msg)
|
46
|
+
puts msg
|
47
|
+
exit 1
|
48
|
+
end
|
49
|
+
|
29
50
|
def parse_dates(datestring)
|
30
51
|
dates = [nil, nil]
|
31
52
|
return dates if datestring.nil? or datestring.strip == ""
|
@@ -2,6 +2,7 @@ module GridCLI
|
|
2
2
|
class DislikeCommand < BaseCommand
|
3
3
|
def initialize
|
4
4
|
super "dislike", "Dislike something."
|
5
|
+
add_format_option
|
5
6
|
end
|
6
7
|
|
7
8
|
def usage
|
@@ -21,7 +22,7 @@ module GridCLI
|
|
21
22
|
return
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
+
pprint post.to_post_json
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -17,7 +17,7 @@ module GridCLI
|
|
17
17
|
log "Getting all friends of '#{username}'"
|
18
18
|
friends = Friendship.find(:all, :params => { :id => username })
|
19
19
|
friends.each { |f|
|
20
|
-
|
20
|
+
pprint f.user.to_json
|
21
21
|
}
|
22
22
|
puts "You have no friends :(" if friends.length == 0
|
23
23
|
rescue ActiveResource::ForbiddenAccess
|
@@ -2,6 +2,7 @@ module GridCLI
|
|
2
2
|
class LikeCommand < BaseCommand
|
3
3
|
def initialize
|
4
4
|
super "like", "Like something."
|
5
|
+
add_format_option
|
5
6
|
end
|
6
7
|
|
7
8
|
def usage
|
@@ -21,7 +22,7 @@ module GridCLI
|
|
21
22
|
return
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
+
pprint post.to_post_json
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -2,6 +2,7 @@ module GridCLI
|
|
2
2
|
class ListCommand < BaseCommand
|
3
3
|
def initialize
|
4
4
|
super "list", "List posts of a particular kind or all posts"
|
5
|
+
add_format_option
|
5
6
|
end
|
6
7
|
|
7
8
|
def usage
|
@@ -16,7 +17,7 @@ module GridCLI
|
|
16
17
|
parse_opts args
|
17
18
|
|
18
19
|
log "Showing #{type} posts in range #{dates.first || 'first'} - #{dates.last || 'last'}"
|
19
|
-
GridCLI.storage.list(type, dates[0], dates[1])
|
20
|
+
GridCLI.storage.list(type, dates[0], dates[1], output_format)
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
@@ -1,24 +1,35 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
|
1
3
|
module GridCLI
|
2
4
|
class MessageCommand < BaseCommand
|
3
5
|
def initialize
|
4
6
|
super "message", "Send a message to a friend or group of friends."
|
7
|
+
add_option("-s subject", "--subject subject", "Subject for message") { |s| @opts[:subject] = s }
|
8
|
+
add_option("-f file", "--file file", "File to use for message body") { |f| @opts[:file] = f }
|
9
|
+
add_option("-b body", "--body body", "Message body") { |b| @opts[:body] = b }
|
10
|
+
add_format_option
|
5
11
|
end
|
6
12
|
|
7
13
|
def usage
|
8
|
-
super "<username>[,<username>,...]
|
14
|
+
super "<username>[,<username>,...]"
|
9
15
|
end
|
10
16
|
|
11
17
|
def run(args)
|
12
18
|
usage if args.length < 2
|
13
19
|
recipients = args.shift
|
14
|
-
if args.length > 1 and not args[1].start_with?('-')
|
15
|
-
subject = args.shift
|
16
|
-
else
|
17
|
-
subject = args.first.slice(0,30) + "..."
|
18
|
-
end
|
19
|
-
body = args.shift
|
20
20
|
parse_opts args
|
21
21
|
|
22
|
+
body = nil
|
23
|
+
if not @opts[:file].nil?
|
24
|
+
error("File '#{@opts[:file]}' does not exist.") unless File.exists? @opts[:file]
|
25
|
+
body = File.read(@opts[:file])
|
26
|
+
elsif not @opts[:body].nil?
|
27
|
+
body = @opts[:body]
|
28
|
+
end
|
29
|
+
|
30
|
+
error("Body cannot be blank. Use one of -f or -b") if body.nil?
|
31
|
+
subject = @opts[:subject].nil? ? body.truncate(30) : @opts[:subject]
|
32
|
+
|
22
33
|
begin
|
23
34
|
log "Trying to send a message '#{subject}' to '#{recipients}'"
|
24
35
|
post = Post::Message.create :subject => subject, :body => body, :recipients => recipients, :posttype => 'message'
|
@@ -27,7 +38,7 @@ module GridCLI
|
|
27
38
|
return
|
28
39
|
end
|
29
40
|
|
30
|
-
|
41
|
+
pprint post.to_post_json
|
31
42
|
end
|
32
43
|
end
|
33
44
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module GridCLI
|
2
|
+
class PluginCommand < BaseCommand
|
3
|
+
def initialize
|
4
|
+
super "plugin", "Install / uninstall plugins"
|
5
|
+
end
|
6
|
+
|
7
|
+
def usage
|
8
|
+
super "[<install|uninstall> <name>]"
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(args)
|
12
|
+
if args.length == 0
|
13
|
+
puts "The following plugins are installed: "
|
14
|
+
puts GridCLI.plugins['enabled'].join(', ')
|
15
|
+
elsif args.length == 2 and args.first == "install"
|
16
|
+
log "Attempting to install gem grid-plugin-#{args[1]}"
|
17
|
+
GridCLI.plugins.install args[1]
|
18
|
+
elsif args.length == 2 and args.first == "uninstall"
|
19
|
+
log "Attempting to uninstall gem grid-plugin-#{args[1]}"
|
20
|
+
GridCLI.plugins.uninstall args[1]
|
21
|
+
else
|
22
|
+
usage
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Runner.register "plugin", PluginCommand
|
28
|
+
end
|
@@ -2,16 +2,14 @@ module GridCLI
|
|
2
2
|
class PPrintCommand < BaseCommand
|
3
3
|
def initialize
|
4
4
|
super "pprint", "A program that will pretty print posts/users"
|
5
|
+
add_format_option
|
5
6
|
end
|
6
7
|
|
7
8
|
def run(args)
|
8
|
-
|
9
|
+
parse_opts args
|
9
10
|
|
10
11
|
ARGV.clear
|
11
|
-
ARGF.each { |line|
|
12
|
-
puts PrettyPrinter.new(line)
|
13
|
-
puts
|
14
|
-
}
|
12
|
+
ARGF.each { |line| pprint(line) }
|
15
13
|
end
|
16
14
|
end
|
17
15
|
|
@@ -10,6 +10,11 @@ module GridCLI
|
|
10
10
|
@opts[:name] = u
|
11
11
|
@opts[:update] = true
|
12
12
|
}
|
13
|
+
add_option("--avatar file", "Set your avatar (a text file)") { |u|
|
14
|
+
@opts[:avatar] = u
|
15
|
+
@opts[:update] = true
|
16
|
+
}
|
17
|
+
add_format_option
|
13
18
|
end
|
14
19
|
|
15
20
|
def usage
|
@@ -34,11 +39,18 @@ module GridCLI
|
|
34
39
|
# if we're supposed to update, do so
|
35
40
|
if @opts[:update]
|
36
41
|
[:github_username, :name].each { |n| user.send("#{n.to_s}=", @opts[n]) }
|
42
|
+
unless @opts[:avatar].nil?
|
43
|
+
if File.exists?(@opts[:avatar])
|
44
|
+
user.avatar = File.read(@opts[:avatar])
|
45
|
+
else
|
46
|
+
error("File #{@opts[:avatar]} does not exist")
|
47
|
+
end
|
48
|
+
end
|
37
49
|
user.id = username
|
38
50
|
user.save
|
39
51
|
end
|
40
52
|
|
41
|
-
|
53
|
+
pprint user.to_json
|
42
54
|
end
|
43
55
|
end
|
44
56
|
|
@@ -2,6 +2,7 @@ module GridCLI
|
|
2
2
|
class SearchCommand < BaseCommand
|
3
3
|
def initialize
|
4
4
|
super "search", "Search posts"
|
5
|
+
add_format_option
|
5
6
|
end
|
6
7
|
|
7
8
|
def usage
|
@@ -18,7 +19,7 @@ module GridCLI
|
|
18
19
|
parse_opts args
|
19
20
|
|
20
21
|
log "Showing #{type} posts in range #{dates.first || 'first'} - #{dates.last || 'last'}"
|
21
|
-
GridCLI.storage.search(type, query, dates[0], dates[1])
|
22
|
+
GridCLI.storage.search(type, query, dates[0], dates[1], output_format)
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
@@ -2,6 +2,7 @@ module GridCLI
|
|
2
2
|
class StatusCommand < BaseCommand
|
3
3
|
def initialize
|
4
4
|
super "status", "Send a status update to all friends."
|
5
|
+
add_format_option
|
5
6
|
end
|
6
7
|
|
7
8
|
def usage
|
@@ -20,8 +21,8 @@ module GridCLI
|
|
20
21
|
puts "There was an error sending your status. Please make sure it's not empty."
|
21
22
|
return
|
22
23
|
end
|
23
|
-
|
24
|
-
|
24
|
+
|
25
|
+
pprint post.to_post_json
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module GridCLI
|
2
|
+
class SubgridCommand < BaseCommand
|
3
|
+
def initialize
|
4
|
+
super "subgrid", "Create / read / update subgrids (groups)"
|
5
|
+
end
|
6
|
+
|
7
|
+
def usage
|
8
|
+
super "[<groupname> [<comma separated list of users>]]"
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(args)
|
12
|
+
subgrids = SubGrids.new
|
13
|
+
|
14
|
+
groups = (args.length == 0) ? subgrids.groups : [args.shift]
|
15
|
+
|
16
|
+
# if setting users...
|
17
|
+
if args.length > 0
|
18
|
+
subgrids.set_group(groups.first, args.first.split(","))
|
19
|
+
end
|
20
|
+
|
21
|
+
groups.each { |gname|
|
22
|
+
error("Group not found: #{gname}") unless subgrids.groups.include? gname
|
23
|
+
puts "#{gname} has users: #{subgrids.get_group(gname).join(', ')}"
|
24
|
+
}
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Runner.register "subgrid", SubgridCommand
|
30
|
+
end
|
@@ -2,11 +2,14 @@ module GridCLI
|
|
2
2
|
class UpdateCommand < BaseCommand
|
3
3
|
def initialize
|
4
4
|
super "update", "Download all messages"
|
5
|
+
add_format_option
|
5
6
|
end
|
6
7
|
|
7
8
|
def run(args)
|
8
9
|
parse_opts args
|
9
|
-
last_sha = @
|
10
|
+
last_sha = @stats['last_sha']
|
11
|
+
|
12
|
+
GridCLI.hooker.invoke :before_update
|
10
13
|
|
11
14
|
begin
|
12
15
|
if last_sha.nil?
|
@@ -32,11 +35,10 @@ module GridCLI
|
|
32
35
|
posts.each { |p|
|
33
36
|
type = p.known_attributes.first
|
34
37
|
json = p.send(type).to_json(:root => type)
|
35
|
-
|
36
|
-
puts
|
38
|
+
pprint json
|
37
39
|
}
|
38
|
-
@
|
39
|
-
@
|
40
|
+
@stats['last_sha'] = GridCLI.storage.append(posts)
|
41
|
+
@stats.save
|
40
42
|
|
41
43
|
# run again if we got back 300 posts
|
42
44
|
run(args) if posts.length == 300
|
data/lib/gridcli/config.rb
CHANGED
@@ -1,19 +1,7 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
1
|
module GridCLI
|
4
|
-
class Config <
|
2
|
+
class Config < YMLHash
|
5
3
|
def initialize
|
6
|
-
|
7
|
-
@griddir = File.expand_path(File.join("~", ".grid"))
|
8
|
-
Dir.mkdir(@griddir) if not File.exists?(@griddir)
|
9
|
-
|
10
|
-
# This is a hash, so initialize it, set w/ default config options, then set
|
11
|
-
# with any config options in the ~/.grid/config file
|
12
|
-
@conffile = File.join(@griddir, "config")
|
13
|
-
super
|
14
|
-
update default_config
|
15
|
-
# if conf file exists, update this obj w/ it's values. Otherwise, create file
|
16
|
-
File.exists?(@conffile) ? update(YAML.load_file(@conffile)) : save
|
4
|
+
super "config"
|
17
5
|
end
|
18
6
|
|
19
7
|
|
@@ -23,9 +11,5 @@ module GridCLI
|
|
23
11
|
'token' => rand(36**31).to_s(36)
|
24
12
|
}
|
25
13
|
end
|
26
|
-
|
27
|
-
def save
|
28
|
-
File.open(@conffile, 'w') { |f| YAML.dump(self, f) }
|
29
|
-
end
|
30
14
|
end
|
31
15
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module GridCLI
|
2
|
+
class Hooker
|
3
|
+
def initialize
|
4
|
+
@hooks = {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def register(name, &method)
|
8
|
+
@hooks[name] = @hooks.fetch(name, []) + [method]
|
9
|
+
end
|
10
|
+
|
11
|
+
def invoke(name, arg=nil)
|
12
|
+
@hooks.fetch(name, []).inject(arg) { |params,proc| proc.call(params) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems/gem_runner'
|
2
|
+
|
3
|
+
module GridCLI
|
4
|
+
class Plugins < YMLHash
|
5
|
+
def initialize
|
6
|
+
super "plugins"
|
7
|
+
end
|
8
|
+
|
9
|
+
def default_config
|
10
|
+
{
|
11
|
+
'enabled' => [],
|
12
|
+
'disabled' => []
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def install(name)
|
17
|
+
name = "grid-plugin-#{name}" unless name.start_with?("grid-plugin-")
|
18
|
+
unless fetch('enabled', []).include? name
|
19
|
+
self['enabled'] << name
|
20
|
+
save
|
21
|
+
end
|
22
|
+
Gem::GemRunner.new.run ["install", name, "--no-rdoc", "--no-ri"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def uninstall(name)
|
26
|
+
name = "grid-plugin-#{name}" unless name.start_with?("grid-plugin-")
|
27
|
+
return unless fetch('enabled', []).include? name
|
28
|
+
self['enabled'].delete(name)
|
29
|
+
save
|
30
|
+
Gem::GemRunner.new.run ["uninstall", name]
|
31
|
+
end
|
32
|
+
|
33
|
+
def include!
|
34
|
+
fetch('enabled', []).each { |m|
|
35
|
+
require m
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/gridcli/pprinter.rb
CHANGED
@@ -2,47 +2,134 @@ require 'json'
|
|
2
2
|
require 'colorize'
|
3
3
|
|
4
4
|
module GridCLI
|
5
|
-
class
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
5
|
+
class PPTextLineFormat
|
6
|
+
def self.all(parsed)
|
7
|
+
parsed.map { |k,v| "#{k}: #{v}" }.join("; ")
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.like(original, parsed)
|
11
|
+
self.all(parsed)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.dislike(original, parsed)
|
15
|
+
self.all(parsed)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.status(original, parsed)
|
19
|
+
self.all(parsed)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.message(original, parsed)
|
23
|
+
self.all(parsed)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.user(original, parsed)
|
27
|
+
self.all(parsed)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class PPCmdFormat
|
32
|
+
def self.like(original, parsed)
|
33
|
+
"on #{@created_at} #{@contents['from_username']} liked #{@contents['body']}\n\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.dislike(original, parsed)
|
37
|
+
"on #{@created_at} #{@contents['from_username']} disliked #{@contents['body']}\n\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.status(original, parsed)
|
41
|
+
"on #{@created_at} #{@contents['from_username']} was #{@contents['body']}\n\n"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.message(original, parsed)
|
45
|
+
s = "Message from: #{parsed['from_username']}\n"
|
46
|
+
s+= "Subject: #{parsed['subject']}\n"
|
47
|
+
s+= "Date: #{parsed['created_at']}\n"
|
48
|
+
s+= "To: #{parsed['recipients']}\n"
|
49
|
+
s+= "#{parsed['body']}\n\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.user(original, parsed)
|
53
|
+
s = "#{parsed['username']}\n"
|
54
|
+
s+= "created: #{parsed['created_at']}\n"
|
55
|
+
(parsed.keys - ['created_at', 'username', 'avatar']).each { |key|
|
56
|
+
next if parsed[key].nil?
|
57
|
+
s += "#{key}: #{parsed[key]}\n"
|
58
|
+
}
|
59
|
+
s+= parsed['avatar'] unless parsed['avatar'].nil?
|
60
|
+
s += "\n"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class PPCmdColorFormat < PPCmdFormat
|
65
|
+
def self.like(original, parsed)
|
66
|
+
super(original, parsed).green
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.dislike(original, parsed)
|
70
|
+
super(original, parsed).red
|
22
71
|
end
|
23
72
|
|
24
|
-
def
|
25
|
-
|
73
|
+
def self.status(original, parsed)
|
74
|
+
super(original, parsed).cyan
|
26
75
|
end
|
27
76
|
|
28
|
-
def
|
29
|
-
"
|
77
|
+
def self.message(original, parsed)
|
78
|
+
s = "Message from: ".cyan + parsed['from_username'] + "\n"
|
79
|
+
s+= "Subject: ".cyan + parsed['subject'] + "\n"
|
80
|
+
s+= "Date: ".cyan + parsed['created_at'] + "\n"
|
81
|
+
s+= "To: ".cyan + parsed['recipients'] + "\n"
|
82
|
+
s+= "#{parsed['body']}\n\n"
|
30
83
|
end
|
31
84
|
|
32
|
-
def
|
33
|
-
"
|
85
|
+
def self.user(original, parsed)
|
86
|
+
s = "username: ".magenta + "#{parsed['username']}\n".yellow
|
87
|
+
s+= "created: ".magenta + "#{parsed['created_at']}\n"
|
88
|
+
(parsed.keys - ['created_at', 'username', 'avatar']).each { |key|
|
89
|
+
next if parsed[key].nil?
|
90
|
+
s += "#{key}: ".magenta + "#{parsed[key]}\n"
|
91
|
+
}
|
92
|
+
s+= parsed['avatar'] unless parsed['avatar'].nil?
|
93
|
+
s += "\n"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
class PrettyPrinter
|
99
|
+
# format can be one of :cmdcolor, :cmd, :textline, :json
|
100
|
+
def initialize(string, format=nil)
|
101
|
+
@format = format.nil? ? :cmdcolor : format.intern
|
102
|
+
@original = string
|
103
|
+
begin
|
104
|
+
j = JSON.parse(string)
|
105
|
+
@type = j.keys.first
|
106
|
+
@contents = j[@type]
|
107
|
+
@contents['created_at'] = Time.parse(@contents['created_at']).localtime.to_s
|
108
|
+
rescue JSON::ParserError
|
109
|
+
@type = nil
|
110
|
+
@format = nil
|
111
|
+
@contents = {}
|
112
|
+
end
|
34
113
|
end
|
35
114
|
|
36
|
-
def
|
37
|
-
|
38
|
-
s+= "Subject: ".cyan + @contents['subject'] + "\n"
|
39
|
-
s+= "Date: ".cyan + @created_at + "\n"
|
40
|
-
s+= "To: ".cyan + @contents['recipients'] + "\n"
|
41
|
-
s+= @contents['body']
|
115
|
+
def formatters
|
116
|
+
{ :cmdcolor => PPCmdColorFormat, :cmd => PPCmdFormat, :textline => PPTextLineFormat }
|
42
117
|
end
|
43
118
|
|
44
119
|
def to_s
|
45
|
-
@
|
120
|
+
formatter = formatters.fetch(@format, nil)
|
121
|
+
# if the format is unknown or :json return original
|
122
|
+
return @original if formatter.nil?
|
123
|
+
|
124
|
+
case @type
|
125
|
+
when "message" then formatter.message(@original, @contents)
|
126
|
+
when "like" then formatter.like(@original, @contents)
|
127
|
+
when "dislike" then formatter.dislike(@original, @contents)
|
128
|
+
when "status" then formatter.status(@original, @contents)
|
129
|
+
when "friend_request" then formatter.message(@original, @contents)
|
130
|
+
when "user" then formatter.user(@original, @contents)
|
131
|
+
else @original #unknown type
|
132
|
+
end
|
46
133
|
end
|
47
134
|
end
|
48
135
|
end
|
@@ -1,15 +1,37 @@
|
|
1
1
|
module GridCLI
|
2
2
|
module Post
|
3
|
-
|
3
|
+
|
4
|
+
class PostBase < BaseResource
|
5
|
+
# before we create, resolve names from subgrid and call hooks
|
6
|
+
def self.create(attributes)
|
7
|
+
subgrids = SubGrids.new
|
8
|
+
users = attributes[:recipients].split(",")
|
9
|
+
attributes[:recipients] = subgrids.resolve(users).join(",")
|
10
|
+
attributes = GridCLI.hooker.invoke :before_post_creation, attributes
|
11
|
+
super attributes
|
12
|
+
end
|
13
|
+
|
14
|
+
# if we just call post.to_json, the root attribute will be "post"
|
15
|
+
# for prettyprint, the root attribute needs to be one of: like,dislike,status,message
|
16
|
+
def to_post_json
|
17
|
+
type = self.class.name.split("::").last.downcase
|
18
|
+
to_json(:root => type)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Message < PostBase
|
4
23
|
self.element_name = "post"
|
5
24
|
end
|
6
|
-
|
25
|
+
|
26
|
+
class Like < PostBase
|
7
27
|
self.element_name = "post"
|
8
28
|
end
|
9
|
-
|
29
|
+
|
30
|
+
class Dislike < PostBase
|
10
31
|
self.element_name = "post"
|
11
32
|
end
|
12
|
-
|
33
|
+
|
34
|
+
class Status < PostBase
|
13
35
|
self.element_name = "post"
|
14
36
|
end
|
15
37
|
end
|
data/lib/gridcli/storage/base.rb
CHANGED
@@ -8,11 +8,11 @@ module GridCLI
|
|
8
8
|
raise "Not implemented"
|
9
9
|
end
|
10
10
|
|
11
|
-
def search(type, query, state_date, end_date)
|
11
|
+
def search(type, query, state_date, end_date, output_format)
|
12
12
|
raise "Not implemented"
|
13
13
|
end
|
14
14
|
|
15
|
-
def list(type, start_date, end_date)
|
15
|
+
def list(type, start_date, end_date, output_format)
|
16
16
|
raise "Not implemented"
|
17
17
|
end
|
18
18
|
end
|
@@ -83,15 +83,17 @@ module GridCLI
|
|
83
83
|
}
|
84
84
|
end
|
85
85
|
|
86
|
-
def search(type, query, start_date, end_date)
|
86
|
+
def search(type, query, start_date, end_date, output_format)
|
87
|
+
options = output_format.nil? ? "" : "-o #{output_format}"
|
87
88
|
files(type, start_date, end_date) { |path|
|
88
|
-
system "grep -R \"#{query}\" #{path} | #{$0} pprint"
|
89
|
+
system "grep -R \"#{query}\" #{path} | #{$0} pprint #{options}"
|
89
90
|
}
|
90
91
|
end
|
91
92
|
|
92
|
-
def list(type, start_date, end_date)
|
93
|
+
def list(type, start_date, end_date, output_format)
|
94
|
+
options = output_format.nil? ? "" : "-o #{output_format}"
|
93
95
|
files(type, start_date, end_date) { |path|
|
94
|
-
system "cat #{path} | #{$0} pprint"
|
96
|
+
system "cat #{path} | #{$0} pprint #{options}"
|
95
97
|
}
|
96
98
|
end
|
97
99
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module GridCLI
|
2
|
+
class SubGrids < YMLHash
|
3
|
+
def initialize
|
4
|
+
super "subgrids"
|
5
|
+
end
|
6
|
+
|
7
|
+
def get_group(group, stack=nil)
|
8
|
+
stack ||= []
|
9
|
+
if stack.include? group
|
10
|
+
puts "Recursive subgrid definition detected."
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
stack << group
|
14
|
+
|
15
|
+
fetch(group, "").split(" ").map { |user|
|
16
|
+
user.start_with?('@') ? get_group(user, stack) : user
|
17
|
+
}.flatten
|
18
|
+
end
|
19
|
+
|
20
|
+
def groups
|
21
|
+
keys
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_group(name, members)
|
25
|
+
self[name] = members.join(" ")
|
26
|
+
save
|
27
|
+
end
|
28
|
+
|
29
|
+
def resolve(userlist)
|
30
|
+
userlist.map { |user|
|
31
|
+
user.start_with?('@') ? get_group(user) : user
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/gridcli/version.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module GridCLI
|
4
|
+
class YMLHash < Hash
|
5
|
+
def initialize(fname)
|
6
|
+
# Initialize the grid dir
|
7
|
+
@griddir = File.expand_path(File.join("~", ".grid"))
|
8
|
+
Dir.mkdir(@griddir) if not File.exists?(@griddir)
|
9
|
+
|
10
|
+
# This is a hash, so initialize it, set w/ default config options, then set
|
11
|
+
# with any config options in the ~/.grid/#{fname} file
|
12
|
+
@conffile = File.join(@griddir, fname)
|
13
|
+
super
|
14
|
+
update default_config
|
15
|
+
# if conf file exists, update this obj w/ it's values. Otherwise, create file
|
16
|
+
File.exists?(@conffile) ? update(YAML.load_file(@conffile)) : save
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def default_config
|
21
|
+
{}
|
22
|
+
end
|
23
|
+
|
24
|
+
def save
|
25
|
+
File.open(@conffile, 'w') { |f| YAML.dump(self, f) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/gridcli.rb
CHANGED
@@ -3,7 +3,12 @@ require 'active_resource'
|
|
3
3
|
require 'gridcli/storage/base'
|
4
4
|
require 'gridcli/storage/files'
|
5
5
|
|
6
|
+
require 'gridcli/ymlhash'
|
6
7
|
require 'gridcli/config'
|
8
|
+
require 'gridcli/subgrids'
|
9
|
+
require 'gridcli/stats'
|
10
|
+
require 'gridcli/hooks'
|
11
|
+
require 'gridcli/plugins'
|
7
12
|
|
8
13
|
module GridCLI
|
9
14
|
def self.config
|
@@ -13,31 +18,46 @@ module GridCLI
|
|
13
18
|
def self.storage
|
14
19
|
@storage ||= FileStorage.new
|
15
20
|
end
|
21
|
+
|
22
|
+
def self.stats
|
23
|
+
@stats ||= Stats.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.hooker
|
27
|
+
@hooker ||= Hooker.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.plugins
|
31
|
+
@plugins ||= Plugins.new
|
32
|
+
end
|
16
33
|
end
|
17
34
|
|
18
|
-
require 'gridcli/version'
|
19
|
-
require 'gridcli/runner'
|
20
35
|
require 'gridcli/pprinter'
|
36
|
+
require 'gridcli/runner'
|
37
|
+
require 'gridcli/version'
|
21
38
|
|
22
39
|
require 'gridcli/commands/base'
|
23
|
-
require 'gridcli/commands/pprint'
|
24
|
-
require 'gridcli/commands/signup'
|
25
|
-
require 'gridcli/commands/help'
|
26
|
-
require 'gridcli/commands/profile'
|
27
40
|
require 'gridcli/commands/befriend'
|
28
41
|
require 'gridcli/commands/block'
|
42
|
+
require 'gridcli/commands/dislike'
|
29
43
|
require 'gridcli/commands/friends'
|
44
|
+
require 'gridcli/commands/help'
|
45
|
+
require 'gridcli/commands/like'
|
46
|
+
require 'gridcli/commands/list'
|
30
47
|
require 'gridcli/commands/message'
|
48
|
+
require 'gridcli/commands/plugin'
|
49
|
+
require 'gridcli/commands/pprint'
|
50
|
+
require 'gridcli/commands/profile'
|
51
|
+
require 'gridcli/commands/search'
|
52
|
+
require 'gridcli/commands/signup'
|
31
53
|
require 'gridcli/commands/status'
|
32
|
-
require 'gridcli/commands/
|
33
|
-
require 'gridcli/commands/dislike'
|
54
|
+
require 'gridcli/commands/subgrid'
|
34
55
|
require 'gridcli/commands/update'
|
35
|
-
require 'gridcli/commands/search'
|
36
|
-
require 'gridcli/commands/list'
|
37
56
|
|
38
57
|
require 'gridcli/resources/base'
|
39
|
-
require 'gridcli/resources/
|
58
|
+
require 'gridcli/resources/blockage'
|
40
59
|
require 'gridcli/resources/friendship'
|
41
60
|
require 'gridcli/resources/post'
|
42
|
-
require 'gridcli/resources/
|
61
|
+
require 'gridcli/resources/user'
|
43
62
|
|
63
|
+
GridCLI.plugins.include!
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gridcli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brian Muller
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-10-
|
18
|
+
date: 2011-10-08 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -35,9 +35,25 @@ dependencies:
|
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id001
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
|
-
name:
|
38
|
+
name: activesupport
|
39
39
|
prerelease: false
|
40
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 19
|
46
|
+
segments:
|
47
|
+
- 3
|
48
|
+
- 0
|
49
|
+
- 10
|
50
|
+
version: 3.0.10
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: chronic
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
57
|
none: false
|
42
58
|
requirements:
|
43
59
|
- - ">="
|
@@ -49,11 +65,11 @@ dependencies:
|
|
49
65
|
- 4
|
50
66
|
version: 0.6.4
|
51
67
|
type: :runtime
|
52
|
-
version_requirements: *
|
68
|
+
version_requirements: *id003
|
53
69
|
- !ruby/object:Gem::Dependency
|
54
70
|
name: json
|
55
71
|
prerelease: false
|
56
|
-
requirement: &
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
57
73
|
none: false
|
58
74
|
requirements:
|
59
75
|
- - ">="
|
@@ -65,11 +81,11 @@ dependencies:
|
|
65
81
|
- 1
|
66
82
|
version: 1.6.1
|
67
83
|
type: :runtime
|
68
|
-
version_requirements: *
|
84
|
+
version_requirements: *id004
|
69
85
|
- !ruby/object:Gem::Dependency
|
70
86
|
name: colorize
|
71
87
|
prerelease: false
|
72
|
-
requirement: &
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
73
89
|
none: false
|
74
90
|
requirements:
|
75
91
|
- - ">="
|
@@ -81,7 +97,7 @@ dependencies:
|
|
81
97
|
- 8
|
82
98
|
version: 0.5.8
|
83
99
|
type: :runtime
|
84
|
-
version_requirements: *
|
100
|
+
version_requirements: *id005
|
85
101
|
description: "A command line interface to The Grid: Social Networking, Web 0.2"
|
86
102
|
email:
|
87
103
|
- bamuller@gmail.com
|
@@ -98,7 +114,6 @@ files:
|
|
98
114
|
- Gemfile
|
99
115
|
- README.rdoc
|
100
116
|
- Rakefile
|
101
|
-
- TODO
|
102
117
|
- bin/grid
|
103
118
|
- gridcli.gemspec
|
104
119
|
- lib/gridcli.rb
|
@@ -111,13 +126,17 @@ files:
|
|
111
126
|
- lib/gridcli/commands/like.rb
|
112
127
|
- lib/gridcli/commands/list.rb
|
113
128
|
- lib/gridcli/commands/message.rb
|
129
|
+
- lib/gridcli/commands/plugin.rb
|
114
130
|
- lib/gridcli/commands/pprint.rb
|
115
131
|
- lib/gridcli/commands/profile.rb
|
116
132
|
- lib/gridcli/commands/search.rb
|
117
133
|
- lib/gridcli/commands/signup.rb
|
118
134
|
- lib/gridcli/commands/status.rb
|
135
|
+
- lib/gridcli/commands/subgrid.rb
|
119
136
|
- lib/gridcli/commands/update.rb
|
120
137
|
- lib/gridcli/config.rb
|
138
|
+
- lib/gridcli/hooks.rb
|
139
|
+
- lib/gridcli/plugins.rb
|
121
140
|
- lib/gridcli/pprinter.rb
|
122
141
|
- lib/gridcli/resources/base.rb
|
123
142
|
- lib/gridcli/resources/blockage.rb
|
@@ -125,9 +144,12 @@ files:
|
|
125
144
|
- lib/gridcli/resources/post.rb
|
126
145
|
- lib/gridcli/resources/user.rb
|
127
146
|
- lib/gridcli/runner.rb
|
147
|
+
- lib/gridcli/stats.rb
|
128
148
|
- lib/gridcli/storage/base.rb
|
129
149
|
- lib/gridcli/storage/files.rb
|
150
|
+
- lib/gridcli/subgrids.rb
|
130
151
|
- lib/gridcli/version.rb
|
152
|
+
- lib/gridcli/ymlhash.rb
|
131
153
|
has_rdoc: true
|
132
154
|
homepage: http://gridcli.com
|
133
155
|
licenses: []
|
data/TODO
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
grid list friends --of-friends
|
2
|
-
|
3
|
-
pretty print for profiles
|
4
|
-
|
5
|
-
ascii profiles
|
6
|
-
|
7
|
-
circles (or grids?) - with lists stored locally. Format:
|
8
|
-
|
9
|
-
play: [ sally, mary, suzie ]
|
10
|
-
work: [ bob, john ]
|
11
|
-
everyone: [ @work, @play ]
|
12
|
-
|
13
|
-
or something like that..
|