2021-08-01 12:51:54 -04:00
using System.Text.RegularExpressions ;
2021-04-21 22:57:19 +01:00
2021-11-26 21:10:56 -05:00
namespace PluralKit.Core ;
public static class MiscUtils
2021-04-21 22:57:19 +01:00
{
2021-11-26 21:10:56 -05:00
// discord mediaproxy URLs used to be stored directly in the database, so now we cleanup image urls before using them outside of proxying
private static readonly Regex MediaProxyUrl =
new (
@"^https?://media.discordapp.net/attachments/(\d{17,19})/(\d{17,19})/([^/\\&\?]+)\.(png|jpg|jpeg|webp)(\?.*)?$" ) ;
private static readonly string DiscordCdnReplacement = "https://cdn.discordapp.com/attachments/$1/$2/$3.$4" ;
2025-12-05 19:35:33 -05:00
// Rewrite time "cachebuster" parameters for randomly generated/chosen avatars with custom URLs.
2025-12-05 20:03:29 -05:00
private static readonly Regex TimePlaceholder = new ( @"(?:\{|%7B)(time(?:stamp|_(?:1m|5m|30m|1h|6h|1d)))(?:\}|%7D)" ) ;
2025-12-05 19:35:33 -05:00
private const Int64 TimeAccuracy = 60 ;
2021-11-26 21:10:56 -05:00
public static bool TryMatchUri ( string input , out Uri uri )
2021-04-21 22:57:19 +01:00
{
2023-01-09 04:32:41 +13:00
if ( input . StartsWith ( '<' ) & & input . EndsWith ( '>' ) )
input = input [ 1. . ^ 1 ] ;
2021-11-26 21:10:56 -05:00
try
2021-04-21 22:57:19 +01:00
{
2021-11-26 21:10:56 -05:00
uri = new Uri ( input ) ;
2022-12-29 00:54:32 +00:00
if ( ! uri . IsAbsoluteUri | | uri . Scheme ! = "https" )
2021-04-21 22:57:19 +01:00
return false ;
}
2021-11-26 21:10:56 -05:00
catch ( UriFormatException )
2021-08-02 12:22:28 +02:00
{
2021-11-26 21:10:56 -05:00
uri = null ;
return false ;
2021-08-02 12:22:28 +02:00
}
2021-11-26 21:10:56 -05:00
return true ;
2021-04-21 22:57:19 +01:00
}
2021-11-26 21:10:56 -05:00
public static string? TryGetCleanCdnUrl ( this string? url ) = >
2025-12-05 19:35:33 -05:00
url = = null ? null : TimePlaceholder . Replace ( MediaProxyUrl . Replace ( url , DiscordCdnReplacement ) , ProcessTimePlaceholder ) ;
private static string? ProcessTimePlaceholder ( Match m ) {
// Limit maximum accuracy to avoid too much cache thrashing, multiply for standard-ish Unix time
// AND with the maximum positive value so it's always positive (as if this code will exist long enough for the 64-bit signed unix time to go negative...)
var time = ( ( DateTimeOffset . UtcNow . ToUnixTimeSeconds ( ) / TimeAccuracy ) * TimeAccuracy ) & Int64 . MaxValue ;
switch ( m . Groups [ 1 ] . Value ) {
case "timestamp" : break ;
case "time_1m" : time / = 60 ; break ;
case "time_5m" : time / = 60 * 5 ; break ;
case "time_30m" : time / = 60 * 30 ; break ;
case "time_1h" : time / = 60 * 60 ; break ;
case "time_6h" : time / = 6 * 60 * 60 ; break ;
case "time_1d" : time / = 24 * 60 * 60 ; break ;
2025-12-05 19:53:04 -05:00
}
2025-12-05 19:35:33 -05:00
return time . ToString ( ) ;
}
2021-04-21 22:57:19 +01:00
}