All files / app/pipe thumbnail.pipe.ts

24.39% Statements 10/41
4.61% Branches 3/65
16.66% Functions 1/6
21.87% Lines 7/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 7368x           68x 68x           68x     1x 1x 1x                                                                                                            
import { Pipe, PipeTransform } from '@angular/core';
import { map, Observable, of } from 'rxjs';
import { Ref } from '../model/ref';
import { AdminService } from '../service/admin.service';
import { ProxyService } from '../service/api/proxy.service';
import { OembedStore } from '../store/oembed';
import { getExtension } from '../util/http';
import { hasTag } from '../util/tag';
 
@Pipe({
    name: 'thumbnail',
    pure: true
})
export class ThumbnailPipe implements PipeTransform {
 
  constructor(
    private admin: AdminService,
    private store: OembedStore,
    private proxy: ProxyService,
  ) { }
 
  transform(refs: (Ref | undefined)[], force = false): Observable<string> {
    for (const ref of refs) {
      if (!ref) continue;
      for (const plugin of ['plugin/thumbnail', 'plugin/image', 'plugin/video']) {
        if (refUrl(ref, plugin)) return of(this.fetchUrl(refUrl(ref, plugin), ref.origin, ref.title || plugin.substring('plugin/'.length), plugin));
      }
      if (hasTag('plugin/embed', ref)) {
        return this.store.get(ref.plugins?.['plugin/embed']?.url || ref.url).pipe(
          map(oembed => {
            if (oembed?.thumbnail_url) {
              return this.fetchUrl(oembed.thumbnail_url, ref.origin, ref.title || oembed.title || 'thumbnail', 'plugin/thumbnail');
            }
            return '';
          }),
        );
      }
      if (!this.validUrl(ref.url)) continue;
      const embedPlugins = this.admin.getEmbeds(ref);
      for (const plugin of ['plugin/image', 'plugin/video']) {
        if (embedPlugins.includes(plugin)) return of(this.fetchUrl(ref.url, ref.origin, ref.title || plugin.substring('plugin/'.length), plugin));
      }
    }
    if (force) {
      for (const ref of refs) {
        if (!this.validUrl(ref?.url)) continue;
        return of(this.fetchUrl(ref!.url, ref!.origin, ref?.title || 'image', 'plugin/image'));
      }
    }
    return of('');
  }
 
  fetchUrl(url: string, origin: string | undefined, title: string, plugin: string) {
    if (!url) return '';
    if (url.startsWith('cache:') || this.admin.getPlugin(plugin)?.config?.proxy) {
      const ext = getExtension(url) || '';
      return this.proxy.getFetch(url, origin, title + (title.endsWith(ext) ? '' : ext), true);
    }
    return url;
  }
 
  private validUrl(url?: string) {
    return url
      && !url.startsWith('data:')
      && !url.startsWith('comment:')
      && !url.startsWith('internal:');
  }
}
 
function refUrl(ref: Ref, plugin: string) {
  return ref.plugins?.[plugin]?.url;
}