Trying very hard not to miss calendar events
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

First commit, basic C version working

Co-authored-by: Claude <noreply@anthropic.com>

+277
+13
.clang-format
··· 1 + --- 2 + BasedOnStyle: LLVM 3 + IndentWidth: 4 4 + ColumnLimit: 100 5 + BreakBeforeBraces: Linux 6 + AllowShortIfStatementsOnASingleLine: false 7 + AllowShortFunctionsOnASingleLine: None 8 + AllowShortLoopsOnASingleLine: false 9 + IndentCaseLabels: false 10 + PointerAlignment: Right 11 + SpaceAfterCStyleCast: true 12 + AlignConsecutiveAssignments: false 13 + AlignConsecutiveDeclarations: false
+63
.gitignore
··· 1 + # Created by https://www.toptal.com/developers/gitignore/api/c,ninja 2 + # Edit at https://www.toptal.com/developers/gitignore?templates=c,ninja 3 + 4 + ### C ### 5 + # Prerequisites 6 + *.d 7 + 8 + # Object files 9 + *.o 10 + *.ko 11 + *.obj 12 + *.elf 13 + 14 + # Linker output 15 + *.ilk 16 + *.map 17 + *.exp 18 + 19 + # Precompiled Headers 20 + *.gch 21 + *.pch 22 + 23 + # Libraries 24 + *.lib 25 + *.a 26 + *.la 27 + *.lo 28 + 29 + # Shared objects (inc. Windows DLLs) 30 + *.dll 31 + *.so 32 + *.so.* 33 + *.dylib 34 + 35 + # Executables 36 + *.exe 37 + *.out 38 + *.app 39 + *.i*86 40 + *.x86_64 41 + *.hex 42 + 43 + # Debug files 44 + *.dSYM/ 45 + *.su 46 + *.idb 47 + *.pdb 48 + 49 + # Kernel Module Compile Results 50 + *.mod* 51 + *.cmd 52 + .tmp_versions/ 53 + modules.order 54 + Module.symvers 55 + Mkfile.old 56 + dkms.conf 57 + 58 + ### Ninja ### 59 + .ninja_deps 60 + .ninja_log 61 + 62 + # End of https://www.toptal.com/developers/gitignore/api/c,ninja 63 + .vscode/
+20
build.ninja
··· 1 + rule cc 2 + command = gcc -c $cflags $in -o $out 3 + description = Compiling $in 4 + 5 + rule link 6 + command = gcc $in $ldflags -o $out 7 + description = Linking $out 8 + 9 + rule format 10 + command = clang-format -i $in 11 + description = Formatting $in 12 + 13 + cflags = -Wall -Wextra `pkg-config --cflags libedataserver-1.2 libecal-2.0 libsoup-3.0 glib-2.0` 14 + ldflags = `pkg-config --libs libedataserver-1.2 libecal-2.0 libsoup-3.0 glib-2.0` 15 + 16 + build list_events.o: cc list_events.c 17 + 18 + build list_events.out: link list_events.o 19 + 20 + build format: format list_events.c
+181
list_events.c
··· 1 + #include <glib.h> 2 + #include <libecal/libecal.h> 3 + #include <libedataserver/libedataserver.h> 4 + #include <libical-glib/libical-glib.h> 5 + #include <stdio.h> 6 + #include <string.h> 7 + #include <time.h> 8 + 9 + void print_version() 10 + { 11 + printf("Evolution Data Server test program\n"); 12 + printf("Library version info:\n"); 13 + printf(" GLib version: %d.%d.%d\n", glib_major_version, glib_minor_version, 14 + glib_micro_version); 15 + } 16 + 17 + void print_usage(const char *program_name) 18 + { 19 + printf("Usage: %s [COMMAND]\n", program_name); 20 + printf("\nCommands:\n"); 21 + printf(" --version Show version information\n"); 22 + printf(" sources list List available calendar sources\n"); 23 + printf(" events list List events from now to 30 days ahead\n"); 24 + } 25 + 26 + int list_sources() 27 + { 28 + GError *error = NULL; 29 + ESourceRegistry *registry = e_source_registry_new_sync(NULL, &error); 30 + 31 + if (error) { 32 + fprintf(stderr, "Failed to create source registry: %s\n", error->message); 33 + g_error_free(error); 34 + return 1; 35 + } 36 + 37 + if (registry) { 38 + printf("Successfully connected to Evolution Data Server\n"); 39 + 40 + // List available sources 41 + GList *sources = e_source_registry_list_sources(registry, E_SOURCE_EXTENSION_CALENDAR); 42 + printf("Found %d calendar source(s)\n", g_list_length(sources)); 43 + 44 + for (GList *l = sources; l != NULL; l = l->next) { 45 + ESource *source = E_SOURCE(l->data); 46 + const char *display_name = e_source_get_display_name(source); 47 + const char *uid = e_source_get_uid(source); 48 + printf(" - %s (UID: %s)\n", display_name, uid); 49 + } 50 + 51 + g_list_free_full(sources, g_object_unref); 52 + g_object_unref(registry); 53 + } 54 + 55 + return 0; 56 + } 57 + 58 + int list_events() 59 + { 60 + GError *error = NULL; 61 + ESourceRegistry *registry = e_source_registry_new_sync(NULL, &error); 62 + 63 + if (error) { 64 + fprintf(stderr, "Failed to create source registry: %s\n", error->message); 65 + g_error_free(error); 66 + return 1; 67 + } 68 + 69 + // Calculate time range: now to 30 days ahead 70 + time_t now = time(NULL); 71 + time_t end_time = now + (60 * 24 * 60 * 60); 72 + 73 + // Get all calendar sources 74 + GList *sources = e_source_registry_list_sources(registry, E_SOURCE_EXTENSION_CALENDAR); 75 + int total_events = 0; 76 + 77 + for (GList *l = sources; l != NULL; l = l->next) { 78 + ESource *source = E_SOURCE(l->data); 79 + const char *display_name = e_source_get_display_name(source); 80 + 81 + // Create calendar client 82 + EClient *client_base = 83 + e_cal_client_connect_sync(source, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, 30, NULL, &error); 84 + 85 + if (error) { 86 + fprintf(stderr, "Failed to connect to calendar '%s': %s\n", display_name, 87 + error->message); 88 + g_clear_error(&error); 89 + continue; 90 + } 91 + 92 + ECalClient *client = E_CAL_CLIENT(client_base); 93 + 94 + // Query for events in the time range 95 + char *iso_start = isodate_from_time_t(now); 96 + char *iso_end = isodate_from_time_t(end_time); 97 + char *query = g_strdup_printf( 98 + "(occur-in-time-range? (make-time \"%s\") (make-time \"%s\"))", iso_start, iso_end); 99 + 100 + GSList *ical_components = NULL; 101 + gboolean success = 102 + e_cal_client_get_object_list_sync(client, query, &ical_components, NULL, &error); 103 + 104 + if (error) { 105 + fprintf(stderr, "Failed to query events from '%s': %s\n", display_name, error->message); 106 + g_clear_error(&error); 107 + g_free(query); 108 + g_free(iso_start); 109 + g_free(iso_end); 110 + g_object_unref(client_base); 111 + continue; 112 + } 113 + 114 + if (success && ical_components) { 115 + for (GSList *comp = ical_components; comp != NULL; comp = comp->next) { 116 + ICalComponent *icalcomp = (ICalComponent *) comp->data; 117 + 118 + if (!icalcomp) { 119 + continue; 120 + } 121 + 122 + const char *summary = i_cal_component_get_summary(icalcomp); 123 + 124 + ICalTime *start = i_cal_component_get_dtstart(icalcomp); 125 + ICalTime *end = i_cal_component_get_dtend(icalcomp); 126 + 127 + time_t start_t = i_cal_time_as_timet(start); 128 + time_t end_t = i_cal_time_as_timet(end); 129 + 130 + char start_buf[64], end_buf[64]; 131 + strftime(start_buf, sizeof(start_buf), "%Y-%m-%d %H:%M", localtime(&start_t)); 132 + strftime(end_buf, sizeof(end_buf), "%Y-%m-%d %H:%M", localtime(&end_t)); 133 + 134 + printf("[%s] %s | %s - %s\n", display_name, summary ? summary : "(No title)", 135 + start_buf, end_buf); 136 + total_events++; 137 + 138 + g_object_unref(start); 139 + g_object_unref(end); 140 + } 141 + 142 + g_slist_free_full(ical_components, g_object_unref); 143 + } 144 + 145 + g_free(query); 146 + g_free(iso_start); 147 + g_free(iso_end); 148 + g_object_unref(client_base); 149 + } 150 + 151 + printf("\nTotal events: %d\n", total_events); 152 + g_list_free_full(sources, g_object_unref); 153 + g_object_unref(registry); 154 + 155 + return 0; 156 + } 157 + 158 + int main(int argc, char *argv[]) 159 + { 160 + if (argc < 2) { 161 + print_usage(argv[0]); 162 + return 1; 163 + } 164 + 165 + if (strcmp(argv[1], "--version") == 0) { 166 + print_version(); 167 + return 0; 168 + } 169 + 170 + if (argc >= 3 && strcmp(argv[1], "sources") == 0 && strcmp(argv[2], "list") == 0) { 171 + return list_sources(); 172 + } 173 + 174 + if (argc >= 3 && strcmp(argv[1], "events") == 0 && strcmp(argv[2], "list") == 0) { 175 + return list_events(); 176 + } 177 + 178 + fprintf(stderr, "Unknown command\n\n"); 179 + print_usage(argv[0]); 180 + return 1; 181 + }