.gitignore000066400000000000000000000003301516102652500130450ustar00rootroot00000000000000/build /node_modules /*.log .idea/workspace.xml .idea/tasks.xml .idea/profiles_settings.xml .idea/inspectionProfiles/Project_Default.xml .idea/inspectionProfiles/profiles_settings.xml node_modules/.yarn-integrity .npmignore000066400000000000000000000002221516102652500130540ustar00rootroot00000000000000/.idea /artifacts /build /test /node_modules /*.iml /*.ipr /*.iws /.travis.yml /.scrutinizer.yml /Gruntfile.js /*.lock *.log /corifeus-boot.json .travis.yml000066400000000000000000000014571516102652500132010ustar00rootroot00000000000000language: node_js cache: npm: false node_js: - lts/* before_script: - npm install -g grunt-cli npm env: global: secure: QxlWHAw85RgRhOuzVary1TEtebr68iSFzsVUJ4Xdsv0B9uLLCcxT2rgj//hNaqoRALNVFs2v6FuwXLqmk+rp394w68883AN+T3zY2qy83plqlVPXHd95oKsPFhJ0lv5FvuVBxzjrNR1t/rKSOxpuh2IqBqWPxYbrlNQ3kVnEB9jaaRQR7n7CMVYHJKYm2+RqlA8O4tVTUIoy2Vqm0fJ+q3uorz71m1U5vy6BD216PujvMGDDOnJR07QZxijsQKdDm03V4dKRLik1Aomb7N6uzzlMBaySwBMMJBRo5Lbb6dVWy9NT2wJk+HvdM9bwD/648qMMDoDBo8FNAfbexqTF/ZiSxCKGt+uQWxpEzOUOf18+hJay+ejhyi8D0D6USyrRK00HT8iW6R7fHmUM9QFOnZMLB2Tg6CHQol2qiIpJbLbp88sjO6VDcJdkDDmyvjWmiF2ce5g9/cIbRCr+obMIczoHMVfs3ZCSjonKPNklVaOcc5soITSVIJg9pdAo3AIU2SzUYHMLkiGAlyxdEXKYejXqNdLvDxkYXaKyyhaZw2qNgai4BVMe5HTRV4WUkrLUUBaDYZnOqDO0vn97t4cLLHf86C1Xx1D4h8yceq0NFAXtNhC5v/o8e82GjXmk7uk3ngW2DCyJQF5KqVh5U7uAFMHI/MneWvp+DurUp2VTblM= Gruntfile.js000066400000000000000000000004541516102652500133610ustar00rootroot00000000000000module.exports = (grunt) => { const builder = require(`corifeus-builder`); const loader = new builder.loader(grunt); loader.js({ replacer: { type: 'p3x', npmio: true, }, }); grunt.registerTask('default', builder.config.task.build.js); };LICENSE000066400000000000000000000023251516102652500120700ustar00rootroot00000000000000 @license p3x-freenom v2020.10.114 🌐 Freenom API - Promise and auto renew expiring domains https://corifeus.com/freenom Copyright (c) 2020 Patrik Laszlo / P3X / Corifeus and contributors. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. README.md000066400000000000000000000105441516102652500123440ustar00rootroot00000000000000[//]: #@corifeus-header [![NPM](https://nodei.co/npm/p3x-freenom.png?downloads=true&downloadRank=true)](https://www.npmjs.com/package/p3x-freenom/) [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://paypal.me/patrikx3) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) [![Corifeus @ Facebook](https://img.shields.io/badge/Facebook-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) [![Build Status](https://api.travis-ci.com/patrikx3/freenom.svg?branch=master)](https://travis-ci.com/patrikx3/freenom) [![Uptime Robot ratio (30 days)](https://img.shields.io/uptimerobot/ratio/m780749701-41bcade28c1ea8154eda7cca.svg)](https://uptimerobot.patrikx3.com/) # 🌐 Freenom API - Promise and auto renew expiring domains v2020.10.114 **Bugs are evident™ - MATRIX️** ### NodeJs LTS Version Requirement ```txt >=12.13.0 ``` ### Built on NodeJs ```txt v12.19.0 ``` The ```async``` and ```await``` keywords are required. Only the latest LTS variant is supported. Install NodeJs: https://nodejs.org/en/download/package-manager/ # Description [//]: #@corifeus-header:end ## To be able to register and renew FREE DOMAINS Before, we were able to register and renew with free domains, but by now, these functions are allowed and working ONLY with PAID domains. ### Some links http://www.freenom.com/en/resellers.html http://www.freenom.com/en/termsandconditions.html ## API http://www.freenom.com/en/freenom-api.html I am using these only right now. So no other functions but very easy to add in and Promise based. ```js const Freenom = require('p3x-freenom'); const freenom = await Freenom({ email: 'p3x@corifeus', password: 'password', }); await freenom.service.ping(); await freenom.domain.search({ domainname: 'patrikx3.com', domaintype: 'FREE' }) await freenom.domain.delete({ domainname: 'random.tk')); await freenom.domain.register({ domainname: [ 'random.tk', 'random1.tk', 'random2.tk', ], domaintype: 'FREE', period: '1Y', nameserver: [ 'ns1.ns.tk', 'ns2.ns.tk', ] }) await freenom.domain.delete, { domainname: domains }) // if you have no domain in the list, instead of // giving an empty list, it shows and error!!! // so make sure you have one in the domain list // because freenom.domain.expiringRenew will of course // throw an error as well!!! await freenom.domain.list() ``` # The good extra functions It automatically renew the free domains (it checks if it is within 14 days expiry and then does it). ```js // just a helper, you don't relly need it const renewable = await freenom.domain.expiring({ expiry: '60 days', }); // the magic await freenom.domain.expiringRenew({ period: '12M', }) ``` [//]: #@corifeus-footer --- 🙏 This is an open-source project. Star this repository, if you like it, or even donate to maintain the servers and the development. Thank you so much! Possible, this server, rarely, is down, please, hang on for 15-30 minutes and the server will be back up. All my domains ([patrikx3.com](https://patrikx3.com) and [corifeus.com](https://corifeus.com)) could have minor errors, since I am developing in my free time. However, it is usually stable. **Note about versioning:** Versions are cut in Major.Minor.Patch schema. Major is always the current year. Minor is either 4 (January - June) or 10 (July - December). Patch is incremental by every build. If there is a breaking change, it should be noted in the readme. --- [**P3X-FREENOM**](https://corifeus.com/freenom) Build v2020.10.114 [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QZVM4V6HVZJW6) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) [![Like Corifeus @ Facebook](https://img.shields.io/badge/LIKE-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) ## P3X Sponsor [IntelliJ - The most intelligent Java IDE](https://www.jetbrains.com/?from=patrikx3) [![JetBrains](https://cdn.corifeus.com/assets/svg/jetbrains-logo.svg)](https://www.jetbrains.com/?from=patrikx3) [//]: #@corifeus-footer:end freenom.iml000066400000000000000000000005171516102652500132220ustar00rootroot00000000000000 package.json000066400000000000000000000021061516102652500133460ustar00rootroot00000000000000{ "name": "p3x-freenom", "version": "2020.10.114", "corifeus": { "prefix": "p3x-", "publish": true, "type": "p3x", "code": "Mafia", "nodejs": "v12.19.0", "opencollective": false, "reponame": "freenom", "build": true }, "license": "MIT", "description": "🌐 Freenom API - Promise and auto renew expiring domains", "main": "src/index.js", "directories": { "test": "test" }, "scripts": { "test": "grunt" }, "repository": { "type": "git", "url": "git+https://github.com/patrikx3/freenom.git" }, "keywords": [ "freenom", "promise", "api" ], "author": "Patrik Laszlo ", "bugs": { "url": "https://github.com/patrikx3/freenom/issues" }, "homepage": "https://corifeus.com/freenom", "devDependencies": { "corifeus-builder": "^2020.10.118" }, "dependencies": { "corifeus-utils": "^2020.10.115" }, "engines": { "node": ">=12.13.0" } }src/000077500000000000000000000000001516102652500116505ustar00rootroot00000000000000src/endpoint/000077500000000000000000000000001516102652500134705ustar00rootroot00000000000000src/endpoint/v2/000077500000000000000000000000001516102652500140175ustar00rootroot00000000000000src/endpoint/v2/domain.js000066400000000000000000000022641516102652500156300ustar00rootroot00000000000000const search = (exec) => { return async (body) => { return await exec({ service: 'domain', func: 'search', body: body }); } } const register = (exec) => { return async (body) => { return await exec({ service: 'domain', func: 'register', method: 'POST', body: body }) } } const _delete = (exec) => { return async (body) => { return await exec({ service: 'domain', func: 'delete', method: 'DELETE', body: body }) } } const list = (exec) => { return async (body) => { return await exec({ service: 'domain', func: 'list', method: 'GET', body: body, }) } } const renew = (exec) => { return async (body) => { return await exec({ service: 'domain', func: 'renew', method: 'POST', body: body, }) } } module.exports.list = list; module.exports.search = search; module.exports.register = register; module.exports.delete = _delete module.exports.renew = renewsrc/endpoint/v2/nameserver.js000066400000000000000000000013251516102652500165250ustar00rootroot00000000000000const list = (exec) => { return async (body) => { return await exec({ service: 'nameserver', func: 'list', body: body }); } } const _delete = (exec) => { return async (body) => { return await exec({ service: 'nameserver', func: 'delete', method: 'DELETE', body: body }) } } const register = (exec) => { return async (body) => { return await exec({ service: 'nameserver', func: 'register', method: 'PUT', body: body }) } } module.exports.list = list; module.exports.delete = _delete; module.exports.register = register;src/endpoint/v2/service.js000066400000000000000000000001451516102652500160150ustar00rootroot00000000000000module.exports.ping = (exec) => { return async () => { return await exec('ping'); } }src/index.js000066400000000000000000000056171516102652500133260ustar00rootroot00000000000000const utils = require('corifeus-utils'); const querystring = require('querystring'); const mz = require('mz'); const path = require('path'); // http://www.freenom.com/en/freenom-api.html module.exports = async function (options) { let { email, password, debug, version } = options; if (!version) { version = 'v2'; } const baseUrl = 'https://api.freenom.com/v2'; const endpointDir = `${__dirname}/endpoint/${version}`; const endpoints = await mz.fs.readdir(endpointDir) const endpointServices = {}; endpoints.forEach((endpoint) => { const requireName = path.basename(endpoint, '.js'); // console.log(requireName); endpointServices[requireName] = require(`${endpointDir}/${endpoint}`); }) if (debug) { console.log('----------------------------') console.log('endpointService') console.log(endpointServices) console.log(); } return new function(options) { if (debug) { console.log('----------------------------') console.log('Settings') console.log(this) console.log(); } const exec = async (options) => { if (typeof options === 'string') { options = { func: options, } } let { service, func, method, body } = options; service = service || 'service'; method = method || "GET"; body = body || {}; body.email = email; body.password = password; if (debug && !body.hasOwnProperty('test_mode')) { body.test_mode = 1; } let url = `${baseUrl}/${service}/${func}`; Object.keys(body).forEach(key => { if (body[key] === undefined) { delete body[key]; } }) url += '?' + querystring.stringify(body); if (debug) { console.log('----------------------------'); console.log('Request') console.log(method, url, body) } const response = await utils.http.request({ url: url, method: method, }) return response; }; const service = require('./service');; Object.keys(endpointServices).forEach((endpointService) => { service[endpointService] = service[endpointService] || {}; Object.keys(endpointServices[endpointService]).forEach(endpointServiceMethod => { service[endpointService][endpointServiceMethod] = endpointServices[endpointService][endpointServiceMethod](exec); }) }) if (debug) { console.log('----------------------------'); console.log('service') console.log(service) } return service; } }src/lib.js000066400000000000000000000004561516102652500127610ustar00rootroot00000000000000module.exports.stringEightNumbersToDate = (string) => { const year = parseInt(string.substring(0, 4)); const month = parseInt(string.substr(4, 2)); const day = parseInt(string.substr(6, 2)); //console.log(string, year, month, day); return new Date(Date.UTC( year, month -1, day )) }src/service.js000066400000000000000000000050631516102652500136520ustar00rootroot00000000000000const utils = require('corifeus-utils'); const lib = require('./lib'); const service = { domain: {}, }; service.domain.active = async (options) => { const response = await service.domain.list(options); /* { status: 'ACTIVE', expirationdate: '20170729', registrationdate: '20160729', domaintype: 'PAID', domainname: 'corifeus.com' }, */ const domains = {}; const generateDate = (string) => { const year = parseInt(string.substring(0, 4)); const month = parseInt(string.substr(4, 2)); const day = parseInt(string.substr(6, 2)); //console.log(string, year, month, day); return new Date(Date.UTC( year, month -1, day )) } response.body.domain.forEach((domain) => { if (domain.status !== 'ACTIVE') { return; } domain.registration = lib.stringEightNumbersToDate(domain.registrationdate); domain.expiration = lib.stringEightNumbersToDate(domain.expirationdate); delete domain.registrationdate; delete domain.expirationdate; if (!domains.hasOwnProperty(domain.domainname)) { domains[domain.domainname] = domain; } }) return Object.values(domains); } service.domain.expiring = async(options) => { let expiry = '14 days'; if (options.hasOwnProperty('expiry')) { expiry = options.expiry; delete options.expiry; } const maxExpiry = utils.time.span(expiry); let active = await service.domain.active(options); active = active.map((domain) => { domain.expiry = utils.time.verbose( domain.expiration.getTime(), domain.registration.getTime() ) return domain; }) return active.filter((domain) => { // console.log(maxExpiry, domain.expiry.leftMs); // console.log(utils.time.msParse(maxExpiry), utils.time.msParse(domain.expiry.leftMs)); return domain.expiry.leftMs < maxExpiry; }).map((domain) => { const expiry = domain.expiry; delete domain.expiry; domain.left = expiry.left; domain.leftMs = expiry.leftMs; return domain; }); } service.domain.expiringRenew = async(options) => { const renewable = await service.domain.expiring(options); const result = {}; await renewable.forEachAsync(async (domain) => { const response = await service.domain.renew(Object.assign({ domainname: domain.domainname, }, options)); result[domain.domainname] = response.body; }) return result; } module.exports = service;test/000077500000000000000000000000001516102652500120405ustar00rootroot00000000000000test/scripts/000077500000000000000000000000001516102652500135275ustar00rootroot00000000000000test/scripts/glue.js000077500000000000000000000030551516102652500150270ustar00rootroot00000000000000#!/usr/bin/env node const Freenom = require('../../src'); const utils = require('corifeus-utils'); const lib = require('./lib'); const start = async() => { const freenom = await lib.start(); /* await lib.test(freenom.nameserver.delete, { domainname: 'namesystem.tk', hostname: 'IPV6.NAMESYSTEM.TK', }) */ const ns = await lib.test(freenom.nameserver.list, { domainname: 'namesystem.tk' }); /* const response = await utils.http.request({ url: 'https://v4.ident.me/.json', localAddress: '192.168.81.2', }) let ip = response.body.address; ip = '86.101.220.140'; const ns = await lib.test(freenom.nameserver.list, { domainname: 'namesystem.tk' }); await ns.body.nameserver.forEachAsync(async(ns) => { if (ns.ipaddress !== ip) { await lib.test(freenom.nameserver.register, { domainname: ns.domainname, hostname: ns.hostname, ipaddress: ip, test_mode: undefined, }) } }) */ /* const renewable = await lib.test(freenom.domain.expiring, { expiry: '60 days', test_mode: undefined }); const result = {}; await renewable.forEachAsync(async (domain) => { const response = await lib.test(freenom.domain.renew, { domainname: domain.domainname, test_mode: undefined, period: '1Y' }); result[domain.domainname] = response.body; }) console.log(result); */ } start();test/scripts/lib.js000066400000000000000000000013041516102652500146310ustar00rootroot00000000000000const Freenom = require('../../src'); const utils = require('corifeus-utils'); module.exports.start = async() => { const freenom = await Freenom({ email: 'alabard@gmail.com', password: process.argv[2], debug: true, }); return freenom } module.exports.test = async(func, options) => { console.log('------------------------------------------'); if (options !== undefined) { console.log('Request', options) console.log(); } const result = await func(options); if (result.hasOwnProperty('body')) { console.log('Response', result.body); console.log(); } else { console.log(result); } return result; } test/scripts/test.js000077500000000000000000000064531516102652500150570ustar00rootroot00000000000000#!/usr/bin/env node const Freenom = require('../../src'); const utils = require('corifeus-utils'); const lib = require('./lib'); const start = async() => { try { const domainTest = 'p3x-' + await utils.random.lower(6) + '.tk' const freenom = await lib.start(); /* await lib.test(freenom.service.ping) await lib.test(freenom.domain.search, { domainname: domainTest, domaintype: 'FREE' }); try { await lib.test(freenom.domain.delete, { domainname: domainTest }) } catch(e) { console.error('delete domain', e) } */ const domains = [ // prefix + await utils.random.lower(6) + '.tk', // prefix + await utils.random.lower(6) + '.tk', // prefix + await utils.random.lower(6) + '.tk', domainTest ]; const domaintype = 'FREE'; const period = '1Y'; /* await lib.test(freenom.domain.search, { domainname: domains, domaintype: domaintype, }) */ await lib.test(freenom.domain.register, { domainname: domains, domaintype: domaintype, period: '3M', owner_id: 'patrikx3', nameserver: [ 'ns1.afraid.org', 'ns2.afraid.org', 'ns3.afraid.org', 'ns4.afraid.org', ] }) await lib.test(freenom.domain.delete, { domainname: domains }) // await lib.test(freenom.domain.delete, { domainname: 'p3x-ns.tk', test_mode: undefined }) await lib.test(freenom.domain.active, { test_mode: undefined }); await lib.test(freenom.domain.expiringRenew, { expiry: '60 days', // test_mode: undefined, //period: '1Y', }) const ns = await lib.test(freenom.nameserver.list, { domainname: domainTest }); /* const response = await utils.http.request({ url: 'https://v4.ident.me/.json', localAddress: '192.168.81.2', }) let ip = response.body.address; ip = '86.101.220.140'; const ns = await lib.test(freenom.nameserver.list, { domainname: 'namesystem.tk' }); await ns.body.nameserver.forEachAsync(async(ns) => { if (ns.ipaddress !== ip) { await lib.test(freenom.nameserver.register, { domainname: ns.domainname, hostname: ns.hostname, ipaddress: ip, test_mode: undefined, }) } }) */ const renewable = await lib.test(freenom.domain.expiring, { expiry: '60 days', test_mode: undefined }); const result = {}; await renewable.forEachAsync(async (domain) => { const response = await lib.test(freenom.domain.renew, { domainname: domain.domainname, test_mode: undefined, period: '1Y' }); result[domain.domainname] = response.body; }) console.log(result); } catch(e) { console.error(e) } } start();