AppleScript YouTube

[Youtube API]チャンネルIDからチャンネルのアップロードビデオを取得する


【スクリプトエディタで開く】|

#!/usr/bin/env osascript
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
(*
API
https://developers.google.com/youtube/v3
コンソール
https://console.cloud.google.com/apis/dashboard?pli=1
*)
# com.cocolog-nifty.quicktimer.icefloe
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
use framework "Foundation"
use AppleScript version "2.8"
use scripting additions

property refMe : a reference to current application

############設定項目 
####API ID
property strAPIkey : "XXXXXXXXXXXXXXXXXXXXXXX" as text

####################################
property numMaxResults : 10 as number
####################################

set strURL to ("https://www.youtube.com/channel/UCQ6Br7m6vP61FZvjv4lwR5w") as text

######

set ocidURLString to refMe's NSString's stringWithString:(strURL)
set ocidURL to refMe's NSURL's alloc()'s initWithString:(ocidURLString)
set strChannelID to ocidURL's lastPathComponent() as text

##################################################
#チャンネルIDからアップロードビデオのリストID
set ocidUploadsListID to doChannelId2UploadsListID(strChannelID)
log ocidUploadsListID as text
##################################################
#アップロードビデオのplaylistIDからアップロードビデオの詳細
set ocidItemsArray to doGetPlistID2ItemsArray(ocidUploadsListID)
########################
##HTML生成開始
########################
##Header に渡すエレメント
set ocidSetHeaderElement to refMe's NSXMLElement's elementWithName:("div")
set ocidH3Element to refMe's NSXMLElement's elementWithName:("h3")
set ocidAElement to refMe's NSXMLElement's elementWithName:("a")
set strSetValue to ("https://www.youtube.com/playlist?list=" & (ocidUploadsListID as text)) as text
set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("href") stringValue:(strSetValue))
(ocidAElement's addAttribute:(ocidAddNode))
set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("target") stringValue:("_blank"))
(ocidAElement's addAttribute:(ocidAddNode))
set strSetValue to ("YouTUBE PlayList: " & (ocidUploadsListID as text)) as text
(ocidAElement's setStringValue:(strSetValue))
ocidH3Element's addChild:(ocidAElement)
ocidSetHeaderElement's addChild:(ocidH3Element)
########################
#footerに渡すエレメント
set ocidSetFooterElement to refMe's NSXMLElement's elementWithName:("div")
set ocidAElement to refMe's NSXMLElement's elementWithName:("a")
set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("href") stringValue:("https://quicktimer.cocolog-nifty.com/"))
(ocidAElement's addAttribute:(ocidAddNode))
set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("target") stringValue:("_blank"))
(ocidAElement's addAttribute:(ocidAddNode))
set strContents to ("AppleScriptで生成しました") as text
(ocidAElement's setStringValue:(strContents))
ocidSetFooterElement's addChild:(ocidAElement)
########################
#Articleに渡すエレメント
set ocidSetArticleElement to refMe's NSXMLElement's elementWithName:("div")
set ocidH3Element to refMe's NSXMLElement's elementWithName:("h6")
(ocidH3Element's setStringValue:("ビデオ一覧"))
ocidSetArticleElement's addChild:(ocidH3Element)
########################
#テーブル部生成開始
set ocidTableElement to refMe's NSXMLElement's elementWithName:("table")
#####【caption】
set ocidCaptionElement to refMe's NSXMLElement's elementWithName:("caption")
ocidCaptionElement's setStringValue:("YoutubeApiv3で取得")
ocidTableElement's addChild:(ocidCaptionElement)
#####【colgroup】
set ocidColgroupElement to refMe's NSXMLElement's elementWithName:("colgroup")
#タイトル部の数だけ繰り返し
set listColName to {"LineNO", "Key", "Value"}
repeat with itemColName in listColName
  #######【col】col生成
  set ocidAddElement to (refMe's NSXMLElement's elementWithName:("col"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:(itemColName))
(ocidAddElement's addAttribute:(ocidAddNode))
(ocidColgroupElement's addChild:(ocidAddElement))
end repeat
#テーブルエレメントに追加
ocidTableElement's addChild:(ocidColgroupElement)
#######【thead】
set ocidTheadElement to refMe's NSXMLElement's elementWithName:("thead")
#TR
set ocidTrElement to refMe's NSXMLElement's elementWithName:("tr")
set listColName to {"\", "Key", "Value"}
#タイトル部の数だけ繰り返し
repeat with itemColName in listColName
  #ここはTDではなくてTHを利用
  set ocidAddElement to (refMe's NSXMLElement's elementWithName:("th"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:(itemColName))
(ocidAddElement's addAttribute:(ocidAddNode))
  #
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("id") stringValue:(itemColName))
(ocidAddElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidAddElement's addAttribute:(ocidAddNode))
  #値を入れる
(ocidAddElement's setStringValue:(itemColName))
  #TH→TRにセット
(ocidTrElement's addChild:(ocidAddElement))
end repeat
#TRをTHEADにセット
ocidTheadElement's addChild:(ocidTrElement)
#THEADをテーブルにセット
ocidTableElement's addChild:(ocidTheadElement)
##################################
######【tbody】
set ocidTbodyElement to refMe's NSXMLElement's elementWithName:("tbody")
set CntLineNo to 1 as integer
repeat with itemArray in ocidItemsArray
  
  ##############
  #TRの開始
  set ocidTrElement to (refMe's NSXMLElement's elementWithName:("tr"))
  #
  set ocidThElement to (refMe's NSXMLElement's elementWithName:("th"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("項目番号:" & CntLineNo))
(ocidThElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("headers") stringValue:("NameID"))
(ocidThElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidThElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("rowspan") stringValue:("4"))
(ocidThElement's addAttribute:(ocidAddNode))
(ocidThElement's setStringValue:(CntLineNo as text))
(ocidTrElement's addChild:(ocidThElement))
  ##################################
  set ocidVideSnippet to (itemArray's objectForKey:("snippet"))
  ##################################
  set ocidResourceId to (ocidVideSnippet's objectForKey:("resourceId"))
  set strVideID to (ocidResourceId's valueForKey:("videoId")) as text
  ##################################
  set ocidTdElement to (refMe's NSXMLElement's elementWithName:("td"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("videoId"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("headers") stringValue:("key"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidTdElement's addAttribute:(ocidAddNode))
(ocidTdElement's setStringValue:("videoId"))
(ocidTrElement's addChild:(ocidTdElement))
  #####
  set ocidTdElement to (refMe's NSXMLElement's elementWithName:("td"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("videoId"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("headers") stringValue:("key"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidTdElement's addAttribute:(ocidAddNode))
(ocidTdElement's setStringValue:(strVideID))
(ocidTrElement's addChild:(ocidTdElement))
(ocidTbodyElement's addChild:(ocidTrElement))
  
  ##################################
  #TRの開始
  set ocidTrElement to (refMe's NSXMLElement's elementWithName:("tr"))
  #
  set strSetValue to (ocidVideSnippet's valueForKey:("title")) as text
  set ocidTdElement to (refMe's NSXMLElement's elementWithName:("td"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("title"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("headers") stringValue:("key"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidTdElement's addAttribute:(ocidAddNode))
(ocidTdElement's setStringValue:("title"))
(ocidTrElement's addChild:(ocidTdElement))
  #####
  set strSetValue to (ocidVideSnippet's valueForKey:("title")) as text
  set ocidTdElement to (refMe's NSXMLElement's elementWithName:("td"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("title"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("headers") stringValue:("key"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidTdElement's addAttribute:(ocidAddNode))
(ocidTdElement's setStringValue:(strSetValue))
(ocidTrElement's addChild:(ocidTdElement))
(ocidTbodyElement's addChild:(ocidTrElement))
  
  ##################################
  set ocidThumbnails to (ocidVideSnippet's objectForKey:("thumbnails"))
  
  ##################################
  #TRの開始
  set ocidTrElement to (refMe's NSXMLElement's elementWithName:("tr"))
  ##
  set ocidTdElement to (refMe's NSXMLElement's elementWithName:("td"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("thumbnails"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("headers") stringValue:("key"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidTdElement's addAttribute:(ocidAddNode))
(ocidTdElement's setStringValue:("thumbnails"))
(ocidTrElement's addChild:(ocidTdElement))
  ###
  set ocidTdElement to (refMe's NSXMLElement's elementWithName:("td"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("thumbnails"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("headers") stringValue:("key"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidTdElement's addAttribute:(ocidAddNode))
  ####
  set ocidAElement to (refMe's NSXMLElement's elementWithName:("a"))
  set strSetValue to ("https://www.youtube.com/watch?v=" & strVideID) as text
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("href") stringValue:(strSetValue))
(ocidAElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("target") stringValue:("_blank"))
(ocidAElement's addAttribute:(ocidAddNode))
  ##
  set strSetValue to ((ocidThumbnails's valueForKey:("maxres"))'s valueForKey:("url")) as text
  set ocidImgElement to (refMe's NSXMLElement's elementWithName:("img"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("src") stringValue:(strSetValue))
(ocidImgElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("alt") stringValue:("maxres"))
(ocidImgElement's addAttribute:(ocidAddNode))
  #
(ocidAElement's addChild:(ocidImgElement))
(ocidTdElement's addChild:(ocidAElement))
(ocidTrElement's addChild:(ocidTdElement))
(ocidTbodyElement's addChild:(ocidTrElement))
  
  ##################################
  #TRの開始
  set ocidTrElement to (refMe's NSXMLElement's elementWithName:("tr"))
  set ocidSetValue to (ocidVideSnippet's valueForKey:("description"))
  set ocidCdatatValue to (ocidSetValue's stringByReplacingOccurrencesOfString:("\n") withString:("<br>"))
  #TDの開始
  set ocidTdElement to (refMe's NSXMLElement's elementWithName:("td"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("description"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("headers") stringValue:("key"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidTdElement's addAttribute:(ocidAddNode))
(ocidTdElement's setStringValue:("description"))
(ocidTrElement's addChild:(ocidTdElement))
  #TDの開始
  set ocidTdElement to (refMe's NSXMLElement's elementWithName:("td"))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("description"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("headers") stringValue:("key"))
(ocidTdElement's addAttribute:(ocidAddNode))
  set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("col"))
(ocidTdElement's addAttribute:(ocidAddNode))
  
  set ocidAddNode to (refMe's NSXMLNode's alloc()'s initWithKind:(refMe's NSXMLTextKind) options:(refMe's NSXMLNodeIsCDATA))
(ocidAddNode's setStringValue:(ocidCdatatValue))
(ocidTdElement's addChild:(ocidAddNode))
(ocidTrElement's addChild:(ocidTdElement))
(ocidTbodyElement's addChild:(ocidTrElement))
  
  
  
  set CntLineNo to CntLineNo + 1 as integer
end repeat
#Tbodyをテーブルにセット
ocidTableElement's addChild:(ocidTbodyElement)

######【tfoot】 TRで
set ocidTfootElement to refMe's NSXMLElement's elementWithName:("tfoot")
set ocidTrElement to refMe's NSXMLElement's elementWithName:("tr")
#項目数を取得して
set numCntCol to (count of ocidItemsArray) as integer
#colspan指定して1行でセット
set ocidThElement to (refMe's NSXMLElement's elementWithName:("th"))
set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("title") stringValue:("テーブルの終わり"))
(ocidThElement's addAttribute:(ocidAddNode))
set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("colspan") stringValue:(numCntCol as text))
(ocidThElement's addAttribute:(ocidAddNode))
set ocidAddNode to (refMe's NSXMLNode's attributeWithName:("scope") stringValue:("row"))
(ocidThElement's addAttribute:(ocidAddNode))
#
set numCntContents to (count of ocidItemsArray) as integer
set strContents to ("項目数 : " & numCntContents) as text
(ocidThElement's setStringValue:(strContents))
#THをTRにセットして
ocidTrElement's addChild:(ocidThElement)
#TRをTFOOTにセット
ocidTfootElement's addChild:(ocidTrElement)
#TFOOTをテーブルにセット
ocidTableElement's addChild:(ocidTfootElement)
ocidSetArticleElement's addChild:(ocidTableElement)

##############################
#HTMLにする
##############################
set ocidHTML to doMakeRootElement({ocidSetHeaderElement, ocidSetArticleElement, ocidSetFooterElement})
#読み取りやすい表示
set ocidXMLdata to ocidHTML's XMLDataWithOptions:(refMe's NSXMLNodePrettyPrint)


########################################
####出力先/var/folders/XX/(再起動時に削除されます)
set appFileManager to refMe's NSFileManager's defaultManager()
set ocidTemporaryDirPathURL to appFileManager's temporaryDirectory
set ocidVarFoldersDirURL to ocidTemporaryDirPathURL's URLByDeletingLastPathComponent()
set ocidTemporaryItemsPathURL to ocidVarFoldersDirURL's URLByAppendingPathComponent:"TemporaryItems"
##フォルダを作る
set ocidAttrDict to refMe's NSMutableDictionary's alloc()'s initWithCapacity:0
ocidAttrDict's setValue:(511) forKey:(refMe's NSFilePosixPermissions)
set listDone to appFileManager's createDirectoryAtURL:(ocidTemporaryItemsPathURL) withIntermediateDirectories:(true) attributes:(ocidAttrDict) |error|:(reference)
set aliasTemporaryItems to (ocidTemporaryItemsPathURL's absoluteURL()) as alias
##
set strSetValue to ("このディレクトリ内は再起動時に自動で削除されます") as text
set strTmpFileName to ("_起動時削除されるフォルダ") as text
set ocidTmpFileStr to refMe's NSString's stringWithString:(strSetValue)
set ocidTmpFilePathURL to ocidTemporaryItemsPathURL's URLByAppendingPathComponent:(strTmpFileName)
set listDone to ocidTmpFileStr's writeToURL:(ocidTmpFilePathURL) atomically:(true) encoding:(refMe's NSUTF8StringEncoding) |error|:(reference)
##HTML保存先 ファイル名はUUID
set ocidUUID to refMe's NSUUID's alloc()'s init()
set strUUID to ocidUUID's UUIDString
set ocidSaveBaseFilePathURL to ocidTemporaryItemsPathURL's URLByAppendingPathComponent:(strUUID)
set ocidSaveFilePathURL to ocidSaveBaseFilePathURL's URLByAppendingPathExtension:("html")

########################################
set listDone to ocidXMLdata's writeToURL:(ocidSaveFilePathURL) options:(refMe's NSDataWritingAtomic) |error|:(reference)
##Finderで保存先を開く
set aliasSaveFilePath to (ocidSaveFilePathURL's absoluteURL()) as alias
tell application "Finder"
open location aliasSaveFilePath
end tell



###############################################################
#playlistIDからアップロードビデオのarrayを戻す
to doGetPlistID2ItemsArray(argPlayListID)
  ### 【1】JSONのURL
  set strJsonURL to ("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=" & argPlayListID & "&key=" & strAPIkey & "&maxResults=" & numMaxResults & "") as text
  
  set ocidJsonURLStr to refMe's NSString's stringWithString:(strJsonURL)
  set ocidJsonURL to refMe's NSURL's alloc()'s initWithString:(ocidJsonURLStr)
  ### 【2】URLの内容JSONをNSdataに格納
  set ocidOption to (refMe's NSDataReadingMappedIfSafe)
  set listReadData to refMe's NSData's alloc()'s initWithContentsOfURL:(ocidJsonURL) options:(ocidOption) |error|:(reference)
  set ocidReadData to (item 1 of listReadData)
  ### 【3】NSPropertyListSerializationしてレコードに
  set ocidOption to (refMe's NSJSONReadingMutableContainers)
  set listJSONSerialization to (refMe's NSJSONSerialization's JSONObjectWithData:(ocidReadData) options:(ocidOption) |error|:(reference))
  set ocidPlistDictM to item 1 of listJSONSerialization
  ###
  set ocidItemsArray to ocidPlistDictM's objectForKey:("items")
return ocidItemsArray
end doGetPlistID2ItemsArray




###############################################################
to doChannelId2UploadsListID(toChannelId)
  set jsonChannelsURL to "https://www.googleapis.com/youtube/v3/channels?&part=id,snippet,brandingSettings,contentDetails,statistics,topicDetails&id=" & toChannelId & "&key=" & strAPIkey & ""
  ############コマンド整形
  set strCommandText to "/usr/bin/curl -X GET -H 'Content-Type: application/json;charset=UTF-8' \"" & jsonChannelsURL & "\" --connect-timeout 20"
  ####コマンド実行
  set strResponse to (do shell script strCommandText) as text
  ####戻り値を格納
  set ocidResponse to refMe's NSString's stringWithString:(strResponse)
  ###NSDATA化
  set ocidJsonData to (ocidResponse's dataUsingEncoding:(refMe's NSUTF8StringEncoding))
  ##JSONSiriアライズ
  set listJson to (refMe's NSJSONSerialization's JSONObjectWithData:(ocidJsonData) options:0 |error|:(reference))
  set ocidJson to (item 1 of listJson)
  #DICTに格納
  set ocidJsonDict to (refMe's NSDictionary's alloc()'s initWithDictionary:(ocidJson))
  ####チャンネルの名前を取得
  set ocidItemsArray to ocidJsonDict's objectForKey:("items")
  set ocidItemDict to ocidItemsArray's firstObject()
  set ocidItemContentDetails to ocidItemDict's objectForKey:("contentDetails")
  set ocidrelatedPlaylists to ocidItemContentDetails's objectForKey:("relatedPlaylists")
  set ocidUploadsListID to ocidrelatedPlaylists's valueForKey:("uploads")
return ocidUploadsListID
end doChannelId2UploadsListID


##############################
# 基本的なHTMLの構造
(*
doMakeRootElement({argHeaderContents, argArticleContents, argFooterContents})
HTMLのBODY部
header
article
footerにそれぞれAddchildするデータをリストで渡す
戻り値はRootエレメントにセットされた
NSXMLDocumentを戻すので 保存すればOK
*)
##############################
to doMakeRootElement({argHeaderContents, argArticleContents, argFooterContents})
  #XML初期化
  set ocidXMLDoc to refMe's NSXMLDocument's alloc()'s init()
ocidXMLDoc's setDocumentContentKind:(refMe's NSXMLDocumentHTMLKind)
  # DTD付与
  set ocidDTD to refMe's NSXMLDTD's alloc()'s init()
ocidDTD's setName:("html")
ocidXMLDoc's setDTD:(ocidDTD)
  #
  set ocidRootElement to refMe's NSXMLElement's elementWithName:("html")
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("lang") stringValue:("ja")
ocidRootElement's addAttribute:(ocidAddNode)
  #
  set ocidHeadElement to refMe's NSXMLElement's elementWithName:("head")
  #
  set ocidAddElement to refMe's NSXMLElement's elementWithName:("title")
ocidAddElement's setStringValue:("ビデオ一覧")
ocidHeadElement's addChild:(ocidAddElement)
  # http-equiv
  set ocidAddElement to refMe's NSXMLElement's elementWithName:("meta")
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("http-equiv") stringValue:("Content-Type")
ocidAddElement's addAttribute:(ocidAddNode)
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("content") stringValue:("text/html; charset=UTF-8")
ocidAddElement's addAttribute:(ocidAddNode)
ocidHeadElement's addChild:(ocidAddElement)
  #
  set ocidAddElement to refMe's NSXMLElement's elementWithName:("meta")
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("http-equiv") stringValue:("Content-Style-Type")
ocidAddElement's addAttribute:(ocidAddNode)
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("content") stringValue:("text/css")
ocidAddElement's addAttribute:(ocidAddNode)
ocidHeadElement's addChild:(ocidAddElement)
  #
  set ocidAddElement to refMe's NSXMLElement's elementWithName:("meta")
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("http-equiv") stringValue:("Content-Script-Type")
ocidAddElement's addAttribute:(ocidAddNode)
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("content") stringValue:("text/javascript")
ocidAddElement's addAttribute:(ocidAddNode)
ocidHeadElement's addChild:(ocidAddElement)
  #
  set ocidAddElement to refMe's NSXMLElement's elementWithName:("meta")
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("name") stringValue:("viewport")
ocidAddElement's addAttribute:(ocidAddNode)
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("content") stringValue:("width=720")
ocidAddElement's addAttribute:(ocidAddNode)
ocidHeadElement's addChild:(ocidAddElement)
  #
  set ocidAddElement to refMe's NSXMLElement's elementWithName:("style")
ocidAddElement's setStringValue:("body {margin: 10px;background-color: #FFFFFF;}table {max-width: 720;border-spacing: 0;caption-side: top;font-family: system-ui;}thead th {border: solid 1px #666666;padding: .5ch 1ch;border-block-width: 1px 0;border-inline-width: 1px 0;&:first-of-type {border-start-start-radius: .5em}&:last-of-type {border-start-end-radius: .5em;border-inline-end-width: 1px}}tbody td {word-wrap: break-word;max-width: 420px;border-spacing: 0;border: solid 1px #666666;padding: .5ch 1ch;border-block-width: 1px 0;border-inline-width: 1px 0;&:last-of-type {border-inline-end-width: 1px}}tbody th {border-spacing: 0;border: solid 1px #666666;padding: .5ch 1ch;border-block-width: 1px 0;border-inline-width: 1px 0;}tbody tr:nth-of-type(odd) {background: #F2F2F2;}.kind_string {font-size: 0.75em;}.date_string {font-size: 0.5em;}tfoot th {border: solid 1px #666666;padding: .5ch 1ch;&:first-of-type {border-end-start-radius: .5em}&:last-of-type {border-end-end-radius: .5em;border-inline-end-width: 1px}}img {max-width: 360px;}")
ocidHeadElement's addChild:(ocidAddElement)
ocidRootElement's addChild:(ocidHeadElement)
  #
  #ボディエレメント
  set ocidBodyElement to refMe's NSXMLElement's elementWithName:("body")
  #ヘッダー
  set ocidHeaderElement to refMe's NSXMLElement's elementWithName:("header")
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("id") stringValue:("header")
ocidHeaderElement's addAttribute:(ocidAddNode)
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("class") stringValue:("body_header")
ocidHeaderElement's addAttribute:(ocidAddNode)
ocidHeaderElement's addChild:(argHeaderContents)
ocidBodyElement's addChild:(ocidHeaderElement)
  #アーティクル
  set ocidArticleElement to refMe's NSXMLElement's elementWithName:("article")
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("id") stringValue:("article")
ocidArticleElement's addAttribute:(ocidAddNode)
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("class") stringValue:("body_article")
ocidArticleElement's addAttribute:(ocidAddNode)
ocidArticleElement's addChild:(argArticleContents)
ocidBodyElement's addChild:(ocidArticleElement)
  #フッター
  set ocidFooterElement to refMe's NSXMLElement's elementWithName:("footer")
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("id") stringValue:("footer")
ocidFooterElement's addAttribute:(ocidAddNode)
  set ocidAddNode to refMe's NSXMLNode's attributeWithName:("class") stringValue:("body_footer")
ocidFooterElement's addAttribute:(ocidAddNode)
ocidFooterElement's addChild:(argFooterContents)
ocidBodyElement's addChild:(ocidFooterElement)
  
ocidRootElement's addChild:(ocidBodyElement)
ocidXMLDoc's setRootElement:(ocidRootElement)
return ocidXMLDoc
end doMakeRootElement

|

[YoutubeAPI] チャンネルIDからチャンネルのアップロードビデオのリストIDを取得する


【スクリプトエディタで開く】|

#!/usr/bin/env osascript
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
(*
API
https://developers.google.com/youtube/v3
コンソール
https://console.cloud.google.com/apis/dashboard?pli=1
*)
# com.cocolog-nifty.quicktimer.icefloe
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
use framework "Foundation"
use AppleScript version "2.8"
use scripting additions

property refMe : a reference to current application


############設定項目 
####API ID
property strAPIkey : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX" as text


####################################
property numMaxResults : 10 as number
####################################

set strURL to ("https://www.youtube.com/channel/UCQ6Br7m6vP61FZvjv4lwR5w") as text

######

set ocidURLString to refMe's NSString's stringWithString:(strURL)
set ocidURL to refMe's NSURL's alloc()'s initWithString:(ocidURLString)
set strChannelID to ocidURL's lastPathComponent() as text

##################################################
#チャンネルIDからアップロードビデオのリストID
set ocidUploadsListID to doChannelId2UploadsListID(strChannelID)
log ocidUploadsListID as text
#
#基本となるURL
set strPlistURL to ("https://www.youtube.com/playlist") as text
#NSURLにして
set ocidPlistURL to refMe's NSURL's alloc()'s initWithString:(strPlistURL)
#コンポーネントに分割
set ocidURLomponents to refMe's NSURLComponents's componentsWithURL:(ocidPlistURL) resolvingAgainstBaseURL:(false)
#クエリーアイテム
set ocidQueryItems to refMe's NSMutableArray's alloc()'s initWithCapacity:(0)
#クエリー定義
set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("list") value:(ocidUploadsListID)
#クエリーをセット
ocidQueryItems's addObject:(ocidQueryItem)
#コンポーネントに追加
ocidURLomponents's setQueryItems:(ocidQueryItems)
#URLを再定義
set ocidPlaylistURL to ocidURLomponents's |URL|


set strPlaylistURL to ocidPlaylistURL's absoluteString() as text
#
tell application "Finder"
open location strPlaylistURL
end tell



###############################################################
to doChannelId2UploadsListID(toChannelId)
  set jsonChannelsURL to "https://www.googleapis.com/youtube/v3/channels?&part=id,snippet,brandingSettings,contentDetails,statistics,topicDetails&id=" & toChannelId & "&key=" & strAPIkey & ""
  ############コマンド整形
  set strCommandText to "/usr/bin/curl -X GET -H 'Content-Type: application/json;charset=UTF-8' \"" & jsonChannelsURL & "\" --connect-timeout 20"
  ####コマンド実行
  set strResponse to (do shell script strCommandText) as text
  ####戻り値を格納
  set ocidResponse to refMe's NSString's stringWithString:(strResponse)
  ###NSDATA化
  set ocidJsonData to (ocidResponse's dataUsingEncoding:(refMe's NSUTF8StringEncoding))
  ##JSONSiriアライズ
  set listJson to (refMe's NSJSONSerialization's JSONObjectWithData:(ocidJsonData) options:0 |error|:(reference))
  set ocidJson to (item 1 of listJson)
  #DICTに格納
  set ocidJsonDict to (refMe's NSDictionary's alloc()'s initWithDictionary:(ocidJson))
  ####チャンネルの名前を取得
  set ocidItemsArray to ocidJsonDict's objectForKey:("items")
  set ocidItemDict to ocidItemsArray's firstObject()
  set ocidItemContentDetails to ocidItemDict's objectForKey:("contentDetails")
  set ocidrelatedPlaylists to ocidItemContentDetails's objectForKey:("relatedPlaylists")
  set ocidUploadsListID to ocidrelatedPlaylists's valueForKey:("uploads")
return ocidUploadsListID
end doChannelId2UploadsListID

|

[YoutubeAPI] チャンネルIDからカスタムURL=ユーザー名(アカウント名)を取得


【スクリプトエディタで開く】|

#!/usr/bin/env osascript
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
(*
API
https://developers.google.com/youtube/v3
コンソール
https://console.cloud.google.com/apis/dashboard?pli=1
*)
# com.cocolog-nifty.quicktimer.icefloe
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
use framework "Foundation"
use AppleScript version "2.8"
use scripting additions

property refMe : a reference to current application

############設定項目 
####API key
property strAPIkey : "XXXXXXXXXXXXXXXXXX" as text


####################################
property numMaxResults : 10 as number
####################################


set strURL to ("https://www.youtube.com/channel/UCQ6Br7m6vP61FZvjv4lwR5w") as text

######

set ocidURLString to refMe's NSString's stringWithString:(strURL)
set ocidURL to refMe's NSURL's alloc()'s initWithString:(ocidURLString)
set strChannelID to ocidURL's lastPathComponent() as text
##################################################
#チャンネルIDからcustomUrl=forUsernameを取得
set ocidUserName to doChannelId2customUrl(strChannelID)
#customUrlから@取ってforUsernameにする場合
#set ocidForUsername to (strUserName's stringByReplacingOccurrencesOfString:("@") withString:(""))

#基本となるURL
set strBaseURL to ("https://www.youtube.com/") as text
#NSURLにして
set ocidBaseURL to refMe's NSURL's alloc()'s initWithString:(strBaseURL)
#コンポーネントに分割
set ocidURLomponents to refMe's NSURLComponents's componentsWithURL:(ocidBaseURL) resolvingAgainstBaseURL:(false)
#カスタムURLを付与
set strSetValue to ("/" & ocidUserName & "/videos") as text
ocidURLomponents's setPath:(strSetValue)
#URLを再定義
set ocidCustomURL to ocidURLomponents's |URL|
set strCustomURL to ocidCustomURL's absoluteString() as text
#
tell application "Finder"
open location strCustomURL
end tell

###############################################################
to doChannelId2customUrl(toChannelId)
  set jsonChannelsURL to "https://www.googleapis.com/youtube/v3/channels?&part=id,snippet,brandingSettings,contentDetails,statistics,topicDetails&id=" & toChannelId & "&key=" & strAPIkey & ""
  ############コマンド整形
  set strCommandText to "/usr/bin/curl -X GET -H 'Content-Type: application/json;charset=UTF-8' \"" & jsonChannelsURL & "\" --connect-timeout 20"
  ####コマンド実行
  set strResponse to (do shell script strCommandText) as text
  ####戻り値を格納
  set ocidResponse to refMe's NSString's stringWithString:(strResponse)
  ###NSDATA化
  set ocidJsonData to (ocidResponse's dataUsingEncoding:(refMe's NSUTF8StringEncoding))
  ##JSONSiriアライズ
  set listJson to (refMe's NSJSONSerialization's JSONObjectWithData:(ocidJsonData) options:0 |error|:(reference))
  set ocidJson to (item 1 of listJson)
  #DICTに格納
  set ocidJsonDict to (refMe's NSDictionary's alloc()'s initWithDictionary:(ocidJson))
  ####チャンネルの名前を取得
  set ocidItemsArray to ocidJsonDict's objectForKey:("items")
  set ocidItemDict to ocidItemsArray's firstObject()
  set ocidItemSnipet to ocidItemDict's objectForKey:("snippet")
  set ocidCustomURL to ocidItemSnipet's valueForKey:("customUrl")
return ocidCustomURL
end doChannelId2customUrl



|

[Youtube]ビデオIDから主要な情報を取得


【スクリプトエディタで開く】|

#!/usr/bin/env osascript
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
#
(*
API
https://developers.google.com/youtube/v3
コンソール
https://console.cloud.google.com/apis/dashboard?pli=1
*)
# com.cocolog-nifty.quicktimer.icefloe
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
use AppleScript version "2.8"
use framework "Foundation"
use framework "AppKit"
use scripting additions

property refMe : a reference to current application
property refNSNotFound : a reference to 9.22337203685477E+18 + 5807

############設定項目 
####API ID
property strAPIkey : "ApiKeyをここに" as text

########################
## クリップボードの中身取り出し
###初期化
set appPasteboard to refMe's NSPasteboard's generalPasteboard()
set ocidPastBoardTypeArray to appPasteboard's types
###テキストがあれば
set boolContain to ocidPastBoardTypeArray's containsObject:"public.utf8-plain-text"
if boolContain = true then
  ###値を格納する
  tell application "Finder"
    set strReadString to (the clipboard as text) as text
  end tell
  ###Finderでエラーしたら
else
  set boolContain to ocidPastBoardTypeArray's containsObject:"NSStringPboardType"
  if boolContain = true then
    set ocidReadString to ocidPasteboard's readObjectsForClasses:({refMe's NSString}) options:(missing value)
    set strReadString to ocidReadString as text
  else
log "テキストなし"
    set strReadString to "YouTubeのビデオURLを入力" as text
  end if
end if

########################
##ダイアログを前面に出す
set strName to (name of current application) as text
####スクリプトメニューから実行したら
if strName is "osascript" then
  tell application "Finder" to activate
else
  tell current application to activate
end if
########################
##ダイアログ
set aliasIconPath to (POSIX file "/System/Library/CoreServices/Tips.app/Contents/Resources/AppIcon.icns") as alias
set strTitle to ("入力してください") as text
set strMes to ("YouTubeURLを入力してください\r") as text
set recordResult to (display dialog strMes with title strTitle default answer strReadString buttons {"キャンセル", "OK"} default button "OK" cancel button "キャンセル" giving up after 30 with icon aliasIconPath without hidden answer)
if (gave up of recordResult) is true then
return "時間切れです"
else if (button returned of recordResult) is "キャンセル" then
return "キャンセルです"
else
  set strReturnedText to (text returned of recordResult) as text
end if
set ocidReturnedText to refMe's NSString's stringWithString:(strReturnedText)
########################
##改行を取る
set ocidURLStr to ocidReturnedText's stringByReplacingOccurrencesOfString:("\r") withString:("")
set ocidURLStr to ocidURLStr's stringByReplacingOccurrencesOfString:("\n") withString:("")
########################
##NSURLに
set ocidURL to refMe's NSURL's alloc()'s initWithString:(ocidURLStr)
##NSURLComponentsに分解
set ocidURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidURL) resolvingAgainstBaseURL:(true)
########################
##以下はチャンネルと関係ない
##ホスト判定
set strHost to ocidURL's |host|() as text
if strHost is not "www.youtube.com" then
return "Youtube URL 専用"
end if
##パス判定
set strPath to ocidURL's |path|() as text
if strPath starts with "/watch" then
log "ビデオぺージのみ処理する"
else if strPath starts with "/feed" then
return "feedぺージは処理しない"
else if strPath starts with "/results" then
return "resultsぺージは処理しない"
else if strPath starts with "/hashtag" then
return "hashtagぺージは処理しない"
else if strPath is "" then
return "トップぺージは処理しない"
else if strPath is "/" then
return "トップぺージは処理しない"
end if

########################
##クエリーの有無をチェック
set recordRange to ocidURLComponents's rangeOfQuery()
set ocidLocation to location of recordRange
##
if ocidLocation = refNSNotFound then
return "クエリーの無いURLは処理しない"
end if

########################
##【Aクエリーあり】
set ocidQueryArray to ocidURLComponents's queryItems
##【Aー1】ラストパスで判定
set strLastPath to ocidURL's lastPathComponent() as text
##【Aー1−1】ビデオ再生のwatchの場合
if strLastPath is "watch" then
  ##queryItemsから各種ID
  repeat with itemQuery in ocidQueryArray
    set strQueryName to itemQuery's |name| as text
    if strQueryName is "v" then
      #再生中ビデオID
      set strVideoID to itemQuery's value as text
    else if strQueryName is "list" then
      #プレイリストのID
      set strPlayListID to itemQuery's value as text
    else if strQueryName is "index" then
      #プレイリストの曲順番号
      set strPlayListIndex to itemQuery's value as text
    end if
  end repeat
  ##【Aー1−2】プレイリスト画面の場合
else if strLastPath is "playlist" then
  repeat with itemQuery in ocidQueryArray
    set strQueryName to itemQuery's |name| as text
    if strQueryName is "list" then
      #プレイリストのID
      set strPlayListID to itemQuery's value as text
    end if
  end repeat
end if

########################
##APIURL 

if strVideoID ≠ (missing value) then
  #ビデオIDが見つかった場合のクエリー
  set strBaseURL to ("https://www.googleapis.com/youtube/v3/captions") as text
  set ocidBaseURLStr to refMe's NSString's stringWithString:(strBaseURL)
  set ocidBaseURL to refMe's NSURL's alloc()'s initWithString:(ocidBaseURLStr)
  set ocidBaseURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidBaseURL) resolvingAgainstBaseURL:(true)
  set ocidQueryArray to refMe's NSMutableArray's alloc()'s initWithCapacity:(0)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("part") value:("snippet")
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("videoId") value:(strVideoID)
ocidQueryArray's addObject:(ocidQueryItem)

  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("maxResults") value:("1")
ocidQueryArray's addObject:(ocidQueryItem)
else
return "VIDEOidの無いURLは処理しない"
end if

########################
##APIを呼び出すURL
ocidBaseURLComponents's setQueryItems:(ocidQueryArray)
set ocidOpenURL to ocidBaseURLComponents's |URL|()
set strOpenURL to ocidOpenURL's absoluteString() as text
log "呼び出したURL: " & strOpenURL

########################
##Get JSON
### 【1】JSONのURL
set ocidApiURL to ocidOpenURL
### 【2】URLの内容JSONをNSdataに格納
set ocidOption to (refMe's NSDataReadingMappedIfSafe)
set listReadData to refMe's NSData's alloc()'s initWithContentsOfURL:(ocidApiURL) options:(ocidOption) |error|:(reference)
set ocidReadData to (item 1 of listReadData)
### 【3】NSPropertyListSerializationしてレコードに
set ocidOption to (refMe's NSJSONReadingMutableContainers)
set listJSONSerialization to (refMe's NSJSONSerialization's JSONObjectWithData:(ocidReadData) options:(ocidOption) |error|:(reference))
set ocidPlistDict to item 1 of listJSONSerialization
##
set ocidItemsArray to (ocidPlistDict's valueForKey:("items"))
repeat with itemItemsDict in ocidItemsArray
  ##ITEMS
  set ocidVideoID to (itemItemsDict's valueForKey:("id"))
  ##SNIPPET
  set ocidSnipetDict to (itemItemsDict's valueForKey:("snippet"))
  set ocidChannelID to (ocidSnipetDict's valueForKey:("channelId"))
  set ocidChannelTitle to (ocidSnipetDict's valueForKey:("channelTitle"))
  set ocidVideTitle to (ocidSnipetDict's valueForKey:("title"))
  set ocidPublishedDate to (ocidSnipetDict's valueForKey:("publishedAt"))
  set ocidDescription to (ocidSnipetDict's valueForKey:("description"))
  set ocidCategoryID to (ocidSnipetDict's valueForKey:("categoryId"))
  ##thumbnails
  set ocidThumbnailsDict to (ocidSnipetDict's valueForKey:("thumbnails"))
  #
  set ocidDefaultThumbnailsDict to (ocidThumbnailsDict's valueForKey:("default"))
  set ocidDefaultThumbnailsURL to (ocidDefaultThumbnailsDict's valueForKey:("url"))
  set ocidDefaultThumbnailsWidth to (ocidDefaultThumbnailsDict's valueForKey:("width"))
  set ocidDefaultThumbnailsHeight to (ocidDefaultThumbnailsDict's valueForKey:("height"))
  #
  set ocidMediumThumbnailsDict to (ocidThumbnailsDict's valueForKey:("medium"))
  set ocidMediumThumbnailsURL to (ocidMediumThumbnailsDict's valueForKey:("url"))
  set ocidMediumThumbnailsWidth to (ocidMediumThumbnailsDict's valueForKey:("width"))
  set ocidMediumThumbnailsHeight to (ocidMediumThumbnailsDict's valueForKey:("height"))
  #
  set ocidHighThumbnailsDict to (ocidThumbnailsDict's valueForKey:("high"))
  set ocidHighThumbnailsURL to (ocidHighThumbnailsDict's valueForKey:("url"))
  set ocidHighThumbnailsWidth to (ocidHighThumbnailsDict's valueForKey:("width"))
  set ocidHighThumbnailsHeight to (ocidHighThumbnailsDict's valueForKey:("height"))
  #
  set ocidStandardThumbnailsDict to (ocidThumbnailsDict's valueForKey:("standard"))
  set ocidStandardThumbnailsURL to (ocidStandardThumbnailsDict's valueForKey:("url"))
  set ocidStandardThumbnailsWidth to (ocidStandardThumbnailsDict's valueForKey:("width"))
  set ocidStandardThumbnailsHeight to (ocidStandardThumbnailsDict's valueForKey:("height"))
  #
  set ocidMaxresThumbnailsDict to (ocidThumbnailsDict's valueForKey:("maxres"))
  set ocidMaxresThumbnailsURL to (ocidMaxresThumbnailsDict's valueForKey:("url"))
  set ocidMaxresThumbnailsWidth to (ocidMaxresThumbnailsDict's valueForKey:("width"))
  set ocidMaxresThumbnailsHeight to (ocidMaxresThumbnailsDict's valueForKey:("height"))
end repeat

return


|

youtubeのサムネイル画像をダウンロードする


【スクリプトエディタで開く】|

#!/usr/bin/env osascript
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
#
# com.cocolog-nifty.quicktimer.icefloe
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
use AppleScript version "2.8"
use framework "Foundation"
use framework "AppKit"
use scripting additions

property refMe : a reference to current application
property refNSNotFound : a reference to 9.22337203685477E+18 + 5807

########################
## クリップボードの中身取り出し
###初期化
set appPasteboard to refMe's NSPasteboard's generalPasteboard()
set ocidPastBoardTypeArray to appPasteboard's types
###テキストがあれば
set boolContain to ocidPastBoardTypeArray's containsObject:"public.utf8-plain-text"
if boolContain = true then
  ###値を格納する
  tell application "Finder"
    set strReadString to (the clipboard as text) as text
  end tell
  ###Finderでエラーしたら
else
  set boolContain to ocidPastBoardTypeArray's containsObject:"NSStringPboardType"
  if boolContain = true then
    set ocidReadString to ocidPasteboard's readObjectsForClasses:({refMe's NSString}) options:(missing value)
    set strReadString to ocidReadString as text
  else
log "テキストなし"
    set strReadString to "YouTubeのビデオURLを入力" as text
  end if
end if

########################
##ダイアログを前面に出す
set strName to (name of current application) as text
####スクリプトメニューから実行したら
if strName is "osascript" then
  tell application "Finder" to activate
else
  tell current application to activate
end if
########################
##ダイアログ
set aliasIconPath to (POSIX file "/System/Library/CoreServices/Tips.app/Contents/Resources/AppIcon.icns") as alias
set strTitle to ("入力してください") as text
set strMes to ("YouTubeURLを入力してください\r") as text
set recordResult to (display dialog strMes with title strTitle default answer strReadString buttons {"キャンセル", "OK"} default button "OK" cancel button "キャンセル" giving up after 30 with icon aliasIconPath without hidden answer)
if (gave up of recordResult) is true then
return "時間切れです"
else if (button returned of recordResult) is "キャンセル" then
return "キャンセルです"
else
  set strReturnedText to (text returned of recordResult) as text
end if
set ocidReturnedText to refMe's NSString's stringWithString:(strReturnedText)
########################
##改行を取る
set ocidURLStr to ocidReturnedText's stringByReplacingOccurrencesOfString:("\r") withString:("")
set ocidURLStr to ocidURLStr's stringByReplacingOccurrencesOfString:("\n") withString:("")
########################
##NSURLに
set ocidURL to refMe's NSURL's alloc()'s initWithString:(ocidURLStr)
##NSURLComponentsに分解
set ocidURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidURL) resolvingAgainstBaseURL:(true)
########################
##以下はチャンネルと関係ない
##ホスト判定
set strHost to ocidURL's |host|() as text
if strHost is not "www.youtube.com" then
return "Youtube URL 専用"
end if
##パス判定
set strPath to ocidURL's |path|() as text
if strPath starts with "/watch" then
log "ビデオぺージのみ処理する"
else if strPath starts with "/feed" then
return "feedぺージは処理しない"
else if strPath starts with "/results" then
return "resultsぺージは処理しない"
else if strPath starts with "/hashtag" then
return "hashtagぺージは処理しない"
else if strPath is "" then
return "トップぺージは処理しない"
else if strPath is "/" then
return "トップぺージは処理しない"
end if

########################
##クエリーの有無をチェック
set recordRange to ocidURLComponents's rangeOfQuery()
set ocidLocation to location of recordRange
##
if ocidLocation = refNSNotFound then
  if strPath starts with "/shorts" then
    set strVideoID to ocidURL's lastPathComponent() as text
  else if strPath starts with "/embed" then
    set strVideoID to ocidURL's lastPathComponent() as text
  else
return "クエリーの無いURLは処理しない"
  end if
else
  ########################
  ##【Aクエリーあり】
  set ocidQueryArray to ocidURLComponents's queryItems
  ##【Aー1】ラストパスで判定
  set strLastPath to ocidURL's lastPathComponent() as text
  ##【Aー1−1】ビデオ再生のwatchの場合
  if strLastPath is "watch" then
    ##queryItemsから各種ID
    repeat with itemQuery in ocidQueryArray
      set strQueryName to itemQuery's |name| as text
      if strQueryName is "v" then
        #再生中ビデオID
        set strVideoID to itemQuery's value as text
      else if strQueryName is "list" then
        #プレイリストのID
        set strPlayListID to itemQuery's value as text
      else if strQueryName is "index" then
        #プレイリストの曲順番号
        set strPlayListIndex to itemQuery's value as text
      end if
    end repeat
    ##【Aー1−2】プレイリスト画面の場合
  else if strLastPath is "playlist" then
    repeat with itemQuery in ocidQueryArray
      set strQueryName to itemQuery's |name| as text
      if strQueryName is "list" then
        #プレイリストのID
        set strPlayListID to itemQuery's value as text
      end if
    end repeat
  end if
end if
###保存先 ダウンロード
set appFileManager to refMe's NSFileManager's defaultManager()
set ocidURLsArray to (appFileManager's URLsForDirectory:(refMe's NSDownloadsDirectory) inDomains:(refMe's NSUserDomainMask))
set ocidDownloadsDirPathURL to ocidURLsArray's firstObject()
set strMakeDirName to ("www.youtube.com/" & strVideoID) as text
set ocidSaveDirPathURL to ocidDownloadsDirPathURL's URLByAppendingPathComponent:(strMakeDirName)
###フォルダ作成
set ocidAttrDict to refMe's NSMutableDictionary's alloc()'s initWithCapacity:0
ocidAttrDict's setValue:(448) forKey:(refMe's NSFilePosixPermissions)
set listBoolMakeDir to appFileManager's createDirectoryAtURL:(ocidSaveDirPathURL) withIntermediateDirectories:true attributes:(ocidAttrDict) |error|:(reference)
##パスとエイリアス
set strSaveDirPath to (ocidSaveDirPathURL's |path|()) as text
set aliasSaveDirPath to (ocidSaveDirPathURL's absoluteURL()) as alias
###ファイル名
set listFileName to {"frame0", "default", "mqdefault", "hqdefault", "sddefault", "maxresdefault", "0", "1", "2", "3", "hq720", "hq720_1", "hq720_2", "hq720_3", "maxres3", "maxres2", "maxres1", "mq1", "mq2", "mq3", "oar1", "oar2", "oar3", "mqdefault_6s", "oardefault"} as list
##ファイル名の数だけ繰り返し
repeat with itemFileName in listFileName
  ###JPEGサムネイル
  set strFileNameJpeg to (itemFileName & ".jpg") as text
  set strSaveFilePathJpeg to (strSaveDirPath & "/" & strFileNameJpeg) as text
  set numServerNo to ("") as text
  set strBaseUrlJpeg to ("https://i" & numServerNo & ".ytimg.com/vi/") as text
  set strURLjpeg to (strBaseUrlJpeg & strVideoID & "/" & strFileNameJpeg) as text
  set strCommandText to ("/usr/bin/curl -L \"" & strURLjpeg & "\" -o \"" & strSaveFilePathJpeg & "\"") as text
do shell script strCommandText
  ####WEBPサムネイル
  set numServerNo to ("") as text
  set strBaseUrlWebp to ("https://i" & numServerNo & ".ytimg.com/vi_webp/") as text
  set strFileNameWebp to (itemFileName & ".webp") as text
  set strURLwebp to (strBaseUrlWebp & strVideoID & "/" & strFileNameWebp) as text
  set strSaveFilePathWebp to (strSaveDirPath & "/" & strFileNameWebp) as text
  set strCommandText to ("/usr/bin/curl -L \"" & strURLwebp & "\" -o \"" & strSaveFilePathWebp & "\"") as text
do shell script strCommandText
end repeat

##保存先を開く
set appShardWorkspace to refMe's NSWorkspace's sharedWorkspace()
set boolResults to appShardWorkspace's openURL:(ocidSaveDirPathURL)
if boolResults is false then
  tell application "Finder"
make new Finder window to aliasSaveDirPath
  end tell
end if



|

[Youtube]YoutubeのURLからチャンネルIDを取得する


【スクリプトエディタで開く】|

#!/usr/bin/env osascript
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
#
(*
API
https://developers.google.com/youtube/v3
コンソール
https://console.cloud.google.com/apis/dashboard?pli=1
*)
# com.cocolog-nifty.quicktimer.icefloe
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
use AppleScript version "2.8"
use framework "Foundation"
use framework "AppKit"
use scripting additions

property refMe : a reference to current application
property refNSNotFound : a reference to 9.22337203685477E+18 + 5807
property strVideoID : (missing value)
property strPlayListID : (missing value)
property strChannelID : (missing value)
property strUserID : (missing value)
property strCustomUrl : (missing value)
############設定項目 
####API ID
property strAPIkey : "ここにAPIキー" as text

########################
## クリップボードの中身取り出し
###初期化
set appPasteboard to refMe's NSPasteboard's generalPasteboard()
set ocidPastBoardTypeArray to appPasteboard's types
###テキストがあれば
set boolContain to ocidPastBoardTypeArray's containsObject:"public.utf8-plain-text"
if boolContain = true then
  ###値を格納する
  tell application "Finder"
    set strReadString to (the clipboard as text) as text
  end tell
  ###Finderでエラーしたら
else
  set boolContain to ocidPastBoardTypeArray's containsObject:"NSStringPboardType"
  if boolContain = true then
    set ocidReadString to ocidPasteboard's readObjectsForClasses:({refMe's NSString}) options:(missing value)
    set strReadString to ocidReadString as text
  else
log "テキストなし"
    set strReadString to "YouTubeのビデオURLを入力" as text
  end if
end if

########################
##ダイアログを前面に出す
set strName to (name of current application) as text
####スクリプトメニューから実行したら
if strName is "osascript" then
  tell application "Finder" to activate
else
  tell current application to activate
end if
########################
##ダイアログ
set aliasIconPath to (POSIX file "/System/Library/CoreServices/Tips.app/Contents/Resources/AppIcon.icns") as alias
set strTitle to ("入力してください") as text
set strMes to ("YouTubeURLを入力してください\r") as text
set recordResult to (display dialog strMes with title strTitle default answer strReadString buttons {"キャンセル", "OK"} default button "OK" cancel button "キャンセル" giving up after 30 with icon aliasIconPath without hidden answer)
if (gave up of recordResult) is true then
return "時間切れです"
else if (button returned of recordResult) is "キャンセル" then
return "キャンセルです"
else
  set strReturnedText to (text returned of recordResult) as text
end if
set ocidReturnedText to refMe's NSString's stringWithString:(strReturnedText)
########################
##改行を取る
set ocidURLStr to ocidReturnedText's stringByReplacingOccurrencesOfString:("\r") withString:("")
set ocidURLStr to ocidURLStr's stringByReplacingOccurrencesOfString:("\n") withString:("")
########################
##NSURLに
set ocidURL to refMe's NSURL's alloc()'s initWithString:(ocidURLStr)
##NSURLComponentsに分解
set ocidURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidURL) resolvingAgainstBaseURL:(true)
########################
##以下はチャンネルと関係ない
##ホスト判定
set strHost to ocidURL's |host|() as text
if strHost is not "www.youtube.com" then
return "Youtube URL 専用"
end if
##パスで判定
set strPath to ocidURL's |path|() as text
if strPath starts with "/feed" then
return "feedぺージは処理しない"
else if strPath starts with "/results" then
return "resultsぺージは処理しない"
else if strPath starts with "/hashtag" then
return "hashtagぺージは処理しない"
else if strPath is "" then
return "トップぺージは処理しない"
else if strPath is "/" then
return "トップぺージは処理しない"
end if

########################
##クエリーの有無をチェック
set recordRange to ocidURLComponents's rangeOfQuery()
set ocidLocation to location of recordRange
log ocidLocation ≠ refNSNotFound
if ocidLocation ≠ refNSNotFound then
  ########################
  ##【Aクエリーあり】
  set ocidQueryArray to ocidURLComponents's queryItems
  ##【Aー1】ラストパスで判定
  set strLastPath to ocidURL's lastPathComponent() as text
  ##【Aー1−1】ビデオ再生のwatchの場合
  if strLastPath is "watch" then
    ##queryItemsから各種ID
    repeat with itemQuery in ocidQueryArray
      set strQueryName to itemQuery's |name| as text
      if strQueryName is "v" then
        #再生中ビデオID
        set strVideoID to itemQuery's value as text
      else if strQueryName is "list" then
        #プレイリストのID
        set strPlayListID to itemQuery's value as text
      else if strQueryName is "index" then
        #プレイリストの曲順番号
        set strPlayListIndex to itemQuery's value as text
      end if
    end repeat
    ##【Aー1−2】プレイリスト画面の場合
  else if strLastPath is "playlist" then
    repeat with itemQuery in ocidQueryArray
      set strQueryName to itemQuery's |name| as text
      if strQueryName is "list" then
        #プレイリストのID
        set strPlayListID to itemQuery's value as text
      end if
    end repeat
  end if
else
  ########################
  ##【Bクエリー無し】
  if strPath starts with "/shorts" then
    set strVideoID to ocidURL's lastPathComponent() as text
  else if strPath starts with "/channel" then
    set strChannelID to ocidURL's lastPathComponent() as text
  else if strPath starts with "/@" then
    set ocidPathStr to refMe's NSString's stringWithString:(strPath)
    set ocidPathArray to ocidPathStr's componentsSeparatedByString:("/")
    set ocidCustomUrl to (ocidPathArray's objectAtIndex:(1))
    set strUserID to ocidCustomUrl's stringByReplacingOccurrencesOfString:("@") withString:("")
    set strCustomUrl to strUserID as text
  else if strPath starts with "/user/" then
    set ocidPathStr to refMe's NSString's stringWithString:(strPath)
    set ocidPathArray to ocidPathStr's componentsSeparatedByString:("/")
    set ocidCustomUrl to (ocidPathArray's objectAtIndex:(2))
    set strUserID to ocidCustomUrl as text
  else if strPath starts with "/c/" then
    set ocidPathStr to refMe's NSString's stringWithString:(strPath)
    set ocidPathArray to ocidPathStr's componentsSeparatedByString:("/")
    set ocidCustomUrl to (ocidPathArray's objectAtIndex:(2))
    set strCustomUrl to ocidCustomUrl as text
  end if
end if

########################
##APIURL 


if strVideoID ≠ (missing value) then
  #ビデオIDが見つかった場合のクエリー
  set strBaseURL to ("https://www.googleapis.com/youtube/v3/videos") as text
  set ocidBaseURLStr to refMe's NSString's stringWithString:(strBaseURL)
  set ocidBaseURL to refMe's NSURL's alloc()'s initWithString:(ocidBaseURLStr)
  set ocidBaseURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidBaseURL) resolvingAgainstBaseURL:(true)
  set ocidQueryArray to refMe's NSMutableArray's alloc()'s initWithCapacity:(0)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("part") value:("snippet")
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("id") value:(strVideoID)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("key") value:(strAPIkey)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("maxResults") value:("50")
ocidQueryArray's addObject:(ocidQueryItem)
  ###
else if strChannelID ≠ (missing value) then
  #チャンネルIDからユーザーIDを取得する場合
  set strBaseURL to ("https://www.googleapis.com/youtube/v3/channels") as text
  set ocidBaseURLStr to refMe's NSString's stringWithString:(strBaseURL)
  set ocidBaseURL to refMe's NSURL's alloc()'s initWithString:(ocidBaseURLStr)
  set ocidBaseURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidBaseURL) resolvingAgainstBaseURL:(true)
  set ocidQueryArray to refMe's NSMutableArray's alloc()'s initWithCapacity:(0)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("part") value:("snippet")
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("id") value:(strChannelID)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("key") value:(strAPIkey)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("maxResults") value:("50")
ocidQueryArray's addObject:(ocidQueryItem)
else if strUserID ≠ (missing value) then
  #ユーザーIDからチャンネルIDを検索
  set strBaseURL to ("https://www.googleapis.com/youtube/v3/search") as text
  set ocidBaseURLStr to refMe's NSString's stringWithString:(strBaseURL)
  set ocidBaseURL to refMe's NSURL's alloc()'s initWithString:(ocidBaseURLStr)
  set ocidBaseURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidBaseURL) resolvingAgainstBaseURL:(true)
  set ocidQueryArray to refMe's NSMutableArray's alloc()'s initWithCapacity:(0)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("part") value:("snippet")
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("q") value:(strUserID)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("type") value:("channel")
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("key") value:(strAPIkey)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("maxResults") value:("1")
ocidQueryArray's addObject:(ocidQueryItem)
else if strCustomUrl ≠ (missing value) then
  #ユーザーIDからチャンネルIDを検索
  set strBaseURL to ("https://www.googleapis.com/youtube/v3/search") as text
  set ocidBaseURLStr to refMe's NSString's stringWithString:(strBaseURL)
  set ocidBaseURL to refMe's NSURL's alloc()'s initWithString:(ocidBaseURLStr)
  set ocidBaseURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidBaseURL) resolvingAgainstBaseURL:(true)
  set ocidQueryArray to refMe's NSMutableArray's alloc()'s initWithCapacity:(0)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("part") value:("snippet")
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("q") value:(strCustomUrl)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("type") value:("channel")
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("key") value:(strAPIkey)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("maxResults") value:("1")
ocidQueryArray's addObject:(ocidQueryItem)
else if strPlayListID ≠ (missing value) then
  #playlistsからチャンネルIDを取得
  set strBaseURL to ("https://www.googleapis.com/youtube/v3/playlists") as text
  set ocidBaseURLStr to refMe's NSString's stringWithString:(strBaseURL)
  set ocidBaseURL to refMe's NSURL's alloc()'s initWithString:(ocidBaseURLStr)
  set ocidBaseURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidBaseURL) resolvingAgainstBaseURL:(true)
  set ocidQueryArray to refMe's NSMutableArray's alloc()'s initWithCapacity:(0)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("part") value:("id,snippet,status")
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("id") value:(strPlayListID)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("key") value:(strAPIkey)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("maxResults") value:("1")
ocidQueryArray's addObject:(ocidQueryItem)
end if

########################
##APIを呼び出すURL
ocidBaseURLComponents's setQueryItems:(ocidQueryArray)
set ocidOpenURL to ocidBaseURLComponents's |URL|()
set strOpenURL to ocidOpenURL's absoluteString() as text
log "呼び出したURL: " & strOpenURL

########################
##Get JSON
### 【1】JSONのURL
set ocidApiURL to ocidOpenURL
### 【2】URLの内容JSONをNSdataに格納
set ocidOption to (refMe's NSDataReadingMappedIfSafe)
set listReadData to refMe's NSData's alloc()'s initWithContentsOfURL:(ocidApiURL) options:(ocidOption) |error|:(reference)
set ocidReadData to (item 1 of listReadData)
### 【3】NSPropertyListSerializationしてレコードに
set ocidOption to (refMe's NSJSONReadingMutableContainers)
set listJSONSerialization to (refMe's NSJSONSerialization's JSONObjectWithData:(ocidReadData) options:(ocidOption) |error|:(reference))
set ocidPlistDict to item 1 of listJSONSerialization
##
set ocidItemsArray to (ocidPlistDict's valueForKey:("items"))
repeat with itemItemsDict in ocidItemsArray
  set ocidSnipetDict to (itemItemsDict's valueForKey:("snippet"))
  set ocidChannelID to (ocidSnipetDict's valueForKey:("channelId"))
  set ocidUserID to (ocidSnipetDict's valueForKey:("customUrl"))
  if ocidChannelID = (missing value) then
    set ocidChannelID to (itemItemsDict's valueForKey:("id"))
  end if
end repeat


################################
##ユーザーIDが取得出来なかった場合用
if ocidUserID = (missing value) then
  set strBaseURL to ("https://www.googleapis.com/youtube/v3/channels") as text
  set ocidBaseURLStr to refMe's NSString's stringWithString:(strBaseURL)
  set ocidBaseURL to refMe's NSURL's alloc()'s initWithString:(ocidBaseURLStr)
  set ocidBaseURLComponents to refMe's NSURLComponents's componentsWithURL:(ocidBaseURL) resolvingAgainstBaseURL:(true)
  set ocidQueryArray to refMe's NSMutableArray's alloc()'s initWithCapacity:(0)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("part") value:("snippet")
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("id") value:(ocidChannelID)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("key") value:(strAPIkey)
ocidQueryArray's addObject:(ocidQueryItem)
  set ocidQueryItem to refMe's NSURLQueryItem's alloc()'s initWithName:("maxResults") value:("50")
ocidQueryArray's addObject:(ocidQueryItem)
  ####
ocidBaseURLComponents's setQueryItems:(ocidQueryArray)
  set ocidOpenURL to ocidBaseURLComponents's |URL|()
  set strOpenURL to ocidOpenURL's absoluteString() as text
log "呼び出したURL: " & strOpenURL
  ### 【2】URLの内容JSONをNSdataに格納
  set ocidOption to (refMe's NSDataReadingMappedIfSafe)
  set listReadData to refMe's NSData's alloc()'s initWithContentsOfURL:(ocidOpenURL) options:(ocidOption) |error|:(reference)
  set ocidReadData to (item 1 of listReadData)
  ### 【3】NSPropertyListSerializationしてレコードに
  set ocidOption to (refMe's NSJSONReadingMutableContainers)
  set listJSONSerialization to (refMe's NSJSONSerialization's JSONObjectWithData:(ocidReadData) options:(ocidOption) |error|:(reference))
  set ocidPlistDict to item 1 of listJSONSerialization
  ##
  set ocidItemsArray to (ocidPlistDict's valueForKey:("items"))
  repeat with itemItemsDict in ocidItemsArray
    set ocidSnipetDict to (itemItemsDict's valueForKey:("snippet"))
    set ocidChannelID to (ocidSnipetDict's valueForKey:("channelId"))
    set ocidUserID to (ocidSnipetDict's valueForKey:("customUrl"))
    set strCustomUrl to ocidUserID as text
  end repeat
  
  
end if


########################
log "チャンネルID: " & ocidChannelID as text
log "ユーザーID: " & ocidUserID as text
log "カスタムチャンネルID: " & strCustomUrl as text

return


|

コピーしたURLをヘッダーとURLに分ける



tell application "Finder"
set strResponse to the clipboard as text
end tell


set AppleScript's text item delimiters to "'"
set listResponse to every text item of strResponse as list
set AppleScript's text item delimiters to ""
set strURL to (item 2 of listResponse) as text
-->>URL部分

set AppleScript's text item delimiters to "\\\r"
set listResponse to every text item of strResponse as list
set AppleScript's text item delimiters to ""
set strHeader to (items 2 thru (last item) of listResponse) as text
-->ヘッダー部分

|

[Youtube]ダウンロード・ヘルパー

WEBインスペクタを利用したダウンロードのヘルパー
ダウンロード
APIを利用してタイトルを取得
再エンコードまで実施
必須 ffmpegとYoutubeAPIキー



20220701160256_1628x842x144_0

20220701160306_1670x840x1440


#!/usr/bin/env osascript
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
#
#
(*

videoplayback

*)
#
#
# com.cocolog-nifty.quicktimer.icefloe
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
##自分環境がos12なので2.8にしているだけです
use AppleScript version "2.8"
use framework "Foundation"
use scripting additions


property objMe : a reference to current application
property objNSString : a reference to objMe's NSString
property objNSMutableString : a reference to objMe's NSMutableString

property objNSURL : a reference to objMe's NSURL
property objNSDictionary : a reference to objMe's NSDictionary

property objNSArray : a reference to objMe's NSArray
property objNSMutableArray : a reference to objMe's NSMutableArray

property objNSJSONSerialization : a reference to objMe's NSJSONSerialization


#############################################
####設定項目
set strPathToFFMPEG to "echo $HOME/bin/ffmpeg.5.0.2/ffmpeg" as text
set strPathToFFMPEG to (do shell script strPathToFFMPEG)


#############################################
tell application "System Events"
set listAppList to title of (every process where background only is false)
end tell
repeat with objAppList in listAppList
set strAppList to objAppList as text
if strAppList is "スクリプトエディタ" then
tell application "Script Editor"
if frontmost is true then
try
tell application "System Events" to click menu item "ログを表示" of menu "表示" of menu bar item "表示" of menu bar 1 of application process "Script Editor"
end try
end if
end tell
end if
end repeat
#############################################


property strAPIkey : "AIzaSyCeh3883bLyCSumkUcdQWjD20uuiZw0dIo" as text

#############################################
###URL取得 Safari
try
tell application "Safari"
activate
set the strURL to the URL of document 1 as text
end tell
if strURL does not contain "youtube.com" then
error "" number -128
end if
on error
###URL取得Chrome
tell application "Google Chrome"
activate
tell window 1
tell active tab
set strURL to URL as text
end tell
end tell
end tell
if strURL does not contain "youtube.com" then
error "" number -128
end if
end try

#############################################
set AppleScript's text item delimiters to "/"
set listURL to every text item of strURL as list
set AppleScript's text item delimiters to ""
set strQuery to last text item of listURL as text
#############################################
set toQuery to strQuery as text
####watchがある=閲覧画面のVideoID
set AppleScript's text item delimiters to "&"
set listQuery to every text item of toQuery as list
set AppleScript's text item delimiters to ""
repeat with objQuery in listQuery
set AppleScript's text item delimiters to "="
set listObjQuery to every text item of objQuery as list
set AppleScript's text item delimiters to ""
if (text item 1 of listObjQuery as text) is "watch?v" then
####VideoID
set strVideoID to (text item 2 of listObjQuery as text)
else if (text item 1 of listObjQuery as text) is "v" then
####VideoID
set strVideoID to (text item 2 of listObjQuery as text)
end if
if (text item 1 of listObjQuery as text) is "list" then
####プレイリスト再生の場合のプレイリストID
set strPlayListID to (text item 2 of listObjQuery as text)
end if
end repeat

log "strPlayListID:" & strPlayListID
log "strVideoID:" & strVideoID

#############################################
#####ビデオIDJSON取得
set ocidVideoContents to doGetVideoID2Contents(strVideoID)
###### pageInfo
set ocidPageInfo to |pageInfo| of ocidVideoContents
###### totalResults
set ocidTotalResults to |totalResults| of ocidPageInfo
###### items
set ocidItemes to |items| of ocidVideoContents
###### snippet
set ocidSnippet to snippet of ocidItemes
#######タイトル
set ocidTitle to title of ocidSnippet
set strTitle to ocidTitle as text

#############################################
log strTitle as text

set aliasIconPath to POSIX file "/Applications/Safari.app/Contents/Resources/AppIcon.icns" as alias
tell application "Finder"
set theResponse to the clipboard as text
end tell
try
activate
set objResponse to (display dialog "詳しく" with title "短め" default answer theResponse buttons {"OK", "キャンセル"} default button "OK" cancel button "キャンセル" with icon aliasIconPath giving up after 30 without hidden answer)
on error
log "エラーしました"
return "エラーしました"
error number -128
end try
if true is equal to (gave up of objResponse) then
return "時間切れですやりなおしてください"
error number -128
end if
if "OK" is equal to (button returned of objResponse) then
set strResponse to (text returned of objResponse) as text
else
log "エラーしました"
return "エラーしました"
error number -128
end if

#############################################

set AppleScript's text item delimiters to "&"
set listURL to every text item of strResponse
set AppleScript's text item delimiters to ""


set strNewURL to "" as text
set numCntRepeat to 0 as number
repeat with objUrl in listURL
set strUrlQuery to objUrl as text
#########mine別に判定しておく
if strUrlQuery is "mime=audio%2Fwebm" then
set strFileType to "AudioWebm" as text
else if strUrlQuery is "mime=video%2Fwebm" then
set strFileType to "VideoWebm" as text
else if strUrlQuery is "mime=audio%2Fmp4" then
set strFileType to "AudioMp4" as text
else if strUrlQuery is "mime=video%2Fmp4" then
set strFileType to "VideoMp4" as text
end if
#########rangeを置き換える
if objUrl starts with "range=" then
set objUrl to "range=0-9999999999999999999999999999999999999" as text

end if
if numCntRepeat = 0 then
set strNewURL to (objUrl as text) as text
else
set strNewURL to ("" & strNewURL & "&" & objUrl & "") as text
end if

set numCntRepeat to numCntRepeat + 1 as number
end repeat

log strNewURL

#################################################
set theComandText to ("echo `date '+%Y%m%d_%H%M%S'`") as text
set theDate to (do shell script theComandText) as text

set theComandText to ("mkdir -pm 777 /tmp/" & theDate & "") as text
do shell script theComandText

#############################################
###### ダウンロードURL
#############################################
#########判定したmime別にコマンドを整形
if strFileType is "AudioWebm" then
set theComandText to ("/usr/bin/curl -L -o '/tmp/" & theDate & "/Audio.webm' '" & strNewURL & "' --connect-timeout 20") as text

else if strFileType is "VideoWebm" then
set theComandText to ("/usr/bin/curl -L -o '/tmp/" & theDate & "/Video.webm' '" & strNewURL & "' --connect-timeout 20") as text

else if strFileType is "AudioMp4" then
set theComandText to ("/usr/bin/curl -L -o '/tmp/" & theDate & "/Audio.mp4' '" & strNewURL & "' --connect-timeout 20") as text

else if strFileType is "VideoMp4" then
set theComandText to ("/usr/bin/curl -L -o '/tmp/" & theDate & "/Video.mp4'' '" & strNewURL & "' --connect-timeout 20") as text

end if
log strFileType
log theComandText

#############################################
##### こっちは終了待たせたいのでapplescriptで実行
do shell script theComandText


(*
tell application "Terminal"
launch
activate
set objWindowID to (do script "\n\n")
delay 1
do script theComandText in objWindowID

end tell

delay 10
*)
#############################################
######webmmp3mp4に変換
#############################################
set strDownLoadFolder to (POSIX path of (path to downloads folder from user domain as alias)) as text
set strAudioDistFilePath to ("" & strDownLoadFolder & strTitle & ".mp3") as text
set strVideDistFilePath to ("" & strDownLoadFolder & strTitle & ".mp4") as text

#########判定したmime別にコマンドを整形
if strFileType is "AudioWebm" then
set strCommandText to ("\"" & strPathToFFMPEG & "\" -i \"/tmp/" & theDate & "/Audio.webm\" -vn -ab 320k -ar 44100 -y \"" & strAudioDistFilePath & "\"") as text
else if strFileType is "VideoWebm" then
set strCommandText to ("\"" & strPathToFFMPEG & "\" -i \"/tmp/" & theDate & "/Video.webm\" -vcodec libx264 \"" & strVideDistFilePath & "\"") as text
else if strFileType is "AudioMp4" then
set strCommandText to ("\"" & strPathToFFMPEG & "\" -i \"/tmp/" & theDate & "/Audio.mp4\" -vn -ab 320k -ar 44100 -y \"" & strAudioDistFilePath & "\"") as text
else if strFileType is "VideoMp4" then
set strCommandText to ("\"" & strPathToFFMPEG & "\" -i \"/tmp/" & theDate & "/Video.mp4\" -vcodec libx264 \"" & strVideDistFilePath & "\"") as text
end if

##### コマンド実行
tell application "Terminal"
launch
activate
set objWindowID to (do script "\n\n")
delay 1
do script strCommandText in objWindowID
end tell

###############################################################
### ビデオのコンテンツJSON
###############################################################

to doGetVideoID2Contents(toVideoID)
set strThumbnailsHTML to ""
set jsonVideoIDcontents to ""
set jsonVideoResponceURL to "https://www.googleapis.com/youtube/v3/videos?id=" & toVideoID & "&part=snippet,contentDetails,liveStreamingDetails,player,recordingDetails,statistics,status,topicDetails&key=" & strAPIkey & "" as text
############コマンド整形
set strCommandText to "/usr/bin/curl -X GET -H 'Content-Type: application/json;charset=UTF-8' \"" & jsonVideoResponceURL & "\" --connect-timeout 20"
####コマンド実行
set jsonVideoIDcontents to (do shell script strCommandText) as text
####戻り値を格納
set ocidVideoIDcontents to (objNSJSONSerialization's JSONObjectWithData:((objNSString's stringWithString:jsonVideoIDcontents)'s dataUsingEncoding:(objMe's NSUTF8StringEncoding)) options:0 |error|:(missing value))
return ocidVideoIDcontents
end doGetVideoID2Contents

|

YouTubeの『チャンネル』についてのメモ

ビデオID
https://www.youtube.com/watch?v=XXXXXXX
Shorts
https://www.youtube.com/shorts/XXXXXXX
チャンネルID
https://www.youtube.com/channel/XXXXXXX
カスタムURL 非推奨
https://www.youtube.com/c/XXXXXXX
ユーザーネーム
https://www.youtube.com/user/XXアカウントIDXX
カスタムURL()
https://www.youtube.com/@XXアカウントIDXX
これに
プレイリスト
https://www.youtube.com/playlist?list=XXXXXXX
ハッシュタグ
https://www.youtube.com/hashtag/
検索
https://www.youtube.com/results?search_query=XXXXXXX
フィード
https://www.youtube.com/feed/XXXXXXX
なんがか主要なURL構造ですが

チャンネルについて
例 村治佳織さんのチャンネル
20220623103214_1117x617x720
https://www.youtube.com/channel/UCHAXDtkVqgwHKKtxDyOjpfA
こちらは、最近アップロードされたビデオが登録されています
ビデオページLINKには
ものすごくビデオが登録されているように見えますが
実際は、まだ数本(この記事を書いた時点)で、それ以外のビデオは
音源等はYoutube Music用にメーカーが用意している
Kaori Muraji - Topic が『所有者』になっている
https://www.youtube.com/channel/UC16g1PV0a0DsJlUGEU-G7DA/featured
ただ、アーティストページであるかから?ビデオページにも表示されるといった
見た目と実際の登録ビデオ本数が異なるといったややこしいことになっています。
ユニバーサルからの音源はVEVOに数本チャンネル登録されています
https://www.youtube.com/user/KaoriMurajiVEVO/videos

このように、『音楽』アーティストの場合、登録ビデオについてがちょっとややこしい



20220623103151_1058x300x720
こんな風に
ワーナーがやっているチャンネル(登録できない)

運営がやっているチャンネルの2つ持ちのアーティストもいるので
(この場合、どちらも公式)
さらにややこしい

にしなの場合

チャンネル登録できるのはチャンネルAの@nishinaofficialのみ
チャンネルA
チャンネルID
https://www.youtube.com/channel/UCeJ-aTFXnVBofqL9JXqNSNA
アカウントID (ユーザーID)
https://www.youtube.com/@nishinaofficial
https://www.youtube.com/user/nishinaofficial
カスタムURL
https://www.youtube.com/c/nishinaofficial
カスタムURL
https://www.youtube.com/c/nishina_official
カスタムURL
https://www.youtube.com/c/nishina__official

チャンネルB
チャンネルID
https://www.youtube.com/channel/UCt8MwZ--umWKmmsDSB714ww
アカウントID (ユーザーID)
https://www.youtube.com/@nishina_official
https://www.youtube.com/user/nishina_official


チャンネルC本当に公式か?不明
https://www.youtube.com/channel/UCDx_u4uHnFeMzSQNNhj9xGA
アカウントID (ユーザーID)
https://www.youtube.com/@nishina__official
https://www.youtube.com/user/nishina__official

|

[YouTube Api V3] DataAPI PlayList から登録されている VideoID

注意点
プレイリストには『非公開』や『限定公開』のビデオも含まれているので
取得出来ない物が『ある』→エラー制御が必要



#!/usr/bin/env osascript
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
#
#
(*
API
https://developers.google.com/youtube/v3

コンソール
https://console.cloud.google.com/apis/dashboard?pli=1

*)
#
#
# com.cocolog-nifty.quicktimer.icefloe
----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
use framework "Foundation"
use AppleScript version "2.8"
use scripting additions

property objMe : a reference to current application
property objNSString : a reference to objMe's NSString
property objNSArray : a reference to objMe's NSArray
property objNSMutableArray : a reference to objMe's NSMutableArray

property objNSJSONSerialization : a reference to objMe's NSJSONSerialization

############設定項目 
####API ID
property strAPIkey : "ここにAPIキー " as text


####################################
property numMaxResults : 50 as number
####################################
property strVideoID : "" as text
property strPlayListID : "" as text
property strChannelID : "" as text
property strUserID : "" as text
property strUserName : "" as text
property strNextPageToken : "〓〓〓〓〓" as text
property listVideoID : {} as list


###URL取得 Safari
try
tell application "Safari"
activate
set the strURL to the URL of document 1 as text
end tell
if strURL does not contain "www.youtube.com" then
error "" number -128
end if
on error
###URL取得Chrome
tell application "Google Chrome"
activate
tell window 1
tell active tab
set strURL to URL as text
end tell
end tell
end tell
if strURL does not contain "www.youtube.com" then
error "" number -128
end if
end try

######
set AppleScript's text item delimiters to "/"
set listURL to every text item of strURL as list
set AppleScript's text item delimiters to ""
set strQuery to last text item of listURL as text
###############################################################
### チャンネルIDを取得する
###############################################################

if (text item 4 of listURL) starts with "watch" then
set toQuery to strQuery as text
####watchがある=閲覧画面のVideoID
set AppleScript's text item delimiters to "&"
set listQuery to every text item of toQuery as list
set AppleScript's text item delimiters to ""
repeat with objQuery in listQuery
set AppleScript's text item delimiters to "="
set listObjQuery to every text item of objQuery as list
set AppleScript's text item delimiters to ""
if (text item 1 of listObjQuery as text) is "watch?v" then
####VideoID
set strVideoID to (text item 2 of listObjQuery as text)
else if (text item 1 of listObjQuery as text) is "v" then
####VideoID
set strVideoID to (text item 2 of listObjQuery as text)
end if
if (text item 1 of listObjQuery as text) is "list" then
####プレイリスト再生の場合のプレイリストID
set strPlayListID to (text item 2 of listObjQuery as text)
end if
end repeat
#############チャンネルIDで呼び出している場合
else if (text item 4 of listURL) starts with "playlist" then
set toQuery to strQuery as text
####watchがある=閲覧画面のVideoID
set AppleScript's text item delimiters to "&"
set listQuery to every text item of toQuery as list
set AppleScript's text item delimiters to ""
repeat with objQuery in listQuery
set AppleScript's text item delimiters to "="
set listObjQuery to every text item of objQuery as list
set AppleScript's text item delimiters to ""
if (text item 1 of listObjQuery as text) is "list" then
####プレイリスト再生の場合のプレイリストID
set strPlayListID to (text item 2 of listObjQuery as text)
else if (text item 1 of listObjQuery as text) is "playlist?list" then
set strPlayListID to (text item 2 of listObjQuery as text)
end if
end repeat

####################################################
#############以下はチャンネルと関係ない
else if (text item 4 of listURL) starts with "results" then
return "検索結果からは取得できません"
else if (text item 4 of listURL) is "hashtag" then
return "hashtagページからは取得できません"
else if (text item 4 of listURL) is "" then
return "プレイリストページ以外からは取得できません"
else
return "プレイリストページ以外からは取得できません"
end if

###############################################################
###############################################################
if (strPlayListID as text) is "msng" then
set strPlayListID to "未設定です" as text
end if
log "カスタムURL" & strPlayListID
log "チャンネルID" & strPlayListID
log "処理終了"
###############################################################
###############################################################

set ocidPlayListVideoList to doGetPlayList2VideoID(strPlayListID, strNextPageToken)

set numTotalResults to item 1 of ocidPlayListVideoList as number
set strNextPageToken to item 2 of ocidPlayListVideoList as text

repeat
if strNextPageToken is "〓〓〓〓〓" then
log "EXIT:〓〓〓〓〓"
exit repeat
else
set ocidPlayListVideoList to doGetPlayList2VideoID(strPlayListID, strNextPageToken)
set strNextPageToken to item 2 of ocidPlayListVideoList as text
end if
end repeat
log listVideoID as list
### listVideoID に プレイリストのビデオIDがリストで入っている
###############################################################
###############################################################
### listVideoID のリスト数だけ処理を繰り返す
set strCnt4Log to 1
repeat with strVideoID in listVideoID

log strCnt4Log & ":" & strVideoID as text
set strCnt4Log to strCnt4Log + 1

end repeat

###ここまで
return
###############################################################
###############################################################
to doGetPlayList2VideoID(toPlayListID, toNextPageToken)
####NextPageTokenの有無でURLがかります
if toNextPageToken is "〓〓〓〓〓" then
####URL整形
set strPlaylistItemstUrl to ("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=" & toPlayListID & "&key=" & strAPIkey & "&maxResults=" & numMaxResults & "") as text
else
####URL整形
set strPlaylistItemstUrl to ("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=" & toPlayListID & "&key=" & strAPIkey & "&maxResults=" & numMaxResults & "&pageToken=" & toNextPageToken & "") as text
end if
####コマンド整形
set strCommandText to "/usr/bin/curl -X GET -H 'Content-Type: application/json;charset=UTF-8' \"" & strPlaylistItemstUrl & "\""
####コマンド実行
set jsonPlistResponse to (do shell script strCommandText) as text
####戻り値を格納
set ocidPlistResJson to (objNSJSONSerialization's JSONObjectWithData:((objNSString's stringWithString:jsonPlistResponse)'s dataUsingEncoding:(objMe's NSUTF8StringEncoding)) options:0 |error|:(missing value))
####プレイスとに含まれるビデオの本数
set strTotalResults to (totalResults of |pageInfo| of ocidPlistResJson) as text
set numTotalResults to strTotalResults as number
####50以上の場合次ページがあるのでnextPageToken
if numTotalResults > 50 then
###次のページ用のnextPageToken
try
set strNextPageToken to |nextPageToken| of ocidPlistResJson as text
on error
set strNextPageToken to "〓〓〓〓〓" as text
end try
else
set strNextPageToken to "〓〓〓〓〓" as text
end if
set ocidPlistItems to |items| of ocidPlistResJson


###Jsonitemsの数だけ繰り返す
repeat with objPlistItems in ocidPlistItems
set ocidVideoID to |videoId| of resourceId of snippet of objPlistItems
set strVideoID to ocidVideoID as text
copy strVideoID to end of listVideoID
end repeat
return {strTotalResults, (strNextPageToken as text)}
end doGetPlayList2VideoID

|

その他のカテゴリー

Acrobat Acrobat Annotation Acrobat Dialog Acrobat Form Acrobat JS Acrobat Open Acrobat Plugin Acrobat python Acrobat Reader Acrobat Sequ Acrobat Stamps Admin Admin Account Admin Apachectl Admin configCode Admin Device Management Admin LaunchServices Admin Locationd Admin loginitem Admin Maintenance Admin Permission Admin Pkg Admin Power Management Admin Printer Admin SetUp Admin SMB Admin System Information Admin Tools Admin Users Admin Volumes Adobe Apple AppleScript AppleScript Guide AppleScript Accessibility AppleScript AppKit AppleScript Applications AppleScript AppStore AppleScript Archive AppleScript Attributes AppleScript Automator AppleScript AVAsset AppleScript AVconvert AppleScript AVFoundation AppleScript AVURLAsset AppleScript BackUp AppleScript Barcode AppleScript Bash AppleScript Basic AppleScript Basic Path AppleScript Bluetooth AppleScript BOX AppleScript Browser AppleScript Calendar AppleScript CD/DVD AppleScript Choose AppleScript Chrome AppleScript CIImage AppleScript CloudStorage AppleScript Color AppleScript com.apple.LaunchServices.OpenWith AppleScript Console AppleScript Contacts AppleScript CotEditor AppleScript CURL AppleScript current application AppleScript Date&Time AppleScript delimiters AppleScript Desktop AppleScript Device AppleScript Disk AppleScript do shell script AppleScript Dock AppleScript DropBox AppleScript eMail AppleScript Encode Decode AppleScript Error AppleScript EXIFData AppleScript ffmpeg AppleScript File AppleScript Finder AppleScript Firefox AppleScript Folder AppleScript Fonts AppleScript GIF AppleScript HTML AppleScript Icon AppleScript Illustrator AppleScript Image Events AppleScript Image2PDF AppleScript ImageOptim Applescript iWork AppleScript Javascript AppleScript Jedit AppleScript Json AppleScript Label AppleScript List AppleScript locationd AppleScript LRC AppleScript LSSharedFileList AppleScript m3u8 AppleScript MakePDF AppleScript Map AppleScript Math AppleScript Microsoft AppleScript Microsoft Edge AppleScript Microsoft Excel AppleScript Mobileconfig AppleScript Mouse AppleScript Movie AppleScript Music AppleScript NetWork AppleScript Notes AppleScript NSArray AppleScript NSBitmapImageRep AppleScript NSBundle AppleScript NSCFBoolean AppleScript NSCharacterSet AppleScript NSColor AppleScript NSColorList AppleScript NSData AppleScript NSDictionary AppleScript NSError AppleScript NSEvent AppleScript NSFileAttributes AppleScript NSFileManager AppleScript NSFont AppleScript NSFontManager AppleScript NSImage AppleScript NSIndex AppleScript NSKeyedArchiver AppleScript NSKeyedUnarchiver AppleScript NSLocale AppleScript NSMutableArray AppleScript NSMutableDictionary AppleScript NSMutableString AppleScript NSNotFound AppleScript NSNumber AppleScript NSOpenPanel AppleScript NSPasteboard AppleScript NSPDFImageRep AppleScript NSpoint AppleScript NSPredicate AppleScript NSRange AppleScript NSRegularExpression AppleScript NSRunningApplication AppleScript NSScreen AppleScript NSSize AppleScript NSString AppleScript NSStringCompareOptions AppleScript NSTask AppleScript NSTimeZone AppleScript NSURL AppleScript NSURL File AppleScript NSURLBookmark AppleScript NSURLComponents AppleScript NSURLResourceKey AppleScript NSUserDefaults AppleScript NSUUID AppleScript NSView AppleScript NSWorkspace AppleScript Numbers AppleScript OAuth AppleScript ObjC AppleScript OneDrive AppleScript Osax AppleScript PDF AppleScript PDFAnnotationWidget AppleScript PDFContext AppleScript PDFDisplayBox AppleScript PDFDocumentPermissions AppleScript PDFKit AppleScript PDFnUP AppleScript PDFOutline AppleScript Photos AppleScript Photoshop AppleScript Plist System Events AppleScript PostScript AppleScript prefPane AppleScript Preview AppleScript Python AppleScript QR AppleScript QR Decode AppleScript QuickLook AppleScript QuickTime AppleScript record AppleScript Regular Expression AppleScript Reminders AppleScript ReName AppleScript Repeat AppleScript RTF AppleScript Safari AppleScript SaveFile AppleScript ScreenCapture AppleScript ScreenSaver AppleScript Script Editor AppleScript Script Menu AppleScript Shortcuts AppleScript Shortcuts Events AppleScript Sort AppleScript Sound AppleScript Spotlight AppleScript SRT AppleScript StandardAdditions AppleScript stringByApplyingTransform AppleScript System Events AppleScript System Settings AppleScript TemporaryItems AppleScript Terminal AppleScript Text AppleScript Text CSV AppleScript Text TSV AppleScript TextEdit AppleScript Translate AppleScript Trash AppleScript Twitter AppleScript UI AppleScript Unit Conversion AppleScript UTType AppleScript valueForKeyPath AppleScript Video AppleScript VisionKit AppleScript Visual Studio Code AppleScript webarchive AppleScript webp AppleScript Wifi AppleScript XML AppleScript XML EPUB AppleScript XML OPML AppleScript XML Plist AppleScript XML RSS AppleScript XML SVG AppleScript XML TTML AppleScript XML webloc AppleScript YouTube AppleScript Zero Suppress Applications Barcode OnLine Tools CityCode Design iPhone List Logs lsappinfo Memo Music perl PlistBuddy pluginkit postalcode ReadMe SF Symbols character id SF Symbols Entity sips Skype Slack sqlite TCC Tools Typography Video Wacom zoom