add uploading

This commit is contained in:
2024-07-25 21:27:07 -05:00
parent c6ef195be7
commit a3ae877972
7 changed files with 102 additions and 9 deletions

View File

@ -17,7 +17,7 @@ tauri-build = { version = "1.5.3", features = [] }
[dependencies] [dependencies]
serde_json = "1.0" serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.7.0", features = [ "updater", "os-all", "notification-all", "dialog-confirm", "clipboard-all", "dialog-message", "dialog-ask"] } tauri = { version = "1.7.0", features = [ "app-all", "updater", "os-all", "notification-all", "dialog-confirm", "clipboard-all", "dialog-message", "dialog-ask"] }
dirs = "5.0.1" dirs = "5.0.1"
reqwest = { version = "0.11.18", features = ["json"] } reqwest = { version = "0.11.18", features = ["json"] }
lazy_static = "1.5.0" lazy_static = "1.5.0"

View File

@ -162,6 +162,35 @@ impl Fansly {
Ok(subscriptions.response.subscriptions) Ok(subscriptions.response.subscriptions)
} }
async fn upload_sync_data(&self, data: SyncDataResponse) -> Result<String, reqwest::Error> {
let url = "https://paste.hep.gg/documents";
// Set our content type to application/json
let mut headers = reqwest::header::HeaderMap::new();
headers.insert(
reqwest::header::CONTENT_TYPE,
"application/json".parse().unwrap(),
);
let response = self
.client
.post(url)
.headers(headers)
.json(&data)
.send()
.await?;
if !response.status().is_success() {
eprintln!("[sync::process::upload_sync_data] Failed to upload sync data.");
return Err(response.error_for_status().unwrap_err());
}
let json: serde_json::Value = response.json().await?;
let key = json["key"].as_str().unwrap();
Ok(format!("https://paste.hep.gg/{}", key))
}
pub async fn sync(&self) -> Result<SyncDataResponse, String> { pub async fn sync(&self) -> Result<SyncDataResponse, String> {
// Fetch profile // Fetch profile
println!("[sync::process] Fetching profile..."); println!("[sync::process] Fetching profile...");
@ -244,11 +273,23 @@ impl Fansly {
); );
println!("[sync::process] Sync complete."); println!("[sync::process] Sync complete.");
println!("[sync::process] Uploading sync data to paste.hep.gg for processing...");
// Upload sync data to paste.hep.gg
let paste_url = self
.upload_sync_data(SyncDataResponse {
followers: followers.clone(),
subscribers: subscribers.clone(),
sync_data_url: "".to_string(),
})
.await
.map_err(|e| e.to_string())?;
// Return JSON of what we fetched // Return JSON of what we fetched
Ok(SyncDataResponse { Ok(SyncDataResponse {
followers, followers,
subscribers, subscribers,
sync_data_url: paste_url,
}) })
} }
} }

View File

@ -5,6 +5,7 @@ use serde_json::Value;
pub struct SyncDataResponse { pub struct SyncDataResponse {
pub followers: Vec<FanslyFollowersResponse>, pub followers: Vec<FanslyFollowersResponse>,
pub subscribers: Vec<Subscription>, pub subscribers: Vec<Subscription>,
pub sync_data_url: String,
} }
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]

View File

@ -7,8 +7,8 @@
"distDir": "../build" "distDir": "../build"
}, },
"package": { "package": {
"productName": "fanslysync-desktop", "productName": "FanslySync",
"version": "0.1.0" "version": "0.1.1"
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {
@ -30,6 +30,9 @@
}, },
"os": { "os": {
"all": true "all": true
},
"app": {
"all": true
} }
}, },
"bundle": { "bundle": {

View File

@ -10,6 +10,7 @@ export type Config = {
export interface SyncData { export interface SyncData {
followers: Follower[]; followers: Follower[];
subscribers: Subscriber[]; subscribers: Subscriber[];
sync_data_url: string;
} }
interface Subscriber { interface Subscriber {

View File

@ -52,8 +52,6 @@
} }
status = 'Initialization complete!'; status = 'Initialization complete!';
// Wait 1000ms before redirecting to /setup or /home
await new Promise((resolve) => setTimeout(resolve, 1000));
if (config.is_first_run) { if (config.is_first_run) {
// Navigate to /setup // Navigate to /setup

View File

@ -7,14 +7,23 @@
import { slide } from 'svelte/transition'; import { slide } from 'svelte/transition';
import { sendNotification } from '@tauri-apps/api/notification'; import { sendNotification } from '@tauri-apps/api/notification';
import { platform } from '@tauri-apps/api/os'; import { platform } from '@tauri-apps/api/os';
import { checkUpdate, installUpdate, type UpdateManifest } from '@tauri-apps/api/updater';
import { getVersion, getTauriVersion } from '@tauri-apps/api/app';
import { ask } from '@tauri-apps/api/dialog';
let loadingSync = true; let loadingSync = true;
let syncing = false; let upToDate: boolean | null = null;
let updateMeta: UpdateManifest | null = null;
let versionData = {
appVersion: 'Loading...',
tauriVersion: 'Loading...'
};
let syncState = { let syncState = {
show: false, show: false,
syncing: false, syncing: false,
error: false, error: false,
success: false, success: false,
url: '',
message: '' message: ''
}; };
@ -36,6 +45,13 @@
config = configData; config = configData;
loadingSync = false; loadingSync = false;
const updateStatus = await checkUpdate();
upToDate = updateStatus.shouldUpdate;
updateMeta = updateStatus.manifest || null;
versionData.appVersion = await getVersion();
versionData.tauriVersion = await getTauriVersion();
}); });
async function syncNow() { async function syncNow() {
@ -54,6 +70,8 @@
return; return;
} }
syncState.url = syncData.sync_data_url;
// Return the last sync as unix timestamp // Return the last sync as unix timestamp
config!.last_sync = Date.now(); config!.last_sync = Date.now();
config!.last_sync_data = syncData!; config!.last_sync_data = syncData!;
@ -88,6 +106,24 @@
sound: soundName sound: soundName
}); });
} }
async function doUpdate() {
const confirm = await ask(
`An update is available for FanslySync. Would you like to update now?\n\nCurrent version: ${versionData.appVersion}\nNew (remote) version: ${updateMeta?.version ?? 'Unknown'}`,
{
title: 'Update Available',
okLabel: 'Yes',
cancelLabel: 'No',
type: 'info'
}
);
if (confirm) {
await installUpdate();
} else {
console.log('User declined update');
}
}
</script> </script>
<div class="container bg-zinc-800 w-screen h-screen"> <div class="container bg-zinc-800 w-screen h-screen">
@ -96,7 +132,20 @@
<div class="flex items-center"> <div class="flex items-center">
<img src="/fanslySync.png" alt="FanslySynct" class="w-8 h-8" /> <img src="/fanslySync.png" alt="FanslySynct" class="w-8 h-8" />
<h1 class="text-2xl font-bold text-gray-200 ml-2">FanslySync</h1> <h1 class="text-2xl font-bold text-gray-200 ml-2">FanslySync</h1>
<span class="text-gray-400 ml-2">v0.1.0</span> <span class="text-gray-400 ml-2"
>v{versionData.appVersion} (runtime: {versionData.tauriVersion})</span
>
{#if upToDate === false}
<button
type="button"
class="text-red-500 ml-2 hover:text-red-600 duration-200"
on:click={doUpdate}
>
Update available!
</button>
{:else if upToDate === true}
<span class="text-green-500 ml-2">Up to date!</span>
{/if}
</div> </div>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -250,7 +299,7 @@
<div class="flex flex-col"> <div class="flex flex-col">
<h1 class="text-lg font-bold">Sync Successful!</h1> <h1 class="text-lg font-bold">Sync Successful!</h1>
<p class="text-sm"> <p class="text-sm">
Data synced successfully. Please run the import with the following link {syncState.message} Data synced successfully. Please run the import with the following link {syncState.url}
to import the data. to import the data.
</p> </p>
</div> </div>
@ -260,7 +309,7 @@
<button <button
class="bg-white text-blue-600 px-2 py-1 rounded-lg" class="bg-white text-blue-600 px-2 py-1 rounded-lg"
on:click={() => { on:click={() => {
clipboard.writeText(syncState.message); clipboard.writeText(syncState.url);
}} }}
> >
Copy Copy