shiki 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +52 -0
- data/Rakefile +12 -0
- data/lib/shiki.rb +5 -0
- data/lib/shiki/base.rb +223 -0
- data/lib/shiki/fuda.rb +17 -0
- data/lib/shiki/personality.rb +24 -0
- data/lib/shiki/version.rb +3 -0
- data/shiki.gemspec +21 -0
- data/spec/valid_test_spec.rb +30 -0
- metadata +104 -0
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Oame
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
式(Shiki) beta
|
2
|
+
=============
|
3
|
+
|
4
|
+
Shiki is The "Unidentified" Bot Framework for Twitter. written in Ruby.
|
5
|
+
|
6
|
+
Features / Problems
|
7
|
+
-------------
|
8
|
+
|
9
|
+
* Easy to write.
|
10
|
+
|
11
|
+
Requirement
|
12
|
+
-------------
|
13
|
+
|
14
|
+
* pupil, json and oauth gem
|
15
|
+
* Ruby 1.9.x
|
16
|
+
|
17
|
+
Installation
|
18
|
+
-------------
|
19
|
+
|
20
|
+
gem install shiki
|
21
|
+
|
22
|
+
Examples
|
23
|
+
-------------
|
24
|
+
require "shiki"
|
25
|
+
|
26
|
+
OAUTH_KEY = {
|
27
|
+
:consumer_key => "something", # Required
|
28
|
+
:consumer_secret => "something" # Required
|
29
|
+
:access_token => "something", # Required
|
30
|
+
:access_token_secret => "something" # Required
|
31
|
+
}
|
32
|
+
|
33
|
+
class UsefullBot < Shiki::Base
|
34
|
+
set :oauth_key, OAUTH_KEY
|
35
|
+
use :memory, :database => "databases/memory.db"
|
36
|
+
|
37
|
+
event :mention do |status|
|
38
|
+
status.user.reply "Guten morgen!"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Credits
|
43
|
+
-------------
|
44
|
+
|
45
|
+
Developer: [Oame](http://twitter.com/o_ame)
|
46
|
+
|
47
|
+
License
|
48
|
+
-------------
|
49
|
+
|
50
|
+
Copyright (c) 2011 Oame. See LICENSE.txt for
|
51
|
+
further details.
|
52
|
+
|
data/Rakefile
ADDED
data/lib/shiki.rb
ADDED
data/lib/shiki/base.rb
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require "net/https"
|
4
|
+
require "time"
|
5
|
+
require "json"
|
6
|
+
require "oauth"
|
7
|
+
require "pupil"
|
8
|
+
require "pupil/stream"
|
9
|
+
require "shiki/fuda"
|
10
|
+
#require "shiki/personality"
|
11
|
+
|
12
|
+
module Shiki
|
13
|
+
class Base
|
14
|
+
attr_accessor :memory
|
15
|
+
|
16
|
+
TWITTER_URL = "http://twitter.com"
|
17
|
+
TWITTER_USERSTREAM_API = "https://userstream.twitter.com/2/user.json"
|
18
|
+
|
19
|
+
SCHEMES = [
|
20
|
+
[:status, :mention, :follow, :favorite, :retweet],
|
21
|
+
[:search]
|
22
|
+
]
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
super()
|
26
|
+
@key = self.oauth_key
|
27
|
+
@consumer = OAuth::Consumer.new(@key[:consumer_key], @key[:consumer_secret], :site => TWITTER_URL)
|
28
|
+
@access_token = OAuth::AccessToken.new(@consumer, @key[:access_token], @key[:access_token_secret])
|
29
|
+
register(:twitter => Pupil.new(@key))
|
30
|
+
|
31
|
+
#register(:memory => Shiki::Memory.new(self.memory_database))
|
32
|
+
end
|
33
|
+
|
34
|
+
def register(option)
|
35
|
+
self.class.register(option)
|
36
|
+
end
|
37
|
+
|
38
|
+
def call(action, num, option=nil)
|
39
|
+
self.class.call(action, num, option)
|
40
|
+
end
|
41
|
+
|
42
|
+
def disharmony?(keys)
|
43
|
+
i1 = keys.map{|k| SCHEMES[0].include?(k)}
|
44
|
+
i2 = keys.map{|k| SCHEMES[1].include?(k)}
|
45
|
+
return ((i1&i2).size > 0)? true : false
|
46
|
+
end
|
47
|
+
|
48
|
+
def guess_scheme(keys)
|
49
|
+
if keys.map{|k| SCHEMES[0].index(k)}
|
50
|
+
return :userstream
|
51
|
+
else
|
52
|
+
return :search
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def run
|
57
|
+
keys = self.class.blocks.keys
|
58
|
+
raise ArgumentError, "Disharnomy event blocks are detected." if disharmony?(keys)
|
59
|
+
raise NoMethodError, "self.oauth_key not defined" unless self.respond_to? :oauth_key
|
60
|
+
|
61
|
+
scheme = guess_scheme(keys)
|
62
|
+
ps = Pupil::Stream.new self.oauth_key
|
63
|
+
begin
|
64
|
+
ps.start scheme do |status|
|
65
|
+
#puts "Event: #{status.event}"
|
66
|
+
case status.event
|
67
|
+
when :status
|
68
|
+
if status.text.match /^@/
|
69
|
+
# Mention event
|
70
|
+
next unless self.class.blocks[:mention]
|
71
|
+
proc_status_event(:mention, status)
|
72
|
+
else
|
73
|
+
# Status event
|
74
|
+
next unless self.class.blocks[:status]
|
75
|
+
proc_status_event(:status, status)
|
76
|
+
end
|
77
|
+
when :retweet
|
78
|
+
# Retweeted event
|
79
|
+
next unless self.class.blocks[:retweet]
|
80
|
+
proc_status_event(:retweet, status)
|
81
|
+
when :follow
|
82
|
+
# Foolow event
|
83
|
+
next unless self.class.blocks[:follow]
|
84
|
+
proc_follow(status)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
rescue Interrupt
|
88
|
+
puts "> Stopping ..."
|
89
|
+
exit()
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def proc_follow(status)
|
94
|
+
blocks = self.class.blocks[:follow]
|
95
|
+
num = 0
|
96
|
+
blocks.each do |block|
|
97
|
+
option = block[:option]
|
98
|
+
call(:follow, num, status)
|
99
|
+
num += 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def proc_status_event(event, status)
|
104
|
+
blocks = self.class.blocks[event]
|
105
|
+
num = 0
|
106
|
+
blocks.each do |block|
|
107
|
+
option = block[:option]
|
108
|
+
if option
|
109
|
+
response = []
|
110
|
+
|
111
|
+
if option[:include]
|
112
|
+
if Regexp.new(option[:include]) =~ status.text
|
113
|
+
response << true
|
114
|
+
else
|
115
|
+
response << false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
if option[:from]
|
120
|
+
if option[:from].to_s == status.user.screen_name
|
121
|
+
response << true
|
122
|
+
else
|
123
|
+
response << false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
if response.index(false) == nil
|
128
|
+
call(event, num, status)
|
129
|
+
next
|
130
|
+
else
|
131
|
+
next
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
call(event, num, status)
|
136
|
+
num += 1
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class << self
|
141
|
+
@@blocks = {}
|
142
|
+
@@conditions = {}
|
143
|
+
@@env = {}
|
144
|
+
|
145
|
+
# Accessor methods
|
146
|
+
|
147
|
+
def blocks; @@blocks; end
|
148
|
+
def env(param); @@env[param]; end
|
149
|
+
|
150
|
+
def register(opt)
|
151
|
+
option = [*opt][0]
|
152
|
+
@@conditions[option[0]] = option[1]
|
153
|
+
end
|
154
|
+
|
155
|
+
def call(action, num, option)
|
156
|
+
@@blocks[action][num][:block].call option
|
157
|
+
end
|
158
|
+
|
159
|
+
def set(option, value=nil)
|
160
|
+
#class_eval "def self.#{option}() #{value.inspect} ; end"
|
161
|
+
define_method option, proc{ value }
|
162
|
+
end
|
163
|
+
|
164
|
+
def use(name, option=nil)
|
165
|
+
require(File.join(File.dirname(File.expand_path($0)), "fuda/#{name}"))
|
166
|
+
fuda = eval("#{name.capitalize}")
|
167
|
+
@@env[:fuda] ||= {}
|
168
|
+
if fuda.prepare[:make_instance]
|
169
|
+
@@env[:fuda].update(name.to_sym => {:block => fuda.new(option), :option => option, :instance => true})
|
170
|
+
else
|
171
|
+
@@env[:fuda].update(name.to_sym => {:block => fuda, :option => option, :instance => false})
|
172
|
+
eval("#{name.capitalize}.new(#{option})")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def enable(fuda, option)
|
177
|
+
# Not implement
|
178
|
+
# e.g. auto_follow
|
179
|
+
end
|
180
|
+
|
181
|
+
def event(action, option=nil, &block)
|
182
|
+
@@blocks[action] ||= []
|
183
|
+
@@blocks[action] << {:block => block, :option => option}
|
184
|
+
end
|
185
|
+
|
186
|
+
def method_missing(action, *option)
|
187
|
+
@@env[:fuda].each do |name, option|
|
188
|
+
return option[:block] if action == name && option[:instance]
|
189
|
+
end
|
190
|
+
raise NoMethodError
|
191
|
+
end
|
192
|
+
|
193
|
+
# Bot methods
|
194
|
+
|
195
|
+
def say(sentence)
|
196
|
+
@@conditions[:twitter].update(sentence)
|
197
|
+
end
|
198
|
+
|
199
|
+
alias_method :tweet, :say
|
200
|
+
|
201
|
+
def reply(opts, status=nil)
|
202
|
+
puts "get reply"
|
203
|
+
raise ArgumentError, "target parameter not given" unless opts.values[0]
|
204
|
+
sentence, target = opts.to_a.first
|
205
|
+
name = nil
|
206
|
+
case target.class.to_s
|
207
|
+
when "Pupil::User"
|
208
|
+
name = target.screen_name
|
209
|
+
when "String"
|
210
|
+
name = target
|
211
|
+
when "Symbol"
|
212
|
+
name = target.to_s
|
213
|
+
end
|
214
|
+
if status
|
215
|
+
@@conditions[:twitter].update("@#{name} #{sentence}", status)
|
216
|
+
else
|
217
|
+
@@conditions[:twitter].update("@#{name} #{sentence}")
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
data/lib/shiki/fuda.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "sequel"
|
2
|
+
|
3
|
+
module Shiki
|
4
|
+
class Personality
|
5
|
+
def initialize pattern_db
|
6
|
+
@db = Sequel.sqlite pattern_db
|
7
|
+
@tweets = @db[:tweets]
|
8
|
+
@replies = @db[:replies]
|
9
|
+
@locations = @db[:locations]
|
10
|
+
end
|
11
|
+
|
12
|
+
def tweets time_zone, week
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def replies fear, interest
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def random_location
|
21
|
+
return @locations.to_a
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/shiki.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/shiki/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Oame"]
|
6
|
+
gem.email = ["oame@oameya.com"]
|
7
|
+
gem.description = %q{The "Unidentified" Bot Framework}
|
8
|
+
gem.summary = %q{The "Unidentified" Bot Framework for Twitter.}
|
9
|
+
gem.homepage = "https://github.com/oame/shiki"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "shiki"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Shiki::VERSION
|
17
|
+
gem.add_dependency "json"
|
18
|
+
gem.add_dependency "oauth"
|
19
|
+
gem.add_dependency "pupil"
|
20
|
+
gem.add_development_dependency "rspec"
|
21
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#! -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "rspec"
|
6
|
+
require "yaml"
|
7
|
+
|
8
|
+
TWEETS_FILE = "tweets.yml"
|
9
|
+
REPLY_PATTERNS_FILE = "reply_patterns.yml"
|
10
|
+
LOCATIONS_FILE = "locations.yml"
|
11
|
+
|
12
|
+
describe "YAML Configurations" do
|
13
|
+
before do
|
14
|
+
@tweets = YAML.load_file TWEETS_FILE
|
15
|
+
@replies = YAML.load_file REPLY_PATTERNS_FILE
|
16
|
+
@locations = YAML.load_file LOCATIONS_FILE
|
17
|
+
end
|
18
|
+
|
19
|
+
it "TweetsはHash型であること" do
|
20
|
+
@tweets.class.should == Hash
|
21
|
+
end
|
22
|
+
|
23
|
+
it "RepliesはHash型であること" do
|
24
|
+
@replies.class.should == Hash
|
25
|
+
end
|
26
|
+
|
27
|
+
it "LocationsはArray型であること" do
|
28
|
+
@locations.class.should == Array
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shiki
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Oame
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json
|
16
|
+
requirement: &70329096636120 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70329096636120
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: oauth
|
27
|
+
requirement: &70329096635340 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70329096635340
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: pupil
|
38
|
+
requirement: &70329096634160 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70329096634160
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: &70329096633540 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70329096633540
|
58
|
+
description: The "Unidentified" Bot Framework
|
59
|
+
email:
|
60
|
+
- oame@oameya.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- .gitignore
|
66
|
+
- CHANGELOG.md
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- lib/shiki.rb
|
72
|
+
- lib/shiki/base.rb
|
73
|
+
- lib/shiki/fuda.rb
|
74
|
+
- lib/shiki/personality.rb
|
75
|
+
- lib/shiki/version.rb
|
76
|
+
- shiki.gemspec
|
77
|
+
- spec/valid_test_spec.rb
|
78
|
+
homepage: https://github.com/oame/shiki
|
79
|
+
licenses: []
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.8.15
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: The "Unidentified" Bot Framework for Twitter.
|
102
|
+
test_files:
|
103
|
+
- spec/valid_test_spec.rb
|
104
|
+
has_rdoc:
|