twittbot 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 09e59460e2557a87718a9bad72b57d1b42c2a4c3
4
- data.tar.gz: 179a82d6023f5b2900d54841538e1aeb1b673564
3
+ metadata.gz: c1ccc06698d66c5f816c4021a4f629b2bb7a388f
4
+ data.tar.gz: 809da09ae7ae3724f1c14080eef51dcdefe33c3c
5
5
  SHA512:
6
- metadata.gz: ed8bedb456e2ff5d26857f0758797e20f9ece05bca381e8125381807c0b91168fb20b90263cd162cb2cb6ce0560169c234743d0e07ff38e846df1bf0aa64dc84
7
- data.tar.gz: fe77b02ea6703e0b22e8cf8004e10a05a6cae7381fca8120b29a95392cca7934ae4603ea8ab0a23e37a61162534c7da05e957d0345f307b301fb3527a134ebb7
6
+ metadata.gz: 23668bb8a4caeb9d7bae00775498ff5fe4dc3a17893b5190a105683af2931cf624d36a2e6d2c989a7a51fe071e42f673ee1dbbaa76d8a843832bf3f0f75a6775
7
+ data.tar.gz: 8a9aef2318375d165b3af9eeeebfc219664998df13e4581fb3fdf24f836dc472cd8b4b275eb38932138bbb003e6cd2cfebd1973e02d1b757575d42e68ff4d1d5
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Twittbot
1
+ # Twittbot [![Gem Version](https://badge.fury.io/rb/twittbot.svg)](http://badge.fury.io/rb/twittbot) [![Inline docs](http://inch-ci.org/github/nilsding/twittbot.svg?branch=master)](http://inch-ci.org/github/nilsding/twittbot)
2
2
 
3
3
  Twittbot is the next generation of my old Twitter bot, `twittbot-nd`.
4
4
 
@@ -19,6 +19,10 @@ Authorize with Twitter:
19
19
 
20
20
  $ twittbot auth
21
21
 
22
+ Add yourself as a botadmin:
23
+
24
+ $ twittbot add-admin nilsding
25
+
22
26
  Add a template, such as for a simple reply bot:
23
27
 
24
28
  $ twittbot generate random-reply
data/lib/twittbot/bot.rb CHANGED
@@ -18,12 +18,21 @@ module Twittbot
18
18
  }
19
19
 
20
20
  $bot = {
21
+ botparts: [],
21
22
  callbacks: {},
22
- config: YAML.load_file(File.expand_path("./#{Twittbot::CONFIG_FILE_NAME}", @options[:current_dir])),
23
+ commands: {},
24
+ config: Twittbot::DEFAULT_BOT_CONFIG.merge(
25
+ YAML.load_file(File.expand_path("./#{Twittbot::CONFIG_FILE_NAME}", @options[:current_dir]))
26
+ ),
23
27
  periodic: []
24
28
  }.merge!(options)
25
29
 
26
30
  load_bot_code
31
+
32
+ at_exit do
33
+ save_config
34
+ $bot[:botparts].each { |b| b.save_config }
35
+ end
27
36
  end
28
37
 
29
38
  # Authenticates an account with Twitter.
@@ -54,26 +63,12 @@ module Twittbot
54
63
  # get the bot's user name (screen_name) and print it to the console
55
64
  $bot[:config][:screen_name] = get_screen_name access_token
56
65
  puts "Hello, #{$bot[:config][:screen_name]}!"
57
-
58
- save_config
59
66
  end
60
67
 
61
68
  # Starts the bot.
62
69
  def start
63
70
  check_config
64
- $bot[:client] ||= Twitter::REST::Client.new do |cfg|
65
- cfg.consumer_key = $bot[:config][:consumer_key]
66
- cfg.consumer_secret = $bot[:config][:consumer_secret]
67
- cfg.access_token = $bot[:config][:access_token]
68
- cfg.access_token_secret = $bot[:config][:access_token_secret]
69
- end
70
-
71
- @streamer ||= Twitter::Streaming::Client.new do |cfg|
72
- cfg.consumer_key = $bot[:config][:consumer_key]
73
- cfg.consumer_secret = $bot[:config][:consumer_secret]
74
- cfg.access_token = $bot[:config][:access_token]
75
- cfg.access_token_secret = $bot[:config][:access_token_secret]
76
- end
71
+ init_clients
77
72
 
78
73
  @userstream_thread ||= Thread.new do
79
74
  puts "connected to user stream"
@@ -103,6 +98,23 @@ module Twittbot
103
98
  @periodic_thread.join
104
99
  end
105
100
 
101
+ # @param screen_name [String] the user's screen name
102
+ # @param action [Symbol] :add or :delete
103
+ def modify_admin(screen_name, action = :add)
104
+ init_clients
105
+ user = $bot[:client].user screen_name
106
+ case action
107
+ when :add
108
+ $bot[:config][:admins] << user.id unless $bot[:config][:admins].include? user.id
109
+ when :del, :delete
110
+ $bot[:config][:admins].delete user.id if $bot[:config][:admins].include? user.id
111
+ else
112
+ say "Unknown action " + action.to_s, :red
113
+ end
114
+ rescue Twitter::Error::NotFound
115
+ say "User not found.", :red
116
+ end
117
+
106
118
  # Loads the bot's actual code which is stored in the bot's +lib+
107
119
  # subdirectory.
108
120
  def load_bot_code
@@ -158,6 +170,8 @@ module Twittbot
158
170
  pp object
159
171
  do_callbacks object.name, object, opts
160
172
  end
173
+ when Twitter::DirectMessage
174
+ do_direct_message object, opts
161
175
  else
162
176
  puts "no handler for #{object.class.to_s}\n -- object data:"
163
177
  require 'pp'
@@ -184,6 +198,26 @@ module Twittbot
184
198
  end
185
199
  end
186
200
 
201
+ # Processes a direct message.
202
+ # @param dm [Twitter::DirectMessage] received direct message
203
+ def do_direct_message(dm, opts = {})
204
+ return if dm.sender.screen_name == $bot[:config][:screen_name]
205
+ return do_callbacks(:direct_message, dm, opts) unless dm.text.start_with? $bot[:config][:dm_command_prefix]
206
+ dm_text = dm.text.sub($bot[:config][:dm_command_prefix], '').strip
207
+ return if dm_text.empty?
208
+
209
+ return unless /(?<command>[A-Za-z0-9]+)(?:\s*)(?<args>.*)/m =~ dm_text
210
+ command = Regexp.last_match(:command).to_sym
211
+ args = Regexp.last_match :args
212
+
213
+ cmd = $bot[:commands][command]
214
+ return say_status :dm, "#{dm.sender.screen_name} tried to issue non-existent command :#{command}, ignoring", :cyan if cmd.nil?
215
+ return say_status :dm, "#{dm.sender.screen_name} tried to issue admin command :#{command}, ignoring", :cyan if cmd[:admin] and !dm.sender.admin?
216
+
217
+ say_status :dm, "#{dm.sender.screen_name} issued command :#{command}", :cyan
218
+ cmd[:block].call(args, dm.sender)
219
+ end
220
+
187
221
  # @return [Boolean] whether the bot is already authenticated or not.
188
222
  def already_authed?
189
223
  !($bot[:config][:access_token].empty? or $bot[:config][:access_token_secret].empty?)
@@ -191,6 +225,22 @@ module Twittbot
191
225
 
192
226
  private
193
227
 
228
+ def init_clients
229
+ $bot[:client] ||= Twitter::REST::Client.new do |cfg|
230
+ cfg.consumer_key = $bot[:config][:consumer_key]
231
+ cfg.consumer_secret = $bot[:config][:consumer_secret]
232
+ cfg.access_token = $bot[:config][:access_token]
233
+ cfg.access_token_secret = $bot[:config][:access_token_secret]
234
+ end
235
+
236
+ @streamer ||= Twitter::Streaming::Client.new do |cfg|
237
+ cfg.consumer_key = $bot[:config][:consumer_key]
238
+ cfg.consumer_secret = $bot[:config][:consumer_secret]
239
+ cfg.access_token = $bot[:config][:access_token]
240
+ cfg.access_token_secret = $bot[:config][:access_token_secret]
241
+ end
242
+ end
243
+
194
244
  def get_screen_name(access_token)
195
245
  oauth_response = access_token.get('/1.1/account/verify_credentials.json?skip_status=true')
196
246
  oauth_response.body.match(/"screen_name"\s*:\s*"(.*?)"/).captures.first
@@ -5,13 +5,14 @@ module Twittbot
5
5
  class BotPart
6
6
  # @param name [Symbol] The name of the botpart. Should be the same as the file name without the extension.
7
7
  def initialize(name, &block)
8
- botpart_config_path = File.expand_path("./etc/#{name}.yml")
9
- @config = $bot[:config].merge(if File.exist? botpart_config_path
10
- YAML.load_file botpart_config_path
8
+ @botpart_config_path = File.expand_path("./etc/#{name}.yml")
9
+ @config = $bot[:config].merge(if File.exist? @botpart_config_path
10
+ YAML.load_file @botpart_config_path
11
11
  else
12
12
  {}
13
13
  end)
14
14
  instance_eval &block
15
+ $bot[:botparts] << self
15
16
  end
16
17
 
17
18
  # Adds a new callback to +name+.
@@ -23,6 +24,7 @@ module Twittbot
23
24
  # * :retweet
24
25
  # * :favorite
25
26
  # * :friend_list
27
+ # * :direct_message (i.e. not command DMs, see {cmd} for that)
26
28
  def on(name, *args, &block)
27
29
  $bot[:callbacks][name] ||= {
28
30
  args: args,
@@ -66,5 +68,36 @@ module Twittbot
66
68
  $bot[:client]
67
69
  end
68
70
  alias bot client
71
+
72
+ # Defines a new direct message command.
73
+ # @param name [Symbol] The name of the command. Can only contain alphanumerical characters.
74
+ # The recommended maximum length is 4 characters.
75
+ # @param options [Hash] A customizable set of options.
76
+ # @option options [Boolean] :admin (true) Require admin status for this command.
77
+ def cmd(name, options = {}, &block)
78
+ raise "Command already exists: #{name}" if $bot[:commands].include? name
79
+ raise "Command name does not contain only alphanumerical characters" unless name.to_s.match /\A[A-Za-z0-9]+\z/
80
+
81
+ opts = {
82
+ admin: true
83
+ }.merge(options)
84
+
85
+ $bot[:commands][name] ||= {
86
+ admin: opts[:admin],
87
+ block: block
88
+ }
89
+ end
90
+
91
+ # Saves the botpart's configuration. This is automatically called when
92
+ # Twittbot exits.
93
+ def save_config
94
+ botpart_config = Hash[@config.to_a - $bot[:config].to_a]
95
+
96
+ unless botpart_config.empty?
97
+ File.open @botpart_config_path, 'w' do |f|
98
+ f.write botpart_config.to_yaml
99
+ end
100
+ end
101
+ end
69
102
  end
70
103
  end
data/lib/twittbot/cli.rb CHANGED
@@ -39,5 +39,19 @@ module Twittbot
39
39
  lister = Twittbot::TemplateLister.new options
40
40
  lister.list
41
41
  end
42
+
43
+ desc 'add-admin USER_NAME', 'Adds an user to the botadmin list'
44
+ def add_admin(user_name)
45
+ require 'twittbot/bot'
46
+ bot = Twittbot::Bot.new
47
+ bot.modify_admin(user_name, :add)
48
+ end
49
+
50
+ desc 'del-admin USER_NAME', 'Removes an user from the botadmin list'
51
+ def del_admin(user_name)
52
+ require 'twittbot/bot'
53
+ bot = Twittbot::Bot.new
54
+ bot.modify_admin(user_name, :delete)
55
+ end
42
56
  end
43
57
  end
@@ -1,6 +1,6 @@
1
1
  module Twittbot
2
2
  # The version of Twittbot.
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
 
5
5
  CONSUMER_KEY = 'FYRuQcDbPAXAyVjuPZMuw' # :nodoc:
6
6
  CONSUMER_SECRET = 'KiLCYTftPdxNebl5DNcj7Ey2Y8YVZu7hfqiFRYkcg' # :nodoc:
@@ -16,6 +16,8 @@ module Twittbot
16
16
  consumer_secret: Twittbot::CONSUMER_SECRET,
17
17
  access_token: '',
18
18
  access_token_secret: '',
19
- track: []
19
+ track: [],
20
+ admins: [],
21
+ dm_command_prefix: '!'
20
22
  }
21
23
  end
@@ -1,2 +1,4 @@
1
+ require 'twittbot/gem_ext/twitter/user'
1
2
  require 'twittbot/gem_ext/twitter/tweet'
3
+ require 'twittbot/gem_ext/twitter/direct_message'
2
4
  require 'twittbot/gem_ext/twitter/rest/tweets'
@@ -0,0 +1,13 @@
1
+ module Twitter
2
+ class DirectMessage
3
+ # Replies to this direct message.
4
+ # @param direct_message_text [:String] direct message text
5
+ def reply(direct_message_text)
6
+ return if $bot.nil? or $bot[:client].nil?
7
+
8
+ $bot[:client].create_direct_message self.sender.id, direct_message_text
9
+ rescue Twitter::Error => e
10
+ puts "caught Twitter error while replying via DM: #{e.message}"
11
+ end
12
+ end
13
+ end
@@ -16,7 +16,7 @@ module Twitter
16
16
 
17
17
  $bot[:client].update result, in_reply_to_status_id: self.id
18
18
  rescue Twitter::Error => e
19
- puts "caught Twitter error while retweeting: #{e.message}"
19
+ puts "caught Twitter error while replying: #{e.message}"
20
20
  end
21
21
 
22
22
  # Retweets this tweet.
@@ -0,0 +1,9 @@
1
+ module Twitter
2
+ class User
3
+ # @return [Boolean] whether the current user is a botadmin
4
+ def admin?
5
+ return false if $bot.nil? or $bot[:config].nil?
6
+ $bot[:config][:admins].include? self.id
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,51 @@
1
+ <%
2
+ # This is the config for this botpart.
3
+ # It is a hash and will be serialized to YAML and saved to 'etc/template_name.yml'.
4
+ botpart_config = {
5
+ magic_word: "Supercalifragilisticexpialidocious" # (I'll buy you a beer if you can spell this correctly while drunk)
6
+ }
7
+
8
+ # Display a message after installation template installation
9
+ post_install_message <<-MSG
10
+ In order to make some commands work, you need to be a BotAdmin. You can add
11
+ yourself to the BotAdmin list by starting
12
+
13
+ twittbot add-admin your_user_name
14
+ MSG
15
+ %>
16
+ Twittbot::BotPart.new :<%= @template_name %> do
17
+ # This command gives a BotAdmin the ability to tweet via the bot.
18
+ #
19
+ # Example usage (via direct message):
20
+ # !twet This is a tweet
21
+ cmd :twet do |args, _user|
22
+ bot.tweet args
23
+ end
24
+
25
+ # This command gives anyone who is followed by the bot the ability to echo
26
+ # back their direct message.
27
+ #
28
+ # Example usage:
29
+ # !echo Hello, world!
30
+ cmd :echo, admin: false do |args, user|
31
+ bot.dm user, args
32
+ end
33
+
34
+ ## Uncomment this if you want to remotely stop the bot.
35
+ ##
36
+ ## Example usage:
37
+ ## !stop Supercalifragilisticexpialidocious
38
+ #cmd :stop do |args, user|
39
+ # exit 0 if args.downcase == @config[:magic_word].downcase
40
+ #end
41
+
42
+ # Of course, there's a :direct_message callback too. This applies to
43
+ # everything that is not a command.
44
+ on :direct_message do |dm|
45
+ if dm.sender.admin? # You can check if an user is an admin by using the .admin? method.
46
+ dm.reply "You're an admin! You can use !twet to tweet nice things."
47
+ else
48
+ dm.reply "You're an ordinary user! Try using !echo on me."
49
+ end
50
+ end
51
+ end
@@ -17,4 +17,20 @@ Twittbot::BotPart.new :<%= @template_name %> do
17
17
  # ... tweet a random entry of the :tweets list that you configured
18
18
  bot.tweet @config[:tweets].sample
19
19
  end
20
+
21
+ ## Uncomment the next few lines if you want to add new tweets to the tweet
22
+ ## list on the fly using direct messages.
23
+ ##
24
+ ## Example usage:
25
+ ## !atwt Tweet text
26
+ #cmd :atwt do |args|
27
+ # # adds args (usually the tweet text) to the list of random tweets unless
28
+ # # args already is in the list
29
+ # @config[:tweets] << args unless @config[:tweets].include? args
30
+ #end
31
+ #
32
+ ## Auto-save! \o/
33
+ #every 1, :hour do
34
+ # save_config
35
+ #end
20
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twittbot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nilsding
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-28 00:00:00.000000000 Z
11
+ date: 2015-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -135,8 +135,11 @@ files:
135
135
  - lib/twittbot/cli.rb
136
136
  - lib/twittbot/defaults.rb
137
137
  - lib/twittbot/gem_ext/twitter.rb
138
+ - lib/twittbot/gem_ext/twitter/direct_message.rb
138
139
  - lib/twittbot/gem_ext/twitter/rest/tweets.rb
139
140
  - lib/twittbot/gem_ext/twitter/tweet.rb
141
+ - lib/twittbot/gem_ext/twitter/user.rb
142
+ - lib/twittbot/generators/templates/basic_dm/basic_dm.rb
140
143
  - lib/twittbot/generators/templates/followback/followback.rb
141
144
  - lib/twittbot/generators/templates/random_reply/random_reply.rb
142
145
  - lib/twittbot/generators/templates/random_tweet/random_tweet.rb