gridcli 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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 always in offline mode.
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
- puts post
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
- puts f
20
+ pprint f.user.to_json
21
21
  }
22
22
  puts "You have no friends :(" if friends.length == 0
23
23
  rescue ActiveResource::ForbiddenAccess
@@ -11,7 +11,7 @@ module GridCLI
11
11
  end
12
12
 
13
13
  puts "Usage: grid <cmd>\n\nAvailable commands:\n\n"
14
- Runner.commands.each { |klass|
14
+ Runner.commands.sort { |a,b| a.to_s <=> b.to_s }.each { |klass|
15
15
  inst = klass.new
16
16
  puts "\t#{inst.cmd.ljust(25) + inst.desc}"
17
17
  }
@@ -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
- puts post
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>,...] [<subject>] <body>"
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
- puts post
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
- usage if args.length != 0
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
- puts user
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
 
@@ -14,6 +14,8 @@ module GridCLI
14
14
  username = args.shift
15
15
  parse_opts args
16
16
 
17
+ username = GridCLI.hooker.invoke :before_signup, username
18
+
17
19
  @config["username"] = username
18
20
  @config.save
19
21
 
@@ -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
- puts post
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 = @config['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
- puts PrettyPrinter.new(json)
36
- puts
38
+ pprint json
37
39
  }
38
- @config['last_sha'] = GridCLI.storage.append(posts)
39
- @config.save
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
@@ -1,19 +1,7 @@
1
- require 'yaml'
2
-
3
1
  module GridCLI
4
- class Config < Hash
2
+ class Config < YMLHash
5
3
  def initialize
6
- # Initialize the grid config / message 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/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
@@ -2,47 +2,134 @@ require 'json'
2
2
  require 'colorize'
3
3
 
4
4
  module GridCLI
5
- class PrettyPrinter
6
- def initialize(string)
7
- begin
8
- j = JSON.parse(string)
9
- type = j.keys.first
10
- @contents = j[type]
11
- @created_at = Time.parse(@contents['created_at']).localtime.to_s
12
- @pretty = case type
13
- when "message" then pprint_message
14
- when "like" then pprint_like
15
- when "dislike" then pprint_dislike
16
- when "status" then pprint_status
17
- else string
18
- end
19
- rescue JSON::ParserError
20
- @pretty = string
21
- end
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 pprint_like
25
- "on #{@created_at} #{@contents['from_username']} liked #{@contents['body']}".green
73
+ def self.status(original, parsed)
74
+ super(original, parsed).cyan
26
75
  end
27
76
 
28
- def pprint_dislike
29
- "on #{@created_at} #{@contents['from_username']} disliked #{@contents['body']}".red
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 pprint_status
33
- "on #{@created_at} #{@contents['from_username']} was #{@contents['body']}".cyan
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 pprint_message
37
- s = "Message from: ".cyan + @contents['from_username'] + "\n"
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
- @pretty
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
- class Message < BaseResource
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
- class Like < BaseResource
25
+
26
+ class Like < PostBase
7
27
  self.element_name = "post"
8
28
  end
9
- class Dislike < BaseResource
29
+
30
+ class Dislike < PostBase
10
31
  self.element_name = "post"
11
32
  end
12
- class Status < BaseResource
33
+
34
+ class Status < PostBase
13
35
  self.element_name = "post"
14
36
  end
15
37
  end
@@ -1,4 +1,8 @@
1
1
  module GridCLI
2
2
  class User < BaseResource
3
+ def to_json(args=nil)
4
+ args ||= {}
5
+ super({ :except => ['id'] }.merge(args))
6
+ end
3
7
  end
4
8
  end
@@ -0,0 +1,13 @@
1
+ module GridCLI
2
+ class Stats < YMLHash
3
+ def initialize
4
+ super "stats"
5
+ end
6
+
7
+ def default_config
8
+ {
9
+ 'last_sha' => nil
10
+ }
11
+ end
12
+ end
13
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module GridCLI
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -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/like'
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/user'
58
+ require 'gridcli/resources/blockage'
40
59
  require 'gridcli/resources/friendship'
41
60
  require 'gridcli/resources/post'
42
- require 'gridcli/resources/blockage'
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: 21
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 5
10
- version: 0.0.5
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-03 00:00:00 -04:00
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: chronic
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: *id002
68
+ version_requirements: *id003
53
69
  - !ruby/object:Gem::Dependency
54
70
  name: json
55
71
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::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: *id003
84
+ version_requirements: *id004
69
85
  - !ruby/object:Gem::Dependency
70
86
  name: colorize
71
87
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::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: *id004
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..