File size: 8,118 Bytes
6b825ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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
// @ts-check

import axios, { AxiosResponse, AxiosError } from 'axios';
import { Request, Response } from 'express';

console.log(`[Register Module] src/register.ts file is being evaluated. __dirname is: ${__dirname}`);

interface PastebinResponse {
  link: string;
}

interface RegisterClientPayload {
  user: string;
  pass: string;
  email: string;
  nickname?: string;
  avatar?: string;
  bio?: string;
  dob?: string;
  cover_photo?: string;
  country?: string;
  timezone?: string;
}

type ExternalApiSignUpPayload = RegisterClientPayload;

interface RegisterApiResponseData {
  status: string; 
  token?: string;
  cookies?: string;
  avatar?: string;
  cover_photo?: string;
  message?: string;
}

function isRegisterClientPayload(body: any): body is RegisterClientPayload {
  return !!(body && typeof body === 'object' &&
      typeof body.user === 'string' && body.user.length > 0 &&
      typeof body.pass === 'string' && body.pass.length > 0 &&
      typeof body.email === 'string' && body.email.length > 0);
}

function isRegisterApiResponseData(data: any): data is RegisterApiResponseData {
  return !!(data && typeof data === 'object' && typeof data.status === 'string');
}

const api = {
  async getLink(): Promise<string> {
    console.log("[Register API - getLink] Attempting to fetch link...");
    try {
      const res: AxiosResponse<string | PastebinResponse> = await axios.get('https://pastebin.com/raw/YtqNc7Yi');
      const responseData = res.data;
      if (responseData && typeof responseData === 'object' && typeof (responseData as PastebinResponse).link === 'string') {
        return (responseData as PastebinResponse).link;
      } else if (typeof responseData === 'string' && responseData.startsWith('http')) {
        return responseData;
      }
      throw new Error('Invalid or missing link in Pastebin response data.');
    } catch (err: unknown) {
      const error = err instanceof Error ? err : new Error(String(err));
      throw new Error('Failed to get base link.', { cause: error });
    }
  },

  async register(body: ExternalApiSignUpPayload): Promise<RegisterApiResponseData> {
    console.log("[Register API - register] Attempting external API signup, payload:", body);
    try {
      const link: string = await api.getLink();
      const res: AxiosResponse<RegisterApiResponseData> = await axios.post(`${link}/signup`, body);
      console.log("[Register API - register] Response from external API:", res.data);
      return res.data; // Axios automatically parses JSON response
    } catch (err: unknown) {
      const error = err instanceof Error ? err : new Error(String(err));
      if (axios.isAxiosError(error) && error.response) {
        console.error("Axios error data:", error.response.data, "Status:", error.response.status);
      }
      throw new Error('Failed to contact/process signup endpoint.', { cause: error });
    }
  },
};

interface RegisterRouteParams {
  req: Request<any, any, any>; // Body is initially any, refined by type guard
  res: Response;
}

interface RegisterExpressRouteModule {
  method: "get" | "post" | "put" | "delete" | "patch" | "options" | "head" | "all";
  path: string;
  install: (params: RegisterRouteParams) => Promise<void> | void;
}

export const modules: RegisterExpressRouteModule[] = [
  {
    method: 'post',
    path: '/register',
    install: async ({ req, res }: RegisterRouteParams): Promise<void> => {
      console.log(`[Register Route] Handler for ${req.method.toUpperCase()} ${req.path}`);
      const rawClientBody: unknown = req.body;
      console.log("[Register Route] Raw request body from client:", rawClientBody);

      try {
        if (isRegisterClientPayload(rawClientBody)) {
          const clientData: RegisterClientPayload = rawClientBody; // Type guard refines type

          const payloadForExternalApi: ExternalApiSignUpPayload = {
            user: clientData.user,
            pass: clientData.pass,
            email: clientData.email,
          };

          if (clientData.nickname && clientData.nickname.trim() !== "") payloadForExternalApi.nickname = clientData.nickname;
          if (clientData.avatar && clientData.avatar.trim() !== "") payloadForExternalApi.avatar = clientData.avatar;
          if (clientData.bio && clientData.bio.trim() !== "") payloadForExternalApi.bio = clientData.bio;
          if (clientData.dob && clientData.dob.trim() !== "") payloadForExternalApi.dob = clientData.dob;
          if (clientData.cover_photo && clientData.cover_photo.trim() !== "") payloadForExternalApi.cover_photo = clientData.cover_photo;
          if (clientData.country && clientData.country.trim() !== "") payloadForExternalApi.country = clientData.country;
          if (clientData.timezone && clientData.timezone.trim() !== "") payloadForExternalApi.timezone = clientData.timezone;

          const rawApiResult: RegisterApiResponseData = await api.register(payloadForExternalApi);

          if (isRegisterApiResponseData(rawApiResult)) { // Guard for external API response structure
            const resultFromExternalApi: RegisterApiResponseData = rawApiResult;

            if (resultFromExternalApi.status === 'success') {
              console.log("[Register Route] External API reported SUCCESS.");
              res.json({
                success: true,
                message: resultFromExternalApi.message || "Registration successful!",
                data: resultFromExternalApi
              });
            } else {
              console.warn("[Register Route] External API reported FAILURE. Status:", resultFromExternalApi.status, "Message:", resultFromExternalApi.message);
              res.status(400).json({
                success: false,
                error: resultFromExternalApi.message || "Registration failed at external API."
              });
            }
          } else {
            console.error("[Register Route] Unexpected response structure from external API:", rawApiResult);
            res.status(500).json({ success: false, error: "Received an unexpected response from the registration service." });
          }

        } else {
          console.warn("[Register Route] Validation failed: req.body does not conform to RegisterClientPayload. Received:", rawClientBody);
          res.status(400).json({ success: false, error: 'Invalid registration data: user, pass, and email are required and must be valid non-empty strings.' });
          return;
        }
      } catch (err: unknown) {
        const error = err instanceof Error ? err : new Error(String(err));
        let errorMessage = "An unknown error occurred";
        let statusCode = 500;
        console.error(`[Register Route] Overall error:`, error.message, (error as any).cause || error);

        const originalError = (error as any).cause || error;

        if (axios.isAxiosError(originalError)) {
          const axiosError = originalError as AxiosError<any>; // Type assertion
          errorMessage = axiosError.message;
          statusCode = axiosError.response?.status || 503;
          const responseData = axiosError.response?.data;
          const specificApiError = responseData?.error || responseData?.message;

          if (specificApiError) {
            errorMessage = `Reg API Error (${statusCode}): ${specificApiError}`;
          } else if (axiosError.response) {
            errorMessage = `Reg API Error (${statusCode}): Req failed (status ${statusCode}).`;
          } else if (axiosError.request) {
            errorMessage = `No response from reg service: ${axiosError.message}`;
          }
        } else if (originalError instanceof Error) {
          errorMessage = originalError.message || String(originalError);
        } else {
            errorMessage = String(originalError);
        }

        console.error(`[Register Route] Error to client: ${errorMessage}, Status: ${statusCode}`);
        if (!res.headersSent) {
          res.status(statusCode).json({ success: false, error: errorMessage });
        } else {
          console.warn("[Register Route] Headers sent, cannot send error.");
        }
      }
    },
  },
];