melanie zrewidował ten Gist 8 months ago. Przejdź do rewizji
Brak zmian
melanie zrewidował ten Gist 11 months ago. Przejdź do rewizji
Brak zmian
melanie zrewidował ten Gist 11 months ago. Przejdź do rewizji
1 file changed, 137 insertions
last.fm-to-mastodon.js(stworzono plik)
| @@ -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() | |
Nowsze
Starsze