Removing references of SongsPk.info from downloaded bollywood songs

If you are a software engineer from India, you must have downloaded Bollywood songs from Songspk.info or one of its clone sites at least once. Its a nice service for sure but they definitely have their own quirks. Checking the music file in Windows explorer or Media player will show songspk.info in multiple place including in file names and all the tags. They definitely deserve to do it given the service they provide but I intend to remove that information from downloaded files to keep them short and clean in my media players and hence decided to use Powershell for some automation. Result of that effort is as follows

Before using this, make sure to download taglib-sharp on some folder as it needs to be loaded. Before running any command, make sure to run it with -Whatif parameter to understand what it will do. Code is divided into 3 sections. I intend to add function for modifying tags with multiple values later on. I am greatly indebted to all bloggers on powershell and especially stackoverflow for helping me along the way. They are too many to list out here.


Function Check-TagLibLoad()
{

#validate if taglib-sharp is loaded or not
$taglibload = [System.AppDomain]::CurrentDomain.GetAssemblies() | `
Select-Object -Property FullName | `
Select-String -Pattern "taglib-sharp"
if (!$taglibload){
Throw "Load Taglib using [Reflection.assembly]::LoadFrom(<Full path of downloaded taglib-sharp dll like D:\temp\taglib-sharp-2.1.0.0-windows\Libraries\taglib-sharp.dll>)"
}
}

Function Rearrange-Patterns()
{
# Rearranges array so that if string A is part of B, A comes after B
Param(
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$true)]
[String[]]$Patterns
)
[System.Collections.Generic.List[System.String]]$PatternsTemp = $Patterns | Sort-Object -Unique
for ($cnt1 = 1; $cnt1 -lt $PatternsTemp.Count; $cnt1++){
do{
$found = $false
for ($cnt2 = 0; $cnt2 -lt $cnt1; $cnt2++){
if ($PatternsTemp[$cnt1].Length -le $PatternsTemp[$cnt2].Length){
continue
}
if ($PatternsTemp[$cnt1] -match $PatternsTemp[$cnt2]){
$PatternsTemp.Insert($cnt2,$PatternsTemp[$cnt1])
$PatternsTemp.RemoveAt($cnt1+1)
$found = $true
break
}
}
}while($found -eq $true)
}
$PatternsTemp
}
# Rearrange-Patterns -Patterns "Songspk.info","songs","- Songspk.info","so","pk","info","Songspk","[Songs]"

This function uses above two functions. Save all three in one file and then dot source that file and use this function through pipe lining. Make sure to run with -WhatIf first and carefully examine output.

Function Update-Simple-tags()
{

# Update tags with simple non-array values
[CmdletBinding()]
Param(
[ValidateNotNullOrEmpty()]
[Parameter( Position=0, Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[Alias('FullName')]
[String[]]$FilePath,
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$true)]
[string[]]$RemovePatterns,
[switch]$WhatIf
)
begin{
Check-TagLibLoad
$RemovePatterns = Rearrange-Patterns -Patterns:$RemovePatterns
}
Process
{
Unblock-File -LiteralPath:$FilePath

$Music = [taglib.file]::create($FilePath)
$TagList = @("Title", "Comment", "Lyrics", "Conductor", "Copyright")
$Update = $False
$Message = @("$FilePath")

foreach ($tag in $taglist)

{
$OldTagVal = $Music.tag.$tag
$RemovePatterns | ?{$Music.tag.$tag -Match $_} |

%{
$Music.tag.$tag = ($Music.tag.$tag -replace $_, "").Trim()
$Update = $true
}
if ($update -eq $true) {
$Message += (" '$Tag': '$OldTagVal' to '"+$Music.tag.$tag+"'")}
else{
$Message += (" '$Tag': No Update")
}
$Update = !($Whatif)
}
if ($Update -eq $true) {
$Music.save()
}
$Message
}
End{
}
}

# dir -filter 2015* -Directory | %{dir -Path $_ -Filter *.mp3 -File} | Update-Simple-tags -RemovePatterns "Songspk.info","- Songspk.info","www.SongsPk.Info" -WhatIf  | Out-File Update.log
# dir -filter 2015* -Directory | %{dir -Path $_ -Filter *.mp3 -File} | Update-Simple-tags -RemovePatterns "Songspk.info","- Songspk.info","www.SongsPk.Info" | Out-File Update.log

Below are some commands that can be used to edit downloaded files before running above functions to ensure files are in good naming convention to be modified. Names with ‘[‘ in them are tough to handle otherwise. Unblocking is needed since files are downloaded from internet. Rename-Item cannot work with file with special characters hence Move-Item. Make sure to use -WhatIf beforehand with each command. There is a blog post that talks about unzipping zipped file from Powershell but you can discover that if needed.

#Dir -Filter 2015-*.zip | Unblock-File
#Dir -Filter 2016* -Directory | Move-Item -Destination {$_.FullName -replace "320kbps",""}
#Dir -Filter 2016* -Directory | Move-Item -Destination {$_.FullName -replace "\[Songspk.info\]",""}
#Dir -Filter *-2015.zip | Move-Item -Destination {"2015-"+($_.Name -replace "-2015","")}
#Dir -Filter 2016* -Directory | %{dir -Path $_ -recurse -File} | Move-Item -Destination {$_.FullName -replace "\[Songspk.info\] ",""}
#Dir -Filter *2016* -Directory | | Move-Item -Destination {$_.Name -replace "\[Songspk.info\] ",""}
#[Reflection.Assembly]::LoadFrom("D:\temp\taglib-sharp-2.1.0.0-windows\Libraries\taglib-sharp.dll")

Time zone of a tweet

It took me considerable time for me to decipher, but I finally managed to figure out few idiosyncrasies about Timezones used in a tweet. Twitter uses a simple mechanism when displaying tweet time to you on Twitter.com.

  • If you are logged in, time shown will be of Timezone set in your profile.
  • If you are not logged in, time will be shown in San francisco, USA timezone which is local timezone of twitter HQ.

At no time, it seems to care for system timezone.

As per some research, apparently, it saves the information in the database in GMT based values, but even APIs return values converted to profile timezone. Second case will not occur with API usage since Non-logged in user cannot call API directly. APIs do not seems to save daylight saving information so that will need to be deduced. It though contains UTC offset but its of the API caller not tweet poster. This thus rules out possibility of deducing location through timezone data if location info is not shared by Tweet poster.

To convert time of a tweet to the time of a location, various tools can be used. Most useful seems like https://www.timeanddate.com/worldclock/converter.html . You can provide multiple target cities in this one.

To avoid doing all this, you can use storify.com and copy the tweet there after creating an account and editing default story. Its settings allows one to change timezone of a story to the timezone of your target tweets thus giving this whole information easily.