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
// main.rs
//
// Copyright 2020-2024 nee <nee-git@hidamari.blue>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#[macro_use]
extern crate tracing;
mod application;
#[rustfmt::skip]
mod config;
mod booru;
mod browse_page;
mod data;
mod download;
mod image_page;
mod saved_searches_sidebar;
mod settings;
mod settings_data;
mod sidebar_booru_select;
mod thumb;
mod wiki_page;
mod window;
use gettextrs::{LocaleCategory, gettext};
use gtk::{gio, glib};
use once_cell::sync::Lazy;
pub use settings_data::DEFAULT_THUMB_SIZE_IMAGE;
pub use settings_data::DEFAULT_THUMB_SIZE_UI;
use sqlx::migrate::Migrator;
use std::sync::LazyLock;
use self::application::ExampleApplication;
use self::config::{GETTEXT_PACKAGE, LOCALEDIR, RESOURCES_FILE};
// tokio should be used when doing http fetches, since reqwest depens on it.
pub static RUNTIME: Lazy<tokio::runtime::Runtime> =
Lazy::new(|| tokio::runtime::Runtime::new().unwrap());
static MIGRATOR: Migrator = sqlx::migrate!(); // defaults to "./migrations"
pub static POOL: LazyLock<sqlx::SqlitePool> = LazyLock::new(|| RUNTIME.block_on(init_db()));
fn main() -> glib::ExitCode {
// Initialize logger
tracing_subscriber::fmt::init();
// Prepare i18n
gettextrs::setlocale(LocaleCategory::LcAll, "");
gettextrs::bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR).expect("Unable to bind the text domain");
gettextrs::textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain");
glib::set_application_name(&gettext("Boorus"));
let res = gio::Resource::load(RESOURCES_FILE).expect("Could not load gresource file");
gio::resources_register(&res);
let _ = POOL.clone(); // init the db
// uncomment to easily get hash for any new domain to implement
// use std::collections::HashMap;
// use std::hash::Hasher;
// let mut hasher = std::collections::hash_map::DefaultHasher::new();
// hasher.write("__builtin_localbooru".as_bytes());
// let hash = hasher.finish();
// println!("HASH {}", hash);
let app = ExampleApplication::default();
app.run()
}
async fn init_db() -> sqlx::SqlitePool {
use sqlx::sqlite::*;
let mut path = gtk::glib::user_config_dir();
path.push("boorus");
if let Err(e) = std::fs::create_dir_all(&path) {
error!("failed to create settings dir, during sql pool init: {e}");
}
path.push("db.db");
println!("PATH {}", path.display());
let pool = SqlitePool::connect_with(
SqliteConnectOptions::new()
.filename(path)
.create_if_missing(true),
)
.await
.expect("failed to create db");
MIGRATOR
.run(&pool)
.await
.expect("Error running DB migrations");
pool
}