index.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. const Plugin = require('../../core/Plugin')
  2. const Translator = require('../../core/Translator')
  3. const { h } = require('preact')
  4. const { RequestClient } = require('../../server')
  5. const UrlUI = require('./UrlUI.js')
  6. require('whatwg-fetch')
  7. /**
  8. * Url
  9. *
  10. */
  11. module.exports = class Url extends Plugin {
  12. constructor (uppy, opts) {
  13. super(uppy, opts)
  14. this.id = this.opts.id || 'Url'
  15. this.title = 'Link'
  16. this.type = 'acquirer'
  17. this.icon = () => <svg aria-hidden="true" class="UppyIcon UppyModalTab-icon" width="64" height="64" viewBox="0 0 64 64">
  18. <circle cx="32" cy="32" r="31" />
  19. <g fill-rule="nonzero" fill="#FFF">
  20. <path d="M25.774 47.357a4.077 4.077 0 0 1-5.76 0L16.9 44.24a4.076 4.076 0 0 1 0-5.758l5.12-5.12-1.817-1.818-5.12 5.122a6.651 6.651 0 0 0 0 9.392l3.113 3.116a6.626 6.626 0 0 0 4.699 1.943c1.7 0 3.401-.649 4.697-1.943l10.241-10.243a6.591 6.591 0 0 0 1.947-4.696 6.599 6.599 0 0 0-1.947-4.696l-3.116-3.114-1.817 1.817 3.116 3.114a4.045 4.045 0 0 1 1.194 2.88 4.045 4.045 0 0 1-1.194 2.878L25.774 47.357z" />
  21. <path d="M46.216 14.926a6.597 6.597 0 0 0-4.696-1.946h-.001a6.599 6.599 0 0 0-4.696 1.945L26.582 25.167a6.595 6.595 0 0 0-1.947 4.697 6.599 6.599 0 0 0 1.946 4.698l3.114 3.114 1.818-1.816-3.114-3.114a4.05 4.05 0 0 1-1.194-2.882c0-1.086.424-2.108 1.194-2.878L38.64 16.744a4.042 4.042 0 0 1 2.88-1.194c1.089 0 2.11.425 2.88 1.194l3.114 3.114a4.076 4.076 0 0 1 0 5.758l-5.12 5.12 1.818 1.817 5.12-5.122a6.649 6.649 0 0 0 0-9.393l-3.113-3.114-.003.002z" />
  22. </g>
  23. </svg>
  24. // Set default options and locale
  25. const defaultLocale = {
  26. strings: {
  27. import: 'Import',
  28. enterUrlToImport: 'Enter URL to import a file',
  29. failedToFetch: 'Uppy Server failed to fetch this URL, please make sure it’s correct',
  30. enterCorrectUrl: 'Incorrect URL: Please make sure you are entering a direct link to a file'
  31. }
  32. }
  33. const defaultOptions = {
  34. locale: defaultLocale
  35. }
  36. this.opts = Object.assign({}, defaultOptions, opts)
  37. this.locale = Object.assign({}, defaultLocale, this.opts.locale)
  38. this.locale.strings = Object.assign({}, defaultLocale.strings, this.opts.locale.strings)
  39. this.translator = new Translator({locale: this.locale})
  40. this.i18n = this.translator.translate.bind(this.translator)
  41. this.hostname = this.opts.host
  42. if (!this.hostname) {
  43. throw new Error('Uppy Server hostname is required, please consult https://uppy.io/docs/server')
  44. }
  45. // Bind all event handlers for referencability
  46. this.getMeta = this.getMeta.bind(this)
  47. this.addFile = this.addFile.bind(this)
  48. this.server = new RequestClient(uppy, {host: this.opts.host})
  49. }
  50. getFileNameFromUrl (url) {
  51. return url.substring(url.lastIndexOf('/') + 1)
  52. }
  53. checkIfCorrectURL (url) {
  54. if (!url) return false
  55. const protocol = url.match(/^([a-z0-9]+):\/\//)[1]
  56. if (protocol !== 'http' && protocol !== 'https') {
  57. return false
  58. }
  59. return true
  60. }
  61. addProtocolToURL (url) {
  62. const protocolRegex = /^[a-z0-9]+:\/\//
  63. const defaultProtocol = 'http://'
  64. if (protocolRegex.test(url)) {
  65. return url
  66. }
  67. return defaultProtocol + url
  68. }
  69. getMeta (url) {
  70. return this.server.post('url/meta', { url })
  71. .then((res) => {
  72. if (res.error) {
  73. this.uppy.log('[URL] Error:')
  74. this.uppy.log(res.error)
  75. throw new Error('Failed to fetch the file')
  76. }
  77. return res
  78. })
  79. }
  80. addFile (url) {
  81. url = this.addProtocolToURL(url)
  82. if (!this.checkIfCorrectURL(url)) {
  83. this.uppy.log(`[URL] Incorrect URL entered: ${url}`)
  84. this.uppy.info(this.i18n('enterCorrectUrl'), 'error', 4000)
  85. return
  86. }
  87. return this.getMeta(url)
  88. .then((meta) => {
  89. const tagFile = {
  90. source: this.id,
  91. name: this.getFileNameFromUrl(url),
  92. type: meta.type,
  93. data: {
  94. size: meta.size
  95. },
  96. isRemote: true,
  97. body: {
  98. url: url
  99. },
  100. remote: {
  101. host: this.opts.host,
  102. url: `${this.hostname}/url/get`,
  103. body: {
  104. fileId: url,
  105. url: url
  106. }
  107. }
  108. }
  109. return tagFile
  110. })
  111. .then((tagFile) => {
  112. this.uppy.log('[Url] Adding remote file')
  113. return this.uppy.addFile(tagFile)
  114. })
  115. .then(() => {
  116. const dashboard = this.uppy.getPlugin('Dashboard')
  117. if (dashboard) dashboard.hideAllPanels()
  118. })
  119. .catch((err) => {
  120. this.uppy.log(err)
  121. this.uppy.info({
  122. message: this.i18n('failedToFetch'),
  123. details: err
  124. }, 'error', 4000)
  125. })
  126. }
  127. render (state) {
  128. return <UrlUI
  129. i18n={this.i18n}
  130. addFile={this.addFile} />
  131. }
  132. install () {
  133. const target = this.opts.target
  134. if (target) {
  135. this.mount(target, this)
  136. }
  137. }
  138. uninstall () {
  139. this.unmount()
  140. }
  141. }