Compare commits

...

3 commits

Author SHA1 Message Date
d76e7a49ed feat!: switch database format to CBOR (not compatible with previous format)
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-04-02 18:19:34 +02:00
e53a8ba92b chore(release): prepare for v0.3.0 2023-04-02 17:37:22 +02:00
4421dec657 chore(release): bump version -> 0.3.0 2023-04-02 17:36:58 +02:00
13 changed files with 85 additions and 89 deletions

View file

@ -2,6 +2,24 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [0.3.0] - 2023-04-02
### Bug Fixes
- Move menu bar down
- Set icon size to 48px
### Features
- Add last-modified date to all GET responses
- Add last-version tag to PageInfoModal
- Purge file storage daily
### Miscellaneous Tasks
- Update cargo dependencies
- Bump version -> 0.3.0
## [0.2.0] - 2023-04-01 ## [0.2.0] - 2023-04-01
### Bug Fixes ### Bug Fixes

50
Cargo.lock generated
View file

@ -716,7 +716,7 @@ checksum = "bdd2162b720141a91a054640662d3edce3d50a944a50ffca5313cd951abb35b4"
dependencies = [ dependencies = [
"bit_field", "bit_field",
"flume", "flume",
"half", "half 2.2.1",
"lebe", "lebe",
"miniz_oxide", "miniz_oxide",
"rayon-core", "rayon-core",
@ -984,6 +984,12 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "half"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]] [[package]]
name = "half" name = "half"
version = "2.2.1" version = "2.2.1"
@ -1589,12 +1595,6 @@ dependencies = [
"windows-sys 0.45.0", "windows-sys 0.45.0",
] ]
[[package]]
name = "paste"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]] [[package]]
name = "path_macro" name = "path_macro"
version = "1.0.0" version = "1.0.0"
@ -1977,28 +1977,6 @@ dependencies = [
"uncased", "uncased",
] ]
[[package]]
name = "rmp"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f"
dependencies = [
"byteorder",
"num-traits",
"paste",
]
[[package]]
name = "rmp-serde"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5b13be192e0220b8afb7222aa5813cb62cc269ebb5cac346ca6487681d2913e"
dependencies = [
"byteorder",
"rmp",
"serde",
]
[[package]] [[package]]
name = "ron" name = "ron"
version = "0.7.1" version = "0.7.1"
@ -2139,6 +2117,16 @@ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde_cbor"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half 1.8.2",
"serde",
]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.159" version = "1.0.159"
@ -2358,7 +2346,7 @@ dependencies = [
[[package]] [[package]]
name = "talon" name = "talon"
version = "0.2.0" version = "0.3.0"
dependencies = [ dependencies = [
"async-compression", "async-compression",
"brotli", "brotli",
@ -2378,10 +2366,10 @@ dependencies = [
"poem", "poem",
"poem-openapi", "poem-openapi",
"regex", "regex",
"rmp-serde",
"rstest", "rstest",
"rust-embed", "rust-embed",
"serde", "serde",
"serde_cbor",
"serde_json", "serde_json",
"sha2", "sha2",
"shadow-rs", "shadow-rs",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "talon" name = "talon"
version = "0.2.0" version = "0.3.0"
edition = "2021" edition = "2021"
authors = ["ThetaDev <t.testboy@gmail.com>"] authors = ["ThetaDev <t.testboy@gmail.com>"]
license = "MIT" license = "MIT"
@ -16,7 +16,7 @@ tokio = { version = "1.25.0", features = ["rt-multi-thread", "fs", "signal"] }
sled = "0.34.7" sled = "0.34.7"
serde = "1.0.152" serde = "1.0.152"
serde_json = "1.0.93" serde_json = "1.0.93"
rmp-serde = "1.1.1" serde_cbor = "0.11.2"
toml = "0.7.2" toml = "0.7.2"
thiserror = "1.0.38" thiserror = "1.0.38"
time = { version = "0.3.15", features = [ time = { version = "0.3.15", features = [

View file

@ -107,7 +107,7 @@ impl TalonApi {
.db .db
.get_website(&subdomain) .get_website(&subdomain)
.map(|website| { .map(|website| {
let modified = website.updated_at(); let modified = website.updated_at;
Response::new(Json(Website::from((subdomain.0, website)))).header( Response::new(Json(Website::from((subdomain.0, website)))).header(
header::LAST_MODIFIED, header::LAST_MODIFIED,
httpdate::fmt_http_date(modified.into()), httpdate::fmt_http_date(modified.into()),
@ -308,7 +308,7 @@ impl TalonApi {
.map(|data| { .map(|data| {
Response::new(Json(data)).header( Response::new(Json(data)).header(
header::LAST_MODIFIED, header::LAST_MODIFIED,
httpdate::fmt_http_date(website.updated_at().into()), httpdate::fmt_http_date(website.updated_at.into()),
) )
}) })
.map_err(Error::from) .map_err(Error::from)

View file

@ -30,10 +30,8 @@ struct DbInner {
pub enum DbError { pub enum DbError {
#[error("sled db error: {0}")] #[error("sled db error: {0}")]
Sled(#[from] sled::Error), Sled(#[from] sled::Error),
#[error("msgpack serialization error: {0}")] #[error("cbor serialization error: {0}")]
Serialize(#[from] rmp_serde::encode::Error), Serialize(#[from] serde_cbor::Error),
#[error("msgpack deserialization error: {0}")]
Deserialize(#[from] rmp_serde::decode::Error),
#[error("json serialization error: {0}")] #[error("json serialization error: {0}")]
Json(#[from] serde_json::Error), Json(#[from] serde_json::Error),
#[error("{0} with id `{1}` already exists")] #[error("{0} with id `{1}` already exists")]
@ -100,7 +98,7 @@ impl Db {
for item in self.i.websites.iter() { for item in self.i.websites.iter() {
let (k, v) = item?; let (k, v) = item?;
let key = Self::key_to_string(k.to_vec())?; let key = Self::key_to_string(k.to_vec())?;
let value = rmp_serde::from_slice::<Website>(&v)?; let value = serde_cbor::from_slice::<Website>(&v)?;
let dataset = ExportDataset::Website { key, value }; let dataset = ExportDataset::Website { key, value };
@ -111,7 +109,7 @@ impl Db {
for item in self.i.versions.iter() { for item in self.i.versions.iter() {
let (k, v) = item?; let (k, v) = item?;
let key = Self::key_to_string(k.to_vec())?; let key = Self::key_to_string(k.to_vec())?;
let value = rmp_serde::from_slice::<Version>(&v)?; let value = serde_cbor::from_slice::<Version>(&v)?;
let dataset = ExportDataset::Version { key, value }; let dataset = ExportDataset::Version { key, value };
serde_json::to_writer(&mut writer, &dataset)?; serde_json::to_writer(&mut writer, &dataset)?;
@ -152,11 +150,11 @@ impl Db {
fn import_dataset(&self, ds: ExportDataset) -> Result<()> { fn import_dataset(&self, ds: ExportDataset) -> Result<()> {
match ds { match ds {
ExportDataset::Website { key, value } => { ExportDataset::Website { key, value } => {
let data = rmp_serde::to_vec(&value)?; let data = serde_cbor::to_vec(&value)?;
self.i.websites.insert(key, data)?; self.i.websites.insert(key, data)?;
} }
ExportDataset::Version { key, value } => { ExportDataset::Version { key, value } => {
let data = rmp_serde::to_vec(&value)?; let data = serde_cbor::to_vec(&value)?;
self.i.versions.insert(key, data)?; self.i.versions.insert(key, data)?;
} }
ExportDataset::File { key, value } => { ExportDataset::File { key, value } => {
@ -178,13 +176,13 @@ impl Db {
/// Get a website from the database /// Get a website from the database
pub fn get_website(&self, subdomain: &str) -> Result<Website> { pub fn get_website(&self, subdomain: &str) -> Result<Website> {
let data = self.i.websites.get(subdomain)?; let data = self.i.websites.get(subdomain)?;
data.and_then(|data| rmp_serde::from_slice::<Website>(data.as_ref()).ok()) data.and_then(|data| serde_cbor::from_slice::<Website>(data.as_ref()).ok())
.ok_or_else(|| DbError::NotExists("website", subdomain.to_owned())) .ok_or_else(|| DbError::NotExists("website", subdomain.to_owned()))
} }
/// Insert a new website into the database /// Insert a new website into the database
pub fn insert_website(&self, subdomain: &str, website: &Website) -> Result<()> { pub fn insert_website(&self, subdomain: &str, website: &Website) -> Result<()> {
let data = rmp_serde::to_vec(website)?; let data = serde_cbor::to_vec(website)?;
self.i self.i
.websites .websites
.compare_and_swap(subdomain, None::<&[u8]>, Some(data))? .compare_and_swap(subdomain, None::<&[u8]>, Some(data))?
@ -198,7 +196,7 @@ impl Db {
.i .i
.websites .websites
.update_and_fetch(subdomain, |data| match data { .update_and_fetch(subdomain, |data| match data {
Some(data) => match rmp_serde::from_slice::<Website>(data) { Some(data) => match serde_cbor::from_slice::<Website>(data) {
Ok(mut w) => { Ok(mut w) => {
let website = website.clone(); let website = website.clone();
w.name = website.name.unwrap_or(w.name); w.name = website.name.unwrap_or(w.name);
@ -208,9 +206,9 @@ impl Db {
w.source_url = website.source_url.unwrap_or(w.source_url); w.source_url = website.source_url.unwrap_or(w.source_url);
w.source_icon = website.source_icon.unwrap_or(w.source_icon); w.source_icon = website.source_icon.unwrap_or(w.source_icon);
w.has_icon = website.has_icon.unwrap_or(w.has_icon); w.has_icon = website.has_icon.unwrap_or(w.has_icon);
w.updated_at = Some(OffsetDateTime::now_utc()); w.updated_at = OffsetDateTime::now_utc();
rmp_serde::to_vec(&w).ok() serde_cbor::to_vec(&w).ok()
} }
Err(_) => None, Err(_) => None,
}, },
@ -252,7 +250,7 @@ impl Db {
self.i.websites.iter().map(|r| { self.i.websites.iter().map(|r| {
r.map_err(DbError::from).and_then(|(k, v)| { r.map_err(DbError::from).and_then(|(k, v)| {
let subdomain = Self::key_to_string(k.to_vec())?; let subdomain = Self::key_to_string(k.to_vec())?;
let website = rmp_serde::from_slice::<Website>(&v)?; let website = serde_cbor::from_slice::<Website>(&v)?;
Ok((subdomain, website)) Ok((subdomain, website))
}) })
}) })
@ -301,7 +299,7 @@ impl Db {
let key = Self::version_key(subdomain, id); let key = Self::version_key(subdomain, id);
let data = self.i.versions.get(&key)?; let data = self.i.versions.get(&key)?;
data.and_then(|data| rmp_serde::from_slice::<Version>(data.as_ref()).ok()) data.and_then(|data| serde_cbor::from_slice::<Version>(data.as_ref()).ok())
.ok_or_else(|| DbError::NotExists("version", key)) .ok_or_else(|| DbError::NotExists("version", key))
} }
@ -313,16 +311,16 @@ impl Db {
.i .i
.websites .websites
.update_and_fetch(subdomain, |data| match data { .update_and_fetch(subdomain, |data| match data {
Some(data) => match rmp_serde::from_slice::<Website>(data) { Some(data) => match serde_cbor::from_slice::<Website>(data) {
Ok(mut w) => { Ok(mut w) => {
w.vid_count += 1; w.vid_count += 1;
rmp_serde::to_vec(&w).ok() serde_cbor::to_vec(&w).ok()
} }
Err(_) => None, Err(_) => None,
}, },
None => None, None => None,
})? })?
.and_then(|data| rmp_serde::from_slice::<Website>(&data).ok()); .and_then(|data| serde_cbor::from_slice::<Website>(&data).ok());
let id = match ws { let id = match ws {
Some(ws) => ws.vid_count, Some(ws) => ws.vid_count,
@ -330,7 +328,7 @@ impl Db {
}; };
let key = Self::version_key(subdomain, id); let key = Self::version_key(subdomain, id);
let data = rmp_serde::to_vec(version)?; let data = serde_cbor::to_vec(version)?;
self.i self.i
.versions .versions
.compare_and_swap(&key, None::<&[u8]>, Some(data))? .compare_and_swap(&key, None::<&[u8]>, Some(data))?
@ -345,12 +343,12 @@ impl Db {
self.i self.i
.websites .websites
.update_and_fetch(subdomain, |data| match data { .update_and_fetch(subdomain, |data| match data {
Some(data) => match rmp_serde::from_slice::<Website>(data) { Some(data) => match serde_cbor::from_slice::<Website>(data) {
Ok(mut w) => { Ok(mut w) => {
if w.vid_count == version { if w.vid_count == version {
w.vid_count -= 1; w.vid_count -= 1;
} }
rmp_serde::to_vec(&w).ok() serde_cbor::to_vec(&w).ok()
} }
Err(_) => None, Err(_) => None,
}, },
@ -418,7 +416,7 @@ impl Db {
self.i.versions.scan_prefix(key).map(|r| { self.i.versions.scan_prefix(key).map(|r| {
r.map_err(DbError::from).and_then(|(k, v)| { r.map_err(DbError::from).and_then(|(k, v)| {
let (_, id) = Self::split_version_key(k.to_vec())?; let (_, id) = Self::split_version_key(k.to_vec())?;
let version = rmp_serde::from_slice::<Version>(&v)?; let version = serde_cbor::from_slice::<Version>(&v)?;
Ok((id, version)) Ok((id, version))
}) })
}) })

View file

@ -12,6 +12,8 @@ pub struct Website {
pub name: String, pub name: String,
/// Website creation date /// Website creation date
pub created_at: OffsetDateTime, pub created_at: OffsetDateTime,
/// Website update date
pub updated_at: OffsetDateTime,
/// Latest version ID /// Latest version ID
pub latest_version: Option<u32>, pub latest_version: Option<u32>,
/// Color of the page icon /// Color of the page icon
@ -27,11 +29,7 @@ pub struct Website {
/// value + 1 will be the next version ID /// value + 1 will be the next version ID
pub vid_count: u32, pub vid_count: u32,
/// Does the website have an icon? /// Does the website have an icon?
#[serde(default)]
pub has_icon: bool, pub has_icon: bool,
/// Website update date
#[serde(default)]
pub updated_at: Option<OffsetDateTime>,
} }
impl Default for Website { impl Default for Website {
@ -41,7 +39,7 @@ impl Default for Website {
Self { Self {
name: Default::default(), name: Default::default(),
created_at, created_at,
updated_at: Some(created_at), updated_at: created_at,
latest_version: Default::default(), latest_version: Default::default(),
color: Default::default(), color: Default::default(),
visibility: Default::default(), visibility: Default::default(),
@ -53,12 +51,6 @@ impl Default for Website {
} }
} }
impl Website {
pub fn updated_at(&self) -> OffsetDateTime {
self.updated_at.unwrap_or(self.created_at)
}
}
/// Update a website in the database with the contained values /// Update a website in the database with the contained values
/// ///
/// Values set to `None` remain unchanged. /// Values set to `None` remain unchanged.

View file

@ -75,7 +75,7 @@ fn insert_websites(db: &Db) {
&Website { &Website {
name: "ThetaDev".to_owned(), name: "ThetaDev".to_owned(),
created_at: datetime!(2023-02-18 16:30 +0), created_at: datetime!(2023-02-18 16:30 +0),
updated_at: Some(datetime!(2023-02-18 16:30 +0)), updated_at: datetime!(2023-02-18 16:30 +0),
latest_version: Some(2), latest_version: Some(2),
color: Some(2068974), color: Some(2068974),
visibility: talon::model::Visibility::Featured, visibility: talon::model::Visibility::Featured,
@ -88,7 +88,7 @@ fn insert_websites(db: &Db) {
&Website { &Website {
name: "Spotify-Gender-Ex".to_owned(), name: "Spotify-Gender-Ex".to_owned(),
created_at: datetime!(2023-02-18 16:30 +0), created_at: datetime!(2023-02-18 16:30 +0),
updated_at: Some(datetime!(2023-02-18 16:30 +0)), updated_at: datetime!(2023-02-18 16:30 +0),
latest_version: Some(1), latest_version: Some(1),
color: Some(1947988), color: Some(1947988),
visibility: talon::model::Visibility::Featured, visibility: talon::model::Visibility::Featured,
@ -103,7 +103,7 @@ fn insert_websites(db: &Db) {
&Website { &Website {
name: "RustyPipe".to_owned(), name: "RustyPipe".to_owned(),
created_at: datetime!(2023-02-20 18:30 +0), created_at: datetime!(2023-02-20 18:30 +0),
updated_at: Some(datetime!(2023-02-20 18:30 +0)), updated_at: datetime!(2023-02-20 18:30 +0),
latest_version: Some(1), latest_version: Some(1),
color: Some(7943647), color: Some(7943647),
visibility: talon::model::Visibility::Featured, visibility: talon::model::Visibility::Featured,
@ -118,7 +118,7 @@ fn insert_websites(db: &Db) {
&Website { &Website {
name: "SvelteKit SPA".to_owned(), name: "SvelteKit SPA".to_owned(),
created_at: datetime!(2023-03-03 22:00 +0), created_at: datetime!(2023-03-03 22:00 +0),
updated_at: Some(datetime!(2023-03-03 22:00 +0)), updated_at: datetime!(2023-03-03 22:00 +0),
latest_version: Some(1), latest_version: Some(1),
color: Some(16727552), color: Some(16727552),
visibility: talon::model::Visibility::Hidden, visibility: talon::model::Visibility::Hidden,

View file

@ -2,9 +2,9 @@
source: tests/tests.rs source: tests/tests.rs
expression: data expression: data
--- ---
{"type":"website","key":"rustypipe","value":{"name":"RustyPipe","created_at":[2023,51,18,30,0,0,0,0,0],"latest_version":1,"color":7943647,"visibility":"featured","source_url":"https://code.thetadev.de/ThetaDev/rustypipe","source_icon":"gitea","vid_count":1,"has_icon":false,"updated_at":[2023,51,18,30,0,0,0,0,0]}} {"type":"website","key":"rustypipe","value":{"name":"RustyPipe","created_at":[2023,51,18,30,0,0,0,0,0],"updated_at":[2023,51,18,30,0,0,0,0,0],"latest_version":1,"color":7943647,"visibility":"featured","source_url":"https://code.thetadev.de/ThetaDev/rustypipe","source_icon":"gitea","vid_count":1,"has_icon":false}}
{"type":"website","key":"spa","value":{"name":"SvelteKit SPA","created_at":[2023,62,22,0,0,0,0,0,0],"latest_version":1,"color":16727552,"visibility":"hidden","source_url":null,"source_icon":null,"vid_count":1,"has_icon":false,"updated_at":[2023,62,22,0,0,0,0,0,0]}} {"type":"website","key":"spa","value":{"name":"SvelteKit SPA","created_at":[2023,62,22,0,0,0,0,0,0],"updated_at":[2023,62,22,0,0,0,0,0,0],"latest_version":1,"color":16727552,"visibility":"hidden","source_url":null,"source_icon":null,"vid_count":1,"has_icon":false}}
{"type":"website","key":"spotify-gender-ex","value":{"name":"Spotify-Gender-Ex","created_at":[2023,49,16,30,0,0,0,0,0],"latest_version":1,"color":1947988,"visibility":"featured","source_url":"https://github.com/Theta-Dev/Spotify-Gender-Ex","source_icon":"github","vid_count":1,"has_icon":false,"updated_at":[2023,49,16,30,0,0,0,0,0]}} {"type":"website","key":"spotify-gender-ex","value":{"name":"Spotify-Gender-Ex","created_at":[2023,49,16,30,0,0,0,0,0],"updated_at":[2023,49,16,30,0,0,0,0,0],"latest_version":1,"color":1947988,"visibility":"featured","source_url":"https://github.com/Theta-Dev/Spotify-Gender-Ex","source_icon":"github","vid_count":1,"has_icon":false}}
{"type":"version","key":"rustypipe:1","value":{"created_at":[2023,51,18,30,0,0,0,0,0],"data":{},"fallback":null,"spa":false}} {"type":"version","key":"rustypipe:1","value":{"created_at":[2023,51,18,30,0,0,0,0,0],"data":{},"fallback":null,"spa":false}}
{"type":"version","key":"spa:1","value":{"created_at":[2023,62,22,0,0,0,0,0,0],"data":{},"fallback":"200.html","spa":true}} {"type":"version","key":"spa:1","value":{"created_at":[2023,62,22,0,0,0,0,0,0],"data":{},"fallback":"200.html","spa":true}}
{"type":"version","key":"spotify-gender-ex:1","value":{"created_at":[2023,49,16,30,0,0,0,0,0],"data":{},"fallback":null,"spa":false}} {"type":"version","key":"spotify-gender-ex:1","value":{"created_at":[2023,49,16,30,0,0,0,0,0],"data":{},"fallback":null,"spa":false}}

View file

@ -2,10 +2,10 @@
source: tests/tests.rs source: tests/tests.rs
expression: data expression: data
--- ---
{"type":"website","key":"-","value":{"name":"ThetaDev","created_at":[2023,49,16,30,0,0,0,0,0],"latest_version":2,"color":2068974,"visibility":"featured","source_url":null,"source_icon":null,"vid_count":2,"has_icon":false,"updated_at":[2023,49,16,30,0,0,0,0,0]}} {"type":"website","key":"-","value":{"name":"ThetaDev","created_at":[2023,49,16,30,0,0,0,0,0],"updated_at":[2023,49,16,30,0,0,0,0,0],"latest_version":2,"color":2068974,"visibility":"featured","source_url":null,"source_icon":null,"vid_count":2,"has_icon":false}}
{"type":"website","key":"rustypipe","value":{"name":"RustyPipe","created_at":[2023,51,18,30,0,0,0,0,0],"latest_version":1,"color":7943647,"visibility":"featured","source_url":"https://code.thetadev.de/ThetaDev/rustypipe","source_icon":"gitea","vid_count":1,"has_icon":false,"updated_at":[2023,51,18,30,0,0,0,0,0]}} {"type":"website","key":"rustypipe","value":{"name":"RustyPipe","created_at":[2023,51,18,30,0,0,0,0,0],"updated_at":[2023,51,18,30,0,0,0,0,0],"latest_version":1,"color":7943647,"visibility":"featured","source_url":"https://code.thetadev.de/ThetaDev/rustypipe","source_icon":"gitea","vid_count":1,"has_icon":false}}
{"type":"website","key":"spa","value":{"name":"SvelteKit SPA","created_at":[2023,62,22,0,0,0,0,0,0],"latest_version":1,"color":16727552,"visibility":"hidden","source_url":null,"source_icon":null,"vid_count":1,"has_icon":false,"updated_at":[2023,62,22,0,0,0,0,0,0]}} {"type":"website","key":"spa","value":{"name":"SvelteKit SPA","created_at":[2023,62,22,0,0,0,0,0,0],"updated_at":[2023,62,22,0,0,0,0,0,0],"latest_version":1,"color":16727552,"visibility":"hidden","source_url":null,"source_icon":null,"vid_count":1,"has_icon":false}}
{"type":"website","key":"spotify-gender-ex","value":{"name":"Spotify-Gender-Ex","created_at":[2023,49,16,30,0,0,0,0,0],"latest_version":1,"color":1947988,"visibility":"featured","source_url":"https://github.com/Theta-Dev/Spotify-Gender-Ex","source_icon":"github","vid_count":1,"has_icon":false,"updated_at":[2023,49,16,30,0,0,0,0,0]}} {"type":"website","key":"spotify-gender-ex","value":{"name":"Spotify-Gender-Ex","created_at":[2023,49,16,30,0,0,0,0,0],"updated_at":[2023,49,16,30,0,0,0,0,0],"latest_version":1,"color":1947988,"visibility":"featured","source_url":"https://github.com/Theta-Dev/Spotify-Gender-Ex","source_icon":"github","vid_count":1,"has_icon":false}}
{"type":"version","key":"-:1","value":{"created_at":[2023,49,16,30,0,0,0,0,0],"data":{"Deployed by":"https://github.com/Theta-Dev/Talon/actions/runs/1352014628","Version":"v0.1.0"},"fallback":null,"spa":false}} {"type":"version","key":"-:1","value":{"created_at":[2023,49,16,30,0,0,0,0,0],"data":{"Deployed by":"https://github.com/Theta-Dev/Talon/actions/runs/1352014628","Version":"v0.1.0"},"fallback":null,"spa":false}}
{"type":"version","key":"-:2","value":{"created_at":[2023,49,16,52,0,0,0,0,0],"data":{"Deployed by":"https://github.com/Theta-Dev/Talon/actions/runs/1354755231","Version":"v0.1.1"},"fallback":null,"spa":false}} {"type":"version","key":"-:2","value":{"created_at":[2023,49,16,52,0,0,0,0,0],"data":{"Deployed by":"https://github.com/Theta-Dev/Talon/actions/runs/1354755231","Version":"v0.1.1"},"fallback":null,"spa":false}}
{"type":"version","key":"rustypipe:1","value":{"created_at":[2023,51,18,30,0,0,0,0,0],"data":{},"fallback":null,"spa":false}} {"type":"version","key":"rustypipe:1","value":{"created_at":[2023,51,18,30,0,0,0,0,0],"data":{},"fallback":null,"spa":false}}

View file

@ -6,6 +6,7 @@ expression: "vec![ws1, ws2, ws3]"
Website( Website(
name: "ThetaDev", name: "ThetaDev",
created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0), created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
updated_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
latest_version: Some(2), latest_version: Some(2),
color: Some(2068974), color: Some(2068974),
visibility: featured, visibility: featured,
@ -13,11 +14,11 @@ expression: "vec![ws1, ws2, ws3]"
source_icon: None, source_icon: None,
vid_count: 2, vid_count: 2,
has_icon: false, has_icon: false,
updated_at: Some((2023, 49, 16, 30, 0, 0, 0, 0, 0)),
), ),
Website( Website(
name: "Spotify-Gender-Ex", name: "Spotify-Gender-Ex",
created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0), created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
updated_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
latest_version: Some(1), latest_version: Some(1),
color: Some(1947988), color: Some(1947988),
visibility: featured, visibility: featured,
@ -25,11 +26,11 @@ expression: "vec![ws1, ws2, ws3]"
source_icon: Some(github), source_icon: Some(github),
vid_count: 1, vid_count: 1,
has_icon: false, has_icon: false,
updated_at: Some((2023, 49, 16, 30, 0, 0, 0, 0, 0)),
), ),
Website( Website(
name: "RustyPipe", name: "RustyPipe",
created_at: (2023, 51, 18, 30, 0, 0, 0, 0, 0), created_at: (2023, 51, 18, 30, 0, 0, 0, 0, 0),
updated_at: (2023, 51, 18, 30, 0, 0, 0, 0, 0),
latest_version: Some(1), latest_version: Some(1),
color: Some(7943647), color: Some(7943647),
visibility: featured, visibility: featured,
@ -37,6 +38,5 @@ expression: "vec![ws1, ws2, ws3]"
source_icon: Some(gitea), source_icon: Some(gitea),
vid_count: 1, vid_count: 1,
has_icon: false, has_icon: false,
updated_at: Some((2023, 51, 18, 30, 0, 0, 0, 0, 0)),
), ),
] ]

View file

@ -6,6 +6,7 @@ expression: websites
("-", Website( ("-", Website(
name: "ThetaDev", name: "ThetaDev",
created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0), created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
updated_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
latest_version: Some(2), latest_version: Some(2),
color: Some(2068974), color: Some(2068974),
visibility: featured, visibility: featured,
@ -13,11 +14,11 @@ expression: websites
source_icon: None, source_icon: None,
vid_count: 2, vid_count: 2,
has_icon: false, has_icon: false,
updated_at: Some((2023, 49, 16, 30, 0, 0, 0, 0, 0)),
)), )),
("rustypipe", Website( ("rustypipe", Website(
name: "RustyPipe", name: "RustyPipe",
created_at: (2023, 51, 18, 30, 0, 0, 0, 0, 0), created_at: (2023, 51, 18, 30, 0, 0, 0, 0, 0),
updated_at: (2023, 51, 18, 30, 0, 0, 0, 0, 0),
latest_version: Some(1), latest_version: Some(1),
color: Some(7943647), color: Some(7943647),
visibility: featured, visibility: featured,
@ -25,11 +26,11 @@ expression: websites
source_icon: Some(gitea), source_icon: Some(gitea),
vid_count: 1, vid_count: 1,
has_icon: false, has_icon: false,
updated_at: Some((2023, 51, 18, 30, 0, 0, 0, 0, 0)),
)), )),
("spa", Website( ("spa", Website(
name: "SvelteKit SPA", name: "SvelteKit SPA",
created_at: (2023, 62, 22, 0, 0, 0, 0, 0, 0), created_at: (2023, 62, 22, 0, 0, 0, 0, 0, 0),
updated_at: (2023, 62, 22, 0, 0, 0, 0, 0, 0),
latest_version: Some(1), latest_version: Some(1),
color: Some(16727552), color: Some(16727552),
visibility: hidden, visibility: hidden,
@ -37,11 +38,11 @@ expression: websites
source_icon: None, source_icon: None,
vid_count: 1, vid_count: 1,
has_icon: false, has_icon: false,
updated_at: Some((2023, 62, 22, 0, 0, 0, 0, 0, 0)),
)), )),
("spotify-gender-ex", Website( ("spotify-gender-ex", Website(
name: "Spotify-Gender-Ex", name: "Spotify-Gender-Ex",
created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0), created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
updated_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
latest_version: Some(1), latest_version: Some(1),
color: Some(1947988), color: Some(1947988),
visibility: featured, visibility: featured,
@ -49,6 +50,5 @@ expression: websites
source_icon: Some(github), source_icon: Some(github),
vid_count: 1, vid_count: 1,
has_icon: false, has_icon: false,
updated_at: Some((2023, 49, 16, 30, 0, 0, 0, 0, 0)),
)), )),
] ]

View file

@ -5,6 +5,7 @@ expression: website
Website( Website(
name: "ThetaDev2", name: "ThetaDev2",
created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0), created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
updated_at: "[date]",
latest_version: Some(2), latest_version: Some(2),
color: Some(1000), color: Some(1000),
visibility: hidden, visibility: hidden,
@ -12,5 +13,4 @@ Website(
source_icon: Some(link), source_icon: Some(link),
vid_count: 2, vid_count: 2,
has_icon: false, has_icon: false,
updated_at: "[date]",
) )

View file

@ -862,6 +862,7 @@ mod api {
Website( Website(
name: "Test", name: "Test",
created_at: "[date]", created_at: "[date]",
updated_at: "[date]",
latest_version: None, latest_version: None,
color: Some(1000), color: Some(1000),
visibility: searchable, visibility: searchable,
@ -869,7 +870,6 @@ mod api {
source_icon: Some(git), source_icon: Some(git),
vid_count: 0, vid_count: 0,
has_icon: false, has_icon: false,
updated_at: "[date]",
) )
"###); "###);
} }
@ -918,6 +918,7 @@ mod api {
Website( Website(
name: "Test", name: "Test",
created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0), created_at: (2023, 49, 16, 30, 0, 0, 0, 0, 0),
updated_at: "[date]",
latest_version: Some(2), latest_version: Some(2),
color: Some(1000), color: Some(1000),
visibility: searchable, visibility: searchable,
@ -925,7 +926,6 @@ mod api {
source_icon: Some(git), source_icon: Some(git),
vid_count: 2, vid_count: 2,
has_icon: false, has_icon: false,
updated_at: "[date]",
) )
"###); "###);
} }