You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
6.7 KiB

const membersApiUrl = 'https://lilia.mraveniste.cc/horde-members/api/members';
const featuresApiUrl = 'https://lilia.mraveniste.cc/horde-members/api/features';
6 years ago
const apiKey = 'eyJhbGciOiJIUzUxMiIsImlhdCI6MTU1Mzg5MjYwNSwiZXhwIjoxODY5MjUyNjA1fQ.ImNsaWVudCI.iX2EEEsKbMYpbeU-HB_FcqeepwZn8rkq8XdyfUmr6RJk2-64I744xLdKfrikxskF6_IlJbjBH3jNNcVfWyvswQ';
const discordClientId = '562565397451374593';
const cheeseHordeGuildId = '285154599038353408';
var discordUser = undefined;
6 years ago
function store(feature) {
var writer = new ol.format.GeoJSON({
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
});
$.ajax({
url: featuresApiUrl,
6 years ago
type: 'post',
contentType: 'application/json',
data: writer.writeFeature(feature),
headers: {'X-Members-API-Key': apiKey}
});
}
function remove(id) {
$.ajax({
url: `${membersApiUrl}/${id}`,
type: 'delete',
headers: {'X-Members-API-Key': apiKey}
});
}
6 years ago
function getColor(nick, alpha) {
var r = 0;
var g = 0;
var b = 0;
var p1 = nick.length * 351 / 1000 >> 0;
var p2 = p1 + nick.length * 206 / 1000 >> 0;
nick.slice(0, p1).split('').map((c) => {
r += c.charCodeAt(0)
});
nick.slice(p1, p2).split('').map((c) => {
g += c.charCodeAt(0)
});
nick.slice(p2).split('').map((c) => {
b += c.charCodeAt(0)
});
r %= 256;
g %= 256;
b %= 256;
var k = (299 * r + 587 * g + 114 * b) / 1000;
while (k > 123) {
if (r > 0) r--;
if (g > 0) g--;
if (b > 0) b--;
k = (299 * r + 587 * g + 114 * b) / 1000;
}
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
var discord = new LoginWithDiscord({
clientID: discordClientId,
scopes: [
Scope.Identify,
Scope.Guilds
],
cache: true
});
discord.onlogin = async () => {
var user = await discord.fetchUser();
var guilds = await discord.fetchGuilds();
var horde = guilds.find((guild) => guild.id == cheeseHordeGuildId);
if (horde !== undefined) {
discordUser = user;
var button = discordControl.element.firstElementChild;
button.innerHTML = `${discordUser.username}: Log out`;
button.style.display = null;
}
}
discord.onlogout = async () => {
discordUser = undefined;
var button = discordControl.element.firstElementChild;
button.innerHTML = 'Log in with Discord';
button.style.display = null;
};
async function discordLogin() {
await discord.login();
}
async function discordLogout() {
await discord.logout();
}
var DiscordControl = (function(Control) {
function DiscordControl(opt_options) {
6 years ago
var options = opt_options || {};
var button = document.createElement('button');
button.style.display = 'none';
6 years ago
var element = document.createElement('div');
element.className = 'discord-control ol-unselectable ol-control';
6 years ago
element.appendChild(button);
Control.call(this, {
element: element,
target: options.target
});
button.addEventListener('click', this.handleClick.bind(this), false);
6 years ago
}
if (Control)
DiscordControl.__proto__ = Control;
6 years ago
DiscordControl.prototype = Object.create(Control && Control.prototype);
DiscordControl.prototype.constructor = DiscordControl;
6 years ago
DiscordControl.prototype.handleClick = function() {
if (!discordUser)
discordLogin();
else
discordLogout();
6 years ago
};
return DiscordControl;
6 years ago
}(ol.control.Control));
var discordControl = new DiscordControl();
6 years ago
var source = new ol.source.Vector({
url: featuresApiUrl,
6 years ago
wrapX: false,
format: new ol.format.GeoJSON({
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
})
});
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var vector = new ol.layer.Vector({
source: source,
style: (feature) => new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({
color: getColor(feature.get('nick'), 0.8)
})
}),
text: new ol.style.Text({
text: feature.get('nick'),
font: '12pt sans-serif',
textAlign: 'left',
offsetY: -20,
fill: new ol.style.Fill({
color: 'rgba(0, 0, 0, 0.8)'
}),
backgroundFill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.8)'
}),
backgroundStroke: new ol.style.Stroke({
color: 'rgba(0, 0, 0, 0.8)',
width: 1
}),
padding: [2, 3, 1, 3]
})
})
});
var map = new ol.Map({
target: 'map',
layers: [raster, vector],
view: new ol.View({
center: [0, 0],
minZoom: 2,
zoom: 2
}),
controls: ol.control.defaults().extend([
discordControl
6 years ago
])
});
var snap = new ol.interaction.Snap({
source: source
});
map.addInteraction(snap);
var modify = new ol.interaction.Modify({
source: source,
condition: (evt) => {
if (!discordUser)
6 years ago
return false;
var feature = source.getClosestFeatureToCoordinate(evt.coordinate);
if (!feature)
return false;
return feature.get('id') == discordUser.id;
6 years ago
}
});
modify.on('modifyend', (evt) => {
var feature = evt.features.getArray().find((feature) => feature.getRevision() > 1);
store(feature);
});
map.addInteraction(modify);
var draw = new ol.interaction.Draw({
source: source,
type: 'Point',
condition: (evt) => {
if (!discordUser)
6 years ago
return false;
var feature = source.forEachFeature((feature) => {
if (feature.get('id') == discordUser.id)
6 years ago
return feature;
});
if (feature === undefined)
6 years ago
return true;
var features = [];
// FIXME: allows duplication
6 years ago
map.forEachFeatureAtPixel(evt.pixel, (feature) => {
features.push(feature);
});
return features.length > 1;
}
});
draw.on('drawend', (evt) => {
evt.feature.set('id', discordUser.id);
evt.feature.set('nick', discordUser.username);
store(evt.feature);
});
map.addInteraction(draw);
document.addEventListener('keydown', (evt) => {
if (evt.code != 'Delete')
return;
if (!discordUser)
return;
6 years ago
var feature = source.forEachFeature((feature) => {
if (feature.get('id') == discordUser.id)
6 years ago
return feature;
});
if (feature === undefined)
return;
6 years ago
if (confirm('Are you sure you want to remove yourself?'))
{
source.removeFeature(feature);
6 years ago
remove(discordUser.id);
}
6 years ago
});