Последняя активность 1732922294

Версия 34e718be1524d252458c76c94c3c205106cd5ec2

last.fm-to-mastodon.js Исходник
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
20const LASTFM_URL_IN_VALUE = 'LASTFM_URL_IN_VALUE'
21const 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
33const LASTFM_USERNAME = ''
34const LASTFM_API_KEY = ''
35const MASTODON_INSTANCE = '' // ie: social.lol
36const MASTODON_TOKEN = ''
37const FIND_FIELD_BY = LASTFM_URL_IN_VALUE // or LASTFM_IN_NAME
38
39// More Script Constants
40// - You can ignore this too
41
42const LASTFM_API = `http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${LASTFM_USERNAME}&api_key=${LASTFM_API_KEY}&format=json&limit=1`
43const MASTODON_GET_ACCOUNT_API = `https://${MASTODON_INSTANCE}/api/v1/accounts/verify_credentials`
44const MASTODON_UPDATE_FIELDS_API = `https://${MASTODON_INSTANCE}/api/v1/accounts/update_credentials`
45const MASTODON_HEADERS = {
46 'Content-Type': 'application/json',
47 Authorization: `Bearer ${MASTODON_TOKEN}`,
48}
49
50// Last FM Related Functions
51
52function 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
62async 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
71function 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
82function 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
91async 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
102async 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
137await updateMastodonField()
138