Compare commits

..

6 Commits

Author SHA1 Message Date
d1e34a5c10 add ignoressl toggling
Some checks failed
/ sync-to-origin (push) Has been cancelled
2025-03-06 19:45:18 +01:00
3a78917e10 link ncursesw 2025-03-06 19:42:05 +01:00
a407d8c16a wide string refactor 2025-03-06 19:41:30 +01:00
af5252f732 add basic timetable structure 2025-03-06 18:54:51 +01:00
87c9b1e125 add timetable menu entery 2025-03-06 18:54:37 +01:00
41316160ad fix .PHONY 2025-03-06 15:41:13 +01:00
7 changed files with 315 additions and 188 deletions

View File

@ -1,8 +1,8 @@
# Compiler and flags # Compiler and flags
CPPC = g++ CPPC = g++
CPPC_FLAGS = -std=c++23 -s -O3 -lncurses -lcurl -lmenu -lpanel -Wall -Wextra -Wno-write-strings CPPC_FLAGS = -std=c++23 -s -O3 -lncursesw -lcurl -lmenu -lpanel -Wall -Wextra -Wno-write-strings
# Debug flags: # Debug flags:
# CPPC_FLAGS = -ggdb -std=c++23 -lncurses -lcurl -lmenu -lpanel -Wall -Wextra # CPPC_FLAGS = -ggdb -std=c++23 -lncursesw -lcurl -lmenu -lpanel -Wall -Wextra -Wno-write-strings
SRC_PATH := src SRC_PATH := src
@ -35,4 +35,4 @@ $(OBJ_PATH)/%.o: $(SRC_PATH)/%.cpp
clean: clean:
rm -fr build rm -fr build
.PHONY: all clean make-build-dir .PHONY: all clean install

View File

@ -1,14 +1,17 @@
#include "helper_funcs.h"
#include "color.h"
#include "net.h" #include "net.h"
#include <codecvt>
#include <csignal> #include <csignal>
#include <curses.h> #include <curses.h>
#include <dirent.h> #include <dirent.h>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <locale>
#include <string> #include <string>
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#include "color.h"
void safe_exit(int code) { void safe_exit(int code) {
switch (code) { switch (code) {
@ -44,45 +47,47 @@ std::string bool_to_string(bool bool_in) { return bool_in ? "true" : "false"; }
std::string SoRAuthFile(bool save, std::string data) { std::string SoRAuthFile(bool save, std::string data) {
std::string home = std::getenv("HOME"); std::string home = std::getenv("HOME");
if (home.empty()) { if (home.empty()) {
std::cerr << RED "[ERROR] " RESET << "HOME environment variable not set.\n"; std::cerr << RED "[ERROR] " RESET << "HOME environment variable not set.\n";
safe_exit(EXIT_FAILURE); safe_exit(EXIT_FAILURE);
}
std::string savedir_path = home;
savedir_path.append("/.local/share/bakatui");
if (!std::filesystem::exists(savedir_path)) {
if (!std::filesystem::create_directories(savedir_path)) {
std::cerr << RED "[ERROR] " RESET
<< "Failed to create directory: " << savedir_path << "\n";
safe_exit(EXIT_FAILURE);
} }
}
std::string savedir_path = home; std::string authfile_path = savedir_path + "/auth";
savedir_path.append("/.local/share/bakatui");
if (save) {
if (!std::filesystem::exists(savedir_path)) { std::ofstream authfile(authfile_path);
if (!std::filesystem::create_directories(savedir_path)) { if (!authfile.is_open()) {
std::cerr << RED "[ERROR] " RESET << "Failed to create directory: " << savedir_path << "\n"; std::cerr << RED "[ERROR] " RESET
safe_exit(EXIT_FAILURE); << "Failed to open auth file for writing.\n";
} safe_exit(EXIT_FAILURE);
} }
authfile << data;
std::string authfile_path = savedir_path + "/auth"; authfile.close();
return "";
if (save) { } else {
std::ofstream authfile(authfile_path); std::ifstream authfile(authfile_path);
if (!authfile.is_open()) { if (!authfile.is_open()) {
std::cerr << RED "[ERROR] " RESET << "Failed to open auth file for writing.\n"; std::cerr << RED "[ERROR] " RESET
safe_exit(EXIT_FAILURE); << "Failed to open auth file for reading.\n";
} safe_exit(EXIT_FAILURE);
authfile << data;
authfile.close();
return "";
} else {
std::ifstream authfile(authfile_path);
if (!authfile.is_open()) {
std::cerr << RED "[ERROR] " RESET << "Failed to open auth file for reading.\n";
safe_exit(EXIT_FAILURE);
}
data.assign((std::istreambuf_iterator<char>(authfile)),
std::istreambuf_iterator<char>());
authfile.close();
return data;
} }
data.assign((std::istreambuf_iterator<char>(authfile)),
std::istreambuf_iterator<char>());
authfile.close();
return data;
}
} }
void get_input_and_login() { void get_input_and_login() {
@ -99,6 +104,7 @@ void get_input_and_login() {
bakaapi::login(username, password); bakaapi::login(username, password);
} }
// Original function
void print_in_middle(WINDOW *win, int starty, int startx, int width, void print_in_middle(WINDOW *win, int starty, int startx, int width,
char *string, chtype color) { char *string, chtype color) {
int length, x, y; int length, x, y;
@ -123,19 +129,92 @@ void print_in_middle(WINDOW *win, int starty, int startx, int width,
refresh(); refresh();
} }
// Wide character version
void wprint_in_middle(WINDOW *win, int starty, int startx, int width,
wchar_t *string, chtype color) {
int length, x, y;
float temp;
if (win == NULL)
win = stdscr;
getyx(win, y, x);
if (startx != 0)
x = startx;
if (starty != 0)
y = starty;
if (width == 0)
width = 80;
length = wcslen(string);
temp = (width - length) / 2;
x = startx + (int)temp;
wattron(win, color);
mvwaddwstr(win, y, x, string);
wattroff(win, color);
refresh();
}
const std::string WHITESPACE = " \n\r\t\f\v"; const std::string WHITESPACE = " \n\r\t\f\v";
const std::wstring WWHITESPACE = L" \n\r\t\f\v";
std::string ltrim(const std::string &s) { std::string ltrim(const std::string &s) {
size_t start = s.find_first_not_of(WHITESPACE); size_t start = s.find_first_not_of(WHITESPACE);
return (start == std::string::npos) ? "" : s.substr(start); return (start == std::string::npos) ? "" : s.substr(start);
} }
std::string rtrim(const std::string &s) { std::string rtrim(const std::string &s) {
size_t end = s.find_last_not_of(WHITESPACE); size_t end = s.find_last_not_of(WHITESPACE);
return (end == std::string::npos) ? "" : s.substr(0, end + 1); return (end == std::string::npos) ? "" : s.substr(0, end + 1);
} }
std::string rm_tr_le_whitespace(const std::string &s) { std::string rm_tr_le_whitespace(const std::string &s) {
return rtrim(ltrim(s)); return rtrim(ltrim(s));
}
// Wide character versions
std::wstring wltrim(const std::wstring &s) {
size_t start = s.find_first_not_of(WWHITESPACE);
return (start == std::wstring::npos) ? L"" : s.substr(start);
}
std::wstring wrtrim(const std::wstring &s) {
size_t end = s.find_last_not_of(WWHITESPACE);
return (end == std::wstring::npos) ? L"" : s.substr(0, end + 1);
}
std::wstring wrm_tr_le_whitespace(const std::wstring &s) {
return wrtrim(wltrim(s));
}
// Conversion utilities
char *wchar_to_char(wchar_t *src) {
if (!src)
return nullptr;
size_t len = wcslen(src) + 1; // +1 for null terminator
char *dest = new char[len * MB_CUR_MAX];
std::wcstombs(dest, src, len * MB_CUR_MAX);
return dest;
}
wchar_t *char_to_wchar(char *src) {
if (!src)
return nullptr;
size_t len = strlen(src) + 1; // +1 for null terminator
wchar_t *dest = new wchar_t[len];
std::mbstowcs(dest, src, len);
return dest;
}
std::wstring string_to_wstring(const std::string &str) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.from_bytes(str);
}
std::string wstring_to_string(const std::wstring &wstr) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.to_bytes(wstr);
} }

View File

@ -9,8 +9,22 @@ void safe_exit(int code);
std::string bool_to_string(bool bool_in); std::string bool_to_string(bool bool_in);
std::string SoRAuthFile(bool save, std::string data); std::string SoRAuthFile(bool save, std::string data);
void get_input_and_login(); void get_input_and_login();
// Original functions
void print_in_middle(WINDOW *win, int starty, int startx, int width, void print_in_middle(WINDOW *win, int starty, int startx, int width,
char *string, chtype color); char *string, chtype color);
std::string rm_tr_le_whitespace(const std::string &s); std::string rm_tr_le_whitespace(const std::string &s);
// Wide character support functions
void wprint_in_middle(WINDOW *win, int starty, int startx, int width,
wchar_t *string, chtype color);
std::wstring wrm_tr_le_whitespace(const std::wstring &s);
// Conversion utilities
char *wchar_to_char(wchar_t *src);
wchar_t *char_to_wchar(char *src);
std::wstring string_to_wstring(const std::string &str);
std::string wstring_to_string(const std::wstring &wstr);
#endif #endif

View File

@ -1,23 +1,25 @@
#include "helper_funcs.h" #include "helper_funcs.h"
#include "net.h" #include "net.h"
#include "timetable.h"
#include <cstddef> #include <cstddef>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <curses.h> #include <curses.h>
#include <locale>
#include <menu.h> #include <menu.h>
#include <string>
#include "marks.h" #include "marks.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define CTRLD 4 #define CTRLD 4
char *choices[] = { wchar_t *choices[] = {
"login", "Marks", "timetable", "Komens", L"login", L"Marks", L"timetable", L"Komens",
"Homework", "Absence", "Exit", (char *)NULL, L"Homework", L"Absence", L"Exit", (wchar_t *)NULL,
};
void (*choicesFuncs[])() = {
nullptr, marks_page, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
}; };
void (*choicesFuncs[])() = {nullptr, marks_page, timetable_page, nullptr,
nullptr, nullptr, nullptr, nullptr};
void main_menu() { void main_menu() {
ITEM **my_items; ITEM **my_items;
@ -27,6 +29,7 @@ void main_menu() {
int n_choices, i; int n_choices, i;
/* Initialize curses */ /* Initialize curses */
setlocale(LC_ALL, "");
initscr(); initscr();
start_color(); start_color();
cbreak(); cbreak();
@ -39,7 +42,8 @@ void main_menu() {
n_choices = ARRAY_SIZE(choices); n_choices = ARRAY_SIZE(choices);
my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *)); my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
for (i = 0; i < n_choices; ++i) for (i = 0; i < n_choices; ++i)
my_items[i] = new_item(choices[i], choices[i]); my_items[i] =
new_item(wchar_to_char(choices[i]), wchar_to_char(choices[i]));
/* Crate menu */ /* Crate menu */
my_menu = new_menu((ITEM **)my_items); my_menu = new_menu((ITEM **)my_items);
@ -59,7 +63,7 @@ void main_menu() {
/* Print a border around the main window and print a title */ /* Print a border around the main window and print a title */
box(my_menu_win, 0, 0); box(my_menu_win, 0, 0);
print_in_middle(my_menu_win, 1, 0, 40, "Main Menu", COLOR_PAIR(1)); wprint_in_middle(my_menu_win, 1, 0, 40, L"Main Menu", COLOR_PAIR(1));
mvwaddch(my_menu_win, 2, 0, ACS_LTEE); mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38); mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
mvwaddch(my_menu_win, 2, 39, ACS_RTEE); mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
@ -90,7 +94,7 @@ void main_menu() {
menu_driver(my_menu, REQ_UP_ITEM); menu_driver(my_menu, REQ_UP_ITEM);
break; break;
case 10: // ENTER case 10: // ENTER
clear(); clear();
choicesFuncs[item_index(current_item(my_menu))](); choicesFuncs[item_index(current_item(my_menu))]();
pos_menu_cursor(my_menu); pos_menu_cursor(my_menu);
refresh(); refresh();

View File

@ -1,5 +1,7 @@
#include "marks.h" #include "marks.h"
#include "helper_funcs.h" #include "helper_funcs.h"
#include "net.h"
#include <algorithm>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdio> #include <cstdio>
@ -7,40 +9,17 @@
#include <curses.h> #include <curses.h>
#include <format> #include <format>
#include <iostream> #include <iostream>
#include <locale>
#include <menu.h> #include <menu.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <panel.h> #include <panel.h>
#include <string> #include <string>
#include <algorithm>
#include "net.h"
using nlohmann::json; using nlohmann::json;
// Thsi code is based on // This code is based on
// https://github.com/tony/NCURSES-Programming-HOWTO-examples/blob/master/16-panels // https://github.com/tony/NCURSES-Programming-HOWTO-examples/blob/master/16-panels
/* // MIT License (see original file)
The MIT License (MIT)
Copyright (c) 2016 Tony Narlock
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#define NLINES 10 #define NLINES 10
#define NCOLS 40 #define NCOLS 40
@ -51,8 +30,8 @@ SOFTWARE.
#define DEFAULT_PADDING 4 #define DEFAULT_PADDING 4
void init_wins(WINDOW **wins, int n, json marks_json); void init_wins(WINDOW **wins, int n, json marks_json);
void win_show(WINDOW *win, char *label, int label_color, int width, int height, void win_show(WINDOW *win, wchar_t *label, int label_color, int width,
json marks_json, int SubjectIndex); int height, json marks_json, int SubjectIndex);
void marks_page() { void marks_page() {
// DONT FORGET TO UNCOMMENT // DONT FORGET TO UNCOMMENT
@ -98,8 +77,8 @@ void marks_page() {
// Attach panels // Attach panels
for (size_t i = 0; i < size_my_panels; i++) { for (size_t i = 0; i < size_my_panels; i++) {
my_panels[i] = new_panel(my_wins[i]); my_panels[i] = new_panel(my_wins[i]);
set_panel_userptr(my_panels[i], set_panel_userptr(my_panels[i], (i + 1 < size_my_panels) ? my_panels[i + 1]
(i + 1 < size_my_panels) ? my_panels[i+1] : my_panels[0]); : my_panels[0]);
} }
update_panels(); update_panels();
@ -116,17 +95,17 @@ void marks_page() {
bool needs_update = false; bool needs_update = false;
switch (ch) { switch (ch) {
case KEY_UP: case KEY_UP:
case 'k': // Vim-style up case 'k': // Vim-style up
y_offset--; y_offset--;
needs_update = true; needs_update = true;
break; break;
case KEY_DOWN: case KEY_DOWN:
case 'j': // Vim-style down case 'j': // Vim-style down
y_offset++; y_offset++;
needs_update = true; needs_update = true;
break; break;
} }
// Update window positions if scrolled // Update window positions if scrolled
@ -154,36 +133,48 @@ void marks_page() {
/* Put all the windows */ /* Put all the windows */
void init_wins(WINDOW **wins, int n, json marks_json) { void init_wins(WINDOW **wins, int n, json marks_json) {
int x, y, i; int x, y, i;
char label[1500]; wchar_t label[1500];
y = DEFAULT_Y_OFFSET; y = DEFAULT_Y_OFFSET;
x = DEFAULT_X_OFFSET; x = DEFAULT_X_OFFSET;
uint8_t curent_color = 0; uint8_t curent_color = 0;
int MaxHight = 0; int MaxHight = 0;
// this loop true subjects // this loop through subjects
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
// Calculate label and max_text_length to determine window width // Calculate label and max_text_length to determine window width
std::string sub_name = marks_json["Subjects"][i]["Subject"]["Name"]; std::string sub_name = marks_json["Subjects"][i]["Subject"]["Name"];
// DEBUG
// std::clog << BLUE"[LOG]" << RESET" procesing subject: " << sub_name << "\n";
std::string sub_avg_s = marks_json["Subjects"][i]["AverageText"]; std::string sub_avg_s = marks_json["Subjects"][i]["AverageText"];
sprintf(label, "%s - avg: %s", sub_name.c_str(), sub_avg_s.c_str());
size_t max_text_length = strlen(label); // Convert to wchar_t
std::wstring wsub_name = string_to_wstring(sub_name);
std::wstring wsub_avg_s = string_to_wstring(sub_avg_s);
// Using swprintf for wide character formatting
swprintf(label, sizeof(label) / sizeof(label[0]), L"%ls - avg: %ls",
wsub_name.c_str(), wsub_avg_s.c_str());
size_t max_text_length = wcslen(label);
for (int j = 0; j < marks_json["Subjects"][i]["Marks"].size(); j++) { for (int j = 0; j < marks_json["Subjects"][i]["Marks"].size(); j++) {
std::string caption = rm_tr_le_whitespace(marks_json["Subjects"][i]["Marks"][j]["Caption"]); std::string caption =
std::string theme = rm_tr_le_whitespace(marks_json["Subjects"][i]["Marks"][j]["Theme"]); rm_tr_le_whitespace(marks_json["Subjects"][i]["Marks"][j]["Caption"]);
caption = rm_tr_le_whitespace(caption); std::string theme =
theme = rm_tr_le_whitespace(theme); rm_tr_le_whitespace(marks_json["Subjects"][i]["Marks"][j]["Theme"]);
std::wstring wcaption = string_to_wstring(caption);
std::wstring wtheme = string_to_wstring(theme);
// Some code that does something and fixes some edge cases
std::string testCaption = caption + std::format(" {{{}}} [{}]", "X", 0);
std::wstring wTestCaption = string_to_wstring(testCaption);
max_text_length = max_text_length =
std::max({max_text_length, caption.length(), theme.length()}); std::max({max_text_length, wTestCaption.length(), wtheme.length()});
} }
int width = max_text_length + DEFAULT_PADDING; int width = max_text_length + DEFAULT_PADDING;
// hanndle windows overflowing off screen // handle windows overflowing off screen
if (x + width > COLS) { if (x + width > COLS) {
x = DEFAULT_X_OFFSET; x = DEFAULT_X_OFFSET;
y += MaxHight + 2; y += MaxHight + 2;
@ -207,8 +198,8 @@ void init_wins(WINDOW **wins, int n, json marks_json) {
} }
/* Show the window with a border and a label */ /* Show the window with a border and a label */
void win_show(WINDOW *win, char *label, int label_color, int width, int height, void win_show(WINDOW *win, wchar_t *label, int label_color, int width,
json marks_json, int SubjectIndex) { int height, json marks_json, int SubjectIndex) {
int startx, starty; int startx, starty;
wresize(win, height, width); wresize(win, height, width);
@ -221,30 +212,49 @@ void win_show(WINDOW *win, char *label, int label_color, int width, int height,
mvwhline(win, 2, 1, ACS_HLINE, width - 2); mvwhline(win, 2, 1, ACS_HLINE, width - 2);
mvwaddch(win, 2, width - 1, ACS_RTEE); mvwaddch(win, 2, width - 1, ACS_RTEE);
print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color)); wprint_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
char CaptionBuf[1500]; wchar_t CaptionBuf[1500];
char ThemeBuf[1500]; wchar_t ThemeBuf[1500];
std::string Caption; std::wstring wCaption;
int AdditionalOffset = 0; int AdditionalOffset = 0;
for (size_t i = 0; i < marks_json["Subjects"][SubjectIndex]["Marks"].size(); for (size_t i = 0; i < marks_json["Subjects"][SubjectIndex]["Marks"].size();
i++) { i++) {
Caption = marks_json["Subjects"][SubjectIndex]["Marks"][i]["Caption"]; std::string Caption =
marks_json["Subjects"][SubjectIndex]["Marks"][i]["Caption"];
Caption = rm_tr_le_whitespace(Caption); Caption = rm_tr_le_whitespace(Caption);
Caption.append(std::format(" - {{{}}} [{}]",
marks_json["Subjects"][SubjectIndex]["Marks"][i]["MarkText"]
.get<std::string>(),marks_json["Subjects"][SubjectIndex]["Marks"][i]["Weight"].get<int>()));
strncpy(CaptionBuf, Caption.c_str(), sizeof(CaptionBuf)-1); std::string MarkText =
print_in_middle(win, 3 + i + AdditionalOffset, 0, width, CaptionBuf,COLOR_PAIR(label_color)); marks_json["Subjects"][SubjectIndex]["Marks"][i]["MarkText"];
int Weight = marks_json["Subjects"][SubjectIndex]["Marks"][i]["Weight"];
strncpy(ThemeBuf, // Create formatted string with mark and weight
rm_tr_le_whitespace(marks_json["Subjects"][SubjectIndex]["Marks"][i]["Theme"] std::string formattedCaption =
.get<std::string>()) Caption + std::format(" - {{{}}} [{}]", MarkText, Weight);
.c_str(),
sizeof(ThemeBuf)-1); // Convert to wide string
print_in_middle(win, 3 + i + 1 + AdditionalOffset, 0, width, ThemeBuf, wCaption = string_to_wstring(formattedCaption);
COLOR_PAIR(label_color));
wcsncpy(CaptionBuf, wCaption.c_str(),
sizeof(CaptionBuf) / sizeof(CaptionBuf[0]) - 1);
CaptionBuf[sizeof(CaptionBuf) / sizeof(CaptionBuf[0]) - 1] =
L'\0'; // Ensure null termination
wprint_in_middle(win, 3 + i + AdditionalOffset, 0, width, CaptionBuf,
COLOR_PAIR(label_color));
std::string Theme =
marks_json["Subjects"][SubjectIndex]["Marks"][i]["Theme"];
std::wstring wTheme = string_to_wstring(rm_tr_le_whitespace(Theme));
wcsncpy(ThemeBuf, wTheme.c_str(),
sizeof(ThemeBuf) / sizeof(ThemeBuf[0]) - 1);
ThemeBuf[sizeof(ThemeBuf) / sizeof(ThemeBuf[0]) - 1] =
L'\0'; // Ensure null termination
wprint_in_middle(win, 3 + i + 1 + AdditionalOffset, 0, width, ThemeBuf,
COLOR_PAIR(label_color));
AdditionalOffset++; AdditionalOffset++;
} }
} }

View File

@ -1,5 +1,6 @@
#include "net.h" #include "net.h"
#include "color.h" #include "color.h"
#include "const.h"
#include "helper_funcs.h" #include "helper_funcs.h"
#include "main.h" #include "main.h"
#include <cerrno> #include <cerrno>
@ -16,7 +17,6 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <nlohmann/json_fwd.hpp> #include <nlohmann/json_fwd.hpp>
#include <string> #include <string>
#include "const.h"
using nlohmann::json; using nlohmann::json;
@ -38,9 +38,8 @@ size_t WriteCallback(void *contents, size_t size, size_t nmemb,
return totalSize; return totalSize;
} }
std::tuple<std::string, int> send_curl_request(std::string endpoint, std::tuple<std::string, int>
uint8_t type, send_curl_request(std::string endpoint, uint8_t type, std::string req_data) {
std::string req_data) {
std::string response; std::string response;
std::string url = baka_api_url + endpoint; std::string url = baka_api_url + endpoint;
if (type == GET) { if (type == GET) {
@ -54,28 +53,32 @@ std::tuple<std::string, int> send_curl_request(std::string endpoint,
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); if (config.ignoressl) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
}
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
struct curl_slist *headers = NULL; struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); headers = curl_slist_append(
headers = curl_slist_append(headers, std::format("User-Agent: bakatui/{}", VERSION).c_str()); headers, "Content-Type: application/x-www-form-urlencoded");
headers = curl_slist_append(
headers, std::format("User-Agent: bakatui/{}", VERSION).c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
switch (type) { switch (type) {
case GET: case GET:
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
break; break;
case POST: case POST:
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req_data.c_str()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req_data.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L); curl_easy_setopt(curl, CURLOPT_POST, 1L);
break; break;
default: default:
std::cerr << RED "[ERROR] " << RESET "invalid metod\n"; std::cerr << RED "[ERROR] " << RESET "invalid metod\n";
safe_exit(EINVAL); safe_exit(EINVAL);
} }
} else { } else {
@ -87,8 +90,6 @@ std::tuple<std::string, int> send_curl_request(std::string endpoint,
int http_code = 0; int http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
return {response, http_code}; return {response, http_code};
} }
namespace bakaapi { namespace bakaapi {
@ -141,7 +142,8 @@ void refresh_access_token() {
refresh_token); refresh_token);
// DEBUG // DEBUG
std::clog << "calling send_curl_request() with folowing req_data\n" << req_data << std::endl; std::clog << "calling send_curl_request() with folowing req_data\n"
<< req_data << std::endl;
auto [response, http_code] = send_curl_request("api/login", POST, req_data); auto [response, http_code] = send_curl_request("api/login", POST, req_data);
if (http_code != 200) { if (http_code != 200) {
std::cerr << RED "[ERROR] " << RESET << http_code std::cerr << RED "[ERROR] " << RESET << http_code
@ -156,7 +158,7 @@ void refresh_access_token() {
access_token = resp_parsed["access_token"]; access_token = resp_parsed["access_token"];
} }
void is_access_token_empty() { void is_access_token_empty() {
if(access_token.empty()) { if (access_token.empty()) {
json authfile_parsed = json::parse(SoRAuthFile(false, "")); json authfile_parsed = json::parse(SoRAuthFile(false, ""));
access_token = authfile_parsed["access_token"]; access_token = authfile_parsed["access_token"];
} }
@ -164,19 +166,20 @@ void is_access_token_empty() {
// supports all endpoints that only require access_token // supports all endpoints that only require access_token
json get_data_from_endpoint(std::string endpoint) { json get_data_from_endpoint(std::string endpoint) {
is_access_token_empty(); is_access_token_empty();
std::string req_data = std::string req_data =
std::format("Authorization=Bearer&access_token={}", std::format("Authorization=Bearer&access_token={}", access_token);
access_token);
auto [response, http_code] = send_curl_request(endpoint, GET, req_data); auto [response, http_code] = send_curl_request(endpoint, GET, req_data);
if(http_code != 200) { if (http_code != 200) {
// DEBUG // DEBUG
std::clog << "Failed geting data from endpoint: " << endpoint << " code: " << http_code << "\nrequest: " << req_data <<"\nresponse: " << response << std::endl; std::clog << "Failed geting data from endpoint: " << endpoint
refresh_access_token(); << " code: " << http_code << "\nrequest: " << req_data
} << "\nresponse: " << response << std::endl;
refresh_access_token();
}
return json::parse(response); return json::parse(response);
} }
} // namespace bakaapi } // namespace bakaapi

View File

@ -1,32 +1,49 @@
#include "timetable.h" #include "timetable.h"
#include <cstdint>
#include <nlohmann/json.hpp>
#include "net.h" #include "net.h"
#include <cstdint>
#include <format>
#include <fstream> #include <fstream>
#include <iostream>
#include <locale>
#include <ncurses.h>
#include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
#define NLINES 10
#define NCOLS 40
#define DEFAULT_X_OFFSET 10
#define DEFAULT_Y_OFFSET 2
#define DEFAULT_PADDING 4
void timetable_page() { void timetable_page() {
// DONT FORGET TO UNCOMMENT // DONT FORGET TO UNCOMMENT
// json resp_from_api = bakaapi::get_data_from_endpoint("api/3/timetable/actual"); // json resp_from_api =
std::ifstream f("test-data/timetable.json"); // bakaapi::get_data_from_endpoint("api/3/timetable/actual");
json resp_from_api = json::parse(f); std::ifstream f("test-data/timetable.json");
json resp_from_api = json::parse(f);
// calculate table size // calculate table size
// some lambda dark magic
uint8_t column_number = 0; const uint8_t num_of_columns = [&]() -> uint8_t {
for(uint8_t i = 0; i < resp_from_api["Days"].size(); i++) { uint8_t result = 0;
(resp_from_api["Days"][i]["Atoms"].size() > column_number) ? (column_number = resp_from_api["Days"][i]["Atoms"].size()); for (uint8_t i = 0; i < resp_from_api["Days"].size(); i++) {
uint8_t currentSize = resp_from_api["Days"][i]["Atoms"].size();
if (currentSize > result) {
result = currentSize;
}
} }
return result;
}();
const uint8_t num_of_rows = resp_from_api["Days"].size();
setlocale(LC_ALL, "");
/* Initialize curses */
initscr();
start_color();
cbreak();
noecho();
keypad(stdscr, TRUE);
// Use wide character printing
std::wstring msg = std::format(L"LINES: {} COLS: {}", LINES, COLS);
mvaddwstr(0, 0, msg.c_str());
refresh();
getch(); // Wait for key press
endwin();
} }