<commit_before>import ICAL from 'ical.js'
import { __assign } from 'tslib'
import { createPlugin, EventSourceDef } from '@fullcalendar/common'
import { EVENT_SOURCE_REFINERS } from './event-source-refiners'

type Success = (rawFeed: string, xhr: XMLHttpRequest) => void
type Failure = (error: string, xhr: XMLHttpRequest) => void

export function requestICal(url: string, successCallback: Success, failureCallback: Failure) {

  const xhr = new XMLHttpRequest()
  xhr.open('GET', url, true)

  xhr.onload = function() {
    if (xhr.status >= 200 && xhr.status < 400) {
      successCallback(xhr.responseText, xhr)
    } else {
      failureCallback('Request failed', xhr)
    }
  }

  xhr.onerror = () => failureCallback('Request failed', xhr)

  xhr.send(null)
}


interface ICalFeedMeta {
  feedUrl: string
  extraParams?: any
}


let eventSourceDef: EventSourceDef<ICalFeedMeta> = {

  parseMeta(refined) {
    if (refined.feedUrl) {
      return {
        feedUrl: refined.feedUrl,
      }
    }
    return null
  },

  fetch(arg, success, failure) {
    let meta: ICalFeedMeta = arg.eventSource.meta

    return new Promise((resolve, reject) => {
      requestICal(meta.feedUrl,
        (rawFeed, xhr) => {
          try {
            const iCalFeed = ICAL.parse(rawFeed)
            const iCalComponent = new ICAL.Component(iCalFeed);
            const vevents = iCalComponent.getAllSubcomponents("vevent");
            const events = vevents.map((vevent) => {
              try {
								const event = new ICAL.Event(vevent)
                const fcEvent = {
                  title: event.summary,
                  start: event.startDate.toString(),
                }

                if (event.startDate.isDate && event.endDate === null) {
                  return {
                    ...fcEvent,
                    end: event.startDate.addDuration({days: 1}).toString(),
                    allDay: true,
                  }
                } else if (event.startDate.isDate && event.endDate.isDate) {
                  return {
                    ...fcEvent,
                    end: event.endDate.toString(),
                    allDay: true,
                  }
                } else {
                  return {
                    ...fcEvent,
                    end: event.endDate.toString(),
                  }
                }
              } catch(error) {
                console.log(`Unable to process item in calendar: ${error}.`)
                return null
              }
            }).filter((item: any) => { return item !== null })

            success({ rawEvents: events, xhr })
            resolve()
          } catch(error) {
            console.log(error)
            throw error
          }
        },
        (errorMessage, xhr) => {
          failure({ message: errorMessage, xhr })
          reject()
        },
      )
    })
  }
}


export default createPlugin({
  eventSourceRefiners: EVENT_SOURCE_REFINERS,
  eventSourceDefs: [ eventSourceDef ]
})<commit_msg>Pulls out functions to tighten up exception handling<commit_after>import ICAL from 'ical.js'
import { createPlugin, EventSourceDef, EventInput } from '@fullcalendar/common'
import { EVENT_SOURCE_REFINERS } from './event-source-refiners'

type Success = (rawFeed: string, xhr: XMLHttpRequest) => void
type Failure = (error: string, xhr: XMLHttpRequest) => void

export function requestICal(url: string, successCallback: Success, failureCallback: Failure) {

  const xhr = new XMLHttpRequest()
  xhr.open('GET', url, true)

  xhr.onload = function() {
    if (xhr.status >= 200 && xhr.status < 400) {
      successCallback(xhr.responseText, xhr)
    } else {
      failureCallback('Request failed', xhr)
    }
  }

  xhr.onerror = () => failureCallback('Request failed', xhr)

  xhr.send(null)
}


interface ICalFeedMeta {
  feedUrl: string
  extraParams?: any
}

let buildIcalEvents = (rawFeed: string): ICAL.Event[] => {
  try {
    const iCalFeed = ICAL.parse(rawFeed)
    const iCalComponent = new ICAL.Component(iCalFeed);
    return iCalComponent.getAllSubcomponents("vevent");
  } catch (err) {
    console.log(`Error parsing feed: ${err}`)
    return []
  }
}

let buildEvents = (vevents: ICAL.Event[]): EventInput[] => {
  return vevents.map((vevent) => {
    const event = new ICAL.Event(vevent)
    
    const fcEvent = {
      title: event.summary,
      start: event.startDate.toString(),
    }

    try {
      if (event.startDate.isDate && event.endDate === null) {
        return {
          ...fcEvent,
          end: event.startDate.addDuration({days: 1}).toString(),
          allDay: true,
        }
      } else if (event.startDate.isDate && event.endDate.isDate) {
        return {
          ...fcEvent,
          end: event.endDate.toString(),
          allDay: true,
        }
      } else {
        return {
          ...fcEvent,
          end: event.endDate.toString(),
        }
      }
    } catch(error) {
      console.log(`Unable to process item in calendar: ${error}.`)
      return null
    }
  }).filter((item: EventInput | null) => { return item !== null })
}

let eventSourceDef: EventSourceDef<ICalFeedMeta> = {

  parseMeta(refined) {
    if (refined.feedUrl) {
      return {
        feedUrl: refined.feedUrl,
      }
    }
    return null
  },

  fetch(arg, success, failure) {
    let meta: ICalFeedMeta = arg.eventSource.meta

    return new Promise((resolve, reject) => {
      requestICal(meta.feedUrl,
        (rawFeed, xhr) => {
          const icalEvents = buildIcalEvents(rawFeed)
          const events = buildEvents(icalEvents)

          success({ rawEvents: events, xhr })
          resolve()
        },
        (errorMessage, xhr) => {
          failure({ message: errorMessage, xhr })
          reject()
        },
      )
    })
  }
}


export default createPlugin({
  eventSourceRefiners: EVENT_SOURCE_REFINERS,
  eventSourceDefs: [ eventSourceDef ]
})
{'fraction_non_alphanumeric': 0.1217450118363206, 'fraction_numerical': 0.0023672641190395673, 'mean_word_length': 2.050541516245487, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 25, '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': '4307956', 'n_tokens_mistral': 1808, 'n_tokens_neox': 1723, 'n_words': 390}