-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsee.c
241 lines (206 loc) · 8.48 KB
/
see.c
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#include <ApplicationServices/ApplicationServices.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <math.h>
#include <stdlib.h>
#define INTERVAL 600 // log data every 10 mins
#define HOURS_TO_SECONDS(x) ((x) * 3600)
#define DATA_POINTS (HOURS_TO_SECONDS(24) / 600)
#define PIXELS_TO_METERS(x) ((x) * 0.0002645833) // conversion factor for pixels to meters (assumes 96 DPI)
// struct to hold activity data for single interval
typedef struct {
time_t timestamp;
int keypresses;
double mouse_moves; // store mouse movement [m]
int left_clicks;
int right_clicks;
int middle_clicks;
} ActivityData;
ActivityData data = {0};
ActivityData history[DATA_POINTS] = {0};
int currentIndex = 0;
// cumulative counts
unsigned long long cumulative_keypresses = 0;
double cumulative_mouse_moves = 0.0;
unsigned long long cumulative_left_clicks = 0;
unsigned long long cumulative_right_clicks = 0;
unsigned long long cumulative_middle_clicks = 0;
double last_mouse_x = -1.0, last_mouse_y = -1.0;
CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
if (type == kCGEventKeyDown) {
data.keypresses++;
cumulative_keypresses++;
} else if (type == kCGEventLeftMouseDown) {
data.left_clicks++;
cumulative_left_clicks++;
} else if (type == kCGEventRightMouseDown) {
data.right_clicks++;
cumulative_right_clicks++;
} else if (type == kCGEventMouseMoved) {
CGPoint mouse_pos = CGEventGetLocation(event);
if (last_mouse_x >= 0 && last_mouse_y >= 0) {
double dx = mouse_pos.x - last_mouse_x;
double dy = mouse_pos.y - last_mouse_y;
double distance = sqrt(dx * dx + dy * dy);
double distance_meters = PIXELS_TO_METERS(distance);
data.mouse_moves += distance_meters;
cumulative_mouse_moves += distance_meters;
}
last_mouse_x = mouse_pos.x;
last_mouse_y = mouse_pos.y;
} else if (type == kCGEventOtherMouseDown) {
data.middle_clicks++;
cumulative_middle_clicks++;
}
return event;
}
void logDataToFile() {
// log cumulative counts
FILE *cumulativeFile = fopen("cumulative_data.csv", "w");
if (cumulativeFile) {
fprintf(cumulativeFile, "event,count\n");
fprintf(cumulativeFile, "keypresses,%llu\n", cumulative_keypresses);
fprintf(cumulativeFile, "mousemoves,%.2f meters\n", cumulative_mouse_moves);
fprintf(cumulativeFile, "leftclicks,%llu\n", cumulative_left_clicks);
fprintf(cumulativeFile, "rightclicks,%llu\n", cumulative_right_clicks);
fprintf(cumulativeFile, "middleclicks,%llu\n", cumulative_middle_clicks);
fclose(cumulativeFile);
printf("cumulative data logged successfully!\n");
} else {
perror("error opening cumulative_data.csv");
}
// log past 24 hours
FILE *past24HoursFile = fopen("past_24_hours_data.csv", "w");
if (past24HoursFile) {
unsigned long long past24_keypresses = 0;
double past24_mouse_moves = 0.0;
unsigned long long past24_left_clicks = 0;
unsigned long long past24_right_clicks = 0;
unsigned long long past24_middle_clicks = 0;
fprintf(past24HoursFile, "timestamp,keypresses,mousemoves,leftclicks,rightclicks,middleclicks\n");
for (int i = 0; i < DATA_POINTS; i++) {
int index = (currentIndex + i) % DATA_POINTS;
if (history[index].timestamp != 0) {
fprintf(past24HoursFile, "%ld,%d,%.2f,%d,%d,%d\n",
history[index].timestamp,
history[index].keypresses,
history[index].mouse_moves,
history[index].left_clicks,
history[index].right_clicks,
history[index].middle_clicks);
past24_keypresses += history[index].keypresses;
past24_mouse_moves += history[index].mouse_moves;
past24_left_clicks += history[index].left_clicks;
past24_right_clicks += history[index].right_clicks;
past24_middle_clicks += history[index].middle_clicks;
}
}
// append cumulative summary for 24h
fprintf(past24HoursFile, "cumulative, %llu, %.2f meters, %llu, %llu, %llu\n",
past24_keypresses, past24_mouse_moves,
past24_left_clicks, past24_right_clicks, past24_middle_clicks);
fclose(past24HoursFile);
}
// printf("Current cumulative values: keypresses=%llu, mousemoves=%.2f, leftclicks=%llu, rightclicks=%llu, middleclicks=%llu\n",
// cumulative_keypresses, cumulative_mouse_moves, cumulative_left_clicks, cumulative_right_clicks, cumulative_middle_clicks);
}
// updating git
void update_github() {
time_t now = time(NULL);
char timestamp[26];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&now));
char commit_message[100];
snprintf(commit_message, sizeof(commit_message), "update event data - %s", timestamp);
printf("attempting to update github @ %s...\n", timestamp);
// pull latest changes from remote
int result = system("git pull origin main --rebase");
if (result != 0) {
fprintf(stderr, "error pulling latest changes from git\n");
return;
}
// add updated files to git
result = system("git add cumulative_data.csv past_24_hours_data.csv");
if (result != 0) {
fprintf(stderr, "error adding files to git\n");
return;
}
// commit changes + message
char git_commit_command[150];
snprintf(git_commit_command, sizeof(git_commit_command), "git commit -m \"%s\"", commit_message);
result = system(git_commit_command);
if (result != 0) {
fprintf(stderr, "error committing changes\n");
return;
}
// push changes to remote
result = system("git push origin main");
if (result != 0) {
fprintf(stderr, "error pushing to git\n");
return;
}
printf("git update successful!\n");
}
void storeAndLogData() {
time_t last_github_update = 0;
while (1) {
// save current data to history
time_t now = time(NULL);
data.timestamp = now;
history[currentIndex] = data;
// log data to files
logDataToFile();
// update git every hour
if (now - last_github_update >= 3600) {
update_github();
last_github_update = now;
}
// move to next index
currentIndex = (currentIndex + 1) % DATA_POINTS;
// reset current data
data.keypresses = 0;
data.mouse_moves = 0;
data.left_clicks = 0;
data.right_clicks = 0;
data.middle_clicks = 0;
sleep(INTERVAL);
}
}
int main(int argc, char *argv[]) {
char cwd[1024];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
printf("current working directory: %s\n", cwd);
} else {
perror("getcwd() error");
}
// set-up event tap
CGEventMask eventMask = (1 << kCGEventKeyDown) | (1 << kCGEventLeftMouseDown) |
(1 << kCGEventRightMouseDown) | (1 << kCGEventMouseMoved) |
(1 << kCGEventOtherMouseDown) | (1 << kCGEventKeyUp) |
(1 << kCGEventLeftMouseUp) | (1 << kCGEventRightMouseUp) |
(1 << kCGEventScrollWheel);
CFMachPortRef eventTap = CGEventTapCreate(kCGAnnotatedSessionEventTap,
kCGHeadInsertEventTap,
0,
eventMask,
eventCallback,
NULL);
if (!eventTap) {
fprintf(stderr, "Failed to create event tap!\n");
return 1;
}
CFRunLoopSourceRef runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
CGEventTapEnable(eventTap, true);
printf("event tap created and enabled!\n");
// start the data storage and logging loop in a separate thread
pthread_t logging_thread;
pthread_create(&logging_thread, NULL, (void *)storeAndLogData, NULL);
// start the event loop
CFRunLoopRun(); // this keeps event tap running
// cleanup (never reached unless CFRunLoopRun stops)
CFRelease(eventTap);
CFRelease(runLoopSource);
return 0;
}