diff --git a/Config.cs b/Config.cs
index 762dd7f..7adf586 100644
--- a/Config.cs
+++ b/Config.cs
@@ -1,57 +1,39 @@
namespace InstaFollowersOverseer;
-public class Config
+public class Config : DtsodFile
{
-
- private const string config_file="config.dtsod";
- private const string config_example_file="config-example.dtsod";
-
+ #nullable disable
public string botToken;
public string instagramLogin;
public string instagramPassword;
+ #nullable enable
- public Config(DtsodV23 configDtsod)
+ public Config(string fileNameWithoutExt) : base(fileNameWithoutExt) { }
+
+ public override void LoadFromFile()
{
- botToken = configDtsod[nameof(botToken)];
- instagramLogin = configDtsod[nameof(instagramLogin)];
- instagramPassword = configDtsod[nameof(instagramPassword)];
- }
-
- public static Config ReadFromFile()
- {
- if (!File.Exists(config_file))
+ var dtsod = ReadDtsodFromFile(true);
+ try
{
- EmbeddedResources.CopyToFile(
- $"{EmbeddedResourcesPrefix}.{config_example_file}",
- config_example_file);
- throw new Exception($"File {config_file} doesnt exist. You have create config. See {config_example_file}");
+ botToken = dtsod[nameof(botToken)];
+ instagramLogin = dtsod[nameof(instagramLogin)];
+ instagramPassword = dtsod[nameof(instagramPassword)];
+ }
+ 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
{
{ nameof(botToken), botToken },
{ nameof(instagramLogin), instagramLogin },
- { nameof(instagramLogin), instagramLogin }
+ { nameof(instagramPassword), instagramPassword }
};
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());
- }
}
\ No newline at end of file
diff --git a/DtsodFile.cs b/DtsodFile.cs
new file mode 100644
index 0000000..24cd9f8
--- /dev/null
+++ b/DtsodFile.cs
@@ -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();
+ }
+}
\ No newline at end of file
diff --git a/InstaFollowersOverseer.csproj b/InstaFollowersOverseer.csproj
index 06a38b0..98614b7 100644
--- a/InstaFollowersOverseer.csproj
+++ b/InstaFollowersOverseer.csproj
@@ -1,17 +1,29 @@
-
+
+ Timerix
+ Telegram bot that notifies users when somebody follows/unfollows theit instagram accounts
+ GIT
+ https://github.com/Timerix22/InstaFollowersOverseer
+ MIT
+
Exe
- net6.0
+ net6.0;net7.0
+ embedded
+
+ preview
disable
enable
- preview
+
+
-
+
+
+
@@ -25,6 +37,6 @@
+
-
diff --git a/InstaFollowersOverseer.sln.DotSettings.user b/InstaFollowersOverseer.sln.DotSettings.user
new file mode 100644
index 0000000..0c717f8
--- /dev/null
+++ b/InstaFollowersOverseer.sln.DotSettings.user
@@ -0,0 +1,3 @@
+
+ ShowAndRun
+
\ No newline at end of file
diff --git a/Instagram/InstagramApiLogger.cs b/Instagram/InstagramApiLogger.cs
new file mode 100644
index 0000000..30e7ece
--- /dev/null
+++ b/Instagram/InstagramApiLogger.cs
@@ -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);
+ }
+}
\ No newline at end of file
diff --git a/Instagram/InstagramWrapper.cs b/Instagram/InstagramWrapper.cs
new file mode 100644
index 0000000..3e1ca01
--- /dev/null
+++ b/Instagram/InstagramWrapper.cs
@@ -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 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;
+ }
+}
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
index 4dabd70..f8b7700 100644
--- a/Program.cs
+++ b/Program.cs
@@ -2,6 +2,7 @@
global using System.Threading.Tasks;
global using System.Linq;
global using System.Collections.Generic;
+global using DTLib;
global using DTLib.Filesystem;
global using DTLib.Extensions;
global using DTLib.Dtsod;
@@ -10,18 +11,20 @@ global using File = DTLib.Filesystem.File;
global using Directory = DTLib.Filesystem.Directory;
global using Path = DTLib.Filesystem.Path;
global using static InstaFollowersOverseer.SharedData;
-using System.Net.Http;
using System.Text;
using System.Threading;
-using Telegram.Bot;
-using Telegram.Bot.Polling;
-using Telegram.Bot.Types;
-using Telegram.Bot.Types.Enums;
namespace InstaFollowersOverseer;
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()
{
Console.InputEncoding=Encoding.UTF8;
@@ -29,90 +32,31 @@ static class Program
DTLibInternalLogging.SetLogger(MainLogger.ParentLogger);
try
{
- config = Config.ReadFromFile();
- userSettings = UserSettings.ReadFromFile();
+ MainLogger.LogInfo("reading config");
+ CurrentConfig.LoadFromFile();
+ CurrentUsersData.LoadFromFile();
- CancellationTokenSource mainCancel = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) =>
{
- mainCancel.Cancel();
+ Stop();
Thread.Sleep(1000);
MainLogger.LogInfo("all have cancelled");
e.Cancel = false;
};
- var bot = new TelegramBotClient(config.botToken, new HttpClient());
- var receiverOptions = new ReceiverOptions
- {
- AllowedUpdates = { }, // receive all update types
+ Instagram.InstagramWrapper.Init();
+ Telegram.TelegramWrapper.Init();
- };
- bot.StartReceiving(BotApiUpdateHandler, BotApiExceptionHandler, receiverOptions, mainCancel.Token);
-
- Task.Delay(-1, mainCancel.Token).GetAwaiter().GetResult();
+ Task.Delay(-1, MainCancel.Token).GetAwaiter().GetResult();
Thread.Sleep(1000);
}
+ catch (OperationCanceledException) {}
catch (Exception ex)
{
MainLogger.LogError(ex);
}
+ CurrentConfig.SaveToFile();
+ CurrentUsersData.SaveToFile();
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;
- }
}
\ No newline at end of file
diff --git a/SharedData.cs b/SharedData.cs
index f45d423..41cc837 100644
--- a/SharedData.cs
+++ b/SharedData.cs
@@ -4,13 +4,10 @@ public static class SharedData
{
internal const string EmbeddedResourcesPrefix = "InstaFollowersOverseer.resources";
-#nullable disable
- internal static Config config;
- internal static UserSettings userSettings;
-#nullable enable
-
- public static readonly ContextLogger MainLogger = new ContextLogger("main",new CompositeLogger(
- new ConsoleLogger(),
- new FileLogger("logs","InstaFollowersOverseer"))
- );
+ internal static Config CurrentConfig = new("config");
+ internal static UsersData CurrentUsersData = new("users-data");
+
+ public static readonly CompositeLogger ParentLogger = new(
+ new ConsoleLogger(),
+ new FileLogger("logs", "InstaFollowersOverseer"));
}
\ No newline at end of file
diff --git a/Telegram/TelegramWrapper.cs b/Telegram/TelegramWrapper.cs
new file mode 100644
index 0000000..37c4415
--- /dev/null
+++ b/Telegram/TelegramWrapper.cs
@@ -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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/UserSettings.cs b/UserSettings.cs
deleted file mode 100644
index 914e87a..0000000
--- a/UserSettings.cs
+++ /dev/null
@@ -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> userSettings=new();
-
- private UserSettings()
- {
-
- }
-
- public UserSettings(DtsodV23 _userSettings)
- {
- try
- {
- foreach (var uset in _userSettings)
- {
- string telegramUserId = uset.Key;
-
- List oparams = new List();
- 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 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)
- {
- foreach (var p in instagramObservableParams)
- AddOrSet(telegramUserId, p);
- }
-}
\ No newline at end of file
diff --git a/UsersData.cs b/UsersData.cs
new file mode 100644
index 0000000..ca7d553
--- /dev/null
+++ b/UsersData.cs
@@ -0,0 +1,81 @@
+namespace InstaFollowersOverseer;
+
+public class UsersData : DtsodFile
+{
+ private Dictionary> 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 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(iop =>
+ iop.ToDtsod()
+ ).ToList());
+ return b;
+ }
+
+ public List 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)
+ {
+ foreach (var p in instagramObservableParams)
+ AddOrSet(telegramUserId, p);
+ }
+}
\ No newline at end of file
diff --git a/resources/user-settings-example.dtsod b/resources/users-data-example.dtsod
similarity index 100%
rename from resources/user-settings-example.dtsod
rename to resources/users-data-example.dtsod