-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
129 lines (109 loc) · 4.14 KB
/
script.js
File metadata and controls
129 lines (109 loc) · 4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import securelayEndpoint from 'https://cdn.jsdelivr.net/gh/securelay/api@v0.0.8/script.min.js';
// Brief: Returns the first 5 hex chars from a v4 UUID as a unique string
function newVisitorID () {
return crypto.randomUUID().substr(0, 5);
}
// Brief: Returns {formActionURL, visitorID} if ok, Booelan false otherwise.
async function validate () {
const securelayAddrKey = decodeURIComponent(location.pathname.split('/').pop());
const [securelayPubKey, securelayEndpointID] = securelayAddrKey.split('@');
if (!(securelayPubKey && securelayEndpointID)) return false;
try {
const securelayEndpointURL = securelayEndpoint(securelayEndpointID)[0];
const formActionURL = securelayEndpointURL + '/public/' + securelayPubKey;
const cacheKey = ('visitorID@' + location.pathname);
const oldVisitorID = localStorage.getItem(cacheKey);
if (oldVisitorID) return { formActionURL, visitorID: oldVisitorID };
const response = await fetch(formActionURL.replace('public', 'keys'));
if (!response.ok) throw new Error(404);
const type = await response.json().then((obj) => obj.type);
if (type !== 'public') throw new Error(404);
const visitorID = newVisitorID();
localStorage.setItem(cacheKey, visitorID);
submitNewView(securelayPubKey);
return { formActionURL, visitorID };
} catch (err) {
return false;
}
}
function logChat (msg, received = true) {
const chatbox = document.getElementById('chatbox');
const row = document.createElement('p');
let sender = 'You';
if (received) sender = 'Me';
const entry = `${sender} @ ${Date().split(' ')[4]}: ${msg}`;
row.append(entry);
chatbox.prepend(row);
}
async function loadReply (chatURL) {
return fetch(chatURL)
.then((response) => {
if (!response.ok) throw new Error(response.status);
return response.json();
})
.then((data) => data.Message)
.then((reply) => {
logChat(reply);
})
.catch((err) => err.message);
}
async function geolocateByIP () {
const apiEndpoint = 'https://ipapi.co/json/'; // 'http://ip-api.com/json/?fields=25';
return fetch(apiEndpoint)
.then((response) => {
if (!response.ok) throw new Error(response.status);
return response.json();
})
.then((obj) => [obj.country_name, obj.region, obj.city].join('/'))
.catch((err) => '');
}
async function setupGeolocation (field) {
const fallback = async (err) => {
field.value = await geolocateByIP();
};
const byDevice = (position) => {
field.value = position.coords.latitude + ',' + position.coords.longitude;
};
if (!navigator.geolocation || field.className.split(' ').includes('geolocate-by-ip')) {
await fallback();
} else {
navigator.geolocation.getCurrentPosition(byDevice, fallback);
}
}
async function setupForm (formActionURL, visitorID) {
const contactForm = document.forms.contact;
const checkImgURL = 'https://img.icons8.com/color/30/approval--v1.png';
const crossImgURL = 'https://img.icons8.com/emoji/30/cross-mark-emoji.png';
const query = `?app=formonit&ok=${encodeURIComponent(checkImgURL)}&err=${encodeURIComponent(crossImgURL)}`;
contactForm.elements.ChatID.value = visitorID;
contactForm.action = formActionURL + query;
contactForm.addEventListener('submit', async (event) => {
const thisForm = event.target;
await loadReply(formActionURL + '/' + visitorID);
const msg = thisForm.elements.Message.value;
logChat(msg, false);
});
await setupGeolocation(contactForm.elements.Location);
}
async function submitNewView (securelayPubKey) {
const formID = document.forms.contact.elements.FormID.value;
const url = `https://api.counterapi.dev/v1/${securelayPubKey}/${encodeURIComponent(formID)}/up`;
return fetch(url).catch((err) => {});
}
async function init () {
const { formActionURL, visitorID } = await validate();
spaHide('loading');
if (!formActionURL) {
spaShow('404');
return false;
}
await setupForm(formActionURL, visitorID);
spaShow('form');
const chatURL = formActionURL + '/' + visitorID;
await loadReply(chatURL);
document.getElementById('loadReply').addEventListener('click', (event) => {
loadReply(chatURL);
});
spaShow('chat');
}
init();