lazybird 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "lazybird"
5
+ require "lazybird/cli/command_line"
6
+
7
+ Lazybird::Cli::CommandLine.new
data/bin/setup ADDED
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
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
@@ -0,0 +1,6 @@
1
+ retweet_random:
2
+ desc: 'Retweets a random tweet (latest) from a random friend'
3
+ class: Lazybird::Tasks::RetweetRandomTask
4
+ tweet_storm:
5
+ desc: 'Tweets a random quote from the Storm API http://quotes.stormconsultancy.co.uk'
6
+ class: Lazybird::Tasks::StormQuoteTask
data/lib/lazybird.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'lazybird/version'
2
+ require 'lazybird/config'
3
+ module Lazybird
4
+
5
+ end
@@ -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
@@ -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