telegram and instagram wrappers, DtsodFile

This commit is contained in:
timerix 2023-02-23 18:33:47 +06:00
parent adbebc37ec
commit 327d06b3d0
12 changed files with 436 additions and 238 deletions

View File

@ -1,57 +1,39 @@
namespace InstaFollowersOverseer; namespace InstaFollowersOverseer;
public class Config public class Config : DtsodFile
{ {
#nullable disable
private const string config_file="config.dtsod";
private const string config_example_file="config-example.dtsod";
public string botToken; public string botToken;
public string instagramLogin; public string instagramLogin;
public string instagramPassword; public string instagramPassword;
#nullable enable
public Config(DtsodV23 configDtsod) public Config(string fileNameWithoutExt) : base(fileNameWithoutExt) { }
{
botToken = configDtsod[nameof(botToken)];
instagramLogin = configDtsod[nameof(instagramLogin)];
instagramPassword = configDtsod[nameof(instagramPassword)];
}
public static Config ReadFromFile() public override void LoadFromFile()
{ {
if (!File.Exists(config_file)) var dtsod = ReadDtsodFromFile(true);
try
{ {
EmbeddedResources.CopyToFile( botToken = dtsod[nameof(botToken)];
$"{EmbeddedResourcesPrefix}.{config_example_file}", instagramLogin = dtsod[nameof(instagramLogin)];
config_example_file); instagramPassword = dtsod[nameof(instagramPassword)];
throw new Exception($"File {config_file} doesnt exist. You have create config. See {config_example_file}"); }
catch (Exception ex)
{
throw new Exception($"your {FileName} format is invalid\n"
+ $"See {FileExampleName}", innerException: ex);
} }
return new Config(new DtsodV23(File.ReadAllText(config_file)));
} }
public DtsodV23 ToDtsod() public override DtsodV23 ToDtsod()
{ {
var d = new DtsodV23 var d = new DtsodV23
{ {
{ nameof(botToken), botToken }, { nameof(botToken), botToken },
{ nameof(instagramLogin), instagramLogin }, { nameof(instagramLogin), instagramLogin },
{ nameof(instagramLogin), instagramLogin } { nameof(instagramPassword), instagramPassword }
}; };
return d; return d;
} }
public override string ToString() => ToDtsod().ToString();
public void SaveToFile()
{
File.Copy(config_file,
$"backups/{config_file}.old-"+
"{DateTime.Now.ToString(MyTimeFormat.ForFileNames)}",
true);
File.OpenWrite(config_file)
.FluentWriteString("#DtsodV23\n")
.WriteString(ToDtsod().ToString());
}
} }

64
DtsodFile.cs Normal file
View File

@ -0,0 +1,64 @@
using System.IO;
namespace InstaFollowersOverseer;
public abstract class DtsodFile
{
public readonly string FileNameWithoutExt;
public readonly string FileName;
public readonly string FileExampleName;
public DtsodFile(string fileNameWithoutExt)
{
FileNameWithoutExt = fileNameWithoutExt;
FileName = fileNameWithoutExt + ".dtsod";
FileExampleName = fileNameWithoutExt + "-example.dtsod";
}
public void CreateBackup()
{
string backupPath=$"backups/{FileNameWithoutExt}.d/{FileNameWithoutExt}"
+DateTime.Now.ToString(MyTimeFormat.ForFileNames)+".dtsod";
Program.MainLogger.LogInfo($"creating backup if file {FileName} at path {backupPath}");
File.Copy(FileName,backupPath,false);
}
public DtsodV23 ReadDtsodFromFile(bool trhowIfFileNotFound)
{
Program.MainLogger.LogInfo($"reading file {FileName}");
EmbeddedResources.CopyToFile(
$"{EmbeddedResourcesPrefix}.{FileExampleName}",
FileExampleName);
if (!File.Exists(FileName))
{
File.WriteAllText(FileName, "#DtsodV23\n");
string message = $"file {FileName} doesnt exist, created new blank";
if (trhowIfFileNotFound)
throw new FileNotFoundException(message);
Program.MainLogger.LogWarn(message);
return new DtsodV23();
}
string fileText = File.ReadAllText(FileName);
Program.MainLogger.LogDebug(fileText);
return new DtsodV23(fileText);
}
public abstract void LoadFromFile();
public abstract DtsodV23 ToDtsod();
public void SaveToFile()
{
Program.MainLogger.LogInfo($"saving file {FileName}");
string dtsodStr = ToDtsod().ToString();
Program.MainLogger.LogDebug(dtsodStr);
if(File.Exists(FileName))
CreateBackup();
File.OpenWrite(FileName)
.FluentWriteString("#DtsodV23\n")
.FluentWriteString(dtsodStr)
.Close();
}
}

View File

@ -1,17 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<!--project info-->
<Authors>Timerix</Authors>
<Description>Telegram bot that notifies users when somebody follows/unfollows theit instagram accounts</Description>
<RepositoryType>GIT</RepositoryType>
<RepositoryUrl>https://github.com/Timerix22/InstaFollowersOverseer</RepositoryUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<!--compilation properties-->
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<DebugType>embedded</DebugType>
<!--language features-->
<LangVersion>preview</LangVersion>
<ImplicitUsings>disable</ImplicitUsings> <ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>preview</LangVersion>
</PropertyGroup> </PropertyGroup>
<!--third-party dependencies-->
<ItemGroup> <ItemGroup>
<PackageReference Include="InstaSharper" Version="1.4.82" />
<PackageReference Include="Telegram.Bot" Version="18.0.0" /> <PackageReference Include="Telegram.Bot" Version="18.0.0" />
<PackageReference Include="Telegram.Bots.Extensions.Polling" Version="5.9.0" /> <!--PackageReference Include="Telegram.Bots.Extensions.Polling" Version="5.9.0" /-->
</ItemGroup> </ItemGroup>
<!--dtlib dependencies-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<ProjectReference Include="..\DTLib\DTLib.Logging\DTLib.Logging.csproj" /> <ProjectReference Include="..\DTLib\DTLib.Logging\DTLib.Logging.csproj" />
<ProjectReference Include="..\DTLib\DTLib.Dtsod\DTLib.Dtsod.csproj" /> <ProjectReference Include="..\DTLib\DTLib.Dtsod\DTLib.Dtsod.csproj" />
@ -25,6 +37,6 @@
<ItemGroup> <ItemGroup>
<None Remove="resources\**\*" /> <None Remove="resources\**\*" />
<EmbeddedResource Include="resources\**\*" /> <EmbeddedResource Include="resources\**\*" />
<None Remove=".gitignore" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/SweaWarningsMode/@EntryValue">ShowAndRun</s:String>
</wpf:ResourceDictionary>

View File

@ -0,0 +1,37 @@
using System.Net.Http;
using InstaSharper.Logger;
namespace InstaFollowersOverseer.Instagram;
public class InstagramApiLogger : IInstaLogger
{
public ContextLogger _logger = new("api", InstagramWrapper.InstagramLogger);
public void LogRequest(HttpRequestMessage r)
{
_logger.LogDebug("http",$"request {r.Method.Method.ToUpper()} from {r.RequestUri}:\n"
+ r.Content?.ReadAsStringAsync().GetAwaiter().GetResult());
}
public void LogRequest(Uri uri)
{
}
public void LogResponse(HttpResponseMessage r)
{
_logger.LogDebug("http",$"responce from " +
(r.RequestMessage!=null && r.RequestMessage.RequestUri!=null ? r.RequestMessage.RequestUri.ToString() : "unknown")
+ $" :\n "+ r.Content.ReadAsStringAsync().GetAwaiter().GetResult());
}
public void LogException(Exception ex)
{
_logger.LogError(ex);
}
public void LogInfo(string info)
{
_logger.LogInfo(info);
}
}

View File

@ -0,0 +1,58 @@
using InstaSharper.API;
using InstaSharper.API.Builder;
using InstaSharper.Classes;
using InstaSharper.Classes.Models;
namespace InstaFollowersOverseer.Instagram;
public static class InstagramWrapper
{
public static ContextLogger InstagramLogger = new("instagram",ParentLogger);
private static IInstaApi Api=null!;
public static async void Init()
{
try
{
InstagramLogger.LogInfo("initializing instagram wrapper");
if (CurrentConfig is null)
throw new NullReferenceException("config is null");
var apiLogger = new InstagramApiLogger();
// disabling http request/responce logging
apiLogger._logger.DebugLogEnabled = false;
Api = InstaApiBuilder.CreateBuilder()
.UseLogger(apiLogger)
.SetUser(new UserSessionData
{
UserName = CurrentConfig.instagramLogin,
Password = CurrentConfig.instagramPassword
})
.SetRequestDelay(RequestDelay.FromSeconds(0, 1))
.Build();
InstagramLogger.LogInfo("instagram login starting");
var rezult= await Api.LoginAsync();
if (!rezult.Succeeded)
throw new Exception("login exception:\n" + rezult.Info + '\n' + rezult.Value);
InstagramLogger.LogInfo("instagram wrapper have initialized and connected successfully");
}
catch (OperationCanceledException) {}
catch (Exception ex)
{
InstagramLogger.LogError("init", ex);
Program.Stop();
}
}
public static async Task<InstaUser?> GetUserAsync(string usernameOrUrl)
{
// url
if (usernameOrUrl.Contains('/'))
{
throw new NotImplementedException("get user by url");
}
// username
var u=await Api.GetUserAsync(usernameOrUrl);
return u.Succeeded ? u.Value : null;
}
}

View File

@ -2,6 +2,7 @@
global using System.Threading.Tasks; global using System.Threading.Tasks;
global using System.Linq; global using System.Linq;
global using System.Collections.Generic; global using System.Collections.Generic;
global using DTLib;
global using DTLib.Filesystem; global using DTLib.Filesystem;
global using DTLib.Extensions; global using DTLib.Extensions;
global using DTLib.Dtsod; global using DTLib.Dtsod;
@ -10,18 +11,20 @@ global using File = DTLib.Filesystem.File;
global using Directory = DTLib.Filesystem.Directory; global using Directory = DTLib.Filesystem.Directory;
global using Path = DTLib.Filesystem.Path; global using Path = DTLib.Filesystem.Path;
global using static InstaFollowersOverseer.SharedData; global using static InstaFollowersOverseer.SharedData;
using System.Net.Http;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
namespace InstaFollowersOverseer; namespace InstaFollowersOverseer;
static class Program static class Program
{ {
public static readonly ContextLogger MainLogger = new("main", ParentLogger);
private static CancellationTokenSource MainCancel=new();
public static CancellationToken MainCancelToken = MainCancel.Token;
public static void Stop() => MainCancel.Cancel();
static void Main() static void Main()
{ {
Console.InputEncoding=Encoding.UTF8; Console.InputEncoding=Encoding.UTF8;
@ -29,90 +32,31 @@ static class Program
DTLibInternalLogging.SetLogger(MainLogger.ParentLogger); DTLibInternalLogging.SetLogger(MainLogger.ParentLogger);
try try
{ {
config = Config.ReadFromFile(); MainLogger.LogInfo("reading config");
userSettings = UserSettings.ReadFromFile(); CurrentConfig.LoadFromFile();
CurrentUsersData.LoadFromFile();
CancellationTokenSource mainCancel = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) => Console.CancelKeyPress += (_, e) =>
{ {
mainCancel.Cancel(); Stop();
Thread.Sleep(1000); Thread.Sleep(1000);
MainLogger.LogInfo("all have cancelled"); MainLogger.LogInfo("all have cancelled");
e.Cancel = false; e.Cancel = false;
}; };
var bot = new TelegramBotClient(config.botToken, new HttpClient()); Instagram.InstagramWrapper.Init();
var receiverOptions = new ReceiverOptions Telegram.TelegramWrapper.Init();
{
AllowedUpdates = { }, // receive all update types
}; Task.Delay(-1, MainCancel.Token).GetAwaiter().GetResult();
bot.StartReceiving(BotApiUpdateHandler, BotApiExceptionHandler, receiverOptions, mainCancel.Token);
Task.Delay(-1, mainCancel.Token).GetAwaiter().GetResult();
Thread.Sleep(1000); Thread.Sleep(1000);
} }
catch (OperationCanceledException) {}
catch (Exception ex) catch (Exception ex)
{ {
MainLogger.LogError(ex); MainLogger.LogError(ex);
} }
CurrentConfig.SaveToFile();
CurrentUsersData.SaveToFile();
Console.ResetColor(); Console.ResetColor();
} }
private static ContextLogger botLogger = new ContextLogger("bot", MainLogger.ParentLogger);
static async Task BotApiUpdateHandler(ITelegramBotClient bot, Update update, CancellationToken cls)
{
try
{
switch (update.Type)
{
case UpdateType.Message:
{
var message = update.Message!;
if (message.Text!.StartsWith('/'))
{
botLogger.LogInfo($"user {message.Chat.Id} sent command {message.Text}");
var spl = message.Text.SplitToList(' ');
string command = spl[0].Substring(1);
spl.RemoveAt(0);
string[] args = spl.ToArray();
switch (command)
{
case "start":
await bot.SendTextMessageAsync(message.Chat, "hi");
break;
case "oversee":
break;
// default:
// throw new BotCommandException(command, args);
}
}
else botLogger.LogDebug($"message recieved: {message.Text}");
break;
} /*
case UpdateType.EditedMessage:
break;
case UpdateType.InlineQuery:
break;
case UpdateType.ChosenInlineResult:
break;
case UpdateType.CallbackQuery:
break;*/
default:
botLogger.LogWarn($"unknown update type: {update.Type}");
break;
}
}
catch (Exception ex)
{
botLogger.LogWarn("UpdateHandler", ex);
}
}
static Task BotApiExceptionHandler(ITelegramBotClient bot, Exception ex, CancellationToken cls)
{
botLogger.LogError(ex);
return Task.CompletedTask;
}
} }

View File

@ -4,13 +4,10 @@ public static class SharedData
{ {
internal const string EmbeddedResourcesPrefix = "InstaFollowersOverseer.resources"; internal const string EmbeddedResourcesPrefix = "InstaFollowersOverseer.resources";
#nullable disable internal static Config CurrentConfig = new("config");
internal static Config config; internal static UsersData CurrentUsersData = new("users-data");
internal static UserSettings userSettings;
#nullable enable
public static readonly ContextLogger MainLogger = new ContextLogger("main",new CompositeLogger( public static readonly CompositeLogger ParentLogger = new(
new ConsoleLogger(), new ConsoleLogger(),
new FileLogger("logs","InstaFollowersOverseer")) new FileLogger("logs", "InstaFollowersOverseer"));
);
} }

134
Telegram/TelegramWrapper.cs Normal file
View File

@ -0,0 +1,134 @@
using System.Net.Http;
using System.Threading;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using InstaFollowersOverseer.Instagram;
namespace InstaFollowersOverseer.Telegram;
public static class TelegramWrapper
{
private static ContextLogger TelegramLogger = new("telegram", ParentLogger);
private static TelegramBotClient Bot=null!;
public static async void Init()
{
try
{
TelegramLogger.LogInfo("initializing telegram wrapper");
if (CurrentConfig is null)
throw new NullReferenceException("config is null");
Bot = new TelegramBotClient(CurrentConfig.botToken, new HttpClient());
await Bot.SetMyCommandsAsync(new BotCommand[]
{
new() { Command = "start", Description = "starts the bot"},
// new() { Command = "help", Description = "shows commands list" },
new() { Command = "oversee", Description = "[instagram username] - " +
"enables notifications about instagram user's followers" },
new() { Command = "list", Description = "shows list of overseeing instagram users" }
});
var receiverOptions = new ReceiverOptions
{
// AllowedUpdates = { }, // receive all update types
};
TelegramLogger.LogInfo("bot starting recieving long polls");
Bot.StartReceiving(BotApiUpdateHandler, BotApiExceptionHandler, receiverOptions, Program.MainCancelToken);
TelegramLogger.LogInfo("telegram wrapper have initialized successfully");
}
catch (OperationCanceledException) {}
catch (Exception ex)
{
TelegramLogger.LogError("init", ex);
Program.Stop();
}
}
private static Task BotApiExceptionHandler(ITelegramBotClient bot, Exception ex, CancellationToken cls)
{
TelegramLogger.LogError(ex);
return Task.CompletedTask;
}
static async Task SendInfoReply(string text, Message replyToMessage)
{
TelegramLogger.LogInfo(text);
await Bot.SendTextMessageAsync(replyToMessage.Chat, text,
replyToMessageId: replyToMessage.MessageId,
parseMode:ParseMode.MarkdownV2);
}
static async Task SendErrorReply(string text, Message replyToMessage)
{
TelegramLogger.LogWarn(text);
await Bot.SendTextMessageAsync(replyToMessage.Chat, "error: "+text,
replyToMessageId: replyToMessage.MessageId,
parseMode:ParseMode.MarkdownV2);
}
private static async Task BotApiUpdateHandler(ITelegramBotClient bot, Update update, CancellationToken cls)
{
try
{
switch (update.Type)
{
case UpdateType.Message:
{
var message = update.Message!;
if (message.Text!.StartsWith('/'))
{
TelegramLogger.LogInfo($"user {message.Chat.Id} sent command {message.Text}");
var spl = message.Text.SplitToList(' ');
string command = spl[0].Substring(1);
spl.RemoveAt(0);
string[] args = spl.ToArray();
await ExecCommandAsync(command, args, message);
}
else TelegramLogger.LogDebug($"message recieved: {message.Text}");
break;
}
/*case UpdateType.InlineQuery:
break;
case UpdateType.ChosenInlineResult:
break;
case UpdateType.CallbackQuery:
break;*/
default:
TelegramLogger.LogWarn($"unknown update type: {update.Type}");
break;
}
}
catch (OperationCanceledException) {}
catch (Exception ex)
{
TelegramLogger.LogWarn("UpdateHandler", ex);
}
}
private static async Task ExecCommandAsync(string command, string[] args, Message message)
{
switch (command)
{
case "start":
await Bot.SendTextMessageAsync(message.Chat, "hi");
break;
case "oversee":
{
string usernameOrUrl = args[0];
await SendInfoReply($"searching for instagram user <{usernameOrUrl}>", message);
var user = await InstagramWrapper.GetUserAsync(usernameOrUrl);
if (user is null)
{
await SendErrorReply($"user **{usernameOrUrl}** doesnt exist", message);
return;
}
CurrentUsersData.AddOrSet(message.Chat.Id.ToString(), new InstagramObservableParams(usernameOrUrl));
CurrentUsersData.SaveToFile();
break;
}
default:
await SendErrorReply("ivalid command", message);
break;
}
}
}

View File

@ -1,114 +0,0 @@
namespace InstaFollowersOverseer;
public class UserSettings
{
private const string user_settings_file="user-settings.dtsod";
private const string user_settings_example_file="user-settings-example.dtsod";
private Dictionary<string, List<InstagramObservableParams>> userSettings=new();
private UserSettings()
{
}
public UserSettings(DtsodV23 _userSettings)
{
try
{
foreach (var uset in _userSettings)
{
string telegramUserId = uset.Key;
List<InstagramObservableParams> oparams = new List<InstagramObservableParams>();
foreach (DtsodV23 _overseeParams in uset.Value)
oparams.Add(new InstagramObservableParams(_overseeParams));
userSettings.Add(telegramUserId, oparams);
}
}
catch (Exception ex)
{
throw new Exception($"your {user_settings_file} format is invalid\n"
+ $"See {user_settings_example_file}", innerException:ex);
}
}
public static UserSettings ReadFromFile()
{
EmbeddedResources.CopyToFile(
$"{EmbeddedResourcesPrefix}.{user_settings_example_file}",
user_settings_example_file);
if (File.Exists(user_settings_file))
return new UserSettings(new DtsodV23(File.ReadAllText(user_settings_file)));
MainLogger.LogWarn($"file {user_settings_file} doesnt exist, creating new");
File.WriteAllText(user_settings_file,"#DtsodV23\n");
return new UserSettings();
}
public DtsodV23 ToDtsod()
{
var b = new DtsodV23();
foreach (var userS in userSettings)
b.Add(userS.Key,
userS.Value.Select(iop =>
iop.ToDtsod()
).ToList());
return b;
}
public override string ToString() => ToDtsod().ToString();
public void SaveToFile()
{
File.Copy(user_settings_file,
$"backups/{user_settings_file}.old-"+
"{DateTime.Now.ToString(MyTimeFormat.ForFileNames)}",
true);
File.OpenWrite(user_settings_file)
.FluentWriteString("#DtsodV23\n")
.WriteString(ToDtsod().ToString());
}
public List<InstagramObservableParams> Get(string telegramUserId)
{
if (!userSettings.TryGetValue(telegramUserId, out var overseeParams))
throw new Exception($"there is no settings for user {telegramUserId}");
return overseeParams;
}
public void AddOrSet(string telegramUserId, InstagramObservableParams instagramObservableParams)
{
// Add
// doesnt contain settings for telegramUserId
if (!userSettings.TryGetValue(telegramUserId, out var thisUserSettings))
{
userSettings.Add(telegramUserId, new (){ instagramObservableParams });
return;
}
// Set
// settings for telegramUserId contain InstagramObservableParams with instagramObservableParams.instagramUserId
for (var i = 0; i < thisUserSettings.Count; i++)
{
if (thisUserSettings[i].instagramUserId == instagramObservableParams.instagramUserId)
{
thisUserSettings[i] = instagramObservableParams;
return;
}
}
// Add
// doesnt contain InstagramObservableParams with instagramObservableParams.instagramUserId
thisUserSettings.Add(instagramObservableParams);
}
public void AddOrSet(string telegramUserId, IEnumerable<InstagramObservableParams> instagramObservableParams)
{
foreach (var p in instagramObservableParams)
AddOrSet(telegramUserId, p);
}
}

81
UsersData.cs Normal file
View File

@ -0,0 +1,81 @@
namespace InstaFollowersOverseer;
public class UsersData : DtsodFile
{
private Dictionary<string, List<InstagramObservableParams>> usersData=new();
public UsersData(string fileName) : base(fileName) {}
public override void LoadFromFile()
{
var dtsod=ReadDtsodFromFile(false);
try
{
foreach (var uset in dtsod)
{
string telegramUserId = uset.Key;
List<InstagramObservableParams> oparams = new();
foreach (DtsodV23 _overseeParams in uset.Value)
oparams.Add(new InstagramObservableParams(_overseeParams));
usersData.Add(telegramUserId, oparams);
}
}
catch (Exception ex)
{
throw new Exception($"your {FileName} format is invalid\n"
+ $"See {FileExampleName}", innerException: ex);
}
}
public override DtsodV23 ToDtsod()
{
var b = new DtsodV23();
foreach (var userS in usersData)
b.Add(userS.Key,
userS.Value.Select<InstagramObservableParams, DtsodV23>(iop =>
iop.ToDtsod()
).ToList());
return b;
}
public List<InstagramObservableParams> Get(string telegramUserId)
{
if (!usersData.TryGetValue(telegramUserId, out var overseeParams))
throw new Exception($"there is no settings for user {telegramUserId}");
return overseeParams;
}
public void AddOrSet(string telegramUserId, InstagramObservableParams instagramObservableParams)
{
// Add
// doesnt contain settings for telegramUserId
if (!usersData.TryGetValue(telegramUserId, out var thisUsersData))
{
usersData.Add(telegramUserId, new (){ instagramObservableParams });
return;
}
// Set
// settings for telegramUserId contain InstagramObservableParams with instagramObservableParams.instagramUserId
for (var i = 0; i < thisUsersData.Count; i++)
{
if (thisUsersData[i].instagramUserId == instagramObservableParams.instagramUserId)
{
thisUsersData[i] = instagramObservableParams;
return;
}
}
// Add
// doesnt contain InstagramObservableParams with instagramObservableParams.instagramUserId
thisUsersData.Add(instagramObservableParams);
}
public void AddOrSet(string telegramUserId, IEnumerable<InstagramObservableParams> instagramObservableParams)
{
foreach (var p in instagramObservableParams)
AddOrSet(telegramUserId, p);
}
}