melanie ha revisionato questo gist 7 months ago. Vai alla revisione
Nessuna modifica
melanie ha revisionato questo gist 10 months ago. Vai alla revisione
Nessuna modifica
melanie ha revisionato questo gist 10 months ago. Vai alla revisione
1 file changed, 137 insertions
last.fm-to-mastodon.js(file creato)
| @@ -0,0 +1,137 @@ | |||
| 1 | + | // Variables used by Scriptable. | |
| 2 | + | // These must be at the very top of the file. Do not edit. | |
| 3 | + | // icon-color: pink; icon-glyph: headphones-alt; | |
| 4 | + | // Last.fm to Mastodon | |
| 5 | + | // by @zicklepop@nyan.lol | |
| 6 | + | // | |
| 7 | + | // Set a profile field to your currently playing track | |
| 8 | + | // | |
| 9 | + | // Requirements: | |
| 10 | + | // - API Key from Last.fm: https://www.last.fm/api | |
| 11 | + | // - Token from Mastodon with permission scopes for: | |
| 12 | + | // `read:account` and `write:account` | |
| 13 | + | // - Find it on your Mastodon instance website under | |
| 14 | + | // Settings -> Development -> New Application | |
| 15 | + | ||
| 16 | + | // Script Constants | |
| 17 | + | // - Ignore, just defining before use | |
| 18 | + | // Continue down to config | |
| 19 | + | ||
| 20 | + | const LASTFM_URL_IN_VALUE = 'LASTFM_URL_IN_VALUE' | |
| 21 | + | const LASTFM_IN_NAME = 'LASTFM_IN_NAME' | |
| 22 | + | ||
| 23 | + | // Config | |
| 24 | + | // - Put in your details below | |
| 25 | + | // - Find Field By: | |
| 26 | + | // - When set to LASTFM_URL_IN_VALUE the script will | |
| 27 | + | // look for a last.fm url in a field value and set | |
| 28 | + | // the title of the field to the current track | |
| 29 | + | // - When set to LASTFM_IN_NAME the script will look | |
| 30 | + | // for a field title that is `last.fm` (case-insenstive) | |
| 31 | + | // and set the value to the current track | |
| 32 | + | ||
| 33 | + | const LASTFM_USERNAME = '' | |
| 34 | + | const LASTFM_API_KEY = '' | |
| 35 | + | const MASTODON_INSTANCE = '' // ie: social.lol | |
| 36 | + | const MASTODON_TOKEN = '' | |
| 37 | + | const FIND_FIELD_BY = LASTFM_URL_IN_VALUE // or LASTFM_IN_NAME | |
| 38 | + | ||
| 39 | + | // More Script Constants | |
| 40 | + | // - You can ignore this too | |
| 41 | + | ||
| 42 | + | const LASTFM_API = `http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${LASTFM_USERNAME}&api_key=${LASTFM_API_KEY}&format=json&limit=1` | |
| 43 | + | const MASTODON_GET_ACCOUNT_API = `https://${MASTODON_INSTANCE}/api/v1/accounts/verify_credentials` | |
| 44 | + | const MASTODON_UPDATE_FIELDS_API = `https://${MASTODON_INSTANCE}/api/v1/accounts/update_credentials` | |
| 45 | + | const MASTODON_HEADERS = { | |
| 46 | + | 'Content-Type': 'application/json', | |
| 47 | + | Authorization: `Bearer ${MASTODON_TOKEN}`, | |
| 48 | + | } | |
| 49 | + | ||
| 50 | + | // Last FM Related Functions | |
| 51 | + | ||
| 52 | + | function formatTrackString(track) { | |
| 53 | + | const { artist, album, name } = track | |
| 54 | + | const albumName = album['#text'] | |
| 55 | + | const artistName = artist['#text'] | |
| 56 | + | ||
| 57 | + | // If you want to change the format of the track | |
| 58 | + | // value, you would do it here. | |
| 59 | + | return `${artistName} - ${albumName} - ${name}` | |
| 60 | + | } | |
| 61 | + | ||
| 62 | + | async function getLatestTrack() { | |
| 63 | + | const res = new Request(LASTFM_API) | |
| 64 | + | const data = await res.loadJSON() | |
| 65 | + | const track = data.recenttracks.track[0] | |
| 66 | + | return formatTrackString(track) | |
| 67 | + | } | |
| 68 | + | ||
| 69 | + | // Mastodon Related Functions | |
| 70 | + | ||
| 71 | + | function findProfileField(el, i) { | |
| 72 | + | const { name, value } = el | |
| 73 | + | if (FIND_FIELD_BY === LASTFM_URL_IN_VALUE) { | |
| 74 | + | return value.toLowerCase().indexOf('last.fm/user/') >= 0 | |
| 75 | + | } | |
| 76 | + | if (FIND_FIELD_BY === LASTFM_IN_NAME) { | |
| 77 | + | return name.toLowerCase().indexOf('last.fm') >= 0 | |
| 78 | + | } | |
| 79 | + | return false | |
| 80 | + | } | |
| 81 | + | ||
| 82 | + | function buildFieldParams(fields) { | |
| 83 | + | return fields.reduce((out, { name, value }, index) => { | |
| 84 | + | const prefix = index === 0 ? '?' : '&' | |
| 85 | + | return `${out}${prefix}fields_attributes[${index}][name]=${encodeURIComponent( | |
| 86 | + | name | |
| 87 | + | )}&fields_attributes[${index}][value]=${encodeURIComponent(value)}` | |
| 88 | + | }, '') | |
| 89 | + | } | |
| 90 | + | ||
| 91 | + | async function getFields() { | |
| 92 | + | const res = new Request(MASTODON_GET_ACCOUNT_API) | |
| 93 | + | res.headers = MASTODON_HEADERS | |
| 94 | + | const data = await res.loadJSON() | |
| 95 | + | const { source } = data | |
| 96 | + | const { fields } = source | |
| 97 | + | const targetField = fields.find(findProfileField) | |
| 98 | + | const index = fields.indexOf(targetField) | |
| 99 | + | return { index, fields } | |
| 100 | + | } | |
| 101 | + | ||
| 102 | + | async function updateMastodonField() { | |
| 103 | + | const latestTrack = await getLatestTrack() | |
| 104 | + | const { fields, index } = await getFields() | |
| 105 | + | let hasChange = false | |
| 106 | + | ||
| 107 | + | if (FIND_FIELD_BY === LASTFM_URL_IN_VALUE) { | |
| 108 | + | if (fields[index].name !== latestTrack) { | |
| 109 | + | hasChange = true | |
| 110 | + | fields[index].name = latestTrack | |
| 111 | + | } | |
| 112 | + | } | |
| 113 | + | if (FIND_FIELD_BY === LASTFM_IN_NAME) { | |
| 114 | + | if (fields[index].value !== latestTrack) { | |
| 115 | + | hasChange = true | |
| 116 | + | fields[index].value = latestTrack | |
| 117 | + | } | |
| 118 | + | } | |
| 119 | + | ||
| 120 | + | if (hasChange) { | |
| 121 | + | const apiUrl = `${MASTODON_UPDATE_FIELDS_API}${buildFieldParams(fields)}` | |
| 122 | + | const res = new Request(apiUrl) | |
| 123 | + | res.headers = MASTODON_HEADERS | |
| 124 | + | res.method = 'PATCH' | |
| 125 | + | const data = await res.loadJSON() | |
| 126 | + | ||
| 127 | + | if (data.error) { | |
| 128 | + | console.log(`Error: ${data.error}`) | |
| 129 | + | } else { | |
| 130 | + | console.log('Updated') | |
| 131 | + | } | |
| 132 | + | } else { | |
| 133 | + | console.log('No change') | |
| 134 | + | } | |
| 135 | + | } | |
| 136 | + | ||
| 137 | + | await updateMastodonField() | |
Più nuovi
Più vecchi