shiki 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .DS_Store
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/*
17
+ tmp
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ 0.0.1
2
+ ------------
3
+
4
+ First release!
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in shiki.gemspec
4
+ gemspec
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
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ desc "Run RSpec test"
5
+ task :test do
6
+ `rspec -c spec/valid_test_rspec.rb`
7
+ end
8
+
9
+ desc "Pulling repository from master"
10
+ task :update do
11
+ `git pull origin master`
12
+ end
data/lib/shiki.rb ADDED
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ $LOAD_PATH << File.dirname(File.expand_path(__FILE__))
4
+ require "shiki/version"
5
+ require "shiki/base"
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,17 @@
1
+ module Shiki
2
+ class Fuda
3
+ def initialize()
4
+ super()
5
+ end
6
+
7
+ def self.prepare
8
+ {
9
+ :make_instance => true
10
+ }
11
+ end
12
+
13
+ def self.depends
14
+ []
15
+ end
16
+ end
17
+ end
@@ -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
@@ -0,0 +1,3 @@
1
+ module Shiki
2
+ VERSION = "0.0.1"
3
+ 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: