index.ts 6.78 KB
Newer Older
duanjinfei's avatar
duanjinfei committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Follow this setup guide to integrate the Deno language server with your editor:
// https://deno.land/manual/getting_started/setup_your_environment
// This enables autocomplete, go to definition, etc.

// Setup type definitions for built-in Supabase Runtime APIs
import "jsr:@supabase/functions-js/edge-runtime.d.ts"
import { createClient } from 'jsr:@supabase/supabase-js@2'

// 分页查询函数
async function fetchAllData(supabase, table: string, pageSize: number = 1000) {
  let allData: any[] = [];
  let offset = 0;

  while (true) {
    const { data, error } = await supabase
      .from(table)
17
      .select('id,name,icon,points,link,appPlatforms,caption,category_id,is_forward,recommend,category(is_show)') // 可以根据需要调整字段
duanjinfei's avatar
duanjinfei committed
18
      .gt('is_show', 0)
duanjinfei's avatar
duanjinfei committed
19
      .gt('recommend', 0)
duanjinfei's avatar
duanjinfei committed
20
      // .eq('is_show', 1)
21
      .eq("category.is_show", true)
duanjinfei's avatar
duanjinfei committed
22
      .order('recommend', { ascending: false })
23
      .order('updated_at', { ascending: false }) // 按照创建时间排序
duanjinfei's avatar
duanjinfei committed
24 25 26 27 28 29
      .range(offset, offset + pageSize - 1); // 分页范围

    if (error) {
      console.error(`Error fetching data from ${table}:`, error);
      throw error;
    }
30 31 32 33 34 35 36
    let newdata = data.filter((data) => {
      if (data.category && data.category.is_show) {
        return data.category.is_show == true;
      }
    });
    if (newdata && newdata.length > 0) {
      allData = allData.concat(newdata); // 合并当前页数据
duanjinfei's avatar
duanjinfei committed
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
      offset += pageSize; // 移动到下一页
    } else {
      break; // 如果没有更多数据,则退出循环
    }
  }

  return allData;
}

const getTimestampForMidnight3AM = () => {
  const timestamp = Math.floor(Date.now() / 3600000) * 3600; // 计算整点的时间戳
  return timestamp

};

async function cacheTaskCount(supabase, directory, bucketName) {
  const pageFileName = `${directory}/task_count.json`;

  // // 获取所有任务组 ID
  // const { data: taskGroupArr, error: groupError } = await supabase
  //   .from('task')
  //   .select('task_group_id');

  // if (groupError) {
  //   console.error("Error fetching task groups:", groupError);
  //   return;
  // }

  // // 提取所有任务组 ID
  // const groupIds = taskGroupArr.map(group => group.task_group_id);

  // // 使用 IN 操作符来一次性查询所有匹配的任务组任务数量
  // const { data, error } = await supabase
  //   .from('taskcenter.task')
  //   .select('group_id, id', { count: 'exact' })
  //   .in('group_id', groupIds);

  // if (error) {
  //   console.error("Error fetching task counts:", error);
  //   return;
  // }
  const pageJson = JSON.stringify({
    total_count: 4,
  });

  const { error: pageUploadError } = await supabase.storage
    .from(bucketName)
    .upload(pageFileName, new Blob([pageJson]), {
      contentType: 'application/json',
      upsert: true,
    });

  if (pageUploadError) {
    console.error(`Error uploading cacheTaskCount JSON:`, pageUploadError);
  } else {
    console.log(`Uploading cacheTaskCount JSON scuccessful`);
  }
}

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
async function cacheAnnouncementData(supabase, directory, bucketName) {
  const pageFileName = `${directory}/announcement_data.json`;

  let { data: announcementData, error: announcementError } = await supabase
    .from("announcement")
    .select("comment")
    .is('deleted_at', null)
    .order("update_at", { ascending: false })
    .limit(0, 1);

  const pageJson = JSON.stringify(announcementData);

  const { error: pageUploadError } = await supabase.storage
    .from(bucketName)
    .upload(pageFileName, new Blob([pageJson]), {
      contentType: 'application/json',
      upsert: true,
    });

  if (pageUploadError) {
    console.error(`Error uploading announcement_data JSON:`, pageUploadError);
  } else {
    console.log(`Uploading announcement_data JSON scuccessful`);
  }
}

duanjinfei's avatar
duanjinfei committed
122 123
async function cacheRecommendApp(supabase, allApps, directory, bucketName) {
  const recommendPageSize = 3;
duanjinfei's avatar
duanjinfei committed
124 125 126
  // const recommendApps = allApps.filter(app => app.recommend > 0)
  //   .sort((a, b) => b.recommend - a.recommend);  // 按 recommend 字段降序排序
  const recommendTotalCount = allApps.length;
duanjinfei's avatar
duanjinfei committed
127 128
  const recommendPaginatedApps = [];
  for (let i = 0; i < recommendTotalCount; i += recommendPageSize) {
duanjinfei's avatar
duanjinfei committed
129
    recommendPaginatedApps.push(allApps.slice(i, i + recommendPageSize));
duanjinfei's avatar
duanjinfei committed
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 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
  }

  console.log("total page:", recommendPaginatedApps.length);

  // 遍历分页后的数据并上传
  for (let pageNum = 1; pageNum <= recommendPaginatedApps.length; pageNum++) {
    const pageApps = recommendPaginatedApps[pageNum - 1];

    const pageJson = JSON.stringify({
      total_count: recommendTotalCount,
      apps: pageApps,
    });

    const pageFileName = `${directory}/app_recommend_${pageNum}.json`;

    const { error: pageUploadError } = await supabase.storage
      .from(bucketName)
      .upload(pageFileName, new Blob([pageJson]), {
        contentType: 'application/json',
        upsert: true,
      });

    if (pageUploadError) {
      console.error(`Error uploading page ${pageNum} JSON:`, pageUploadError);
    } else {
      console.log(`Uploading page app_recommend_${pageNum}.json JSON successful`);
    }
  }
}

// Mark the longRunningTask's returned promise as a background task.
// note: we are not using await because we don't want it to block.

// Use beforeunload event handler to be notified when function is about to shutdown
addEventListener('beforeunload', (ev) => {
  console.log('Function will be shutdown due to', ev.detail?.reason)

  // save state or log the current progress
})

Deno.serve(async (req) => {
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }
  try {
    // const { name } = await req.json()
    const supabase = createClient(
      Deno.env.get('SUPABASE_URL') ?? '',
      Deno.env.get('SUPABASE_ANON_KEY') ?? '',
      { global: { headers: { Authorization: req.headers.get('Authorization')! } } }
    )
    // 获取所有 app 数据
    const allApps = await fetchAllData(supabase, 'app');
    // 获取当前时间的整点时间戳
    const timestamp = getTimestampForMidnight3AM();

    // 上传所有 app 数据到 storage
    const directory = `app-category/${timestamp}`;
    const bucketName = 'cache'; // 替换为存储桶名称

    EdgeRuntime.waitUntil(cacheTaskCount(supabase, directory, bucketName));

192
    EdgeRuntime.waitUntil(cacheAnnouncementData(supabase, directory, bucketName));
duanjinfei's avatar
duanjinfei committed
193

194
    EdgeRuntime.waitUntil(cacheRecommendApp(supabase, allApps, directory, bucketName));
duanjinfei's avatar
duanjinfei committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212

    return new Response(
      JSON.stringify({
        message: 'All data uploaded successfully',
      }),
      {
        headers: { 'Content-Type': 'application/json' },
        status: 200
      }
    );
  } catch (err) {
    console.error('Unexpected error:', err);
    return new Response(JSON.stringify({ error: 'Internal server error' }), {
      headers: { 'Content-Type': 'application/json' },
      status: 500,
    });
  }
})