How to validate youtube video ids? - validation

I want to validate youtube video ids sbumitted in the URL to one of my sites before accessing the Youtube API, but I don't know what the allowed characters are in such an id. I see people on the net guessing it can contain numbers and characters, but I haven't yet seen an official specification of these video ids.
Is there one?

See this thread for official info.
you can hit this: http://gdata.youtube.com/feeds/api/videos/VIDEO_ID (Page now returns: "No longer available".)
and determine if the video is valid based on response
There's no way you can check the validity of the ID with RegEx, since not all alpha-numeric values are valid ID's.
p.s. i'm pretty sure i saw "dashes" in video ID's
p.p.s. "underscore" is a valid character also: http://www.youtube.com/watch?v=nrGk0AuFd_9
[a-zA-Z0-9_-]{11} is the regex (source), but there's no guarantee that the video will be there even if regex is valid

With v3 of the YouTube API I achieved this by calling:
GET https://www.googleapis.com/youtube/v3/videos?part=id&id=Tr5WcGSDqDg&key={YOUR_API_KEY}
This returns something like:
{
"kind": "youtube#videoListResponse",
"etag": "\"dc9DtKVuP_z_ZIF9BZmHcN8kvWQ/P2cGwKgbH6EYZAGxiKCZSH8R1KY\"",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
},
"items": [{
"kind": "youtube#video",
"etag": "\"dc9DtKVuP_z_ZIF9BZmHcN8kvWQ/Rgd0_ApwigPcJHVX1Z2SIQ5FJtU\"",
"id": "Tr5WcGSDqDg"
}]
}
So you can just do a check:
if(json.hasOwnProperty('pageInfo') && json.pageInfo.totalResults === 1) {
if(items[0].kind==='youtube#video') {
//valid video ID
}
}

If you are looking for a quicker and more scalable solution I would say to use REGEX with some logging/fallback for errors to be pro-active if YouTube changes their ID in the future.
I've been working with the YouTube API for a while now, dealing with millions of videos. Looping through them, I found this to be the most ideal:
/^[A-Za-z0-9_-]{11}$/
A more detailed example say in PHP:
public static function validId($id) {
return preg_match('/^[a-zA-Z0-9_-]{11}$/', $id) > 0;
}

I solved this issue in the same way Roman recommended. In my helper:
Be sure to include your requires at the top of the file:
require "net/http"
require "uri"
Then:
def validate_id(youtube_id)
uri = URI.parse("http://gdata.youtube.com/feeds/api/videos/#{ youtube_id }")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
%Q{ #{response.code} }
end
Be sure there is no white space between the brackets in "#{response.code}"
Lastly, compare it to the desired response:
def youtube_data(youtube_id)
if validate_id(youtube_id) == "200"
#video is good code
else %Q{ Video is no longer valid }
end
end

Here is a simple implementation in JavaScript:
async function validVideoId(id) {
const url = "http://img.youtube.com/vi/" + id + "/mqdefault.jpg";
const { status } = await fetch(url);
if (status === 404) return false;
return true;
}
console.log(validVideoId('60ItHLz5WEA'));

I just look to see if it is alphanumeric with possible dash or not. You might want to look into oEmbed, you can query YouTube to see if the ID is a valid video or not.

Here is a simple implementation of Roman's approach in PHP:
function validYoutube($id){
$id = trim($id);
if (strlen($id) === 11){
$file = #file_get_contents('http://gdata.youtube.com/feeds/api/videos/'.$id);
return !!$file;
}
return false;
}
And here are the tests:
echo validYoutube('Nv7U6_WhqvQ');
echo validYoutube('Nv7U6_Whqvf');
echo validYoutube('Nv7U6_Whqzz');

I think this works for checking if the video exists or not. Other validation can be done using REGEX as mentioned above. (Implemented using PHP)
public function verifyVideoID($videoID) {
parse_str(file_get_contents("http://youtube.com/get_video_info?el=detailpage&video_id=".$videoID), $info);
if (isset($info['errorcode'])) {
$response = ['response' => false];
return response()->json($response);
} else {
$response = ['response' => true];
return response()->json($response);
}
}

Here's one I came up with from combining info from other answers here and elsewhere:
function validId($id) {
return preg_match('/^[a-zA-Z0-9_-]{11}$/', $id) > 0;
}
function isvalYtube($url) {
$purl = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));
if (!strpos($url, 'youtu.be/') && ($purl != 'youtu.be')) {
if (strpos($url, 'watch') && ($purl = 'youtube.com')) {
parse_str(parse_url($url, PHP_URL_QUERY), $id);
if (!empty($id['v'])) { return(validId($id['v']) ? true : false); } else { return false; }
}
} else {
if (!empty(basename($url))) { return(validId(basename($url)) ? true : false); } else { return false; }
}
}
echo isvalYtube($url) ? 'valid link' : 'invalid link';
First function checks if we're dealing with a valid Youtube video ID.
Second function simply checks if it's a valid youtube VIDEO LINK or VIDEO from PLAYLIST LINK, excluding channel links.
Note: It doesn't determine if it's an active video nor does it check if it exists or not. These functions act merely as Youtube video-link syntax checkers and should be treated as such.
Usage examples:
$url = 'http://www.youtube.com/watch?v=o_QBk4VwnIA';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'valid link'
$url = 'http://youtu.be/o_QBk4VwnIA';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'valid link'
$url = 'http://www.youtube.com/watch?v=o_QBk4VwnIA&feature=youtu.be';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'valid link'
$url = 'https://www.youtube.com/watch?v=Sq3eLdixvCc&list=OLAK5uy_nvaYLo9AG_rZyqkXzYlkJfLjBuZS84bIU';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'valid link'
$url = 'https://www.youtube.com/channel/UCMPQY9gW0hQ9e_-IdQUKEAw';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'invalid link'

Simple use this code:
public class HelloWorld{
public static void main(String []args){
String expression = "^.*((youtu.be"+ "\\/)" + "|(v\\/)|(\\/u\\/w\\/)|(embed\\/)|(watch\\?))\\??v?=?([^#\\&\\?]*).*"; // var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
String video_url = "https://www.youtube.com/watch?v=as3tGTN2u98";
if (video_url.matches(expression)) {
System.out.println("It's valid");
}
}
}

Related

Retrieve value from json based on key provided using cypress

let expectedKey = 'Student';
cy.readFile('cypress/fixtures/applicationDetails.json').then((appDetails) => {
if(expectedKey === 'Student'){
cy.get('app-screen').find('#code-details').should('have.text', appDetails.studentCode);
}
if(expectedDKey === 'Department'){
cy.get('app-screen').find('#code-details').should('have.text', appDetails.departmentCode);
}
if(expectedKey === 'Paper'){
cy.get('app-screen').find('#code-details').should('have.text', appDetails.paperCode);
}
if(expectedKey === 'Results'){
cy.get('app-screen').find('#code-details').should('have.text', appDetails.resultsCode);
}
}
I don't want to use these many if blocks as there will more keys in the future. Instead, I have to pick the required value for studentCode, departmentCode, paperCode, or resultsCode from JSON based on expectedKey. Any help please?
You can access object properties by dot notation (foo.bar) or bracket notation (foo['bar']). In your case, you'll have to ensure expectedKey matches a valid key in your object with assertion before the cy commands.
let expectedKey = 'studentCode';
cy.readFile('cypress/fixtures/applicationDetails.json').then((appDetails) => {
expect(appDetails, 'valid key').to.have.property(expectedKey)
cy.get('app-screen').find('#code-details').should('have.text', appDetails[expectedKey]);
}
Assuming that you have the expectedKey inside the cy.readFile(), you can do like this:
Create a custom command at cypress/support/commands.js:
Cypress.Commands.add('codeDetailsText', (expectedKey, appDetails) => {
expectedKeyCode = expectedKey.toLowerCase() + 'Code'
cy.get('app-screen')
.find('#code-details')
.should('have.text', appDetails[expectedKeyCode])
})
In your test just write:
cy.readFile('cypress/fixtures/applicationDetails.json').then((appDetails) => {
//Assuming expectedKey value is available here
cy.codeDetailsText(expectedKey, appDetails)
})

Is that possible to use IF statement to get data from database and save it into String?

I want to get some record from tbl_jadwal and save it into string in my laravel.
This is my code,
$get_time = if (now()->isMonday()) {
return DB::table('tbl_jadwal')->where('Hari', 'Senin')->value('Jadwal_masuk');
} else if(now()->isSaturday()) { {
return DB::table('tbl_jadwal')->where('Hari', 'Sabtu')->value('Jadwal_masuk');
};
$time = $get_time;
but i got message syntax error, unexpected token "if", is there any other way to solve this problem ?
Broadly speaking you can do:
if (now()->isMonday()) {
$get_time = DB::table('tbl_jadwal')->where('Hari', 'Senin')->value('Jadwal_masuk');
} else if(now()->isSaturday()) { {
$get_time = DB::table('tbl_jadwal')->where('Hari', 'Sabtu')->value('Jadwal_masuk');
}
// Caution: $get_time may not be defined here
return $get_time??null;
You can also use when:
if (!now()->isSaturday() && !now()->isMonday()) { return null; }
return DB::table('tbl_jadwal')
->when(now()->isSaturday(), function ($q) { $q->where('Hari', 'Sabtu'); )
->when(now()->isMonday(), function ($q) { $q->where('Hari', 'Senin'); )
->value('Jadwal_masuk');
However carbon also supports localisation so you may be able to get now()->dayName to actually return the day name according to your locale.

Yup validation with one field but two possible options (OR)

I am trying to create an input that takes a string that will be used as the href value for a tag. The href can be a url OR an email (for mailto:).
It works if I just check for email, or if I just check for URL. However, I want to check for one or the other. I am looking through yup documentation but I can't find a way to do an OR.
I noticed that there is a when to test for another field but I'm not checking if another field is true or not, or use test but I also can't seem to get it to work.
const vSchema = yup.object().shape({
text: yup.string().required(),
href: yup
.string()
.email('Link must be a URL or email')
.url('Link must be a URL or email')
.required('Link is a required field'),
});
test this
yup.addMethod(yup.string, "or", function(schemas, msg) {
return this.test({
name: "or",
message: "Please enter valid url or email." || msg,
test: value => {
if (Array.isArray(schemas) && schemas.length > 1) {
const resee = schemas.map(schema => schema.isValidSync(value));
return resee.some(res => res);
} else {
throw new TypeError("Schemas is not correct array schema");
}
},
exclusive: false
});
});

how to check if youtube url exist or not in laravel?

I want to check if entered URL exist on YouTube or not before saving that URL in my database
I am using this code
$url = 'https://www.youtube.com/watch?v=KeaoSIKaxeg';
if(preg_match('/http:\/\/www\.youtube\.com\/watch\?v=[^&]+/', $url))
{
dd('match');
}
else
{
dd('not match');
}
I have tried everything but nothing works. It always returns 'not match' even if the URL is valid.
$headers = get_headers('http://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=KeaoSIKaxeg');
if (!strpos($headers[0], '200')) {
echo "The YouTube video you entered does not exist";
}
You're trying to match against http://, not https://:
$url = 'https://www.youtube.com/watch?v=KeaoSIKaxeg';
if(preg_match('/https:\/\/www\.youtube\.com\/watch\?v=[^&]+/', $url)) {
dd('match');
}
else {
dd('not match');
}

Loopback custom password validation

very simple question: if I try to validate a password in a User model it seems I can only validate the already encrypted password?
So for example if I use
Customer.validatesLengthOf('password', { min: 8, message: 'Too short' })
Then the encrypted password is checked (which is always longer than 8 characters), so no good... If I try to use a custom validation, how can I get access to the original password (the original req.body.password basically)?
EDIT (August 20, 2019): I am unsure if this is still an issue in the latest loopback releases.
In fact, this is a known problem in loopback. The tacitly approved solution is to override the <UserModel>.validatePassword() method with your own. YMMV.
akapaul commented on Jan 10, 2017 •
I've found another way to do this. In common model User there is a
method called validatePassword. If we extend our UserModel from User,
we can redefine this method in JS, like following:
var g = require('loopback/lib/globalize');
module.exports = function(UserModel) {
UserModel.validatePassword = function(plain) {
var err,
passwordProperties = UserModel.definition.properties.password;
if (plain.length > passwordProperties.max) {
err = new Error (g.f('Password too long: %s (maximum %d symbols)', plain, passwordProperties.max));
err.code = 'PASSWORD_TOO_LONG';
} else if (plain.length < passwordProperties.min) {
err = new Error(g.f('Password too short: %s (minimum %d symbols)', plain, passwordProperties.min));
err.code = 'PASSWORD_TOO_SHORT';
} else if(!(new RegExp(passwordProperties.pattern, 'g').test(plain))) {
err = new Error(g.f('Invalid password: %s (symbols and numbers are allowed)', plain));
err.code = 'INVALID_PASSWORD';
} else {
return true;
}
err.statusCode = 422;
throw err;
};
};
This works for me. I don't think that g (globalize) object is required
here, but I added this, just in case. Also, I've added my validator
options in JSON definition of UserModel, because of Loopback docs
For using the above code, one would put their validation rules in the model's .json definition like so (see max, min, and pattern under properties.password):
{
"name": "UserModel",
"base": "User",
...
"properties": {
...
"password": {
"type": "string",
"required": true,
...
"max": 50,
"min": 8,
"pattern": "(?=.*[A-Z])(?=.*[!##$&*])(?=.*[0-9])(?=.*[a-z])^.*$"
},
...
},
...
}
ok, no answer so what I'm doing is using a remote hook to get access to the original plain password and that'll do for now.
var plainPwd
Customer.beforeRemote( 'create', function (ctx, inst, next) {
plainPwd = ctx.req.body.password
next()
})
Then I can use it in a custom validation:
Customer.validate( 'password', function (err, res) {
const pattern = new RegExp(/some-regex/)
if (plainPwd && ! pattern.test( plainPwd )) err()
}, { message: 'Invalid format' })
Ok I guess the above answer is quite novel and obviously is accepted, but If you want a real easy solution with just some basic validations done and not much code then loopback-mixin-complexity is the solution for you.
If you don't want to create another dependency then you can go ahead with a custom mixin, that you can add into your user model or any other model where you need some kind of validation and it would do the validation for you.
Here's a sample code for how to create such mixin
module.exports = function(Model, options) {
'use strict';
Model.observe('before save', function event(ctx, next) { //Observe any insert/update event on Model
if (ctx.instance) {
if(!yourValidatorFn(ctx.instance.password) )
next('password not valid');
else
next();
}
else {
if(!yourValidatorFn(ctx.data.password) )
next('password not valid');
else
next();
}
});
};

Resources