lazybird 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +110 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +339 -0
- data/README.md +74 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/lazybird +7 -0
- data/bin/setup +6 -0
- data/lazybird.gemspec +30 -0
- data/lib/config/tasks.yml +6 -0
- data/lib/lazybird.rb +5 -0
- data/lib/lazybird/cli/command_line.rb +64 -0
- data/lib/lazybird/cli/commands.rb +88 -0
- data/lib/lazybird/config.rb +37 -0
- data/lib/lazybird/db.rb +84 -0
- data/lib/lazybird/lazybird_facade.rb +86 -0
- data/lib/lazybird/tasks/quote.rb +40 -0
- data/lib/lazybird/tasks/retweet_random_task.rb +9 -0
- data/lib/lazybird/tasks/storm_quote_task.rb +12 -0
- data/lib/lazybird/tasks/task.rb +20 -0
- data/lib/lazybird/tasks/task_scheduler.rb +38 -0
- data/lib/lazybird/twitter_client.rb +48 -0
- data/lib/lazybird/utils.rb +17 -0
- data/lib/lazybird/version.rb +7 -0
- metadata +183 -0
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Lazybird (Beta)
|
2
|
+
|
3
|
+
[![Gem Version](https://img.shields.io/badge/lazybird-v0.1.0beta-orange.svg)][gem]
|
4
|
+
|
5
|
+
[gem]: https://rubygems.org/gems/lazybird
|
6
|
+
|
7
|
+
Twitter for busy people.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Register at https://apps.twitter.com/app/new
|
12
|
+
|
13
|
+
Example:
|
14
|
+
|
15
|
+
![](http://i.imgsafe.org/fbf19e8.png)
|
16
|
+
|
17
|
+
Then click on keys and access tokens and generate an access token. You will need this for the setup.
|
18
|
+
|
19
|
+
|
20
|
+
Install lazybird running:
|
21
|
+
|
22
|
+
$ gem install lazybird
|
23
|
+
|
24
|
+
## Setup
|
25
|
+
|
26
|
+
Once lazybird is installed you can run it with:
|
27
|
+
|
28
|
+
`lazybird`
|
29
|
+
|
30
|
+
or
|
31
|
+
|
32
|
+
`bundle exec lazybird`
|
33
|
+
|
34
|
+
The CLI should appear:
|
35
|
+
|
36
|
+
![](http://i.imgsafe.org/bdeff99.png)
|
37
|
+
|
38
|
+
|
39
|
+
Typically you want to setup the database first running `setup`
|
40
|
+
|
41
|
+
And run config to enter your twitter settings: `config consumer_key consumer_secret access_token access_token_secret`
|
42
|
+
|
43
|
+
## Usage
|
44
|
+
|
45
|
+
Run it with `lazybird` - you would need to keep the app running as long as you want to tweet automatically.
|
46
|
+
|
47
|
+
Lazybird contains (at the moment) only two tasks that run at a certain configured time:
|
48
|
+
|
49
|
+
|
50
|
+
_retweet_random_: Retweets a random tweet (latest) from a random friend
|
51
|
+
|
52
|
+
_tweet_storm_: Tweets a random quote from the Storm API http://quotes.stormconsultancy.co.uk
|
53
|
+
|
54
|
+
|
55
|
+
Add them both to your list of tasks (this will store them in an internal DB to resume later)
|
56
|
+
|
57
|
+
`add retweet_random`
|
58
|
+
|
59
|
+
`add tweet_storm`
|
60
|
+
|
61
|
+
Then you want to either randomly tweet something now with `run now` or schedule it to tweet every N minutes/hours/day:s `run 2h` or `run 30m` for example.
|
62
|
+
|
63
|
+
You will need to keep the command line open and you should see an update everytime something random gets tweeted.
|
64
|
+
|
65
|
+
Lazybird stores a DB/config file at ~/.twitter.db - make sure it's safe.
|
66
|
+
|
67
|
+
|
68
|
+
## Contributing
|
69
|
+
|
70
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/bluegod/lazybird.
|
71
|
+
|
72
|
+
## License
|
73
|
+
|
74
|
+
GPL v2
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "lazybird"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/lazybird
ADDED
data/bin/setup
ADDED
data/lazybird.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'lazybird/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'lazybird'
|
8
|
+
spec.version = Lazybird::VERSION
|
9
|
+
spec.authors = ['James Lopez']
|
10
|
+
spec.email = ['james@jameslopez.es']
|
11
|
+
spec.license = 'GPL-2.0'
|
12
|
+
|
13
|
+
spec.summary = %q{Twitter for lazy people. Automatically tweets/retweets random stuff. }
|
14
|
+
spec.description = %q{Provides a command line interface to interact with twitter and automatically tweets/retweets some predefined (or API based tweets) at a specified frequency. }
|
15
|
+
spec.homepage = "https://github.com/bluegod/lazybird"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "bin"
|
19
|
+
spec.executables = ['lazybird']
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.3"
|
25
|
+
spec.add_dependency 'twitter', '~> 5.15'
|
26
|
+
spec.add_dependency 'rufus-scheduler', '~> 3.1'
|
27
|
+
spec.add_dependency 'amalgalite', '~> 1.4'
|
28
|
+
spec.add_dependency 'sequel', '~> 4.27'
|
29
|
+
spec.add_dependency 'colorize', '~> 0.7'
|
30
|
+
end
|
data/lib/lazybird.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
require 'lazybird/version'
|
3
|
+
require 'lazybird/lazybird_facade'
|
4
|
+
require 'lazybird/cli/commands'
|
5
|
+
require 'rbconfig'
|
6
|
+
|
7
|
+
module Lazybird
|
8
|
+
module Cli
|
9
|
+
class CommandLine
|
10
|
+
include Lazybird::Cli::Commands
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@facade = Lazybird::LazybirdFacade.new
|
14
|
+
intro.display
|
15
|
+
setup_check
|
16
|
+
run_main_loop
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def setup_check
|
22
|
+
if Lazybird::Config.db_file_exists?
|
23
|
+
@facade.load_default_tasks
|
24
|
+
else
|
25
|
+
puts 'Type: '.bold + "setup \u{23ce}".red.bold + " as this is the first time running the app.\n".bold
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def run_main_loop
|
30
|
+
loop do
|
31
|
+
display_prompt
|
32
|
+
command, *params = gets.chomp.split /\s/
|
33
|
+
process_command(command, params) if command
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def newline
|
38
|
+
puts
|
39
|
+
end
|
40
|
+
|
41
|
+
def process_command(command, params)
|
42
|
+
command.downcase!
|
43
|
+
if respond_to?(command)
|
44
|
+
send(command, params)
|
45
|
+
else
|
46
|
+
puts 'Invalid command'.light_red
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def display_prompt
|
51
|
+
prompt.yellow.display
|
52
|
+
end
|
53
|
+
|
54
|
+
def prompt
|
55
|
+
@_prompt ||=
|
56
|
+
begin
|
57
|
+
os = RbConfig::CONFIG['host_os']
|
58
|
+
icon = os.start_with?('darwin') ? "\u{1F425}" : ')<'
|
59
|
+
"#{icon} Lazybird> "
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Lazybird
|
2
|
+
module Cli
|
3
|
+
module Commands
|
4
|
+
|
5
|
+
def config(params)
|
6
|
+
@facade.config(params)
|
7
|
+
display_done
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup(params)
|
11
|
+
@facade.init
|
12
|
+
display_done
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(params)
|
16
|
+
@facade.add_task params.first
|
17
|
+
display_done
|
18
|
+
end
|
19
|
+
|
20
|
+
def my_tasks(params)
|
21
|
+
@facade.current_tasks.join("\n").green.display
|
22
|
+
newline
|
23
|
+
end
|
24
|
+
|
25
|
+
def rem(params)
|
26
|
+
@facade.rem_task(params.first)
|
27
|
+
display_done
|
28
|
+
end
|
29
|
+
|
30
|
+
def run(params)
|
31
|
+
cursor = -> () do
|
32
|
+
display_prompt
|
33
|
+
end
|
34
|
+
@facade.run_tasks(params, &cursor)
|
35
|
+
end
|
36
|
+
|
37
|
+
def my_run(params)
|
38
|
+
@facade.run_info.green.display
|
39
|
+
newline
|
40
|
+
end
|
41
|
+
|
42
|
+
def exit(params)
|
43
|
+
Kernel.exit(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
def intro
|
47
|
+
"Lazybird v#{Lazybird.version}\n".light_yellow +
|
48
|
+
"by James Lopez <http://jameslopez.net> <https://github.com/bluegod/lazybird>\n".blue +
|
49
|
+
'Type: ' + "help \u{23ce}".bold + " for a list of commands.\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
def help(params)
|
53
|
+
begin
|
54
|
+
"List of available commands: \n".yellow +
|
55
|
+
"config ".bold + "consumer_key consumer_secret access_token access_token_secret".green + " \u{23ce} \n".white +
|
56
|
+
"Configures twitter account (Should be the first step!)\n" +
|
57
|
+
"tasks \u{23ce} \n".bold +
|
58
|
+
"Displays a list of available tasks \n" +
|
59
|
+
"my_tasks".bold + " \u{23ce} \n" +
|
60
|
+
"Displays a list of your selected tasks \n" +
|
61
|
+
"add ".bold + "task".green + " \u{23ce} \n".white +
|
62
|
+
"Adds a task to be randomly tweeted\n" +
|
63
|
+
"rem ".bold + "task".green + " \u{23ce} \n".white +
|
64
|
+
"Removes a task from your list\n" +
|
65
|
+
"run ".bold + "time".green + " \u{23ce} \n".white +
|
66
|
+
"Sets how frequent we tweet (Ex: run 3h or run 1d or run 30m)\n" +
|
67
|
+
"my_run ".bold + " \u{23ce} \n" +
|
68
|
+
"Displays the current frequency of tweets \n" +
|
69
|
+
"setup \u{23ce} \n".bold +
|
70
|
+
"setups the app for the first time \n" +
|
71
|
+
"exit \u{23ce} \n".bold +
|
72
|
+
"Exits the app \n"
|
73
|
+
end.display
|
74
|
+
end
|
75
|
+
|
76
|
+
def tasks(params)
|
77
|
+
@facade.tasks.each do |k, v|
|
78
|
+
puts "#{k}:".bold + " #{v['desc']}".green
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def display_done
|
83
|
+
'done!'.green.display
|
84
|
+
newline
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'twitter'
|
2
|
+
require 'yaml'
|
3
|
+
require 'lazybird/db'
|
4
|
+
|
5
|
+
module Lazybird
|
6
|
+
module Config
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def client
|
10
|
+
@_client ||= Twitter::REST::Client.new do |config|
|
11
|
+
config.consumer_key = db_config[:consumer_key]
|
12
|
+
config.consumer_secret = db_config[:consumer_secret]
|
13
|
+
config.access_token = db_config[:access_token]
|
14
|
+
config.access_token_secret = db_config[:access_token_secret]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def tasks
|
19
|
+
@_tasks ||= YAML::load_file('./lib/config/tasks.yml')
|
20
|
+
end
|
21
|
+
|
22
|
+
def db_file
|
23
|
+
"#{Dir.home}/.twitter.db"
|
24
|
+
end
|
25
|
+
|
26
|
+
def db_file_exists?
|
27
|
+
File.file? db_file
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def db_config
|
33
|
+
#TODO: nice to have - this should go to the DB if a new config is saved.
|
34
|
+
@_config ||= Lazybird::Db.config
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/lazybird/db.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
require 'lazybird/tasks/task'
|
3
|
+
require 'lazybird/utils'
|
4
|
+
require 'lazybird/config'
|
5
|
+
module Lazybird
|
6
|
+
module Db
|
7
|
+
extend self
|
8
|
+
|
9
|
+
#TODO: refactor this. This is a quick & dirty way to create the DB
|
10
|
+
def self.init
|
11
|
+
db.transaction do
|
12
|
+
db.create_table :config do
|
13
|
+
primary_key :id
|
14
|
+
String :name, :unique => true, :null => false
|
15
|
+
String :consumer_key, :null => false
|
16
|
+
String :consumer_secret, :null => false
|
17
|
+
String :access_token, :null => false
|
18
|
+
String :access_token_secret, :null => false
|
19
|
+
end
|
20
|
+
|
21
|
+
db.create_table :tweets do
|
22
|
+
primary_key :id
|
23
|
+
String :text, :unique => true, :null => false
|
24
|
+
DateTime :created_at
|
25
|
+
end
|
26
|
+
|
27
|
+
db.create_table :tasks do
|
28
|
+
primary_key :id
|
29
|
+
String :command, :unique => true, :null => false
|
30
|
+
String :options
|
31
|
+
DateTime :created_at
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def save_tweet!(text:)
|
37
|
+
db[:tweets].insert(text: text, created_at: DateTime.now)
|
38
|
+
end
|
39
|
+
|
40
|
+
# TODO: Ideally we should have different configs, perhaps per twitter user
|
41
|
+
# for now, let's just delete every time we save a new one.
|
42
|
+
def save_config!(config)
|
43
|
+
db[:config].delete
|
44
|
+
db[:config].insert(config.merge(name: 'default'))
|
45
|
+
end
|
46
|
+
|
47
|
+
def config
|
48
|
+
db[:config].first
|
49
|
+
end
|
50
|
+
|
51
|
+
def save_task!(task)
|
52
|
+
task_hash = {command: task.command,
|
53
|
+
created_at: DateTime.now}
|
54
|
+
task_hash.merge!(options: task.opts) if !task.opts.empty?
|
55
|
+
db[:tasks].insert(Lazybird::Utils::Hash.compact(task_hash))
|
56
|
+
end
|
57
|
+
|
58
|
+
def rem_task!(task_command)
|
59
|
+
db[:tasks].where('command = ?', task_command).delete
|
60
|
+
end
|
61
|
+
|
62
|
+
def list_tasks
|
63
|
+
db[:tasks].select(:command)
|
64
|
+
end
|
65
|
+
|
66
|
+
def tasks
|
67
|
+
db[:tasks].all.map do |task|
|
68
|
+
found = Lazybird::Utils::Hash.find_by_key(Lazybird::Config.tasks, task[:command])
|
69
|
+
unless found.empty?
|
70
|
+
task_found(task[:command], found).new(command: task[:command],
|
71
|
+
options: found[:options])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def task_found(task_name, found)
|
77
|
+
Object.const_get(found[task_name]['class'])
|
78
|
+
end
|
79
|
+
|
80
|
+
def db
|
81
|
+
@_db ||= Sequel.amalgalite(Lazybird::Config.db_file)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'lazybird/config'
|
2
|
+
require 'lazybird/db'
|
3
|
+
require 'lazybird/utils'
|
4
|
+
require 'lazybird/tasks/storm_quote_task'
|
5
|
+
require 'lazybird/tasks/retweet_random_task'
|
6
|
+
require 'lazybird/tasks/task_scheduler'
|
7
|
+
|
8
|
+
module Lazybird
|
9
|
+
#TODO: split this file
|
10
|
+
class LazybirdFacade
|
11
|
+
|
12
|
+
attr_reader :tasks
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@current_tasks = Set.new
|
16
|
+
@tasks = Lazybird::Config.tasks
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_task(task_name)
|
20
|
+
# TODO refactor this method
|
21
|
+
found = Lazybird::Utils::Hash.find_by_key(@tasks, task_name)
|
22
|
+
if found
|
23
|
+
task = Object.const_get(found[task_name]['class']).new(command: task_name)
|
24
|
+
begin
|
25
|
+
Lazybird::Db.save_task!(task)
|
26
|
+
rescue Sequel::UniqueConstraintViolation
|
27
|
+
puts 'Task added already'.light_red
|
28
|
+
end
|
29
|
+
@current_tasks << task
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def rem_task(task_name)
|
34
|
+
Lazybird::Db.rem_task!(task_name)
|
35
|
+
@current_tasks.delete_if { |t| t.command == task_name }
|
36
|
+
end
|
37
|
+
|
38
|
+
def current_tasks
|
39
|
+
@current_tasks.map { |t| t.command }
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_default_tasks
|
43
|
+
@current_tasks.merge(Lazybird::Db.tasks)
|
44
|
+
end
|
45
|
+
|
46
|
+
def init
|
47
|
+
Lazybird::Db.init
|
48
|
+
end
|
49
|
+
|
50
|
+
def config(params)
|
51
|
+
config = Lazybird::Utils::Hash.array_to_hash([:consumer_key,
|
52
|
+
:consumer_secret,
|
53
|
+
:access_token,
|
54
|
+
:access_token_secret], params)
|
55
|
+
Lazybird::Db.save_config! config
|
56
|
+
end
|
57
|
+
|
58
|
+
def run_tasks(params, &block)
|
59
|
+
if params.first == 'now'
|
60
|
+
run_random_task
|
61
|
+
else
|
62
|
+
Lazybird::Tasks::TaskScheduler.schedule(frequency: params.first) do
|
63
|
+
run_random_task(&block)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def run_info
|
69
|
+
Lazybird::Tasks::TaskScheduler.job_info
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def run_random_task(&block)
|
75
|
+
puts 'Twitting something random...'.yellow
|
76
|
+
text = @current_tasks.to_a.sample.run
|
77
|
+
if text.nil?
|
78
|
+
puts "Sorry! We couldn't tweet :(".light_red
|
79
|
+
else
|
80
|
+
puts "<<#{text.magenta}>>"
|
81
|
+
end
|
82
|
+
yield if block
|
83
|
+
text
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|