plagiarism 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/LICENSE.txt +20 -0
- data/README.md +78 -0
- data/lib/plagiarism.rb +72 -0
- data/lib/plagiarism/balance.rb +35 -0
- data/lib/plagiarism/request.rb +38 -0
- data/lib/plagiarism/response.rb +25 -0
- data/lib/plagiarism/search.rb +76 -0
- data/lib/plagiarism/text_search.rb +20 -0
- data/lib/plagiarism/url_search.rb +21 -0
- data/plagiarism.gemspec +23 -11
- data/spec/plagiarism/balance_spec.rb +39 -0
- data/spec/plagiarism/plagiarism_spec.rb +7 -0
- data/spec/plagiarism/text_search_spec.rb +52 -0
- data/spec/plagiarism/url_search_spec.rb +54 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/vcr_cassettes/successful_balance_request.yml +37 -0
- data/spec/vcr_cassettes/valid_text_search_with_results.yml +7948 -0
- data/spec/vcr_cassettes/valid_url_search_with_results.yml +7950 -0
- metadata +131 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ade6a7ba134174de6ea534c5af530e9c217fe64
|
4
|
+
data.tar.gz: 76be3b73bd7c18fb59faafa37165e9a123150f61
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e69458e5af8d77b6b6d06b7098c587f8941655c59d6eb568ada3919b7bd6e8e0960db6cafcedf45fdad3dea71191a8f0031e85eed072f1a22d1a4329bac4c819
|
7
|
+
data.tar.gz: d65947e99d90ac5fcc892eca6b622603404c64d9edd41a255254c3ae98c7ef2006fe33ee2804952f8e43a7427eee33b218453a1c77285065bdec02f9d9972482
|
data/.rspec
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Zach Ohlgren
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
## Plagiarism
|
2
|
+
|
3
|
+
Search for plagiarism and check the originality of your content with Copyscape.
|
4
|
+
|
5
|
+
Plagiarism is a Ruby wrapper for the Copyscape (http://copyscape.com) Premium API.
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
### Getting Started
|
10
|
+
|
11
|
+
|
12
|
+
gem install plagiarism
|
13
|
+
|
14
|
+
require 'plagiarism'
|
15
|
+
|
16
|
+
|
17
|
+
Once you have your Copyscape username and API key you'll need to configure them.
|
18
|
+
|
19
|
+
Plagiarism.username = "username"
|
20
|
+
Plagiarism.api_key = "123456"
|
21
|
+
|
22
|
+
|
23
|
+
You can enable test mode to have Copyscape search against their example page,
|
24
|
+
http://www.copyscape.com/example.html.
|
25
|
+
|
26
|
+
Plagiarism.test_mode = true
|
27
|
+
|
28
|
+
|
29
|
+
### Usage
|
30
|
+
|
31
|
+
|
32
|
+
##### Check a URL for plagiarism
|
33
|
+
|
34
|
+
search = Plagiarism.url_seach("http://example.com")
|
35
|
+
|
36
|
+
if search.results? # => true
|
37
|
+
|
38
|
+
# How many results were found?
|
39
|
+
search.count # => 324
|
40
|
+
|
41
|
+
# Wow! That's a lot of results. Let's take a look...
|
42
|
+
search.results_url # => "http://view.copyscape.com/search/hm2yx3g9kg"
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
##### Check some text for plagiarism
|
49
|
+
|
50
|
+
# Some text to search against (15 words minimum)
|
51
|
+
excerpt = "When in the course of human events, it becomes necessary
|
52
|
+
for one people to dissolve the political bands"
|
53
|
+
|
54
|
+
search = Plagiarism.text_seach(excerpt)
|
55
|
+
|
56
|
+
if search.results? # => true
|
57
|
+
|
58
|
+
# How many results were found?
|
59
|
+
search.count # => 324
|
60
|
+
|
61
|
+
# Wow! That's a lot of results. Let's take a look...
|
62
|
+
search.results_url # => "http://view.copyscape.com/search/hm2yx3g9kg"
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
##### Check your account balance (in cents)
|
69
|
+
|
70
|
+
Plagiarism.balance # => 9900
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
##### Check your remaining search credits
|
75
|
+
|
76
|
+
Plagiarism.credits # => 1980
|
77
|
+
|
78
|
+
|
data/lib/plagiarism.rb
CHANGED
@@ -1,3 +1,75 @@
|
|
1
|
+
require 'plagiarism/request'
|
2
|
+
require 'plagiarism/response'
|
3
|
+
require 'plagiarism/balance'
|
4
|
+
require 'plagiarism/search'
|
5
|
+
require 'plagiarism/url_search'
|
6
|
+
require 'plagiarism/text_search'
|
7
|
+
|
1
8
|
module Plagiarism
|
2
9
|
|
10
|
+
@test_mode = false
|
11
|
+
@response_format = :xml
|
12
|
+
|
13
|
+
|
14
|
+
class << self
|
15
|
+
|
16
|
+
attr_reader :response_format
|
17
|
+
attr_accessor :username, :api_key, :test_mode
|
18
|
+
|
19
|
+
def configure
|
20
|
+
yield self
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Return the current balance (in cents) in your Copyscape account
|
26
|
+
#
|
27
|
+
def balance
|
28
|
+
Balance.amount
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
# Return the number remaining credits in your Copyscape account
|
33
|
+
#
|
34
|
+
def credits
|
35
|
+
Balance.credits
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# Search for copies of some text
|
40
|
+
#
|
41
|
+
# Options:
|
42
|
+
#
|
43
|
+
# encoding:
|
44
|
+
# UTF-8, ISO-8859-1, etc. (default is UTF-8)
|
45
|
+
#
|
46
|
+
# scope:
|
47
|
+
# public, private, full (default is public)
|
48
|
+
#
|
49
|
+
# full_comparisons:
|
50
|
+
# number of full-text comparisons to request on matching
|
51
|
+
# results (default is 0, maximum is 10).
|
52
|
+
#
|
53
|
+
def text_search(text, options = {})
|
54
|
+
TextSearch.new(text, options)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Search for copies of a web page
|
59
|
+
#
|
60
|
+
# Options:
|
61
|
+
#
|
62
|
+
# scope:
|
63
|
+
# public, private, full (default is public)
|
64
|
+
#
|
65
|
+
# full_comparisons:
|
66
|
+
# number of full-text comparisons to request on matching
|
67
|
+
# results (default is 0, maximum is 10).
|
68
|
+
#
|
69
|
+
def url_search(url, options = {})
|
70
|
+
URLSearch.new(url, options)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
3
75
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'money'
|
2
|
+
|
3
|
+
module Plagiarism
|
4
|
+
class Balance < Request
|
5
|
+
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# Return the amount (in cents) of your remaining Copyscape account balance
|
10
|
+
#
|
11
|
+
def amount
|
12
|
+
response = Request.new(:get, o: 'balance').response
|
13
|
+
if response.success?
|
14
|
+
Money.parse(response.doc.css('value').text).cents
|
15
|
+
else
|
16
|
+
raise "An error occurred while attempting to retrieve your account balance"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
# Return search credits remaining for your Copyscape account
|
22
|
+
#
|
23
|
+
def credits
|
24
|
+
response = Request.new(:get, o: 'balance').response
|
25
|
+
if response.success?
|
26
|
+
response.doc.css('total').text.to_i
|
27
|
+
else
|
28
|
+
raise "An error occurred while attempting to retrieve your account balance"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Plagiarism
|
4
|
+
class Request
|
5
|
+
include HTTParty
|
6
|
+
|
7
|
+
base_uri "http://www.copyscape.com/api"
|
8
|
+
|
9
|
+
attr_accessor :response, :params
|
10
|
+
|
11
|
+
def initialize(method, options = {})
|
12
|
+
@params = build_params(options)
|
13
|
+
if method.eql? :get
|
14
|
+
@response = Response.new self.class.get('/', query: @params)
|
15
|
+
elsif method.eql? :post
|
16
|
+
@response = Response.new self.class.post('/', body: @params)
|
17
|
+
else
|
18
|
+
raise "Invalid HTTP request method"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
# Build the request parameters
|
25
|
+
def build_params(options = {})
|
26
|
+
raise "You must provide your Copyscape username" unless Plagiarism.username
|
27
|
+
raise "You must provide your Copyscape API key" unless Plagiarism.api_key
|
28
|
+
params = {
|
29
|
+
u: Plagiarism.username, # Copyscape username
|
30
|
+
k: Plagiarism.api_key, # Copyscape API key
|
31
|
+
f: Plagiarism.response_format, # Response format
|
32
|
+
}.merge(options)
|
33
|
+
params.merge!(x: 1) if Plagiarism.test_mode
|
34
|
+
params
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Plagiarism
|
4
|
+
class Response
|
5
|
+
|
6
|
+
attr_accessor :response, :doc
|
7
|
+
|
8
|
+
|
9
|
+
def initialize(response)
|
10
|
+
@response = response
|
11
|
+
@doc = Nokogiri::XML(response.body) if @response.ok?
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def success?
|
16
|
+
@response.ok? && @doc.css("error").text == ""
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def error?
|
21
|
+
not success?
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Plagiarism
|
2
|
+
class Search
|
3
|
+
|
4
|
+
attr_accessor :request, :response
|
5
|
+
|
6
|
+
|
7
|
+
# Return the number of results found
|
8
|
+
#
|
9
|
+
def count
|
10
|
+
@response.success? ? @response.doc.css("count").text.to_i : nil
|
11
|
+
end
|
12
|
+
|
13
|
+
# Return true if any results were found
|
14
|
+
#
|
15
|
+
def results?
|
16
|
+
count && count > 0 ? true : false
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return true if an error occurred
|
20
|
+
#
|
21
|
+
def error?
|
22
|
+
@response && @response.error? ? true : false
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# Return true if the search request was successful
|
27
|
+
def success?
|
28
|
+
@response && @response.success? ? true : false
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
# Return the number of words checked
|
33
|
+
#
|
34
|
+
def words
|
35
|
+
@response.success? ? @response.doc.css("querywords").text.to_i : nil
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# Return the URL for viewing results
|
40
|
+
#
|
41
|
+
def results_url
|
42
|
+
if @response.success? && viewing_url = @response.doc.css("allviewurl").text
|
43
|
+
viewing_url != "" ? viewing_url : nil
|
44
|
+
else
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
|
53
|
+
def search_params(options)
|
54
|
+
params = {
|
55
|
+
o: operation_for_scope(options[:scope]),
|
56
|
+
c: options[:full_comparisons] || 0
|
57
|
+
}
|
58
|
+
params.merge(e: options[:encoding]) if self.class == TextSearch
|
59
|
+
params
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# Map search scope to an api operation
|
64
|
+
#
|
65
|
+
def operation_for_scope(scope)
|
66
|
+
if scope == "full"
|
67
|
+
"cpsearch"
|
68
|
+
elsif scope == "private"
|
69
|
+
"psearch"
|
70
|
+
else
|
71
|
+
"csearch"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Plagiarism
|
2
|
+
class TextSearch < Search
|
3
|
+
|
4
|
+
def initialize(search_text, options = {})
|
5
|
+
validate_text(search_text)
|
6
|
+
params = {e: "UTF-8", t: search_text}.merge(search_params(options))
|
7
|
+
@request = Request.new(:post, params)
|
8
|
+
@response = @request.response
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
|
15
|
+
def validate_text(text)
|
16
|
+
raise "Invalid search text" if text.class != String || text.nil? || text == ""
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Plagiarism
|
2
|
+
class URLSearch < Search
|
3
|
+
|
4
|
+
def initialize(search_url, options = {})
|
5
|
+
validate_url(search_url)
|
6
|
+
params = search_params(options).merge(q: search_url)
|
7
|
+
@request = Request.new(:get, params)
|
8
|
+
@response = @request.response
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
|
15
|
+
def validate_url(url)
|
16
|
+
uri = URI.parse URI.encode(url)
|
17
|
+
raise "Please provide a valid search URL" unless uri.scheme && uri.host && uri.path
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/plagiarism.gemspec
CHANGED
@@ -1,12 +1,24 @@
|
|
1
|
-
Gem::Specification.new do |
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = 'plagiarism'
|
3
|
+
gem.version = '0.1.0'
|
4
|
+
gem.summary = "A Ruby wrapper for the Copyscape Premium API"
|
5
|
+
gem.description = "Search for plagiarism and check your content for originality with Copyscape"
|
6
|
+
gem.homepage = "https://github.com/zohlgren/plagiarism"
|
7
|
+
gem.authors = ["Zach Ohlgren"]
|
8
|
+
gem.email = "zach@ohlgren.me"
|
9
|
+
gem.license = 'MIT'
|
10
|
+
|
11
|
+
gem.add_dependency 'httparty'
|
12
|
+
gem.add_dependency 'nokogiri'
|
13
|
+
gem.add_dependency 'money'
|
14
|
+
gem.add_development_dependency 'rspec-core'
|
15
|
+
gem.add_development_dependency 'vcr'
|
16
|
+
gem.add_development_dependency 'excon', '>= 0.22.0'
|
17
|
+
gem.add_development_dependency 'webmock', '< 1.12.0'
|
18
|
+
|
19
|
+
|
20
|
+
gem.files = `git ls-files`.split("\n")
|
21
|
+
gem.test_files = gem.files.grep(/^spec/)
|
22
|
+
gem.require_path = "lib"
|
23
|
+
|
12
24
|
end
|