shiki 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|