social_media 0.0.1 → 0.0.3
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.
- checksums.yaml +4 -4
- data/README.md +123 -17
- data/lib/social_media/errors.rb +3 -1
- data/lib/social_media/service/base.rb +10 -1
- data/lib/social_media/service/twitter.rb +35 -10
- data/lib/social_media/version.rb +1 -1
- metadata +15 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3645c86fb3100ad97c8d96b815909f4e4efec2f7
|
4
|
+
data.tar.gz: 2fc2e9b44d9ffa04525ce28a67fa0aa96a28e3d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68a239377322773877518168bd6d4ff027b56d732ce70ab7ef3cc5dab65539ab497c424e5eb0f3c1c15cf72119305e8eec03ff2fd4ae6bdb2ce84039b75e0272
|
7
|
+
data.tar.gz: 74c94291b1046b800f5b6c866f27a84b5498ecad11abaf0dbc76a7bf42275f0fb9f6a1564f3ec8a131bca298e96d381d46adfaed8b5eced87604aabc7b7bb8dd
|
data/README.md
CHANGED
@@ -1,28 +1,65 @@
|
|
1
1
|
# SocialMedia
|
2
2
|
|
3
|
-
Facebook: 1,712,000,000 users
|
4
|
-
WhatsApp 1,000,000,000 users
|
5
|
-
Facebook Messenger: 1,000,000,000 users
|
6
|
-
QQ: 899,000,000 users
|
7
|
-
WeChat: 806,000,000 users
|
8
|
-
QZone: 652,000,000 users
|
9
|
-
Tumblr: 555,000,000 users
|
10
|
-
Instagram: 500,000,000 users
|
11
|
-
Twitter: 313,000,000 users
|
12
|
-
Baidu Tieba: 300,000,000 users
|
13
|
-
Skype: 300,000,000 users
|
14
|
-
Sina Weibo: 282,000,000 users
|
15
|
-
Viber: 249,000,000 users
|
16
|
-
Line: 218,000,000 users
|
17
|
-
Snapchat: 200,000,000 users
|
18
|
-
|
19
3
|
## Usage
|
20
4
|
The idea is to treat social media sites like databases. With that in mind, we'll have adapters for each each social media service
|
21
5
|
that we connect, passing the appropriate connection strings to. Once connected, we can then query and publish to the connection using
|
22
6
|
the same method calls and parameters across the various social media services. Of course some services will have more functionality
|
23
7
|
than others. The library can be configured to silently ignore limited functionality or to explicitly raise errors.
|
24
8
|
|
9
|
+
The main objective with this library is to enable centralized maintenance of Profile/Account information across many social media
|
10
|
+
services and directory listing sites -- a critical component of local businesses optimizing for Google Maps local results.
|
11
|
+
|
12
|
+
Save your credentials in a YAML file (config/services.yml, for example):
|
13
|
+
```yaml
|
14
|
+
twitter:
|
15
|
+
consumer_key: 'YOUR_CONSUMER_KEY'
|
16
|
+
consumer_secret: 'YOUR_CONSUMER_SECRET'
|
17
|
+
access_token: 'YOUR_ACCESS_TOKEN'
|
18
|
+
access_token_secret: 'YOUR_ACCESS_TOKEN_SECRET'
|
19
|
+
|
20
|
+
facebook:
|
21
|
+
app_key: 'YOUR_APP_KEY'
|
22
|
+
app_secret: 'YOUR_APP_SECRET'
|
23
|
+
|
24
|
+
# ...
|
25
|
+
```
|
26
|
+
|
27
|
+
Load and go!
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require 'social_media'
|
31
|
+
|
32
|
+
def symbolized_keys hash
|
33
|
+
hash.keys.each do |key|
|
34
|
+
hash[(key.to_sym rescue key) || key] = hash.delete(key)
|
35
|
+
end
|
36
|
+
hash.each_pair{|k,v| hash[k] = symbolized_keys(v) if v.is_a?(Hash)}
|
37
|
+
return hash
|
38
|
+
end
|
39
|
+
|
40
|
+
def service_configurations
|
41
|
+
config_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'config'))
|
42
|
+
@service_configurations ||= symbolized_keys YAML::load_file(File.join(config_path, 'services.yml'))
|
43
|
+
end
|
44
|
+
|
45
|
+
my_new_avatar_filename = "./images/avatar.png"
|
46
|
+
|
47
|
+
service_configurations.each_key do |service_name|
|
48
|
+
options = service_configurations[service_name]
|
49
|
+
options.merge!(not_provided_error: :silent)
|
50
|
+
client = SocialMedia::Service::service(service_name).new options
|
51
|
+
client.send_message "Just Rambling about Social Media"
|
52
|
+
client.upload_profile_avatar my_new_avatar_filename
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
The above would iterate every service, send a text message and upload a new profile avatar (for the services that support it).
|
57
|
+
In the above example, the "not_provided_error: :silent" allows services that do not implement a specific API to silently fail.
|
58
|
+
This makes it easy to build an app that updates as many possible profile/account fields without worrying about dealing with
|
59
|
+
shortcomings of the library itself.
|
60
|
+
|
25
61
|
## Installation
|
62
|
+
|
26
63
|
Add this line to your application's Gemfile:
|
27
64
|
|
28
65
|
```ruby
|
@@ -40,7 +77,76 @@ $ gem install social_media
|
|
40
77
|
```
|
41
78
|
|
42
79
|
## Contributing
|
43
|
-
|
80
|
+
|
81
|
+
So far, the following have been implemented:
|
82
|
+
|
83
|
+
* Twitter
|
84
|
+
* Facebook (WiP)
|
85
|
+
* Linkedin (WiP)
|
86
|
+
* Google+ (WiP)
|
87
|
+
|
88
|
+
The following are planned:
|
89
|
+
|
90
|
+
### Social Media Services:
|
91
|
+
* Yahoo
|
92
|
+
* Facebook
|
93
|
+
* Apple
|
94
|
+
* Yelp
|
95
|
+
* WhitePages
|
96
|
+
* Local.com
|
97
|
+
* Foursquare
|
98
|
+
|
99
|
+
### Directories:
|
100
|
+
* Google
|
101
|
+
* Bing
|
102
|
+
* MapQuest
|
103
|
+
* Superpages
|
104
|
+
* CitySearch
|
105
|
+
* MerchantCircle
|
106
|
+
* eLocal
|
107
|
+
* Topic
|
108
|
+
* YellowPageCity
|
109
|
+
* LocalStack
|
110
|
+
* ShowMeLocal
|
111
|
+
* EZLocal
|
112
|
+
* WhereTo?
|
113
|
+
* YellowMoxie
|
114
|
+
* CitySquares
|
115
|
+
* LocalDatabase
|
116
|
+
* Yellowise
|
117
|
+
|
118
|
+
### Statistics
|
119
|
+
|
120
|
+
* Facebook: 1,712,000,000 users
|
121
|
+
* WhatsApp 1,000,000,000 users
|
122
|
+
* Facebook Messenger: 1,000,000,000 users
|
123
|
+
* QQ: 899,000,000 users
|
124
|
+
* WeChat: 806,000,000 users
|
125
|
+
* QZone: 652,000,000 users
|
126
|
+
* Tumblr: 555,000,000 users
|
127
|
+
* Instagram: 500,000,000 users
|
128
|
+
* Twitter: 313,000,000 users
|
129
|
+
* Baidu Tieba: 300,000,000 users
|
130
|
+
* Skype: 300,000,000 users
|
131
|
+
* Sina Weibo: 282,000,000 users
|
132
|
+
* Viber: 249,000,000 users
|
133
|
+
* Line: 218,000,000 users
|
134
|
+
* Snapchat: 200,000,000 users
|
135
|
+
|
136
|
+
## Contributing
|
137
|
+
|
138
|
+
This is an open source project. If you don't see a service implemented that you need, then fork the project, implement, and
|
139
|
+
submit your pull request. Make sure your PR is accompanied by specs, but *don't commit account credentials* to the repo!
|
140
|
+
That also means you should never check in your VCR cassettes. If someone else wants to test a service, they should set up
|
141
|
+
their own accounts and generate their own VCR cassettes.
|
142
|
+
|
143
|
+
Testing is done by setting up a spec/config/services.yml which has the keyname that matches the new service's name.
|
144
|
+
|
145
|
+
You'll need to add a new:
|
146
|
+
* lib/service/new_service.rb
|
147
|
+
* spec/lib/service/new_service_spec.rb
|
148
|
+
* connection credentials to spec/config/services.yml
|
149
|
+
* any gem dependencies for the new service if you use an API/SDK library.
|
44
150
|
|
45
151
|
## License
|
46
152
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/social_media/errors.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module SocialMedia
|
2
|
-
|
3
2
|
def self.convert_exception_class exception, klass
|
4
3
|
return exception if exception.is_a?(klass)
|
5
4
|
e = klass.new("#{exception.class}: #{exception.message}")
|
@@ -16,4 +15,7 @@ module SocialMedia
|
|
16
15
|
|
17
16
|
Unauthorized = Class.new(Error)
|
18
17
|
Error::Unauthorized = Unauthorized
|
18
|
+
|
19
|
+
NotProvided = Class.new(Error)
|
20
|
+
Error::NotProvided = NotProvided
|
19
21
|
end
|
@@ -6,15 +6,24 @@ module SocialMedia
|
|
6
6
|
end
|
7
7
|
|
8
8
|
attr_reader :connection_params
|
9
|
+
attr_reader :not_provided_behavior
|
9
10
|
|
10
11
|
def initialize connection_params
|
11
12
|
@connection_params = connection_params
|
13
|
+
@not_provided_behavior = connection_params.delete(:not_provided_behavior) || :raise_error
|
12
14
|
end
|
13
15
|
|
14
16
|
def cast_error error
|
15
17
|
return Error
|
16
18
|
end
|
17
|
-
|
19
|
+
|
20
|
+
def raise_not_provided_error
|
21
|
+
return if not_provided_behavior == :silent
|
22
|
+
|
23
|
+
method_name = caller.first.scan(/\:in \`(.*)\'$/).join
|
24
|
+
raise SocialMedia::Error::NotProvided.new "#{self.class.to_s}##{method_name}"
|
25
|
+
end
|
26
|
+
|
18
27
|
def handle_error &block
|
19
28
|
begin
|
20
29
|
yield
|
@@ -20,7 +20,7 @@ module SocialMedia::Service
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def send_message message, options={}
|
23
|
-
return send_text_message(message, options) unless options.has_key? :
|
23
|
+
return send_text_message(message, options) unless options.has_key?(:filenames) || options.has_key?(:filename)
|
24
24
|
send_multipart_message message, options
|
25
25
|
end
|
26
26
|
|
@@ -29,17 +29,44 @@ module SocialMedia::Service
|
|
29
29
|
result.first.id
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
client.update_profile_banner(
|
32
|
+
def upload_profile_cover filename
|
33
|
+
client.update_profile_banner(open_file filename)
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
|
36
|
+
def remove_profile_cover
|
37
|
+
client.remove_profile_banner
|
38
|
+
end
|
39
|
+
|
40
|
+
def upload_profile_avatar filename
|
41
|
+
result = client.update_profile_image(open_file filename)
|
38
42
|
result.id
|
39
43
|
end
|
40
44
|
|
45
|
+
def remove_profile_avatar
|
46
|
+
raise_not_provided_error
|
47
|
+
end
|
48
|
+
|
41
49
|
private
|
42
50
|
|
51
|
+
# The Twitter gem is particular about the type of IO object it
|
52
|
+
# recieves when tweeting an image. If an image is < 10kb, Ruby opens it as a
|
53
|
+
# StringIO object. Which is not supported by the Twitter gem/api.
|
54
|
+
#
|
55
|
+
# This method ensures we always have a valid IO object for Twitter.
|
56
|
+
def open_file filename
|
57
|
+
image_file = open(filename)
|
58
|
+
return image_file unless image_file.is_a?(StringIO)
|
59
|
+
|
60
|
+
base_name = File.basename(filename)
|
61
|
+
temp_file = Tempfile.new(base_name)
|
62
|
+
|
63
|
+
temp_file.binmode
|
64
|
+
temp_file.write(image_file.read)
|
65
|
+
temp_file.close
|
66
|
+
|
67
|
+
open(temp_file.path)
|
68
|
+
end
|
69
|
+
|
43
70
|
def send_text_message message, options
|
44
71
|
handle_error do
|
45
72
|
result = client.update(message, options)
|
@@ -48,11 +75,9 @@ module SocialMedia::Service
|
|
48
75
|
end
|
49
76
|
|
50
77
|
def send_multipart_message message, options
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
result.id
|
55
|
-
end
|
78
|
+
media_ids = Array(options.delete(:filename)).map{ |fn| client.upload open_file(fn) }
|
79
|
+
media_ids += Array(options.delete(:filenames)).map{ |fn| client.upload open_file(fn) }
|
80
|
+
send_text_message message, options.merge(media_ids: media_ids.join(","))
|
56
81
|
end
|
57
82
|
end
|
58
83
|
end
|
data/lib/social_media/version.rb
CHANGED
metadata
CHANGED
@@ -1,71 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: social_media
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mwlang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: twitter
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 6.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 6.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: koala
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '2.4'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: '2.4'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: google-api-client
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0.9'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0.9'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
62
|
-
type: :
|
61
|
+
version: 10.5.0
|
62
|
+
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 10.5.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|