Skip to content

Commit

Permalink
Merge pull request #7 from studiowebux/5-cannot-read-properties-error
Browse files Browse the repository at this point in the history
fix: added error handling, not tested yet
  • Loading branch information
studiowebux authored Mar 30, 2024
2 parents 9d1e3c5 + 5b07f22 commit c10d7e4
Show file tree
Hide file tree
Showing 9 changed files with 422 additions and 166 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ main.js
*.map

# obsidian
data.json
data.json*

# Exclude macOS Finder (System Explorer) View States
.DS_Store
2 changes: 1 addition & 1 deletion src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export async function getCurrentlyPlayingTrack(

try {
const response: RequestUrlResponse = await requestUrl({
url: `${SPOTIFY_API_BASE_ADDRESS}/me/player/currently-playing`,
url: `${SPOTIFY_API_BASE_ADDRESS}/me/player/currently-playing?additional_types=track,episode`,
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
Expand Down
12 changes: 12 additions & 0 deletions src/default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { SpotifyLinkSettings } from "./types";

export const DEFAULT_SETTINGS: SpotifyLinkSettings = {
spotifyClientId: "",
spotifyClientSecret: "",
spotifyScopes: "user-read-currently-playing",
spotifyState: "it-can-be-anything",
templates: [
"**Song Name:** {{ song_name }}\n**Song URL:** {{ song_link }}\n**Album Name:** {{ album }}\n**Album Release Date:** {{ album_release }}\n**Album URL:** {{ album_link }}\n**Cover:** {{ album_cover_medium }}\n**Cover URL:** {{ album_cover_link_medium }}\n**Artists:** {{ artists }}\n**Added at:** *{{ timestamp }}*",
"**Episode Name:** {{ episode_name }}\n**Description:** {{ description }}\n**Added at:** *{{ timestamp }}*",
],
};
88 changes: 88 additions & 0 deletions src/episode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { CurrentlyPlayingTrack, Episode } from "./types";
import { millisToMinutesAndSeconds } from "./utils";

export function isEpisode(data: CurrentlyPlayingTrack) {
return data.item.type === "episode";
}

export function getEpisodeMessageTimestamp(data: CurrentlyPlayingTrack) {
if (!isEpisode(data)) throw new Error("Not an episode.");
const episode = data.item as Episode;

const episode_name = episode?.name;
const description = episode?.description;
const release_date = episode?.release_date;
const progress = data.progress_ms;
const duration = episode.duration_ms;
const url = episode.external_urls.spotify;
return `['**${episode_name}**': ***${description}***, released ${release_date} | **${millisToMinutesAndSeconds(
progress
)}** (${((progress / duration) * 100).toFixed(0)}%)](${url})`;
}

export function getEpisodeMessage(
data: CurrentlyPlayingTrack,
template: string
) {
if (!isEpisode(data)) throw new Error("Not an episode.");
const episode = data.item as Episode;

return template
.replace(/{{ episode_name }}|{{episode_name}}/g, episode.name)
.replace(
/{{ episode_link }}|{{episode_link}}/g,
episode.external_urls.spotify
)
.replace(/{{ description }}|{{description}}/g, episode.description)
.replace(
/{{ duration_ms }}|{{duration_ms}}/g,
episode.duration_ms.toString()
)
.replace(
/{{ audio_preview_url }}|{{audio_preview_url}}/g,
`![Audio preview url](${episode.audio_preview_url})`
)
.replace(
/{{ episode_cover_large }}|{{episode_cover_large}}/g,
`![${episode.name}](${episode.images[0]?.url})`
)
.replace(
/{{ episode_cover_medium }}|{{episode_cover_medium}}/g,
`![${episode.name}](${episode.images[1]?.url})`
)
.replace(
/{{ episode_cover_small }}|{{episode_cover_small}}/g,
`![${episode.name}](${episode.images[2]?.url})`
)
.replace(
/{{ episode_cover_link_large }}|{{episode_cover_link_large}}/g,
episode.images[0].url
)
.replace(
/{{ episode_cover_link_medium }}|{{episode_cover_link_medium}}/g,
episode.images[1]?.url
)
.replace(
/{{ episode_cover_link_small }}|{{episode_cover_link_small}}/g,
episode.images[2]?.url
)
.replace(/{{ release_date }}|{{release_date}}/g, episode.release_date)
.replace(/{{ show_name }}|{{show_name}}/g, episode.show.name)
.replace(/{{ publisher }}|{{publisher}}/g, episode.show.publisher)
.replace(
/{{ show_description }}|{{show_description}}/g,
episode.show.description
)
.replace(
/{{ show_link }}|{{show_link}}/g,
episode.show.external_urls.spotify
)
.replace(
/{{ total_episodes }}|{{total_episodes}}/g,
episode.show.total_episodes.toString()
)
.replace(
/{{ timestamp }}|{{timestamp}}/g,
`${new Date().toDateString()} - ${new Date().toLocaleTimeString()}`
);
}
33 changes: 32 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Editor, Notice, Plugin, addIcon } from "obsidian";
import { SpotifyLinkSettings, SpotifyAuthCallback } from "./types";
import { getSpotifyUrl, handleCallback, requestRefreshToken } from "./api";
import SettingsTab, { DEFAULT_SETTINGS } from "./settingsTab";
import SettingsTab from "./settingsTab";
import { handleEditor, handleTemplateEditor } from "./ui";
import { onLogin, onAutoLogin } from "./events";
import { DEFAULT_SETTINGS } from "./default";

export default class SpotifyLinkPlugin extends Plugin {
settings: SpotifyLinkSettings;
Expand Down Expand Up @@ -92,6 +93,36 @@ export default class SpotifyLinkPlugin extends Plugin {
// USER INTERACTION
//

//
// Episode focused
//

this.addCommand({
id: "append-currently-playing-episode-using-template",
name: "Append Spotify currently playing episode using template",
editorCallback: async (editor: Editor) => {
await handleTemplateEditor(
editor,
this.settings.templates[1],
this.settings.spotifyClientId,
this.settings.spotifyClientSecret
);
},
});
this.addCommand({
id: "append-currently-playing-episode",
name: "Append Spotify currently playing episode with timestamp",
editorCallback: async (editor: Editor) => {
await handleEditor(
editor,
this.settings.spotifyClientId,
this.settings.spotifyClientSecret
);
},
});
//
// Song focused
//
this.addCommand({
id: "append-currently-playing-track-using-template",
name: "Append Spotify currently playing track using template",
Expand Down
93 changes: 28 additions & 65 deletions src/output.ts
Original file line number Diff line number Diff line change
@@ -1,81 +1,44 @@
import { getEpisodeMessage, getEpisodeMessageTimestamp } from "./episode";
import {
getTrackMessage,
getTrackMessageTimestamp,
getTrackType,
} from "./track";
import { CurrentlyPlayingTrack } from "./types";
import { millisToMinutesAndSeconds } from "./utils";

export function processCurrentlyPlayingTrackInput(
data: CurrentlyPlayingTrack
): string {
let message = "";
if (data && data.is_playing) {
message = `['**${data.item.name}**' by ***${data.item.artists
.map((a) => a.name)
.join(", ")}*** **${millisToMinutesAndSeconds(
data.progress_ms
)}** (${(
(data.progress_ms / parseInt(data.item.duration_ms)) *
100
).toFixed(0)}%)](${data.item.external_urls.spotify})`;
} else {
message = "No song is playing.";
if (getTrackType(data) === "track") {
return getTrackMessageTimestamp(data);
}
if (getTrackType(data) === "episode") {
return getEpisodeMessageTimestamp(data);
}

throw new Error(
"The data received is not handle. You can request it by opening a GitHub issue and providing the track URL so that I can adjust the tool accordingly."
);
}
return message;
return "No song is playing.";
}

export function processCurrentlyPlayingTrack(
data: CurrentlyPlayingTrack,
template = `'{{ song_name }}' by {{ artists }} from {{ album }} released in {{ album_release }}\n{{ timestamp }}`
): string {
let message = "";
if (data && data.is_playing) {
message = template
.replace(/{{ song_name }}|{{song_name}}/g, data.item.name)
.replace(
/{{ song_link }}|{{song_link}}/g,
data.item.external_urls.spotify
)
.replace(
/{{ artists }}|{{artist}}/g,
data.item.artists.map((a) => a.name).join(", ")
)
.replace(
/{{ album_release }}|{{album_release}}/g,
data.item.album.release_date
)
.replace(
/{{ album_cover_large }}|{{album_cover_large}}/g,
`![${data.item.album.name}](${data.item.album.images[0].url})`
)
.replace(
/{{ album_cover_medium }}|{{album_cover_medium}}/g,
`![${data.item.album.name}](${data.item.album.images[1]?.url})`
)
.replace(
/{{ album_cover_small }}|{{album_cover_small}}/g,
`![${data.item.album.name}](${data.item.album.images[2]?.url})`
)
.replace(
/{{ album_cover_link_large }}|{{album_cover_link_large}}/g,
data.item.album.images[0].url
)
.replace(
/{{ album_cover_link_medium }}|{{album_cover_link_medium}}/g,
data.item.album.images[1]?.url
)
.replace(
/{{ album_cover_link_small }}|{{album_cover_link_small}}/g,
data.item.album.images[2]?.url
)
.replace(
/{{ album_link }}|{{album_link}}/g,
data.item.album.external_urls.spotify
)
.replace(/{{ album }}|{{album}}/g, data.item.album.name)
.replace(
/{{ timestamp }}|{{timestamp}}/g,
`${new Date().toDateString()} - ${new Date().toLocaleTimeString()}`
);
} else {
message = "No song is playing.";
}
if (getTrackType(data) === "track") {
return getTrackMessage(data, template);
}
if (getTrackType(data) === "episode") {
return getEpisodeMessage(data, template);
}

return message;
throw new Error(
"The data received is not handle. You can request it by opening a GitHub issue and providing the track URL so that I can adjust the tool accordingly."
);
}
return "No song is playing.";
}
53 changes: 41 additions & 12 deletions src/settingsTab.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
import { App, PluginSettingTab, Setting } from "obsidian";
import { SpotifyLinkSettings } from "./types";
import SpotifyLinkPlugin from "./main";

export const DEFAULT_SETTINGS: SpotifyLinkSettings = {
spotifyClientId: "",
spotifyClientSecret: "",
spotifyScopes: "user-read-currently-playing",
spotifyState: "it-can-be-anything",
templates: [],
};

export default class SettingsTab extends PluginSettingTab {
plugin: SpotifyLinkPlugin;

Expand Down Expand Up @@ -101,7 +92,7 @@ export default class SettingsTab extends PluginSettingTab {
href: "https://studiowebux.github.io/obsidian-plugins-docs/docs/spotify-link/custom-template",
text: "Custom Template Documentation",
});
divDoc.createEl("p", { text: "Available variables:" });
divDoc.createEl("p", { text: "Available variables (song):" });
divDoc
.createEl("ul")
.createEl("li", { text: "{{ album }}" })
Expand All @@ -118,10 +109,32 @@ export default class SettingsTab extends PluginSettingTab {
.createEl("li", { text: "{{ song_link }}" })
.createEl("li", { text: "{{ timestamp }}" });

divDoc.createEl("p", { text: "Available variables (podcast):" });
divDoc
.createEl("ul")
.createEl("li", { text: "{{ episode_name }}" })
.createEl("li", { text: "{{ episode_link }}" })
.createEl("li", { text: "{{ description }}" })
.createEl("li", { text: "{{ duration_ms }}" })
.createEl("li", { text: "{{ audio_preview_url }}" })
.createEl("li", { text: "{{ episode_cover_large }}" })
.createEl("li", { text: "{{ episode_cover_medium }}" })
.createEl("li", { text: "{{ episode_cover_small }}" })
.createEl("li", { text: "{{ episode_cover_link_large }}" })
.createEl("li", { text: "{{ episode_cover_link_medium }}" })
.createEl("li", { text: "{{ episode_cover_link_small }}" })
.createEl("li", { text: "{{ release_date }}" })
.createEl("li", { text: "{{ show_name }}" })
.createEl("li", { text: "{{ publisher }}" })
.createEl("li", { text: "{{ show_description }}" })
.createEl("li", { text: "{{ show_link }}" })
.createEl("li", { text: "{{ total_episodes }}" })
.createEl("li", { text: "{{ timestamp }}" });

new Setting(containerEl)
.setName("Template")
.setName("Template for song")
.setDesc(
"Define a custom template to print the currently playing song"
"Define a custom template to print the currently playing song (Song only)"
)
.addTextArea((text) =>
text
Expand All @@ -134,6 +147,22 @@ export default class SettingsTab extends PluginSettingTab {
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName("Template for podcast")
.setDesc(
"Define a custom template to print the currently playing episode (Podcast only)"
)
.addTextArea((text) =>
text
.setPlaceholder(
"Example: '{{ podcast_name }}': {{ description }} released {{ release_date }}\n{{ timestamp }}"
)
.setValue(this.plugin.settings.templates[1])
.onChange(async (value) => {
this.plugin.settings.templates[1] = value;
await this.plugin.saveSettings();
})
);

containerEl.createEl("hr");

Expand Down
Loading

0 comments on commit c10d7e4

Please sign in to comment.