Last active
October 11, 2022 23:02
-
-
Save OscarPuentee/44cd15156ab2c839c5b4353cb0672552 to your computer and use it in GitHub Desktop.
Scriptable code for the Pokemon shiny hunting iOS widget
This file contains 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
// This script was created by Oscar Puente. | |
// Important notes: | |
// 1. Available colors are black, blue, brown, cyan, green, orange, purple, red, white and yellow. | |
// 2. The language used is the device language. Current languages available are spanish, english and german (added by pabumake). | |
// If your language is not any of those, it defaults to english. | |
// 3. The Pokemon list delimits which pokemon can appear based on their pokedex number. | |
// Support for the 8th generation in the API is currently limited and it may cause errors due to missing info. | |
// It is strongly advised to keep the pokemon list between the first 7 generations (1-807). | |
// 4. The shiny-chance parameter should be a number from 1 to any other number. | |
// The higher the number, the harder to get a shiny pokemon. Set to 1 if you want to see only shiny pokemon. | |
// 5. Any image used as a background must be placed in the iCloud Scriptable folder. | |
// Contact for any comments or doubts: u/Technoir12 | |
var lang = Device.language(); | |
var widgetArgs; | |
if (config.runsInApp) { | |
let alert = new Alert(); | |
alert.title = (lang == "es") ? "Selecciona una acción" : "Choose an action"; | |
alert.addAction((lang == "es") ? "Personalizar widget" : "Customize widget"); | |
alert.addAction((lang == "es") ? "Ver ejemplo" : "View example"); | |
alert.addCancelAction((lang == "es") ? "Cancelar" : "Cancel"); | |
let option = await alert.presentAlert(); | |
if (option == 0){ | |
let imageAlert = new Alert(); | |
imageAlert.title = (lang == "es") ? "Imagen de fondo" : "Background image"; | |
imageAlert.message = (lang == "es") ? "Si no se provee una imagen se utilizarán los fondos default (deben descargarse primero y colocarse en la carpeta de Scriptable)." : "If no image is provided, default backgrounds will be used (must be downloaded first and placed inside the Scriptable folder)."; | |
imageAlert.addAction((lang == "es") ? "Seleccionar de la galería" : "Choose from gallery"); | |
imageAlert.addAction((lang == "es") ? "Utilizar fondos default" : "Use default backgrounds"); | |
imageAlert.addAction((lang == "es") ? "Descargar fondos default" : "Download default backgrounds"); | |
imageAlert.addCancelAction((lang == "es") ? "Cancelar" : "Cancel"); | |
let imageOption = await imageAlert.presentAlert(); | |
switch (imageOption){ | |
case 0: | |
let imageSelected = await Photos.fromLibrary(); | |
let dp = await DocumentPicker.exportImage(imageSelected); | |
var pathElements = dp[0].split("/"); | |
break; | |
case 1: | |
break; | |
case 2: | |
Safari.open("https://mega.nz/folder/tZJXxSDR#gHBnSzCfSdpOR0jdMfhQAA"); | |
break; | |
default: | |
return; | |
} | |
let paramsAlert = new Alert(); | |
paramsAlert.title = (lang == "es") ? "Escribe tus preferencias" : "Write down your preferences"; | |
paramsAlert.message = (lang == "es") ? "El contenido entre paréntesis representa ejemplos de posibles valores para ese parámetro." : "The content between parenthesis represent possible values for that parameter."; | |
paramsAlert.addTextField(((lang == "es") ? "Margen superior" : "Top margin") + " (20)"); | |
paramsAlert.addTextField(((lang == "es") ? "Color del texto" : "Text color") + " (white, black, etc.)"); | |
paramsAlert.addTextField(((lang == "es") ? "Tamaño del texto" : "Text size") + " (small, medium, big)"); | |
paramsAlert.addTextField(((lang == "es") ? "Listado de Pokemon" : "Pokemon list") + " (1-151)"); | |
paramsAlert.addTextField(((lang == "es") ? "Probabilidad Shiny" : "Shiny chance") + " (496)"); | |
paramsAlert.addTextField(((lang == "es") ? "Tamaño del widget" : "Widget size") + " (small, medium)"); | |
paramsAlert.addAction((lang == "es") ? "Listo" : "Done"); | |
paramsAlert.addCancelAction((lang == "es") ? "Cancelar" : "Cancel"); | |
let params = await paramsAlert.presentAlert(); | |
if (params == -1) | |
return; | |
for (i=0; i<6; i++) { | |
if (paramsAlert.textFieldValue(i) == "") | |
throw Error("All parameters are required."); | |
} | |
widgetArgs = paramsAlert.textFieldValue(0) + "|" + | |
paramsAlert.textFieldValue(1) + "|" + | |
paramsAlert.textFieldValue(2) + "|" + | |
paramsAlert.textFieldValue(3) + "|" + | |
paramsAlert.textFieldValue(4) + "|" + | |
paramsAlert.textFieldValue(5); | |
if (pathElements !== undefined){ | |
widgetArgs = widgetArgs + "|" + pathElements[pathElements.length - 1]; | |
} | |
let finalAlert = new Alert(); | |
finalAlert.title = (lang == "es") ? "Estos son tus parámetros" : "These are your parameters"; | |
finalAlert.message = (lang == "es") ? "Agrega un widget de Scriptable en tu pantalla de inicio. En las opciones, agrega el nombre de tu script y pega estos parámetros." : "Add a Scriptable widget to your homescreen. On settings, add the name of your script and paste these parameters."; | |
finalAlert.addTextField("", widgetArgs); | |
finalAlert.addAction((lang == "es") ? "Ver resultado" : "View result"); | |
finalAlert.addCancelAction((lang == "es") ? "Salir" : "Exit"); | |
let final = await finalAlert.presentAlert(); | |
if (final == 1) | |
return; | |
} | |
else if (option == -1){ | |
return; | |
} | |
} | |
if (config.runsInWidget) | |
widgetArgs = args.widgetParameter; | |
//Default parameters for testing | |
if (widgetArgs === undefined) | |
widgetArgs = "25|black|medium|1-650|496|medium"; | |
var argsArray = widgetArgs.split("|"); | |
var argsCount = argsArray.length; | |
if (argsCount < 6 || argsCount > 7) | |
throw new Error("Number of parameters must be beween 6 and 7. " + argsCount + " given."); | |
/* --------------- */ | |
/* Text settings */ | |
/* --------------- */ | |
// Set text color | |
var textColor = argsArray[1]; | |
switch (textColor) { | |
case "black": | |
textColor = Color.black(); | |
break; | |
case "blue": | |
textColor = Color.blue(); | |
break; | |
case "brown": | |
textColor = Color.brown(); | |
break; | |
case "cyan": | |
textColor = Color.cyan(); | |
break; | |
case "green": | |
textColor = Color.green(); | |
break; | |
case "orange": | |
textColor = Color.orange(); | |
break; | |
case "purple": | |
textColor = Color.purple(); | |
break; | |
case "red": | |
textColor = Color.red(); | |
break; | |
case "white": | |
textColor = Color.white(); | |
break; | |
case "yellow": | |
textColor = Color.yellow(); | |
break; | |
default: | |
throw new Error("Invalid color."); | |
} | |
//Set date | |
var today = new Date(); | |
var days, months = []; | |
if (lang == "es") { | |
days = ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado']; | |
months = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']; | |
} | |
else if (lang == "de"){ | |
days = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag']; | |
months = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'July', 'August', 'September', 'Oktober', 'November', 'Dezember']; | |
} | |
else { | |
days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; | |
months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; | |
} | |
var currentWeekday = days[today.getDay()]; | |
var currentMonth = months[today.getMonth()]; | |
var currentDay = today.getDate(); | |
var hour = today.getHours(); | |
var fullDate = currentMonth + " " + currentDay; | |
/* --------------- */ | |
/* Pokemon code */ | |
/* --------------- */ | |
var pokemonLimits = argsArray[3].split("-"); | |
var randomPoke = Math.floor(Math.random() * (parseInt(pokemonLimits[1]) - parseInt(pokemonLimits[0]))) + parseInt(pokemonLimits[0]); | |
var shinyChance = argsArray[4]; | |
var shinyResult = Math.floor(Math.random() * shinyChance); | |
var isShiny = false; | |
if (shinyResult == 0) | |
isShiny = true; | |
const r = new Request("https://pokeapi.co/api/v2/pokemon/" + randomPoke); | |
var apiResult = await r.loadJSON(); | |
var pokemon = []; | |
pokemon.name = apiResult.name.charAt(0).toUpperCase() + apiResult.name.slice(1); | |
pokemon.sprite = (apiResult.sprites.versions["generation-v"]["black-white"].front_default != null) | |
? apiResult.sprites.versions["generation-v"]["black-white"].front_default | |
: apiResult.sprites.versions["generation-vii"]["ultra-sun-ultra-moon"].front_default; | |
pokemon.type = apiResult.types[0].type.name; | |
if (isShiny) | |
pokemon.sprite = apiResult.sprites.front_shiny; | |
var sprRequest = new Request(pokemon.sprite); | |
pokemon.sprite = await sprRequest.loadImage(); | |
/* ---------------- */ | |
/* Background image */ | |
/* ---------------- */ | |
var scriptablePath = "/var/mobile/Library/Mobile Documents/iCloud~dk~simonbs~Scriptable/Documents/"; | |
var imageName, imageFullPath; | |
var widgetSize = argsArray[5]; | |
if (argsCount == 7) | |
imageName = argsArray[6]; | |
else { | |
if (widgetSize == "small") { | |
if (hour >= 6 && hour < 18) | |
imageName = "poke_small_day.JPG"; | |
else | |
imageName = "poke_small_night.JPG"; | |
} else { | |
if (hour >= 6 && hour < 18) { | |
switch(pokemon.type) { | |
case "rock": | |
imageName = "rock_day.JPG"; | |
break; | |
case "ground": | |
imageName = "rock_day.JPG"; | |
break; | |
case "bug": | |
imageName = "bug_day.JPG"; | |
break; | |
case "ice": | |
imageName = "ice_day.JPG"; | |
break; | |
case "water": | |
imageName = "water_day.JPG"; | |
break; | |
case "ghost": | |
imageName = "ghost_day.JPG"; | |
break; | |
case "dark": | |
imageName = "ghost_day.JPG"; | |
break; | |
case "steel": | |
imageName = "rock_day.JPG"; | |
break; | |
default: | |
imageName = "poke_day.JPG"; | |
break; | |
} | |
} | |
else { | |
switch(pokemon.type) { | |
case "rock": | |
imageName = "rock_night.JPG"; | |
break; | |
case "ground": | |
imageName = "rock_night.JPG"; | |
break; | |
case "bug": | |
imageName = "bug_night.JPG"; | |
break; | |
case "ice": | |
imageName = "ice_night.JPG"; | |
break; | |
case "water": | |
imageName = "water_night.JPG"; | |
break; | |
case "ghost": | |
imageName = "ghost_night.JPG"; | |
break; | |
case "dark": | |
imageName = "ghost_night.JPG"; | |
break; | |
case "steel": | |
imageName = "rock_night.JPG"; | |
break; | |
default: | |
imageName = "poke_night.JPG"; | |
break; | |
} | |
} | |
} | |
} | |
imagePath = scriptablePath + imageName; | |
var fm = FileManager.iCloud(); | |
if (fm.fileExists(imagePath)) { | |
//Download image from iCloud if it exists but it's not downloaded | |
if (!fm.isFileDownloaded(imagePath)) { | |
fm.downloadFileFromiCloud(imagePath); | |
} | |
} else { | |
throw new Error("Image not found. Remember that file name AND format are case-sensitive."); | |
} | |
/* --------------- */ | |
/* Widget Creation */ | |
/* --------------- */ | |
var pokemonWidget = new ListWidget(); | |
//Top margin | |
var spacing = parseInt(argsArray[0]); | |
pokemonWidget.addSpacer(spacing); | |
var fontSize = argsArray[2]; | |
var fontSizeValues = [10,14]; | |
if (fontSize == "medium") | |
fontSizeValues = [12, 16]; | |
else if (fontSize == "big") | |
fontSizesValues = [14, 24]; | |
// Add shiny icon to text | |
if (isShiny) | |
fullDate = fullDate + " \u2728"; | |
// Weekday label | |
var weekdayLabel = pokemonWidget.addText(currentWeekday); | |
weekdayLabel.font = Font.systemFont(fontSizeValues[0]); | |
weekdayLabel.textColor = textColor; | |
// Date label | |
var dateLabel = pokemonWidget.addText(fullDate); | |
dateLabel.font = Font.boldSystemFont(fontSizeValues[1]); | |
dateLabel.textColor = textColor; | |
// Background image | |
pokemonWidget.backgroundImage = Image.fromFile(imagePath); | |
// Pokemon sprite | |
if (widgetSize == "small") { | |
pokemonWidget.addSpacer(20); | |
var widgetImg = pokemonWidget.addImage(pokemon.sprite); | |
widgetImg.centerAlignImage(); | |
pokemonWidget.setPadding(0, 10, 0, 0); | |
} | |
else { | |
var widgetImg = pokemonWidget.addImage(pokemon.sprite); | |
widgetImg.rightAlignImage(); | |
pokemonWidget.setPadding(0, 25, 0, 10); | |
} | |
widgetImg.imageSize = new Size(100, 100); | |
pokemonWidget.url = "https://pokemondb.net/pokedex/" + pokemon.name; | |
if (widgetSize == "small") | |
pokemonWidget.presentSmall(); | |
else | |
pokemonWidget.presentMedium(); | |
Script.setWidget(pokemonWidget); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment