opengraph_transporter 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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +45 -0
- data/Rakefile +12 -0
- data/bin/opengraph_transporter +21 -0
- data/lib/.DS_Store +0 -0
- data/lib/opengraph_transporter/.DS_Store +0 -0
- data/lib/opengraph_transporter/base.rb +214 -0
- data/lib/opengraph_transporter/browser.rb +99 -0
- data/lib/opengraph_transporter/common.rb +159 -0
- data/lib/opengraph_transporter/gracefulquit.rb +33 -0
- data/lib/opengraph_transporter/resources/FacebookLocales.xml +850 -0
- data/lib/opengraph_transporter/scraper.rb +136 -0
- data/lib/opengraph_transporter/version.rb +3 -0
- data/lib/opengraph_transporter.rb +22 -0
- data/opengraph_transporter.gemspec +31 -0
- data/test/.DS_Store +0 -0
- data/test/lib/.DS_Store +0 -0
- data/test/lib/opengraph_transporter/version_test.rb +8 -0
- data/test/test_helper.rb +3 -0
- metadata +210 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: aa0283f8d7638544d60cda64f99807201bb1a5e5
|
4
|
+
data.tar.gz: 8fcd12be282e33dbdb62fef653c3ee621b4df58c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d7dee52e5207f8e2ffcd78a56c4885373d7bc5d4bfd3d1d0e06caf97e3a93c6e4a12f5a70aa41ecb7309fd28e7b83fbca7c96b09cdbd004a9bed43b4d19c85d9
|
7
|
+
data.tar.gz: 8fd34a80d0b543ad24e37c5a33a6e3d779698a5953fe0fdc3dfb479b7b72bd17b8472a4a8880c9f480d788af067a953a1827c013c629307a54ed564c779b724d
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Barry Quigley
|
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,45 @@
|
|
1
|
+
# OpengraphTransporter
|
2
|
+
|
3
|
+
opengraph_transporter is a Ruby console app that exports Facebook OpenGraph translations between Developer Apps.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'opengraph_transporter'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install opengraph_transporter
|
18
|
+
|
19
|
+
|
20
|
+
## Requirements
|
21
|
+
|
22
|
+
* Ruby 1.9.3 or higher
|
23
|
+
* Firefox 22.0.0 or higher
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
1. Run opengraph_transporter
|
28
|
+
2. Enter Source Facebook Developer App ID and App Secret
|
29
|
+
3. Enter Destination Facebook Developer App ID and App Secret
|
30
|
+
4. Enter App translations locale.
|
31
|
+
5. Follow the prompts.
|
32
|
+
|
33
|
+
|
34
|
+
```
|
35
|
+
$ Please Enter Source Application Id
|
36
|
+
```
|
37
|
+
|
38
|
+
|
39
|
+
## Contributing
|
40
|
+
|
41
|
+
1. Fork it
|
42
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
43
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
44
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
45
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.libs << 'lib/opengraph_transporter'
|
8
|
+
t.test_files = FileList['test/lib/opengraph_transporter/*_test.rb']
|
9
|
+
t.verbose = true
|
10
|
+
end
|
11
|
+
|
12
|
+
task :default => :test
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
## $VERBOSE
|
4
|
+
## -W0 NO Warnings nil
|
5
|
+
## -W1 Quiet false
|
6
|
+
## -W2 Verbose true
|
7
|
+
BEGIN { $VERBOSE = false }
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'opengraph_transporter'
|
11
|
+
rescue LoadError
|
12
|
+
require 'rubygems'
|
13
|
+
require 'opengraph_transporter'
|
14
|
+
end
|
15
|
+
|
16
|
+
# -----------------------------------------------------------------------
|
17
|
+
# Main
|
18
|
+
# -----------------------------------------------------------------------
|
19
|
+
|
20
|
+
OpengraphTransporter::Base.run
|
21
|
+
|
data/lib/.DS_Store
ADDED
Binary file
|
Binary file
|
@@ -0,0 +1,214 @@
|
|
1
|
+
module OpengraphTransporter
|
2
|
+
class Base
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
@@translation = nil
|
7
|
+
@@user = {}
|
8
|
+
|
9
|
+
def run
|
10
|
+
setup
|
11
|
+
say("<%= color('Preparing Translations....', YELLOW, BOLD) %>")
|
12
|
+
prepare
|
13
|
+
Common.show_translations_info(translation)
|
14
|
+
say("<%= color('Process existing Destination application Translations (#{Base.translation[:dst_app_name]} native stubs) ....', YELLOW, BOLD) %>")
|
15
|
+
run_export
|
16
|
+
end
|
17
|
+
|
18
|
+
def translation
|
19
|
+
@@translation
|
20
|
+
end
|
21
|
+
|
22
|
+
def translation=(value)
|
23
|
+
@@translation = value
|
24
|
+
end
|
25
|
+
|
26
|
+
def user
|
27
|
+
@@user
|
28
|
+
end
|
29
|
+
|
30
|
+
def user=(value)
|
31
|
+
@@user = value
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect
|
35
|
+
"<#{self.name} user: #{user} translation: #{translation.inspect} >"
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
inspect
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def setup
|
45
|
+
display_app_splash
|
46
|
+
get_apps_details
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def run_export
|
51
|
+
translation[:dst_translation_arr] = Scraper.ingest_app_translations(translation[:destination_application_id], translation[:app_locale])
|
52
|
+
if translation[:dst_translation_arr].length == 0
|
53
|
+
say("No destination app <%= color('(#{Base.translation[:dst_app_name]})', RED, BOLD) %> Open Graph Translations found, please check that Open Graph stories exist and localization.")
|
54
|
+
else
|
55
|
+
translation[:src_translation_arr] = Scraper.update_display_names!(translation[:src_translation_arr], translation[:src_app_name].to_s, translation[:dst_app_name].to_s)
|
56
|
+
translations_cleanup
|
57
|
+
say("<%= color('Export Translations....', YELLOW, BOLD) %>")
|
58
|
+
choose do |menu|
|
59
|
+
menu.prompt = "This action will overwrite existing #{translation[:dst_app_name]} translations. Are you sure you want to export translations?"
|
60
|
+
menu.choice(:Yes) {
|
61
|
+
say("....starting Export!")
|
62
|
+
Browser.export
|
63
|
+
}
|
64
|
+
menu.choices(:No) { say("...exiting Exporter!") }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def prepare
|
70
|
+
src_translation_arr = Common.get_application_translations(translation[:source_app_token], translation[:app_locale], false)
|
71
|
+
dst_translation_arr = Common.get_application_translations(translation[:destination_app_token], translation[:app_locale], true)
|
72
|
+
translation[:src_translation_arr] = src_translation_arr
|
73
|
+
translation[:dst_translation_arr] = dst_translation_arr
|
74
|
+
|
75
|
+
if translation[:src_translation_arr].nil?
|
76
|
+
Common.show_arguments_info(translation)
|
77
|
+
say("<%= color('Invalid application data, please recheck application and locale settings.', RED, BOLD) %>")
|
78
|
+
exit
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_apps_details(error_keys = [])
|
83
|
+
invalid_entries = false
|
84
|
+
initialize_translation
|
85
|
+
|
86
|
+
translation.each do |key, val|
|
87
|
+
if val.empty? || error_keys.include?(key.to_s)
|
88
|
+
invalid_entries = true
|
89
|
+
case key
|
90
|
+
when :source_application_id then translation[key] = ask_for_app_id(key).to_s
|
91
|
+
when :source_application_secret then translation[key] = ask_for_app_secret(key)
|
92
|
+
when :destination_application_id then translation[key] = ask_for_app_id(key).to_s
|
93
|
+
when :destination_application_secret then translation[key] = ask_for_app_secret(key)
|
94
|
+
else translation[key] = ask("\nPlease Enter <%= color('#{capitalize(key)}', GREEN, BOLD) %>", String)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
if invalid_entries
|
100
|
+
validate_applications_data
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate_applications_data
|
105
|
+
locales = generate_locales
|
106
|
+
error_keys = []
|
107
|
+
|
108
|
+
if translation[:source_application_id].empty?
|
109
|
+
error_keys << "source_application_id"
|
110
|
+
end
|
111
|
+
if translation[:source_application_secret].empty?
|
112
|
+
error_keys << "source_application_secret"
|
113
|
+
end
|
114
|
+
if translation[:destination_application_id].empty?
|
115
|
+
error_keys << "destination_application_token"
|
116
|
+
end
|
117
|
+
if translation[:destination_application_secret].empty?
|
118
|
+
error_keys << "destination_application_secret"
|
119
|
+
end
|
120
|
+
if translation[:source_application_id].eql?(translation[:destination_application_id])
|
121
|
+
say("<%= color('Duplicated selection: ', RED, BOLD) %> please selection different source and destination applications. \n")
|
122
|
+
error_keys << "destination_application_id" << "destination_application_secret"
|
123
|
+
end
|
124
|
+
if translation[:app_locale].empty?
|
125
|
+
error_keys << "app_locale"
|
126
|
+
else
|
127
|
+
if !locales.include?(translation[:app_locale])
|
128
|
+
error_keys << "app_locale"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
if !error_keys.empty?
|
133
|
+
say("<%= color('Invalid Data: ', RED, BOLD) %> #{error_keys.join(' ')} \n")
|
134
|
+
choose do |menu|
|
135
|
+
menu.prompt = "Re-enter app details?"
|
136
|
+
menu.choice(:Yes) {
|
137
|
+
get_apps_details(error_keys)
|
138
|
+
}
|
139
|
+
menu.choices(:No) {
|
140
|
+
say("...exiting Exporter!")
|
141
|
+
exit
|
142
|
+
}
|
143
|
+
end
|
144
|
+
else
|
145
|
+
get_app_specfics
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def generate_locales
|
150
|
+
locales_arr = []
|
151
|
+
app_root = File.expand_path(File.dirname(__FILE__))
|
152
|
+
fb_locales_doc = File.open(File.join(app_root, "/resources/FacebookLocales.xml"))
|
153
|
+
locales = Nokogiri::XML(fb_locales_doc)
|
154
|
+
|
155
|
+
locales.xpath("//representation").each do |locale|
|
156
|
+
locales_arr << locale.text
|
157
|
+
end
|
158
|
+
|
159
|
+
return locales_arr
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_app_specfics
|
163
|
+
say("\n.....retrieving app tokens")
|
164
|
+
translation[:source_app_token] = Common.get_app_token(translation[:source_application_id], translation[:source_application_secret])
|
165
|
+
translation[:destination_app_token] = Common.get_app_token(translation[:destination_application_id], translation[:destination_application_secret])
|
166
|
+
|
167
|
+
translation[:src_app_name] = Common.get_application_name(translation[:source_app_token], translation[:source_application_id])
|
168
|
+
translation[:dst_app_name] = Common.get_application_name(translation[:destination_app_token], translation[:destination_application_id])
|
169
|
+
end
|
170
|
+
|
171
|
+
def initialize_translation
|
172
|
+
@@translation ||= {:source_application_id => '', :source_application_secret => '', :destination_application_id => '', :destination_application_secret => '', :app_locale => '' }
|
173
|
+
end
|
174
|
+
|
175
|
+
def translations_cleanup
|
176
|
+
Common.update_destination_translations(translation)
|
177
|
+
Common.remove_empty_translations(translation)
|
178
|
+
Common.show_translations_info(translation)
|
179
|
+
end
|
180
|
+
|
181
|
+
def capitalize(sym)
|
182
|
+
sym.to_s.split('_').map(&:capitalize).join(' ')
|
183
|
+
end
|
184
|
+
|
185
|
+
def ask_for_app_id(translation_key)
|
186
|
+
ask("\nPlease Enter <%= color('#{capitalize(translation_key)}', GREEN, BOLD) %>", lambda { |id| id.to_s.strip } ) do |q|
|
187
|
+
q.validate = lambda { |p| (p =~ /^\d{15}$/) != nil }
|
188
|
+
q.responses[:not_valid] = "Please enter a 15 digit App Id."
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def ask_for_app_secret(translation_key)
|
193
|
+
ask("\nPlease Enter <%= color('#{capitalize(translation_key)}', GREEN, BOLD) %>", lambda { |id| id.to_s.strip } ) do |q|
|
194
|
+
q.validate = lambda { |p| (p =~ /^[a-zA-Z0-9]{32}$/) != nil }
|
195
|
+
q.responses[:not_valid] = "Please enter a 32 character alphanumeric App Secret."
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def display_app_splash
|
200
|
+
puts "\n"
|
201
|
+
splash = ConsoleSplash.new(6, 88)
|
202
|
+
splash.write_horizontal_pattern("||")
|
203
|
+
splash.write_vertical_pattern("||")
|
204
|
+
splash.write_center(-4, "Open Graph Translations Exporter")
|
205
|
+
splash.write_center(-3, "Version: #{OpengraphTransporter::VERSION}")
|
206
|
+
splash.splash
|
207
|
+
puts "\n"
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module OpengraphTransporter
|
2
|
+
class Browser
|
3
|
+
|
4
|
+
MAX_TRANSLATION_PAGE_LIMIT = 30
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def export
|
9
|
+
begin
|
10
|
+
Watir.driver = :webdriver
|
11
|
+
@browser = Watir::Browser.new :firefox
|
12
|
+
@page_index_counter = 0
|
13
|
+
@translation_count_index = 0
|
14
|
+
@translation = Base.translation
|
15
|
+
@translation_arr = @translation [:dst_translation_arr].clone
|
16
|
+
fb_login
|
17
|
+
|
18
|
+
developer_translations_home_uri = "https://www.facebook.com/translations/admin/browse.php?search=&sloc=en_US&aloc=#{@translation[:app_locale]}&app=#{@translation[:destination_application_id]}"
|
19
|
+
@browser.goto developer_translations_home_uri
|
20
|
+
GracefulQuit.enable
|
21
|
+
parse_translation_rows
|
22
|
+
|
23
|
+
rescue Exception => e
|
24
|
+
say("An error occurred when generating automated browser, do you have FireFox installed? \n\n error: #{e}.")
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def parse_translation_rows
|
32
|
+
@translation_arr.each_with_index do |translation, index|
|
33
|
+
row_hash = "variant:" << translation[:native_hash]
|
34
|
+
translation_row = @browser.tr(:id, row_hash)
|
35
|
+
if translation_row.exists? && !translation[:translation].empty?
|
36
|
+
say("updating translation native hash: #{translation[:native_hash]} : #{translation[:translation]}")
|
37
|
+
translation_row.td(:class, /s_trans/).click
|
38
|
+
translation_row.textarea(:class, /uiTextareaAutogrow/).set translation[:translation]
|
39
|
+
translation_row.button(:id, /submit:/).click
|
40
|
+
sleep(0.25)
|
41
|
+
@translation_count_index += 1
|
42
|
+
end
|
43
|
+
GracefulQuit.check
|
44
|
+
end
|
45
|
+
process_next_page
|
46
|
+
end
|
47
|
+
|
48
|
+
def process_next_page
|
49
|
+
next_button = @browser.div(:class => "pagerpro_container").link(:text => /Next/)
|
50
|
+
if next_button.exists? && @page_index_counter < MAX_TRANSLATION_PAGE_LIMIT
|
51
|
+
begin
|
52
|
+
translations_page = @page_index_counter + 1
|
53
|
+
say("processing translation page.... #{translations_page + 1}")
|
54
|
+
@page_index_counter += 1
|
55
|
+
next_button.click
|
56
|
+
sleep(2.5)
|
57
|
+
parse_translation_rows
|
58
|
+
rescue Exception => e
|
59
|
+
say("Translation error: #{e}, carry on.")
|
60
|
+
parse_translation_rows
|
61
|
+
end
|
62
|
+
else
|
63
|
+
complete_translations_process
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def complete_translations_process
|
68
|
+
fb_logout
|
69
|
+
open_graph_translations_stats
|
70
|
+
end
|
71
|
+
|
72
|
+
def fb_login
|
73
|
+
say("\n.....logging into Facebook")
|
74
|
+
@browser.goto "https://www.facebook.com"
|
75
|
+
@browser.text_field(id: "email").set Base.user[:fb_username]
|
76
|
+
@browser.text_field(id: "pass").set Base.user[:fb_password]
|
77
|
+
@browser.label(id: "loginbutton").click
|
78
|
+
end
|
79
|
+
|
80
|
+
def fb_logout
|
81
|
+
say(".....logging out of Facebook \n")
|
82
|
+
@browser.div(id: "userNavigationLabel").click
|
83
|
+
@browser.label(class: "uiLinkButton navSubmenu").click
|
84
|
+
@browser.close
|
85
|
+
end
|
86
|
+
|
87
|
+
def open_graph_translations_stats
|
88
|
+
say("<%= color('\n***********************************************************************************************************', GREEN, BOLD) %>")
|
89
|
+
say("Source Application: <%= color('#{@translation[:src_app_name]}', GREEN, BOLD) %>")
|
90
|
+
say("Destination Application: <%= color('#{@translation[:dst_app_name]}', GREEN, BOLD) %>")
|
91
|
+
say("Export completed: <%= color('#{@translation[:dst_translation_arr].length} Open Graph translations processed', GREEN, BOLD) %>")
|
92
|
+
say("<%= color('***********************************************************************************************************\n', GREEN, BOLD) %>")
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module OpengraphTransporter
|
2
|
+
class Common
|
3
|
+
|
4
|
+
FB_GRAPH_HOST = "https://graph.facebook.com"
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def update_destination_translations(translation)
|
9
|
+
say(".....updating translation text")
|
10
|
+
translation[:dst_translation_arr].each do |dst_translation|
|
11
|
+
translation[:src_translation_arr].each do |src_translation|
|
12
|
+
if dst_translation[:native].eql?(src_translation['native'])
|
13
|
+
dst_translation[:translation] = src_translation['translation']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def remove_empty_translations(translation)
|
20
|
+
say(".....remove empty translations")
|
21
|
+
translation[:dst_translation_arr].each_with_index do |dst_translation, index|
|
22
|
+
if dst_translation[:translation].empty?
|
23
|
+
translation[:dst_translation_arr].delete_at(index)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_application_translations(app_token, app_locale, include_hash)
|
29
|
+
if include_hash
|
30
|
+
fql = %Q{select native_hash, native_string, best_string FROM translation WHERE locale = "#{app_locale}"}
|
31
|
+
mappings = {"native_hash" => "native_hash", "native_string" => "native", "best_string" => "translation"}
|
32
|
+
else
|
33
|
+
fql = %Q{select native_string, best_string FROM translation WHERE locale = "#{app_locale}"}
|
34
|
+
mappings = {"native_string" => "native", "best_string" => "translation"}
|
35
|
+
end
|
36
|
+
|
37
|
+
params = {:access_token => app_token, :q => fql}
|
38
|
+
request = 'fql'
|
39
|
+
app_translations = fb_graph_call(request, params)['data']
|
40
|
+
@app_translations = Array.new
|
41
|
+
|
42
|
+
app_translations.each do |translation|
|
43
|
+
@app_translations.push(Hash[translation.map {|k, v| [mappings[k], v] }])
|
44
|
+
end
|
45
|
+
|
46
|
+
if !include_hash
|
47
|
+
@app_translations = @app_translations.uniq!
|
48
|
+
end
|
49
|
+
return @app_translations
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_application_details(app_token, app_id)
|
53
|
+
fql = %Q{select display_name, description, link, namespace from application where app_id = #{app_id}}
|
54
|
+
params = {:access_token => app_token, :q => fql}
|
55
|
+
request = 'fql'
|
56
|
+
response = fb_graph_call(request, params)
|
57
|
+
return response['data'][0]
|
58
|
+
end
|
59
|
+
|
60
|
+
def show_translations_info(translation)
|
61
|
+
say("<%= color('\n***********************************************************************************************************', YELLOW, BOLD) %>")
|
62
|
+
say("Source Application ID: <%= color('#{translation[:source_application_id]}', BOLD) %> Existing translations: <%= color('#{translation[:src_translation_arr].length}', YELLOW, BOLD) %> Application Name: <%= color('#{translation[:src_app_name]}', BOLD) %>")
|
63
|
+
say("Destination Application ID: <%= color('#{translation[:destination_application_id]}', BOLD) %> Existing translations: <%= color('#{translation[:dst_translation_arr].length}', YELLOW, BOLD) %> Application Name: <%= color('#{translation[:dst_app_name]}', BOLD) %>")
|
64
|
+
say("<%= color('***********************************************************************************************************\n', YELLOW, BOLD) %>")
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def show_arguments_info(translation)
|
69
|
+
say("<%= color('\n***********************************************************************************************************', YELLOW, BOLD) %>")
|
70
|
+
say("Source Application ID: <%= color('#{Base.translation[:source_application_id]}', YELLOW, BOLD) %> Application Name: <%= color('#{Base.translation[:src_app_name]}', YELLOW, BOLD) %>")
|
71
|
+
say("Destination Application ID: <%= color('#{Base.translation[:destination_application_id]}', YELLOW, BOLD) %> Application Name: <%= color('#{Base.translation[:dst_app_name]}', YELLOW, BOLD) %>")
|
72
|
+
say("Selected Locale: <%= color('#{Base.translation[:app_locale]}', YELLOW, BOLD) %>")
|
73
|
+
say("<%= color('***********************************************************************************************************\n', YELLOW, BOLD) %>")
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_application_name(app_token, app_id)
|
77
|
+
params = {:access_token => app_token}
|
78
|
+
request = "#{app_id}"
|
79
|
+
response = fb_graph_call(request, params)
|
80
|
+
if response.nil?
|
81
|
+
show_arguments_info(translation)
|
82
|
+
say("<%= color('Invalid application data, please recheck application and locale settings.', RED, BOLD) %>")
|
83
|
+
exit
|
84
|
+
end
|
85
|
+
return response['name']
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_app_token(app_id, app_secret)
|
89
|
+
params = {
|
90
|
+
:client_id => app_id,
|
91
|
+
:client_secret => app_secret,
|
92
|
+
:grant_type => 'client_credentials'
|
93
|
+
}
|
94
|
+
path = "/oauth/access_token"
|
95
|
+
response = fb_graph_call(path, params, {:format => :text})
|
96
|
+
|
97
|
+
if response.nil?
|
98
|
+
say("<%= color('Invalid Data:', RED, BOLD) %> please recheck source and destination app_id and app_secret.")
|
99
|
+
exit
|
100
|
+
end
|
101
|
+
|
102
|
+
dummy = Addressable::URI.new
|
103
|
+
dummy.query = response
|
104
|
+
access_token = dummy.query_values["access_token"]
|
105
|
+
|
106
|
+
return access_token
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def fb_graph_call(path, params = {}, options = {})
|
113
|
+
clnt = HTTPClient.new
|
114
|
+
uri = Addressable::URI.parse(FB_GRAPH_HOST)
|
115
|
+
uri.path = path
|
116
|
+
query = params
|
117
|
+
# default to JSON response
|
118
|
+
options = {:format => :json}.merge(options)
|
119
|
+
begin
|
120
|
+
response = clnt.get(uri, query)
|
121
|
+
if response.status == 200
|
122
|
+
case options[:format]
|
123
|
+
when :text then response.body
|
124
|
+
else JSON.parse(response.content)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
rescue StandardError => e
|
128
|
+
say("Graph Call error: #{e}")
|
129
|
+
say("...exiting Exporter!")
|
130
|
+
exit
|
131
|
+
# raise e
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# unused
|
136
|
+
def write_csv(translations_arr)
|
137
|
+
unless translations_arr.length == 0
|
138
|
+
csv_file_name = "appid_#{@translation[:source_application_id]}.csv"
|
139
|
+
csv_tmp_file = Tempfile.new(csv_file_name)
|
140
|
+
headers_arr = Array.new
|
141
|
+
translations_arr[0].each_key {|key| headers_arr.push(key) }
|
142
|
+
|
143
|
+
CSV.open(csv_tmp_file, "w") do |csv|
|
144
|
+
csv << headers_arr
|
145
|
+
translations_arr.each do |el|
|
146
|
+
csv << el.values
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
send_file csv_tmp_file, :type => 'text/csv', :disposition => 'download', :filename => csv_file_name
|
151
|
+
csv_tmp_file.close
|
152
|
+
csv_tmp_file.unlink
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "singleton"
|
2
|
+
module OpengraphTransporter
|
3
|
+
|
4
|
+
class GracefulQuit
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
attr_accessor :breaker
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
self.breaker = false
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
def enable
|
16
|
+
trap('INT') {
|
17
|
+
yield if block_given?
|
18
|
+
self.instance.breaker = true
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def check(message = "Quitting Exporter")
|
23
|
+
if self.instance.breaker
|
24
|
+
yield if block_given?
|
25
|
+
puts message
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|