Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dispalying locations is better #19

Merged
merged 1 commit into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions eventSuggestion.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import fetchLocationData from './nominatim.js'
import {
fetchLocationData
} from './nominatim.js'


const userStates = {};
Expand Down Expand Up @@ -185,7 +187,6 @@ const handleOptionalField = (bot, chatId, field) => {
};

const sendEventForApproval = (bot, userChatId, eventDetails) => {
console.log(userStates, userChatId);
userStates[userChatId].pendingEvent = eventDetails;
const adminChatId = process.env.ADMIN_CHAT_ID;
const userInfo = userStates[userChatId];
Expand Down
9 changes: 8 additions & 1 deletion handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ const handleAdminApproval = async (bot, callbackQuery) => {
console.log(`Event ${isApproved ? 'approved' : 'rejected'} for user ${userChatId}`);

if (isApproved) {
console.log(userStates, userChatId);
const eventDetails = userStates[userChatId].pendingEvent;
if (!eventDetails) {
console.error('No pending event found for user', userChatId);
Expand Down Expand Up @@ -712,7 +711,15 @@ const handleCallbackQuery = async (bot, callbackQuery) => {
});
await bot.deleteMessage(chatId, msg.message_id);
} else if (action === 'confirm_location') {
console.log("local: ", userStates[chatId].tempLocation.data);
const locationData = userStates[chatId].tempLocation.data;
const lat = locationData.lat;
const lon = locationData.lon;
const googleMapsLink = `https://www.google.com/maps/search/?api=1&query=${lat},${lon}`;
const osmLink = "https://www.openstreetmap.org/" + locationData.osm_type + "/" + locationData.osm_id;

userStates[chatId].osm_link = osmLink;
userStates[chatId].gmaps_link = googleMapsLink;
userStates[chatId].location = locationData.display_name;
userStates[chatId].step = 'description';
bot.sendMessage(chatId, 'Großartig! Zum Schluss, gib bitte eine kurze Beschreibung des Events ein:\n\nOder tippe /cancel um abzubrechen.', {
Expand Down
57 changes: 57 additions & 0 deletions helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const escapeHTML = (text) => {
return text
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
};

const extractTelegramUsername = (tags) => {
const rTag = tags.find(t => t[0] === 'r' && t[1].startsWith('https://t.me/'));
if (rTag) {
const username = rTag[1].split('/').pop();
return `@${username}`;
}
return null;
};

const formatLocation = (location, googleMapsLink, osmLink) => {
const suffix = ', Schweiz/Suisse/Svizzera/Svizra';
let formattedLocation = location.endsWith(suffix) ? location.slice(0, -suffix.length).trim() : location;

let result = `📍 ${escapeHTML(formattedLocation)}\n`;
if (googleMapsLink || osmLink) {
result += ' ';
if (googleMapsLink) {
result += `🌍 <a href="${googleMapsLink}">Google Maps</a>`;
}
if (googleMapsLink && osmLink) {
result += ' | ';
}
if (osmLink) {
result += `🕵️ <a href="${osmLink}">OpenStreetMap</a>`;
}
result += '\n';
}
return result;
};

const formatDate = (timestamp) => {
const date = new Date(timestamp);
return date.toLocaleString('de-CH', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false
});
};

export {
extractTelegramUsername,
formatLocation,
formatDate,
escapeHTML
};
4 changes: 3 additions & 1 deletion nominatim.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ const fetchLocationData = async (query) => {
}
};

export default fetchLocationData;
export {
fetchLocationData
};
7 changes: 4 additions & 3 deletions nostrUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ const publishEventToNostr = async (eventDetails) => {

const eventId = crypto.randomBytes(16).toString('hex');
const startTimestamp = Math.floor(new Date(`${eventDetails.date}T${eventDetails.time}`).getTime() / 1000);
const geohash = ngeohash.encode(eventDetails.latitude, eventDetails.longitude);
const geohash = ngeohash.encode(eventDetails.latitude, eventDetails.longitude); //TODO fix geohash by setting at fetch

eventTemplate = {
kind: 31923, // Time-Based Calendar Event
Expand All @@ -223,11 +223,12 @@ const publishEventToNostr = async (eventDetails) => {
['p', calendarPubkey, '', 'host'],
['a', calendarNaddr],
['calendar', `31924:${calendarPubkey}:${calendarIdentifier}`],
['r', eventDetails.gmaps_link],
['r', eventDetails.osm_link],
['r', "https://t.me/g1ll0hn3r"], //TODO: add user
],
};

console.log("eventTemplate: ", eventTemplate)

if (eventDetails.end_date && eventDetails.end_time) {
const endTimestamp = Math.floor(new Date(`${eventDetails.end_date}T${eventDetails.end_time}`).getTime() / 1000);
eventTemplate.tags.push(['end', endTimestamp.toString()]);
Expand Down
93 changes: 42 additions & 51 deletions utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,80 +4,71 @@ import {
import {
checkForDeletionEvent
} from './nostrUtils.js';
import ngeohash from 'ngeohash';
import {
extractTelegramUsername,
formatLocation,
formatDate,
escapeHTML
} from './helpers.js'

const escapeHTML = (text) => {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
};

const formatMeetupsMessage = async (allEvents, timeFrame) => {
let headerMessage;
const getHeaderMessage = (timeFrame) => {
switch (timeFrame) {
case 'today':
headerMessage = '🗓 Meetups heute';
break;
return 'Meetups heute';
case 'week':
headerMessage = '🗓 Meetups diese Woche';
break;
return 'Meetups diese Woche';
case 'month':
headerMessage = '🗓 Meetups diesen Monat';
break;
return 'Meetups diesen Monat';
default:
headerMessage = '🗓 Alle bevorstehenden Meetups';
return 'Alle bevorstehenden Meetups';
}
};

let message = `<b>${headerMessage}</b>\n\n`;
const formatMeetupsMessage = async (allEvents, timeFrame) => {
let message = `🍻 <b>${getHeaderMessage(timeFrame)}</b>\n\n`;

for (const {
calendarName,
events,
naddr
} of allEvents) {
for (const { calendarName, events, naddr } of allEvents) {
if (events.length > 0) {
const calendarUrl = `https://www.flockstr.com/calendar/${naddr}`;
message += `<b>📅 <a href="${calendarUrl}">${escapeHTML(calendarName)}</a></b>\n\n`;

const uniqueEvents = events.reduce((acc, event) => {
const eventId = event.id;
if (!acc.some(e => e.id === eventId)) {
acc.push(event);
}
return acc;
}, []);
for (const event of events) {
if (await checkForDeletionEvent(event.id)) continue;

uniqueEvents.sort((a, b) => {
const aStart = parseInt(a.tags.find(t => t[0] === 'start')?. [1] || '0');
const bStart = parseInt(b.tags.find(t => t[0] === 'start')?. [1] || '0');
return aStart - bStart;
});
const title = event.tags.find(t => t[0] === 'name')?.[1] || event.tags.find(t => t[0] === 'title')?.[1];
if (!title) continue;

for (const event of uniqueEvents) {
// Check for deletion event
const isDeleted = await checkForDeletionEvent(event.id);
if (isDeleted) {
console.log(`Event ${event.id} has been deleted. Skipping.`);
continue; // Skip this event if it has been deleted
}
const start = event.tags.find(t => t[0] === 'start')?.[1];
if (!start) continue;

const locationTag = event.tags.find(t => t[0] === 'location');
const location = locationTag ? locationTag[1] : null;

const title = escapeHTML(event.tags.find(t => t[0] === 'name')?. [1] || event.tags.find(t => t[0] === 'title')?. [1] || 'Unbenanntes Meetup');
const start = new Date(parseInt(event.tags.find(t => t[0] === 'start')?. [1] || '0') * 1000);
const location = escapeHTML(event.tags.find(t => t[0] === 'location')?. [1] || 'Kein Ort angegeben');
const eventNaddr = nip19.naddrEncode({
kind: event.kind,
pubkey: event.pubkey,
identifier: event.tags.find(t => t[0] === 'd')?. [1] || '',
identifier: event.tags.find(t => t[0] === 'd')?.[1] || '',
});
const eventUrl = `https://www.flockstr.com/event/${eventNaddr}`;

message += `<b> 🎉 <a href="${eventUrl}">${title}</a></b>\n`;
message += ` 🕒 <i>Datum:</i> ${start.toLocaleString('de-CH')}\n`;
message += ` 📍 <i>Ort:</i> ${location}\n\n`;
}
message += `🎉 <b><a href="${eventUrl}">${escapeHTML(title)}</a></b>\n`;
if (start) message += `🕒 ${formatDate(parseInt(start) * 1000)}\n`;

message += '\n';
if (location) {
const googleMapsLink = event.tags.find(t => t[0] === 'r' && t[1].includes('google.com/maps'))?.[1];
const osmLink = event.tags.find(t => t[0] === 'r' && t[1].includes('openstreetmap.org'))?.[1];
message += formatLocation(location, googleMapsLink, osmLink);
}

// Handle Telegram link
const telegramLink = event.tags.find(t => t[0] === 'r' && t[1].includes('t.me'));
if (telegramLink && false) { //TODO: tg organ implement
message += `👤 <b>Organisator:</b> <a href="${telegramLink[1]}">DM</a>\n`;
}

message += '\n';
}
}
}

Expand Down
Loading