jekyll-mail-comments 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4ebed81f1e8338d62ed7b4260a85053cebba168a7ad734785ba90ba4e2358a4f
4
+ data.tar.gz: 8a06546dd5307ca7c0142fd9dcca55542510c419edd62d93fb8898a12fb9b65e
5
+ SHA512:
6
+ metadata.gz: b1261991ca3b7f61b1b9f2f81a7ad5517f7ba50d2cb4801cc57c4b9a40412e569e15e80c3d803df7952750ed498652b4ba3c3051b78eb335dbf24356f6b08c12
7
+ data.tar.gz: 5291b56543dc5b8fb8fe97275a942c40500327380d3d877bb6d2fff112845097b9694c19687d8ceed8631c07e8795b685475bcd7a50ee48c5be6144dc39d86ec
data/.env.dist ADDED
@@ -0,0 +1,5 @@
1
+ export MC_LOGIN="username@mailhost.com"
2
+ export MC_PASSWORD=p4ss0rd
3
+ export MC_HOST="imap.mailhost.com"
4
+ export MC_PORT=993
5
+ export MC_SUBJECT_SUFFIX="Jekyll"
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle
2
+ /.rbenv-vars
3
+ /.ruby-version
4
+ /.rvmrc
5
+ /corpus
6
+ /coverage
7
+ /Gemfile.lock
8
+ /gems
9
+ /mail-*.gem
10
+ /rdoc
11
+ *~
12
+ .env
13
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ source "https://rubygems.org"
3
+ gemspec
4
+ gem 'mail'
5
+ gem 'jekyll'
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # Jekyll Mail comments
2
+
3
+ This gem fetches email from your mailbox by filtering with specific suffix, it makes data files which you can use to generate Jekyll comments.
4
+
5
+ ## How it works ?
6
+
7
+ * You've to setup mailbox, on Jekyll pages you will have mailto link which opens native system mail client with pre filled subject.
8
+ * Person who wants to comment message write message to your specific email address.
9
+ * Fetch program watch for special subject suffix to distinct comments from other emails
10
+ * Fetch program generate json based data files which perfectly fits to Jekyll data system https://jekyllrb.com/docs/datafiles/
11
+
12
+
13
+ ## What is the purpose ?
14
+
15
+ * Jekyll static site generator has no comments system
16
+ * Don't want to inject 3rdparty javascript code to work with SaSS comments system
17
+ * Any RDBS for static site generator is overhead
18
+
19
+
20
+ ## How-to Setup
21
+
22
+ * Go to your jekyll site `cd ~/jekull_site`
23
+ * Install gem `gem install mail_comments`
24
+ * Setup credentials
25
+
26
+ There few credentials your have to setup before run:
27
+
28
+ ** MC_LOGIN - Login to imap server
29
+ ** MC_PASSWORD - Password for imap server
30
+ ** MC_HOST - IMAP server hostname
31
+ ** MC_PORT - IMAP server port
32
+ ** MC_SUBJECT_SUFFIX - Suffix to filter comments
33
+
34
+ * You have put this as environment variables `see .env.dist`
35
+ * `jekyll-mail-comments-fetch`
36
+ * After that you will get comments data files inside Jekyll data directory - **_data**
37
+
38
+ After that if new comments are present it will generate data files with comments which you can process with Jekyll with data tag.
39
+ See here. https://jekyllrb.com/docs/datafiles/ or below.
40
+
41
+ Here is how to you can include comments block into your Jekyll post template
42
+
43
+ ```
44
+
45
+ <section>
46
+ {% include comments-count.html replies_to=page.path %}
47
+
48
+ {% if comment_count %}
49
+ <h2>Comments ({{- comment_count -}}) <small class="text-muted">Read carefuly </small> </h2>
50
+ {% include comments.html replies_to=page.path indent_class="ml-auto" title=page.title %}
51
+ {% else %}
52
+ <h2>No comments here yet <small class="text-muted">Write here gently</small></h2>
53
+ {% endif %}
54
+ <div class="mt-3"><a class="btn btn-outline-secondary btn-block" href="mailto:{{site.comments.email}}?subject=RE:{{page.path}}:{{site.comments.subject_suffix}}:{{post.title}}">Write a comment</a> </div>
55
+ </section>
56
+ ```
57
+ Templates can be found inside **templates** directory of this gem.
58
+
59
+
60
+ ## Credits
61
+
62
+ Inspiration while searching for already existing gem for email comments
63
+
64
+ * https://stevescott.ca/2017-04-03-static-site-comments-via-email.html
65
+ * https://github.com/aioobe/dead-simple-jekyll-comments/
66
+
67
+
68
+ ## Example
69
+
70
+ * https://blog.falsetrue.io
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'jekyll-mail-comments'
4
+ Jekyll::MailComments.fetch
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'jekyll-mail-comments'
3
+ s.version = '0.0.2'
4
+ s.date = '2022-01-01'
5
+ s.summary = "Email based comment system for Jekyll static site generator"
6
+ s.description = <<DESC
7
+ Provides html generator of threaded comments pages fetched from an IMAP for Jekyll
8
+ DESC
9
+ s.authors = "Dmitry Rodichev"
10
+ s.email = 'noroot@falsetrue.io'
11
+ s.files = `git ls-files`.split($/)
12
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
14
+
15
+ s.add_dependency 'jekyll'
16
+ s.homepage = 'https://github.com/noroot/jekyll-mail-comments'
17
+ s.license = 'GPL-3.0'
18
+ s.post_install_message = <<MSG
19
+ Don't forget to put credentials inside .env file, see .env.dist inside gem source.
20
+ MSG
21
+ end
@@ -0,0 +1,103 @@
1
+ require 'net/imap'
2
+ require 'mail'
3
+ require 'fileutils'
4
+ require "base64"
5
+ require 'yaml'
6
+ require 'digest'
7
+ require 'jekyll'
8
+
9
+ module Jekyll
10
+
11
+ module MailComments
12
+
13
+ class Configuration
14
+ attr_accessor :login
15
+ attr_accessor :password
16
+ attr_accessor :host
17
+ attr_accessor :port
18
+ attr_accessor :subject_suffix
19
+
20
+ def initialize
21
+ @login = ENV.fetch('MC_LOGIN', '')
22
+ @password = ENV.fetch('MC_PASSWORD', '')
23
+ @host = ENV.fetch('MC_HOST', '')
24
+ @port = ENV.fetch('MC_PORT', '')
25
+ @subject_suffix = ENV.fetch('MC_SUBJECT_SUFFIX', '')
26
+ end
27
+ end
28
+
29
+
30
+ class << self
31
+ attr_writer :configuration
32
+ end
33
+
34
+ def self.configuration
35
+ @configuration ||= Configuration.new
36
+ end
37
+
38
+ def self.configure
39
+ yield(configuration)
40
+ end
41
+
42
+ def self.fetch
43
+
44
+ login = MailComments.configuration.login
45
+ password = MailComments.configuration.password
46
+ host = MailComments.configuration.host
47
+ port = MailComments.configuration.port
48
+ subject_suffix = MailComments.configuration.subject_suffix
49
+
50
+ imap = Net::IMAP.new(host, 993, true)
51
+ imap.login(login, password)
52
+ imap.select("INBOX")
53
+ cx = imap.search(["SUBJECT", subject_suffix, "UNSEEN"])
54
+ if !cx.nil? && cx.length > 0
55
+ puts "Comments found CX=#{cx.length}"
56
+ comments = {}
57
+ cx.each do |message_id|
58
+ msg = imap.fetch(message_id,'RFC822')[0].attr['RFC822']
59
+ mail = Mail.read_from_string(msg)
60
+ if mail.multipart?
61
+ body = mail.multipart?? mail.text_part.body.decoded : mail.html_part.body.decoded
62
+ else
63
+ body = mail.body.decoded
64
+ end
65
+
66
+ author = mail.header['From'].field.addrs.first.display_name
67
+
68
+ begin
69
+ tmp = mail.subject.split(":")
70
+ if tmp.length == 4
71
+ reply_id = mail.subject.split(":")[1].strip()
72
+ post_title = mail.subject.split(":")[3].strip()
73
+
74
+ message_id = Digest::SHA1.hexdigest(mail['Message-ID'].value)
75
+ comment = {
76
+ title: post_title,
77
+ reply_to: reply_id,
78
+ id: message_id,
79
+ author: author,
80
+ from: mail.from.first,
81
+ date: mail.date,
82
+ text: body
83
+ }
84
+ file_name = "#{mail.date.strftime("%s").to_s}-#{message_id}.yaml"
85
+ File.open("_data/comments/#{file_name}", "w") do |f|
86
+ f.write(comment.transform_keys(&:to_s).to_yaml)
87
+ end
88
+ puts "Comment from #{comment[:author]} - <#{comment[:from]}> on \"#{comment[:title]}\" at #{comment[:date]}"
89
+ else
90
+ puts "Wrong subject for #{msg}"
91
+ end
92
+
93
+ rescue => e
94
+ puts e
95
+ end
96
+ end
97
+ else
98
+ puts "No messages found."
99
+ end
100
+
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,100 @@
1
+ require 'net/imap'
2
+ require 'mail'
3
+ require 'fileutils'
4
+ require "base64"
5
+ require 'yaml'
6
+ require 'digest'
7
+
8
+
9
+ module MailComments
10
+
11
+ class Configuration
12
+ attr_accessor :login
13
+ attr_accessor :password
14
+ attr_accessor :host
15
+ attr_accessor :port
16
+ attr_accessor :subject_suffix
17
+
18
+ def initialize
19
+ @login = ENV.fetch('MC_LOGIN', '')
20
+ @password = ENV.fetch('MC_PASSWORD', '')
21
+ @host = ENV.fetch('MC_HOST', '')
22
+ @port = ENV.fetch('MC_PORT', '')
23
+ @subject_suffix = ENV.fetch('MC_SUBJECT_SUFFIX', '')
24
+ end
25
+ end
26
+
27
+
28
+ class << self
29
+ attr_writer :configuration
30
+ end
31
+
32
+ def self.configuration
33
+ @configuration ||= Configuration.new
34
+ end
35
+
36
+ def self.configure
37
+ yield(configuration)
38
+ end
39
+
40
+ def self.fetch
41
+
42
+ login = MailComments.configuration.login
43
+ password = MailComments.configuration.password
44
+ host = MailComments.configuration.host
45
+ port = MailComments.configuration.port
46
+ subject_suffix = MailComments.configuration.subject_suffix
47
+
48
+ imap = Net::IMAP.new(host, 993, true)
49
+ imap.login(login, password)
50
+ imap.select("INBOX")
51
+ cx = imap.search(["SUBJECT", subject_suffix, "UNSEEN"])
52
+ if !cx.nil? && cx.length > 0
53
+ puts "Comments found CX=#{cx.length}"
54
+ comments = {}
55
+ cx.each do |message_id|
56
+ msg = imap.fetch(message_id,'RFC822')[0].attr['RFC822']
57
+ mail = Mail.read_from_string(msg)
58
+ if mail.multipart?
59
+ body = mail.multipart?? mail.text_part.body.decoded : mail.html_part.body.decoded
60
+ else
61
+ body = mail.body.decoded
62
+ end
63
+
64
+ author = mail.header['From'].field.addrs.first.display_name
65
+
66
+ begin
67
+ tmp = mail.subject.split(":")
68
+ if tmp.length == 4
69
+ reply_id = mail.subject.split(":")[1].strip()
70
+ post_title = mail.subject.split(":")[3].strip()
71
+
72
+ message_id = Digest::SHA1.hexdigest(mail['Message-ID'].value)
73
+ comment = {
74
+ title: post_title,
75
+ reply_to: reply_id,
76
+ id: message_id,
77
+ author: author,
78
+ from: mail.from.first,
79
+ date: mail.date,
80
+ text: body
81
+ }
82
+ file_name = "#{mail.date.strftime("%s").to_s}-#{message_id}.yaml"
83
+ File.open("_data/comments/#{file_name}", "w") do |f|
84
+ f.write(comment.transform_keys(&:to_s).to_yaml)
85
+ end
86
+ puts "Comment from #{comment[:author]} - <#{comment[:from]}> on \"#{comment[:title]}\" at #{comment[:date]}"
87
+ else
88
+ puts "Wrong subject for #{msg}"
89
+ end
90
+
91
+ rescue => e
92
+ puts e
93
+ end
94
+ end
95
+ else
96
+ puts "No messages found."
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,7 @@
1
+ {%- for entry in site.data.comments -%}
2
+ {%- if entry[1].reply_to == include.replies_to -%}
3
+ {%- assign comment_count = comment_count | plus: 1 -%}
4
+ {%- assign com_id = entry[0] -%}
5
+ {%- include comments-count.html replies_to=com_id -%}
6
+ {%- endif -%}
7
+ {%- endfor -%}
@@ -0,0 +1,30 @@
1
+ {% assign sorted = site.data.comments | sort %}
2
+ {%- for entry in sorted -%}
3
+
4
+ {%- assign cid = entry[0] -%}
5
+ {%- assign com = entry[1] -%}
6
+ {%- assign indent_class = include.indent_class %}
7
+ {%- assign title = include.title %}
8
+ {%- if com.reply_to != include.replies_to -%}
9
+ {%- continue -%}
10
+ {%- endif -%}
11
+
12
+ <div class="{{ indent_class }} comment" id="{{ cid }}">
13
+ <div class="d-flex">
14
+ <div><a href="" class="comment-author">{{ com.author | escape | strip_newlines }}</a> - <span class="comment-date"> {{ com.date | date_to_rfc822 }}</span></div>
15
+ <!-- <div class="ml-auto">at {{ com.date | date_to_rfc822 }}</div> -->
16
+ </div>
17
+ <div>
18
+ {{ com.text | escape | newline_to_br | strip_newlines | markdownify | replace: "&amp;#39;", "'" | replace: "&amp;quot;", '"' }}
19
+
20
+ <!-- <div class="comment-controls">
21
+ <a href="#{{cid}}">Permalink</a> | <a href="mailto:{{site.comments.email}}?subject=RE:{{cid}}:{{site.comments.subject_suffix}}:{{ page.path}}">Reply</a>
22
+ </div> -->
23
+ </div>
24
+ <div class="d-flex">
25
+ <div class="ml-auto"><a href="#{{cid}}">Permalink</a> | <a href="mailto:{{site.comments.email}}?subject=RE:{{cid}}:{{site.comments.subject_suffix}}:{{title}}">Reply</a> </div>
26
+ </div>
27
+ {%- include comments.html replies_to=cid indent_class="ml-3 comment-indent" title=title -%}
28
+ </div>
29
+
30
+ {%- endfor -%}
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-mail-comments
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Dmitry Rodichev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-01-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: 'Provides html generator of threaded comments pages fetched from an IMAP
28
+ for Jekyll
29
+
30
+ '
31
+ email: noroot@falsetrue.io
32
+ executables:
33
+ - jekyll-mail-comments-fetch
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - ".env.dist"
38
+ - ".gitignore"
39
+ - Gemfile
40
+ - README.md
41
+ - bin/jekyll-mail-comments-fetch
42
+ - jekyll-mail-comments.gemspec
43
+ - lib/jekyll-mail-comments.rb
44
+ - lib/jekyll_mail_comments.rb
45
+ - templates/comments-count.html
46
+ - templates/comments.html
47
+ homepage: https://github.com/noroot/jekyll-mail-comments
48
+ licenses:
49
+ - GPL-3.0
50
+ metadata: {}
51
+ post_install_message: 'Don''t forget to put credentials inside .env file, see .env.dist
52
+ inside gem source.
53
+
54
+ '
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubygems_version: 3.0.6
70
+ signing_key:
71
+ specification_version: 4
72
+ summary: Email based comment system for Jekyll static site generator
73
+ test_files: []