fix: support PascalCase properties in Ombi webhooks (#42)
This commit is contained in:
@@ -717,9 +717,12 @@ router.post('/ombi', webhookLimiter, (req, res) => {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
|
||||
// Ombi uses notificationType instead of eventType
|
||||
const { notificationType, requestId, requestedUser, applicationUrl } = req.body;
|
||||
const eventType = notificationType || req.body.eventType;
|
||||
// Ombi uses notificationType instead of eventType. Support PascalCase for .NET apps
|
||||
const notificationType = req.body.notificationType || req.body.NotificationType;
|
||||
const requestId = req.body.requestId || req.body.RequestId;
|
||||
const applicationUrl = req.body.applicationUrl || req.body.ApplicationUrl;
|
||||
|
||||
const eventType = notificationType || req.body.eventType || req.body.EventType;
|
||||
|
||||
// Extract username from requestedUser (handles both object and string formats)
|
||||
const username = extractRequestedUser(req.body);
|
||||
@@ -732,7 +735,7 @@ router.post('/ombi', webhookLimiter, (req, res) => {
|
||||
// Use applicationUrl as instance identifier for replay protection
|
||||
const instanceName = applicationUrl || 'ombi';
|
||||
// Use requestId + eventType + current time as replay key
|
||||
const eventDate = req.body.requestedDate || new Date().toISOString();
|
||||
const eventDate = req.body.requestedDate || req.body.RequestedDate || new Date().toISOString();
|
||||
|
||||
if (isReplay(eventType, instanceName, `${requestId}-${eventDate}`)) {
|
||||
logToFile(`[Webhook] Ombi duplicate event ignored: ${eventType} requestId=${requestId}`);
|
||||
|
||||
@@ -15,17 +15,19 @@
|
||||
function extractRequestedUser(request) {
|
||||
if (!request) return '';
|
||||
|
||||
const requestedUser = request.requestedUser || request.RequestedUser;
|
||||
|
||||
// Handle object format: OmbiStore.Entities.OmbiUser
|
||||
if (request.requestedUser && typeof request.requestedUser === 'object') {
|
||||
if (requestedUser && typeof requestedUser === 'object') {
|
||||
// Priority: alias > userAlias > userName > normalizedUserName > requestedByAlias
|
||||
return request.requestedUser.alias ||
|
||||
request.requestedUser.userAlias ||
|
||||
request.requestedUser.userName ||
|
||||
request.requestedUser.normalizedUserName ||
|
||||
request.requestedByAlias || '';
|
||||
return requestedUser.alias || requestedUser.Alias ||
|
||||
requestedUser.userAlias || requestedUser.UserAlias ||
|
||||
requestedUser.userName || requestedUser.UserName ||
|
||||
requestedUser.normalizedUserName || requestedUser.NormalizedUserName ||
|
||||
request.requestedByAlias || request.RequestedByAlias || '';
|
||||
}
|
||||
// Handle string format (fallback for compatibility)
|
||||
return request.requestedUser || request.requestedByAlias || '';
|
||||
return requestedUser || request.requestedByAlias || request.RequestedByAlias || '';
|
||||
}
|
||||
|
||||
function filterRequestsByUser(requests, username, showAll) {
|
||||
|
||||
@@ -647,5 +647,32 @@ describe('POST /api/webhook/ombi', () => {
|
||||
expect(res2.status).toBe(200);
|
||||
expect(res2.body.duplicate).toBe(true);
|
||||
});
|
||||
|
||||
it('returns 200 { received: true } for a valid NewRequest event with PascalCase payload', async () => {
|
||||
const app = makeApp();
|
||||
|
||||
nock('https://ombi.test')
|
||||
.get('/api/v1/Request/movie')
|
||||
.reply(200, []);
|
||||
nock('https://ombi.test')
|
||||
.get('/api/v1/Request/tv')
|
||||
.reply(200, []);
|
||||
|
||||
const payload = {
|
||||
NotificationType: 'NewRequest',
|
||||
RequestId: 126,
|
||||
RequestedUser: { UserName: 'gordon_pascal' },
|
||||
Title: 'Pascal Movie',
|
||||
Type: 'Movie',
|
||||
RequestStatus: 'Pending',
|
||||
ApplicationUrl: 'https://ombi.test',
|
||||
RequestedDate: '2026-05-23T20:33:00.000Z'
|
||||
};
|
||||
|
||||
const res = await postOmbi(app, payload);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body.received).toBe(true);
|
||||
expect(res.body.duplicate).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user