Skip to content

Commit

Permalink
Configurable StaticMaps Toggle (#290)
Browse files Browse the repository at this point in the history
* - Add static map toggle to config.
- Add reusable location links generator.
- Update internal default embeds example.
- Let user know if emoji does not exist.
- Fix locales directory path.

* Update docs
  • Loading branch information
versx authored Jun 24, 2022
1 parent 6e5cfef commit b9b0e1e
Show file tree
Hide file tree
Showing 24 changed files with 352 additions and 417 deletions.
4 changes: 1 addition & 3 deletions docs/dts/pokemon.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ Use any of the following in your embeds file to structure how notifications will
| moveset | Fast & Charge move names | Quick Attack/Thunder
| type_1 | Pokemon type | Dark
| type_2 | Pokemon type | Water
| type_1_emoji | Pokemon type emoji | <:00000:types_water>
| type_2_emoji | Pokemon type emoji | <:00000:types_rock>
| types | Both types (if 2nd exists) | Dark/Fire
| types | Both Pokemon types (if 2nd exists) | Dark/Fire
| types_emoji | Type Discord emoji | <:00000:types_fire> <00001:types_dark>
| atk_iv | Attack IV stat | 15
| def_iv | Defense IV stat | 7
Expand Down
4 changes: 1 addition & 3 deletions docs/dts/raids.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ Use any of the following in your embeds file to structure how notifications will
| moveset | Fast & Charge move names | Quick Attack/Thunder
| type_1 | Pokemon type | Dark
| type_2 | Pokemon type | Water
| type_1_emoji | Pokemon type emoji | <:00000:types_water>
| type_2_emoji | Pokemon type emoji | <:00000:types_rock>
| types | Both types (if 2nd exists) | Dark/Fire
| types | Both Pokemon types (if 2nd exists) | Dark/Fire
| types_emoji | Type Discord emoji | <:00000:types_fire> <00001:types_dark>
| weaknesses | Raid boss weaknesses | Rock, Ground, Dark
| weaknesses_emoji | Emoji(s) of raid boss weaknesses | Rock Ground Dark
Expand Down
1 change: 1 addition & 0 deletions examples/configs/config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
}
},
"staticMaps": {
"enabled": false,
"url": "http://tiles.example.com:8080",
// StaticMap or MultiStaticMap
"type": "StaticMap",
Expand Down
2 changes: 1 addition & 1 deletion examples/embeds/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"{{#if power_up_level}}**Power Level**",
"Level: {{power_up_level}} | Points: {{power_up_points}}",
"Time Left: {{power_up_end_time_left}}",
"{{/if}}{{#if is_ex}}{{ex_gym_emoji}} Gym!",
"{{/if}}{{#if is_ex}}{{ex_emoji}} Gym!",
"{{/if}}**[Google]({{gmaps_url}}) | [Apple]({{applemaps_url}}) | [Waze]({{wazemaps_url}}) | [Scanner]({{scanmaps_url}})**"
],
"iconUrl": "{{gym_url}}",
Expand Down
50 changes: 22 additions & 28 deletions src/Commands/Discord/Nests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using WhMgr.Services;
using WhMgr.Services.Alarms.Embeds;
using WhMgr.Services.Geofence;
using WhMgr.Services.Geofence.Geocoding;
using WhMgr.Services.Icons;
using WhMgr.Services.StaticMap;

Expand Down Expand Up @@ -197,41 +198,36 @@ public DiscordEmbed GenerateEmbedMessage(ulong guildId, DiscordClient client, Ne

public dynamic GetProperties(DiscordGuild guild, Nest nest, string pokemonImageUrl)
{
var config = _config.Instance;
var pkmnInfo = GameMaster.GetPokemon(nest.PokemonId);
var pkmnImage = pokemonImageUrl;
var nestName = nest.Name ?? "Unknown";
var type1 = pkmnInfo?.Types?[0];
var type2 = pkmnInfo?.Types?.Count > 1 ? pkmnInfo.Types?[1] : PokemonType.None;
var type1Emoji = pkmnInfo?.Types?[0].GetTypeEmojiIcons();
var type2Emoji = pkmnInfo?.Types?.Count > 1 ? pkmnInfo?.Types?[1].GetTypeEmojiIcons() : string.Empty;
var typeEmojis = $"{type1Emoji} {type2Emoji}";
var types = pkmnInfo?.Types;
var type1 = types?.Count >= 1
? types[0]
: PokemonType.None;
var type2 = types?.Count > 1
? types[1]
: PokemonType.None;
var typeEmojis = types?.GetTypeEmojiIcons() ?? string.Empty;
var gmapsLink = string.Format(Strings.Defaults.GoogleMaps, nest.Latitude, nest.Longitude);
var appleMapsLink = string.Format(Strings.Defaults.AppleMaps, nest.Latitude, nest.Longitude);
var wazeMapsLink = string.Format(Strings.Defaults.WazeMaps, nest.Latitude, nest.Longitude);
var scannerMapsLink = string.Format(_config.Instance.Urls.ScannerMap, nest.Latitude, nest.Longitude);
var scannerMapsLink = string.Format(config.Urls.ScannerMap, nest.Latitude, nest.Longitude);
var address = ReverseGeocodingLookup.Instance.GetAddressAsync(new Coordinate(nest)).Result;

//pkmnImage,
var osmNest = _osmManager.GetNest(nest.Name)?.FirstOrDefault();
var polygonPath = OsmManager.MultiPolygonToLatLng(osmNest?.Geometry?.Coordinates, true);
var staticMapConfig = _config.Instance.StaticMaps;
var staticMap = new StaticMapGenerator(new StaticMapOptions
{
BaseUrl = staticMapConfig.Url,
MapType = StaticMapType.Nests,
TemplateType = staticMapConfig.Type == StaticMapTemplateType.StaticMap
? StaticMapTemplateType.StaticMap
: StaticMapTemplateType.MultiStaticMap,
Latitude = nest.Latitude,
Longitude = nest.Longitude,
SecondaryImageUrl = pokemonImageUrl,
PolygonPath = polygonPath,
Pregenerate = staticMapConfig.Pregenerate,
Regeneratable = true,
});
var staticMapLink = staticMap.GenerateLink();
var geofence = GeofenceService.GetGeofence(_config.Instance.Servers[guild.Id].Geofences, new Coordinate(nest));
var staticMapLink = config.StaticMaps?.GenerateStaticMap(
StaticMapType.Nests,
nest,
pokemonImageUrl,
null,
null,
polygonPath
);
var geofence = GeofenceService.GetGeofence(config.Servers[guild.Id].Geofences, new Coordinate(nest));
var city = geofence?.Name ?? "Unknown";
//var address = new Coordinate(city, nest.Latitude, nest.Longitude).GetAddress(_config.Instance);

var dict = new
{
Expand All @@ -244,8 +240,6 @@ public dynamic GetProperties(DiscordGuild guild, Nest nest, string pokemonImageU
nest_name = nestName,
type_1 = Convert.ToString(type1),
type_2 = Convert.ToString(type2),
type_1_emoji = type1Emoji,
type_2_emoji = type2Emoji,
types = $"{type1} | {type2}",
types_emojis = typeEmojis,

Expand All @@ -265,7 +259,7 @@ public dynamic GetProperties(DiscordGuild guild, Nest nest, string pokemonImageU
wazemaps_url = wazeMapsLink,
scanmaps_url = scannerMapsLink,

//address = address?.Address,
address = address ?? string.Empty,

// Discord Guild properties
guild_name = guild?.Name,
Expand Down
1 change: 0 additions & 1 deletion src/Configuration/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using WhMgr.Data;
using WhMgr.Extensions;
using WhMgr.Services.Icons;
using WhMgr.Services.StaticMap;

/// <summary>
/// Configuration file class
Expand Down
3 changes: 3 additions & 0 deletions src/Configuration/StaticMapConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

public class StaticMapConfig
{
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;

[JsonPropertyName("url")]
public string Url { get; set; }

Expand Down
3 changes: 3 additions & 0 deletions src/Defaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ public Defaults()
// Ex gym emoji
"ex",

// AR fort emoji
"ar",

// Type emojis
"types_fire",
"types_grass",
Expand Down
7 changes: 7 additions & 0 deletions src/Extensions/DateTimeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using GeoTimeZone;
using TimeZoneConverter;

using WhMgr.Services.Webhook.Models;

public static class DateTimeExtensions
{
public static TimeSpan GetTimeRemaining(this DateTime startTime, DateTime endTime)
Expand All @@ -13,6 +15,11 @@ public static TimeSpan GetTimeRemaining(this DateTime startTime, DateTime endTim
return remaining;
}

public static DateTime ConvertTimeFromCoordinates(this DateTime date, IWebhookPoint coord)
{
return ConvertTimeFromCoordinates(date, coord.Latitude, coord.Longitude);
}

public static DateTime ConvertTimeFromCoordinates(this DateTime date, double lat, double lon)
{
var tzIana = TimeZoneLookup.GetTimeZone(lat, lon).Result;
Expand Down
20 changes: 17 additions & 3 deletions src/Extensions/PokemonExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,33 @@ public static string GetTypeEmojiIcons(this IEnumerable<PokemonType> pokemonType
return string.Join(" ", list);
}

public static string GetEmojiIcon<T>(this T type, string keyPrefix, bool asString)
public static string GetEmojiIcon<T>(this T type, string keyPrefix, bool asString, string defaultValue = null)
{
var value = asString ? type.ToString().ToLower() : Convert.ToInt32(type).ToString();
var key = string.IsNullOrEmpty(keyPrefix) ? value : $"{keyPrefix}_{value}";
var emojiId = GameMaster.Instance.Emojis.ContainsKey(key)
? GameMaster.Instance.Emojis[key]
: 0;
var emojiName = string.IsNullOrEmpty(GameMaster.Instance.CustomEmojis[key])

if (emojiId == 0)
{
Console.WriteLine($"Emoji '{key}' does not exist! Using fallback text.");
}

// Check if custom emoji list contains specified emoji string or if custom emoji is not overwritten.
var emojiName = !GameMaster.Instance.CustomEmojis.ContainsKey(key) || string.IsNullOrEmpty(GameMaster.Instance.CustomEmojis[key])
// Check if we retrieved Discord emoji successfully
? emojiId > 0
// Construct Discord emoji string
? string.Format(Strings.Defaults.EmojiSchema, key, emojiId)
// Fallback to text instead of emoji
: type.ToString()
// Custom emoji is set which overwrites Discord emojis
: GameMaster.Instance.CustomEmojis[key] ?? type.ToString();
return emojiName;
var result = !string.IsNullOrEmpty(emojiName)
? emojiName
: defaultValue;
return result;
}

public static string GetWeaknessEmojiIcons(this List<PokemonType> pokemonTypes)
Expand Down
58 changes: 58 additions & 0 deletions src/Extensions/StaticMapExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
namespace WhMgr.Extensions
{
using System;
using System.Threading.Tasks;

using WhMgr.Common;
using WhMgr.Configuration;
using WhMgr.Services.Cache;
using WhMgr.Services.StaticMap;
using WhMgr.Services.Webhook.Models;

public static class StaticMapExtensions
{
public static string GenerateStaticMap(this StaticMapConfig config, StaticMapType mapType, IWebhookPoint coord, string imageUrl, IMapDataCache cache = null, PokemonTeam? team = null, string polygonPath = null)
{
var url = GenerateStaticMapAsync(config, mapType, coord, imageUrl, cache, team, polygonPath).Result;
return url;
}

public static async Task<string> GenerateStaticMapAsync(this StaticMapConfig config, StaticMapType mapType, IWebhookPoint coord, string imageUrl, IMapDataCache cache = null, PokemonTeam? team = null, string polygonPath = null)
{
if (!(config?.Enabled ?? false))
{
return string.Empty;
}

if (string.IsNullOrEmpty(config.Url))
{
return string.Empty;
}

var staticMap = new StaticMapGenerator(new StaticMapOptions
{
BaseUrl = config.Url,
MapType = mapType,
TemplateType = config.Type,
Latitude = coord.Latitude,
Longitude = coord.Longitude,
SecondaryImageUrl = imageUrl,
Gyms = config.IncludeNearbyGyms && cache != null
// Fetch nearby gyms from MapDataCache
? await cache?.GetGymsNearby(coord.Latitude, coord.Longitude)
: new(),
Pokestops = config.IncludeNearbyPokestops && cache != null
// Fetch nearby pokestops from MapDataCache
? await cache?.GetPokestopsNearby(coord.Latitude, coord.Longitude)
: new(),
Team = team,
PolygonPath = polygonPath,
Pregenerate = config.Pregenerate,
Regeneratable = true,
});

var url = staticMap.GenerateLink();
return url ?? string.Empty;
}
}
}
3 changes: 1 addition & 2 deletions src/Localization/Language.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ public Language()
: this(default)
{
CurrentCulture = new CultureInfo(DefaultLanguage);
LocaleDirectory = Strings.LocaleFolder;

LocaleDirectory = Path.Combine(Strings.BasePath, Strings.LocaleFolder);
//_map = LoadCountry(CurrentCulture.TwoLetterISOLanguageName);
}

Expand Down
6 changes: 2 additions & 4 deletions src/Services/Alarms/Embeds/EmbedMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,10 @@ public class EmbedMessage : Dictionary<EmbedMessageType, EmbedMessageSettings>
"{{/if}}{{#if is_ditto}}**Catch Pokemon:** {{original_pkmn_name}}",
"{{/if}}{{#if has_capture_rates}}{{capture_1_emoji}} {{capture_1}}% {{capture_2_emoji}} {{capture_2}}% {{capture_3_emoji}} {{capture_3}}%",
"{{/if}}{{#if is_event}}Go Fest Spawn",
"{{/if}}{{#if has_pvp}}",
"{{#each pvp}}**{{@key}}**",
"{{/if}}{{#if has_pvp}}{{#each pvp}}**{{@key}}**",
"{{#each this}}",
"#{{rank}} {{getPokemonName pokemonId}} {{getFormName formId}} {{cp}}CP @ L{{level}} {{formatPercentage percentage}}%",
"{{/each}}{{/each}}",
"{{/if}}**[Google]({{gmaps_url}}) | [Apple]({{applemaps_url}}) | [Waze]({{wazemaps_url}}) | [Scanner]({{scanmaps_url}})**",
"{{/each}}{{/each}}{{/if}}**[Google]({{gmaps_url}}) | [Apple]({{applemaps_url}}) | [Waze]({{wazemaps_url}}) | [Scanner]({{scanmaps_url}})**"
},
IconUrl = "{{pkmn_img_url}}",
Title = "{{geofence}}",
Expand Down
2 changes: 1 addition & 1 deletion src/Services/Discord/DiscordClientService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ private async Task CreateEmojisAsync(ulong guildId)
}

// Create steam of emoji file data
var fs = new FileStream(emojiPath, FileMode.Open, FileAccess.Read);
using var fs = new FileStream(emojiPath, FileMode.Open, FileAccess.Read);

// Create emoji for Discord guild
await guild.CreateEmojiAsync(emoji, fs, null, $"Missing `{emoji}` emoji.");
Expand Down
69 changes: 69 additions & 0 deletions src/Services/Webhook/Models/GenericEmbedProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
namespace WhMgr.Services.Webhook.Models
{
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using DSharpPlus.Entities;

using WhMgr.Configuration;
using WhMgr.Extensions;
using WhMgr.Services.Geofence;
using WhMgr.Services.Geofence.Geocoding;
using WhMgr.Services.Yourls;

public class GenericEmbedProperties
{
public string GoogleMapsLocationLink { get; set; }

public string AppleMapsLocationLink { get; set; }

public string WazeMapsLocationLink { get; set; }

public string ScannerMapsLocationLink { get; set; }

public string Address { get; set; }

public DiscordGuild Guild { get; set; }

public DateTime Now { get; set; }


public static GenericEmbedProperties Generate(Config config, IReadOnlyDictionary<ulong, DiscordGuild> guilds, ulong guildId, IWebhookPoint coord)
{
var data = GenerateAsync(config, guilds, guildId, coord).Result;
return data;
}

public static async Task<GenericEmbedProperties> GenerateAsync(Config config, IReadOnlyDictionary<ulong, DiscordGuild> guilds, ulong guildId, IWebhookPoint coord)
{
var gmapsLink = string.Format(Strings.Defaults.GoogleMaps, coord.Latitude, coord.Longitude);
var appleMapsLink = string.Format(Strings.Defaults.AppleMaps, coord.Latitude, coord.Longitude);
var wazeMapsLink = string.Format(Strings.Defaults.WazeMaps, coord.Latitude, coord.Longitude);
var scannerMapsLink = string.Format(config.Urls.ScannerMap, coord.Latitude, coord.Longitude);

var urlShortener = new UrlShortener(config.ShortUrlApi);
var gmapsLocationLink = await urlShortener.CreateAsync(gmapsLink);
var appleMapsLocationLink = await urlShortener.CreateAsync(appleMapsLink);
var wazeMapsLocationLink = await urlShortener.CreateAsync(wazeMapsLink);
var scannerMapsLocationLink = await urlShortener.CreateAsync(scannerMapsLink);
var address = await ReverseGeocodingLookup.Instance.GetAddressAsync(new Coordinate(coord));

var now = DateTime.UtcNow.ConvertTimeFromCoordinates(coord);
var guild = guilds?.ContainsKey(guildId) ?? false
? guilds[guildId]
: null;

return new GenericEmbedProperties
{
GoogleMapsLocationLink = gmapsLocationLink,
AppleMapsLocationLink = appleMapsLocationLink,
WazeMapsLocationLink = wazeMapsLocationLink,
ScannerMapsLocationLink = scannerMapsLocationLink,
Address = address ?? string.Empty,
Guild = guild,
Now = now,
};
}
}
}
Loading

0 comments on commit b9b0e1e

Please sign in to comment.