mirror of
https://github.com/System-End/scraps.git
synced 2026-04-20 00:25:18 +00:00
whoops
This commit is contained in:
parent
149568f101
commit
aa16e2a844
3 changed files with 79 additions and 24 deletions
|
|
@ -113,14 +113,29 @@ function parseHackatimeProject(hackatimeProject: string | null): string | null {
|
|||
return hackatimeProject.substring(slashIndex + 1)
|
||||
}
|
||||
|
||||
function parseHackatimeProjects(hackatimeProject: string | null): string[] {
|
||||
function parseHackatimeProjectSlackId(hackatimeProject: string | null): string | null {
|
||||
if (!hackatimeProject) return null
|
||||
const slashIndex = hackatimeProject.indexOf('/')
|
||||
if (slashIndex === -1) return null
|
||||
return hackatimeProject.substring(0, slashIndex)
|
||||
}
|
||||
|
||||
interface ParsedHackatimeEntry {
|
||||
slackId: string | null
|
||||
projectName: string
|
||||
}
|
||||
|
||||
function parseHackatimeProjects(hackatimeProject: string | null): ParsedHackatimeEntry[] {
|
||||
if (!hackatimeProject) return []
|
||||
return hackatimeProject
|
||||
.split(',')
|
||||
.map(p => p.trim())
|
||||
.filter(p => p.length > 0)
|
||||
.map(p => parseHackatimeProject(p))
|
||||
.filter((p): p is string => p !== null)
|
||||
.map(p => ({
|
||||
slackId: parseHackatimeProjectSlackId(p),
|
||||
projectName: parseHackatimeProject(p)!
|
||||
}))
|
||||
.filter(p => p.projectName !== null)
|
||||
}
|
||||
|
||||
async function syncAllProjects(): Promise<void> {
|
||||
|
|
@ -179,14 +194,38 @@ async function syncAllProjects(): Promise<void> {
|
|||
|
||||
// Match each scraps project to its hackatime project(s)
|
||||
for (const project of userProjects) {
|
||||
const projectNames = parseHackatimeProjects(project.hackatimeProject)
|
||||
if (projectNames.length === 0) continue
|
||||
const entries = parseHackatimeProjects(project.hackatimeProject)
|
||||
if (entries.length === 0) continue
|
||||
|
||||
let totalSeconds = 0
|
||||
for (const name of projectNames) {
|
||||
const duration = adminProjectMap.get(name)
|
||||
if (duration !== undefined) {
|
||||
totalSeconds += duration
|
||||
|
||||
// Group entries by slackId to batch lookups for different users
|
||||
const entriesBySlackId = new Map<string, string[]>()
|
||||
for (const entry of entries) {
|
||||
const key = entry.slackId || identifier
|
||||
const existing = entriesBySlackId.get(key) || []
|
||||
existing.push(entry.projectName)
|
||||
entriesBySlackId.set(key, existing)
|
||||
}
|
||||
|
||||
for (const [entryIdentifier, projectNames] of entriesBySlackId) {
|
||||
let projectsData: { name: string; total_duration: number }[] | null
|
||||
|
||||
if (entryIdentifier === identifier) {
|
||||
// Same user, reuse already-fetched data
|
||||
projectsData = adminProjects
|
||||
} else {
|
||||
// Different user (slackId prefix), fetch their projects
|
||||
projectsData = await fetchUserProjects(entryIdentifier)
|
||||
}
|
||||
|
||||
if (projectsData) {
|
||||
for (const name of projectNames) {
|
||||
const found = projectsData.find(p => p.name === name)
|
||||
if (found) {
|
||||
totalSeconds += found.total_duration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -305,23 +344,37 @@ export async function syncSingleProject(projectId: number): Promise<{ hours: num
|
|||
if (!project) return { hours: 0, updated: false, error: 'Project not found' }
|
||||
if (!project.hackatimeProject) return { hours: project.hours ?? 0, updated: false, error: 'No Hackatime project linked' }
|
||||
|
||||
const projectNames = parseHackatimeProjects(project.hackatimeProject)
|
||||
if (projectNames.length === 0) return { hours: project.hours ?? 0, updated: false, error: 'Invalid Hackatime project format' }
|
||||
const entries = parseHackatimeProjects(project.hackatimeProject)
|
||||
if (entries.length === 0) return { hours: project.hours ?? 0, updated: false, error: 'Invalid Hackatime project format' }
|
||||
|
||||
const hackatimeUser = await getHackatimeUser(project.userEmail)
|
||||
if (hackatimeUser === null) return { hours: project.hours ?? 0, updated: false, error: 'Could not find Hackatime user' }
|
||||
|
||||
const identifier = hackatimeUser.slack_uid || hackatimeUser.username
|
||||
const adminProjects = await fetchUserProjects(identifier)
|
||||
if (adminProjects === null) return { hours: project.hours ?? 0, updated: false, error: 'Failed to fetch Hackatime projects' }
|
||||
|
||||
let totalSeconds = 0
|
||||
for (const name of projectNames) {
|
||||
const hackatimeProject = adminProjects.find(p => p.name === name)
|
||||
if (hackatimeProject) {
|
||||
totalSeconds += hackatimeProject.total_duration
|
||||
|
||||
// Group entries by slackId to batch lookups for different users
|
||||
const entriesBySlackId = new Map<string, string[]>()
|
||||
for (const entry of entries) {
|
||||
const key = entry.slackId || identifier
|
||||
const existing = entriesBySlackId.get(key) || []
|
||||
existing.push(entry.projectName)
|
||||
entriesBySlackId.set(key, existing)
|
||||
}
|
||||
|
||||
for (const [entryIdentifier, projectNames] of entriesBySlackId) {
|
||||
const projectsData = await fetchUserProjects(entryIdentifier)
|
||||
if (projectsData === null) continue
|
||||
|
||||
for (const name of projectNames) {
|
||||
const hackatimeProject = projectsData.find(p => p.name === name)
|
||||
if (hackatimeProject) {
|
||||
totalSeconds += hackatimeProject.total_duration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hours = Math.round(totalSeconds / 3600 * 10) / 10
|
||||
|
||||
if (hours !== project.hours) {
|
||||
|
|
|
|||
|
|
@ -18,9 +18,7 @@ const ALLOWED_IMAGE_DOMAIN = 'cdn.hackclub.com'
|
|||
|
||||
function parseHackatimeProject(hackatimeProject: string | null): string | null {
|
||||
if (!hackatimeProject) return null
|
||||
const slashIndex = hackatimeProject.indexOf('/')
|
||||
if (slashIndex === -1) return hackatimeProject
|
||||
return hackatimeProject.substring(slashIndex + 1)
|
||||
return hackatimeProject.trim()
|
||||
}
|
||||
|
||||
function parseHackatimeProjects(hackatimeProject: string | null): string | null {
|
||||
|
|
@ -29,8 +27,6 @@ function parseHackatimeProjects(hackatimeProject: string | null): string | null
|
|||
.split(',')
|
||||
.map(p => p.trim())
|
||||
.filter(p => p.length > 0)
|
||||
.map(p => parseHackatimeProject(p))
|
||||
.filter((p): p is string => p !== null)
|
||||
.join(',')
|
||||
|| null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,11 @@
|
|||
imagePreview = project?.image || null;
|
||||
hasSubmittedFeedbackBefore = responseData.hasSubmittedFeedback ?? false;
|
||||
if (project?.hackatimeProject) {
|
||||
selectedHackatimeNames = project.hackatimeProject.split(',').map((p: string) => p.trim()).filter((p: string) => p.length > 0);
|
||||
selectedHackatimeNames = project.hackatimeProject.split(',').map((p: string) => {
|
||||
const trimmed = p.trim();
|
||||
const slashIndex = trimmed.indexOf('/');
|
||||
return slashIndex !== -1 ? trimmed.substring(slashIndex + 1) : trimmed;
|
||||
}).filter((p: string) => p.length > 0);
|
||||
}
|
||||
selectedTier = project?.tier ?? 1;
|
||||
fetchHackatimeProjects();
|
||||
|
|
@ -215,7 +219,9 @@
|
|||
submitting = true;
|
||||
error = null;
|
||||
|
||||
const hackatimeValue = selectedHackatimeNames.length > 0 ? selectedHackatimeNames.join(',') : null;
|
||||
const hackatimeValue = selectedHackatimeNames.length > 0
|
||||
? selectedHackatimeNames.map(name => userSlackId ? `${userSlackId}/${name}` : name).join(',')
|
||||
: null;
|
||||
|
||||
try {
|
||||
// First update the project with any changes
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue