mirror of
https://github.com/FoggedLens/deflock.git
synced 2026-05-23 16:09:57 +02:00
separate fe and be, deploy on push to master
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
|
||||
const GITHUB_TOKEN = process.env.GITHUB_TOKEN || '';
|
||||
const graphQLEndpoint = 'https://api.github.com/graphql';
|
||||
|
||||
export const SponsorSchema = Type.Object({
|
||||
sponsor: Type.Object({
|
||||
avatarUrl: Type.String(),
|
||||
login: Type.String(),
|
||||
name: Type.Union([Type.String(), Type.Null()]),
|
||||
url: Type.String(),
|
||||
}),
|
||||
});
|
||||
|
||||
export type Sponsor = Static<typeof SponsorSchema>;
|
||||
|
||||
export const SponsorsResponseSchema = Type.Array(SponsorSchema);
|
||||
|
||||
export class GithubClient {
|
||||
async getSponsors(username: string): Promise<Sponsor[]> {
|
||||
const query = `query { user(login: \"${username}\") { sponsorshipsAsMaintainer(first: 100) { nodes { sponsor { login name avatarUrl url } } } } }`;
|
||||
const body = JSON.stringify({ query, variables: '' });
|
||||
const response = await fetch(graphQLEndpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${GITHUB_TOKEN}`,
|
||||
'User-Agent': 'Shotgun',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body,
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to get sponsors: ${response.status}`);
|
||||
}
|
||||
const json = await response.json();
|
||||
return json?.data?.user?.sponsorshipsAsMaintainer?.nodes || [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
import { createCache, Cache } from 'cache-manager';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
const { DiskStore } = require('cache-manager-fs-hash');
|
||||
|
||||
export const NominatimResultSchema = Type.Object({
|
||||
addresstype: Type.String(),
|
||||
boundingbox: Type.Tuple([Type.String(), Type.String(), Type.String(), Type.String()]),
|
||||
class: Type.String(),
|
||||
display_name: Type.String(),
|
||||
geojson: Type.Object({
|
||||
coordinates: Type.Any(),
|
||||
type: Type.String(),
|
||||
}),
|
||||
importance: Type.Number(),
|
||||
lat: Type.String(),
|
||||
licence: Type.String(),
|
||||
lon: Type.String(),
|
||||
name: Type.String(),
|
||||
osm_id: Type.Number(),
|
||||
osm_type: Type.String(),
|
||||
place_id: Type.Number(),
|
||||
place_rank: Type.Number(),
|
||||
type: Type.String(),
|
||||
});
|
||||
|
||||
export type NominatimResult = Static<typeof NominatimResultSchema>;
|
||||
|
||||
const cache: Cache = createCache({
|
||||
stores: [new DiskStore({
|
||||
path: '/tmp/nominatim-cache',
|
||||
ttl: 3600 * 24, // 24 hours
|
||||
maxsize: 1000 * 1000 * 100, // 100MB
|
||||
subdirs: true,
|
||||
zip: false,
|
||||
})]
|
||||
});
|
||||
|
||||
export class NominatimClient {
|
||||
baseUrl = 'https://nominatim.openstreetmap.org/search';
|
||||
|
||||
async geocodePhrase(query: string): Promise<NominatimResult[]> {
|
||||
const cacheKey = `geocode:${query}`;
|
||||
const cached = await cache.get(cacheKey);
|
||||
if (cached) {
|
||||
return cached as NominatimResult[];
|
||||
}
|
||||
const url = `${this.baseUrl}?q=${encodeURIComponent(query)}&polygon_geojson=1&format=json`;
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
'User-Agent': 'DeFlock/1.1',
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to geocode phrase: ${response.status}`);
|
||||
}
|
||||
const json = await response.json();
|
||||
await cache.set(cacheKey, json);
|
||||
return json;
|
||||
}
|
||||
|
||||
async geocodeSingleResult(query: string): Promise<NominatimResult | null> {
|
||||
const results = await this.geocodePhrase(query);
|
||||
|
||||
if (!results.length) return null;
|
||||
|
||||
const cityStatePattern = /(.+),\s*(\w{2})/;
|
||||
const postalCodePattern = /\d{5}/;
|
||||
|
||||
if (cityStatePattern.test(query)) {
|
||||
const cityStateResults = results.filter((result: NominatimResult) =>
|
||||
["city", "town", "village", "hamlet", "suburb", "quarter", "neighbourhood", "borough"].includes(result.addresstype)
|
||||
);
|
||||
if (cityStateResults.length) {
|
||||
return cityStateResults[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (postalCodePattern.test(query)) {
|
||||
const postalCodeResults = results.filter((result: NominatimResult) => result.addresstype === "postcode");
|
||||
if (postalCodeResults.length) {
|
||||
return postalCodeResults[0];
|
||||
}
|
||||
}
|
||||
|
||||
return results[0];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user