-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathProgram.cs
More file actions
218 lines (187 loc) · 9.29 KB
/
Copy pathProgram.cs
File metadata and controls
218 lines (187 loc) · 9.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
using System.Text;
using System.Text.Json;
using DotNetEnv;
using GLotifi.Models;
using Microsoft.Toolkit.Uwp.Notifications;
using Microsoft.Win32;
namespace GLotifi
{
internal static class Program
{
private static readonly string DEFAULT_TODO_DIRECTORY_PATH = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GLotifi");
private static string TODO_FILE_PATH = Path.Join(DEFAULT_TODO_DIRECTORY_PATH, "alreadyAnnounced.json");
private static string GITLAB_URL = "";
private static string GITLAB_TOKEN = "";
private static int EXEC_EVERY_SEC = 30;
private static DateTime LastExec = DateTime.Now;
private static TimeSpan EXEC_EVERY_SEC_TSPAN = TimeSpan.FromSeconds(EXEC_EVERY_SEC);
private const string AUTOSTART_REG_PATH = @"Software\Microsoft\Windows\CurrentVersion\Run";
private const string APP_NAME = "GLotifi";
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var notifyIcon = new NotifyIcon
{
Icon = new Icon(Path.Join(AppDomain.CurrentDomain.BaseDirectory, "GLotifi.ico")),
Visible = true,
Text = "GLotifi"
};
var contextMenu = new ContextMenuStrip();
var autostartItem = new ToolStripMenuItem("Autostart")
{
CheckOnClick = true,
Checked = IsAutostartEnabled()
};
autostartItem.CheckedChanged += (s, e) =>
{
if (autostartItem.Checked)
{
EnableAutostart();
new ToastContentBuilder()
.AddToastActivationInfo("action=enableAutostart", ToastActivationType.Foreground)
.AddAppLogoOverride(new Uri(Path.Join("file:///", AppDomain.CurrentDomain.BaseDirectory, "GLotifi.png")))
.AddText("GLotifi")
.AddText("Autostart is enabled!")
.SetToastDuration(ToastDuration.Short)
.Show();
}
else
{
DisableAutostart();
new ToastContentBuilder()
.AddToastActivationInfo("action=enableAutostart", ToastActivationType.Foreground)
.AddAppLogoOverride(new Uri(Path.Join("file:///", AppDomain.CurrentDomain.BaseDirectory, "GLotifi.png")))
.AddText("GLotifi")
.AddText("Autostart is disabled!")
.SetToastDuration(ToastDuration.Short)
.Show();
}
};
contextMenu.Items.Add(autostartItem);
contextMenu.Items.Add(new ToolStripSeparator());
var exitItem = new ToolStripMenuItem("Exit GLotifi");
exitItem.Click += (s, e) =>
{
notifyIcon.Visible = false;
Application.Exit();
Environment.Exit(0);
};
contextMenu.Items.Add(exitItem);
notifyIcon.ContextMenuStrip = contextMenu;
Task.Run(() => StartBackgroundLoop());
Application.Run(); // Starting application
}
static void StartBackgroundLoop()
{
try
{
Env.Load(Path.Join(AppDomain.CurrentDomain.BaseDirectory, ".env"));
var envTodoFilePath = Environment.GetEnvironmentVariable("TODO_FILE_PATH");
if (envTodoFilePath != null) TODO_FILE_PATH = envTodoFilePath;
else Directory.CreateDirectory(DEFAULT_TODO_DIRECTORY_PATH);
GITLAB_URL = GetEnvVar("GITLAB_URL");
GITLAB_TOKEN = GetEnvVar("GITLAB_TOKEN");
EXEC_EVERY_SEC = int.Parse(GetEnvVar("EXEC_EVERY_SEC"));
EXEC_EVERY_SEC_TSPAN = TimeSpan.FromSeconds(EXEC_EVERY_SEC);
if (!File.Exists(TODO_FILE_PATH))
{
File.Create(TODO_FILE_PATH).Close();
File.WriteAllText(TODO_FILE_PATH, "[]");
}
new ToastContentBuilder()
.AddToastActivationInfo("action=viewDetails", ToastActivationType.Foreground)
.AddAppLogoOverride(new Uri(Path.Join("file:///", AppDomain.CurrentDomain.BaseDirectory, "GLotifi.png")))
.AddText("GLotifi")
.AddText("GLotifi got successfully started in the background!\n\nStart observing your todo list!")
.SetProtocolActivation(new Uri("https://github.com/lNaymonl/GLotifi"))
.SetToastDuration(ToastDuration.Short)
.Show();
while (true)
{
if (DateTime.Now - LastExec < EXEC_EVERY_SEC_TSPAN)
{
Task.Delay(1000).Wait();
continue;
}
try
{
var task = GetUnanouncedTodos();
task.Wait();
var unannounced = task.Result.ToList();
foreach (var todo in unannounced)
{
new ToastContentBuilder()
.AddToastActivationInfo("action=viewDetails", ToastActivationType.Foreground)
.AddAppLogoOverride(new Uri(Path.Join("file:///", AppDomain.CurrentDomain.BaseDirectory, "GLotifi.png")))
.AddText(todo.Target.Title)
.AddText(todo.Target.Description)
.SetProtocolActivation(new Uri(todo.TargetUrl))
.SetToastDuration(ToastDuration.Long)
.Show();
}
LastExec = DateTime.Now;
}
catch (Exception ex)
{
new ToastContentBuilder()
.AddToastActivationInfo("action=viewDetails", ToastActivationType.Foreground)
.AddAppLogoOverride(new Uri(Path.Join("file:///", AppDomain.CurrentDomain.BaseDirectory, "GLotifi.png")))
.AddText("An error occurred while running GLotifi: " + ex.Message)
.SetToastDuration(ToastDuration.Short)
.Show();
Environment.Exit(1);
}
Task.Delay(1000).Wait();
}
}
catch (Exception ex)
{
new ToastContentBuilder()
.AddToastActivationInfo("action=viewDetails", ToastActivationType.Foreground)
.AddAppLogoOverride(new Uri(Path.Join("file:///", AppDomain.CurrentDomain.BaseDirectory, "GLotifi.png")))
.AddText("An error occurred while starting GLotifi: " + ex.Message)
.SetToastDuration(ToastDuration.Short)
.Show();
Environment.Exit(1);
}
}
public static string GetEnvVar(string name) =>
Environment.GetEnvironmentVariable(name) ?? throw new Exception($"{name} variable must be present in .env file");
public static async Task<IEnumerable<Todo>> GetTodos()
{
using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("PRIVATE-TOKEN", GITLAB_TOKEN);
var res = await httpClient.GetAsync($"{GITLAB_URL}/api/v4/todos");
var content = await res.Content.ReadAsByteArrayAsync();
var contentString = Encoding.UTF8.GetString(content);
var todos = JsonSerializer.Deserialize<Todo[]>(contentString) ?? throw new NullReferenceException("Could not parse todos");
return todos;
}
public static async Task<IEnumerable<Todo>> GetUnanouncedTodos()
{
string alreadyAnnouncedTodosStr = File.ReadAllText(TODO_FILE_PATH);
List<int> alreadyAnnouncedTodos = [.. JsonSerializer.Deserialize<int[]>(alreadyAnnouncedTodosStr) ?? throw new NullReferenceException("Given file content could not be parsed into int array!")];
var todos = await GetTodos();
File.WriteAllText(TODO_FILE_PATH, JsonSerializer.Serialize(todos.Select(todo => todo.Id)));
return todos.Where(todo => !alreadyAnnouncedTodos.Contains(todo.Id)).ToList();
}
private static void EnableAutostart()
{
string exePath = Application.ExecutablePath;
using RegistryKey key = Registry.CurrentUser.OpenSubKey(AUTOSTART_REG_PATH, true)!;
key.SetValue(APP_NAME, $"\"{exePath}\"");
}
private static void DisableAutostart()
{
using RegistryKey key = Registry.CurrentUser.OpenSubKey(AUTOSTART_REG_PATH, true)!;
key.DeleteValue(APP_NAME, false);
}
private static bool IsAutostartEnabled()
{
using RegistryKey key = Registry.CurrentUser.OpenSubKey(AUTOSTART_REG_PATH, false)!;
return key.GetValue(APP_NAME) != null;
}
}
}