diff --git a/.env b/.env
index f87d42da03..26270e769c 100644
--- a/.env
+++ b/.env
@@ -1,4 +1,5 @@
-NC_USER=xxx
-NC_API_KEY=xxxxxxxxxxxxxxx
-NC_DOMAIN=domain.com
-IP_ADDRESS=100.100.100.100
+DOMAIN_USER=username
+DOMAIN_API_KEY=apikey
+DOMAIN_API_HOST=api-example.com
+DOMAIN_API_PORT=2087
+DOMAIN_DOMAIN=example.com
diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml
new file mode 100644
index 0000000000..736201bc81
--- /dev/null
+++ b/.github/workflows/bot.yml
@@ -0,0 +1,23 @@
+name: Helper
+
+on:
+ pull_request_target:
+ types:
+ - closed
+
+jobs:
+ instructions:
+ name: instructions
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Comment
+ if: github.event_name == 'pull_request_target' && github.event.action == 'closed' && github.event.pull_request.merged == true
+ uses: actions/github-script@v3
+ with:
+ github-token: ${{secrets.GITHUB_TOKEN}}
+ script: |
+ const { hasLabel } = require(`${process.env.GITHUB_WORKSPACE}/scripts/action-utils.js`);
+ const { instructions } = require(`${process.env.GITHUB_WORKSPACE}/scripts/reply.js`);
+ if (hasLabel(context, 'domain'))
+ await instructions(context, github);
diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index e8519241f0..6ff9fe1cd8 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -8,7 +8,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - uses: borales/actions-yarn@v2.0.0
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ fetch-depth: 0
+ - name: Installing dependencies
+ uses: borales/actions-yarn@v2.0.0
with:
cmd: install
- name: Running tests
diff --git a/.github/workflows/publish-records.yml b/.github/workflows/publish-records.yml
index 17bb7bdc0a..e4b02e0117 100644
--- a/.github/workflows/publish-records.yml
+++ b/.github/workflows/publish-records.yml
@@ -8,12 +8,13 @@ jobs:
publish:
runs-on: ubuntu-latest
env:
- CI: '1'
+ CI: 1
ENV: production
- NC_USER: ${{ secrets.NC_USER }}
- NC_API_KEY: ${{ secrets.NC_API_KEY }}
- NC_DOMAIN: ${{ secrets.NC_DOMAIN }}
- IP_ADDRESS: ${{ secrets.IP_ADDRESS }}
+ DOMAIN_USER: ${{ secrets.DOMAIN_USER }}
+ DOMAIN_API_KEY: ${{ secrets.DOMAIN_API_KEY }}
+ DOMAIN_API_HOST: ${{ secrets.DOMAIN_API_HOST }}
+ DOMAIN_API_PORT: ${{ secrets.DOMAIN_API_PORT }}
+ DOMAIN_DOMAIN: ${{ secrets.DOMAIN_DOMAIN }}
steps:
- uses: actions/checkout@v2
- uses: borales/actions-yarn@v2.0.0
diff --git a/API.md b/API.md
index cd14511c20..43bc51d648 100644
--- a/API.md
+++ b/API.md
@@ -2,27 +2,28 @@
## How to register
* First you need to create a pull request with your `domains/my-domain.json` file
-* This PR will be reviewed, merged
-* The changes will take effect in less than a day after the PR gets merged
-* `Github pages` users, need to go to their repo settings page and change the domain to `your-domain.is-a.dev` after everything is done
+* This PR will be reviewed
+* The changes will take effect soon after the PR gets merged
* And that's it
-Example (for github pages) -
+### For github pages users
+* A github pages json file (with cname record and https redirection) will look something like this -
```json
{
"description": "Add some description",
- "repo": "https://github.com/user/user.github.io",
+ "repo": "https://github.com/github-username/github-username.github.io",
"owner": {
- "username": "your-github-username",
+ "username": "github-username",
"email": "any@email"
},
"record": {
- "CNAME": "user.github.io"
+ "CNAME": "github-username.github.io"
}
}
```
+* After the pull request is merged, you will see a 404 error on `your-domain.is-a.dev`. To fix this go to your github page repo's `Settings > Github pages > Custom domain` and add `your-domain.is-a.dev` in the given field
+* Check the `Enforce HTTPS` checkbox below the custom domain input
-NOTE: For github pages users, to fix the 404 you get after registering the domain, add `your-domain.is-a.dev` to your github pages repo in Settings > Github pages > Custom domain.
## Domains json file
@@ -61,12 +62,11 @@ This is a link to your website repository or your github account. This is purely
### record (required)
This is where you specify how you want to link to your server/webpage.
-Currently, only `CNAME`, `ALIAS`, `A`, `URL` record types are supported.
+Currently, only `CNAME`, `A`, `URL` record types are supported.
Here's a few different use cases for the given record types -
-* **CNAME/ALIAS**
-Replace CNAME with ALIAS for alias record type
+* **CNAME**
```json
{
"record": {
@@ -98,13 +98,3 @@ Replace CNAME with ALIAS for alias record type
}
```
-* **Force HTTPS on your CNAME (or ALIAS or A) record**
-```json
-{
- "record": {
- "CNAME": "username.github.io",
- "URL": "https://your-domain.is-a.dev"
- }
-}
-```
-
diff --git a/README.md b/README.md
index c7889bee65..fce687fbe5 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,11 @@
-
+
is-a-dev is a service that allows developers to get a sweet-looking `.is-a.dev` domain for their personal websites.
-Note: This service is currently in **beta** so expect some delays in PR merge.
+Note: This service is currently in **beta** so expect some delays in PR merge and report any issues you encounter so that the service can be improved.
+
## How do I register?
@@ -16,13 +17,14 @@ Note: This service is currently in **beta** so expect some delays in PR merge.
* That's it! Done! Now go show off your cool `.is-a.dev` domain
+
## Donations
This project is a free service for developers and will stay that way.
Donations will be greatly appreciated!
-
-
+
+
diff --git a/domains/@.json b/domains/@.json
index 52b9663653..36cd14e7be 100644
--- a/domains/@.json
+++ b/domains/@.json
@@ -1,5 +1,6 @@
{
"description": "The root domain for is-a.dev website",
+ "repo": "https://github.com/is-a-dev/is-a-dev.github.io",
"owner": {
"username": "phenax",
"email": "phenax5@gmail.com"
diff --git a/domains/aaron.json b/domains/aaron.json
new file mode 100644
index 0000000000..9778d91504
--- /dev/null
+++ b/domains/aaron.json
@@ -0,0 +1,12 @@
+{
+ "description": "Aaron's personal developer website",
+ "repo": "https://github.com/aaron-harvey",
+ "owner": {
+ "username": "aaronharvey",
+ "email": "aaron@lolsup.com"
+ },
+ "record": {
+ "CNAME": "lolsup.com",
+ "URL": "https://aaron.is-a.dev"
+ }
+}
diff --git a/domains/aashutosh.json b/domains/aashutosh.json
new file mode 100644
index 0000000000..2399d7be08
--- /dev/null
+++ b/domains/aashutosh.json
@@ -0,0 +1,11 @@
+{
+ "description": "Aashutosh Rathi's Space on Web",
+ "owner": {
+ "username": "aashutoshrathi",
+ "email": "me@aashutosh.dev"
+ },
+ "record": {
+ "CNAME": "aashutosh.dev",
+ "URL": "https://aashutosh.is-a.dev"
+ }
+}
diff --git a/domains/abhay.json b/domains/abhay.json
new file mode 100644
index 0000000000..1e722675c5
--- /dev/null
+++ b/domains/abhay.json
@@ -0,0 +1,12 @@
+{
+ "description": "Abhay's portfolio website",
+ "repo": "https://github.com/daggron/daggron.github.io",
+ "owner": {
+ "username": "Daggron",
+ "email": "returnofking04@gmail.com"
+ },
+ "record": {
+ "CNAME": "codeinator.me",
+ "URL": "https://abhay.is-a.dev"
+ }
+}
\ No newline at end of file
diff --git a/domains/abhishek.json b/domains/abhishek.json
new file mode 100644
index 0000000000..22545cd82e
--- /dev/null
+++ b/domains/abhishek.json
@@ -0,0 +1,12 @@
+{
+ "description": "Abhishek's personal website",
+ "repo": "https://github.com/nullpointxr",
+ "owner": {
+ "username": "nullpointxr",
+ "email": "abhishek.sankar.in@protonmail.com"
+ },
+ "record": {
+ "CNAME": "nullpointxr.github.io",
+ "URL": "https://abhishek.is-a.dev"
+ }
+}
diff --git a/domains/abishek.json b/domains/abishek.json
new file mode 100644
index 0000000000..3fde17249c
--- /dev/null
+++ b/domains/abishek.json
@@ -0,0 +1,12 @@
+{
+ "description": "Abishek's portfolio website",
+ "repo": "https://github.com/vj-abishek/vj-abishek.github.io",
+ "owner": {
+ "username": "vj-abishek",
+ "email": "abigosearch@gmail.com"
+ },
+ "record": {
+ "CNAME": "vj-abishek.github.io",
+ "URL": "https://abishek.is-a.dev"
+ }
+}
diff --git a/domains/adarshs.json b/domains/adarshs.json
new file mode 100644
index 0000000000..47670879bf
--- /dev/null
+++ b/domains/adarshs.json
@@ -0,0 +1,12 @@
+{
+ "description": "The portfolio of Adarsh S",
+ "repo": "https://github.com/adarshsuresh07",
+ "owner": {
+ "username": "adarshsuresh07",
+ "email": "adarshsuresh@cet.ac.in"
+ },
+ "record": {
+ "CNAME":"adarshsuresh07.github.io",
+ "URL": "https://adarshs.is-a.dev"
+ }
+}
diff --git a/domains/adrian.json b/domains/adrian.json
new file mode 100644
index 0000000000..d2873ec127
--- /dev/null
+++ b/domains/adrian.json
@@ -0,0 +1,12 @@
+{
+ "description": "The awesome portfolio site for Adrian Grimm",
+ "repo": "https://github.com/usmcamgrimm/usmcamgrimm.github.io",
+ "owner": {
+ "username": "usmcamgrimm",
+ "email": "usmcamgrimm@gmail.com"
+ },
+ "record": {
+ "CNAME": "usmcamgrimm.github.io",
+ "URL": "https://adrian.is-a.dev"
+ }
+ }
diff --git a/domains/ahsan.json b/domains/ahsan.json
new file mode 100644
index 0000000000..00b8590251
--- /dev/null
+++ b/domains/ahsan.json
@@ -0,0 +1,11 @@
+{
+ "description": "Ahsan's Personal Website",
+ "owner": {
+ "username": "aqureshi",
+ "email": "ahsan.qureshi8@gmail.com"
+ },
+ "record": {
+ "CNAME": "www.thisisahsan.com",
+ "URL": "https://ahsan.is-a.dev"
+ }
+}
diff --git a/domains/akas.json b/domains/akas.json
new file mode 100644
index 0000000000..a0ddc0f4e3
--- /dev/null
+++ b/domains/akas.json
@@ -0,0 +1,12 @@
+{
+ "description": "Akas Portfolio",
+ "repo":"https://github.com/akasrai/akasrai.github.io",
+ "owner": {
+ "username": "akasrai",
+ "email": "akasky70@gmail.com"
+ },
+ "record": {
+ "CNAME":"akasrai.github.io",
+ "URL": "https://akas.is-a.dev"
+ }
+}
\ No newline at end of file
diff --git a/domains/akash.json b/domains/akash.json
new file mode 100644
index 0000000000..0fa33a8b3c
--- /dev/null
+++ b/domains/akash.json
@@ -0,0 +1,12 @@
+{
+ "description": "Akash Santhosh is a Dev",
+ "repo": "https://github.com/akash-santhosh/is-a-dev",
+ "owner": {
+ "username": "akash-santhosh",
+ "email": "akashsanthosh@icloud.com"
+ },
+ "record": {
+ "CNAME": "akash-santhosh.github.io",
+ "URL": "https://akash.is-a.dev"
+ }
+}
diff --git a/domains/akshay-ashok.json b/domains/akshay-ashok.json
new file mode 100644
index 0000000000..132781ef9a
--- /dev/null
+++ b/domains/akshay-ashok.json
@@ -0,0 +1,12 @@
+{
+ "description": "Akshay Ashok has a is a dev domain",
+ "repo": "https://github.com/Akshay090/akshay090.github.io",
+ "owner": {
+ "username": "Akshay090",
+ "email": "aks28id@gmail.com"
+ },
+ "record": {
+ "CNAME": "akshay090.github.io",
+ "URL": "https://akshay-ashok.is-a.dev"
+ }
+}
diff --git a/domains/akshay.json b/domains/akshay.json
index 413137d46f..b5ddaa0bb3 100644
--- a/domains/akshay.json
+++ b/domains/akshay.json
@@ -1,5 +1,5 @@
{
- "description": "Akshay's personal website",
+ "description": "Akshay's portfolio website and blog",
"repo": "https://github.com/phenax/phenax.github.io",
"owner": {
"username": "phenax",
diff --git a/domains/alan.json b/domains/alan.json
new file mode 100644
index 0000000000..eb0a1bd310
--- /dev/null
+++ b/domains/alan.json
@@ -0,0 +1,12 @@
+{
+ "description": "Alan's personal developer website",
+ "repo": "https://github.com/schirrel",
+ "owner": {
+ "username": "schirrel",
+ "email": "alan@schirrel.dev"
+ },
+ "record": {
+ "CNAME": "schirrel.dev",
+ "URL": "https://alan.is-a.dev"
+ }
+}
diff --git a/domains/alestor123.json b/domains/alestor123.json
new file mode 100644
index 0000000000..b9ae0804ef
--- /dev/null
+++ b/domains/alestor123.json
@@ -0,0 +1,12 @@
+{
+ "description": "A Mortal Web Developer With Immortal Dreams",
+ "repo": "https://github.com/alestor123/alestor123.github.io",
+ "owner": {
+ "username": "alestor123",
+ "email": "alestoraldous@gmail.com"
+ },
+ "record": {
+ "CNAME": "alestor123.github.io",
+ "URL": "https://alestor123.is-a.dev"
+ }
+}
diff --git a/domains/alexander.json b/domains/alexander.json
new file mode 100644
index 0000000000..43758f6d18
--- /dev/null
+++ b/domains/alexander.json
@@ -0,0 +1,12 @@
+{
+ "description": "Alexander's personal website",
+ "repo": "https://github.com/amatzen",
+ "owner": {
+ "username": "amatzen",
+ "email": "alexander@alexander.dk"
+ },
+ "record": {
+ "CNAME": "alexander.dk",
+ "URL": "https://alexander.is-a.dev"
+ }
+}
diff --git a/domains/alexjoseph.json b/domains/alexjoseph.json
new file mode 100644
index 0000000000..01c7cc49e0
--- /dev/null
+++ b/domains/alexjoseph.json
@@ -0,0 +1,12 @@
+{
+ "description": "This is my first githib page",
+ "repo": "https://github.com/alexkjoseph/alexkjoseph.github.io",
+ "owner": {
+ "username": "alexkjoseph",
+ "email": "aj71563@gmail.com"
+ },
+ "record": {
+ "CNAME": "alexkjoseph.github.io",
+ "URL": "https://alexjoseph.is-a.dev"
+ }
+}
diff --git a/domains/alexlykesas.json b/domains/alexlykesas.json
new file mode 100644
index 0000000000..3cf45f5d06
--- /dev/null
+++ b/domains/alexlykesas.json
@@ -0,0 +1,11 @@
+{
+ "description": "Alex Lykesas's personal developer website",
+ "repo": "https://github.com/Alexookah/alexlykesas.com",
+ "owner": {
+ "username": "alexookah",
+ "email": "alexlykesas@gmail.com"
+ },
+ "record": {
+ "URL": "https://alexlykesas.com"
+ }
+}
diff --git a/domains/allan.json b/domains/allan.json
new file mode 100644
index 0000000000..6ca03fa35b
--- /dev/null
+++ b/domains/allan.json
@@ -0,0 +1,12 @@
+{
+ "description": "Allan's personal website",
+ "repo": "https://github.com/abarriel",
+ "owner": {
+ "username": "abarriel",
+ "email": "abarriel@student.42.fr"
+ },
+ "record": {
+ "CNAME": "abarriel.github.io",
+ "URL": "https://allan.is-a.dev"
+ }
+}
diff --git a/domains/andrew.json b/domains/andrew.json
new file mode 100644
index 0000000000..ea141e4aed
--- /dev/null
+++ b/domains/andrew.json
@@ -0,0 +1,12 @@
+{
+ "description": "Andrew Nguyen's portfolio",
+ "repo": "https://github.com/andrewnt219/andrewnt219.github.io",
+ "owner": {
+ "username": "andrewnt219",
+ "email": "hey@andrewnt.dev"
+ },
+ "record": {
+ "CNAME": "andrewnt219.github.io",
+ "URL": "https://andrew.is-a.dev"
+ }
+}
diff --git a/domains/andros.json b/domains/andros.json
new file mode 100644
index 0000000000..8d17a744f0
--- /dev/null
+++ b/domains/andros.json
@@ -0,0 +1,12 @@
+{
+ "description": "Andros's personal developer website",
+ "repo": "https://github.com/tanrax",
+ "owner": {
+ "username": "Andros Fenollosa Hurtado",
+ "email": "",
+ "twitter": "@androsfenollosa"
+ },
+ "record": {
+ "URL": "https://programadorwebvalencia.com/"
+ }
+}
diff --git a/domains/anoop.json b/domains/anoop.json
new file mode 100644
index 0000000000..53c1c378c9
--- /dev/null
+++ b/domains/anoop.json
@@ -0,0 +1,12 @@
+{
+ "description": "Anoop's blog",
+ "repo": "https://gitlab.com/anoopmsivadas/anoopmsivadas.gitlab.io",
+ "owner": {
+ "username": "anoopmsivadas",
+ "email": "anoopms@disroot.org"
+ },
+ "record": {
+ "CNAME": "anoopmsivadas.gitlab.io",
+ "URL": "https://anoop.is-a.dev"
+ }
+}
diff --git a/domains/anthony.json b/domains/anthony.json
new file mode 100644
index 0000000000..76eace3753
--- /dev/null
+++ b/domains/anthony.json
@@ -0,0 +1,11 @@
+{
+ "description": "Anthony's personal developer website",
+ "owner": {
+ "username": "hubsta",
+ "email": "admin@thehubble.com.au"
+ },
+ "record": {
+ "CNAME": "brisbaneweb.dev",
+ "URL": "https://anthony.is-a.dev"
+ }
+}
diff --git a/domains/arya.json b/domains/arya.json
new file mode 100644
index 0000000000..7510a71e23
--- /dev/null
+++ b/domains/arya.json
@@ -0,0 +1,12 @@
+{
+ "description": "Arya Vinodan's Website",
+ "repo": "https://github.com/aryavinodan",
+ "owner": {
+ "username": "aryavinodan",
+ "email": "aryavinodan2000@gmail.com"
+ },
+ "record": {
+ "CNAME": "aryavinodan2000.github.io",
+ "URL": "https://arya.is-a.dev"
+ }
+}
diff --git a/domains/asad-khan.json b/domains/asad-khan.json
new file mode 100644
index 0000000000..fc9c93aa0e
--- /dev/null
+++ b/domains/asad-khan.json
@@ -0,0 +1,12 @@
+{
+ "description": "👋 Hello there! I'm Asad, nice to meet you. Building things that bring delight to users is what I enjoy, always learning new stuff everyday.",
+ "repo": "https://github.com/asadkhan777",
+ "owner": {
+ "username": "asadkhan777",
+ "email": "asadkhan1776@gmail.com"
+ },
+ "record": {
+ "CNAME": "asadkhan777.github.io",
+ "URL": "https://asad-khan.is-a.dev"
+ }
+}
diff --git a/domains/ashish.json b/domains/ashish.json
new file mode 100644
index 0000000000..a1d6e24987
--- /dev/null
+++ b/domains/ashish.json
@@ -0,0 +1,12 @@
+{
+ "description": "Ashish's personal developer website",
+ "repo": "https://github.com/ashiishme",
+ "owner": {
+ "username": "ashiishme",
+ "email": "contact@ashiish.me"
+ },
+ "record": {
+ "CNAME": "ashiish.me",
+ "URL": "https://ashish.is-a.dev"
+ }
+}
diff --git a/domains/atechadventurer.json b/domains/atechadventurer.json
new file mode 100644
index 0000000000..562f3ed467
--- /dev/null
+++ b/domains/atechadventurer.json
@@ -0,0 +1,11 @@
+{
+ "description": "ATechAdventurer's Site",
+ "repo": "https://github.com/ATechAdventurer",
+ "owner": {
+ "username": "ATechAdventurer",
+ "email": "cam.steeleis@gmail.com"
+ },
+ "record": {
+ "URL": "https://github.com/ATechAdventurer"
+ }
+}
diff --git a/domains/atlas.json b/domains/atlas.json
new file mode 100644
index 0000000000..b02d233214
--- /dev/null
+++ b/domains/atlas.json
@@ -0,0 +1,12 @@
+{
+ "description": "Portfolio website",
+ "repo": "https://github.com/robertdrakedennis/portfolio",
+ "owner": {
+ "username": "robertdrakedennis",
+ "email": "robertdennispersonal@gmail.com"
+ },
+ "record": {
+ "CNAME": "robertdennis.netlify.app",
+ "URL": "https://atlas.is-a.dev"
+ }
+}
diff --git a/domains/augustine.json b/domains/augustine.json
new file mode 100644
index 0000000000..83610f6753
--- /dev/null
+++ b/domains/augustine.json
@@ -0,0 +1,12 @@
+{
+ "description": "Augustine's personal developer website",
+ "repo": "https://github.com/augustineaykara",
+ "owner": {
+ "username": "augustineaykara",
+ "email": "augustineaykara@gmail.com"
+ },
+ "record": {
+ "CNAME": "augustine.aykara4.com",
+ "URL": "https://augustine.is-a.dev"
+ }
+}
diff --git a/domains/b45i.json b/domains/b45i.json
new file mode 100644
index 0000000000..6e3ef7d7d6
--- /dev/null
+++ b/domains/b45i.json
@@ -0,0 +1,12 @@
+{
+ "description": "B45i - Home Page",
+ "repo": "https://github.com/B45i/b45i.github.io",
+ "owner": {
+ "username": "B45i",
+ "email": "amalshajan2011@gmail.com"
+ },
+ "record": {
+ "CNAME": "b45i.github.io",
+ "URL": "https://b45i.is-a.dev"
+ }
+}
\ No newline at end of file
diff --git a/domains/bhadra.json b/domains/bhadra.json
new file mode 100644
index 0000000000..69b9a8fd18
--- /dev/null
+++ b/domains/bhadra.json
@@ -0,0 +1,12 @@
+{
+ "description": "Personal Website",
+ "repo": "https://github.com/BhadraJayakumarSandhya/BhadraJayakumarSandhya.github.io",
+ "owner": {
+ "username": "BhadraJayakumarSandhya",
+ "email": "tomjerryparu@gmail.com"
+ },
+ "record": {
+ "CNAME": "BhadraJayakumarSandhya.github.io",
+ "URL": "https://bhadra.is-a.dev"
+ }
+}
diff --git a/domains/bradley.json b/domains/bradley.json
new file mode 100644
index 0000000000..29a3966c11
--- /dev/null
+++ b/domains/bradley.json
@@ -0,0 +1,10 @@
+{
+ "description": "Bradley's website",
+ "owner": {
+ "username": "bholbrook73",
+ "email": "bradley73@gmail.com"
+ },
+ "record": {
+ "CNAME": "bradleyholbrook.com"
+ }
+}
diff --git a/domains/brandon.json b/domains/brandon.json
new file mode 100644
index 0000000000..b533a756a9
--- /dev/null
+++ b/domains/brandon.json
@@ -0,0 +1,12 @@
+{
+ "description": "Brandons's personal developer website",
+ "repo": "https://github.com/b-hexsoul",
+ "owner": {
+ "username": "b-hexsoul",
+ "email": "brandon.hexsel@gmail.com"
+ },
+ "record": {
+ "CNAME": "b-hexsoul.github.io",
+ "URL": "https://brandon.is-a.dev"
+ }
+}
diff --git a/domains/charlie.json b/domains/charlie.json
new file mode 100644
index 0000000000..419de86fa0
--- /dev/null
+++ b/domains/charlie.json
@@ -0,0 +1,12 @@
+{
+ "description": " Charlie is a Dev",
+ "repo": "https://github.com/cachrisman/cachrisman.github.io",
+ "owner": {
+ "username": "cachrisman",
+ "email": "charlie.chrisman@gmail.com"
+ },
+ "record": {
+ "CNAME": "cachrisman.github.io",
+ "URL": "https://charlie.is-a.dev"
+ }
+}
diff --git a/domains/chetanbasuray.json b/domains/chetanbasuray.json
new file mode 100644
index 0000000000..9dcaaf9b18
--- /dev/null
+++ b/domains/chetanbasuray.json
@@ -0,0 +1,12 @@
+{
+ "description": "Chetan's website",
+ "repo": "https://github.com/chetanbasuray/chetanbasuray.github.io",
+ "owner": {
+ "username": "chetanbasuray",
+ "email": "basuraychetan@gmail.com"
+ },
+ "record": {
+ "CNAME": "chetanbasuray.github.io",
+ "URL": "https://chetan-basuray.is-a.dev"
+ }
+}
\ No newline at end of file
diff --git a/domains/chris.json b/domains/chris.json
new file mode 100644
index 0000000000..4d2e473101
--- /dev/null
+++ b/domains/chris.json
@@ -0,0 +1,13 @@
+
+{
+ "description": "Chris' Site",
+ "repo": "https://github.com/Sp4nd3x/",
+ "owner": {
+ "username": "Sp4nd3x",
+ "email": "chrisisadev@gmail.com"
+ },
+ "record": {
+ "CNAME": "sp4nd3x.github.io",
+ "URL": "https://chris.is-a.dev"
+ }
+}
diff --git a/domains/codefoster.json b/domains/codefoster.json
new file mode 100644
index 0000000000..a21e921c26
--- /dev/null
+++ b/domains/codefoster.json
@@ -0,0 +1,11 @@
+{
+ "description": "The main for codefoster - a Software Engineer at Microsoft.",
+ "repo": "https://github.com/codefoster",
+ "owner": {
+ "username": "codefoster",
+ "email": "jeremy.foster@live.com"
+ },
+ "record": {
+ "URL": "http://codefoster.com"
+ }
+}
diff --git a/domains/codethoma.json b/domains/codethoma.json
new file mode 100644
index 0000000000..baafb82d11
--- /dev/null
+++ b/domains/codethoma.json
@@ -0,0 +1,12 @@
+{
+ "description": "The ThunderDome",
+ "repo": "https://github.com/codethoma/",
+ "owner": {
+ "username": "codethoma",
+ "email": "mrthundergod@gmail.com"
+ },
+ "record": {
+ "CNAME": "codethoma.github.io",
+ "URL": "https://codethoma.is-a.dev"
+ }
+}
diff --git a/domains/dan-habot.json b/domains/dan-habot.json
new file mode 100644
index 0000000000..c58d894fd6
--- /dev/null
+++ b/domains/dan-habot.json
@@ -0,0 +1,12 @@
+{
+ "description": "Fullstack web & mobile dev, quality assurance, automation, reverse engineering, and flexible",
+ "repo": "https://github.com/danhab99/danhab99.github.io",
+ "owner": {
+ "username": "danhab99",
+ "email": "dan.habot@gmail.com"
+ },
+ "record": {
+ "CNAME": "danhab99.github.io",
+ "URL": "https://dan-habot.is-a.dev"
+ }
+}
diff --git a/domains/danilofuchs.json b/domains/danilofuchs.json
new file mode 100644
index 0000000000..46f2cf52ac
--- /dev/null
+++ b/domains/danilofuchs.json
@@ -0,0 +1,12 @@
+{
+ "description": "danilofuchs's is-a.dev domain",
+ "repo": "https://github.com/danilofuchs/danilofuchs.github.io",
+ "owner": {
+ "username": "danilofuchs",
+ "email": "danilo_fuchs@hotmail.com"
+ },
+ "record": {
+ "CNAME": "danilofuchs.github.io",
+ "URL": "https://danilofuchs.is-a.dev"
+ }
+}
diff --git a/domains/davish.json b/domains/davish.json
new file mode 100644
index 0000000000..de8704486b
--- /dev/null
+++ b/domains/davish.json
@@ -0,0 +1,12 @@
+{
+ "description": "Davish's Wesbite",
+ "repo": "https://github.com/akchy/akchy.github.io",
+ "owner": {
+ "username": "akchy",
+ "email": "akarshashok12@gmail.com"
+ },
+ "record": {
+ "CNAME": "akchy.github.io",
+ "URL": "https://davish.is-a.dev"
+ }
+}
diff --git a/domains/derek-briggs.json b/domains/derek-briggs.json
new file mode 100644
index 0000000000..9aaa137f75
--- /dev/null
+++ b/domains/derek-briggs.json
@@ -0,0 +1,10 @@
+{
+ "owner" : {
+ "username": "Derek52",
+ "email": "contact@derekbriggs.xyz"
+ },
+ "record": {
+ "CNAME": "Derek52.github.io",
+ "URL": "https://Derek52.is-a.dev"
+ }
+}
diff --git a/domains/dino.json b/domains/dino.json
new file mode 100644
index 0000000000..af974a8de8
--- /dev/null
+++ b/domains/dino.json
@@ -0,0 +1,12 @@
+{
+ "description": "Vitor Dino is a front-end developer and ui designer",
+ "repo": "https://github.com/vitordino",
+ "owner": {
+ "username": "vitordino",
+ "email": "me@vitordino.com"
+ },
+ "record": {
+ "CNAME": "vitordino.com",
+ "URL": "https://dino.is-a.dev"
+ }
+}
diff --git a/domains/ecalzo.json b/domains/ecalzo.json
new file mode 100644
index 0000000000..1243a68c52
--- /dev/null
+++ b/domains/ecalzo.json
@@ -0,0 +1,12 @@
+{
+ "description": "Evan's personal developer blog",
+ "repo": "https://github.com/Ecalzo/ecalzo.github.io",
+ "owner": {
+ "username": "ecalzo",
+ "email": "evancalz@me.com"
+ },
+ "record": {
+ "CNAME": "ecalzo.github.io",
+ "URL": "https://ecalzo.is-a.dev"
+ }
+}
diff --git a/domains/eric.json b/domains/eric.json
new file mode 100644
index 0000000000..ab49675306
--- /dev/null
+++ b/domains/eric.json
@@ -0,0 +1,12 @@
+{
+ "description": "Eric's website and blog",
+ "repo": "https://github.com/yurrriq",
+ "owner": {
+ "username": "yurrriq",
+ "email": "eric@ericb.me"
+ },
+ "record": {
+ "CNAME": "yurrriq.github.io",
+ "URL": "https://eric.is-a.dev"
+ }
+}
diff --git a/domains/ezedinff.json b/domains/ezedinff.json
new file mode 100644
index 0000000000..8a10dd6dfc
--- /dev/null
+++ b/domains/ezedinff.json
@@ -0,0 +1,12 @@
+{
+ "description": "Ezedin's personal developer website",
+ "repo": "https://github.com/ezedinff",
+ "owner": {
+ "username": "ezedinff",
+ "email": "ezedin.fedlu@gmail.com"
+ },
+ "record": {
+ "CNAME": "black-horse-coder-blog.vercel.app",
+ "URL": "https://ezedin.is-a.dev"
+ }
+}
diff --git a/domains/farzan.json b/domains/farzan.json
new file mode 100644
index 0000000000..535308431b
--- /dev/null
+++ b/domains/farzan.json
@@ -0,0 +1,12 @@
+{
+ "description": "Farzan F A is a Dev",
+ "repo": "https://github.com/Farzanfa/Farzanfa.github.io",
+ "owner": {
+ "username": "farzanfa",
+ "email": "farzanfa007@gmail.com"
+ },
+ "record": {
+ "CNAME": "Farzanfa.github.io",
+ "URL": "https://farzan.is-a.dev"
+ }
+}
diff --git a/domains/gaurav.json b/domains/gaurav.json
new file mode 100644
index 0000000000..4a5f346c0c
--- /dev/null
+++ b/domains/gaurav.json
@@ -0,0 +1,12 @@
+{
+ "description": "Gaurav Tewari",
+ "repo": "https://github.com/tewarig/tewarig.github.io",
+ "owner": {
+ "username": "Gaurav",
+ "email": "gauravtewari111@gmail.com"
+ },
+ "record": {
+ "CNAME": "tewarig.github.io",
+ "URL": "https://gaurav.is-a.dev"
+ }
+}
diff --git a/domains/george.json b/domains/george.json
new file mode 100644
index 0000000000..5246589f1a
--- /dev/null
+++ b/domains/george.json
@@ -0,0 +1,11 @@
+{
+ "description": "George Aykara's personal developer website",
+ "repo": "https://github.com/aykarageorge",
+ "owner": {
+ "username": "aykarageorge",
+ "email": "aykarageorge@gmail.com"
+ },
+ "record": {
+ "CNAME": "george.aykara4.com"
+ }
+}
diff --git a/domains/georgekaran.json b/domains/georgekaran.json
new file mode 100644
index 0000000000..ae89517f2b
--- /dev/null
+++ b/domains/georgekaran.json
@@ -0,0 +1,11 @@
+{
+ "description": "George Karan - Personal Page",
+ "repo": "https://github.com/georgekaran",
+ "owner": {
+ "username": "georgekaran",
+ "email": "georgekaran12@gmail.com"
+ },
+ "record": {
+ "URL": "https://georgekaran.com"
+ }
+}
diff --git a/domains/getify.json b/domains/getify.json
new file mode 100644
index 0000000000..4aff2f839a
--- /dev/null
+++ b/domains/getify.json
@@ -0,0 +1,9 @@
+{
+ "owner": {
+ "username": "getify",
+ "email": "domains@dontsend.me"
+ },
+ "record": {
+ "A": ["50.116.28.162"]
+ }
+}
diff --git a/domains/gilad.json b/domains/gilad.json
new file mode 100644
index 0000000000..612ba57b11
--- /dev/null
+++ b/domains/gilad.json
@@ -0,0 +1,11 @@
+{
+ "description": "Gilad's personal developer website",
+ "owner": {
+ "username": "gilade",
+ "email": "gilad@eventov.com"
+ },
+ "record": {
+ "CNAME": "gilad.ninja",
+ "URL": "https://gilad.is-a.dev"
+ }
+}
diff --git a/domains/gkr.json b/domains/gkr.json
new file mode 100644
index 0000000000..fed031e3cc
--- /dev/null
+++ b/domains/gkr.json
@@ -0,0 +1,9 @@
+{
+ "owner": {
+ "username": "gautamkrishnar",
+ "email": "hello@gautamkrishnar.com"
+ },
+ "record": {
+ "A": ["185.224.138.125"]
+ }
+}
diff --git a/domains/gkucmierz.json b/domains/gkucmierz.json
new file mode 100644
index 0000000000..85339e1b26
--- /dev/null
+++ b/domains/gkucmierz.json
@@ -0,0 +1,10 @@
+{
+ "description": "gkucmierz's personal blog",
+ "owner": {
+ "username": "gkucmierz",
+ "email": "gkucmierz@gmail.com"
+ },
+ "record": {
+ "URL": "https://dev.to/gkucmierz"
+ }
+}
diff --git a/domains/glpzzz.json b/domains/glpzzz.json
new file mode 100644
index 0000000000..0ac165228b
--- /dev/null
+++ b/domains/glpzzz.json
@@ -0,0 +1,12 @@
+{
+ "description": "Gabriel A. López López",
+ "repo": "https://github.com/glpzzz/glpzzz.github.io",
+ "owner": {
+ "username": "glpzzz",
+ "email": "glpz@daxslab.com"
+ },
+ "record": {
+ "CNAME": "glpzzz.github.io",
+ "URL": "https://glpzzz.is-a.dev"
+ }
+}
diff --git a/domains/gokul.json b/domains/gokul.json
new file mode 100644
index 0000000000..7032658d26
--- /dev/null
+++ b/domains/gokul.json
@@ -0,0 +1,12 @@
+{
+ "description": "Personal Page",
+ "repo": "https://github.com/gkdskp/gkdskp.github.io",
+ "owner": {
+ "username": "gkdskp",
+ "email": "gokuldskp@gmail.com"
+ },
+ "record": {
+ "CNAME": "gkdskp.github.io",
+ "URL": "https://gokul.is-a.dev"
+ }
+}
diff --git a/domains/govind.json b/domains/govind.json
new file mode 100644
index 0000000000..32732a21d9
--- /dev/null
+++ b/domains/govind.json
@@ -0,0 +1,12 @@
+{
+ "description": "Govind's personal developer website",
+ "repo": "https://github.com/govind-shenoy",
+ "owner": {
+ "username": "govind-shenoy",
+ "email": "govindvshenoy@gmail.com"
+ },
+ "record": {
+ "CNAME": "govind-shenoy.github.io",
+ "URL": "https://govind.is-a.dev"
+ }
+}
diff --git a/domains/guptasiddhant.json b/domains/guptasiddhant.json
new file mode 100644
index 0000000000..d954107e64
--- /dev/null
+++ b/domains/guptasiddhant.json
@@ -0,0 +1,11 @@
+{
+ "description": "Is Dev domain for Siddhant GUPTA",
+ "repo": "https://github.com/guptasiddhant/guptasiddhant/",
+ "owner": {
+ "username": "GuptaSiddhant",
+ "email": "me@guptasiddhant.com"
+ },
+ "record": {
+ "URL": "http://guptasiddhant.com"
+ }
+}
diff --git a/domains/h3r3t1c.json b/domains/h3r3t1c.json
new file mode 100644
index 0000000000..b984f4a2c5
--- /dev/null
+++ b/domains/h3r3t1c.json
@@ -0,0 +1,12 @@
+{
+ "description": "My personal page",
+ "repo": "https://github.com/lfdominguez/lfdominguez.github.io",
+ "owner": {
+ "username": "lfdominguez",
+ "email": "ldominguezvega@gmail.com"
+ },
+ "record": {
+ "CNAME": "lfdominguez.github.io",
+ "URL": "https://h3r3t1c.is-a.dev"
+ }
+}
diff --git a/domains/harry.json b/domains/harry.json
new file mode 100644
index 0000000000..dc5607be34
--- /dev/null
+++ b/domains/harry.json
@@ -0,0 +1,11 @@
+{
+ "owner": {
+ "username": "Harry-Ross",
+ "email": "hazross@hotmail.com"
+ },
+ "description": "Personal site/blog",
+ "repository": "https://github.com/Harry-Ross/harry-ross.github.io.git",
+ "record": {
+ "CNAME": "harry-ross.github.io"
+ }
+}
diff --git a/domains/haseena.json b/domains/haseena.json
new file mode 100644
index 0000000000..8bf3248445
--- /dev/null
+++ b/domains/haseena.json
@@ -0,0 +1,12 @@
+{
+ "description": "Haseena's website",
+ "repo": "https://github.com/haseena-hassan/is-a-dev",
+ "owner": {
+ "username": "haseena-hassan",
+ "email": "haseena2199@gmail.com"
+ },
+ "record": {
+ "CNAME": "haseena-hassan.github.io",
+ "URL": "https://haseena.is-a.dev"
+ }
+}
diff --git a/domains/ivolimasilva.json b/domains/ivolimasilva.json
new file mode 100644
index 0000000000..edf16bcfdb
--- /dev/null
+++ b/domains/ivolimasilva.json
@@ -0,0 +1,12 @@
+{
+ "description": "Ivo Lima Silva's personal website",
+ "repo": "https://github.com/ivolimasilva/ivolimasilva.github.io",
+ "owner": {
+ "username": "ivolimasilva",
+ "email": "ivolimasilva@outlook.com"
+ },
+ "record": {
+ "CNAME": "ivolimasilva.xyz",
+ "URL": "https://ivolimasilva.is-a.dev"
+ }
+}
diff --git a/domains/jacob.json b/domains/jacob.json
new file mode 100644
index 0000000000..230214ceed
--- /dev/null
+++ b/domains/jacob.json
@@ -0,0 +1,12 @@
+{
+ "description": "My cool dev",
+ "repo": "https://github.com/jacob13400/jacob13400.github.io",
+ "owner": {
+ "username": "jacob13400",
+ "email": "jacob13400@gmail.com"
+ },
+ "record": {
+ "CNAME": "jacob13400.github.io",
+ "URL": "https://jacob.is-a.dev"
+ }
+}
diff --git a/domains/jimscope.json b/domains/jimscope.json
new file mode 100644
index 0000000000..127d858140
--- /dev/null
+++ b/domains/jimscope.json
@@ -0,0 +1,12 @@
+{
+ "description": "/home/jimscope",
+ "repo": "https://github.com/jimscope/jimscope.github.io",
+ "owner": {
+ "username": "jimscope",
+ "email": "jimscope@protonmail.com"
+ },
+ "record": {
+ "CNAME": "jimscope.github.io",
+ "URL": "https://jimscope.is-a.dev"
+ }
+}
diff --git a/domains/josh.json b/domains/josh.json
new file mode 100644
index 0000000000..8627871fb9
--- /dev/null
+++ b/domains/josh.json
@@ -0,0 +1,12 @@
+{
+ "description": "Josh's personal developer website",
+ "repo": "https://github.com/miltzi",
+ "owner": {
+ "username": "miltzi",
+ "email": "josh@miltz.co.za"
+ },
+ "record": {
+ "CNAME": "joshisadev.miltz.co.za",
+ "URL": "https://josh.is-a.dev"
+ }
+}
diff --git a/domains/justin.json b/domains/justin.json
new file mode 100644
index 0000000000..c2fb26afa6
--- /dev/null
+++ b/domains/justin.json
@@ -0,0 +1,12 @@
+{
+ "description": "My personal Page",
+ "repo": "https://github.com/justinjohnymathew/justinjohnymathew.github.io",
+ "owner": {
+ "username": "justinjohnymathew",
+ "email": "justinjohny.jj@gmail.com"
+ },
+ "record": {
+ "CNAME": "justinjohnymathew.github.io",
+ "URL": "https://justin.is-a.dev"
+ }
+}
diff --git a/domains/keli5.json b/domains/keli5.json
new file mode 100644
index 0000000000..9d505fab24
--- /dev/null
+++ b/domains/keli5.json
@@ -0,0 +1,12 @@
+{
+ "description": "keli5",
+ "repo": "https://github.com/keli5/keli5.github.io",
+ "owner": {
+ "username": "keli5",
+ "email": "",
+ "twitter": "keli5_letters"
+ },
+ "record": {
+ "CNAME": "keli5.github.io"
+ }
+}
diff --git a/domains/kevin.json b/domains/kevin.json
new file mode 100644
index 0000000000..d563af887d
--- /dev/null
+++ b/domains/kevin.json
@@ -0,0 +1,9 @@
+{
+ "owner": {
+ "username": "KevinBrogan",
+ "email": "kevin@brogan.ca"
+ },
+ "record": {
+ "CNAME": "brogan.ca"
+ }
+}
diff --git a/domains/kiss.json b/domains/kiss.json
new file mode 100644
index 0000000000..9f04710c2c
--- /dev/null
+++ b/domains/kiss.json
@@ -0,0 +1,10 @@
+{
+ "owner": {
+ "username": "filipekiss",
+ "email": "filipe@kiss.ink"
+ },
+ "record": {
+ "CNAME": "filipe.kiss.ink",
+ "URL": "https://kiss.is-a.dev"
+ }
+}
diff --git a/domains/liancg.json b/domains/liancg.json
new file mode 100644
index 0000000000..d16338e78b
--- /dev/null
+++ b/domains/liancg.json
@@ -0,0 +1,12 @@
+{
+ "description": "Lian's Own Dev Domain",
+ "repo": "https://github.com/liancastellon/liancastellon.github.io",
+ "owner": {
+ "username": "liancastellon",
+ "email": "liancg@gmail.com"
+ },
+ "record": {
+ "CNAME": "liancastellon.github.io",
+ "URL": "https://liancg.is-a.dev"
+ }
+}
diff --git a/domains/madhav.json b/domains/madhav.json
new file mode 100644
index 0000000000..e66d5f4cb8
--- /dev/null
+++ b/domains/madhav.json
@@ -0,0 +1,11 @@
+{
+ "repo": "https://github.com/LaBus3/LaBus3.github.io",
+ "owner": {
+ "username": "LaBus3",
+ "email": "madhav.v.1996@gmail.com"
+ },
+ "record": {
+ "CNAME": "LaBus3.github.io",
+ "URL": "https://madhav.is-a.dev"
+ }
+}
diff --git a/domains/mamun.json b/domains/mamun.json
new file mode 100644
index 0000000000..1480b32084
--- /dev/null
+++ b/domains/mamun.json
@@ -0,0 +1,12 @@
+{
+ "description": "Mamun's website",
+ "repo": "https://github.com/mamunhpath",
+ "owner": {
+ "username": "mamunhpath",
+ "email": "mamunhpath@hotmail.com"
+ },
+ "record": {
+ "CNAME": "mamunhpath.github.io",
+ "URL": "https://mamun.is-a.dev"
+ }
+}
diff --git a/domains/mark.json b/domains/mark.json
new file mode 100644
index 0000000000..8c79922a8d
--- /dev/null
+++ b/domains/mark.json
@@ -0,0 +1,12 @@
+
+{
+ "description": "Makr Davydov is a Developer!",
+ "repo": "https://github.com/markrity",
+ "owner": {
+ "username": "markrity",
+ "email": "markrity@gmail.com"
+ },
+ "record": {
+ "URL": "https://www.linkedin.com/in/davydovmark/"
+ }
+}
diff --git a/domains/martial.json b/domains/martial.json
new file mode 100644
index 0000000000..255ef51be3
--- /dev/null
+++ b/domains/martial.json
@@ -0,0 +1,12 @@
+{
+ "description": "Martial is a dev",
+ "repo": "https://github.com/MartialSeron/MartialSeron.github.io",
+ "owner": {
+ "username": "MartialSeron",
+ "email": "martial.seron@gmail.com"
+ },
+ "record": {
+ "CNAME": "martialseron.github.io",
+ "URL": "https://martial.is-a.dev"
+ }
+}
diff --git a/domains/matheus.json b/domains/matheus.json
new file mode 100644
index 0000000000..d5f7196f5f
--- /dev/null
+++ b/domains/matheus.json
@@ -0,0 +1,12 @@
+{
+ "description": "Matheus Costa's personal developer website",
+ "repo": "https://github.com/mthcsta/mthcsta.github.io",
+ "owner": {
+ "username": "mthcsta",
+ "email": "matheuscosta.dev@yahoo.com"
+ },
+ "record": {
+ "CNAME": "mthcsta.github.io",
+ "URL": "https://matheus.is-a.dev"
+ }
+}
diff --git a/domains/matt.json b/domains/matt.json
new file mode 100644
index 0000000000..5b86de240b
--- /dev/null
+++ b/domains/matt.json
@@ -0,0 +1,11 @@
+{
+ "description": "Matt Casey is a Developer!",
+ "repo": "https://github.com/mattcasey",
+ "owner": {
+ "username": "mattcasey",
+ "email": "mattwad@gmail.com"
+ },
+ "record": {
+ "URL": "https://www.linkedin.com/in/mbcasey"
+ }
+}
\ No newline at end of file
diff --git a/domains/mayur.json b/domains/mayur.json
new file mode 100644
index 0000000000..6d137b53cf
--- /dev/null
+++ b/domains/mayur.json
@@ -0,0 +1,12 @@
+{
+ "description": "Mayur Dange is a Developer!",
+ "repo": "https://github.com/mayurdange/mayurdange.github.io",
+ "owner": {
+ "username": "mayurdange",
+ "email": "mayurdange@live.com"
+ },
+ "record": {
+ "CNAME": "mayurdange.github.io",
+ "URL": "https://mayur.is-a.dev"
+ }
+}
diff --git a/domains/michael.json b/domains/michael.json
new file mode 100644
index 0000000000..8e827e0ed8
--- /dev/null
+++ b/domains/michael.json
@@ -0,0 +1,13 @@
+{
+ "description": "Michael's portfolio website and blog",
+ "repo": "https://github.com/michaelmano/michaelmano.github.io",
+ "owner": {
+ "username": "michaelmano",
+ "email": "michael.mano26@gmail.com"
+ },
+ "record": {
+ "CNAME": "michaelmano.github.io",
+ "URL": "https://michael.is-a.dev"
+ }
+ }
+
\ No newline at end of file
diff --git a/domains/mike.json b/domains/mike.json
new file mode 100644
index 0000000000..7feea0794f
--- /dev/null
+++ b/domains/mike.json
@@ -0,0 +1,12 @@
+{
+ "description": "Mike's portfolio website and blog",
+ "repo": "https://github.com/mdrobbins",
+ "owner": {
+ "username": "mdrobbins",
+ "email": "mikedrobbins@gmail.com"
+ },
+ "record": {
+ "URL": "https://mikerobbins.me"
+ }
+ }
+
\ No newline at end of file
diff --git a/domains/mpy.json b/domains/mpy.json
new file mode 100644
index 0000000000..474c3889b6
--- /dev/null
+++ b/domains/mpy.json
@@ -0,0 +1,12 @@
+{
+ "description": "Mike Perry Y Attara's personal website",
+ "repo": "https://github.com/mikeattara",
+ "owner": {
+ "username": "mikeattara",
+ "email": "mpyebattara@gmail.com"
+ },
+ "record": {
+ "CNAME": "mikeattara.github.io",
+ "URL": "https://mpy.is-a.dev"
+ }
+}
\ No newline at end of file
diff --git a/domains/mrthundergod.json b/domains/mrthundergod.json
new file mode 100644
index 0000000000..a7d5f9b20f
--- /dev/null
+++ b/domains/mrthundergod.json
@@ -0,0 +1,12 @@
+{
+ "description": "The ThunderDome",
+ "repo": "https://github.com/mrthundergod/",
+ "owner": {
+ "username": "mrthundergod",
+ "email": "mrthundergod@gmail.com"
+ },
+ "record": {
+ "CNAME": "mrthundergod.github.io",
+ "URL": "https://mrthundergod.is-a.dev"
+ }
+}
diff --git a/domains/mverhees.json b/domains/mverhees.json
new file mode 100644
index 0000000000..19b6d3678c
--- /dev/null
+++ b/domains/mverhees.json
@@ -0,0 +1,12 @@
+{
+ "description": "Mike's website",
+ "repo": "https://github.com/MikeVerhees/MikeVerhees.github.io",
+ "owner": {
+ "username": "MikeVerhees",
+ "email": "mikeverhees95@gmail.com"
+ },
+ "record": {
+ "CNAME": "MikeVerhees.github.io",
+ "URL": "https://mverhees.is-a.dev"
+ }
+}
diff --git a/domains/nimish.json b/domains/nimish.json
new file mode 100644
index 0000000000..a8b343dec0
--- /dev/null
+++ b/domains/nimish.json
@@ -0,0 +1,12 @@
+{
+ "description": "Nimish's Engineering Diary",
+ "repo": "https://github.com/nimish-gupta/blog",
+ "owner": {
+ "username": "nimish-gupta",
+ "email": "gnimish03@gmail.com"
+ },
+ "record": {
+ "CNAME": "nimish-gupta.dev",
+ "URL": "https://nimish.is-a.dev"
+ }
+}
diff --git a/domains/nishant.json b/domains/nishant.json
new file mode 100644
index 0000000000..8c827c715e
--- /dev/null
+++ b/domains/nishant.json
@@ -0,0 +1,12 @@
+{
+ "description": "Nishant's website and blog",
+ "repo": "https://github.com/nishch/nishch.github.io",
+ "owner": {
+ "username": "nishch",
+ "email": "nishantchvedi@gmail.com"
+ },
+ "record": {
+ "CNAME": "twistedsoft.com",
+ "URL": "https://nishant.is-a.dev"
+ }
+}
diff --git a/domains/owain.json b/domains/owain.json
new file mode 100644
index 0000000000..09020668a3
--- /dev/null
+++ b/domains/owain.json
@@ -0,0 +1,11 @@
+{
+ "description": "Owain's Website",
+ "owner": {
+ "username": "owjothegreat",
+ "email": "owain.jones74@gmail.com"
+ },
+ "record": {
+ "CNAME": "0wain.xyz",
+ "URL": "https://owain.is-a.dev"
+ }
+}
diff --git a/domains/parshnt.json b/domains/parshnt.json
new file mode 100644
index 0000000000..8319fd3504
--- /dev/null
+++ b/domains/parshnt.json
@@ -0,0 +1,12 @@
+{
+ "description": "YAY, new place for my Portfolio",
+ "repo": "https://github.com/parshnt",
+ "owner": {
+ "username": "parshnt",
+ "email": "hi.parshant@gmail.com"
+ },
+ "record": {
+ "CNAME": "parshnt.github.io",
+ "URL": "https://parshnt.is-a.dev"
+ }
+}
diff --git a/domains/picklerick.json b/domains/picklerick.json
new file mode 100644
index 0000000000..b9d70f69e9
--- /dev/null
+++ b/domains/picklerick.json
@@ -0,0 +1,12 @@
+{
+ "description": "cool stuff",
+ "repo": "https://github.com/ticklerick/ticklerick.github.io",
+ "owner": {
+ "username": "ticklerick",
+ "email": "pickle@anonemail.net"
+ },
+ "record": {
+ "CNAME": "ticklerick.github.io",
+ "URL": "https://picklerick.is-a.dev"
+ }
+}
\ No newline at end of file
diff --git a/domains/piyush.json b/domains/piyush.json
new file mode 100644
index 0000000000..d7d87b331f
--- /dev/null
+++ b/domains/piyush.json
@@ -0,0 +1,10 @@
+{
+ "description": "Piyush's Website",
+ "owner": {
+ "username": "officialpiyush",
+ "email": "bhangalepiyush@gmail.com"
+ },
+ "record": {
+ "URL": "https://piyush.codes"
+ }
+}
diff --git a/domains/proghead00.json b/domains/proghead00.json
new file mode 100644
index 0000000000..e647ed5d98
--- /dev/null
+++ b/domains/proghead00.json
@@ -0,0 +1,12 @@
+{
+ "description": "Susnata's is.a.dev domain!",
+ "repo": "https://github.com/proghead00/proghead00.github.io",
+ "owner": {
+ "username": "proghead00",
+ "email": "susnata00@gmail.com"
+ },
+ "record": {
+ "CNAME": "proghead00.github.io",
+ "URL": "https://proghead00.is-a.dev"
+ }
+}
diff --git a/domains/rabbi-shuki.json b/domains/rabbi-shuki.json
new file mode 100644
index 0000000000..b834efb750
--- /dev/null
+++ b/domains/rabbi-shuki.json
@@ -0,0 +1,12 @@
+{
+ "description": "TODO: update readme",
+ "repo": "https://github.com/rabbishuki/rabbishuki.github.io",
+ "owner": {
+ "username": "Rabbi Shuki",
+ "email": "rabbishuki+is-a-dev@gmail.com"
+ },
+ "record": {
+ "CNAME": "rabbishuki.github.io",
+ "URL": "https://rabbi-shuki.is-a.dev"
+ }
+}
diff --git a/domains/rayvid.json b/domains/rayvid.json
new file mode 100644
index 0000000000..3455bc522f
--- /dev/null
+++ b/domains/rayvid.json
@@ -0,0 +1,13 @@
+
+{
+ "description": "Rayvid's website",
+ "repo": "https://github.com/Rayvid",
+ "owner": {
+ "username": "rayvid",
+ "email": "gin.kisonas@gmail.com"
+ },
+ "record": {
+ "CNAME": "rayvid.github.io",
+ "URL": "https://rayvid.is-a.dev"
+ }
+}
diff --git a/domains/reed.json b/domains/reed.json
new file mode 100644
index 0000000000..5f70ceda15
--- /dev/null
+++ b/domains/reed.json
@@ -0,0 +1,11 @@
+{
+ "repo": "https://github.com/reed-jones",
+ "owner": {
+ "username": "reed-jones",
+ "email": "reedjones@reedjones.com"
+ },
+ "record": {
+ "CNAME": "reedjones.com",
+ "URL": "https://reed.is-a.dev"
+ }
+}
diff --git a/domains/roy.json b/domains/roy.json
new file mode 100644
index 0000000000..678134f47c
--- /dev/null
+++ b/domains/roy.json
@@ -0,0 +1,12 @@
+{
+ "description": "Roy's portfolio website",
+ "repo": "https://github.com/rcrj/rcrj.github.io",
+ "owner": {
+ "username": "rcrj",
+ "email": "rcrj95@gmail.com"
+ },
+ "record": {
+ "CNAME": "rcrj.github.io",
+ "URL": "https://roy.is-a.dev"
+ }
+}
diff --git a/domains/rwithik.json b/domains/rwithik.json
new file mode 100644
index 0000000000..6615c5d683
--- /dev/null
+++ b/domains/rwithik.json
@@ -0,0 +1,12 @@
+{
+ "description": "Rwithik's Website",
+ "repo": "https://github.com/rwithik/rwithik.github.io",
+ "owner": {
+ "username": "rwithik",
+ "email": "rwithik@gmail.com"
+ },
+ "record": {
+ "CNAME": "rwithik.github.io",
+ "URL": "https://rwithik.is-a.dev"
+ }
+}
diff --git a/domains/sailesh.json b/domains/sailesh.json
new file mode 100644
index 0000000000..641f1d2634
--- /dev/null
+++ b/domains/sailesh.json
@@ -0,0 +1,10 @@
+{
+ "description": "Sailesh's Personal Website",
+ "owner": {
+ "username": "saileshbro",
+ "email": "saileshbro@gmail.com"
+ },
+ "record": {
+ "CNAME": "saileshbro.github.io"
+ }
+}
diff --git a/domains/saisandeepvaddi.json b/domains/saisandeepvaddi.json
new file mode 100644
index 0000000000..584f761aea
--- /dev/null
+++ b/domains/saisandeepvaddi.json
@@ -0,0 +1,10 @@
+{
+ "description": "Sai Sandeep Vaddi's website",
+ "owner": {
+ "username": "saisandeepvaddi",
+ "email": "saisandeepvaddi@gmail.com"
+ },
+ "record": {
+ "A": ["104.198.14.52"]
+ }
+}
diff --git a/domains/sarath.json b/domains/sarath.json
new file mode 100644
index 0000000000..757b1183f8
--- /dev/null
+++ b/domains/sarath.json
@@ -0,0 +1,12 @@
+{
+ "description": "Sarath's Website",
+ "repo": "https://github.com/Sharkaboi/sharkaboi.github.io",
+ "owner": {
+ "username": "Sharkaboi",
+ "email": "sarathsedu@gmail.com"
+ },
+ "record": {
+ "CNAME": "sharkaboi.github.io",
+ "URL": "https://sarath.is-a.dev"
+ }
+ }
\ No newline at end of file
diff --git a/domains/savio.json b/domains/savio.json
new file mode 100644
index 0000000000..0bdea966a9
--- /dev/null
+++ b/domains/savio.json
@@ -0,0 +1,12 @@
+ {
+ "description": "Savio Martin is a Dev",
+ "repo": "https://github.com/saviomartin/register",
+ "owner": {
+ "username": "saviomartin",
+ "email": "saviomartin2020@gmail.com"
+ },
+ "record": {
+ "CNAME": "saviomartin.github.io",
+ "URL": "https://savio.is-a.dev"
+ }
+}
diff --git a/domains/shalom.json b/domains/shalom.json
new file mode 100644
index 0000000000..bf7bd85011
--- /dev/null
+++ b/domains/shalom.json
@@ -0,0 +1,11 @@
+{
+ "description": "Shalom's personal website",
+ "owner": {
+ "username": "shalomscott",
+ "email": "shalomss525@gmail.com"
+ },
+ "record": {
+ "CNAME": "shalom-is-a-dev.netlify.app",
+ "URL": "https://shalom.is-a.dev"
+ }
+}
diff --git a/domains/sharath.json b/domains/sharath.json
new file mode 100644
index 0000000000..c213eb8264
--- /dev/null
+++ b/domains/sharath.json
@@ -0,0 +1,12 @@
+{
+ "description": "Social media website project.",
+ "repo": "https://github.com/thesct22",
+ "owner": {
+ "username": "thesct22",
+ "email": "sharathct22@gmail.com"
+ },
+ "record": {
+ "CNAME": "thesct22.github.io",
+ "URL": "http://sharath.is-a.dev"
+ }
+}
diff --git a/domains/sharifclick.json b/domains/sharifclick.json
new file mode 100644
index 0000000000..b81e16c036
--- /dev/null
+++ b/domains/sharifclick.json
@@ -0,0 +1,12 @@
+{
+ "description": "personal website",
+ "repo": "https://github.com/SharifClick/sharifclick.github.io",
+ "owner": {
+ "username": "sharifclick",
+ "email": "me.sharifahmed@gmail.com"
+ },
+ "record": {
+ "CNAME": "sharifclick.github.io",
+ "URL": "https://sharifclick.is-a.dev"
+ }
+}
diff --git a/domains/shenjunru.json b/domains/shenjunru.json
new file mode 100644
index 0000000000..d521ea0549
--- /dev/null
+++ b/domains/shenjunru.json
@@ -0,0 +1,12 @@
+{
+ "description": "Shen Junru is a Dev",
+ "repo": "https://github.com/shenjunru/is-a-dev",
+ "owner": {
+ "username": "shenjunru",
+ "email": "shenjunru@gmail.com"
+ },
+ "record": {
+ "CNAME": "shenjunru.github.io",
+ "URL": "https://shenjunru.is-a.dev"
+ }
+}
diff --git a/domains/shibiliya.json b/domains/shibiliya.json
new file mode 100644
index 0000000000..4c31049862
--- /dev/null
+++ b/domains/shibiliya.json
@@ -0,0 +1,12 @@
+{
+ "description": "Shibiliya's personal developer website",
+ "repo": "https://github.com/duaboola",
+ "owner": {
+ "username": "duaboola",
+ "email": "ismailshibiliya@gmail.com"
+ },
+ "record": {
+ "CNAME": "duaboola.github.io",
+ "URL": "https://shibiliya.is-a.dev"
+ }
+}
diff --git a/domains/steven.json b/domains/steven.json
new file mode 100644
index 0000000000..1e798e9419
--- /dev/null
+++ b/domains/steven.json
@@ -0,0 +1,12 @@
+{
+ "description": "Steven Frohlich's portfolio",
+ "repo": "https://github.com/StevenRonnyFrohlich/StevenRonnyFrohlich.github.io",
+ "owner": {
+ "username": "StevenRonnyFrohlich",
+ "email": "steve.r.frohlich@gmail.com"
+ },
+ "record": {
+ "CNAME": "StevenRonnyFrohlich.github.io",
+ "URL": "https://steven.is-a.dev"
+ }
+}
diff --git a/domains/stiforr.json b/domains/stiforr.json
new file mode 100644
index 0000000000..77be3c5e29
--- /dev/null
+++ b/domains/stiforr.json
@@ -0,0 +1,9 @@
+{
+ "owner": {
+ "username": "stiforr",
+ "email": "norwood.sean@gmail.com"
+ },
+ "record": {
+ "CNAME": "stiforr.com"
+ }
+}
\ No newline at end of file
diff --git a/domains/swanny.json b/domains/swanny.json
new file mode 100644
index 0000000000..b59c071c22
--- /dev/null
+++ b/domains/swanny.json
@@ -0,0 +1,12 @@
+{
+ "description": "Swanny is a Dev",
+ "repo": "https://github.com/swanny246/swannyIsADev/",
+ "owner": {
+ "username": "swanny246",
+ "email": "github@andrewswan.net"
+ },
+ "record": {
+ "CNAME": "swannyisadev.andrewswan.net",
+ "URL": "https://swanny.is-a.dev"
+ }
+}
diff --git a/domains/tjr.json b/domains/tjr.json
new file mode 100644
index 0000000000..4b4a6010c2
--- /dev/null
+++ b/domains/tjr.json
@@ -0,0 +1,9 @@
+{
+ "owner": {
+ "username": "tjrgg",
+ "email": "hello@tjrgg.co"
+ },
+ "record": {
+ "URL": "https://tjrgg.co"
+ }
+}
diff --git a/domains/tjrgg.json b/domains/tjrgg.json
new file mode 100644
index 0000000000..4b4a6010c2
--- /dev/null
+++ b/domains/tjrgg.json
@@ -0,0 +1,9 @@
+{
+ "owner": {
+ "username": "tjrgg",
+ "email": "hello@tjrgg.co"
+ },
+ "record": {
+ "URL": "https://tjrgg.co"
+ }
+}
diff --git a/domains/tokyo.json b/domains/tokyo.json
new file mode 100644
index 0000000000..fb1814029d
--- /dev/null
+++ b/domains/tokyo.json
@@ -0,0 +1,12 @@
+{
+ "description": "A-Tokyo's website",
+ "repo": "https://github.com/a-tokyo/tokyo",
+ "owner": {
+ "username": "a-tokyo",
+ "email": "ahmed.tokyo1@gmail.com"
+ },
+ "record": {
+ "CNAME": "a-tokyo.github.io",
+ "URL": "https://tokyo.is-a.dev"
+ }
+}
diff --git a/domains/tom.json b/domains/tom.json
new file mode 100644
index 0000000000..f97d865bbf
--- /dev/null
+++ b/domains/tom.json
@@ -0,0 +1,10 @@
+{
+ "owner": {
+ "username": "tommitchelmore",
+ "email": "tommitchelmore@outlook.com"
+ },
+ "repo": "https://github.com/tommitchelmore",
+ "record": {
+ "URL": "https://github.com/tommitchelmore"
+ }
+}
diff --git a/domains/tomas.json b/domains/tomas.json
new file mode 100644
index 0000000000..b14ef10909
--- /dev/null
+++ b/domains/tomas.json
@@ -0,0 +1,10 @@
+{
+ "description": "Tomas's personal developer website",
+ "owner": {
+ "username": "Tomas Ukrinas",
+ "email": "tomas@ukrinas.eu"
+ },
+ "record": {
+ "CNAME": "ukrinas.eu"
+ }
+}
diff --git a/domains/tyler.json b/domains/tyler.json
new file mode 100644
index 0000000000..8048410386
--- /dev/null
+++ b/domains/tyler.json
@@ -0,0 +1,12 @@
+{
+ "description": "Tyler McCarthy is a Developer!",
+ "repo": "https://github.com/tmccarthyj",
+ "owner": {
+ "username": "tmccarthyj",
+ "email": "tyler@tjm.dev"
+ },
+ "record": {
+ "CNAME": "tjm.dev",
+ "URL": "https://tyler.is-a.dev"
+ }
+}
\ No newline at end of file
diff --git a/domains/vaskian.json b/domains/vaskian.json
new file mode 100644
index 0000000000..f3d371e950
--- /dev/null
+++ b/domains/vaskian.json
@@ -0,0 +1,11 @@
+{
+ "description": "Vaskian is a Dev",
+ "repo": "https://github.com/Nami2012",
+ "owner": {
+ "username": "Nami2012",
+ "email": "namithasadeeshbabu@gmail.com"
+ },
+ "record": {
+ "URL": "https://vaskian.me/"
+ }
+}
diff --git a/domains/vivekkumar.json b/domains/vivekkumar.json
new file mode 100644
index 0000000000..c7048deaa1
--- /dev/null
+++ b/domains/vivekkumar.json
@@ -0,0 +1,13 @@
+{
+ "description": "Vivek's portfolio website",
+ "repo": "https://github.com/VivekKumarNeu/VivekKumarNeu.github.io",
+ "owner": {
+ "username": "vivekkumarneu",
+ "email": "vivek-kumar@live.in"
+ },
+ "record": {
+ "CNAME": "VivekKumarNeu.github.io",
+ "URL": "https://vivekkumar.is-a.dev"
+ }
+ }
+
\ No newline at end of file
diff --git a/domains/www.json b/domains/www.json
index d0ce430339..359253458f 100644
--- a/domains/www.json
+++ b/domains/www.json
@@ -1,4 +1,6 @@
{
+ "description": "www.is-a.dev",
+ "repo": "https://github.com/is-a-dev/is-a-dev.github.io",
"owner": {
"username": "phenax",
"email": "phenax5@gmail.com"
diff --git a/domains/yujia.json b/domains/yujia.json
new file mode 100644
index 0000000000..4d56109d94
--- /dev/null
+++ b/domains/yujia.json
@@ -0,0 +1,12 @@
+{
+ "description": "Yujia's Magic",
+ "repo": "https://github.com/YujiaY",
+ "owner": {
+ "username": "YujiaY",
+ "email": "aujackyuan@gmail.com"
+ },
+ "record": {
+ "CNAME": "YujiaY.github.io",
+ "URL": "https://yujia.is-a.dev"
+ }
+}
\ No newline at end of file
diff --git a/domains/yuksel.json b/domains/yuksel.json
new file mode 100644
index 0000000000..5e110378e4
--- /dev/null
+++ b/domains/yuksel.json
@@ -0,0 +1,12 @@
+{
+ "description": "Yuksel Beyti's personal developer website",
+ "repo": "https://github.com/yuks/yuks.github.io",
+ "owner": {
+ "username": "yuks",
+ "email": "admin@yukselbeyti.com"
+ },
+ "record": {
+ "CNAME": "yuks.github.io",
+ "URL": "https://yuksel.is-a.dev"
+ }
+}
diff --git a/media/banner.png b/media/banner.png
new file mode 100644
index 0000000000..bfa9b8132a
Binary files /dev/null and b/media/banner.png differ
diff --git a/media/banner.svg b/media/banner.svg
index 6c8ffc0542..f0b9a6440a 100644
--- a/media/banner.svg
+++ b/media/banner.svg
@@ -1 +1,99 @@
-
\ No newline at end of file
+
+
diff --git a/package.json b/package.json
index e7f7277a11..8a92a77a15 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"description": "Register *.is-a.dev domains for free",
"scripts": {
"test": "ENV=test jest",
- "publish-records": "yarn test && node ./scripts/register-domains.js"
+ "publish-records": "node ./scripts/register-domains.js"
},
"repository": {
"type": "git",
@@ -16,9 +16,9 @@
"author": "Akshay Nair ",
"license": "GPL-3.0",
"dependencies": {
- "@rqt/namecheap": "^2.4.2",
"dotenv": "^8.2.0",
"jest": "^26.4.2",
+ "node-fetch": "^2.6.1",
"ramda": "^0.27.1"
}
}
diff --git a/scripts/action-utils.js b/scripts/action-utils.js
new file mode 100644
index 0000000000..f4fde5761e
--- /dev/null
+++ b/scripts/action-utils.js
@@ -0,0 +1,8 @@
+module.exports = {
+ hasLabel: (context, label) => {
+ const pr = context.payload.pull_request || context.payload.issue;
+ const { labels = [] } = pr;
+
+ return !!labels.find(({ name }) => name === label);
+ },
+};
diff --git a/scripts/migrate.js b/scripts/migrate.js
new file mode 100644
index 0000000000..e5da7ebf5f
--- /dev/null
+++ b/scripts/migrate.js
@@ -0,0 +1,30 @@
+const fs = require('fs');
+const path = require('path');
+const R = require('ramda');
+const { DOMAINS_PATH } = require('./utils/constants');
+
+const migrate = ([file, domain]) => [
+ file,
+ {
+ ...domain,
+ record: /\.github\.io$/.test(domain.record.CNAME || '')
+ ? R.dissoc('URL', domain.record)
+ : domain.record,
+ }
+];
+
+const main = async () => {
+ const domains = await fs.promises.readdir(DOMAINS_PATH).then(R.map(async file => [
+ file,
+ JSON.parse(await fs.promises.readFile(path.join(DOMAINS_PATH, file), 'utf-8')),
+ ])).then(ps => Promise.all(ps));
+
+ const newDomains = domains.map(migrate);
+
+ await Promise.all(newDomains.map(([file, json]) => {
+ return fs.promises.writeFile(path.join(DOMAINS_PATH, file), JSON.stringify(json, null, 2));
+ }));
+};
+
+main();
+
diff --git a/scripts/register-domains.js b/scripts/register-domains.js
index 73186f79ab..00626092f1 100644
--- a/scripts/register-domains.js
+++ b/scripts/register-domains.js
@@ -10,27 +10,27 @@ const toHostList = R.chain(data => {
return R.chain(([recordType, urls]) =>
(Array.isArray(urls) ? urls : [urls]).map(url => ({
- HostName: data.name,
- RecordType: recordType,
- Address: url,
- TTL,
+ name: data.name,
+ type: recordType,
+ address: (recordType === 'CNAME' ? `${url}`.toLowerCase() : `${url}`).replace(/\/$/g, ''),
+ ttl: TTL,
}))
, rs);
});
-const registerDomains = async ({ domainService, getDomains }) => {
+const registerDomains = async ({ domainService, getDomains, log = () => {} }) => {
const domains = await getDomains().then(toHostList);
if (domains.length === 0)
return Promise.reject(new Error('Nothing to register'));
- console.log(`Publishing ${domains.length} records...`);
+ log(`${domains.length} records found`);
return domainService.updateHosts(domains);
};
const main = async () => {
console.log(`Running in ${ENV} mode`);
- const result = await registerDomains({ domainService: dc, getDomains: gd });
+ const result = await registerDomains({ domainService: dc, getDomains: gd, log: console.log });
console.log(result);
};
diff --git a/scripts/reply.js b/scripts/reply.js
new file mode 100644
index 0000000000..9c5fc11b29
--- /dev/null
+++ b/scripts/reply.js
@@ -0,0 +1,41 @@
+
+const getInstructions = () => `
+The changes have been published!! It should reflect in less than 24 hours.
+
+## Here\'s what you need to do next
+
+If your domain points to a server you own, add \`domain-name.is-a.dev\` to your server config. For https, you will have to configure ssl certificate to allow the new subdomain.
+
+### For github pages users,
+* Go to your github page repo (\`user/user.github.io\`)
+* Open up the **settings** tab
+* Scroll down to the **Github pages** section
+* In the **Custom domain** text input, enter the domain you registered (\`domain-name.is-a.dev\`)
+* Check the 'Enforce HTTPS' checkbox below the input
+* Give it some time to reflect and you should be good to go
+
+
+## Need support with your domain?
+If you are having trouble setting up your domain, [create an issue](https://github.com/is-a-dev/register/issues/new/choose). I\'ll try my best to get back to you asap!
+
+
+## Love/Hate the service?
+**Love it?** Leave it a **star**! Also consider **[donating](https://github.com/is-a-dev/register#donations)** so that I can keep this service running forever.
+
+**Hate it?** Please leave your feedback by [creating an issue](https://github.com/is-a-dev/register/issues/new/choose). I\'d really like to keep improving this service for developers.
+`;
+
+module.exports = {
+ async instructions(context, github) {
+ const pr = context.payload.issue || context.payload.pull_request;
+ const { number } = pr;
+
+ await github.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: number,
+ body: getInstructions(),
+ });
+ }
+};
+
diff --git a/tests/cpanel.test.js b/tests/cpanel.test.js
new file mode 100644
index 0000000000..f92ce51d33
--- /dev/null
+++ b/tests/cpanel.test.js
@@ -0,0 +1,143 @@
+const R = require('ramda');
+const { CpanelClient } = require('../utils/lib/cpanel');
+
+const mockFetch = (expectRequest, decorate = R.identity) => (reqUrl, request) => {
+ expectRequest(reqUrl, request);
+ return Promise.resolve({
+ json: async () => decorate(request),
+ });
+};
+
+describe('Cpanel client', () => {
+ describe('fetchzonerecords', () => {
+ it('should make the correct request', async () => {
+ const fetch = mockFetch((url, request) => {
+ expect(url).toBe('https://example.com:2000/json-api/cpanel?customonly=1&domain=a.b&cpanel_jsonapi_user=boy&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzone_records&cpanel_jsonapi_apiversion=2');
+ expect(request).toEqual({
+ headers: {
+ Authorization: 'cpanel boy:boybyebye',
+ },
+ rejectUnauthorized: false,
+ });
+ });
+
+ const cpanel = CpanelClient({
+ host: 'example.com',
+ port: 2000,
+ username: 'boy',
+ apiKey: 'boybyebye',
+ domain: 'a.b',
+ dependencies: { fetch },
+ });
+
+ await cpanel.zone.fetch();
+ });
+
+ it('should make the correct request with query', async () => {
+ const fetch = mockFetch((url, request) => {
+ expect(url).toBe('https://example.com:2000/json-api/cpanel?customonly=1&domain=foobar.boeey&cpanel_jsonapi_user=boy&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzone_records&cpanel_jsonapi_apiversion=2');
+ expect(request).toEqual({
+ headers: {
+ Authorization: 'cpanel boy:boybyebye',
+ },
+ rejectUnauthorized: false,
+ });
+ });
+
+ const cpanel = CpanelClient({
+ host: 'example.com',
+ port: 2000,
+ username: 'boy',
+ apiKey: 'boybyebye',
+ domain: 'a.b',
+ dependencies: { fetch },
+ });
+
+ await cpanel.zone.fetch({ domain: 'foobar.boeey' });
+ });
+ });
+
+ describe('addzonerecord', () => {
+ it('should make the correct request', async () => {
+ const fetch = mockFetch((url, request) => {
+ expect(url).toBe('https://example.com:2000/json-api/cpanel?domain=a.b&name=googo&type=CNAME&cname=beey&ttl=2020&cpanel_jsonapi_user=boy&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=add_zone_record&cpanel_jsonapi_apiversion=2');
+ expect(request).toEqual({
+ headers: {
+ Authorization: 'cpanel boy:boybyebye',
+ },
+ rejectUnauthorized: false,
+ });
+ });
+
+ const cpanel = CpanelClient({
+ host: 'example.com',
+ port: 2000,
+ username: 'boy',
+ apiKey: 'boybyebye',
+ domain: 'a.b',
+ dependencies: { fetch },
+ });
+
+ await cpanel.zone.add({
+ name: 'googo',
+ type: 'boyee',
+ cname: 'beey',
+ type: 'CNAME',
+ ttl: 2020,
+ });
+ });
+ });
+
+ describe('fetchredirections', () => {
+ it('should make the correct request', async () => {
+ const fetch = mockFetch((url, request) => {
+ expect(url).toBe('https://example.com:2000/execute/Mime/list_redirects?cpanel_jsonapi_user=boy&cpanel_jsonapi_module=Mime&cpanel_jsonapi_func=list_redirects&cpanel_jsonapi_apiversion=2');
+ expect(request).toEqual({
+ headers: {
+ Authorization: 'cpanel boy:boybyebye',
+ },
+ rejectUnauthorized: false,
+ });
+ });
+
+ const cpanel = CpanelClient({
+ host: 'example.com',
+ port: 2000,
+ username: 'boy',
+ apiKey: 'boybyebye',
+ domain: 'a.b',
+ dependencies: { fetch },
+ });
+
+ await cpanel.redirection.fetch();
+ });
+ });
+ describe('addredirection', () => {
+ it('should make the correct request', async () => {
+ const fetch = mockFetch((url, request) => {
+ expect(url).toBe('https://example.com:2000/execute/Mime/add_redirect?domain=googo&destination=https%3A%2F%2Foodf.com&cpanel_jsonapi_user=boy&cpanel_jsonapi_module=Mime&cpanel_jsonapi_func=add_redirect&cpanel_jsonapi_apiversion=2');
+ expect(request).toEqual({
+ headers: {
+ Authorization: 'cpanel boy:boybyebye',
+ },
+ rejectUnauthorized: false,
+ });
+ });
+
+ const cpanel = CpanelClient({
+ host: 'example.com',
+ port: 2000,
+ username: 'boy',
+ apiKey: 'boybyebye',
+ domain: 'a.b',
+ dependencies: { fetch },
+ });
+
+ await cpanel.redirection.add({
+ domain: 'googo',
+ destination: 'https://oodf.com'
+ });
+ });
+ });
+});
+
diff --git a/tests/domain-service.test.js b/tests/domain-service.test.js
index 08e49e9b67..19154db6ef 100644
--- a/tests/domain-service.test.js
+++ b/tests/domain-service.test.js
@@ -1,118 +1,255 @@
const R = require('ramda');
-const { getDomainService } = require('../utils/domain-service');
+const { getDomainService, diffRecords } = require('../utils/domain-service');
+const {DOMAIN_DOMAIN} = require('../utils/constants');
-const getNc = ({ onSet, onGet } = {}) => ({
- dns: {
- setHosts: (_, list) => onSet(list),
- getHosts: (_) => onGet(),
+const getCpanel = ({ zone, addZone, editZone, redir, addRedir, editRedir } = {}) => ({
+ zone: {
+ fetch: (_) => zone(),
+ add: (rec) => addZone(rec),
+ edit: (rec) => editZone(rec),
+ },
+ redirection: {
+ fetch: (_) => redir(),
+ add: (rec) => addRedir(rec),
+ edit: (rec) => editRedir(rec),
},
});
-describe('Domain service', () => {
- describe('getHosts', () => {
- it('should resolve with a list of hosts', async () => {
- const hosts = [
- { Name: 'xx', Type: 'CNAME', Address: 'fck.com.' },
- { Name: 'xx', Type: 'A', Address: '111.1.1212.1' },
- ];
- const onGet = async () => ({ hosts })
- const mockDomainService = getDomainService({ nc: getNc({ onGet }) });
- const list = await mockDomainService.getHosts();
+describe('diffRecords', () => {
+ it('should show added record', () => {
+ const oldRecords = [
+ { name: 'xx', type: 'CNAME', address: 'fck.com.' },
+ { name: 'xa', type: 'A', address: '111.1.1212.1' },
+ ];
+ const newRecords = [
+ { name: 'xx', type: 'CNAME', address: 'fck.com.' },
+ { name: 'xa', type: 'A', address: '111.1.1212.1' },
+ { name: 'boo', type: 'CNAME', address: 'x.com' },
+ ];
- expect(list).toEqual([
- { HostName: 'xx', RecordType: 'CNAME', Address: 'fck.com' },
- { HostName: 'xx', RecordType: 'A', Address: '111.1.1212.1' },
- ]);
+ const result = diffRecords(oldRecords, newRecords);
+ expect(result).toEqual({
+ edit: [],
+ add: [
+ { name: 'boo', type: 'CNAME', address: 'x.com' },
+ ],
});
});
- describe('setHosts', () => {
+ it('should show edited records', () => {
+ const oldRecords = [
+ { name: 'xx', type: 'CNAME', address: 'fck.com.' },
+ { name: 'xa', type: 'A', address: '111.1.1212.1' },
+ ];
+ const newRecords = [
+ { name: 'xx', type: 'CNAME', address: 'fck.com.' },
+ { name: 'xa', type: 'A', address: '69.69.69.69' },
+ ];
+
+ const result = diffRecords(oldRecords, newRecords);
+ expect(result).toEqual({
+ edit: [
+ { name: 'xa', type: 'A', address: '69.69.69.69' },
+ ],
+ add: [],
+ });
+ });
+
+ it('should show added records with the same name and record type', () => {
+ const oldRecords = [
+ { name: 'xx', type: 'CNAME', address: 'fck.com.' },
+ { name: 'xa', type: 'A', address: '69.69.69.69' },
+ ];
+ const newRecords = [
+ { name: 'xx', type: 'CNAME', address: 'fck.com.' },
+ { name: 'xa', type: 'A', address: '69.69.69.69' },
+ { name: 'xa', type: 'A', address: '69.69.4.20' },
+ ];
+
+ const result = diffRecords(oldRecords, newRecords);
+ expect(result).toEqual({
+ edit: [],
+ add: [
+ { name: 'xa', type: 'A', address: '69.69.4.20' },
+ ],
+ });
+ });
+});
+
+describe('Domain service', () => {
+ const addZone = jest.fn(async () => ({}));
+ const editZone = jest.fn(async () => ({}));
+ const addRedir = jest.fn(async () => ({}));
+ const editRedir = jest.fn(async () => ({}));
+
+ const mockDS = ({ zones, redirections }) => getDomainService({ cpanel: getCpanel({
+ zone: async () => zones,
+ redir: async () => redirections,
+ addZone,
+ addRedir,
+ editZone,
+ editRedir,
+ }) });
+
+ const getRecordCalls = recfn => recfn.mock.calls.map(R.head).map(R.pick(['name', 'type', 'address', 'redirect', 'domain']));
+
+ beforeEach(() => {
+ addZone.mockClear();
+ editZone.mockClear();
+ addRedir.mockClear();
+ editRedir.mockClear();
+ });
+
+ describe('getHosts', () => {
it('should resolve with a list of hosts', async () => {
- const records = [ { x: 'y' }, { z: 'a' } ];
+ const zones = [
+ { name: 'xx', type: 'CNAME', address: 'fck.com.' },
+ { name: 'xx', type: 'A', address: '111.1.1212.1' },
+ ];
+ const redirections = [];
+ const zone = async () => zones;
+ const redir = async () => redirections;
+ const mockDomainService = getDomainService({ cpanel: getCpanel({ zone, redir }) });
+ const list = await mockDomainService.getHosts();
- const onSet = jest.fn((list) => {
- expect(list).toBe(records);
- return Promise.resolve(null);
- });
+ expect(list).toEqual([
+ { name: 'xx', type: 'CNAME', address: 'fck.com' },
+ { name: 'xx', type: 'A', address: '111.1.1212.1' },
+ ]);
+ });
- const mockDomainService = getDomainService({ nc: getNc({ onSet }) });
- await mockDomainService.setHosts(records);
- expect(onSet).toBeCalledTimes(1);
+ it('should resolve with a redirections', async () => {
+ const zones = [
+ { name: 'xx', type: 'CNAME', address: 'fck.com.' },
+ { name: 'xx', type: 'A', address: '111.1.1212.1' },
+ ];
+ const redirections = [
+ { domain: 'foo.booboo.xyz', destination: 'https://google.com' },
+ { domain: 'foo1.booboo.xyz', destination: 'https://duck.com' },
+ ];
+ const zone = async () => zones;
+ const redir = async () => redirections;
+ const mockDomainService = getDomainService({ cpanel: getCpanel({ zone, redir }) });
+ const list = await mockDomainService.getHosts();
+
+ expect(list).toEqual([
+ { name: 'xx', type: 'CNAME', address: 'fck.com' },
+ { name: 'xx', type: 'A', address: '111.1.1212.1' },
+ { name: 'foo', type: 'URL', address: 'https://google.com' },
+ { name: 'foo1', type: 'URL', address: 'https://duck.com' },
+ ]);
});
});
describe('updateHosts', () => {
it('should append new hosts with existing ones and set it', async () => {
- const records = [
- { HostId: 1, Name: 'a', Type: 'CNAME', Address: 'boo' },
- { HostId: 2, Name: 'b', Type: 'CNAME', Address: 'goo' },
+ const zones = [
+ { someid: 1, name: 'a', type: 'CNAME', address: 'boo' },
+ { someid: 2, name: 'b', type: 'CNAME', address: 'goo' },
];
+ const redirections = [];
- const onGet = () => Promise.resolve({ hosts: records });
- const onSet = jest.fn(async () => ({}));
-
- const mockDomainService = getDomainService({ nc: getNc({ onSet, onGet }) });
+ const mockDomainService = mockDS({ zones, redirections });
await mockDomainService.updateHosts([
- { HostName: 'a', RecordType: 'CNAME', Address: 'boo' },
- { HostName: 'b', RecordType: 'CNAME', Address: 'goo' },
- { HostName: 'c', RecordType: 'A', Address: '12.131321.213' },
+ { name: 'a', type: 'CNAME', address: 'boo' },
+ { name: 'b', type: 'CNAME', address: 'goo' },
+ { name: 'c', type: 'A', address: '12.131321.213' },
]);
- const [hosts] = onSet.mock.calls[0];
+ expect(addZone).toBeCalledTimes(1);
+ expect(getRecordCalls(addZone)).toEqual([
+ { name: 'c', type: 'A', address: '12.131321.213' },
+ ]);
+ expect(editZone).toBeCalledTimes(0);
+ });
- expect(hosts.map(R.pick(['HostName', 'RecordType', 'Address']))).toEqual([
- { HostName: 'a', RecordType: 'CNAME', Address: 'boo' },
- { HostName: 'b', RecordType: 'CNAME', Address: 'goo' },
- { HostName: 'c', RecordType: 'A', Address: '12.131321.213' },
+ it('should update matching host and set it', async () => {
+ const zones = [
+ { someid: 1, name: 'a', type: 'CNAME', address: 'boo' },
+ { someid: 2, name: 'b', type: 'CNAME', address: 'goo' },
+ ];
+ const redirections = [];
+
+ const mockDomainService = mockDS({ zones, redirections });
+ await mockDomainService.updateHosts([
+ { name: 'a', type: 'CNAME', address: 'boo' },
+ { name: 'b', type: 'CNAME', address: 'googoogaga' },
+ ]);
+
+ expect(addZone).toBeCalledTimes(0);
+ expect(editZone).toBeCalledTimes(1);
+ expect(getRecordCalls(editZone)).toEqual([
+ { name: 'b', type: 'CNAME', address: 'googoogaga' },
]);
});
it('should update matching host and set it', async () => {
- const records = [
- { HostId: 1, Name: 'a', Type: 'CNAME', Address: 'boo' },
- { HostId: 2, Name: 'b', Type: 'CNAME', Address: 'goo' },
+ const zones = [
+ { someid: 1, name: 'a', type: 'CNAME', address: 'boo' },
+ { someid: 2, name: 'b', type: 'CNAME', address: 'goo' },
+ { someid: 2, name: 'b', type: 'CNAME', address: 'xaa' },
];
+ const redirections = [];
- const onGet = () => Promise.resolve({ hosts: records });
- const onSet = jest.fn(async () => ({}));
-
- const mockDomainService = getDomainService({ nc: getNc({ onSet, onGet }) });
+ const mockDomainService = mockDS({ zones, redirections });
await mockDomainService.updateHosts([
- { HostName: 'a', RecordType: 'CNAME', Address: 'boo' },
- { HostName: 'b', RecordType: 'CNAME', Address: 'googoogaga' },
+ { name: 'a', type: 'CNAME', address: 'boo' },
+ { name: 'b', type: 'CNAME', address: 'googoogaga' },
+ { name: 'b', type: 'CNAME', address: 'farboo' },
]);
- const [hosts] = onSet.mock.calls[0];
-
- expect(hosts.map(R.pick(['HostName', 'RecordType', 'Address']))).toEqual([
- { HostName: 'a', RecordType: 'CNAME', Address: 'boo' },
- { HostName: 'b', RecordType: 'CNAME', Address: 'googoogaga' },
+ expect(addZone).toBeCalledTimes(0);
+ expect(editZone).toBeCalledTimes(2);
+ expect(getRecordCalls(editZone)).toEqual([
+ { name: 'b', type: 'CNAME', address: 'googoogaga' },
+ { name: 'b', type: 'CNAME', address: 'farboo' },
]);
});
- it('should update matching host and set it', async () => {
- const records = [
- { HostId: 1, Name: 'a', Type: 'CNAME', Address: 'boo' },
- { HostId: 2, Name: 'b', Type: 'CNAME', Address: 'goo' },
- { HostId: 2, Name: 'b', Type: 'CNAME', Address: 'xaa' },
+ it('should workout this complex example', async () => {
+ const zones = [
+ { someid: 1, name: 'a', type: 'CNAME', address: 'world' },
+ { someid: 2, name: 'b', type: 'A', address: '1' },
+ { someid: 2, name: 'b', type: 'A', address: '2' },
+ { someid: 2, name: 'c', type: 'CNAME', address: 'hello.com' },
+ ];
+ const redirections = [
+ { domain: `b.${DOMAIN_DOMAIN}`, destination: 'https://foobar.com' },
+ { domain: `c.${DOMAIN_DOMAIN}`, destination: 'https://goobar.com' },
+ { domain: `x.${DOMAIN_DOMAIN}`, destination: 'https://example.com' },
];
- const onGet = () => Promise.resolve({ hosts: records });
- const onSet = jest.fn(async () => ({}));
-
- const mockDomainService = getDomainService({ nc: getNc({ onSet, onGet }) });
+ const mockDomainService = mockDS({ zones, redirections });
await mockDomainService.updateHosts([
- { HostName: 'a', RecordType: 'CNAME', Address: 'boo' },
- { HostName: 'b', RecordType: 'CNAME', Address: 'googoogaga' },
- { HostName: 'b', RecordType: 'CNAME', Address: 'farboo' },
+ { name: 'a', type: 'CNAME', address: 'boo' },
+ { name: 'b', type: 'A', address: '1' },
+ { name: 'b', type: 'A', address: '2' },
+ { name: 'b', type: 'A', address: '3' },
+ { name: 'b', type: 'URL', address: 'https://wowow.com' },
+ { name: 'c', type: 'CNAME', address: 'hello.com' },
+ { name: 'c', type: 'URL', address: 'https://goobar.com' },
+ { name: 'd', type: 'CNAME', address: 'helo.com' },
+ { name: 'd', type: 'URL', address: 'https://hhh.com' },
+ { name: 'x', type: 'URL', address: 'https://example69.com' },
]);
- const [hosts] = onSet.mock.calls[0];
-
- expect(hosts.map(R.pick(['HostName', 'RecordType', 'Address']))).toEqual([
- { HostName: 'a', RecordType: 'CNAME', Address: 'boo' },
- { HostName: 'b', RecordType: 'CNAME', Address: 'googoogaga' },
- { HostName: 'b', RecordType: 'CNAME', Address: 'farboo' },
+ expect(addZone).toBeCalledTimes(2);
+ expect(editZone).toBeCalledTimes(1);
+ expect(addRedir).toBeCalledTimes(1);
+ expect(editRedir).toBeCalledTimes(2);
+ expect(getRecordCalls(addZone)).toEqual([
+ { name: 'b', type: 'A', address: '3' },
+ { name: 'd', type: 'CNAME', address: 'helo.com' }
+ ]);
+ expect(getRecordCalls(editZone)).toEqual([
+ { name: 'a', type: 'CNAME', address: 'boo' },
+ ]);
+ expect(getRecordCalls(addRedir)).toEqual([
+ { domain: `d.${DOMAIN_DOMAIN}`, type: 'permanent', redirect: 'https://hhh.com' },
+ ]);
+ expect(getRecordCalls(editRedir)).toEqual([
+ { domain: `b.${DOMAIN_DOMAIN}`, type: 'permanent', redirect: 'https://wowow.com' },
+ { domain: `x.${DOMAIN_DOMAIN}`, type: 'permanent', redirect: 'https://example69.com' },
]);
});
});
diff --git a/tests/domains.test.js b/tests/domains.test.js
index 37c59575e7..7f219fec4c 100644
--- a/tests/domains.test.js
+++ b/tests/domains.test.js
@@ -1,7 +1,14 @@
const R = require('ramda');
+const fs = require('fs');
const { getDomains, validateDomainData } = require('../utils/domain');
+const { DOMAINS_PATH } = require('../utils/constants');
describe('Domains', () => {
+ it('should all be json', async () => {
+ const files = await fs.promises.readdir(DOMAINS_PATH, {});
+ expect(files.filter(f => !/\.json$/g.test(f)).length).toBe(0);
+ });
+
it('should be valid', (done) => {
getDomains()
.then(R.map(data => {
diff --git a/tests/register.test.js b/tests/register.test.js
index 23d1ffd439..0a87f2f4ec 100644
--- a/tests/register.test.js
+++ b/tests/register.test.js
@@ -1,11 +1,18 @@
+const R = require('ramda');
const { toHostList, registerDomains } = require('../scripts/register-domains');
-const { TTL } = require('../utils/constants');
+const { TTL, DOMAIN_DOMAIN } = require('../utils/constants');
const { getDomainService } = require('../utils/domain-service');
-const getNc = ({ onSet, onGet } = {}) => ({
- dns: {
- setHosts: (_, list) => onSet(list),
- getHosts: (_) => onGet(),
+const getCpanel = ({ zone, addZone, editZone, redir, addRedir, editRedir } = {}) => ({
+ zone: {
+ fetch: (_) => zone(),
+ add: (rec) => addZone(rec),
+ edit: (rec) => editZone(rec),
+ },
+ redirection: {
+ fetch: (_) => redir(),
+ add: (rec) => addRedir(rec),
+ edit: (rec) => editRedir(rec),
},
});
@@ -18,113 +25,80 @@ describe('toHostList', () => {
]);
expect(res).toEqual([
- { HostName: 'akshay', RecordType: 'CNAME', Address: 'phenax.github.io', TTL },
- { HostName: 'foobar', RecordType: 'CNAME', Address: 'v.io', TTL },
- { HostName: 'xx', RecordType: 'A', Address: '1.2.3.4', TTL },
- { HostName: 'xx', RecordType: 'A', Address: '5.6.3.2', TTL },
- { HostName: 'xx', RecordType: 'A', Address: '1.2.31.1', TTL },
+ { name: 'akshay', type: 'CNAME', address: 'phenax.github.io', ttl: TTL },
+ { name: 'foobar', type: 'CNAME', address: 'v.io', ttl: TTL },
+ { name: 'xx', type: 'A', address: '1.2.3.4', ttl: TTL },
+ { name: 'xx', type: 'A', address: '5.6.3.2', ttl: TTL },
+ { name: 'xx', type: 'A', address: '1.2.31.1', ttl: TTL },
]);
});
});
describe('registerDomains', () => {
+ const addZone = jest.fn(async () => ({}));
+ const editZone = jest.fn(async () => ({}));
+ const addRedir = jest.fn(async () => ({}));
+ const editRedir = jest.fn(async () => ({}));
+
+ const mockDS = ({ zones, redirections }) => getDomainService({ cpanel: getCpanel({
+ zone: async () => zones,
+ redir: async () => redirections,
+ addZone,
+ addRedir,
+ editZone,
+ editRedir,
+ }) });
+
+ beforeEach(() => {
+ addZone.mockClear();
+ editZone.mockClear();
+ addRedir.mockClear();
+ editRedir.mockClear();
+ });
+
it('should register the new set of hosts generated from domains list', async () => {
const localHosts = [
{ name: 'a', record: { CNAME: 'hello' } },
{ name: 'b', record: { CNAME: 'xaa' } },
];
const remoteHosts = [
- { HostId: 1, Name: 'a', Type: 'CNAME', Address: 'boo' },
- { HostId: 2, Name: 'b', Type: 'CNAME', Address: 'goo' },
- { HostId: 2, Name: 'b', Type: 'CNAME', Address: 'xaa' },
+ { someididk: 1, name: 'a', type: 'CNAME', address: 'hello' },
+ { someididk: 2, name: 'b', type: 'CNAME', address: 'goo' },
+ { someididk: 2, name: 'b', type: 'CNAME', address: 'xaa' },
];
+ const remoteRedirections = [];
- const onSet = jest.fn(async () => ({}));
-
- const domainService = getDomainService({ nc: getNc({ onSet, onGet: async () => ({ hosts: remoteHosts }) }) });
+ const domainService = mockDS({ zones: remoteHosts, redirections: remoteRedirections });
await registerDomains({ getDomains: async () => localHosts, domainService });
- expect(onSet).toBeCalledTimes(1);
-
- const [hosts] = onSet.mock.calls[0];
- expect(hosts).toEqual([
- { HostId: 1, Address: 'hello', HostName: 'a', RecordType: 'CNAME', TTL },
- { HostId: 2, Address: 'xaa', HostName: 'b', RecordType: 'CNAME', TTL },
- ]);
+ expect(addZone).toBeCalledTimes(0);
+ expect(editZone).toBeCalledTimes(0);
+ expect(addRedir).toBeCalledTimes(0);
+ expect(editRedir).toBeCalledTimes(0);
});
it('should add the new set hosts', async () => {
const localHosts = [
- { name: 'a', record: { CNAME: 'boo' } },
- { name: 'b', record: { CNAME: 'xaa' } },
- { name: 'c', record: { CNAME: 'yello' } },
+ { name: 'a', record: { CNAME: 'boo', URL: 'z' } },
+ { name: 'b', record: { CNAME: 'xaa', URL: 'x' } },
+ { name: 'c', record: { CNAME: 'yello', URL: 'https://google.com' } },
];
const remoteHosts = [
- { HostId: 1, Name: 'a', Type: 'CNAME', Address: 'boo' },
- { HostId: 2, Name: 'b', Type: 'CNAME', Address: 'xaa' },
+ { someididk: 1, name: 'a', type: 'CNAME', address: 'boo' },
+ { someididk: 2, name: 'b', type: 'CNAME', address: 'xaa' },
+ ];
+ const remoteRedirections = [
+ { domain: `b.${DOMAIN_DOMAIN}`, destination: 'x' },
+ { domain: `a.${DOMAIN_DOMAIN}`, destination: 'y' },
];
- const onSet = jest.fn(async () => ({}));
-
- const domainService = getDomainService({ nc: getNc({ onSet, onGet: async () => ({ hosts: remoteHosts }) }) });
+ const domainService = mockDS({ zones: remoteHosts, redirections: remoteRedirections });
await registerDomains({ getDomains: async () => localHosts, domainService });
- expect(onSet).toBeCalledTimes(1);
-
- const [hosts] = onSet.mock.calls[0];
- expect(hosts).toEqual([
- { HostId: 1, Address: 'boo', HostName: 'a', RecordType: 'CNAME', TTL },
- { HostId: 2, Address: 'xaa', HostName: 'b', RecordType: 'CNAME', TTL },
- { Address: 'yello', HostName: 'c', RecordType: 'CNAME', TTL },
- ]);
- });
-
- it('should remove unlisted hosts', async () => {
- const localHosts = [
- { name: 'a', record: { CNAME: 'boo' } },
- ];
- const remoteHosts = [
- { HostId: 1, Name: 'a', Type: 'CNAME', Address: 'boo' },
- { HostId: 2, Name: 'b', Type: 'CNAME', Address: 'xaa' },
- ];
-
- const onSet = jest.fn(async () => ({}));
-
- const domainService = getDomainService({ nc: getNc({ onSet, onGet: async () => ({ hosts: remoteHosts }) }) });
- await registerDomains({ getDomains: async () => localHosts, domainService });
-
- expect(onSet).toBeCalledTimes(1);
-
- const [hosts] = onSet.mock.calls[0];
- expect(hosts).toEqual([
- { HostId: 1, Address: 'boo', HostName: 'a', RecordType: 'CNAME', TTL },
- ]);
- });
-
- it('should change record type from cname to a', async () => {
- const localHosts = [
- { name: 'a', record: { CNAME: 'boo' } },
- { name: 'b', record: { A: ['1', '2', '3'] } },
- ];
- const remoteHosts = [
- { HostId: 1, Name: 'a', Type: 'CNAME', Address: 'boo' },
- { HostId: 2, Name: 'b', Type: 'CNAME', Address: 'xaa' },
- ];
-
- const onSet = jest.fn(async () => ({}));
-
- const domainService = getDomainService({ nc: getNc({ onSet, onGet: async () => ({ hosts: remoteHosts }) }) });
- await registerDomains({ getDomains: async () => localHosts, domainService });
-
- expect(onSet).toBeCalledTimes(1);
-
- const [hosts] = onSet.mock.calls[0];
- expect(hosts).toEqual([
- { HostId: 1, Address: 'boo', HostName: 'a', RecordType: 'CNAME', TTL },
- { Address: '1', HostName: 'b', RecordType: 'A', TTL },
- { Address: '2', HostName: 'b', RecordType: 'A', TTL },
- { Address: '3', HostName: 'b', RecordType: 'A', TTL },
- ]);
+ expect(addZone).toBeCalledTimes(1);
+ expect(editZone).toBeCalledTimes(0);
+ expect(addRedir).toBeCalledTimes(1);
+ expect(editRedir).toBeCalledTimes(1);
});
});
diff --git a/utils/constants.js b/utils/constants.js
index 89a9b627fa..086bb0f29b 100644
--- a/utils/constants.js
+++ b/utils/constants.js
@@ -1,21 +1,26 @@
const path = require('path');
-const { ENV = 'sandbox', CI } = process.env;
+const { ENV = 'test', CI } = process.env;
if (!CI) {
require('dotenv').config({ path: path.resolve(`.env.${ENV}`) });
}
-const { NC_USER, NC_API_KEY, NC_DOMAIN, IP_ADDRESS } = process.env;
+const { DOMAIN_USER, DOMAIN_API_KEY, DOMAIN_DOMAIN, DOMAIN_API_HOST, DOMAIN_API_PORT } = process.env;
const IS_TEST = ENV === 'test';
+const DOMAINS_PATH = require('path').resolve('domains');
+
module.exports = {
ENV,
- VALID_RECORD_TYPES: ['CNAME', 'A', 'ALIAS', 'URL'],
- NC_DOMAIN: NC_DOMAIN || 'booboo.xyz',
- NC_USER: IS_TEST ? 'testuser' : NC_USER,
- NC_API_KEY: IS_TEST ? 'testkey' : NC_API_KEY,
- IP_ADDRESS,
- TTL: 5*60,
+ IS_TEST,
+ VALID_RECORD_TYPES: ['CNAME', 'A', 'URL'],
+ DOMAIN_DOMAIN: DOMAIN_DOMAIN || 'booboo.xyz',
+ DOMAIN_USER: IS_TEST ? 'testuser' : DOMAIN_USER,
+ DOMAIN_API_KEY: IS_TEST ? 'testkey' : DOMAIN_API_KEY,
+ DOMAIN_API_HOST: IS_TEST ? 'example.com' : DOMAIN_API_HOST,
+ DOMAIN_API_PORT: IS_TEST ? 6969 : DOMAIN_API_PORT,
+ DOMAINS_PATH,
+ TTL: 5*60*60,
};
diff --git a/utils/domain-service.js b/utils/domain-service.js
index 0831f3cb25..733ca29b6d 100644
--- a/utils/domain-service.js
+++ b/utils/domain-service.js
@@ -1,72 +1,146 @@
const R = require('ramda');
-const Namecheap = require('@rqt/namecheap');
-const { NC_DOMAIN, NC_USER, NC_API_KEY, ENV, IP_ADDRESS } = require('../utils/constants');
+const { cpanel } = require('./lib/cpanel');
+const { DOMAIN_DOMAIN, IS_TEST } = require('./constants');
-const IS_SANDBOX = ENV === 'sandbox';
+const log = IS_TEST ? () => {} : console.log;
-const getDomainService = ({ nc }) => {
+const recordToRedirection = ({ name, address }) => ({
+ domain: `${name}.${DOMAIN_DOMAIN}`,
+ redirect: address,
+ type: 'permanent',
+ redirect_wildcard: 1,
+ redirect_www: 1,
+});
+const recordToZone = ({ name, type, address, ...rec }) => ({
+ ...rec, //line
+ name,
+ type,
+ address,
+ ...(type === 'CNAME' ? { cname: address } : {}),
+});
+
+const cleanName = name => `${name}`.replace(new RegExp(`\.${DOMAIN_DOMAIN}\.?$`), '').toLowerCase();
+
+const zoneToRecord = ({ name, type, cname, address, record, ...host }) => ({
+ ...host,
+ name: cleanName(name),
+ type: `${type}`,
+ address: `${cname || address || record}`.replace(/\.$/g, '').toLowerCase(),
+});
+const redirectionToRecord = ({ domain, destination }) => ({
+ name: cleanName(domain),
+ type: 'URL',
+ address: `${destination}`.replace(/\/$/g, ''),
+});
+
+const getHostKey = host => `${host.name}##${host.type}`;
+
+const toHostMap = hosts => hosts.reduce((acc, host) => {
+ const key = getHostKey(host);
+ return { ...acc, [key]: [ ...(acc[key] || []), host ] };
+}, {});
+
+const diffRecords = (oldRecords, newRecords) => {
+ const remoteHostMap = toHostMap(oldRecords);
+ const localHostMap = toHostMap(newRecords);
+
+ return R.toPairs(localHostMap).reduce((acc, [key, local]) => {
+ const remote = remoteHostMap[key];
+
+ if (remote) {
+ let adds = [];
+ let edits = [];
+
+ const diff = R.differenceWith((a, b) => a.address === b.address, local, remote);
+
+ if (diff.length === local.length - remote.length) {
+ adds = diff;
+ } else {
+ edits = diff;
+ }
+
+ return { ...acc, add: acc.add.concat(adds), edit: acc.edit.concat(edits) };
+ }
+
+ return { ...acc, add: acc.add.concat(local) };
+ }, { add: [], edit: [] });
+};
+
+const lazyTask = fn => data => () => fn(data);
+
+const batchLazyTasks = count => tasks => tasks.reduce((batches, task) => {
+ if (batches.length === 0) return [[task]];
+
+ const full = R.init(batches);
+ const last = R.last(batches);
+
+ if (last.length >= count) return [...batches, [task]];
+ return [...full, [...last, task]];
+}, []);
+
+const executeBatch = (batches) => batches.reduce((promise, batch, index) => {
+ return promise.then(async () => {
+ log('>>> Running batch number:', index + 1, `(size: ${batch.length})`);
+
+ const values = await Promise.all(batch.map(fn => fn().catch(e => console.error(e))));
+
+ const results = values.map(R.pathOr({}, ['cpanelresult', 'data', 0]));
+ const failed = results.filter(x => (x.result || {}).status != 1);
+
+ log(`${values.length - failed.length}/${values.length}`);
+ failed.length && log(failed);
+
+ return null;
+ });
+}, Promise.resolve());
+
+const getDomainService = ({ cpanel }) => {
let hostList = [];
+ const fetchZoneRecords = () => cpanel.zone.fetch().then(R.map(zoneToRecord));
+ const fetchRedirections = () => cpanel.redirection.fetch().then(R.map(redirectionToRecord));
+
+ const addZoneRecord = lazyTask(R.compose(cpanel.zone.add, recordToZone));
+ const editZoneRecord = lazyTask(R.compose(cpanel.zone.edit, recordToZone));
+ const addRedirection = lazyTask(R.compose(cpanel.redirection.add, recordToRedirection));
+ const editRedirection = lazyTask(R.compose(cpanel.redirection.edit, recordToRedirection));
+
const getHosts = async () => {
if (hostList.length) return hostList;
- const list = await nc.dns.getHosts(NC_DOMAIN)
- .then(R.propOr([], 'hosts'))
- .then(R.map(host => R.omit(['Name', 'Type'], {
- ...host,
- HostName: host.Name,
- RecordType: host.Type,
- Address: `${host.Address}`.replace(/\.$/g, ''),
- })));
+ const list = await Promise.all([fetchZoneRecords(), fetchRedirections()]).then(R.flatten);
hostList = list;
return list;
};
- const setHosts = hosts => nc.dns.setHosts(NC_DOMAIN, hosts);
+ const BATCH_SIZE = 1;
- const getHostKey = host => `${host.HostName}--${host.RecordType}`;
- const toHostMap = hosts => hosts.reduce((acc, host) => {
- const key = getHostKey(host);
- return { ...acc, [key]: [ ...(acc[key] || []), host ] };
- }, {});
+ const addRecords = R.compose(batchLazyTasks(BATCH_SIZE), R.filter(Boolean), R.map(R.cond([
+ [ R.propEq('name', 'www'), () => null ],
+ [ R.propEq('type', 'URL'), addRedirection ],
+ [ R.T, addZoneRecord ],
+ ])));
+ const editRecords = R.compose(batchLazyTasks(BATCH_SIZE), R.map(R.cond([
+ [ R.propEq('type', 'URL'), editRedirection ],
+ [ R.T, editZoneRecord ],
+ ])));
const updateHosts = async hosts => {
- const hostList = await getHosts();
- const remoteHostMap = toHostMap(hostList);
- const localHostMap = toHostMap(hosts);
+ const remoteHostList = await getHosts();
+ const { add, edit } = diffRecords(remoteHostList, hosts);
- const newHostList = R.toPairs(localHostMap).reduce((acc, [key, local]) => {
- const remote = remoteHostMap[key];
-
- if (remote) {
- return acc.concat(local.map((localItem, index) => R.merge(remote[index], localItem)));
- }
-
- return [...acc, ...local];
- }, []);
-
- return setHosts(newHostList);
+ await executeBatch(addRecords(add).concat(editRecords(edit)));
+ return { additions: add.length, edits: edit.length };
};
- return { getHosts, setHosts, updateHosts };
+ return { getHosts, updateHosts };
};
-if (!NC_API_KEY) {
- console.error('NC_API_KEY cannot be empty');
- process.exit(1);
-}
-
-const nc = new Namecheap({
- user: NC_USER,
- key: NC_API_KEY,
- ip: IP_ADDRESS,
- sandbox: IS_SANDBOX,
-});
-
-const domainService = getDomainService({ nc });
+const domainService = getDomainService({ cpanel });
module.exports = {
getDomainService,
domainService,
+ diffRecords,
};
diff --git a/utils/domain.js b/utils/domain.js
index 089bde4255..f7819f02ab 100644
--- a/utils/domain.js
+++ b/utils/domain.js
@@ -1,9 +1,7 @@
const fs = require('fs');
const path = require('path');
const R = require('ramda');
-const { VALID_RECORD_TYPES } = require('./constants');
-
-const DOMAINS_PATH = path.resolve('domains');
+const { VALID_RECORD_TYPES, DOMAINS_PATH } = require('./constants');
const log = m => x => console.log(m, x) || x;
@@ -38,7 +36,7 @@ const validateDomainData = validate({
R.equals('@'),
R.allPass([
R.compose(between(2, 100), R.length),
- str => str && str.match(/^[A-Za-z0-9\-]+$/ig),
+ str => str && str.match(/^[a-z0-9\-]+$/ig),
])
]),
},
@@ -62,7 +60,6 @@ const validateDomainData = validate({
R.compose(R.isEmpty, R.flip(R.difference)(VALID_RECORD_TYPES), R.keys),
R.cond([
[R.prop('CNAME'), validateNameRecord('CNAME')],
- [R.prop('ALIAS'), validateNameRecord('ALIAS')],
[R.prop('A'), R.propSatisfies(R.is(Array), 'A')],
[R.prop('URL'), R.propSatisfies(R.is(String), 'URL')],
[R.T, R.T],
diff --git a/utils/lib/cpanel.js b/utils/lib/cpanel.js
new file mode 100644
index 0000000000..c29c10145e
--- /dev/null
+++ b/utils/lib/cpanel.js
@@ -0,0 +1,87 @@
+const R = require('ramda');
+const fetch = require('node-fetch');
+const qs = require('qs');
+const { DOMAIN_API_HOST, DOMAIN_API_PORT, DOMAIN_USER, DOMAIN_API_KEY, DOMAIN_DOMAIN } = require('../constants');
+
+const CpanelClient = (options) => {
+ // TODO: Make defaultQuery functional
+ const api = ({ basePath = '', action = '' }) => (module, func, defaultQuery = {}) => (q = {}) => {
+ const query = {
+ ...defaultQuery,
+ ...q,
+ cpanel_jsonapi_user: options.username,
+ cpanel_jsonapi_module: module,
+ cpanel_jsonapi_func: func,
+ cpanel_jsonapi_apiversion: 2,
+ };
+
+ const request = {
+ headers: {
+ Authorization: `cpanel ${options.username}:${options.apiKey}`,
+ },
+ rejectUnauthorized: false,
+ };
+
+ const path = `${basePath}/${action}?${qs.stringify(query)}`;
+ const reqUrl = `https://${options.host}:${options.port}/${path}`;
+
+ const { fetch } = options.dependencies;
+ return fetch(reqUrl, request).then(res => res.json());
+ };
+
+ const api2 = api({ basePath: 'json-api', action: 'cpanel' });
+ const uapi = (module, func, defaultQuery) =>
+ api({ basePath: 'execute', action: `${module}/${func}` })(module, func, defaultQuery);
+
+ return {
+ zone: {
+ // { customonly, domain }
+ // -> { cpanelresult: { data[{ class, ttl, name, line, Line, cname, type, record }] } }
+ fetch: R.compose(
+ p => p.then(R.pathOr([], ['cpanelresult', 'data'])),
+ api2('ZoneEdit', 'fetchzone_records', { customonly: 1, domain: options.domain })
+ ),
+
+ // { name, type(A|CNAME), cname, address, ttl }
+ // -> {}
+ add: api2('ZoneEdit', 'add_zone_record', { domain: options.domain }),
+
+ // { name, type(A|CNAME), cname, address, ttl }
+ // -> {}
+ edit: api2('ZoneEdit', 'edit_zone_record', { domain: options.domain }),
+ },
+ redirection: {
+ // {}
+ // -> { domain, destination }
+ fetch: R.compose(
+ p => p.then(R.pathOr([], ['data'])),
+ uapi('Mime', 'list_redirects'),
+ ),
+
+ // { domain, redirect, type(permanent|tmp), redirect_wildcard(0|1), redirect(0|1|2) }
+ // -> {}
+ add: uapi('Mime', 'add_redirect'),
+ edit: uapi('Mime', 'add_redirect'), // NOTE: adding new updates exisiting
+ },
+ };
+};
+
+if (!DOMAIN_API_KEY) {
+ console.error('Api key cannot be empty');
+ process.exit(1);
+}
+
+const cpanel = CpanelClient({
+ host: DOMAIN_API_HOST,
+ port: DOMAIN_API_PORT,
+ username: DOMAIN_USER,
+ apiKey: DOMAIN_API_KEY,
+ domain: DOMAIN_DOMAIN,
+ dependencies: { fetch },
+});
+
+module.exports = {
+ cpanel,
+ CpanelClient,
+};
+
diff --git a/yarn.lock b/yarn.lock
index 2cb029d016..fb8f6f11e7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -458,11 +458,6 @@
"@types/yargs" "^15.0.0"
chalk "^4.0.0"
-"@rqt/namecheap@^2.4.2":
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/@rqt/namecheap/-/namecheap-2.4.2.tgz#8537eea6efbe7ac4fd449e3aee5f2c1d80986fcf"
- integrity sha512-RfrK7ywOraz0nR/BlQt8fJQDcOfI9cLSTpa6l9JS9ER0HJ6t1FQ8Pxmplj/lVQv8rkczuVADdZVC3HlL98Q31w==
-
"@sinonjs/commons@^1.7.0":
version "1.8.1"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217"
@@ -2468,6 +2463,11 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+node-fetch@^2.6.1:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
+ integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
+
node-int64@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"