<commit_before>import _debug from 'debug'
import forEach from 'lodash/forEach'
import omit from 'lodash/omit'
import { HangUpAction } from '../actions/CallActions'
import { MediaStreamAction } from '../actions/MediaActions'
import { AddStreamAction, AddStreamTrackAction, RemoveStreamAction, RemoveStreamTrackAction, StreamAction, StreamType } from '../actions/StreamActions'
import { HANG_UP, MEDIA_STREAM, STREAM_ADD, STREAM_REMOVE, STREAM_TRACK_ADD, STREAM_TRACK_REMOVE } from '../constants'
import { createObjectURL, revokeObjectURL } from '../window'

const debug = _debug('peercalls')
const defaultState = Object.freeze({})

function safeCreateObjectURL (stream: MediaStream) {
  try {
    return createObjectURL(stream)
  } catch (err) {
    return undefined
  }
}

export interface StreamWithURL {
  stream: MediaStream
  type: StreamType | undefined
  url?: string
}

export interface UserStreams {
  userId: string
  streams: StreamWithURL[]
}

export interface StreamsState {
  [userId: string]: UserStreams
}

interface StreamWithUserId {
  stream: MediaStream
  userId: string
}

function getStreamWithUserId(payload: StreamWithUserId): StreamWithUserId {
  const { stream } = payload
  const streamId = stream.id
  const streamIdPayload = streamId.split('_')
  if (streamId.startsWith('sfu_') && streamIdPayload.length === 3) {
    const userId = streamIdPayload[1]
    debug(
      'getStreamWithUserId: converting MediaStream.id from %s to %s',
      stream.id, userId,
    )
    return { stream, userId }
  }
  return payload
}

function addStream (
  state: StreamsState, payload: AddStreamAction['payload'],
): StreamsState {
  const { userId, stream } = getStreamWithUserId(payload)

  const userStreams = state[userId] || {
    userId,
    streams: [],
  }

  if (userStreams.streams.map(s => s.stream).indexOf(stream) >= 0) {
    return state
  }

  const streamWithURL: StreamWithURL = {
    stream,
    type: payload.type,
    url: safeCreateObjectURL(stream),
  }

  return {
    ...state,
    [userId]: {
      userId,
      streams: [...userStreams.streams, streamWithURL],
    },
  }
}

function removeStream (
  state: StreamsState, payload: RemoveStreamAction['payload'],
): StreamsState {
  const { userId, stream } = getStreamWithUserId(payload)
  const userStreams = state[userId]
  if (!userStreams) {
    return state
  }

  if (stream) {
    const streams = userStreams.streams.filter(s => {
      const found = s.stream === stream
      if (found) {
        stream.getTracks().forEach(track => track.stop())
        s.url && revokeObjectURL(s.url)
      }
      return !found
    })
    if (streams.length > 0) {
      return {
        ...state,
        [userId]: {
          userId,
          streams,
        },
      }
    } else {
      omit(state, [userId])
    }
  }

  userStreams && userStreams.streams.forEach(s => {
    s.stream.getTracks().forEach(track => track.stop())
    s.url && revokeObjectURL(s.url)
  })
  return omit(state, [userId])
}<commit_msg>Remove check if (stream) check<commit_after>import _debug from 'debug'
import forEach from 'lodash/forEach'
import omit from 'lodash/omit'
import { HangUpAction } from '../actions/CallActions'
import { MediaStreamAction } from '../actions/MediaActions'
import { AddStreamAction, AddStreamTrackAction, RemoveStreamAction, RemoveStreamTrackAction, StreamAction, StreamType } from '../actions/StreamActions'
import { HANG_UP, MEDIA_STREAM, STREAM_ADD, STREAM_REMOVE, STREAM_TRACK_ADD, STREAM_TRACK_REMOVE } from '../constants'
import { createObjectURL, revokeObjectURL } from '../window'

const debug = _debug('peercalls')
const defaultState = Object.freeze({})

function safeCreateObjectURL (stream: MediaStream) {
  try {
    return createObjectURL(stream)
  } catch (err) {
    return undefined
  }
}

export interface StreamWithURL {
  stream: MediaStream
  type: StreamType | undefined
  url?: string
}

export interface UserStreams {
  userId: string
  streams: StreamWithURL[]
}

export interface StreamsState {
  [userId: string]: UserStreams
}

interface StreamWithUserId {
  stream: MediaStream
  userId: string
}

function getStreamWithUserId(payload: StreamWithUserId): StreamWithUserId {
  const { stream } = payload
  const streamId = stream.id
  const streamIdPayload = streamId.split('_')
  if (streamId.startsWith('sfu_') && streamIdPayload.length === 3) {
    const userId = streamIdPayload[1]
    debug(
      'getStreamWithUserId: converting MediaStream.id from %s to %s',
      stream.id, userId,
    )
    return { stream, userId }
  }
  return payload
}

function addStream (
  state: StreamsState, payload: AddStreamAction['payload'],
): StreamsState {
  const { userId, stream } = getStreamWithUserId(payload)

  const userStreams = state[userId] || {
    userId,
    streams: [],
  }

  if (userStreams.streams.map(s => s.stream).indexOf(stream) >= 0) {
    return state
  }

  const streamWithURL: StreamWithURL = {
    stream,
    type: payload.type,
    url: safeCreateObjectURL(stream),
  }

  return {
    ...state,
    [userId]: {
      userId,
      streams: [...userStreams.streams, streamWithURL],
    },
  }
}

function removeStream (
  state: StreamsState, payload: RemoveStreamAction['payload'],
): StreamsState {
  const { userId, stream } = getStreamWithUserId(payload)
  const userStreams = state[userId]
  if (!userStreams) {
    return state
  }

  const streams = userStreams.streams.filter(s => {
    const found = s.stream === stream
    if (found) {
      stream.getTracks().forEach(track => track.stop())
      s.url && revokeObjectURL(s.url)
    }
    return !found
  })
  if (streams.length > 0) {
    return {
      ...state,
      [userId]: {
        userId,
        streams,
      },
    }
  } else {
    omit(state, [userId])
  }

  userStreams && userStreams.streams.forEach(s => {
    s.stream.getTracks().forEach(track => track.stop())
    s.url && revokeObjectURL(s.url)
  })
  return omit(state, [userId])
}
{'fraction_non_alphanumeric': 0.12200435729847495, 'fraction_numerical': 0.0013407072230601643, 'mean_word_length': 3.5041509433962266, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1660878', 'n_tokens_mistral': 1869, 'n_tokens_neox': 1895, 'n_words': 434}