Forked from aashrith825/Scriptable widget Harry potter
Last active
December 30, 2021 06:59
-
-
Save brainno722/66d14789f1ff6158a2cdb314a5546345 to your computer and use it in GitHub Desktop.
Scriptable widget with custom font, greetings, calendar events, football api, Fitbit api and Unsplash images
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Variables used by Scriptable. | |
// These must be at the very top of the file. Do not edit. | |
// icon-color: deep-purple; icon-glyph: image; | |
// download harrypotter font from fontspace.com/phoenix-phonts and install it using fontcase app | |
/* | |
* Change the widget values and test out the widget in this section. | |
* =================================================================== | |
*/ | |
const IMAGE_SOURCE = "Unsplash" | |
const TERMS = "Harry-Potter-Dark" | |
// Change to true to update widget background image | |
const FORCE_IMAGE_UPDATE = false | |
// Change to true to see a preview of your widget. | |
const testMode = true | |
// Optionally specify the size of your widget preview. | |
const widgetSize = "large" | |
// Change to false to show the date only. | |
const showEvents = true | |
// Specify how many events to show. | |
const numberOfEvents = 2 | |
// Can be top, middle, or bottom. | |
const verticalAlignment = "top" | |
// Can be left, center, or right. | |
const horizontalAlignment = "left" | |
// Use iosfonts.com, or change to "" for the system font. | |
const GreetingFont = "Harryp" | |
const fontName = "futura-Medium" | |
// Find colors on htmlcolorcodes.com | |
const fontColor = new Color("#ffffff") | |
const greetingColor = new Color ("#daa520") | |
const stepsColor = new Color ("#e1af33") | |
// Change the font sizes for elements. | |
const GreetingFontSize = 42 | |
const DateSize = 24 | |
const footballFontSize = 20 | |
const stepsFontSize = 20 | |
const eventTitleSize = 18 | |
const eventTimeSize = 12 | |
// football variables | |
const footballAuthToken = <insert your api auth token from football-data.org>; | |
const myTeamName = 'FC Barcelona'; | |
const myTeamId = 81; | |
// fitbit steps variables | |
const stepsGoal = 10000 | |
const userId = <insert fitbit userid here>; | |
const fitbitAuthToken = <insert your api oauth2 token generated from fitbit api here>; | |
// greeting wiget initializations | |
let widgetHello = new ListWidget(); | |
var today = new Date(); | |
let df = new DateFormatter() | |
df.dateFormat = "yyyy-MM-dd" | |
// fitbit date variable | |
let activityDate = df.string(today) | |
// Long-form days and months | |
var days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']; | |
var months = ['January','February','March','April','May','June','July','August','September','October','November','December']; | |
// Greetings arrays per time period. | |
var greetingsMorning = [ | |
'Good Morning Muggle.' | |
]; | |
var greetingsAfternoon = [ | |
'Good Afternoon.' | |
]; | |
var greetingsEvening = [ | |
'Good Evening Muggle.' | |
]; | |
var greetingsNight = [ | |
'Bedtime.' | |
]; | |
var greetingsLateNight = [ | |
'Go to sleep Muggle!' | |
]; | |
// Holiday customization | |
var holidaysByKey = { | |
// month,week,day: datetext | |
"11,4,4": "Happy Thanksgiving!" | |
} | |
var holidaysByDate = { | |
// month,date: greeting | |
"1,1": "Happy " + (today.getFullYear()).toString() + "!", | |
"10,31": "Happy Halloween!", | |
"12,12": "Happy Birthday!", | |
"12,25": "Merry Christmas!" | |
} | |
var holidayKey = (today.getMonth() + 1).toString() + "," + (Math.ceil(today.getDate() / 7)).toString() + "," + (today.getDay()).toString(); | |
var holidayKeyDate = (today.getMonth() + 1).toString() + "," + (today.getDate()).toString(); | |
// Date Calculations | |
var g_weekday = days[ today.getDay() ]; | |
var g_month = months[ today.getMonth() ]; | |
var g_date = today.getDate(); | |
var g_hour = today.getHours(); | |
// Append ordinal suffix to date | |
function ordinalSuffix(input) { | |
if (input % 10 == 1 && g_date != 11) { | |
return input.toString() + "st"; | |
} else if (input % 10 == 2 && g_date != 12) { | |
return input.toString() + "nd"; | |
} else if (input % 10 == 3 && g_date != 13) { | |
return input.toString() + "rd"; | |
} else { | |
return input.toString() + "th"; | |
} | |
} | |
// Generate date string | |
var datefull = g_weekday + ", " + g_month + " " + ordinalSuffix(g_date); | |
function randomGreeting(greetingArray) { | |
return Math.floor(Math.random() * greetingArray.length); | |
} | |
var greeting = new String("Howdy.") | |
if (g_hour < 5 && g_hour >= 1) { // 1am - 5am | |
greeting = greetingsLateNight[randomGreeting(greetingsLateNight)]; | |
} else if (g_hour >= 23 || g_hour < 1) { // 11pm - 1am | |
greeting = greetingsNight[randomGreeting(greetingsNight)]; | |
} else if (g_hour < 12) { // Before noon (5am - 12pm) | |
greeting = greetingsMorning[randomGreeting(greetingsMorning)]; | |
} else if (g_hour >= 12 && g_hour < 16) { // 12pm - 5pm | |
greeting = greetingsAfternoon[randomGreeting(greetingsAfternoon)]; | |
} else if (g_hour >= 16 && g_hour < 23) { // 5pm - 11pm | |
greeting = greetingsEvening[randomGreeting(greetingsEvening)]; | |
} | |
// Overwrite greeting if calculated holiday | |
if (holidaysByKey[holidayKey]) { | |
greeting = holidaysByKey[holidayKey]; | |
} | |
// Overwrite all greetings if specific holiday | |
if (holidaysByDate[holidayKeyDate]) { | |
greeting = holidaysByDate[holidayKeyDate]; | |
} | |
// creates fitbit data | |
let activities = await loadActivities(userId,fitbitAuthToken) | |
async function createSteps(activities) { | |
let summary = activities | |
var monLoc = [ | |
'Gryffindor House.' | |
]; | |
var tueLoc = [ | |
'Quidditch Grounds.' | |
]; | |
var wedLoc = [ | |
'Hagrids hut.' | |
]; | |
var thuLoc = [ | |
'Room of Requirement.' | |
]; | |
var friLoc = [ | |
'Hogsmeade!', | |
'Three Broomsticks!', | |
'honey dukes!' | |
]; | |
var weekendLoc = [ | |
'Forbidden Forest!' | |
]; | |
function randomLoc(LocArray) { | |
return Math.floor(Math.random() * LocArray.length); | |
} | |
var locGoal = new String("Howdy.") | |
if (g_weekday == 'Monday') { | |
locGoal = monLoc[randomLoc(monLoc)]; | |
} else if (g_weekday == 'Tuesday') { | |
locGoal = tueLoc[randomLoc(tueLoc)]; | |
} else if (g_weekday == 'Wednesday') { | |
locGoal = wedLoc[randomLoc(wedLoc)]; | |
} else if (g_weekday == 'Thursday') { | |
locGoal = thuLoc[randomLoc(thuLoc)]; | |
} else if (g_weekday == 'Friday') { | |
locGoal = friLoc[randomLoc(friLoc)]; | |
} else if (g_weekday == 'Saturday'||g_weekday == 'Sunday') { | |
locGoal = weekendLoc[randomLoc(weekendLoc)]; | |
} | |
let steps1 = summary["steps"] | |
let stepsLeft = stepsGoal-steps1 | |
let stepsText = "..."+stepsLeft+" paces to "+locGoal | |
return stepsText | |
} | |
// function creates match data | |
let matches = await loadMatches(myTeamId,footballAuthToken) | |
if (matches.length > 0) { | |
async function createWidget(matches) { | |
let match = matches[0] | |
let rawDate = match["utcDate"] | |
let date = new Date(Date.parse(rawDate)) | |
let justDate = date.getDate(); | |
let dateFormatter = new DateFormatter() | |
dateFormatter.dateFormat = "h:mm a" | |
let strTime = dateFormatter.string(date) | |
function ordinalSuffix(input) { | |
if (input % 10 == 1 && justDate != 11) { | |
return input.toString() + "st"; | |
} else if (input % 10 == 2 && justDate != 12) { | |
return input.toString() + "nd"; | |
} else if (input % 10 == 3 && justDate != 13) { | |
return input.toString() + "rd"; | |
} else { | |
return input.toString() + "th"; | |
} | |
} | |
let homeTeam = match.homeTeam.name | |
let awayTeam = match.awayTeam.name | |
let OtherTeam = new String("Howdy.") | |
if(homeTeam = myTeamName){ | |
OtherTeam = awayTeam; | |
} | |
else { | |
OtherTeam = homeTeam; | |
} | |
let nextmatchtext = "Plays "+OtherTeam+ " on " + ordinalSuffix(justDate) + " at " +strTime | |
return nextmatchtext | |
} | |
} | |
// Store current datetime | |
const date = new Date() | |
// If we're in the widget or testing, build the widget. | |
if (config.runsInWidget || testMode){ | |
let widget = new ListWidget() | |
let files = FileManager.local() | |
const path = files.documentsDirectory() + "/calendar_widget.jpg" | |
const modificationDate = files.modificationDate(path) | |
// Download image if it doesn't exist, wasn't created today, or update is forced | |
if (!modificationDate || !sameDay(modificationDate,date) || FORCE_IMAGE_UPDATE) { | |
try { | |
let img = await provideImage(IMAGE_SOURCE,TERMS) | |
files.writeImage(path,img) | |
widget.backgroundImage = img | |
} catch { | |
widget.backgroundImage = files.readImage(path) | |
} | |
} else | |
{ | |
widget.backgroundImage = files.readImage(path) | |
} | |
let gradient = new LinearGradient() | |
gradient.colors = [new Color("#000000",0.5), new Color("#000000",0.4)] | |
gradient.locations = [0,0.9] | |
widget.backgroundGradient = gradient | |
// Add text to widget | |
if (verticalAlignment == "middle" || verticalAlignment == "bottom") { widget.addSpacer() } | |
// Store all of the events in widgettext. | |
let widgetText = [] | |
widget.addSpacer(4) | |
// push greetings to widget | |
let hello = widget.addText(greeting); | |
hello.font = provideFont(GreetingFont,GreetingFontSize) | |
hello.textColor = greetingColor; | |
widget.addSpacer(2) | |
// push Date to widget | |
let datetext = widget.addText(datefull); | |
datetext.font = provideFont(GreetingFont,DateSize); | |
datetext.textColor = fontColor; | |
widget.addSpacer(10) | |
// push Match info to widget | |
if(matches.length > 0) { | |
let gametime = await createWidget(matches); | |
let imgURL = "https://i.ibb.co/BGtkZWZ/fc-barcelona-png-logo-5903.png" | |
let imgReq = new Request(imgURL) | |
let img = await imgReq.loadImage() | |
let stack1 = widget.addStack() | |
stack1.centerAlignContent() | |
stack1.setPadding(0, -8, 0, 0) | |
let logo = stack1.addImage(img) | |
logo.imageSize = new Size(40,40) | |
stack1.url = "https://onefootball.com/en/team/barcelona-5/fixtures" | |
let matchstyle = stack1.addText(gametime) | |
matchstyle.font = provideFont(GreetingFont,footballFontSize); | |
matchstyle.textColor = fontColor; | |
matchstyle.centerAlignText() | |
widget.addSpacer(12) | |
} | |
// create and push events data to widget | |
// Format the date info | |
let df = new DateFormatter() | |
df.dateFormat = "EEEE" | |
// Add events if we're supposed to. | |
if (showEvents) { | |
// Only show events that aren't all day or canceled. | |
const events = await CalendarEvent.today([]) | |
let shownEvents = [] | |
for (const event of events) { | |
if (shownEvents.length == numberOfEvents) { break } | |
if (event.startDate.getTime() > date.getTime() && !event.isAllDay && !event.title.startsWith("Canceled:")) { | |
shownEvents.push(event) | |
} | |
} | |
// Format the text for each event. | |
for (const shownEvent of shownEvents) { | |
widget.addSpacer(12) | |
let title = widget.addText(shownEvent.title) | |
title.font = provideFont(GreetingFont,eventTitleSize) | |
widgetText.push(title) | |
widget.addSpacer(7) | |
let time = widget.addText(formatTime(shownEvent.startDate)) | |
time.font = provideFont(fontName,eventTimeSize) | |
widgetText.push(time) | |
} | |
} | |
// Format the text for all events text. | |
for (const textItem of widgetText) { | |
textItem.textColor = fontColor | |
textItem.url = "calshow://" | |
if (horizontalAlignment == "right") { textItem.rightAlignText() } | |
else if (horizontalAlignment == "center") { textItem.centerAlignText() } | |
else { textItem.leftAlignText() } | |
} | |
if (verticalAlignment == "top" || verticalAlignment == "middle") { widget.addSpacer() } | |
// Add fitbit text to widget | |
let stack2 = widget.addStack() | |
stack2.bottomAlignContent() | |
stack2.addSpacer() | |
let stepsWidget = await createSteps(activities); | |
let stepsLeft = stack2.addText(stepsWidget) | |
stepsLeft.url = "fitbit://" | |
stepsLeft.font = provideFont(GreetingFont,stepsFontSize); | |
stepsLeft.textColor = stepsColor; | |
stepsLeft.rightAlignText() | |
Script.setWidget(widget) | |
if (testMode) { | |
let widgetSizeFormat = widgetSize.toLowerCase() | |
if (widgetSizeFormat == "small") {widget.presentSmall()} | |
if (widgetSizeFormat == "medium") {widget.presentMedium()} | |
if (widgetSizeFormat == "large") {widget.presentLarge()} | |
} | |
Script.complete() | |
} | |
else { | |
Script.complete() | |
} | |
/* | |
* Helper functions | |
* ================ | |
*/ | |
// Retieve football data | |
async function loadMatches(TEAMID,TOKEN) { | |
let url = 'http://api.football-data.org/v2/teams/'+TEAMID+'/matches?status=SCHEDULED' | |
let req = new Request(url); | |
req.headers = { 'X-Auth-Token': TOKEN}; | |
let json = await req.loadJSON(); | |
return json.matches; | |
} | |
// Retieve fitbit data | |
async function loadActivities(USERID,TOKEN) { | |
let url = 'https://api.fitbit.com/1/user/'+USERID+'/activities/date/'+activityDate+'.json' | |
let req = new Request(url); | |
req.headers = { 'Authorization': TOKEN}; | |
let json = await req.loadJSON(); | |
return json.summary; | |
} | |
// Retrieve Unsplash or bing image | |
async function provideImage(source,terms) { | |
if (source == "Bing") { | |
const url = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US" | |
const req = new Request(url) | |
const json = await req.loadJSON() | |
const imgURL = "http://bing.com" + json.images[0].url | |
const img = await downloadImage(imgURL) | |
const rect = new Rect(-78,0,356,200) | |
return cropImage(img, rect) | |
} else if (source == "Unsplash") { | |
const img = await downloadImage("https://source.unsplash.com/featured/500x500/?"+terms) | |
return img | |
} | |
} | |
// Helper function to download images | |
async function downloadImage(url) { | |
const req = new Request(url) | |
return await req.loadImage() | |
} | |
// Crop an image into a rect | |
function cropImage(img,rect) { | |
let draw = new DrawContext() | |
draw.respectScreenScale = true | |
draw.drawImageInRect(img,rect) | |
return draw.getImage() | |
} | |
function cropImage(img,rect) { | |
let draw = new DrawContext() | |
draw.size = new Size(rect.width, rect.height) | |
draw.drawImageAtPoint(img,new Point(-rect.x, -rect.y)) | |
return draw.getImage() | |
} | |
// Provide the specified font. | |
function provideFont(fontName,fontSize) { | |
if (fontName == "" || fontName == null) { | |
return Font.regularSystemFont(fontSize) | |
} else { | |
return new Font(fontName,fontSize) | |
} | |
} | |
// Formats the times under each event | |
function formatTime(date) { | |
let df = new DateFormatter() | |
df.useNoDateStyle() | |
df.useShortTimeStyle() | |
return df.string(date) | |
} | |
// Determines if two dates occur on the same day | |
function sameDay(d1, d2) { | |
return d1.getFullYear() === d2.getFullYear() && | |
d1.getMonth() === d2.getMonth() && | |
d1.getDate() === d2.getDate() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment