Greasy Fork

Greasy Fork is available in English.

MusicBrainz: Import from Amazon

Import releases from Amazon

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        MusicBrainz: Import from Amazon
// @namespace   https://github.com/Goram/MusicBrainz-Import-from-Amazon
// @include     *://www.amazon.*
// @version     0.98.5
// @grant       none
// @author      Gore (based on https://github.com/dufferzafar/Userscripts)
// @description Import releases from Amazon
// @require     https://code.jquery.com/jquery-2.2.3.min.js
// @require     https://code.jquery.com/ui/1.11.4/jquery-ui.min.js
// @require     https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js
// @run-at      document-end
// ==/UserScript==

'use strict';

var jquery = {};

jquery = jQuery.noConflict(true);

if (jquery('#rightCol').length) {
    jquery('#rightCol').prepend(
        '<data-gore-mbifa-bootstrap data-ng-app="goreMbifa" data-ng-controller="mbifaController">'
    );
} else if (jquery('.buyingDetailsGrid').length) {
    jquery('.buyingDetailsGrid').prepend(
        '<tr><td><data-gore-mbifa-bootstrap data-ng-app="goreMbifa" data-ng-controller="mbifaController"></td></tr>'
    );
}

var goreMbifa = angular.module('goreMbifa', []);

goreMbifa.constant('config', {
    'sites': {
        'www.amazon.de': {
            'languages': {
                'de': {
                    'months': { 'Januar': '1', 'Februar': '2', 'März': '3', 'April': '4', 'Mai': '5', 'Juni': '6', 'Juli': '7', 'August': '8', 'September': '9', 'Oktober': '10', 'November': '11', 'Dezember': '12' },
                    'disc': 'Disk',
                    'releaseDateOrder': [0, 1, 2],
                    'regexReleaseDate': /Audio CD  \((.*)\)/,
                    'regexNumDiscs': /Anzahl Disks\/Tonträger: (.*)/,
                    'regexReleaseLabel': /Label: (.*)/
                }
            }
        },
        'www.amazon.com': {
            'languages': {
                'en': {
                    'months': { 'January': '1', 'February': '2', 'March': '3', 'April': '4', 'May': '5', 'June': '6', 'July': '7', 'August': '8', 'September': '9', 'October': '10', 'November': '11', 'December': '12' },
                    'disc': 'Disc',
                    'releaseDateOrder': [1, 0, 2],
                    'regexReleaseDate': /Audio CD  \((.*)\)/,
                    'regexNumDiscs': /Number of Discs: (.*)/,
                    'regexReleaseLabel': /Label: (.*)/
                }
            }
        },
        'www.amazon.co.uk': {
            'languages': {
                'en': {
                    'months': { 'Jan.': '1', 'Feb.': '2', 'March': '3', 'April': '4', 'May': '5', 'June': '6', 'July': '7', 'Aug.': '8', 'Sept.': '9', 'Oct.': '10', 'Nov.': '11', 'Dec': '12' },
                    'disc': 'Disc',
                    'releaseDateOrder': [0, 1, 2],
                    'regexReleaseDate': /Audio CD  \((.*)\)/,
                    'regexNumDiscs': /Number of Discs: (.*)/,
                    'regexReleaseLabel': /Label: (.*)/
                }
            }
        },
        'www.amazon.ca': {
            'languages': {
                'en': {
                    'months': { 'Jan': '1', 'Feb': '2', 'March': '3', 'April': '4', 'May': '5', 'June': '6', 'July': '7', 'Aug': '8', 'Sept': '9', 'Oct': '10', 'Nov': '11', 'Dec': '12' },
                    'disc': 'Disc',
                    'releaseDateOrder': [1, 0, 2],
                    'regexReleaseDate': /Audio CD  \((.*)\)/,
                    'regexNumDiscs': /Number of Discs: (.*)/,
                    'regexReleaseLabel': /Label: (.*)/
                },
                'fr': {
                    'months': { 'janvier': '1', 'février': '2', 'mars': '3', 'avril': '4', 'mai': '5', 'juin': '6', 'juillet': '7', 'août': '8', 'septembre': '9', 'octobre': '10', 'novembre': '11', 'décembre': '12' },
                    'disc': 'Disc',
                    'releaseDateOrder': [0, 1, 2],
                    'regexReleaseDate': /Audio CD  \((.*)\)/,
                    'regexNumDiscs': /Quantité de disques : (.*)/,
                    'regexReleaseLabel': /Étiquette : (.*)/
                }
            }
        },
        'www.amazon.fr': {
            'languages': {
                'fr': {
                    'months': { 'janvier': '1', 'février': '2', 'mars': '3', 'avril': '4', 'mai': '5', 'juin': '6', 'juillet': '7', 'août': '8', 'septembre': '9', 'octobre': '10', 'novembre': '11', 'décembre': '12' },
                    'disc': 'Disc',
                    'releaseDateOrder': [0, 1, 2],
                    'regexReleaseDate': /CD  \((.*)\)/,
                    'regexNumDiscs': /Nombre de disques: (.*)/,
                    'regexReleaseLabel': /Label: (.*)/
                }
            }
        }
    },
    'form': {
        'method': 'post',
        'action': 'https://musicbrainz.org/release/add',
        'acceptCharset': 'UTF-8',
        'primaryType': {
            'name': 'type',
            'types': [
                {'key': '', 'value': 'Primary Type'},
                {'key': 'Album', 'value': 'Album'},
                {'key': 'Single', 'value': 'Single'},
                {'key': 'EP', 'value': 'EP'},
                {'key': 'Broadcast', 'value': 'Broadcast'},
                {'key': 'Other', 'value': 'Other'}
            ]
        },
        'editNode': 'Release added using the MB-Import-From-Amazon userscript from page: '
    },
    'link': {
        'href': 'https://musicbrainz.org/search',
        'type': 'release',
        'limit': '25',
        'method': 'direct'
    }
});

goreMbifa.config(function ($sceDelegateProvider) {
    $sceDelegateProvider.resourceUrlWhitelist([
      'https://musicbrainz.org/**'
    ]);
});


goreMbifa.directive('goreMbifaBootstrap', function () {
    return {
        template:
           `<style>
                #gorembifa-app {
                    border: 1px solid #ddd;
                    border-radius: 4px;
                    padding: 14px 18px 12px 18px;
                    margin: 0px 0px 12px 0px;
                }

                #gorembifa-app select {
                    width: 100%;
                    border: 1px solid #ddd;
                    border-radius: 4px;
                    padding: 3px;
                }

                #gorembifa-app form {
                    width: 100%;
                    display: block;
                    margin-bottom: 10px;
                }

                #gorembifa-app input[type="submit"] {
                    width: 100%;
                    height: 24px;
                    border: 1px solid #ddd;
                    border-radius: 3px;
                    background: linear-gradient(to bottom, #f7f8fa, #e7e9ec);
                    margin: 10px 0px 0px 0px;
                    font-family: Arial, sans-serif;
                }

                #gorembifa-app #search-direct, #search-indexed {
                    width: 100%;
                    text-align: center;
                }

                #gorembifa-app #search-indexed div {
                    text-align: left;
                    margin: 10px 0px 0px 0px;
                }
            </style>
            <div id="gorembifa-app">
                <form method="{{ form.method }}" action="{{ form.action }}" accept-charset="{{ form.acceptCharset }}">
                    <select name="{{ form.primaryType.name }}" data-ng-model="form.primaryType.selectedType" data-ng-options="type.value for type in form.primaryType.types track by type.key"/>
                    <input type="hidden" name="name" value="{{ form.title }}"/>
                    <input type="hidden" name="artist_credit.names.0.name" value="{{ form.artist }}"/>
                    <input type="hidden" name="status" value="{{ form.status }}"/>
                    <input type="hidden" name="events.0.date.day" value="{{ form.releaseDate[0] }}"/>
                    <input type="hidden" name="events.0.date.month" value="{{ form.releaseDate[1] }}"/>
                    <input type="hidden" name="events.0.date.year" value="{{ form.releaseDate[2] }}"/>
                    <input type="hidden" name="labels.0.name" value="{{ form.label }}"/>
                    <input type="hidden" name="urls.0.link_type" value="{{ form.externalLinkType }}"/>
                    <input type="hidden" name="urls.0.url" value="{{ form.asin }}"/>
                    <discs data-ng-repeat="disc in form.tracklist.discs track by $index">
                        <input type="hidden" name="mediums.{{ $index }}.format" value="CD"/>
                        <tracks data-ng-repeat="track in disc.tracks" track by $index>
                            <input type="hidden" name="mediums.{{ $parent.$index }}.track.{{ $index }}.number" value="{{ track.number }}"/>
                            <input type="hidden" name="mediums.{{ $parent.$index }}.track.{{ $index }}.name" value="{{ track.title }}"/>
                            <input type="hidden" name="mediums.{{ $parent.$index }}.track.{{ $index }}.length" value="{{ track.length }}"/>
                        </tracks>
                    </discs>
                    <input type="hidden" name="edit_note" value="{{ form.editNote }}"/>
                    <input type="submit" value="Export to MusicBrainz"/>
                </form>
                <div id="search-direct">
                    <a href="{{ link.href }}?query={{ link.query }}&type={{ link.type }}&limit={{ link.limit }}&method={{ link.method }}"
                       title="Direct search uses exact matches only, but provides up to the minute correct results. If the result is empty, modify your search or try the indexed one.">
                       Direct search on MusicBrainz
                    </a>
                </div>
                <div id="search-indexed">
                    <a href="" title=" Search indexes are updated every 3 hours.">Indexed search results</a>
                    <div>
                        <ul data-ng-if="searchIndexed.error === false" data-ng-repeat="release in searchIndexed.releases">
                            <li>
                                {{ release['artist-credit'][0].artist.name }} - {{ release.title }}<br/>
                                Score: {{ release.score }}<br/>
                                Format: <media data-ng-repeat="media in release.media">{{ media.format }} </media>
                            </li>
                        </ul>
                        <span data-ng-if="searchIndexed.error == true">The indexed search was not available.</span>
                    </div>
                </div>
            </div>`
    };
});

goreMbifa.controller('mbifaController', function ($scope, $http, config, dataCollectorService) {
    var data = dataCollectorService.collectData();
    var documentLocationHref = document.location.href.split('?')[0]

    $scope.form = {
        'method': config.form.method,
        'action': config.form.action,
        'acceptCharset': config.form.acceptCharset,
        'primaryType': {
            'name': config.form.primaryType.name,
            'types': config.form.primaryType.types,
            'selectedType': config.form.primaryType.types[0]
        },
        'title': data['title'],
        'artist': data['artist'],
        'status': 'official',
        'releaseDate': data['releaseDate'],
        'label': data['label'],
        'externalLinkType': '77',
        'asin': documentLocationHref,
        'tracklist': data['tracklist'],
        'editNote': config.form.editNode + documentLocationHref
    };

    $scope.link = {
        'href': config.link.href,
        'query': encodeURIComponent(data['title']),
        'type': config.link.type,
        'limit': config.link.limit,
        'method': config.link.method
    };

    $scope.searchIndexed = {
        'releases':{},
        'error': false
    }

    $http({
        method: 'GET',
        url: 'https://musicbrainz.org/ws/2/release?query=' + encodeURIComponent(data['title']) + '&fmt=json'
    }).then(
    function (response) {
        $scope.searchIndexed.releases = response.data.releases;
    },
    function (response) {
        $scope.searchIndexed.error = true;
    });

    jquery('#search-indexed').accordion({
        heightStyle: 'content',
        active: false,
        collapsible: true
    });
});

goreMbifa.service('dataCollectorService', function (config, siteLookupService, languageLookupService) {
    this.collectData = function () {
        var siteSpecificConfig = config.sites[siteLookupService].languages[languageLookupService]

        var title = '';

        if (jquery('#productTitle').length) {
            title = jquery('#productTitle').text().trim();
        } else if (jquery('.buying').length) {
            title = jquery('#btAsinTitle span').clone().find('span').remove().end().html().trim();
        }

        var artist = '';

        if (jquery('.author a').length) {
            artist = jquery('.author a').text().trim();
        } else if (jquery('.buying').length) {
            artist = jquery('.buying span a').html().trim()
        }

        return {
            'title': title,
            'artist': artist,
            'releaseDate': this.collectReleaseDate(siteSpecificConfig),
            'label': this.collectLabel(siteSpecificConfig),
            'tracklist': this.collectTracklist(siteSpecificConfig)
        };
    };

    this.collectReleaseDate = function (siteSpecificConfig) {
        var releaseDate = [];

        var releaseDateElement = jquery('#productDetailsTable li').filter(function () {
            return siteSpecificConfig.regexReleaseDate.test(jquery(this).text());
        });

        var releaseDateMatch = siteSpecificConfig.regexReleaseDate.exec(releaseDateElement.text());

        if (releaseDateMatch) {
            var releaseDateParts = releaseDateMatch[1].replace(/[.,]/g, '').split(' ');

            for (var i = 0; i < siteSpecificConfig.releaseDateOrder.length; i++) {
                if (i == 1) {
                    releaseDate.push(siteSpecificConfig.months[releaseDateParts[siteSpecificConfig.releaseDateOrder[i]]]);
                    continue;
                }

                releaseDate.push(releaseDateParts[siteSpecificConfig.releaseDateOrder[i]]);
            }
        }

        return releaseDate;
    }

    this.collectLabel = function (siteSpecificConfig) {
        var label = '';

        var labelElement = jquery('#productDetailsTable li').filter(function () {
            return siteSpecificConfig.regexReleaseLabel.test(jquery(this).text());
        });

        var labelMatch = siteSpecificConfig.regexReleaseLabel.exec(labelElement.text());

        if (labelMatch) {
            label = labelMatch[1];
        }

        return label;
    }

    this.collectTracklist = function (siteSpecificConfig) {
        var tracklist = { 'discs': [] };
        var disc = 0;
        var tracks = { 'tracks': [] };

        // Amazon has more than one tracklist...
        if (jquery('#dmusic_tracklist_content').length) {
            /*
                Tracklists:
                One Disk: http://www.amazon.de/01-Fl%C3%BCsterer-Remastered-Gabriel-Burns/dp/B00N29D69I
                Multiple Disks: http://www.amazon.de/Book-Souls-limited-Deluxe/dp/B00ZVFYVMM
            */
            var tracklistContent = jquery('#dmusic_tracklist_content tr');

            for (var i = 1; i < tracklistContent.length; i++) {
                if (tracklistContent[i].id == 'dmusic_tracklist_player_disc_' + (disc + 2)) {
                    tracklist['discs'][disc] = tracks;

                    disc++;
                    var tracks = { 'tracks': [] };

                    continue;
                }

                var trackDetails = tracklistContent[i].getElementsByTagName('td');

                if (trackDetails[0].getElementsByClassName('TrackNumber')[0]) {
                    tracks['tracks'].push({
                        'number': trackDetails[0].getElementsByClassName('TrackNumber')[0].textContent.trim(),
                        'title': trackDetails[1].getElementsByClassName('TitleLink')[0].textContent.trim(),
                        'length': trackDetails[2].getElementsByTagName("span")[0].textContent.trim()
                    });
                }
            }
        } else if (jquery('#dmusic_tracklist_player').length) {
            /*
                Tracklists:
                One Disk: http://www.amazon.de/Seventh-Son-Iron-Maiden/dp/B0000251W3
                Multiple Disks: http://www.amazon.de/Deceiver-Gods-Amon-Amarth/dp/B00CEJ2H6K
            */
            var tracklistContent = jquery('#dmusic_tracklist_player .a-row');

            for (var i = 1; i < tracklistContent.length; i++) {
                if (tracklistContent[i].textContent.trim() == siteSpecificConfig.disc + ": " + (disc + 2)) {
                    tracklist['discs'][disc] = tracks;

                    disc++;
                    var tracks = { 'tracks': [] };

                    continue;
                }

                var trackDetails = tracklistContent[i].textContent.split('. ');

                tracks['tracks'].push({
                    'number': trackDetails[0].trim(),
                    'title': trackDetails[1].trim()
                });
            }
        } else if (jquery('#musicTracksFeature').length) {
            /*
                Tracklists:
                One Disk: http://www.amazon.ca/gp/product/B00062PWOQ
                Multiple Disks: http://www.amazon.ca/The-Book-Souls-Deluxe-Hardcover/dp/B00ZVFYVMM
            */

            var tracklistContent = jquery('#musicTracksFeature tr');

            for (var i = 0; i < tracklistContent.length; i++) {
                if (tracklistContent[i].classList.contains('sampleTracksHeader')) {
                    if (i == 0) {
                        continue;
                    }

                    tracklist['discs'][disc] = tracks;

                    disc++;
                    var tracks = { 'tracks': [] };

                    continue;
                }

                if (tracklistContent[i].hasAttribute('class')) {
                    var trackDetails = tracklistContent[i].getElementsByTagName('td')[0].textContent.split('. ');

                    tracks['tracks'].push({
                        'number': trackDetails[0].trim(),
                        'title': trackDetails[1].trim()
                    });
                }
            }
        }

        tracklist['discs'][disc] = tracks;

        return tracklist;
    }
});

goreMbifa.factory('languageLookupService', function () {
    var navLocale = jquery('header').attr('class').split(' ')[1];

    return navLocale.substring(9, 11);
});

goreMbifa.value('siteLookupService', document.domain);