File size: 4,562 Bytes
57a889c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { Body, Controller, Delete, Get, Headers, HttpCode, Param, Post, Put, Res, UseGuards } from '@nestjs/common';
import type { Response } from 'express';
import type { User } from '../../types';
import type { Selection } from '../../services/memories/helpersService';
import { MemoriesService } from './memories.service';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { CurrentUser } from '../auth/current-user.decorator';

/**
 * /api/integrations/memories/unified — provider-agnostic trip photo + album-link
 * management.
 *
 * Byte-identical to the legacy Express router (server/src/routes/memories/unified.ts):
 * bare `authenticate` (JwtAuthGuard), success bodies on 200, and the per-result
 * error envelope `{ error }` at `result.error.status` reused from the unified
 * service. Lenient hand-rolled body coercion is preserved — no Zod here.
 */
@Controller('api/integrations/memories/unified')
@UseGuards(JwtAuthGuard)
export class UnifiedMemoriesController {
  constructor(private readonly memories: MemoriesService) {}

  @Get('trips/:tripId/photos')
  listPhotos(@CurrentUser() user: User, @Param('tripId') tripId: string, @Res() res: Response): void {
    const result = this.memories.listTripPhotos(tripId, user.id);
    if ('error' in result) {
      res.status(result.error.status).json({ error: result.error.message });
      return;
    }
    res.json({ photos: result.data });
  }

  @Post('trips/:tripId/photos')
  @HttpCode(200)
  async addPhotos(
    @CurrentUser() user: User,
    @Param('tripId') tripId: string,
    @Body() body: Record<string, unknown>,
    @Headers('x-socket-id') sid: string,
    @Res() res: Response,
  ): Promise<void> {
    const selections: Selection[] = Array.isArray(body?.selections) ? (body.selections as Selection[]) : [];
    const shared = body?.shared === undefined ? true : !!body?.shared;
    const result = await this.memories.addTripPhotos(tripId, user.id, shared, selections, sid);
    if ('error' in result) {
      res.status(result.error.status).json({ error: result.error.message });
      return;
    }
    res.json({ success: true, added: result.data.added });
  }

  @Put('trips/:tripId/photos/sharing')
  async setSharing(
    @CurrentUser() user: User,
    @Param('tripId') tripId: string,
    @Body() body: Record<string, unknown>,
    @Res() res: Response,
  ): Promise<void> {
    const result = await this.memories.setTripPhotoSharing(tripId, user.id, Number(body?.photo_id), body?.shared as boolean);
    if ('error' in result) {
      res.status(result.error.status).json({ error: result.error.message });
      return;
    }
    res.json({ success: true });
  }

  @Delete('trips/:tripId/photos')
  async removePhoto(
    @CurrentUser() user: User,
    @Param('tripId') tripId: string,
    @Body() body: Record<string, unknown>,
    @Res() res: Response,
  ): Promise<void> {
    const result = this.memories.removeTripPhoto(tripId, user.id, Number(body?.photo_id));
    if ('error' in result) {
      res.status(result.error.status).json({ error: result.error.message });
      return;
    }
    res.json({ success: true });
  }

  @Get('trips/:tripId/album-links')
  listAlbumLinks(@CurrentUser() user: User, @Param('tripId') tripId: string, @Res() res: Response): void {
    const result = this.memories.listTripAlbumLinks(tripId, user.id);
    if ('error' in result) {
      res.status(result.error.status).json({ error: result.error.message });
      return;
    }
    res.json({ links: result.data });
  }

  @Post('trips/:tripId/album-links')
  @HttpCode(200)
  createAlbumLink(
    @CurrentUser() user: User,
    @Param('tripId') tripId: string,
    @Body() body: Record<string, unknown>,
    @Res() res: Response,
  ): void {
    const passphrase = body?.passphrase ? String(body.passphrase) : undefined;
    const result = this.memories.createTripAlbumLink(tripId, user.id, body?.provider, body?.album_id, body?.album_name, passphrase);
    if ('error' in result) {
      res.status(result.error.status).json({ error: result.error.message });
      return;
    }
    res.json({ success: true });
  }

  @Delete('trips/:tripId/album-links/:linkId')
  removeAlbumLink(
    @CurrentUser() user: User,
    @Param('tripId') tripId: string,
    @Param('linkId') linkId: string,
    @Res() res: Response,
  ): void {
    const result = this.memories.removeAlbumLink(tripId, linkId, user.id);
    if ('error' in result) {
      res.status(result.error.status).json({ error: result.error.message });
      return;
    }
    res.json({ success: true });
  }
}