# rddb.pm # # rhrdlibs # # Copyright (C) 2015-2016 Christian Pointner # # This file is part of rhrdlibs. # # rhrdlibs is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # any later version. # # rhrdlibs is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with rhrdlibs. If not, see . # package RHRD::utils; use strict; use POSIX; use DateTime; use DateTime::TimeZone; use LWP::Simple; use URI::Fetch; use JSON::MaybeXS; use URI::QueryParam; sub get_rd_week { my ($time) = @_; # # This computes the current Rivendell Week based on the number # of weeks since epoch. # # Explanation: # epoch was at 01.01.1970 which was a Thursday. # Monday in that week is (s-from-epoch + 3*24*60*60) seconds ago. # This needs to be adjusted by the timezone offset for Europe/Vienna # which is of course not constant (damn you daylight savings time) # Divide this by (7*24*60*60) and you get the number of # weeks since the Monday in the week of epoch adjusted for timezone offsets. # This week had week number 3 so add an offset of 2 and # get the modulo of 4. This rounded down gives you the current week # with 0 meaning Week 1. So add 1 to that number and you will get # the current RD week. # if(!defined($time)) { $time = DateTime->now(); } my $tz = DateTime::TimeZone->new(name => 'Europe/Vienna'); my $tz_offset = $tz->offset_for_datetime($time); my $sEpoch = $time->epoch() + $tz_offset; my $week = floor(((($sEpoch + 259200)/604800) + 2) % 4) + 1; return $week; } use constant { DB_PARAM_TYPE_HINT => "only S, M and J are allowed with S -> Show, M -> Musicpool, J -> Jingles", DB_PARAM_RHYTHM_HINT => "only 0 or 1 are allowed, length must be exactly 4 and it must not be '0000'", DB_PARAM_DOW_HINT => "must be between 1 and 7 (1=Monday, ..., 7=Sunday)", DB_PARAM_STARTTIME_HINT => "must be in format HHMM (without seperator) in 24 hour format", DB_PARAM_LEN_HINT => "must be a positive number below 1440", CMDLINE_WEEK_HINT => "must be one of W1, W2, W3, W4", CMDLINE_DOW_HINT => "must be one of MO, TU, WE, TH, FR, SA, SU", # this is a subset of the colors from: stackoverflow.com/questions/2328339 POOL_COLORS => ["FFFFFF", "FFFF00", "1CE6FF", "FF34FF", "FF4A46", "008941", "006FA6", "FFDBE5", "7A4900", "0000A6", "63FFAC", "B79762", "004D43", "8FB0FF", "5A0007", "809693", "FEFFE6", "4FC601", "3B5DFF", "4A3B53", "FF2F80", "61615A", "BA0900", "6B7900", "00C2A0", "FFAA92", "FF90C9", "B903AA", "7B4F4B", "A1C299", "0AA6D8", "00846F", "997D87", "D16100", "6A3A4C", "FFB500", "C2FFED", "A079BF", "CC0744", "C0B9B2", "C2FF99", "012C58", "00489C", "6F0062", "0CBD66", "EEC3FF", "B77B68", "7A87A1", "788D66", "885578", "FAD09F", "FF8A9A", "D157A0", "BEC459", "0086ED", "886F4C", "549E79", "FFF69F", "72418F", "BC23FF", "99ADC0", "3A2465", "922329", "5B4534", "404E55", "0089A3", "CB7E98", "A4E804", "324E72", "A30059", "B4A8BD", "452C2C", "636375", "A3C8C9", "9B9700", "D0AC94", "FF6832", "575329", "00FECF", "B05B6F", "8CD0FF", "1E6E00", "66E1D3", "CFCDAC", "A77500", "6367A9", "A05837", "772600", "D790FF", "5B4E51", "8ADBB4", "83AB58", "D1F7CE", "C8D0F6", "A3A489", "806C66", "BF5650", "66796D", "DA007C", "FF1A59"] }; sub get_musicpool_color { my ($num) = @_; $num = 0 if($num < 0 || $num > $#{+POOL_COLORS}); return POOL_COLORS->[$num]; } sub dropbox_param_type_ok { my ($type) = @_; unless(defined($type) && ($type == 'S' || $type == 'M' || $type == 'J')) { return (0, "unkown type '" . (defined($type) ? $type : 'undef') . "'", DB_PARAM_TYPE_HINT); } return (1, 'OK', DB_PARAM_TYPE_HINT); } sub dropbox_param_rhythm_ok { my ($rhythm) = @_; if(!defined($rhythm) || $rhythm !~ m/^[01]{4}$/ || $rhythm eq '0000') { return (0, "rhythm '" . (defined($rhythm) ? $rhythm : 'undef') . "' contains illegal characters or is too long/short", DB_PARAM_RHYTHM_HINT); } return (1, 'OK', DB_PARAM_RHYTHM_HINT); } sub dropbox_param_dow_ok { my ($dow) = @_; if(!defined($dow) || $dow < 1 || $dow > 7) { return (0, "dow '" . (defined($dow) ? $dow : 'undef') . "' is out of bounds", DB_PARAM_DOW_HINT); } return (1, 'OK', DB_PARAM_DOW_HINT); } sub dropbox_param_starttime_ok { my ($starttime) = @_; if(!defined($starttime) || $starttime !~ m/^[0-2][0-9][0-5][0-9]$/ || $starttime > 2359) { return (0, "starttime '" . (defined($starttime) ? $starttime : 'undef') . "' is not a valid clock time", DB_PARAM_STARTTIME_HINT); } return (1, 'OK', DB_PARAM_STARTTIME_HINT); } sub dropbox_param_len_ok { my ($len) = @_; if(!defined($len) || $len <= 0 || $len > 1440) { return (0, "len '" . (defined($len) ? $len : 'undef') . "' is out of bounds", DB_PARAM_LEN_HINT); } return (1, 'OK', DB_PARAM_LEN_HINT); } sub cmdline_rdweek { my ($dow) = @_; if(uc($dow) eq "W1") { return (1, 'OK', CMDLINE_WEEK_HINT); } elsif(uc($dow) eq "W2") { return (2, 'OK', CMDLINE_WEEK_HINT); } elsif(uc($dow) eq "W3") { return (3, 'OK', CMDLINE_WEEK_HINT); } elsif(uc($dow) eq "W4") { return (4, 'OK', CMDLINE_WEEK_HINT); } return (undef, 'invalid week', CMDLINE_WEEK_HINT); } sub cmdline_dow { my ($dow) = @_; if(uc($dow) eq "MO") { return (1, 'OK', CMDLINE_DOW_HINT); } elsif(uc($dow) eq "TU") { return (2, 'OK', CMDLINE_DOW_HINT); } elsif(uc($dow) eq "WE") { return (3, 'OK', CMDLINE_DOW_HINT); } elsif(uc($dow) eq "TH") { return (4, 'OK', CMDLINE_DOW_HINT); } elsif(uc($dow) eq "FR") { return (5, 'OK', CMDLINE_DOW_HINT); } elsif(uc($dow) eq "SA") { return (6, 'OK', CMDLINE_DOW_HINT); } elsif(uc($dow) eq "SU") { return (7, 'OK', CMDLINE_DOW_HINT); } return (undef, 'invalid day-of-week', CMDLINE_DOW_HINT); } sub fetch_parse_json { my ($url, $ua_str, $headers, $queries) = @_; my $uri = URI->new($url); if (defined $queries) { while(my ($name, $value) = each %{$queries}) { $uri->query_param($name => $value); } } $ua_str = "Radio Helsinki Rivendell Utilities" unless $ua_str; my $ua = LWP::UserAgent->new; $ua->agent($ua_str); $ua->env_proxy; if (defined $headers) { while(my ($field, $value) = each %{$headers}) { $ua->default_header($field, $value); } } my $res = URI::Fetch->fetch($uri, UserAgent => $ua) or return (0, URI::Fetch->errstr); if($res->status == URI::Fetch::URI_GONE()) { return (0, "This resource has been permanently removed"); } my $json = $res->content; my $data; eval { my $j = JSON::MaybeXS->new(utf8 => 0); $data = $j->decode($json); 1; } or do { return (0, "error parsing import result"); }; return (1, $data); } return 1;