MyAnimeList Dynamic Signature
Added by astuffedtiger on 2017-05-16 19:44:50
Plan to Watch'=>'>Plan to Read','>Watching'=>'>Reading','>Rewatching'=>'>Re-Reading','>On-Hold'=>'>Reading On Hold','>Completed'=>'>Finished Reading') );
// easiest to parse if we just merge the feeds together and parse all at once
$buffer = $anibuffer . $mangabuffer;
// now we have to sanitize the information we saved to the buffer (no newlines/tabs and replace xml entities)
$buffer = strtr($buffer, array("\n" => '', "\r" => '', "\t" => '', '<' => '<', '>'=>'>', '&' => '&', '"' => '"', '''=>"'") );
// these lines just extract the anime title and status information into $titles[] and $status[] arrays, plus other info
preg_match_all("/([^<]*)<\/title>/i", $buffer, $titlematches);
preg_match_all("/<description>([^<]*) - ([\d?]+) of ([\d?]+) (episodes?|chapters?)<\/description>/i", $buffer, $statusmatches);
preg_match_all("/<pubDate>([^<]*)<\/pubDate>/i", $buffer, $timematches);
$titles = $titlematches[1]; // $anititles is now an array of titles
$status = $statusmatches[1]; // $anistatus is now an array of statuses
$current = $statusmatches[2]; // $current is now an array of all the current episodes/chapters
$totals = $statusmatches[3]; // $totals is now an array of all the episode/chapter totals
$units = $statusmatches[4]; // $units is now an array of 'episode(s)' or 'chapter(s)'
$timestamps = $timematches[1]; // $timestamps is now an array of dates watched/read
// let's  go through the whole list and format it how we want
for($i = 0; $i < count($titles); $i++) {
	// convert timestamps to unix timestamps (numbers) so we can sort them properly later (don't change this line)
	$timestamps[$i] = strtotime($timestamps[$i]);
	// just remove all that junk at the end
	$titles[$i] = preg_replace('/ - (TV|Movie|ONA|OVA|OAD|Special|Manga|Manhwa|Manhua|Novel|One Shot|Doujin|OEL)$/', '', $titles[$i]);
	// limit the titles to 21 characters; adjust this to your needs
	$titles[$i] = textlimit($titles[$i],32);
	// FORMAT THE STATUS VALUES - you can change the format as you like
	if ($status[$i] == "Watching" or $status[$i] == "Rewatching" or $status[$i] == "Reading" or $status[$i] == "Re-Reading") {
		$status[$i] = "$status[$i] at $current[$i] of $totals[$i] $units[$i]";
	} else { // "Completed, "Plan to Watch", "Dropped", or "On Hold"
		$status[$i] = "$status[$i]"; // doesn't really do anything, but feel free to modify
	$status[$i] = strtolower($status[$i]); // make all the statuses lowercase
// sort all of the arrays by the timestamps, so that the most recent entries are first
$sigimage = open_image("jimmy-sig-2011.png"); // load your background image
$font = 'completeinhim.ttf'; // if you use another font, make sure you copy the *.ttf file into the same directory
// let's define a font color - the last three arguments are the red, green, and blue values (so 0,0,0 = black and 255,255,255 = white)
$colour = imagecolorallocate($sigimage,0,0,0);
//$colour2 = imagecolorallocate($sigimage,0,0,0);
// draw the text - the template is imagettftext(image, font size, angle, x-pos, y-pos, font color, fontfile, text output, 'c' or 'l' or 'r')
// OVERLAY ANOTHER IMAGE over the font and background (optional)
// finally, let's output our pretty signature image to the browser
header("Content-type: image/png");
@imagepng($sigimage, $cachedpath); // try to save a copy of our signature to the cache location we set earlier
// Don't modify below here... just a few helping functions that can be called in the above code
// textlimit($string, $length) takes any $string you pass it and resturns it shortened to $length characters (use it to limit title length)
function textlimit($string, $length=25) {
	return (strlen(trim($string))>$length ? trim( substr(trim($string),0,$length-3) )."..." : $string);
// textlimitpx($string, $pixels, $font) returns the shortened $string that fits within exactly $pixels width horizontally when using $font and $size
function textlimitpx($string, $pixels, $font, $size) {
	for($k = strlen(trim($string)); $k > 0; $k--) {
		$box = imagettfbbox($size,0,$font,textlimit($string,$k));
		$w = $box[2] - $box[0];
		if ($w <= $pixels) break;
	return textlimit($string,$k);
// overlay_image($baseimage,$overlaypath,$x,$y) opens the image at $imagepath and overlays it onto $sigimage at position ($x, $y)
// most image types should work, but 24-bit/true color PNG is recommended if you need transparency
function overlay_image($overlaypath,$x=0,$y=0) {
	global $sigimage;
	$overlay = open_image($overlaypath); // open any image
	imagecopy($sigimage, $overlay, $x, $y, 0, 0, imagesx($overlay), imagesy($overlay)); // overlay onto our base image
	@imagedestroy($overlay); // clean up memory, since we don't need the overlay image anymore
// open_image($path) will load an image into memory so we can work with it, and return an error if we fail
function open_image($path) {
	$image = @imagecreatefromstring(file_get_contents($path));
	if (!$image) die("could not open image ($path) make sure it exists");
	imagealphablending($image,true); imagesavealpha($image,true); // preserve transparency
	return $image;
// check_cache($minutes) returns a cached image and stops execution if $minutes has not passed since the last update
function check_cache($minutes) {
	global $cachedpath;
	if ( !( is_writable($cachedpath) or is_writable(dirname($cachedpath)) and !file_exists($cachedpath) ) )
		die("The cache is not writable; please change it to 777 permissions using FTP.\n\$cachedpath = {$cachedpath}");
	if ( time() - @filemtime($cachedpath) < 60*$minutes ) {
		header("Content-type: image/png");
		echo file_get_contents($cachedpath);
// imagettftextalign() is basically a wrapper for imagettftext() to add the ability to center/right-align text to a point
// the $align argument can be 'c' for center, 'r' for right align, or 'l' for left align (default)
function imagettftextalign(&$img,$size,$angle,$x,$y,&$c,$font,$string,$align='l') {
	$box = imagettfbbox($size,$angle,$font,$string);
	$w = $box[2] - $box[0];
	$h = $box[3] - $box[1];
	switch (strtolower($align)) {
		case 'r': $x -= $w; $y -= $h; break;
		case 'c': $x -= $w/2; $y -= $h/2; break;
					<div class="card-footer fs-7">
						<div class="d-flex justify-content-end"><span class="align-bottom"><i class="fal fa-code pe-1"></i> </span> PHP</div>
						<div class="clearfix"></div>
<div id="footer">
			<div class="container">
				<div class="center-block">
					<p class="text-center fs-7">This site was built with <i class="fas fa-heart pink"></i> by <a class="text-decoration-none" href="">Jimmy B.</a></p>
		<script src=""></script>
		<script src="" integrity="sha512-NC2WFBzw/SdbWrzG0C+sg3iv1OITcQKsUitDcYKfOp9vxe92zpNlRc5Ad3q81kAp8Ff/fDV8pZQxdCCeyFdgLw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
		<script src="" integrity="sha512-GP4x8UWxWyh4BMbyJGOGneiTbkrWEF5izsVJByzVLodP8CuJH/n936+yQDMJJrOPUHLgyPbLiGw2rXmdvGdXHA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
		<script src="" integrity="sha512-dubtf8xMHSQlExGRQ5R7toxHLgSDZ0K7AunqPWHXmJQ8XyVIG19S1T95gBxlAeGOK02P4Da2RTnQz0Za0H0ebQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
		<script src="" crossorigin="anonymous"></script>

				<!-- Login / Register Modal -->
		<div class="modal fade" id="loginRegisterModal" tabindex="-1" role="dialog" aria-labelledby="loginRegisterModalLabel" aria-hidden="true">
			<div class="modal-dialog">
				<div class="modal-content">
					<div class="modal-header">
						<h5 class="modal-title" id="exampleModalLabel">Login or Register</h5>
						<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
					<div class="modal-body">
						<ul class="nav nav-tabs" id="myTab" role="tablist">
							<li class="nav-item"><button class="nav-link active text-black" id="login-tab" data-bs-toggle="tab" data-bs-target="#login" type="button" role="tab" aria-controls="login" aria-selected="true">Login</button></li>
							<li class="nav-item"><button class="nav-link text-black" id="register-tab" data-bs-toggle="tab" data-bs-target="#register" type="button" role="tab" aria-controls="register" aria-selected="true">Register</a></a></li>
						<div class="tab-content" id="myTabContent">
							<div class="tab-pane fade show active mt-3" id="login" role="tabpanel" aria-labelledby="login-tab">
								<form class="form-vertical" method="post" action="/login">
									<input type="hidden" name="_token" value="XVK7EDr7NdUFZejNGY5VRiDtsm1T6wphgIbjwiNr">									<div class="input-group mb-3">
										<span class="input-group-text"><i class="fas fa-user"></i></span>
										<input type="text" class="form-control input-sm" id="username" name="username" placeholder="Username">
									<div class="input-group mb-3">
										<span class="input-group-text"><i class="fal fa-key"></i></span>
										<input type="password" class="form-control input-sm" id="password" name="password" placeholder="Password">
									<div class="form-group d-flex justify-content-end">
										<button type="submit" class="btn btn-sm btn-dark">Login</button>
							<div class="tab-pane fade mt-3" id="register" role="tabpanel" aria-labelledby="register-tab">
								<div class="alert alert-info" role="alert"><i class="fal fa-info-circle"></i> Registration is coming soon...</div>