File size: 4,999 Bytes
4befee3
 
 
 
 
 
28268ed
4befee3
 
28268ed
4befee3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28268ed
 
6042f7c
4befee3
 
28268ed
4befee3
28268ed
 
 
 
 
 
 
6042f7c
 
28268ed
4befee3
 
 
28268ed
7dd4a60
4befee3
 
28268ed
 
 
 
 
 
 
4befee3
28268ed
4befee3
 
28268ed
4befee3
 
 
28268ed
 
4befee3
 
 
28268ed
4befee3
 
 
 
 
28268ed
4befee3
 
28268ed
4befee3
 
 
28268ed
4befee3
 
 
 
1a8b559
28268ed
 
4befee3
 
 
28268ed
 
4befee3
 
28268ed
 
4befee3
 
 
 
 
 
 
 
 
 
28268ed
4befee3
 
 
 
 
 
 
 
 
 
28268ed
4befee3
 
 
 
 
 
 
 
28268ed
 
4befee3
 
 
28268ed
 
4befee3
 
28268ed
 
4befee3
 
 
28268ed
4befee3
 
 
28268ed
4befee3
 
 
 
28268ed
4befee3
28268ed
7dd4a60
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
const express = require('express');
const cors = require('cors');
const fetch = require('node-fetch');
const bodyParser = require('body-parser');

const app = express();
const PORT = 7860; // Default port for Hugging Face Spaces

// --- CONFIGURATION ---
// These tokens must be set in your Space Settings -> Variables and secrets
const STORAGE_POOLS = [
  { 
    repo: "abhy60098/MY-STORAGE", 
    token: process.env.HF_TOKEN_1 
  },
  { 
    repo: "sushmasinharnc/MY-STORAGE", 
    token: process.env.HF_TOKEN_2 
  },
  { 
    repo: "shuarya2011/MY-STORAGE", 
    token: process.env.HF_TOKEN_3 
  }
];

const DB_FILE = "db.json";

// --- MIDDLEWARE ---
app.use(cors()); // Allows any website to connect
app.use(bodyParser.json({ limit: '50mb' })); // Allows large image uploads

// --- ROUTES ---

// 1. Health Check / Home Page
app.get('/', (req, res) => {
  res.send(`
    <div style="font-family: sans-serif; text-align: center; margin-top: 50px;">
      <h1>🚀 Distributed Storage API is Online</h1>
      <p>Status: <b>Connected to ${STORAGE_POOLS.length} Storage Pools</b></p>
      <p>Use <code>/posts</code> (GET) to fetch data and <code>/posts</code> (POST) to upload.</p>
    </div>
  `);
});

// 2. GET: Fetch data from all 3 datasets and merge them
app.get('/posts', async (req, res) => {
  try {
    const allResults = await Promise.all(STORAGE_POOLS.map(async (pool) => {
      // We check if the token exists before calling
      if (!pool.token) return [];

      const url = `https://huggingface.co/api/datasets/${pool.repo}/raw/main/${DB_FILE}`;
      const response = await fetch(url, { 
        headers: { Authorization: `Bearer ${pool.token}` } 
      });

      if (response.ok) {
        const data = await response.json();
        return data.posts || [];
      }
      return []; // Return empty if file doesn't exist yet
    }));

    // Flatten the array of arrays and sort by ID (timestamp) descending
    const mergedPosts = allResults.flat().sort((a, b) => b.id - a.id);
    res.json(mergedPosts);
  } catch (err) {
    console.error("GET Error:", err);
    res.status(500).json({ error: "Failed to fetch posts from pools." });
  }
});

// 3. POST: Upload image and update database in a random pool
app.post('/posts', async (req, res) => {
  try {
    const { username, caption, imageBase64, fileName } = req.body;

    if (!imageBase64 || !username) {
      return res.status(400).json({ error: "Missing required fields (username or image)." });
    }

    // Pick a random pool to distribute storage usage
    const pool = STORAGE_POOLS[Math.floor(Math.random() * STORAGE_POOLS.length)];
    
    if (!pool.token) {
      return res.status(500).json({ error: "Storage pool token not configured in Secrets." });
    }

    const timestamp = Date.now();
    const imagePath = `uploads/${timestamp}-${fileName}`;

    // A. Upload the Image file
    const uploadImageUrl = `https://huggingface.co/api/datasets/${pool.repo}/upload/main/${imagePath}`;
    const imageUploadRes = await fetch(uploadImageUrl, {
      method: 'POST',
      headers: { 
        Authorization: `Bearer ${pool.token}`, 
        'Content-Type': 'application/json' 
      },
      body: JSON.stringify({
        content: imageBase64, // Expecting raw base64 string
        message: `Upload image from ${username}`
      })
    });

    if (!imageUploadRes.ok) {
      const errorText = await imageUploadRes.text();
      throw new Error(`Image Upload Failed: ${errorText}`);
    }

    const finalImageUrl = `https://huggingface.co/datasets/${pool.repo}/resolve/main/${imagePath}`;

    // B. Fetch existing db.json from the SAME pool
    const dbUrl = `https://huggingface.co/api/datasets/${pool.repo}/raw/main/${DB_FILE}`;
    const dbRes = await fetch(dbUrl, { 
      headers: { Authorization: `Bearer ${pool.token}` } 
    });
    
    let db = { posts: [] };
    if (dbRes.ok) {
      db = await dbRes.json();
    }

    // C. Add new post to the beginning of the list
    db.posts.unshift({
      id: timestamp,
      username,
      caption,
      imageUrl: finalImageUrl,
      pool: pool.repo
    });

    // D. Upload the updated db.json back to Hugging Face
    const updateDbUrl = `https://huggingface.co/api/datasets/${pool.repo}/upload/main/${DB_FILE}`;
    const dbUploadRes = await fetch(updateDbUrl, {
      method: 'POST',
      headers: { 
        Authorization: `Bearer ${pool.token}`, 
        'Content-Type': 'application/json' 
      },
      body: JSON.stringify({
        content: Buffer.from(JSON.stringify(db, null, 2)).toString('base64'),
        message: "Update database JSON"
      })
    });

    if (!dbUploadRes.ok) throw new Error("Database update failed.");

    res.status(201).json({ success: true, imageUrl: finalImageUrl });
  } catch (err) {
    console.error("POST Error:", err);
    res.status(500).json({ error: err.message });
  }
});

// Start the server
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});