Skip to content

Commit

Permalink
Merge pull request #94 from JuanPabloLoCoco/fix_roStorymove_params
Browse files Browse the repository at this point in the history
chore: fix storyID parameter on roStoryMove
  • Loading branch information
nytamin committed Feb 2, 2024
2 parents 70441b4 + 7529616 commit 6c32772
Show file tree
Hide file tree
Showing 7 changed files with 638 additions and 28 deletions.
98 changes: 86 additions & 12 deletions packages/connector/src/MosDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,14 +355,41 @@ export class MosDevice implements IMOSDevice {
},
}
} else if (data.roStoryMove) {
// From documentation:
// **Note**: If the second <storyID> tag is blank move the story to the bottom of the Running Order.

let storyIDs: string[]

if (Array.isArray(data.roStoryMove.storyID)) {
storyIDs = data.roStoryMove.storyID
} else {
if (this.strict) {
// The storyID is xml-converted to a string if the second tag is missing.
// The spec says that there must be two storyID tags, so we'll throw an error here:
return new MosModel.ROAck(
{
ID: this.mosTypes.mosString128.create(data.roStoryMove.roID),
Status: this.mosTypes.mosString128.create(
`The second <storyID> tag is missing in <roStoryMove>.`
),
Stories: [],
},
this.strict
)
} else {
// Non strict mode: This is technically out of spec, but it's a common mistake, so we'll handle it like so:
storyIDs = [data.roStoryMove.storyID as string, '']
}
}

data.roElementAction = {
roID: data.roStoryMove.roID,
operation: 'MOVE',
element_target: {
storyID: data.roStoryMove.storyID[1],
storyID: storyIDs[1],
},
element_source: {
storyID: data.roStoryMove.storyID[0],
storyID: storyIDs[0],
},
}
} else if (data.roStorySwap) {
Expand All @@ -384,11 +411,53 @@ export class MosDevice implements IMOSDevice {
storyID: data.roStoryDelete.storyID,
},
}
} else if (data.roStoryMoveMultiple && data.roStoryMoveMultiple.storyID.length > 1) {
const l = data.roStoryMoveMultiple.storyID.length
} else if (data.roStoryMoveMultiple && data.roStoryMoveMultiple.storyID) {
const stories: string[] = Array.isArray(data.roStoryMoveMultiple.storyID)
? (data.roStoryMoveMultiple.storyID as string[])
: [data.roStoryMoveMultiple.storyID as string]

{
// From documentation:
// Validation: Duplicate storyIDs are not permitted with in the storyID list.
// This prevents the move from being ambiguous; if two IDs are the same, it is unclear
// where in the playlist the story with duplicate ID must be placed.
const uniqueStoryIds = new Set<string>()
for (const storyId of stories) {
if (uniqueStoryIds.has(storyId))
return new MosModel.ROAck(
{
ID: this.mosTypes.mosString128.create(data.roStoryMoveMultiple.roID),
Status: this.mosTypes.mosString128.create(
`Duplicate storyIDs are not permitted with in the storyID list.`
),
Stories: [],
},
this.strict
)
uniqueStoryIds.add(storyId)
}
}

let target: string
let sources: string[]

const target = data.roStoryMoveMultiple.storyID[l - 1]
const sources = data.roStoryMoveMultiple.storyID.slice(0, l - 1)
if (stories.length > 1) {
target = stories[stories.length - 1]
sources = stories.slice(0, stories.length - 1)
} else {
if (this.strict) {
// Technically a no-op:
target = stories[0]
sources = []
} else {
// Handling of edge-case:
// If there is only a single storyId, we assume that the single mentioned story should be moved to the end of the playlist
// (ie that there is supposed to be a second, blank storyId that was just omitted by the sender)

target = ''
sources = stories
}
}

data.roElementAction = {
roID: data.roStoryMoveMultiple.roID,
Expand Down Expand Up @@ -435,21 +504,26 @@ export class MosDevice implements IMOSDevice {
itemID: data.roItemDelete.itemID,
},
}
} else if (data.roItemMoveMultiple && data.roItemMoveMultiple.itemID.length > 1) {
const l = data.roItemMoveMultiple.itemID.length
} else if (data.roItemMoveMultiple && data.roItemMoveMultiple.itemID && data.roItemMoveMultiple.storyID) {
const items: string[] = Array.isArray(data.roItemMoveMultiple.itemID)
? (data.roItemMoveMultiple.itemID as string[])
: [data.roItemMoveMultiple.itemID as string]

// An aditional validation checking the length of items can be added
const l = items.length

const target = data.roItemMoveMultiple.itemID[l - 1]
const sources = data.roItemMoveMultiple.itemID.slice(0, l - 1)
const target = items[l - 1]
const sources = items.slice(0, l - 1)

data.roElementAction = {
roID: data.roItemMoveMultiple.roID,
operation: 'MOVE',
element_target: {
storyID: data.roItemMoveMultiple.storyID,
itemID: target,
itemID: l === 1 ? undefined : target,
},
element_source: {
itemID: sources,
itemID: l === 1 ? items : sources,
},
}
}
Expand Down
19 changes: 19 additions & 0 deletions packages/connector/src/__mocks__/testData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,12 @@ const xmlData = {
roStoryInsert: `<roStoryInsert><roID>5PM</roID> <storyID>HOTEL FIRE</storyID> <story> <storyID>V: BRIDGE COLLAPSE</storyID> <storySlug>Bridge Collapse</storySlug> <storyNum>B7</storyNum> <item> <itemID>30848</itemID> <objID>M000627</objID> <mosID>testmos.enps.com</mosID><objPaths><objPath techDescription="MPEG2 Video">\\\\server\\media\\clip392028cd2320s0d.mxf</objPath><objProxyPath techDescription="WM9 750Kbps">http://server/proxy/clipe.wmv</objProxyPath></objPaths> <itemEdStart>0</itemEdStart> <itemEdDur>815</itemEdDur> <itemUserTimingDur>310</itemUserTimingDur> <macroIn>c01/l04/dve07</macroIn> <macroOut>r00</macroOut> <mosExternalMetadata> <mosScope>PLAYLIST</mosScope> <mosSchema>http://MOSA4.com/mos/supported_schemas/MOSAXML2.08</mosSchema> <mosPayload> <Owner>SHOLMES</Owner> <transitionMode>2</transitionMode> <transitionPoint>463</transitionPoint> <source>a</source> <destination>b</destination> </mosPayload> </mosExternalMetadata> <mosExternalMetadata> <mosScope>PLAYLIST</mosScope> <mosSchema>http://MOSA4.com/mos/supported_schemas/MOSBXML2.08</mosSchema> <mosPayload> <rate>52</rate> <background>2</background> <overlay>463</overlay> </mosPayload> </mosExternalMetadata> </item> <item> <itemID>30849</itemID> <objID>M000628</objID> <mosID>testmos</mosID> <itemEdStart>0</itemEdStart> <itemEdDur>815</itemEdDur> <itemUserTimingDur>310</itemUserTimingDur> <macroIn>c01/l04/dve07</macroIn> <macroOut>r00</macroOut> <mosExternalMetadata> <mosScope>PLAYLIST</mosScope> <mosSchema>http://MOSA4.com/mos/supported_schemas/MOSAXML2.08</mosSchema> <mosPayload> <Owner>SHOLMES</Owner> <transitionMode>2</transitionMode> <transitionPoint>463</transitionPoint> <source>a</source> <destination>b</destination> </mosPayload> </mosExternalMetadata> </item> </story> </roStoryInsert>`,
roStoryReplace: `<roStoryReplace><roID>5PM</roID> <storyID>P: PHILLIPS INTERVIEW</storyID> <story> <storyID>V: HOTEL FIRE</storyID> <storySlug>Hotel Fire</storySlug> <storyNum>C1</storyNum> <item> <itemID>30848</itemID> <itemSlug>Hotel Fire vo</itemSlug> <objID>M000702</objID> <mosID>testmos</mosID><objPaths><objPath techDescription="MPEG2 Video">\\\\server\\media\\clip392028cd2320s0d.mxf</objPath><objProxyPath techDescription="WM9 750Kbps">http://server/proxy/clipe.wmv</objProxyPath></objPaths> <itemEdStart>0</itemEdStart> <itemEdDur>900</itemEdDur> <itemUserTimingDur>800</itemUserTimingDur> <macroIn>c01/l04/dve07</macroIn> <macroOut>r00</macroOut> <mosExternalMetadata> <mosScope>PLAYLIST</mosScope> <mosSchema>http://MOSA4.com/mos/supported_schemas/MOSAXML2.08</mosSchema> <mosPayload> <Owner>SHOLMES</Owner> <transitionMode>2</transitionMode> <transitionPoint>463</transitionPoint> <source>a</source> <destination>b</destination> </mosPayload> </mosExternalMetadata> </item> </story> <story> <storyID>V: DORMITORY FIRE</storyID> <storySlug>Dormitory Fire</storySlug> <storyNum>C2</storyNum> <item> <itemID>1</itemID> <itemSlug>Dormitory Fire vo</itemSlug> <objID>M000705</objID> <mosID>testmos</mosID> <itemEdStart>0</itemEdStart> <itemEdDur>800</itemEdDur> <itemUserTimingDur>310</itemUserTimingDur> <macroIn>c01/l04/dve07</macroIn> <macroOut>r00</macroOut> <mosExternalMetadata> <mosScope>PLAYLIST</mosScope> <mosSchema>http://MOSA4.com/mos/supported_schemas/MOSAXML2.08</mosSchema> <mosPayload> <Owner>SHOLMES</Owner> <transitionMode>2</transitionMode> <transitionPoint>463</transitionPoint> <source>a</source> <destination>b</destination> </mosPayload> </mosExternalMetadata> </item> </story> </roStoryReplace>`,
roStoryMove: `<roStoryMove><roID>5PM</roID> <storyID>V: BRIDGE COLLAPSE</storyID> <storyID>P: PHILLIPS INTERVIEW</storyID> </roStoryMove>`,
roStoryMove_blank: `<roStoryMove><roID>5PM</roID> <storyID>V: BRIDGE COLLAPSE</storyID> <storyID></storyID> </roStoryMove>`,
roStoryMove_offspec_missing: `<roStoryMove><roID>5PM</roID> <storyID>V: BRIDGE COLLAPSE</storyID></roStoryMove>`,
roStorySwap: `<roStorySwap><roID>5PM</roID> <storyID>V: BRIDGE COLLAPSE</storyID> <storyID>P: PHILLIPS INTERVIEW</storyID> </roStorySwap> `,
roStoryDelete: `<roStoryDelete><roID>5PM</roID> <storyID>V: BRIDGE COLLAPSE</storyID> <storyID>P: PHILLIPS INTERVIEW</storyID> </roStoryDelete>`,
roStoryMoveMultiple: `<roStoryMoveMultiple><roID>5PM</roID> <storyID>2</storyID> <storyID>3</storyID> <storyID>5</storyID> <storyID>6</storyID> <storyID>1</storyID> </roStoryMoveMultiple>`,
roStoryMoveMultiple_single_storyId: `<roStoryMoveMultiple><roID>5PM</roID> <storyID>2</storyID> </roStoryMoveMultiple>`,
roItemInsert: `<roItemInsert> <roID>5PM</roID> <storyID>2597609</storyID> <itemID>5</itemID> <item> <itemID>30848</itemID> <itemSlug>Hotel Fire vo</itemSlug> <objID>M00702</objID> <mosID>testmos</mosID> <objPaths><objPath techDescription="MPEG2 Video">\\\\server\\media\\clip392028cd2320s0d.mxf</objPath><objProxyPath techDescription="WM9 750Kbps">http://server/proxy/clipe.wmv</objProxyPath> </objPaths> <itemEdStart>0</itemEdStart> <itemEdDur>900</itemEdDur> <itemUserTimingDur>310</itemUserTimingDur> </item> <item> <itemID>1</itemID> <itemSlug>Dormitory Fire vo</itemSlug> <objID>M00705</objID> <mosID>testmos</mosID> <itemEdStart>0</itemEdStart> <itemEdDur>800</itemEdDur> <itemUserTimingDur>310</itemUserTimingDur> </item> </roItemInsert>`,
roItemReplace: `<roItemReplace> <roID>5PM</roID> <storyID>2597609</storyID> <itemID>5</itemID> <item> <itemID>30848</itemID> <itemSlug>Hotel Fire vo</itemSlug> <objID>M00702</objID> <mosID>testmos</mosID><objPaths><objPath techDescription="MPEG2 Video">\\\\server\\media\\clip392028cd2320s0d.mxf</objPath><objProxyPath techDescription="WM9 750Kbps">http://server/proxy/clipe.wmv</objProxyPath></objPaths> <itemEdStart>0</itemEdStart> <itemEdDur>900</itemEdDur> <itemUserTimingDur>810</itemUserTimingDur> </item> <item> <itemID>1</itemID> <itemSlug>Dormitory Fire vo</itemSlug> <objID>M00705</objID> <mosID>testmos</mosID> <itemEdStart>0</itemEdStart> <itemEdDur>800</itemEdDur> <itemUserTimingDur>610</itemUserTimingDur> </item> </roItemReplace>`,
roItemMoveMultiple: `<roItemMoveMultiple><roID>5PM</roID> <storyID>Barn Fire</storyID> <itemID>2</itemID> <itemID>3</itemID> <itemID>5</itemID> <itemID>6</itemID> <itemID>1</itemID> </roItemMoveMultiple> `,
Expand Down Expand Up @@ -1523,6 +1526,10 @@ const xmlApiData = {
StoryID: mosTypes.mosString128.create('P: PHILLIPS INTERVIEW'),
}),
roElementAction_roStoryMove_stories: [mosTypes.mosString128.create('V: BRIDGE COLLAPSE')],
roElementAction_roStoryMove_blank_action: literal<IMOSStoryAction>({
RunningOrderID: mosTypes.mosString128.create('5PM'),
StoryID: mosTypes.mosString128.create(''),
}),
roElementAction_roStorySwap_action: literal<IMOSROAction>({
RunningOrderID: mosTypes.mosString128.create('5PM'),
}),
Expand All @@ -1546,6 +1553,18 @@ const xmlApiData = {
mosTypes.mosString128.create('5'),
mosTypes.mosString128.create('6'),
],
// Thechnically a no-op, but if reading the docs literally...:
roElementAction_roStoryMoveMultiple_single_storyId_action: literal<IMOSStoryAction>({
RunningOrderID: mosTypes.mosString128.create('5PM'),
StoryID: mosTypes.mosString128.create('2'),
}),
roElementAction_roStoryMoveMultiple_single_storyId_stories: [],
// Assuming that the single storyId is the story to be moved:
roElementAction_roStoryMoveMultiple_single_storyId_offspec_action: literal<IMOSStoryAction>({
RunningOrderID: mosTypes.mosString128.create('5PM'),
StoryID: mosTypes.mosString128.create(''),
}),
roElementAction_roStoryMoveMultiple_single_storyId_offspec_stories: [mosTypes.mosString128.create('2')],
roElementAction_roItemInsert_action: literal<IMOSItemAction>({
RunningOrderID: mosTypes.mosString128.create('5PM'),
StoryID: mosTypes.mosString128.create('2597609'),
Expand Down
Loading

0 comments on commit 6c32772

Please sign in to comment.