Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8c09da3
commit 1e37626
Showing
12 changed files
with
463 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
bin/ | ||
obj/ | ||
/packages/ | ||
riderModule.iml | ||
/_ReSharper.Caches/ | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace OfferSimulation.Core; | ||
|
||
public static class CustomConsole | ||
{ | ||
public static void WriteLine(string text, ConsoleColor color) | ||
{ | ||
Console.ForegroundColor = color; | ||
Console.WriteLine(text); | ||
Console.ResetColor(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System.Text.Json; | ||
|
||
namespace OfferSimulation; | ||
|
||
public static class IpAddress | ||
{ | ||
/// <summary> | ||
/// Gets the current users IP Address. | ||
/// This IP is used for fetching offers from OGAds. | ||
/// </summary> | ||
public static async Task<string?> GetAsync() | ||
{ | ||
using var client = new HttpClient(); | ||
var resp = await client.GetStringAsync("https://api.ipify.org/?format=json"); | ||
var json = JsonSerializer.Deserialize<Dictionary<string, string>>(resp); | ||
return json?["ip"]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.Text.Json.Serialization; | ||
|
||
namespace OfferSimulation.Models; | ||
|
||
public class Offer | ||
{ | ||
[JsonPropertyName("offerid")] | ||
public int OfferId { get; set; } | ||
[JsonPropertyName("name")] | ||
public string Name { get; set; } | ||
[JsonPropertyName("name_short")] | ||
public string NameShort { get; set; } | ||
[JsonPropertyName("description")] | ||
public string Description { get; set; } | ||
[JsonPropertyName("adcopy")] | ||
public string AdCopy { get; set; } | ||
[JsonPropertyName("picture")] | ||
public string Picture { get; set; } | ||
[JsonPropertyName("payout")] | ||
public string Payout { get; set; } | ||
[JsonPropertyName("country")] | ||
public string Country { get; set; } | ||
[JsonPropertyName("device")] | ||
public string Device { get; set; } | ||
[JsonPropertyName("link")] | ||
public string Link { get; set; } | ||
[JsonPropertyName("epc")] | ||
public string Epc { get; set; } | ||
|
||
public override string ToString() | ||
{ | ||
return NameShort; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System.Text.Json.Serialization; | ||
|
||
namespace OfferSimulation.Models; | ||
|
||
public class OfferResponse | ||
{ | ||
[JsonPropertyName("success")] | ||
public bool Success { get; set; } | ||
[JsonPropertyName("error")] | ||
public object Error { get; set; } | ||
[JsonPropertyName("offers")] | ||
public List<Offer> Offers { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net7.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<ApplicationIcon>icon.ico</ApplicationIcon> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Bogus" Version="34.0.2" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OfferSimulation", "OfferSimulation.csproj", "{C7017427-2F50-4FBF-BC21-9102C2396B93}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{C7017427-2F50-4FBF-BC21-9102C2396B93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{C7017427-2F50-4FBF-BC21-9102C2396B93}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{C7017427-2F50-4FBF-BC21-9102C2396B93}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{C7017427-2F50-4FBF-BC21-9102C2396B93}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using System.Net.Http.Headers; | ||
using System.Text.Json; | ||
using System.Web; | ||
using OfferSimulation.Core; | ||
using OfferSimulation.Models; | ||
|
||
namespace OfferSimulation; | ||
|
||
public class Offers | ||
{ | ||
private readonly string _offerApi = "https://unlockcontent.net/api/v2"; | ||
private readonly string _userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1"; | ||
|
||
/// <summary> | ||
/// Fetches offers from OGAds with the <c>_userAgent</c> and <c>IP address</c> provided. | ||
/// This allows us to send real offers to the user. | ||
/// </summary> | ||
public async Task<List<Offer>> GetAsync(string apiKey, string ipAddress) | ||
{ | ||
using var client = new HttpClient(); | ||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); | ||
|
||
// Build URL with query parameters | ||
var builder = new UriBuilder(_offerApi); | ||
var query = HttpUtility.ParseQueryString(builder.Query); | ||
query["ip"] = ipAddress; | ||
query["user_agent"] = _userAgent; | ||
query["ctype"] = "1"; | ||
builder.Query = query.ToString(); | ||
|
||
var url = builder.Uri.ToString(); | ||
try | ||
{ | ||
var resp = await client.GetStringAsync(url); | ||
var offers = JsonSerializer.Deserialize<OfferResponse>(resp); | ||
return offers!.Offers; | ||
} | ||
catch (Exception) | ||
{ | ||
CustomConsole.WriteLine("[ERROR] Failed to fetch offers from OGAds. Either you provided an invalid API key or the request timed out", ConsoleColor.Red); | ||
Console.WriteLine("Press any key to continue..."); | ||
Console.ReadKey(); | ||
throw; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
using System.Security.Cryptography; | ||
using System.Text.RegularExpressions; | ||
using System.Web; | ||
using Bogus; | ||
using OfferSimulation.Models; | ||
|
||
namespace OfferSimulation; | ||
|
||
public class PostbackUrl | ||
{ | ||
private string _url; | ||
private readonly Offer _offer; | ||
private readonly string _ipAddress; | ||
private readonly Faker _faker; | ||
|
||
public PostbackUrl(string url, Offer offer, string ipAddress) | ||
{ | ||
_url = url; | ||
_offer = offer; | ||
_ipAddress = ipAddress; | ||
_faker = new Faker(); | ||
} | ||
|
||
/// <summary> | ||
/// Replaces all possible parameters in the URL and returns the updated URL | ||
/// For example this would convert as follows: | ||
/// https://website.com/postback.php?id={offer_id}&payout={payout}&ip={session_ip}&offer_name={offer_name}&datetime={datetime}&ran={ran} | ||
/// https://website.com/postback.php?id=49377&payout=6.59&ip=0.0.0.0&offer_name=WWE+Champions&datetime=2023-05-11 12:14:04&ran=78639 | ||
/// </summary> | ||
public string ReplaceAll() | ||
{ | ||
ReplaceOfferId(); | ||
ReplaceOfferName(); | ||
ReplaceAffiliateId(); | ||
ReplaceSource(); | ||
ReplaceSessionIp(); | ||
ReplacePayout(); | ||
ReplaceDate(); | ||
ReplaceTime(); | ||
ReplaceDateTime(); | ||
ReplaceSessionTimeStamp(); | ||
ReplaceAffSub(); | ||
ReplaceAffSub2(); | ||
ReplaceAffSub3(); | ||
ReplaceAffSub4(); | ||
ReplaceAffSub5(); | ||
ReplaceRan(); | ||
return _url; | ||
} | ||
|
||
private void ReplaceOfferId() => _url = _url.Replace("{offer_id}", _offer.OfferId.ToString()); | ||
|
||
private void ReplaceOfferName() => _url = _url.Replace("{offer_name}", HttpUtility.UrlEncode(_offer.NameShort)); | ||
|
||
private void ReplaceAffiliateId() | ||
{ | ||
var random = new Random(); | ||
var affId = random.Next(1, 100000); | ||
_url = _url.Replace("{affiliate_id}", affId.ToString()); | ||
} | ||
|
||
private void ReplaceSource() | ||
{ | ||
if (_url.Contains("{source}")) | ||
{ | ||
Console.Write("Provide the source or press enter to leave blank:"); | ||
var source = Console.ReadLine(); | ||
_url = _url.Replace("{source}", source); | ||
} | ||
} | ||
|
||
private void ReplaceSessionIp() => _url = _url.Replace("{session_ip}", _ipAddress); | ||
|
||
private void ReplacePayout() => _url = _url.Replace("{payout}", _offer.Payout); | ||
|
||
private void ReplaceDate() | ||
{ | ||
var date = DateTime.Now.ToString("yyyy-MM-dd"); | ||
_url = _url.Replace("{date}", date); | ||
} | ||
|
||
private void ReplaceTime() | ||
{ | ||
var time = DateTime.Now.ToString("HH:mm:ss"); | ||
_url = _url.Replace("{time}", time); | ||
} | ||
|
||
private void ReplaceDateTime() | ||
{ | ||
var dateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); | ||
_url = _url.Replace("{datetime}", dateTime); | ||
} | ||
|
||
private void ReplaceSessionTimeStamp() | ||
{ | ||
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); | ||
_url = _url.Replace("{session_timestamp}", timestamp); | ||
} | ||
|
||
private void ReplaceAffSub() | ||
{ | ||
_url = _url.Replace("{aff_sub}", "ContentLocker"); | ||
} | ||
|
||
/// <summary> | ||
/// AffSub2 is a randomly generated 5 numerical and character string. | ||
/// This isn't the exact way OGAds does it, but it gives the end user the right idea. | ||
/// </summary> | ||
private void ReplaceAffSub2() | ||
{ | ||
var bytes = RandomNumberGenerator.GetBytes(5); | ||
var token = Convert.ToBase64String(bytes); | ||
|
||
// Remove special characters and shorten string | ||
var reg = new Regex("[*'\",_&#^@=]"); | ||
token = reg.Replace(token, string.Empty); | ||
token = token[..5]; | ||
|
||
_url = _url.Replace("{aff_sub2}", token); | ||
} | ||
|
||
/// <summary> | ||
/// AffSub3 is a long JWT token. | ||
/// While this isn't a JWT token, it gives the end user the right idea. | ||
/// </summary> | ||
private void ReplaceAffSub3() | ||
{ | ||
var bytes = RandomNumberGenerator.GetBytes(20); | ||
var token = Convert.ToBase64String(bytes); | ||
|
||
// Remove special characters and shorten string | ||
var reg = new Regex("[*'\",_&#^@=]"); | ||
token = reg.Replace(token, string.Empty); | ||
|
||
_url = _url.Replace("{aff_sub3}", token); | ||
} | ||
|
||
/// <summary> | ||
/// AffSub4 is randomly generated or can be provided by the end user. | ||
/// This only triggers if aff_sub4 is in the url. | ||
/// </summary> | ||
private void ReplaceAffSub4() | ||
{ | ||
if (_url.Contains("{aff_sub4}")) | ||
{ | ||
// Check if the user wants to manually provide or generate the aff_sub4 | ||
Console.Write("Generate aff_sub4? (y/n):"); | ||
var key = Console.ReadKey().Key; | ||
Console.Write("\n"); | ||
|
||
string? affSub4; | ||
if (key == ConsoleKey.N) | ||
{ | ||
Console.Write("Provide aff_sub4, or press enter to leave blank:"); | ||
affSub4 = Console.ReadLine(); | ||
} | ||
else | ||
{ | ||
affSub4 = _faker.Internet.Email(); | ||
} | ||
|
||
_url = _url.Replace("{aff_sub4}", affSub4); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// AffSub5 is randomly generated or provided by the user. | ||
/// This only triggers if aff_sub5 is in the url. | ||
/// </summary> | ||
private void ReplaceAffSub5() | ||
{ | ||
if (_url.Contains("{aff_sub5}")) | ||
{ | ||
// Check if the user wants to manually provide or generate the aff_sub5 | ||
Console.Write("Generate aff_sub5? (y/n):"); | ||
var key = Console.ReadKey().Key; | ||
Console.Write("\n"); | ||
|
||
string? affSub5; | ||
if (key == ConsoleKey.N) | ||
{ | ||
Console.WriteLine("Provide aff_sub5, or press enter to leave blank:"); | ||
affSub5 = Console.ReadLine(); | ||
} | ||
else | ||
{ | ||
affSub5 = _faker.Person.FirstName; | ||
} | ||
|
||
_url = _url.Replace("{aff_sub5}", affSub5); | ||
} | ||
} | ||
|
||
private void ReplaceRan() | ||
{ | ||
var random = new Random(); | ||
var ranNum = random.Next(1, 100000); | ||
_url = _url.Replace("{ran}", ranNum.ToString()); | ||
} | ||
} |
Oops, something went wrong.