ebooks start command, reorganizing CLI
This commit is contained in:
parent
daeda5d7eb
commit
fa45316553
1 changed files with 158 additions and 80 deletions
238
bin/ebooks
238
bin/ebooks
|
|
@ -2,31 +2,54 @@
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
|
||||||
require 'twitter_ebooks'
|
require 'twitter_ebooks'
|
||||||
require 'csv'
|
require 'ostruct'
|
||||||
|
|
||||||
$debug = true
|
$debug = true
|
||||||
|
|
||||||
module Ebooks::CLI
|
module Ebooks::CLI
|
||||||
APP_PATH = Dir.pwd # XXX do some recursive thing instead
|
APP_PATH = Dir.pwd # XXX do some recursive thing instead
|
||||||
|
HELP = OpenStruct.new
|
||||||
|
|
||||||
def self.new(reponame)
|
HELP.default = <<STR
|
||||||
usage = <<STR
|
Usage:
|
||||||
Usage: ebooks new <reponame>
|
ebooks help <command>
|
||||||
|
|
||||||
Creates a new skeleton repository defining a template bot in
|
ebooks new <reponame>
|
||||||
the current working directory specified by <reponame>.
|
ebooks auth
|
||||||
|
ebooks consume <corpus_path> [corpus_path2] [...]
|
||||||
|
ebooks consume-all <corpus_path> [corpus_path2] [...]
|
||||||
|
ebooks gen <model_path> [input]
|
||||||
|
ebooks score <model_path> <input>
|
||||||
|
ebooks archive <username> <outpath>
|
||||||
|
ebooks tweet <model_path> <botname>
|
||||||
STR
|
STR
|
||||||
|
|
||||||
|
def self.help(command=nil)
|
||||||
|
if command.nil?
|
||||||
|
log HELP.default
|
||||||
|
else
|
||||||
|
log HELP[command].gsub(/^ {4}/, '')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
HELP.new = <<-STR
|
||||||
|
Usage: ebooks new <reponame>
|
||||||
|
|
||||||
|
Creates a new skeleton repository defining a template bot in
|
||||||
|
the current working directory specified by <reponame>.
|
||||||
|
STR
|
||||||
|
|
||||||
|
def self.new(reponame)
|
||||||
if reponame.nil?
|
if reponame.nil?
|
||||||
log usage
|
help :new
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
path = "./#{reponame}"
|
path = "./#{reponame}"
|
||||||
|
|
||||||
if File.exists?(path)
|
if File.exists?(path)
|
||||||
log "#{path} already exists. Please remove if you want to recreate."
|
log "#{path} already exists. Please remove if you want to recreate."
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
FileUtils.cp_r(SKELETON_PATH, path)
|
FileUtils.cp_r(SKELETON_PATH, path)
|
||||||
|
|
@ -39,17 +62,17 @@ STR
|
||||||
log "New twitter_ebooks app created at #{reponame}"
|
log "New twitter_ebooks app created at #{reponame}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
HELP.consume = <<-STR
|
||||||
|
Usage: ebooks consume <corpus_path> [corpus_path2] [...]
|
||||||
|
|
||||||
|
Processes some number of text files or json tweet corpuses
|
||||||
|
into usable models. These will be output at model/<name>.model
|
||||||
|
STR
|
||||||
|
|
||||||
def self.consume(pathes)
|
def self.consume(pathes)
|
||||||
usage = <<STR
|
|
||||||
Usage: ebooks consume <corpus_path> [corpus_path2] [...]
|
|
||||||
|
|
||||||
Processes some number of text files or json tweet corpuses
|
|
||||||
into usable models. These will be output at model/<name>.model
|
|
||||||
STR
|
|
||||||
|
|
||||||
if pathes.empty?
|
if pathes.empty?
|
||||||
log usage
|
help :consume
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
pathes.each do |path|
|
pathes.each do |path|
|
||||||
|
|
@ -62,17 +85,17 @@ STR
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
HELP.consume_all = <<-STR
|
||||||
|
Usage: ebooks consume-all <name> <corpus_path> [corpus_path2] [...]
|
||||||
|
|
||||||
|
Processes some number of text files or json tweet corpuses
|
||||||
|
into one usable model. It will be output at model/<name>.model
|
||||||
|
STR
|
||||||
|
|
||||||
def self.consume_all(name, paths)
|
def self.consume_all(name, paths)
|
||||||
usage = <<STR
|
|
||||||
Usage: ebooks consume-all <name> <corpus_path> [corpus_path2] [...]
|
|
||||||
|
|
||||||
Processes some number of text files or json tweet corpuses
|
|
||||||
into one usable model. It will be output at model/<name>.model
|
|
||||||
STR
|
|
||||||
|
|
||||||
if paths.empty?
|
if paths.empty?
|
||||||
log usage
|
help :consume_all
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
outpath = File.join(APP_PATH, 'model', "#{name}.model")
|
outpath = File.join(APP_PATH, 'model', "#{name}.model")
|
||||||
|
|
@ -88,16 +111,17 @@ STR
|
||||||
log "Corpuses consumed to #{outpath}"
|
log "Corpuses consumed to #{outpath}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.gen(model_path, input)
|
HELP.gen = <<-STR
|
||||||
usage = <<STR
|
Usage: ebooks gen <model_path> [input]
|
||||||
Usage: ebooks gen <model_path> [input]
|
|
||||||
|
|
||||||
Make a test tweet from the processed model at <model_path>.
|
Make a test tweet from the processed model at <model_path>.
|
||||||
Will respond to input if provided.
|
Will respond to input if provided.
|
||||||
STR
|
STR
|
||||||
|
|
||||||
|
def self.gen(model_path, input)
|
||||||
if model_path.nil?
|
if model_path.nil?
|
||||||
log usage
|
help :gen
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
model = Model.load(model_path)
|
model = Model.load(model_path)
|
||||||
|
|
@ -108,50 +132,51 @@ STR
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.score(model_path, input)
|
HELP.score = <<-STR
|
||||||
usage = <<STR
|
Usage: ebooks score <model_path> <input>
|
||||||
Usage: ebooks score <model_path> <input>
|
|
||||||
|
|
||||||
Scores "interest" in some text input according to how
|
Scores "interest" in some text input according to how
|
||||||
well unique keywords match the model.
|
well unique keywords match the model.
|
||||||
STR
|
STR
|
||||||
|
|
||||||
|
def self.score(model_path, input)
|
||||||
if model_path.nil? || input.nil?
|
if model_path.nil? || input.nil?
|
||||||
log usage
|
help :score
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
model = Model.load(model_path)
|
model = Model.load(model_path)
|
||||||
model.score_interest(input)
|
model.score_interest(input)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
HELP.archive = <<-STR
|
||||||
|
Usage: ebooks archive <username> <outpath>
|
||||||
|
|
||||||
|
Downloads a json corpus of the <username>'s tweets to <outpath>.
|
||||||
|
Due to API limitations, this can only receive up to ~3000 tweets
|
||||||
|
into the past.
|
||||||
|
STR
|
||||||
|
|
||||||
def self.archive(username, outpath)
|
def self.archive(username, outpath)
|
||||||
usage = <<STR
|
|
||||||
Usage: ebooks archive <username> <outpath>
|
|
||||||
|
|
||||||
Downloads a json corpus of the <username>'s tweets to <outpath>.
|
|
||||||
Due to API limitations, this can only receive up to ~3000 tweets
|
|
||||||
into the past.
|
|
||||||
STR
|
|
||||||
|
|
||||||
if username.nil? || outpath.nil?
|
if username.nil? || outpath.nil?
|
||||||
log usage
|
help :archive
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
Archive.new(username, outpath).sync
|
Archive.new(username, outpath).sync
|
||||||
end
|
end
|
||||||
|
|
||||||
|
HELP.tweet = <<-STR
|
||||||
|
Usage: ebooks tweet <model_path> <botname>
|
||||||
|
|
||||||
|
Sends a public tweet from the specified bot using text
|
||||||
|
from the processed model at <model_path>.
|
||||||
|
STR
|
||||||
|
|
||||||
def self.tweet(modelpath, botname)
|
def self.tweet(modelpath, botname)
|
||||||
usage = <<STR
|
|
||||||
Usage: ebooks tweet <model_path> <botname>
|
|
||||||
|
|
||||||
Sends a public tweet from the specified bot using text
|
|
||||||
from the processed model at <model_path>.
|
|
||||||
STR
|
|
||||||
|
|
||||||
if modelpath.nil? || botname.nil?
|
if modelpath.nil? || botname.nil?
|
||||||
log usage
|
help :tweet
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
load File.join(APP_PATH, 'bots.rb')
|
load File.join(APP_PATH, 'bots.rb')
|
||||||
|
|
@ -163,6 +188,15 @@ STR
|
||||||
bot.tweet(statement)
|
bot.tweet(statement)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
HELP.auth = <<-STR
|
||||||
|
Usage: ebooks auth
|
||||||
|
|
||||||
|
Authenticates your Twitter app for any account. By default, will
|
||||||
|
use the consumer key and secret from the first defined bot. You
|
||||||
|
can specify another by setting the CONSUMER_KEY and CONSUMER_SECRET
|
||||||
|
environment variables.
|
||||||
|
STR
|
||||||
|
|
||||||
def self.auth
|
def self.auth
|
||||||
consumer_key, consumer_secret = find_consumer
|
consumer_key, consumer_secret = find_consumer
|
||||||
require 'oauth'
|
require 'oauth'
|
||||||
|
|
@ -196,9 +230,59 @@ STR
|
||||||
" access token secret: #{access_token.secret}"
|
" access token secret: #{access_token.secret}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.c
|
HELP.console = <<-STR
|
||||||
|
Usage: ebooks c[onsole]
|
||||||
|
|
||||||
|
Starts an interactive ruby session with your bots loaded
|
||||||
|
and configured.
|
||||||
|
STR
|
||||||
|
|
||||||
|
def self.console
|
||||||
load_bots
|
load_bots
|
||||||
require 'pry'; pry
|
require 'pry'; Ebooks.module_exec { pry }
|
||||||
|
end
|
||||||
|
|
||||||
|
HELP.start = <<-STR
|
||||||
|
Usage: ebooks s[tart] [botname]
|
||||||
|
|
||||||
|
Starts running bots. If botname is provided, only runs that bot.
|
||||||
|
STR
|
||||||
|
|
||||||
|
def self.start(botname=nil)
|
||||||
|
load_bots
|
||||||
|
|
||||||
|
if botname.nil?
|
||||||
|
bots = Ebooks::Bot.all
|
||||||
|
else
|
||||||
|
bots = bots.select { |bot| bot.username == botname }
|
||||||
|
if bots.empty?
|
||||||
|
log "Couldn't find a defined bot for @#{botname}!"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
threads = []
|
||||||
|
bots.each do |bot|
|
||||||
|
threads << Thread.new { bot.prepare }
|
||||||
|
end
|
||||||
|
threads.each(&:join)
|
||||||
|
|
||||||
|
threads = []
|
||||||
|
bots.each do |bot|
|
||||||
|
threads << Thread.new do
|
||||||
|
loop do
|
||||||
|
begin
|
||||||
|
bot.start
|
||||||
|
rescue Exception
|
||||||
|
bot.log $!
|
||||||
|
puts $@
|
||||||
|
end
|
||||||
|
bot.log "Sleeping before reconnect"
|
||||||
|
sleep 5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
threads.each(&:join)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Non-command methods
|
# Non-command methods
|
||||||
|
|
@ -229,7 +313,7 @@ STR
|
||||||
log "Couldn't find any consumer details to auth an account with.\n" +
|
log "Couldn't find any consumer details to auth an account with.\n" +
|
||||||
"Please either configure a bot with consumer_key and consumer_secret\n" +
|
"Please either configure a bot with consumer_key and consumer_secret\n" +
|
||||||
"or provide the CONSUMER_KEY and CONSUMER_SECRET environment variables."
|
"or provide the CONSUMER_KEY and CONSUMER_SECRET environment variables."
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -242,20 +326,9 @@ STR
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.command(args)
|
def self.command(args)
|
||||||
usage = <<STR
|
|
||||||
Usage:
|
|
||||||
ebooks new <reponame>
|
|
||||||
ebooks consume <corpus_path> [corpus_path2] [...]
|
|
||||||
ebooks consume-all <corpus_path> [corpus_path2] [...]
|
|
||||||
ebooks gen <model_path> [input]
|
|
||||||
ebooks score <model_path> <input>
|
|
||||||
ebooks archive <@user> <outpath>
|
|
||||||
ebooks tweet <model_path> <botname>
|
|
||||||
STR
|
|
||||||
|
|
||||||
if args.length == 0
|
if args.length == 0
|
||||||
log usage
|
help
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
case args[0]
|
case args[0]
|
||||||
|
|
@ -268,9 +341,14 @@ STR
|
||||||
when "tweet" then tweet(args[1], args[2])
|
when "tweet" then tweet(args[1], args[2])
|
||||||
when "jsonify" then jsonify(args[1..-1])
|
when "jsonify" then jsonify(args[1..-1])
|
||||||
when "auth" then auth
|
when "auth" then auth
|
||||||
when "c" then c
|
when "console" then console
|
||||||
|
when "c" then console
|
||||||
|
when "start" then start
|
||||||
|
when "s" then start
|
||||||
|
when "help" then help(args[1])
|
||||||
else
|
else
|
||||||
log usage
|
log "No such command '#{args[0]}'"
|
||||||
|
help
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue