├── master
├── docs
├── img
│ ├── gui.PNG
│ ├── gui2.PNG
│ ├── gui3.PNG
│ ├── gui4.PNG
│ ├── gui5.PNG
│ ├── submit.PNG
│ ├── accounts.PNG
│ ├── accounts2.PNG
│ ├── accounts3.PNG
│ ├── articles.PNG
│ ├── articles2.PNG
│ ├── articles3.PNG
│ ├── articles4.PNG
│ ├── articles5.PNG
│ ├── articles6.PNG
│ ├── articles7.PNG
│ ├── indexers1.PNG
│ ├── indexers2.PNG
│ ├── indexers3.PNG
│ ├── install.PNG
│ ├── install2.PNG
│ ├── install3.PNG
│ ├── install4.PNG
│ ├── install5.PNG
│ ├── install6.PNG
│ ├── submit2.PNG
│ ├── submit3.PNG
│ ├── submit4.PNG
│ ├── submit5.PNG
│ ├── submit6.PNG
│ └── home-image.png
├── current-services.md
├── gui.md
├── readme.md
├── accounts.md
├── indexers.md
├── submit.md
├── install-cli.md
└── articles.md
├── settings
└── services.txt
├── .gitignore
├── license.md
├── indexers
├── backlinksindexer.coffee
├── backlinksindexer.js
├── indexification.coffee
└── indexification.js
├── app
├── console-xtra.coffee
├── console-xtra.js
├── imports.coffee
├── spinner.coffee
├── spinner.js
└── imports.js
├── services
├── blogdotcom.coffee
├── blogdotcom.js
├── wordpress.coffee
└── wordpress.js
├── README.md
├── open-submitter.coffee
└── open-submitter.js
/master:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/img/gui.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/gui.PNG
--------------------------------------------------------------------------------
/docs/img/gui2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/gui2.PNG
--------------------------------------------------------------------------------
/docs/img/gui3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/gui3.PNG
--------------------------------------------------------------------------------
/docs/img/gui4.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/gui4.PNG
--------------------------------------------------------------------------------
/docs/img/gui5.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/gui5.PNG
--------------------------------------------------------------------------------
/docs/img/submit.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/submit.PNG
--------------------------------------------------------------------------------
/docs/img/accounts.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/accounts.PNG
--------------------------------------------------------------------------------
/docs/img/accounts2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/accounts2.PNG
--------------------------------------------------------------------------------
/docs/img/accounts3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/accounts3.PNG
--------------------------------------------------------------------------------
/docs/img/articles.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/articles.PNG
--------------------------------------------------------------------------------
/docs/img/articles2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/articles2.PNG
--------------------------------------------------------------------------------
/docs/img/articles3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/articles3.PNG
--------------------------------------------------------------------------------
/docs/img/articles4.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/articles4.PNG
--------------------------------------------------------------------------------
/docs/img/articles5.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/articles5.PNG
--------------------------------------------------------------------------------
/docs/img/articles6.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/articles6.PNG
--------------------------------------------------------------------------------
/docs/img/articles7.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/articles7.PNG
--------------------------------------------------------------------------------
/docs/img/indexers1.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/indexers1.PNG
--------------------------------------------------------------------------------
/docs/img/indexers2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/indexers2.PNG
--------------------------------------------------------------------------------
/docs/img/indexers3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/indexers3.PNG
--------------------------------------------------------------------------------
/docs/img/install.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/install.PNG
--------------------------------------------------------------------------------
/docs/img/install2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/install2.PNG
--------------------------------------------------------------------------------
/docs/img/install3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/install3.PNG
--------------------------------------------------------------------------------
/docs/img/install4.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/install4.PNG
--------------------------------------------------------------------------------
/docs/img/install5.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/install5.PNG
--------------------------------------------------------------------------------
/docs/img/install6.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/install6.PNG
--------------------------------------------------------------------------------
/docs/img/submit2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/submit2.PNG
--------------------------------------------------------------------------------
/docs/img/submit3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/submit3.PNG
--------------------------------------------------------------------------------
/docs/img/submit4.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/submit4.PNG
--------------------------------------------------------------------------------
/docs/img/submit5.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/submit5.PNG
--------------------------------------------------------------------------------
/docs/img/submit6.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/submit6.PNG
--------------------------------------------------------------------------------
/docs/img/home-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BackSpaceTech/open-submitter/HEAD/docs/img/home-image.png
--------------------------------------------------------------------------------
/settings/services.txt:
--------------------------------------------------------------------------------
1 | #name#
2 | wordpress
3 | #status#
4 | ok
5 | #name#
6 | blogdotcom
7 | #status#
8 | bad
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.csv
2 | node_modules/*
3 | accounts/*
4 | articles/*
5 | backlinks/*
6 | settings/indexers.txt
7 | capture/*
8 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | Open Submitter is free and open source software licensed under the [GNU GPL v3][970c67c8]
2 |
3 | [970c67c8]: https://www.gnu.org/licenses/gpl-3.0.en.html "Open Submitter GNU GPL License"
4 |
--------------------------------------------------------------------------------
/docs/current-services.md:
--------------------------------------------------------------------------------
1 | # Current Open Submitter Services List
2 |
3 |
4 |
5 | This list is updated when new services are created. Make sure you have Sibbel set up to notify of updates (see [set up page](install-cli.md) for more details).
6 |
7 |
8 | | Service ID | Service | Service Homepage | Reliability | Script Last Updated |
9 | |------------ |----------- |------------------ |------------- |--------------------- |
10 | | wordpress | WordPress | wordpress.com | Excellent | 19 July 2016 |
11 | | blog.com | Blog.com | blog.com | Poor | 19 July 2016 |
12 |
13 |
14 |
15 |
16 |
17 | [Documentation Home][c689026d]
18 |
19 | [c689026d]: readme.md "Open Submitter Documentation"
20 |
--------------------------------------------------------------------------------
/indexers/backlinksindexer.coffee:
--------------------------------------------------------------------------------
1 | exports.name = 'backlinksindexer.com'
2 | exports.steps = [
3 | {
4 | command: 'open'
5 | url: 'http://backlinksindexer.com/wp-login.php'
6 | confirm: '#user_login'
7 | }
8 | {
9 | command: 'login-indexer'
10 | form: '#loginform'
11 | username: '#user_login'
12 | password: '#user_pass'
13 | submit: false
14 | }
15 | {
16 | command: 'click'
17 | selector: '#wp-submit'
18 | confirmtxt: 'Log out'
19 | }
20 | {
21 | command: 'open'
22 | url: 'http://backlinksindexer.com/dashboard/'
23 | confirm: '#url-textarea'
24 | }
25 | {
26 | command: 'backlinks'
27 | selector: '#url-textarea'
28 | }
29 | {
30 | command: 'click'
31 | selector: '#submit_add'
32 | confirm: '.alert-success'
33 | }
34 | ]
35 |
--------------------------------------------------------------------------------
/app/console-xtra.coffee:
--------------------------------------------------------------------------------
1 | exports.log = (msgColor, msg) ->
2 | colorsANSI = [
3 | {
4 | text: 'black'
5 | code: '\x1b[30m'
6 | }
7 | {
8 | text: 'red'
9 | code: '\x1b[31m'
10 | }
11 | {
12 | text: 'green'
13 | code: '\x1b[32m'
14 | }
15 | {
16 | text: 'yellow'
17 | code: '\x1b[33m'
18 | }
19 | {
20 | text: 'blue'
21 | code: '\x1b[34m'
22 | }
23 | {
24 | text: 'magenta'
25 | code: '\x1b[35m'
26 | }
27 | {
28 | text: 'cyan'
29 | code: '\x1b[36m'
30 | }
31 | {
32 | text: 'white'
33 | code: '\x1b[37m'
34 | }
35 | ]
36 | colorCode = ''
37 | for i in [0...colorsANSI.length]
38 | if msgColor == colorsANSI[i].text
39 | colorCode = colorsANSI[i].code
40 | console.log colorCode, msg, '\x1b[0m'
41 |
--------------------------------------------------------------------------------
/indexers/backlinksindexer.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.3.3
2 | (function() {
3 |
4 | exports.name = 'backlinksindexer.com';
5 |
6 | exports.steps = [
7 | {
8 | command: 'open',
9 | url: 'http://backlinksindexer.com/wp-login.php',
10 | confirm: '#user_login'
11 | }, {
12 | command: 'login-indexer',
13 | form: '#loginform',
14 | username: '#user_login',
15 | password: '#user_pass',
16 | submit: false
17 | }, {
18 | command: 'click',
19 | selector: '#wp-submit',
20 | confirmtxt: 'Log out'
21 | }, {
22 | command: 'open',
23 | url: 'http://backlinksindexer.com/dashboard/',
24 | confirm: '#url-textarea'
25 | }, {
26 | command: 'backlinks',
27 | selector: '#url-textarea'
28 | }, {
29 | command: 'click',
30 | selector: '#submit_add',
31 | confirm: '.alert-success'
32 | }
33 | ];
34 |
35 | }).call(this);
36 |
--------------------------------------------------------------------------------
/indexers/indexification.coffee:
--------------------------------------------------------------------------------
1 | exports.name = 'indexification.com'
2 | exports.steps = [
3 | {
4 | command: 'open'
5 | url: 'http://www.indexification.com/'
6 | confirm: '#button-login'
7 | }
8 | {
9 | command: 'click'
10 | selector: '#button-login'
11 | confirm: '#dialog-login'
12 | }
13 | {
14 | command: 'login-indexer'
15 | form: '#LoginForm'
16 | username: '#loginuser'
17 | password: '#loginpass'
18 | submit: false
19 | }
20 | {
21 | command: 'click'
22 | xpath: '(//button[@type="button"])[4]'
23 | }
24 | {
25 | command: 'wait'
26 | value: 5000
27 | }
28 | {
29 | command: 'open'
30 | url: 'http://www.indexification.com/members/addcampaign.php'
31 | confirm: '#links'
32 | }
33 | {
34 | command: 'backlinks'
35 | selector: '#links'
36 | }
37 | {
38 | command: 'click'
39 | selector: '#user-updateprofile'
40 | confirmtxt: 'Success!'
41 | }
42 | ]
43 |
--------------------------------------------------------------------------------
/docs/gui.md:
--------------------------------------------------------------------------------
1 | # Open Submitter Graphical User Interface (GUI)
2 |
3 | The Graphical User Interface (GUI) simplifies the creation of article submission files and indexer setup files.
4 |
5 | 
6 |
7 | It can be download and installed from the [Chrome app store][db40ed37].
8 |
9 | ## Create shortcut for app
10 |
11 | Navigate to your desktop in file explorer. Right click and select create shortcut.
12 | 
13 |
14 | Paste the URL for the app:
15 | https://chrome.google.com/webstore/detail/open-submitter/pdhmmmkbclicklmfjpjbklkmoacdlolg
16 |
17 |
18 |
19 | 
20 |
21 | Click Next
22 |
23 | Give the link the name Open Submitter
24 |
25 | 
26 |
27 | Click Finish
28 |
29 | Check your desktop to find the link to the app.
30 |
31 |
32 | 
33 |
34 |
35 |
36 | [Documentation Home][47774e43]
37 |
38 | [db40ed37]: https://chrome.google.com/webstore/detail/open-submitter/pdhmmmkbclicklmfjpjbklkmoacdlolg "Open Submitter App"
39 | [47774e43]: readme.md "Open Submitter Documentation"
40 |
--------------------------------------------------------------------------------
/indexers/indexification.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.3.3
2 | (function() {
3 |
4 | exports.name = 'indexification.com';
5 |
6 | exports.steps = [
7 | {
8 | command: 'open',
9 | url: 'http://www.indexification.com/',
10 | confirm: '#button-login'
11 | }, {
12 | command: 'click',
13 | selector: '#button-login',
14 | confirm: '#dialog-login'
15 | }, {
16 | command: 'login-indexer',
17 | form: '#LoginForm',
18 | username: '#loginuser',
19 | password: '#loginpass',
20 | submit: false
21 | }, {
22 | command: 'click',
23 | xpath: '(//button[@type="button"])[4]'
24 | }, {
25 | command: 'wait',
26 | value: 5000
27 | }, {
28 | command: 'open',
29 | url: 'http://www.indexification.com/members/addcampaign.php',
30 | confirm: '#links'
31 | }, {
32 | command: 'backlinks',
33 | selector: '#links'
34 | }, {
35 | command: 'click',
36 | selector: '#user-updateprofile',
37 | confirmtxt: 'Success!'
38 | }
39 | ];
40 |
41 | }).call(this);
42 |
--------------------------------------------------------------------------------
/app/console-xtra.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.3.3
2 | (function() {
3 |
4 | exports.log = function(msgColor, msg) {
5 | var colorCode, colorsANSI, i, _i, _ref;
6 | colorsANSI = [
7 | {
8 | text: 'black',
9 | code: '\x1b[30m'
10 | }, {
11 | text: 'red',
12 | code: '\x1b[31m'
13 | }, {
14 | text: 'green',
15 | code: '\x1b[32m'
16 | }, {
17 | text: 'yellow',
18 | code: '\x1b[33m'
19 | }, {
20 | text: 'blue',
21 | code: '\x1b[34m'
22 | }, {
23 | text: 'magenta',
24 | code: '\x1b[35m'
25 | }, {
26 | text: 'cyan',
27 | code: '\x1b[36m'
28 | }, {
29 | text: 'white',
30 | code: '\x1b[37m'
31 | }
32 | ];
33 | colorCode = '';
34 | for (i = _i = 0, _ref = colorsANSI.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
35 | if (msgColor === colorsANSI[i].text) {
36 | colorCode = colorsANSI[i].code;
37 | }
38 | }
39 | return console.log(colorCode, msg, '\x1b[0m');
40 | };
41 |
42 | }).call(this);
43 |
--------------------------------------------------------------------------------
/docs/readme.md:
--------------------------------------------------------------------------------
1 | # Open Submitter Documentation
2 |
3 | ## Contents:
4 | - [Set Up Open Submitter][f159407d]
5 | - [Accounts][f3cb5827]
6 | - [Graphical User Interface (GUI)][90d887fa]
7 | - [Articles][305c1ef4]
8 | - [Indexers][a2eb8215]
9 | - [Submitting to Services][0c9539fb]
10 | - Creating New Services
11 |
12 | [489d3415]: prerequisites.md "Open Submitter Prerequisites"
13 | [f159407d]: install-cli.md "Open Submitter CLI Install"
14 | [f3cb5827]: accounts.md "Open Submitter Documentation - Accounts"
15 | [90d887fa]: gui.md "Open Submitter Graphical User Interface (GUI)"
16 | [305c1ef4]: articles.md "Open Submitter Article Creation"
17 | [a2eb8215]: indexers.md "Open Submitter Indexers"
18 | [0c9539fb]: submit.md "Open Submitter Submitting to Services"
19 |
20 |
21 | ## More tutorials and information at the [Open Submitter Home Page][76d3e968]
22 |
23 | Free and open source software licensed under the [GNU GPL v3][efb18a06]. Copyright [BackSpace Technology][3ed15560].
24 |
25 | [76d3e968]: http://opensubmitter.org/ "Free and open source backlinking software app."
26 | [efb18a06]: https://www.gnu.org/licenses/gpl-3.0.en.html "Open Submitter GNU GPL License"
27 | [3ed15560]: https://backspace.academy/ "BackSpace Academy"
28 |
--------------------------------------------------------------------------------
/services/blogdotcom.coffee:
--------------------------------------------------------------------------------
1 | exports.name = 'blog.com'
2 | exports.steps = [
3 | {
4 | command: 'create'
5 | micro: false
6 | noHTML: false
7 | }
8 | {
9 | command: 'open'
10 | url: 'http://blog.com/'
11 | confirm: '#loginform'
12 | }
13 | {
14 | command: 'login'
15 | form: '#loginform'
16 | username: '#user_login'
17 | password: '#user_pass'
18 | submit: true
19 | confirm: '#site-title'
20 | }
21 | {
22 | command: 'open-site'
23 | begin: 'http://'
24 | end: '.blog.com/wp-admin/post-new.php'
25 | confirm: '#post-body'
26 | }
27 | {
28 | command: 'click'
29 | selector: '#edButtonHTML'
30 | }
31 | {
32 | command: 'title'
33 | selector: 'input#title'
34 | }
35 | {
36 | command: 'wait'
37 | value: 1000
38 | }
39 | {
40 | command: 'body'
41 | selector: 'textarea#content'
42 | }
43 | {
44 | command: 'wait'
45 | value: 1000
46 | }
47 | {
48 | command: 'click'
49 | selector: 'input#publish'
50 | confirmtxt: 'Post published. '
51 | }
52 | {
53 | command: 'wait'
54 | value: 1000
55 | }
56 | {
57 | command: 'save-href'
58 | selector: '#message p a'
59 | }
60 | {
61 | command: 'click'
62 | selector: 'a[title="Sign Out"]'
63 | confirm: '#loginform'
64 | }
65 | ]
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Open Submitter
2 | SEO Spinning and Backlinking App
3 |
4 | 
5 |
6 | ## SEO Backlinking software:
7 | - Spins articles
8 | - Inserts backlinks
9 | - Inserts images from custom list in random locations
10 | - Submits spun articles to blogs, microblogs, social pages etc.
11 | - Saves backlink URL to file
12 | - Submits backlinks to indexing services
13 | - Additional services can be added through simple command steps
14 |
15 | ## Prerequisites
16 | - [NodeJS][ca1dffb7] v4.4.7 or greater
17 | - [PhantomJS][6997c770] v2.1 or greater
18 | - [CasperJS][476ee510] v1.1.1 or greater
19 | - [Cmder][9924c39d] (optional)
20 | - [The Best Spinner][67703f2d] (optional)
21 |
22 | [ca1dffb7]: http://nodejs.org/ "NodeJS"
23 | [6997c770]: http://phantomjs.org/ "PhantomJS"
24 | [476ee510]: http://casperjs.org/ "CasperJS"
25 | [9924c39d]: http://cmder.net/ "Cmder"
26 | [67703f2d]: http://paydotcom.net/r/95330/pcoady/27453918/ "The Best Spinner"
27 |
28 |
29 | ## More details in the [documentation][bd90079e]
30 |
31 |
32 | Open Submitter is free and open source software licensed under the [GNU GPL v3][471c7b4b]. Copyright [BackSpace Technology.][520d0698]
33 |
34 | [bd90079e]: https://github.com/BackSpaceTech/open-submitter/tree/master/docs "Open Submitter Documentation"
35 | [471c7b4b]: https://www.gnu.org/licenses/gpl-3.0.en.html "Open Submitter GNU GPL License"
36 | [520d0698]: https://backspace.academy/ "BackSpace Technology"
37 |
--------------------------------------------------------------------------------
/services/blogdotcom.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.3.3
2 | (function() {
3 |
4 | exports.name = 'blog.com';
5 |
6 | exports.steps = [
7 | {
8 | command: 'create',
9 | micro: false,
10 | noHTML: false
11 | }, {
12 | command: 'open',
13 | url: 'http://blog.com/',
14 | confirm: '#loginform'
15 | }, {
16 | command: 'login',
17 | form: '#loginform',
18 | username: '#user_login',
19 | password: '#user_pass',
20 | submit: true,
21 | confirm: '#site-title'
22 | }, {
23 | command: 'open-site',
24 | begin: 'http://',
25 | end: '.blog.com/wp-admin/post-new.php',
26 | confirm: '#post-body'
27 | }, {
28 | command: 'click',
29 | selector: '#edButtonHTML'
30 | }, {
31 | command: 'title',
32 | selector: 'input#title'
33 | }, {
34 | command: 'wait',
35 | value: 1000
36 | }, {
37 | command: 'body',
38 | selector: 'textarea#content'
39 | }, {
40 | command: 'wait',
41 | value: 1000
42 | }, {
43 | command: 'click',
44 | selector: 'input#publish',
45 | confirmtxt: 'Post published. '
46 | }, {
47 | command: 'wait',
48 | value: 1000
49 | }, {
50 | command: 'save-href',
51 | selector: '#message p a'
52 | }, {
53 | command: 'click',
54 | selector: 'a[title="Sign Out"]',
55 | confirm: '#loginform'
56 | }
57 | ];
58 |
59 | }).call(this);
60 |
--------------------------------------------------------------------------------
/docs/accounts.md:
--------------------------------------------------------------------------------
1 | # Open Submitter Accounts
2 |
3 | Accounts are required for Open Submitter to login and submit your articles.
4 |
5 | ## Creating Accounts
6 |
7 | Each service (e.g. Wordpress) will have its own process for creating accounts. Normally only one account per email address can be created. Free emails can be created at mail.ru (use Google Chrome Translate to view in English). After your accounts are created you will need the login names (or email addresses if applicable), passwords and site names (if applicable). Try to create many accounts for each service.
8 |
9 | ## Creating Accounts List file
10 |
11 | Open Submitter will look for your acounts file in the accounts directory of the Open Subnmitter root directory. This does not exist so you need to create it first. Make sure the folder name is in lowercase.
12 |
13 | 
14 |
15 | Account lists need to be created in csv format. Open a spreadsheet application and create a new spreadsheet with the account details on each row in the following order:
16 | - service id (see [current available services][3f03f862])
17 | - username
18 | - password
19 | - site name (if applicable)
20 |
21 | [3f03f862]: current-services.md "Open Submitter Current Available Services"
22 |
23 | 
24 |
25 | Now save your file as csv type in the accounts folder.
26 |
27 | 
28 |
29 |
30 |
31 | [Documentation Home][03b4df1a]
32 |
33 | [03b4df1a]: readme.md "Open Submitter Documentation"
34 |
--------------------------------------------------------------------------------
/services/wordpress.coffee:
--------------------------------------------------------------------------------
1 | exports.name = 'wordpress'
2 | exports.steps = [
3 | {
4 | command: 'create'
5 | micro: false
6 | noHTML: false
7 | }
8 | {
9 | command: 'open'
10 | url: 'https://wordpress.com/wp-login.php'
11 | confirm: '#user_login'
12 | }
13 | {
14 | command: 'login'
15 | form: '#loginform'
16 | username: '#user_login'
17 | password: '#user_pass'
18 | submit: true
19 | confirm: 'a[data-tip-target="my-sites"]'
20 | }
21 | {
22 | command: 'open-site'
23 | begin: 'https://wordpress.com/post/'
24 | end: ''
25 | confirm: '#tinymce-1'
26 | }
27 | {
28 | command: 'click'
29 | selector: 'svg.gridicon.gridicons-create'
30 | }
31 | {
32 | command: 'wait'
33 | value: 1000
34 | }
35 | {
36 | command: 'title'
37 | selector: 'textarea.textarea-autosize.editor-title__input'
38 | }
39 | {
40 | command: 'click'
41 | selector: 'a[title="Edit the raw HTML code"]'
42 | }
43 | {
44 | command: 'wait'
45 | value: 1000
46 | }
47 | {
48 | command: 'body'
49 | selector: '#tinymce-1'
50 | }
51 | {
52 | command: 'click'
53 | xpath: '//*[text()[contains(.,"Publish")]]'
54 | confirm: '.is-success'
55 | }
56 | {
57 | command: 'save-href'
58 | selector: 'a.notice__action'
59 | }
60 | {
61 | command: 'click'
62 | selector: 'img[class="gravatar"]'
63 | confirm: 'button[title="Sign out of WordPress.com"]'
64 | }
65 | {
66 | command: 'click'
67 | selector: 'button[title="Sign out of WordPress.com"]'
68 | }
69 | {
70 | command: 'wait'
71 | value: 5000
72 | }
73 | ]
74 |
--------------------------------------------------------------------------------
/services/wordpress.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.3.3
2 | (function() {
3 |
4 | exports.name = 'wordpress';
5 |
6 | exports.steps = [
7 | {
8 | command: 'create',
9 | micro: false,
10 | noHTML: false
11 | }, {
12 | command: 'open',
13 | url: 'https://wordpress.com/wp-login.php',
14 | confirm: '#user_login'
15 | }, {
16 | command: 'login',
17 | form: '#loginform',
18 | username: '#user_login',
19 | password: '#user_pass',
20 | submit: true,
21 | confirm: 'a[data-tip-target="my-sites"]'
22 | }, {
23 | command: 'open-site',
24 | begin: 'https://wordpress.com/post/',
25 | end: '',
26 | confirm: '#tinymce-1'
27 | }, {
28 | command: 'click',
29 | selector: 'svg.gridicon.gridicons-create'
30 | }, {
31 | command: 'wait',
32 | value: 1000
33 | }, {
34 | command: 'title',
35 | selector: 'textarea.textarea-autosize.editor-title__input'
36 | }, {
37 | command: 'click',
38 | selector: 'a[title="Edit the raw HTML code"]'
39 | }, {
40 | command: 'wait',
41 | value: 1000
42 | }, {
43 | command: 'body',
44 | selector: '#tinymce-1'
45 | }, {
46 | command: 'click',
47 | xpath: '//*[text()[contains(.,"Publish")]]',
48 | confirm: '.is-success'
49 | }, {
50 | command: 'save-href',
51 | selector: 'a.notice__action'
52 | }, {
53 | command: 'click',
54 | selector: 'img[class="gravatar"]',
55 | confirm: 'button[title="Sign out of WordPress.com"]'
56 | }, {
57 | command: 'click',
58 | selector: 'button[title="Sign out of WordPress.com"]'
59 | }, {
60 | command: 'wait',
61 | value: 5000
62 | }
63 | ];
64 |
65 | }).call(this);
66 |
--------------------------------------------------------------------------------
/docs/indexers.md:
--------------------------------------------------------------------------------
1 | # Set Up Indexing Services
2 |
3 |
4 | An indexing service is required to drive search engines to your submitted articles. The techniques used vary but are generally backlink based or pinging based (poor quality) or a mix of both. Depending on the technique used by the service, results can vary. Some services can get links on to search engines only to have then drop off later. The ratio of new to lost links is a significant factor in search engine ranking. This may not be an issue if you are just getting paid to create new backlinks.
5 |
6 |
7 | [BacklinksIndexer.com][ace3719b] is recommended if your require high ranking on search engines. This service will provide high quality tier 1, 2 and 3 backlinks to your articles. This can be used to not only index your article backlinks, but you can also submit your main site URLs regularly to create further backlinks from various domains. This makes your SEO campaign look more natural to search engines.
8 |
9 | [Indexification.com][44bd53cf] is a low cost indexing service with good indexing rates at very low cost. This is a good service for SEO contractors that are getting paid to create links on a regular basis for clients. It is also a good option to use as a backup to a premium service when you run out of monthly credits.
10 |
11 | ## Create Indexers Configuration File
12 |
13 |
14 | When you have created your accounts with an indexing provider you can set up Open Submitter to automatically submit URLs to them. Open the GUI app and select "Set Up Indexers".
15 |
16 | 
17 |
18 | Enter your username and account for the service. Make sure you check "Automatically send backlinks to indexer".
19 |
20 | 
21 |
22 | Now save the file as indexers.txt to the settings folder.
23 |
24 |
25 | 
26 |
27 |
28 |
29 | [Documentation Home][3acc32de]
30 |
31 | [3acc32de]: readme.md "Open Submitter Documentation"
32 |
33 |
34 | [44bd53cf]: http://aff.innocoders.com/idevaffiliate.php?id=1640_2_3_1 "Indexification.com"
35 |
36 |
37 |
38 | [ace3719b]: http://jvz1.com/c/540185/31395 "BacklinksIndexer.com"
39 |
--------------------------------------------------------------------------------
/docs/submit.md:
--------------------------------------------------------------------------------
1 | # Submitting to Services
2 |
3 | Once you have set up Open Submitter:
4 | - prequesite frameworks installed and tested
5 | - article submission file has been created and saved to the articles folder
6 | - accounts csv file created and saved to accounts folder
7 | - indexing service file created and saved to settings folder
8 |
9 | You can now start the submit service.
10 |
11 | ## Starting the Submit Service
12 |
13 | The submit service must be started through the Command Line Interface (CLI). Open a command console (we recommend using the free app [Cmder][35fd80d0] if you are using Windows) and navigate to the Open Submitter directory.
14 |
15 | 
16 |
17 |
18 | To start the service run the following casperjs command:
19 | - casperjs (the headless webkit service)
20 | - open-submitter.js (Open Submitter application)
21 | - the name of your accounts file without the file extension
22 | - the name of your article submission file without the file extension
23 | - the file name to store backlinks to without the file extension
24 | - number of submission loops. e.g. if you have 20 accounts per service you may want to submit 5 randomly per day.
25 |
26 | e.g.
27 |
28 | casperjs open-submitter.js accounts articles backlinks 5
29 |
30 |
31 | 
32 |
33 | The submit service will now start submitting the article to the services.
34 |
35 | 
36 |
37 |
38 | After each article is submitted it is added to the backlinks file. When all the submissions have been completed Open Submitter will submit the URLs to the indexing service.
39 |
40 |
41 | If any services are not working they can be disabled (ses below).
42 |
43 |
44 | ## Enabling and Disabling Unreliable Services
45 |
46 | Not all services are reliable and many seem to be down more than they are up. Unreliable services can be disabled and enabled back again when reliable. To disable a service open the services.txt file in the setting folder. We recommend using the free app [Notepad++][a35f49bf] as the formatting is not changed when editing:
47 |
48 | 
49 |
50 | Now change the status of the service from ok to bad.
51 |
52 | 
53 |
54 | **Note:** Make sure you do not change the file name, otherwise Open Submitter won't find it again.
55 |
56 | [a35f49bf]: https://notepad-plus-plus.org/ "Notepad++"
57 |
58 |
59 | [35fd80d0]: http://cmder.net/ "Cmder Console"
60 |
--------------------------------------------------------------------------------
/docs/install-cli.md:
--------------------------------------------------------------------------------
1 | # Set Up Open Submitter
2 |
3 | How to set up the Open Submitter Command Line Interface (CLI). The CLI is required to submit articles to services.
4 |
5 | ## Prerequisites
6 | Please ensure the following prerequisite frameworks and applications are installed.
7 |
8 | - [NodeJS][ca1dffb7] v4.4.7 or greater
9 | - [PhantomJS][6997c770] v2.1 or greater
10 | - [CasperJS][476ee510] v1.1.1 or greater
11 | - [Cmder][9924c39d] (optional)
12 | - [The Best Spinner][a6914f8e] (optional)
13 |
14 | [ca1dffb7]: http://nodejs.org/ "NodeJS"
15 | [6997c770]: http://phantomjs.org/ "PhantomJS"
16 | [476ee510]: http://casperjs.org/ "CasperJS"
17 | [9924c39d]: http://cmder.net/ "Cmder"
18 | [a6914f8e]: http://paydotcom.net/r/95330/pcoady/27453918/ "The Best Spinner"
19 |
20 |
21 | ## Update Environment Variables
22 | Make sure your path environment variables are updated for NodeJS, PhantomJS, CasperJS and Cmder with the executable path.
23 | Depending on where you installed the software the paths will be similar to:
24 | - C:\Program Files\nodejs\
25 | - C:\phantomjs
26 | - C:\casperjs\batchbin
27 |
28 |
29 | ## Check Prerequisities
30 | After the executables paths have been added to your environment variables you can check they are installed correctly using the following commands from the command line:
31 | - node --version
32 | - phantomjs --version
33 | - casperjs --version
34 |
35 | If everything is installed correctly each command will return the curent version details.
36 |
37 | If you have any problems installing the prerequisite frameworks please post a question on [Stack Overflow][0f0072cf].
38 |
39 |
40 | [0f0072cf]: stackoverflow.com "Open Submitter Stack Overflow"
41 |
42 | ## Download latest release of Open Submitter
43 |
44 | Go to the main [repository page](https://github.com/BackSpaceTech/open-submitter).
45 |
46 | Click the releases.
47 |
48 | 
49 |
50 | Download archive file (zip or tar)
51 |
52 | 
53 |
54 | Extract archive to the location you want Open Submitter.
55 |
56 | ## Create additional required folders
57 |
58 | The following additional folders need to be created after the archive is extracted. Make sure all folder names are lowercase:
59 | - accounts
60 | - articles
61 | - backlinks
62 | - capture
63 |
64 | 
65 |
66 | ## Set up Sibbel
67 |
68 | Sibble will notify you by email of any repository changes to repositories you have starred. Always update immediately with new releases which can include bug fixes and new features and services. Sibbel does not spam you.
69 |
70 | First open a free GitHub account:
71 |
72 | 
73 |
74 | Then star the Open Submitter repository:
75 |
76 | 
77 |
78 | Then go to to Sibbel.com and set up Sibble.
79 |
80 | 
81 |
82 | You will now be notified by email of any new releases to Open Submitter.
83 | ### When copying a new release over an old, make sure you save your accounts, backlinks and settings/indexers.txt files before copying the new files.
84 |
85 | [Documentation Home][bdc43f25]
86 |
87 | [bdc43f25]: readme.md "Open Submitter Documentation"
88 |
--------------------------------------------------------------------------------
/docs/articles.md:
--------------------------------------------------------------------------------
1 | # Open Submitter Article Submissions
2 |
3 | Open Submitter article submission files contain the following information:
4 | - Title of article to be submitted in spin text.
5 | - Description of article in spin text.
6 | - Body of article in spin text.
7 | - Keywords in spin text and comma separated.
8 | - Link URLs in spin text and comma separated.
9 | - Image URLs in spin text and comma separated.
10 |
11 | ## Using Spin Syntax
12 |
13 | Spin syntax is used to allow Open Submitter to create unlimited unique articles to be submitted to services. Spin is surrounded by curly brackets {} and synonyms are separated by pipe symbols | e.g.
14 |
15 | **Phrase:**
16 |
17 | My great blog post.
18 |
19 | **Spin Syntax:**
20 |
21 |
22 | {My|A|This is a|A really} {great|awesome|cool} {blog post|article|review|commentary}
23 |
24 | **Example results after spinning**
25 |
26 | A cool commentary
27 |
28 | A really awesome commentary
29 |
30 | A great review
31 |
32 | This is a cool blog post
33 |
34 | My great commentary
35 |
36 | **Important Note**
37 |
38 | Do not nest spin as it will give unpredictable results with Open Submitter. e.g.
39 |
40 | Don't use this:
41 |
42 | {{this|this2}|this3}
43 |
44 | Only use this:
45 |
46 | {this|this2|this3}
47 |
48 | ## Spinning Tools
49 |
50 | Creating articles of any size in spin syntax manually is very slow process. The most popular tool used by professional SEO consultants to speed up this process is [The Best Spinner][3a94b86c].
51 |
52 | ## Create an Article
53 |
54 | Open the GUI and click "Create Article"
55 |
56 | Enter the title, description and body of your article. Click Spin Preview to see the results after spinning.
57 |
58 | 
59 |
60 | ## Add Link Tags to Article
61 |
62 | To create backlinks in your article body and description where you want insert link tags (#links#). Open Submitter will insert a random keyword with a random link from the article keyword and link list. If no link tags are put in, Open Submitter will place one at the end. Do not insert too many link tags as search engines may reject the article as spam. Don't exceed one link per two paragraphs. The best results will come from having only one link only in the article body and description. Do not put links in title as these will not be recognised by Open Submitter.
63 |
64 | 
65 |
66 | ## Add keywords, links.
67 |
68 | Keywords and links need to be supplied for Open Submitter to use. These are comma separated. Open Submitter will select randomly. Spin syntax can be used to group together long tail keywords and less important links. This way you can influence the ratio of selection of links and keywords.
69 |
70 |
71 | 
72 |
73 | ## Add Images
74 |
75 | Images make articles look more interesting and less spammy. Open Submitter selects images at random from the images list supplied. These are comma separated URLs. The imgaes are randomly located vertically and randomly floating left or right. Please note not all services accept images.
76 |
77 |
78 | 
79 |
80 |
81 | ## Create and Save Submission File
82 |
83 | Click on "Preview Submission" to see your final submission.
84 |
85 | 
86 |
87 | 
88 |
89 |
90 | Now Save the article submission file to the articles folder (you will need to create this folder). Please note it must be saved in the article folder only for open submitter to find it. Make sure the folder name is lowercase. If you have multiple submission files you can use multiple submission file names. All file names must have the .txt file extension. If you want multiple submissions in a single file simply use an editor such as Notepad++ and add them one after the other. Open Submitter will randomly select articles if multiple are available.
91 |
92 |
93 |
94 | 
95 |
96 |
97 | [Documentation Home][91a747ec]
98 |
99 | [91a747ec]: readme.md "Open Submitter Documentation"
100 |
101 |
102 | [3a94b86c]: http://paydotcom.net/r/95330/pcoady/27453918/ "The Best Spinner"
103 |
--------------------------------------------------------------------------------
/app/imports.coffee:
--------------------------------------------------------------------------------
1 | fs = require('fs')
2 | consolex = require('./console-xtra')
3 |
4 | exports.accounts = (filePath) ->
5 | # Load accounts.csv
6 | tempAccounts = []
7 | if fs.exists(filePath) and fs.isFile(filePath)
8 | console.log 'Loading user accounts...'
9 | ins = fs.open(filePath, 'r')
10 | a = 0
11 | while !ins.atEnd()
12 | buffer = ins.readLine()
13 | temp = buffer.split(/\s*,\s*/)
14 | tempAccounts[a] = {
15 | accountType: temp[0]
16 | loginID: temp[1]
17 | password: temp[2]
18 | siteName: temp[3]
19 | }
20 | ++a
21 | tempAccounts # Return accounts
22 | else
23 | console.log 'Could not load ' + filePath
24 |
25 | exports.articles = (filePath) ->
26 | # Load Articles.txt
27 | tempArticles = []
28 | articleStatus = ''
29 | firstLine = false
30 | if fs.exists(filePath) and fs.isFile(filePath)
31 | console.log 'Loading articles...'
32 | ins = fs.open(filePath, 'r')
33 | a = -1
34 | while !ins.atEnd()
35 | buffer = ins.readLine()
36 | temp = buffer.trim()
37 | if temp == '#Title'
38 | articleStatus = 'title'
39 | ++a
40 | tempArticles[a] = {
41 | title: ''
42 | description: ''
43 | body: ''
44 | keywords: ''
45 | links: ''
46 | images: ''
47 | }
48 | else if temp == '#Body'
49 | articleStatus = 'body'
50 | firstLine = true
51 | else if temp == '#Keywords'
52 | articleStatus = 'keywords'
53 | else if temp == '#Links'
54 | articleStatus = 'links'
55 | else if temp == '#Images'
56 | articleStatus = 'images'
57 | else if articleStatus == 'title'
58 | tempArticles[a].title += temp
59 | else if articleStatus == 'body'
60 | if firstLine and temp != ''
61 | tempArticles[a].description = temp + '
'
62 | firstLine = false
63 | tempArticles[a].body += temp + '
'
64 | else if articleStatus == 'keywords'
65 | temp = buffer.split(/\s*,\s*/)
66 | tempArticles[a].keywords = temp
67 | else if articleStatus == 'links'
68 | temp = buffer.split(/\s*,\s*/)
69 | tempArticles[a].links = temp
70 | else if articleStatus == 'images'
71 | temp = buffer.split(/\s*,\s*/)
72 | tempArticles[a].images = temp
73 | ins.close()
74 | a = 0
75 | tempArticles # Return Articles
76 | else
77 | console.log 'Could not load ' + filePath
78 |
79 | exports.indexers = (filePath) ->
80 | # Load Indexer.txt
81 | tempIndexers = []
82 | status = ''
83 | if fs.exists(filePath) and fs.isFile(filePath)
84 | ins = fs.open(filePath, 'r')
85 | a = -1
86 | while !ins.atEnd()
87 | buffer = ins.readLine()
88 | temp = buffer.trim()
89 | if temp == '#name#'
90 | status = 'name'
91 | ++a
92 | tempIndexers[a] = {
93 | name: ''
94 | username: ''
95 | password: ''
96 | status: ''
97 | }
98 | else if temp == '#username#'
99 | status = 'username'
100 | else if temp == '#password#'
101 | status = 'password'
102 | else if temp == '#status#'
103 | status = 'status'
104 | else if status == 'name'
105 | tempIndexers[a].name = temp
106 | status = ''
107 | else if status == 'username'
108 | tempIndexers[a].username = temp
109 | status = ''
110 | else if status == 'password'
111 | tempIndexers[a].password = temp
112 | status = ''
113 | else if status == 'status'
114 | tempIndexers[a].status = temp
115 | status = ''
116 | ins.close()
117 | a = 0
118 | temp2 = 0
119 | tempIndexers2 = []
120 | for i in [0...tempIndexers.length]
121 | if tempIndexers[i].status.toLowerCase() == 'ok'
122 | tempIndexers2[temp2] = tempIndexers[i]
123 | ++temp2
124 | tempIndexers2 # Return Indexer
125 | else
126 | console.log 'Could not load ' + filePath
127 |
128 | exports.services = (filePath) ->
129 | # Load Indexer.txt
130 | tempServices = []
131 | status = ''
132 | if fs.exists(filePath) and fs.isFile(filePath)
133 | ins = fs.open(filePath, 'r')
134 | a = -1
135 | while !ins.atEnd()
136 | buffer = ins.readLine()
137 | temp = buffer.trim()
138 | if temp == '#name#'
139 | status = 'name'
140 | ++a
141 | tempServices[a] = {
142 | name: ''
143 | status: ''
144 | }
145 | else if temp == '#status#'
146 | status = 'status'
147 | else if status == 'name'
148 | tempServices[a].name = temp
149 | else if status == 'status'
150 | tempServices[a].status = temp
151 | ins.close()
152 | a = 0
153 | tempServices # Return Articles
154 | else
155 | console.log 'Could not load ' + filePath
156 |
--------------------------------------------------------------------------------
/app/spinner.coffee:
--------------------------------------------------------------------------------
1 | fs = require('fs')
2 | consolex = require('./console-xtra')
3 |
4 | # -------------------- Get random account ----------------------------
5 |
6 | exports.getAccount = (accounts, accountType) ->
7 | # Random wordpress account details
8 | tempRandomAccount =
9 | username: ''
10 | password: ''
11 | site: ''
12 | tempAccArray = accounts.filter (el) ->
13 | el.accountType == accountType
14 | if (tempAccArray.length > 0)
15 | randomAcc = Math.floor(Math.random() * tempAccArray.length)
16 | tempRandomAccount.username = tempAccArray[randomAcc].loginID
17 | tempRandomAccount.password = tempAccArray[randomAcc].password
18 | tempRandomAccount.site = tempAccArray[randomAcc].siteName
19 | else
20 | tempRandomAccount.username = 'no accounts'
21 | tempRandomAccount # Return a random account
22 |
23 | # -------------------- Create new spun article ----------------------------
24 |
25 | spinner = (x) ->
26 | tempStr = ''
27 | tempSpinner = x.split( /\{([^}]+)\}/ )
28 | y = 0
29 | while y < tempSpinner.length
30 | temp3 = tempSpinner[y].split( "|" )
31 | tempStr += temp3[Math.floor(temp3.length*Math.random())]
32 | ++y
33 | tempStr
34 |
35 | spinnerLoop = (x) ->
36 | tempArray = []
37 | y = 0
38 | while y < x.length
39 | tempArray[y] = spinner(x[y])
40 | ++y
41 | tempArray
42 |
43 | exports.getArticle = (articles, microBlog, noHTML) ->
44 | # Create spun article
45 | a = Math.floor(articles.length*Math.random())
46 | newArticle =
47 | title: ''
48 | body: ''
49 | keywords: []
50 | links: []
51 | images: []
52 |
53 | # Spin article title
54 | console.log 'Spinning title for article # ' + a + '...'
55 | newArticle.title = spinner(articles[a].title)
56 |
57 | # Spin article keywords
58 | console.log 'Spinning keywords for article # ' + a + '...'
59 | newArticle.keywords = spinnerLoop(articles[a].keywords)
60 |
61 | # Spin article links
62 | console.log 'Spinning links for article # ' + a + '...'
63 | newArticle.links = spinnerLoop(articles[a].links)
64 |
65 | # Spin article images
66 | console.log 'Spinning images for article # ' + a + '...'
67 | newArticle.images = spinnerLoop(articles[a].images)
68 |
69 | # Spin article body / description
70 | console.log 'Spinning body of article # ' + a + '...'
71 | if microBlog
72 | temp = articles[a].description
73 | else
74 | temp = articles[a].body
75 | newArticle.body = spinner(temp)
76 | if noHTML
77 | newArticle.body = newArticle.body.replace('
', '\n')
78 |
79 | # Insert random links
80 | console.log 'Inserting random links in article # ' + a + '...'
81 | if !noHTML
82 | # Insert random links with random keywords in body
83 | tempIndex = 0
84 | while tempIndex < newArticle.keywords.length # Check for empty string
85 | if newArticle.keywords[tempIndex].trim().length == 0
86 | newArticle.keywords.splice(tempIndex, 1)
87 | ++tempIndex
88 | if newArticle.keywords.length == 0 # If no keywords
89 | newArticle.keywords[0] = 'here'
90 | if (newArticle.body.indexOf("#links#")) == -1 # No link tags
91 | newArticle.body += ' #links#'
92 | while (newArticle.body.indexOf("#links#")) != -1
93 | tempRandom = Math.floor(Math.random()*newArticle.links.length)
94 | randomLink = newArticle.links[tempRandom]
95 | tempRandom = Math.floor(Math.random()*newArticle.keywords.length)
96 | randomKeyword = newArticle.keywords[tempRandom]
97 | tempLink = ' ' +
98 | randomKeyword.toString().trim() + ' '
99 | newArticle.body = newArticle.body.replace('#links#', tempLink)
100 | else
101 | # Remove link tags
102 | newArticle.body = newArticle.body.replace('#links#', ' ')
103 | # Insert random link at end of body
104 | temp = Math.floor(Math.random()*newArticle.links.length)
105 | randomLink = newArticle.links[temp]
106 | newArticle.body += (' ' + randomLink)
107 |
108 | # Add random image in a random position of body
109 | if !noHTML
110 | console.log 'Inserting random image in article # ' + a + '...'
111 | temp = newArticle.body.length
112 | floatPos = ['style="float:right"','style="float:left"']
113 | randomFloat = Math.round(Math.random())
114 | randomPos = Math.ceil(Math.random() * temp)
115 | randomImage = Math.floor(Math.random() * newArticle.images.length)
116 | # Split body and insert image. Make sure not splitting a word
117 | while newArticle.body.charAt(randomPos-1) != ' '
118 | randomPos = Math.ceil(Math.random() * temp)
119 | temp1 = newArticle.body.slice(0, randomPos)
120 | temp2 = '
'
122 | temp3 = newArticle.body.slice(randomPos, temp)
123 | newArticle.body = temp1 + temp2 + temp3
124 |
125 | consolex.log 'magenta', 'Created article: ' + newArticle.title
126 | newArticle # Return the article to submit
127 |
--------------------------------------------------------------------------------
/app/spinner.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.3.3
2 | (function() {
3 | var consolex, fs, spinner, spinnerLoop;
4 |
5 | fs = require('fs');
6 |
7 | consolex = require('./console-xtra');
8 |
9 | exports.getAccount = function(accounts, accountType) {
10 | var randomAcc, tempAccArray, tempRandomAccount;
11 | tempRandomAccount = {
12 | username: '',
13 | password: '',
14 | site: ''
15 | };
16 | tempAccArray = accounts.filter(function(el) {
17 | return el.accountType === accountType;
18 | });
19 | if (tempAccArray.length > 0) {
20 | randomAcc = Math.floor(Math.random() * tempAccArray.length);
21 | tempRandomAccount.username = tempAccArray[randomAcc].loginID;
22 | tempRandomAccount.password = tempAccArray[randomAcc].password;
23 | tempRandomAccount.site = tempAccArray[randomAcc].siteName;
24 | } else {
25 | tempRandomAccount.username = 'no accounts';
26 | }
27 | return tempRandomAccount;
28 | };
29 |
30 | spinner = function(x) {
31 | var temp3, tempSpinner, tempStr, y;
32 | tempStr = '';
33 | tempSpinner = x.split(/\{([^}]+)\}/);
34 | y = 0;
35 | while (y < tempSpinner.length) {
36 | temp3 = tempSpinner[y].split("|");
37 | tempStr += temp3[Math.floor(temp3.length * Math.random())];
38 | ++y;
39 | }
40 | return tempStr;
41 | };
42 |
43 | spinnerLoop = function(x) {
44 | var tempArray, y;
45 | tempArray = [];
46 | y = 0;
47 | while (y < x.length) {
48 | tempArray[y] = spinner(x[y]);
49 | ++y;
50 | }
51 | return tempArray;
52 | };
53 |
54 | exports.getArticle = function(articles, microBlog, noHTML) {
55 | var a, floatPos, newArticle, randomFloat, randomImage, randomKeyword, randomLink, randomPos, temp, temp1, temp2, temp3, tempIndex, tempLink, tempRandom;
56 | a = Math.floor(articles.length * Math.random());
57 | newArticle = {
58 | title: '',
59 | body: '',
60 | keywords: [],
61 | links: [],
62 | images: []
63 | };
64 | console.log('Spinning title for article # ' + a + '...');
65 | newArticle.title = spinner(articles[a].title);
66 | console.log('Spinning keywords for article # ' + a + '...');
67 | newArticle.keywords = spinnerLoop(articles[a].keywords);
68 | console.log('Spinning links for article # ' + a + '...');
69 | newArticle.links = spinnerLoop(articles[a].links);
70 | console.log('Spinning images for article # ' + a + '...');
71 | newArticle.images = spinnerLoop(articles[a].images);
72 | console.log('Spinning body of article # ' + a + '...');
73 | if (microBlog) {
74 | temp = articles[a].description;
75 | } else {
76 | temp = articles[a].body;
77 | }
78 | newArticle.body = spinner(temp);
79 | if (noHTML) {
80 | newArticle.body = newArticle.body.replace('
', '\n');
81 | }
82 | console.log('Inserting random links in article # ' + a + '...');
83 | if (!noHTML) {
84 | tempIndex = 0;
85 | while (tempIndex < newArticle.keywords.length) {
86 | if (newArticle.keywords[tempIndex].trim().length === 0) {
87 | newArticle.keywords.splice(tempIndex, 1);
88 | }
89 | ++tempIndex;
90 | }
91 | if (newArticle.keywords.length === 0) {
92 | newArticle.keywords[0] = 'here';
93 | }
94 | if ((newArticle.body.indexOf("#links#")) === -1) {
95 | newArticle.body += ' #links#';
96 | }
97 | while ((newArticle.body.indexOf("#links#")) !== -1) {
98 | tempRandom = Math.floor(Math.random() * newArticle.links.length);
99 | randomLink = newArticle.links[tempRandom];
100 | tempRandom = Math.floor(Math.random() * newArticle.keywords.length);
101 | randomKeyword = newArticle.keywords[tempRandom];
102 | tempLink = ' ' + randomKeyword.toString().trim() + ' ';
103 | newArticle.body = newArticle.body.replace('#links#', tempLink);
104 | }
105 | } else {
106 | newArticle.body = newArticle.body.replace('#links#', ' ');
107 | temp = Math.floor(Math.random() * newArticle.links.length);
108 | randomLink = newArticle.links[temp];
109 | newArticle.body += ' ' + randomLink;
110 | }
111 | if (!noHTML) {
112 | console.log('Inserting random image in article # ' + a + '...');
113 | temp = newArticle.body.length;
114 | floatPos = ['style="float:right"', 'style="float:left"'];
115 | randomFloat = Math.round(Math.random());
116 | randomPos = Math.ceil(Math.random() * temp);
117 | randomImage = Math.floor(Math.random() * newArticle.images.length);
118 | while (newArticle.body.charAt(randomPos - 1) !== ' ') {
119 | randomPos = Math.ceil(Math.random() * temp);
120 | }
121 | temp1 = newArticle.body.slice(0, randomPos);
122 | temp2 = '
';
123 | temp3 = newArticle.body.slice(randomPos, temp);
124 | newArticle.body = temp1 + temp2 + temp3;
125 | }
126 | consolex.log('magenta', 'Created article: ' + newArticle.title);
127 | return newArticle;
128 | };
129 |
130 | }).call(this);
131 |
--------------------------------------------------------------------------------
/app/imports.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.3.3
2 | (function() {
3 | var consolex, fs;
4 |
5 | fs = require('fs');
6 |
7 | consolex = require('./console-xtra');
8 |
9 | exports.accounts = function(filePath) {
10 | var a, buffer, ins, temp, tempAccounts;
11 | tempAccounts = [];
12 | if (fs.exists(filePath) && fs.isFile(filePath)) {
13 | console.log('Loading user accounts...');
14 | ins = fs.open(filePath, 'r');
15 | a = 0;
16 | while (!ins.atEnd()) {
17 | buffer = ins.readLine();
18 | temp = buffer.split(/\s*,\s*/);
19 | tempAccounts[a] = {
20 | accountType: temp[0],
21 | loginID: temp[1],
22 | password: temp[2],
23 | siteName: temp[3]
24 | };
25 | ++a;
26 | }
27 | return tempAccounts;
28 | } else {
29 | return console.log('Could not load ' + filePath);
30 | }
31 | };
32 |
33 | exports.articles = function(filePath) {
34 | var a, articleStatus, buffer, firstLine, ins, temp, tempArticles;
35 | tempArticles = [];
36 | articleStatus = '';
37 | firstLine = false;
38 | if (fs.exists(filePath) && fs.isFile(filePath)) {
39 | console.log('Loading articles...');
40 | ins = fs.open(filePath, 'r');
41 | a = -1;
42 | while (!ins.atEnd()) {
43 | buffer = ins.readLine();
44 | temp = buffer.trim();
45 | if (temp === '#Title') {
46 | articleStatus = 'title';
47 | ++a;
48 | tempArticles[a] = {
49 | title: '',
50 | description: '',
51 | body: '',
52 | keywords: '',
53 | links: '',
54 | images: ''
55 | };
56 | } else if (temp === '#Body') {
57 | articleStatus = 'body';
58 | firstLine = true;
59 | } else if (temp === '#Keywords') {
60 | articleStatus = 'keywords';
61 | } else if (temp === '#Links') {
62 | articleStatus = 'links';
63 | } else if (temp === '#Images') {
64 | articleStatus = 'images';
65 | } else if (articleStatus === 'title') {
66 | tempArticles[a].title += temp;
67 | } else if (articleStatus === 'body') {
68 | if (firstLine && temp !== '') {
69 | tempArticles[a].description = temp + '
';
70 | firstLine = false;
71 | }
72 | tempArticles[a].body += temp + '
';
73 | } else if (articleStatus === 'keywords') {
74 | temp = buffer.split(/\s*,\s*/);
75 | tempArticles[a].keywords = temp;
76 | } else if (articleStatus === 'links') {
77 | temp = buffer.split(/\s*,\s*/);
78 | tempArticles[a].links = temp;
79 | } else if (articleStatus === 'images') {
80 | temp = buffer.split(/\s*,\s*/);
81 | tempArticles[a].images = temp;
82 | }
83 | }
84 | ins.close();
85 | a = 0;
86 | return tempArticles;
87 | } else {
88 | return console.log('Could not load ' + filePath);
89 | }
90 | };
91 |
92 | exports.indexers = function(filePath) {
93 | var a, buffer, i, ins, status, temp, temp2, tempIndexers, tempIndexers2, _i, _ref;
94 | tempIndexers = [];
95 | status = '';
96 | if (fs.exists(filePath) && fs.isFile(filePath)) {
97 | ins = fs.open(filePath, 'r');
98 | a = -1;
99 | while (!ins.atEnd()) {
100 | buffer = ins.readLine();
101 | temp = buffer.trim();
102 | if (temp === '#name#') {
103 | status = 'name';
104 | ++a;
105 | tempIndexers[a] = {
106 | name: '',
107 | username: '',
108 | password: '',
109 | status: ''
110 | };
111 | } else if (temp === '#username#') {
112 | status = 'username';
113 | } else if (temp === '#password#') {
114 | status = 'password';
115 | } else if (temp === '#status#') {
116 | status = 'status';
117 | } else if (status === 'name') {
118 | tempIndexers[a].name = temp;
119 | status = '';
120 | } else if (status === 'username') {
121 | tempIndexers[a].username = temp;
122 | status = '';
123 | } else if (status === 'password') {
124 | tempIndexers[a].password = temp;
125 | status = '';
126 | } else if (status === 'status') {
127 | tempIndexers[a].status = temp;
128 | status = '';
129 | }
130 | }
131 | ins.close();
132 | a = 0;
133 | temp2 = 0;
134 | tempIndexers2 = [];
135 | for (i = _i = 0, _ref = tempIndexers.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
136 | if (tempIndexers[i].status.toLowerCase() === 'ok') {
137 | tempIndexers2[temp2] = tempIndexers[i];
138 | ++temp2;
139 | }
140 | }
141 | return tempIndexers2;
142 | } else {
143 | return console.log('Could not load ' + filePath);
144 | }
145 | };
146 |
147 | exports.services = function(filePath) {
148 | var a, buffer, ins, status, temp, tempServices;
149 | tempServices = [];
150 | status = '';
151 | if (fs.exists(filePath) && fs.isFile(filePath)) {
152 | ins = fs.open(filePath, 'r');
153 | a = -1;
154 | while (!ins.atEnd()) {
155 | buffer = ins.readLine();
156 | temp = buffer.trim();
157 | if (temp === '#name#') {
158 | status = 'name';
159 | ++a;
160 | tempServices[a] = {
161 | name: '',
162 | status: ''
163 | };
164 | } else if (temp === '#status#') {
165 | status = 'status';
166 | } else if (status === 'name') {
167 | tempServices[a].name = temp;
168 | } else if (status === 'status') {
169 | tempServices[a].status = temp;
170 | }
171 | }
172 | ins.close();
173 | a = 0;
174 | return tempServices;
175 | } else {
176 | return console.log('Could not load ' + filePath);
177 | }
178 | };
179 |
180 | }).call(this);
181 |
--------------------------------------------------------------------------------
/open-submitter.coffee:
--------------------------------------------------------------------------------
1 | fs = require('fs')
2 | system = require('system')
3 | consolex = require('./app/console-xtra')
4 | imports = require('./app/imports')
5 | spinner = require('./app/spinner')
6 | page = require('webpage').create()
7 |
8 | casper = require('casper').create(
9 | pageSettings: webSecurityEnabled: false
10 | viewportSize: {width: 800, height: 600}
11 | timeout: 3600000 # 1 hour general timeout
12 | stepTimeout: 300000 # 5 min default step timeout
13 | waitTimeout: 60000 # 1 min default wait timeout
14 | verbose: true
15 | onError: (self, msg) ->
16 | consolex.log 'red', 'FATAL:' + msg
17 | self.exit()
18 | return
19 | onTimeout: (self, msg) ->
20 | @.capture('./capture/timeout.png')
21 | consolex.log 'red', 'general timeout error: ' + msg
22 | return
23 | onStepTimeout: (self, msg) ->
24 | @.capture('./capture/timeout.png')
25 | consolex.log 'red', 'step timeout error: step ' + msg
26 | return
27 | onWaitTimeout: (self, msg) ->
28 | @.capture ('./capture/timeout.png')
29 | consolex.log 'red','wait timeout error: ' + msg
30 | return
31 | )
32 |
33 | casper.userAgent 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 ' +
34 | '(KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
35 |
36 | fileAccounts = './accounts/' + casper.cli.get(0) + '.csv'
37 | fileArticles = './articles/' + casper.cli.get(1) + '.txt'
38 | fileBacklinks = './backlinks/' + casper.cli.get(2) + '.txt'
39 | numPosts = casper.cli.get(3)
40 |
41 | console.log '\n'
42 | consolex.log 'cyan', '---------------- Submission Details --------------------'
43 | consolex.log 'cyan', 'Accounts file: ' + fileAccounts
44 | consolex.log 'cyan', 'Articles file: ' + fileArticles
45 | consolex.log 'cyan', 'Backlinks saved to file: ' + fileBacklinks
46 | consolex.log 'cyan', 'Number of Submissions: ' + numPosts
47 |
48 | currentService = 0
49 | currentStep = 0
50 | submitArticle =
51 | title: ''
52 | body: ''
53 | keywords: ''
54 |
55 | # Import settings
56 | services = imports.services('./settings/services.txt')
57 | indexerDetails = imports.indexers('./settings/indexers.txt')
58 |
59 | # Load services
60 | numLoops = 0
61 | service = []
62 | currentService = 0
63 | for i in [0...services.length]
64 | if services[i].status.toLowerCase() == 'ok'
65 | service[currentService] = require('./services/' + services[i].name)
66 | numLoops += service[currentService].steps.length
67 | ++currentService
68 | numLoops *= numPosts
69 |
70 | # Load indexer
71 | numIndexerLoops = 0
72 | indexers = []
73 | indexersLogin = []
74 | currentIndexer = 0
75 | for i in [0...indexerDetails.length]
76 | if indexerDetails[i].status.toLowerCase() == 'ok'
77 | indexers[currentIndexer] = require('./indexers/' + indexerDetails[i].name)
78 | indexersLogin[currentIndexer] = indexerDetails[i]
79 | numIndexerLoops += indexers[currentIndexer].steps.length
80 | ++currentIndexer
81 |
82 | # ---------------- Import Files ------------------------
83 |
84 | console.log ('------------------- Import Files -------------------------')
85 | accounts = imports.accounts(fileAccounts)
86 | articles = imports.articles(fileArticles)
87 |
88 | # ------------------ Utils ------------------------
89 |
90 | currentStep = 0
91 | randomAccount =
92 | username: ''
93 | password: ''
94 | site: ''
95 | submitArticle =
96 | title: ''
97 | body: ''
98 | keywords: ''
99 | backlinksList = ''
100 |
101 | skipService = ->
102 | console.log 'Skipping ' + service[currentService].name
103 | ++currentService
104 | currentStep = 0
105 |
106 | errorMsg = ->
107 | console.log 'Failed step ' + currentStep
108 | console.log 'Check error.png file'
109 | skipService()
110 |
111 | # ------------------------ Step Commands ------------------------------
112 |
113 | currentSubmission = 0
114 | currentService = 0
115 | currentIndexer = 0
116 | currentIndexerStep = 0
117 |
118 | casper.doStep = (objStep, serviceName) ->
119 | @echo 'Step: ' + currentStep
120 | # -------------------------- Create -------------------------------------
121 | if objStep.command == 'create'
122 | @echo 'Creating article...'
123 | submitArticle = spinner.getArticle(articles, objStep.micro,objStep.noHTML)
124 | randomAccount = spinner.getAccount(accounts, serviceName)
125 | str = '-------------- Submit to ' + serviceName+' ----------------'
126 | consolex.log 'yellow', str
127 | # -------------------------- Open ---------------------------------------
128 | else if objStep.command == 'open'
129 | @echo 'Opening url '+objStep.url+'...'
130 | @open(objStep.url).then ->
131 | @capture('./capture/capture' + currentStep + '.png')
132 | if objStep.confirm
133 | @waitForSelector objStep.confirm,
134 | ->
135 | @echo 'Opened url'
136 | ->
137 | errorMsg()
138 | @capture('./capture/error.png')
139 | else if objStep.confirmtxt
140 | @waitForText objStep.confirmtxt,
141 | ->
142 | @echo 'Opened url'
143 | ->
144 | errorMsg()
145 | @capture('./capture/error.png')
146 | # -------------------------- Open Site -----------------------------------
147 | else if objStep.command == 'open-site'
148 | tempURL = objStep.begin + randomAccount.site + objStep.end
149 | @echo 'Opening url ' + tempURL + '...'
150 | @open(tempURL).then ->
151 | @capture('./capture/capture' + currentStep + '.png')
152 | if objStep.confirm
153 | @waitForSelector objStep.confirm,
154 | ->
155 | @echo 'Opened url'
156 | ->
157 | errorMsg()
158 | @capture('./capture/error.png')
159 | else if objStep.confirmtxt
160 | @waitForText objStep.confirmtxt,
161 | ->
162 | @echo 'Opened url'
163 | ->
164 | errorMsg()
165 | @capture('./capture/error.png')
166 | # -------------------------- Login ----------------------------------------
167 | else if objStep.command == 'login'
168 | if randomAccount.username == 'no accounts'
169 | @echo 'No '+ serviceName + ' accounts!'
170 | skipService()
171 | else
172 | @echo 'Logging in: ' + randomAccount.username + '...'
173 | # Login to WordPress with random account
174 | tempObj =
175 | formElem: objStep.form
176 | nameElem: objStep.username
177 | pwdElem: objStep.password
178 | name: randomAccount.username
179 | pwd: randomAccount.password
180 | submit: objStep.submit
181 | @evaluate ((s) ->
182 | document.querySelector(s.nameElem).value = s.name
183 | document.querySelector(s.pwdElem).value = s.pwd
184 | if s.submit
185 | document.querySelector(s.formElem).submit()
186 | return
187 | ), tempObj
188 | @capture('./capture/capture' + currentStep + '.png')
189 | @echo 'Waiting for login confirmation...'
190 | if objStep.submit
191 | @waitForSelector objStep.confirm,
192 | ->
193 | @echo 'Login success.'
194 | ->
195 | errorMsg()
196 | @capture('./capture/error.png')
197 | else if objStep.confirmtxt
198 | @waitForText objStep.confirmtxt,
199 | ->
200 | @echo 'Login success.'
201 | ->
202 | errorMsg()
203 | @capture('./capture/error.png')
204 | # -------------------------- Login-Indexer -----------------------------------
205 | else if objStep.command == 'login-indexer'
206 | @capture('./capture/indexer0.png')
207 | if indexersLogin.length == 0
208 | @echo 'No indexer accounts set up!'
209 | else
210 | @echo 'Logging in: ' +
211 | indexersLogin[currentIndexer].username + '...'
212 | # Login to Indexer
213 | tempObj =
214 | formElem: objStep.form
215 | nameElem: objStep.username
216 | pwdElem: objStep.password
217 | name: indexersLogin[currentIndexer].username
218 | pwd: indexersLogin[currentIndexer].password
219 | submit: objStep.submit
220 | @evaluate ((s) ->
221 | document.querySelector(s.nameElem).value = s.name
222 | document.querySelector(s.pwdElem).value = s.pwd
223 | if s.submit
224 | document.querySelector(s.formElem).submit()
225 | return
226 | ), tempObj
227 | @capture('./capture/indexer1.png')
228 | @echo 'Waiting for login confirmation...'
229 | if objStep.confirm
230 | @waitForSelector objStep.confirm,
231 | ->
232 | @echo 'Login success.'
233 | ->
234 | @capture('./capture/error.png')
235 | errorMsg()
236 | else if objStep.confirmtxt
237 | @waitForText objStep.confirmtxt,
238 | ->
239 | @echo 'Login success.'
240 | ->
241 | @capture('./capture/error.png')
242 | errorMsg()
243 | # --------------------------- Click ---------------------------------------
244 | if objStep.command == 'click'
245 | if objStep.selector
246 | tempObj = objStep.selector
247 | else if objStep.xpath
248 | tempObj = {
249 | type: 'xpath',
250 | path: objStep.xpath
251 | }
252 | if @exists(tempObj)
253 | @click tempObj
254 | @echo 'Clicked on DOM selector'
255 | if objStep.confirm
256 | @waitForSelector objStep.confirm,
257 | ->
258 | @echo 'Found confirm selector.'
259 | ->
260 | @echo 'Confirm DOM selector not found', 'ERROR'
261 | errorMsg()
262 | @capture('./capture/error.png')
263 | if objStep.confirmtxt
264 | @waitForText objStep.confirmtxt,
265 | ->
266 | @echo 'Found confirm text: ' + objStep.confirmtxt
267 | ->
268 | @echo 'Confirm text' + objStep.confirmtxt + 'not found', 'ERROR'
269 | errorMsg()
270 | @capture('./capture/error.png')
271 | else
272 | @echo 'DOM selector not found', 'ERROR'
273 | errorMsg()
274 | # --------------------------- Wait ---------------------------------------
275 | if objStep.command == 'wait'
276 | @echo 'Waiting for ' + objStep.value + ' ms'
277 | @wait objStep.value, ->
278 | @echo 'Finished wait time.'
279 | return
280 | # --------------------------- Title ---------------------------------------
281 | if objStep.command == 'title'
282 | if objStep.selector
283 | tempObj = objStep.selector
284 | else if objStep.xpath
285 | tempObj = {
286 | type: 'xpath',
287 | path: objStep.xpath
288 | }
289 | if @exists(tempObj)
290 | @sendKeys(tempObj, submitArticle.title)
291 | @echo 'Entered title'
292 | else
293 | @echo 'Input field not found', 'ERROR'
294 | errorMsg()
295 | # --------------------------- Title ---------------------------------------
296 | if objStep.command == 'backlinks'
297 | if objStep.selector
298 | tempObj = objStep.selector
299 | else if objStep.xpath
300 | tempObj = {
301 | type: 'xpath',
302 | path: objStep.xpath
303 | }
304 | if @exists(tempObj)
305 | @sendKeys(tempObj, backlinksList)
306 | @echo 'Entered backlinks list'
307 | else
308 | @echo 'Input field not found', 'ERROR'
309 | errorMsg()
310 | # --------------------------- Body ---------------------------------------
311 | if objStep.command == 'body'
312 | if objStep.selector
313 | tempObj = objStep.selector
314 | else if objStep.xpath
315 | tempObj = {
316 | type: 'xpath',
317 | path: objStep.xpath
318 | }
319 | if @exists(tempObj)
320 | @sendKeys(tempObj, submitArticle.body)
321 | @echo 'Entered body'
322 | else
323 | @echo 'Input field not found', 'ERROR'
324 | errorMsg()
325 | # --------------------------- Save-href -----------------------------------
326 | if objStep.command == 'save-href'
327 | if objStep.selector
328 | tempObj = objStep.selector
329 | else if objStep.xpath
330 | tempObj = {
331 | type: 'xpath',
332 | path: objStep.xpath
333 | }
334 | if @exists(tempObj)
335 | submitURL = @getElementAttribute tempObj, 'href'
336 | backlinksList += submitURL + '\n'
337 | consolex.log 'cyan', 'Submitted post to URL: ' + submitURL
338 | # Save backlinks.txt
339 | try
340 | fs.write fileBacklinks, submitURL, 'a'
341 | fs.write fileBacklinks, '\n', 'a'
342 | catch e
343 | @echo e
344 | @echo 'Saved backlink to ' + fileBacklinks
345 | else
346 | @echo 'DOM selector not found' +tempObj, 'ERROR'
347 | errorMsg()
348 |
349 | # ------------------ Submit to Services ------------------------
350 |
351 | casper.start()
352 | casper.repeat numLoops, ->
353 | @then ->
354 | if currentService >= service.length
355 | ++currentSubmission
356 | currentService = 0
357 | currentStep = 0
358 | if currentSubmission < numPosts
359 | serviceName = service[currentService].name
360 | objStep = service[currentService].steps[currentStep]
361 | @.doStep(objStep, serviceName)
362 | @then ->
363 | @capture('./capture/capture' + currentStep + '.png')
364 | ++currentStep
365 | if currentStep == service[currentService].steps.length
366 | serviceName = service[currentService].name
367 | consolex.log 'green', 'Completed submit to '+serviceName + '\n'
368 | ++currentService
369 | currentStep = 0
370 | return
371 | return
372 |
373 | casper.then ->
374 | consolex.log 'blue', 'Submitting links to indexeing services'
375 |
376 | casper.repeat numIndexerLoops, ->
377 | @then ->
378 | if currentIndexer < indexers.length
379 | serviceName = indexers[currentIndexer].name
380 | objStep = indexers[currentIndexer].steps[currentIndexerStep]
381 | @.doStep(objStep, serviceName)
382 | ++currentIndexerStep
383 | if currentIndexerStep == indexers[currentIndexer].steps.length
384 | ++currentIndexer
385 | currentIndexerStep = 0
386 |
387 | casper.run ->
388 | consolex.log 'green', 'Finished all submissions.'
389 | @echo 'Press ctrl C to exit'
390 | @exit(0)
391 | @bypass(1)
392 | return
393 | #
394 |
--------------------------------------------------------------------------------
/open-submitter.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.3.3
2 | (function() {
3 | var accounts, articles, backlinksList, casper, consolex, currentIndexer, currentIndexerStep, currentService, currentStep, currentSubmission, errorMsg, fileAccounts, fileArticles, fileBacklinks, fs, i, imports, indexerDetails, indexers, indexersLogin, numIndexerLoops, numLoops, numPosts, page, randomAccount, service, services, skipService, spinner, submitArticle, system, _i, _j, _ref, _ref1;
4 |
5 | fs = require('fs');
6 |
7 | system = require('system');
8 |
9 | consolex = require('./app/console-xtra');
10 |
11 | imports = require('./app/imports');
12 |
13 | spinner = require('./app/spinner');
14 |
15 | page = require('webpage').create();
16 |
17 | casper = require('casper').create({
18 | pageSettings: {
19 | webSecurityEnabled: false
20 | },
21 | viewportSize: {
22 | width: 800,
23 | height: 600
24 | },
25 | timeout: 3600000,
26 | stepTimeout: 300000,
27 | waitTimeout: 60000,
28 | verbose: true,
29 | onError: function(self, msg) {
30 | consolex.log('red', 'FATAL:' + msg);
31 | self.exit();
32 | },
33 | onTimeout: function(self, msg) {
34 | this.capture('./capture/timeout.png');
35 | consolex.log('red', 'general timeout error: ' + msg);
36 | },
37 | onStepTimeout: function(self, msg) {
38 | this.capture('./capture/timeout.png');
39 | consolex.log('red', 'step timeout error: step ' + msg);
40 | },
41 | onWaitTimeout: function(self, msg) {
42 | this.capture('./capture/timeout.png');
43 | consolex.log('red', 'wait timeout error: ' + msg);
44 | }
45 | });
46 |
47 | casper.userAgent('Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 ' + '(KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36');
48 |
49 | fileAccounts = './accounts/' + casper.cli.get(0) + '.csv';
50 |
51 | fileArticles = './articles/' + casper.cli.get(1) + '.txt';
52 |
53 | fileBacklinks = './backlinks/' + casper.cli.get(2) + '.txt';
54 |
55 | numPosts = casper.cli.get(3);
56 |
57 | console.log('\n');
58 |
59 | consolex.log('cyan', '---------------- Submission Details --------------------');
60 |
61 | consolex.log('cyan', 'Accounts file: ' + fileAccounts);
62 |
63 | consolex.log('cyan', 'Articles file: ' + fileArticles);
64 |
65 | consolex.log('cyan', 'Backlinks saved to file: ' + fileBacklinks);
66 |
67 | consolex.log('cyan', 'Number of Submissions: ' + numPosts);
68 |
69 | currentService = 0;
70 |
71 | currentStep = 0;
72 |
73 | submitArticle = {
74 | title: '',
75 | body: '',
76 | keywords: ''
77 | };
78 |
79 | services = imports.services('./settings/services.txt');
80 |
81 | indexerDetails = imports.indexers('./settings/indexers.txt');
82 |
83 | numLoops = 0;
84 |
85 | service = [];
86 |
87 | currentService = 0;
88 |
89 | for (i = _i = 0, _ref = services.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
90 | if (services[i].status.toLowerCase() === 'ok') {
91 | service[currentService] = require('./services/' + services[i].name);
92 | numLoops += service[currentService].steps.length;
93 | ++currentService;
94 | }
95 | }
96 |
97 | numLoops *= numPosts;
98 |
99 | numIndexerLoops = 0;
100 |
101 | indexers = [];
102 |
103 | indexersLogin = [];
104 |
105 | currentIndexer = 0;
106 |
107 | for (i = _j = 0, _ref1 = indexerDetails.length; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
108 | if (indexerDetails[i].status.toLowerCase() === 'ok') {
109 | indexers[currentIndexer] = require('./indexers/' + indexerDetails[i].name);
110 | indexersLogin[currentIndexer] = indexerDetails[i];
111 | numIndexerLoops += indexers[currentIndexer].steps.length;
112 | ++currentIndexer;
113 | }
114 | }
115 |
116 | console.log('------------------- Import Files -------------------------');
117 |
118 | accounts = imports.accounts(fileAccounts);
119 |
120 | articles = imports.articles(fileArticles);
121 |
122 | currentStep = 0;
123 |
124 | randomAccount = {
125 | username: '',
126 | password: '',
127 | site: ''
128 | };
129 |
130 | submitArticle = {
131 | title: '',
132 | body: '',
133 | keywords: ''
134 | };
135 |
136 | backlinksList = '';
137 |
138 | skipService = function() {
139 | console.log('Skipping ' + service[currentService].name);
140 | ++currentService;
141 | return currentStep = 0;
142 | };
143 |
144 | errorMsg = function() {
145 | console.log('Failed step ' + currentStep);
146 | console.log('Check error.png file');
147 | return skipService();
148 | };
149 |
150 | currentSubmission = 0;
151 |
152 | currentService = 0;
153 |
154 | currentIndexer = 0;
155 |
156 | currentIndexerStep = 0;
157 |
158 | casper.doStep = function(objStep, serviceName) {
159 | var str, submitURL, tempObj, tempURL;
160 | this.echo('Step: ' + currentStep);
161 | if (objStep.command === 'create') {
162 | this.echo('Creating article...');
163 | submitArticle = spinner.getArticle(articles, objStep.micro, objStep.noHTML);
164 | randomAccount = spinner.getAccount(accounts, serviceName);
165 | str = '-------------- Submit to ' + serviceName + ' ----------------';
166 | consolex.log('yellow', str);
167 | } else if (objStep.command === 'open') {
168 | this.echo('Opening url ' + objStep.url + '...');
169 | this.open(objStep.url).then(function() {
170 | this.capture('./capture/capture' + currentStep + '.png');
171 | if (objStep.confirm) {
172 | return this.waitForSelector(objStep.confirm, function() {
173 | return this.echo('Opened url');
174 | }, function() {
175 | errorMsg();
176 | return this.capture('./capture/error.png');
177 | });
178 | } else if (objStep.confirmtxt) {
179 | return this.waitForText(objStep.confirmtxt, function() {
180 | return this.echo('Opened url');
181 | }, function() {
182 | errorMsg();
183 | return this.capture('./capture/error.png');
184 | });
185 | }
186 | });
187 | } else if (objStep.command === 'open-site') {
188 | tempURL = objStep.begin + randomAccount.site + objStep.end;
189 | this.echo('Opening url ' + tempURL + '...');
190 | this.open(tempURL).then(function() {
191 | this.capture('./capture/capture' + currentStep + '.png');
192 | if (objStep.confirm) {
193 | return this.waitForSelector(objStep.confirm, function() {
194 | return this.echo('Opened url');
195 | }, function() {
196 | errorMsg();
197 | return this.capture('./capture/error.png');
198 | });
199 | } else if (objStep.confirmtxt) {
200 | return this.waitForText(objStep.confirmtxt, function() {
201 | return this.echo('Opened url');
202 | }, function() {
203 | errorMsg();
204 | return this.capture('./capture/error.png');
205 | });
206 | }
207 | });
208 | } else if (objStep.command === 'login') {
209 | if (randomAccount.username === 'no accounts') {
210 | this.echo('No ' + serviceName + ' accounts!');
211 | skipService();
212 | } else {
213 | this.echo('Logging in: ' + randomAccount.username + '...');
214 | tempObj = {
215 | formElem: objStep.form,
216 | nameElem: objStep.username,
217 | pwdElem: objStep.password,
218 | name: randomAccount.username,
219 | pwd: randomAccount.password,
220 | submit: objStep.submit
221 | };
222 | this.evaluate((function(s) {
223 | document.querySelector(s.nameElem).value = s.name;
224 | document.querySelector(s.pwdElem).value = s.pwd;
225 | if (s.submit) {
226 | document.querySelector(s.formElem).submit();
227 | }
228 | }), tempObj);
229 | this.capture('./capture/capture' + currentStep + '.png');
230 | this.echo('Waiting for login confirmation...');
231 | if (objStep.submit) {
232 | this.waitForSelector(objStep.confirm, function() {
233 | return this.echo('Login success.');
234 | }, function() {
235 | errorMsg();
236 | return this.capture('./capture/error.png');
237 | });
238 | } else if (objStep.confirmtxt) {
239 | this.waitForText(objStep.confirmtxt, function() {
240 | return this.echo('Login success.');
241 | }, function() {
242 | errorMsg();
243 | return this.capture('./capture/error.png');
244 | });
245 | }
246 | }
247 | } else if (objStep.command === 'login-indexer') {
248 | this.capture('./capture/indexer0.png');
249 | if (indexersLogin.length === 0) {
250 | this.echo('No indexer accounts set up!');
251 | } else {
252 | this.echo('Logging in: ' + indexersLogin[currentIndexer].username + '...');
253 | tempObj = {
254 | formElem: objStep.form,
255 | nameElem: objStep.username,
256 | pwdElem: objStep.password,
257 | name: indexersLogin[currentIndexer].username,
258 | pwd: indexersLogin[currentIndexer].password,
259 | submit: objStep.submit
260 | };
261 | this.evaluate((function(s) {
262 | document.querySelector(s.nameElem).value = s.name;
263 | document.querySelector(s.pwdElem).value = s.pwd;
264 | if (s.submit) {
265 | document.querySelector(s.formElem).submit();
266 | }
267 | }), tempObj);
268 | this.capture('./capture/indexer1.png');
269 | this.echo('Waiting for login confirmation...');
270 | if (objStep.confirm) {
271 | this.waitForSelector(objStep.confirm, function() {
272 | return this.echo('Login success.');
273 | }, function() {
274 | this.capture('./capture/error.png');
275 | return errorMsg();
276 | });
277 | } else if (objStep.confirmtxt) {
278 | this.waitForText(objStep.confirmtxt, function() {
279 | return this.echo('Login success.');
280 | }, function() {
281 | this.capture('./capture/error.png');
282 | return errorMsg();
283 | });
284 | }
285 | }
286 | }
287 | if (objStep.command === 'click') {
288 | if (objStep.selector) {
289 | tempObj = objStep.selector;
290 | } else if (objStep.xpath) {
291 | tempObj = {
292 | type: 'xpath',
293 | path: objStep.xpath
294 | };
295 | }
296 | if (this.exists(tempObj)) {
297 | this.click(tempObj);
298 | this.echo('Clicked on DOM selector');
299 | if (objStep.confirm) {
300 | this.waitForSelector(objStep.confirm, function() {
301 | return this.echo('Found confirm selector.');
302 | }, function() {
303 | this.echo('Confirm DOM selector not found', 'ERROR');
304 | errorMsg();
305 | return this.capture('./capture/error.png');
306 | });
307 | }
308 | if (objStep.confirmtxt) {
309 | this.waitForText(objStep.confirmtxt, function() {
310 | return this.echo('Found confirm text: ' + objStep.confirmtxt);
311 | }, function() {
312 | this.echo('Confirm text' + objStep.confirmtxt + 'not found', 'ERROR');
313 | errorMsg();
314 | return this.capture('./capture/error.png');
315 | });
316 | }
317 | } else {
318 | this.echo('DOM selector not found', 'ERROR');
319 | errorMsg();
320 | }
321 | }
322 | if (objStep.command === 'wait') {
323 | this.echo('Waiting for ' + objStep.value + ' ms');
324 | this.wait(objStep.value, function() {
325 | this.echo('Finished wait time.');
326 | });
327 | }
328 | if (objStep.command === 'title') {
329 | if (objStep.selector) {
330 | tempObj = objStep.selector;
331 | } else if (objStep.xpath) {
332 | tempObj = {
333 | type: 'xpath',
334 | path: objStep.xpath
335 | };
336 | }
337 | if (this.exists(tempObj)) {
338 | this.sendKeys(tempObj, submitArticle.title);
339 | this.echo('Entered title');
340 | } else {
341 | this.echo('Input field not found', 'ERROR');
342 | errorMsg();
343 | }
344 | }
345 | if (objStep.command === 'backlinks') {
346 | if (objStep.selector) {
347 | tempObj = objStep.selector;
348 | } else if (objStep.xpath) {
349 | tempObj = {
350 | type: 'xpath',
351 | path: objStep.xpath
352 | };
353 | }
354 | if (this.exists(tempObj)) {
355 | this.sendKeys(tempObj, backlinksList);
356 | this.echo('Entered backlinks list');
357 | } else {
358 | this.echo('Input field not found', 'ERROR');
359 | errorMsg();
360 | }
361 | }
362 | if (objStep.command === 'body') {
363 | if (objStep.selector) {
364 | tempObj = objStep.selector;
365 | } else if (objStep.xpath) {
366 | tempObj = {
367 | type: 'xpath',
368 | path: objStep.xpath
369 | };
370 | }
371 | if (this.exists(tempObj)) {
372 | this.sendKeys(tempObj, submitArticle.body);
373 | this.echo('Entered body');
374 | } else {
375 | this.echo('Input field not found', 'ERROR');
376 | errorMsg();
377 | }
378 | }
379 | if (objStep.command === 'save-href') {
380 | if (objStep.selector) {
381 | tempObj = objStep.selector;
382 | } else if (objStep.xpath) {
383 | tempObj = {
384 | type: 'xpath',
385 | path: objStep.xpath
386 | };
387 | }
388 | if (this.exists(tempObj)) {
389 | submitURL = this.getElementAttribute(tempObj, 'href');
390 | backlinksList += submitURL + '\n';
391 | consolex.log('cyan', 'Submitted post to URL: ' + submitURL);
392 | try {
393 | fs.write(fileBacklinks, submitURL, 'a');
394 | fs.write(fileBacklinks, '\n', 'a');
395 | } catch (e) {
396 | this.echo(e);
397 | }
398 | return this.echo('Saved backlink to ' + fileBacklinks);
399 | } else {
400 | this.echo('DOM selector not found' + tempObj, 'ERROR');
401 | return errorMsg();
402 | }
403 | }
404 | };
405 |
406 | casper.start();
407 |
408 | casper.repeat(numLoops, function() {
409 | return this.then(function() {
410 | var objStep, serviceName;
411 | if (currentService >= service.length) {
412 | ++currentSubmission;
413 | currentService = 0;
414 | currentStep = 0;
415 | }
416 | if (currentSubmission < numPosts) {
417 | serviceName = service[currentService].name;
418 | objStep = service[currentService].steps[currentStep];
419 | this.doStep(objStep, serviceName);
420 | this.then(function() {
421 | this.capture('./capture/capture' + currentStep + '.png');
422 | ++currentStep;
423 | if (currentStep === service[currentService].steps.length) {
424 | serviceName = service[currentService].name;
425 | consolex.log('green', 'Completed submit to ' + serviceName + '\n');
426 | ++currentService;
427 | return currentStep = 0;
428 | }
429 | });
430 | return;
431 | }
432 | });
433 | });
434 |
435 | casper.then(function() {
436 | return consolex.log('blue', 'Submitting links to indexeing services');
437 | });
438 |
439 | casper.repeat(numIndexerLoops, function() {
440 | return this.then(function() {
441 | var objStep, serviceName;
442 | if (currentIndexer < indexers.length) {
443 | serviceName = indexers[currentIndexer].name;
444 | objStep = indexers[currentIndexer].steps[currentIndexerStep];
445 | this.doStep(objStep, serviceName);
446 | ++currentIndexerStep;
447 | if (currentIndexerStep === indexers[currentIndexer].steps.length) {
448 | ++currentIndexer;
449 | return currentIndexerStep = 0;
450 | }
451 | }
452 | });
453 | });
454 |
455 | casper.run(function() {
456 | consolex.log('green', 'Finished all submissions.');
457 | this.echo('Press ctrl C to exit');
458 | this.exit(0);
459 | this.bypass(1);
460 | });
461 |
462 | }).call(this);
463 |
--------------------------------------------------------------------------------