JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Update version checks

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨1ed7c39

⁨src/backend/discovery.rs⁩ - ⁨3456⁩ bytes
Raw
1 use std::{
2 collections::hash_map::DefaultHasher,
3 hash::{Hash, Hasher},
4 };
5
6 use anyhow::Error;
7 use base64::{engine::general_purpose::STANDARD, Engine as _};
8 use chrono::{DateTime, Utc};
9 use serde::{Deserialize, Serialize};
10 use sqlx::PgPool;
11
12 use crate::{
13 messages::discovery::{DiscoveryMessage, DiscoveryMessageKind},
14 model::{discovery::DiscoveryItem, repository::Repository},
15 };
16
17 use super::DiscoveryBackend;
18
19 pub struct GiteratedDiscoveryProtocol {
20 pub pool: PgPool,
21 }
22
23 #[derive(Debug, Hash, Serialize, Deserialize, Clone, sqlx::Type)]
24 #[sqlx(type_name = "discovery_type", rename_all = "lowercase")]
25 pub enum DiscoveryType {
26 Instance,
27 Repository,
28 }
29
30 #[async_trait::async_trait]
31 impl DiscoveryBackend for GiteratedDiscoveryProtocol {
32 async fn try_handle(&mut self, request: &DiscoveryMessage) -> Result<bool, Error> {
33 if request
34 .message
35 .validate(&request.message.instance)
36 .await
37 .is_err()
38 {
39 return Ok(false);
40 }
41
42 let inner = request.message.inner().await.clone();
43
44 match inner {
45 DiscoveryMessageKind::Discoveries(mut discoveries) => {
46 let discoveries = discoveries.discoveries.drain(..).map(|discovery| {
47 let hash = {
48 let mut hasher = DefaultHasher::new();
49 discovery.hash(&mut hasher);
50 STANDARD.encode(hasher.finish().to_be_bytes())
51 };
52
53 let (discovery_type, discovery) = match discovery {
54 DiscoveryItem::Instance {
55 instance,
56 signature,
57 } => (DiscoveryType::Instance, instance.to_string()),
58 DiscoveryItem::Repository {
59 repository,
60 signature,
61 } => (DiscoveryType::Repository, repository.to_string()),
62 };
63
64 DiscoveriesRow {
65 discovery_hash: hash,
66 discovery_time: Utc::now(),
67 discovery_type,
68 discovery,
69 }
70 });
71
72 for row in discoveries {
73 let result = sqlx::query!(
74 r#"INSERT INTO discoveries VALUES ($1, $2, $3, $4)"#,
75 row.discovery_hash,
76 row.discovery_time.to_string(),
77 row.discovery_type as _,
78 row.discovery
79 )
80 .execute(&self.pool)
81 .await;
82
83 match result {
84 Ok(_) => {},
85 Err(err) => {
86 error!("Error inserting discovery. {:?}", err);
87 }
88 }
89 }
90 Ok(true)
91 }
92 DiscoveryMessageKind::Offer(offer) => Ok(true),
93 DiscoveryMessageKind::Request(request) => Ok(true),
94 }
95 }
96
97 async fn search(&mut self, _search: &str) -> Result<Vec<Repository>, Error> {
98 todo!()
99 }
100 }
101
102 #[derive(Debug, sqlx::FromRow, sqlx::Type)]
103 pub struct DiscoveriesRow {
104 discovery_hash: String,
105 discovery_time: DateTime<Utc>,
106 discovery_type: DiscoveryType,
107 discovery: String,
108 }