cackle 0.0.2

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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +67 -0
  4. data/Rakefile +32 -0
  5. data/lib/app/helpers/cackle_helper.rb +18 -0
  6. data/lib/app/models/cackle_comment.rb +5 -0
  7. data/lib/app/views/cackle/comments.html.haml +27 -0
  8. data/lib/app/views/cackle/recent.html.haml +62 -0
  9. data/lib/cackle.rb +13 -0
  10. data/lib/cackle/railtie.rb +7 -0
  11. data/lib/cackle/version.rb +3 -0
  12. data/lib/generators/cackle_migration/cackle_migration_generator.rb +19 -0
  13. data/lib/generators/cackle_migration/templates/migration.rb +22 -0
  14. data/lib/tasks/cackle_tasks.rake +90 -0
  15. data/test/cackle_test.rb +7 -0
  16. data/test/dummy/README.rdoc +28 -0
  17. data/test/dummy/Rakefile +6 -0
  18. data/test/dummy/app/assets/javascripts/application.js +13 -0
  19. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  20. data/test/dummy/app/controllers/application_controller.rb +5 -0
  21. data/test/dummy/app/helpers/application_helper.rb +2 -0
  22. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  23. data/test/dummy/bin/bundle +3 -0
  24. data/test/dummy/bin/rails +4 -0
  25. data/test/dummy/bin/rake +4 -0
  26. data/test/dummy/config.ru +4 -0
  27. data/test/dummy/config/application.rb +23 -0
  28. data/test/dummy/config/boot.rb +5 -0
  29. data/test/dummy/config/database.yml +25 -0
  30. data/test/dummy/config/environment.rb +5 -0
  31. data/test/dummy/config/environments/development.rb +29 -0
  32. data/test/dummy/config/environments/production.rb +80 -0
  33. data/test/dummy/config/environments/test.rb +36 -0
  34. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  35. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  36. data/test/dummy/config/initializers/inflections.rb +16 -0
  37. data/test/dummy/config/initializers/mime_types.rb +5 -0
  38. data/test/dummy/config/initializers/secret_token.rb +12 -0
  39. data/test/dummy/config/initializers/session_store.rb +3 -0
  40. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  41. data/test/dummy/config/locales/en.yml +23 -0
  42. data/test/dummy/config/routes.rb +56 -0
  43. data/test/dummy/db/test.sqlite3 +0 -0
  44. data/test/dummy/log/test.log +5 -0
  45. data/test/dummy/public/404.html +58 -0
  46. data/test/dummy/public/422.html +58 -0
  47. data/test/dummy/public/500.html +57 -0
  48. data/test/dummy/public/favicon.ico +0 -0
  49. data/test/test_helper.rb +15 -0
  50. metadata +155 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 795976ed8d1dad277d90976a5b9c3b50043b847b
4
+ data.tar.gz: 73aeafd4731b674daa22a5645b2251c0cbbadfca
5
+ SHA512:
6
+ metadata.gz: 8f1e8f3470be58a6abc29fc528c6aa767357c3846e4a520d7e417e60f76fc2ffb1c2c201ee950bab56a11fa917edf27864620427d9632b7f372dd4ed6d36381d
7
+ data.tar.gz: 66fe2a831c2b9f0340f736a3428c77b0e05d4c9e8674cad1174fe80d367a5b6055ccfc7cd435fe1f4267826c18109ca3a097eb0819e206491b2e641ee74e69a1
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,67 @@
1
+ Cackle.me integration
2
+ =====================
3
+
4
+ Simple Rails plugin implements synchronization of Cackle.me comments.
5
+
6
+ Cackle.me is a real-time comment system with the ability to login
7
+ via popular social networks such as Google+, Facebook, Twitter,
8
+ LinkedIn, Vkontakte, Odnoklassniki, Mail.ru and many others.
9
+
10
+ Storing in local database make comments visible to search robots.
11
+
12
+ Installation
13
+ ------------
14
+
15
+ Add to Gemfile
16
+ ```ruby
17
+ gem 'cackle'
18
+ ```
19
+
20
+ Generate and run migration
21
+ ```
22
+ rails g cacke_migration
23
+ rake db:migrate
24
+ ```
25
+ Create config file config/cackle.yml
26
+ See http://cackle.me/help/comment-sync to get your keys
27
+
28
+ ```yml
29
+ site_id: 12345 # Site ID
30
+ site_api_key: blah-blah-blah # Account API Key
31
+ account_api_key: blah-blah-blah # Site API Key
32
+ jquery_off: true # Disable including jQuery if you already have it loaded
33
+
34
+ recent: # configuretion for recent comments block
35
+ mcSize: 10 # how many comments to display
36
+ mcAvatarSize: 32 # size of avatar image in pixels
37
+ mcTextSize: 150 # length of message block if more shorten with '...'
38
+ mcTitleSize: 40 # title length
39
+ ```
40
+
41
+ Helper methods
42
+ ==============
43
+
44
+ Insert comments widget
45
+ ```ruby
46
+ cackle_comments
47
+ ```
48
+ Recent comments widget
49
+ ```ruby
50
+ cackle_recent_comments
51
+ ```
52
+
53
+ Rake tasks
54
+ ==========
55
+ First time import. Warning clears all comments in base.
56
+ ```
57
+ cackle:import
58
+ ```
59
+
60
+ Syncronize changes. Should be called every 5 minutes by cron.
61
+ ```
62
+ cackle:sync
63
+ ```
64
+
65
+ License
66
+ -------
67
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Cackle'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+ Bundler::GemHelper.install_tasks
21
+
22
+ require 'rake/testtask'
23
+
24
+ Rake::TestTask.new(:test) do |t|
25
+ t.libs << 'lib'
26
+ t.libs << 'test'
27
+ t.pattern = 'test/**/*_test.rb'
28
+ t.verbose = false
29
+ end
30
+
31
+
32
+ task default: :test
@@ -0,0 +1,18 @@
1
+ module CackleHelper
2
+ def cackle_comments
3
+ load_config
4
+ @comments = CackleComment.approved.where("url LIKE ?", "%#{request.path}")
5
+ render template: 'cackle/comments'
6
+ end
7
+
8
+ def cackle_recent_comments
9
+ load_config
10
+ @comments = CackleComment.approved.limit(@config['recent']['mcSize'])
11
+ render template: 'cackle/recent'
12
+ end
13
+
14
+ private
15
+ def load_config
16
+ @config ||= YAML::load(File.open('config/cackle.yml'))
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ class CackleComment < ActiveRecord::Base
2
+ self.primary_key = 'comment_id'
3
+ default_scope order: 'created_at DESC'
4
+ scope :approved, -> { where(status: 'approved') }
5
+ end
@@ -0,0 +1,27 @@
1
+ #mc-container
2
+ #mc-content
3
+ %ul#cackle-comments
4
+ - @comments.each do |comment|
5
+ %li{ id: "cackle-comment-#{comment.comment_id}" }
6
+ #cackle-comment-header.cackle-comment-header
7
+ %cite{ id: "cackle-cite-#{comment.comment_id}" }
8
+ -if comment.author_name
9
+ = link_to comment.author_name, '#', target: '_blank', id: comment.comment_id, rel: 'nofollow'
10
+ -else
11
+ %span{ id: "cackle-author-user-#{comment.comment_id}" }= comment.author_name
12
+ .cackle-comment-body{ id: "cackle-comment-body-#{comment.comment_id}" }
13
+ .cackle-comment-message{ id: "cackle-comment-message-#{comment.comment_id}" }= comment.message
14
+
15
+ :javascript
16
+ var href = window.location.href;
17
+ if (href.indexOf('?') > 0) {
18
+ var mcChannel = href.substring(0, href.indexOf('?'));
19
+ };
20
+ var mcSite = '#{@config['site_id']}';
21
+ (function() {
22
+ var mc = document.createElement('script');
23
+ mc.type = 'text/javascript';
24
+ mc.async = true;
25
+ mc.src = 'http://cackle.me/mc.widget-min.js';
26
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(mc);
27
+ })();
@@ -0,0 +1,62 @@
1
+ :css
2
+ .mc-last-content{position:relative!important;width:100%!important;display:inline-block!important}
3
+ .mc-last-content div,.mc-last-content p,.mc-last-content h3{display:block!important}
4
+ .mc-last-content ul,.mc-last-content li,.mc-last-content ol,.mc-last-content div,.mc-last-content p,.mc-last-content a,.mc-last-content img{background:none repeat scroll 0 50% transparent!important;border:0 none!important;font-style:normal!important;margin:0!important;padding:0!important;text-align:left!important;text-indent:0!important}
5
+ .mc-last-content ul,.mc-last-content li{border:none!important;list-style:none!important;list-style-position:outside!important;list-style-type:none!important;line-height:normal!important}
6
+ .mc-last-content li>div{margin-bottom:5px!important;position:relative!important;word-wrap:break-word!important}
7
+ .mc-last-content li .mc-recent-thumb{position:relative!important;margin-right:6px!important;padding:0!important;float:left!important;width:auto!important}
8
+ .mc-last-content li .mc-recent-thumb:after{border-radius:2px!important;box-shadow:0 0 3px rgba(0,0,0,0.33) inset!important;position:absolute!important;left:0!important;top:0!important;content:" "!important;width:100%!important;height:100%!important}
9
+ .mc-last-content .mc-recent-thumb img{border-radius:2px!important;max-width:100%!important;height:auto!important;float:left!important;vertical-align:middle!important;border:0!important}
10
+ .mc-last-content .mc-recent-body{margin-left:38px!important;line-height:15px!important}
11
+ .mc-last-content .mc-recent-author{color:#8a8a8a!important;font-size:13px!important;font-weight:bold!important;line-height:14px!important;text-decoration:none!important;padding:0!important}
12
+ .mc-last-content .mc-recent-text{font-size:12px!important;line-height:16px!important;margin-top:2px!important}
13
+ .mc-last-content .mc-recent-text a,.mc-last-content .mc-recent-text a:hover{color:inherit!important;text-decoration:none!important}
14
+ .mc-last-content .mc-recent-meta{border-bottom:1px dotted #e0e0e0!important;font-size:11px!important;line-height:15px!important;margin-top:4px!important;color:#a7a7a7!important}
15
+ .mc-last-content .mc-recent-meta a{text-decoration:none!important;color:#a7a7a7!important;font-size:11px!important}
16
+ #mc-link{color:#555!important;font-size:11px!important;clear:both!important;float:right;text-decoration:none!important}
17
+ #mc-link:hover{color:#333!important}
18
+ .mc-recent-thumb img{
19
+ width: #{@config['recent']['mcAvatarSize']}px;
20
+ height: #{@config['recent']['mcAvatarSize']}px;
21
+ }
22
+ #mc-last
23
+ .mc-last-content
24
+ %ul
25
+ - @comments.each do |comment|
26
+ %li
27
+ %div
28
+ - if comment.author_name
29
+ = link_to comment.author_www, target: '_blank' do
30
+ %span.mc-recent-thumb= image_tag(comment.author_avatar, alt: comment.author_name)
31
+ - else
32
+ %span.mc-recent-thumb= image_tag('http://cackle.me/static/img/anonym.png', alt: comment.anonym_name)
33
+ .mc-recent-body
34
+ %div
35
+ - if comment.author_name
36
+ = link_to comment.author_www, target: '_blank' do
37
+ %span.mc-recent-author= comment.author_name
38
+ - else
39
+ %span.mc-recent-author= comment.anonym_name
40
+ %p.mc-recent-text= link_to comment.message.truncate(@config['recent']['mcTextSize']), comment.url + "#mc-#{comment.id}"
41
+ %p.mc-recent-meta
42
+ = link_to comment.title.truncate(@config['recent']['mcTitleSize']), comment.url, title: comment.title
43
+ - unless 1.month.ago > (date = comment.created_at)
44
+ · #{time_ago_in_words date} назад
45
+ - else
46
+ · #{date.strftime("%d.%m")}
47
+ = date.strftime("%H:%M")
48
+
49
+ :javascript
50
+ var mcSite = '#{@config['site_id']}';
51
+ var mcSize = '#{@config['recent']['mcSize']}';
52
+ var mcAvatarSize = '#{@config['recent']['mcAvatarSize']}';;
53
+ var mcTextSize = '#{@config['recent']['mcTextSize']}';
54
+ var mcTitleSize = '#{@config['recent']['mcTitleSize']}';
55
+ var mcJqueryOff = #{@config['recent']['mcJqueryOff']};
56
+ (function() {
57
+ var mc = document.createElement('script');
58
+ mc.type = 'text/javascript';
59
+ mc.async = true;
60
+ mc.src = 'http://cackle.me/mc.last-min.js';
61
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(mc);
62
+ })();
@@ -0,0 +1,13 @@
1
+ module Cackle
2
+ require "cackle/railtie" if defined?(Rails)
3
+ require 'app/helpers/cackle_helper'
4
+
5
+ ActionView::Base.send :include, CackleHelper
6
+
7
+ path = File.join(File.dirname(__FILE__), 'app', 'models')
8
+ $LOAD_PATH << path
9
+ ActiveSupport::Dependencies.autoload_paths << path
10
+ ActiveSupport::Dependencies.autoload_once_paths.delete(path)
11
+
12
+ ActionController::Base.prepend_view_path File.join(File.dirname(__FILE__), 'app/views')
13
+ end
@@ -0,0 +1,7 @@
1
+ module Cackle
2
+ require 'rails'
3
+
4
+ class Railtie < Rails::Railtie
5
+ rake_tasks { load "tasks/cackle_tasks.rake" }
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Cackle
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,19 @@
1
+ class CackleMigrationGenerator < Rails::Generators::Base
2
+ require 'rails/generators'
3
+ require 'rails/generators/migration'
4
+
5
+ include Rails::Generators::Migration
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ def self.next_migration_number(dirname)
9
+ if ActiveRecord::Base.timestamped_migrations
10
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
11
+ else
12
+ "%.3d" % (current_migration_number(dirname) + 1)
13
+ end
14
+ end
15
+
16
+ def create_migration_file
17
+ migration_template 'migration.rb', 'db/migrate/create_cackle_comments.rb'
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ class CreateCackleComments < ActiveRecord::Migration
2
+ def change
3
+ create_table :cackle_comments, id: false do |t|
4
+ t.integer :comment_id
5
+ t.integer :parent_id
6
+ t.string :post_id
7
+ t.string :url
8
+ t.string :title
9
+ t.text :message
10
+ t.string :status
11
+ t.string :ip
12
+ t.string :author_name
13
+ t.string :author_email
14
+ t.string :author_avatar
15
+ t.string :author_www
16
+ t.string :author_provider
17
+ t.string :anonym_name
18
+ t.string :anonym_email
19
+ t.timestamps
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,90 @@
1
+ require 'open-uri'
2
+
3
+ namespace :cackle do
4
+ def load_config
5
+ @config = YAML::load(File.open('config/cackle.yml'))
6
+ @path = "http://cackle.me/api/comment/mutable_list?siteApiKey=#{@config['site_api_key']}&accountApiKey=#{@config['account_api_key']}"
7
+ raise "Create config/cackle.yml first" unless @config
8
+
9
+ puts "will use: "
10
+ puts @config['site_id']
11
+ puts @config['site_api_key']
12
+ puts @config['account_api_key']
13
+ end
14
+
15
+ def create_comment c
16
+ comment = CackleComment.new(
17
+ comment_id: c['id'],
18
+ parent_id: c['parentId'],
19
+ post_id: c['channel'],
20
+ url: c['url'],
21
+ title: c['title'],
22
+ message: c['message'],
23
+ status: c['status'],
24
+ ip: c['ip'],
25
+ created_at: Time.strptime((c['created']/1000).to_s, "%s"),
26
+ updated_at: Time.strptime(c['modified'][0..9], "%s"))
27
+ if c['author']
28
+ comment.author_name = c['author']['name']
29
+ comment.author_email = c['author']['email']
30
+ comment.author_www = c['author']['www']
31
+ comment.author_avatar = c['author']['avatar']
32
+ comment.author_provider = c['author']['provider']
33
+ else
34
+ comment.anonym_name = c['anonym']['name']
35
+ comment.anonym_email = c['anonym']['email']
36
+ end
37
+ if comment.save
38
+ puts "created #{comment.comment_id}"
39
+ end
40
+ end
41
+
42
+ desc 'Initial comment base load'
43
+ task import: :environment do
44
+ CackleComment.delete_all
45
+ load_config
46
+ begin
47
+ max = CackleComment.maximum('created_at')
48
+ @url = max ? @path + "&modified=#{max.to_i*1000}" : @path
49
+ response = open(@url).read
50
+ json = JSON.parse(response)
51
+ comments = json['comments']
52
+ comments.each do |c|
53
+ create_comment c
54
+ end
55
+ end while (comments.size == 100)
56
+ puts "Total #{CackleComment.count} in base"
57
+ end
58
+
59
+ desc 'Synchronize comments database'
60
+ task sync: :environment do
61
+ load_config
62
+
63
+ max = CackleComment.maximum('updated_at')
64
+ raise "run bootstrap first" unless max
65
+
66
+ puts "maximum found in base: #{max}"
67
+ @url = @path + "&modified=#{max.to_i*1000}"
68
+
69
+ response = open(@url).read
70
+ json = JSON.parse(response)
71
+
72
+ json['comments'].each do |c|
73
+ comment = CackleComment.find_by_comment_id(c['id'])
74
+ if comment
75
+ if (time = Time.strptime((c['modified'][0..9]).to_s, "%s")) > comment.updated_at
76
+ puts "updating: #{c['id']}"
77
+ comment.update_attributes(
78
+ message: c['message'],
79
+ status: c['status'],
80
+ updated_at: time)
81
+ comment.save
82
+ else
83
+ puts "comment: #{c['id']} already exist"
84
+ end
85
+ else
86
+ create_comment c
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class CackleTest < ActiveSupport::TestCase
4
+ test "truth" do
5
+ assert_kind_of Module, Cackle
6
+ end
7
+ end
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.