چرا گنو/لینوکس را دوست دارم – تئوری بیگ بنگ

تقریبا یه دوسالی میشه که این دامنه رو ثبت کردم و وردپرس نصب کردم روش اما هیچوقت حس نوشتن نمیومد . الان هم چون مسابقه است و حرف پول و جایزه شده یکم تونستم به تنبلی غلبه کنم و راه بندازم وبلاگ رو .
خب اولین پست وبلاگ رو تقدیم میکنم به  بهنام توکلی عزیز و مسابقه‌ی چرا گنو/لینوکس رو دوست دارم .

تو این پاراگراف تصمیم داشتم قبل از اینکه برم سراغ بحث اصلی یه عالمه توضیح بدم که چرا از گنو/لینوکس استفاده میکنم ، چرا گنو/لینوکس خوبه ، چرا گنو/لینوکس آزاده و کلی چرندیات دیگه که به یکباره از همشون صرف نظر کردم . چند سالی میشه که حوصله‌ی حرف جدی رو خیلی ندارم .

خب من عاشق این سریال بیگ بنگ تئوری هستم  (آره آره میدونم سریال های خیلی بهتری برای دیدن هست اما من اینو دوست دارم) . وقتی هم که یه قسمت از این سریال بیاد هرکاری که دستم باشه میذارم کنار و این سریال رو میبینم . پس هر بار که یه قسمت جدید میاد من یه سری کارهای تکراری انجام میدم . از اونجایی که وقت آدما (آدمای واقعی نه ماها که برای باز کردن یه حساب تو بانک ۲ ساعت وقتمون هدر میره) خیلی اهمیت داره باید توش صرفه جویی بشه و به جاش وقت کامپیوتر گرفته بشه . کل داستان هم از همینجا شروع میشه .

در گنو/لینوکس کلی ابزار کوچیک و بزرگ وجود داره که هر کدوم کارهای کوچیک یا بزرگی رو انجام میدن . شناخت بیشتر این ابزارها باعث میشه بتونید کارهاتون رو سریع تر راه بندازید . پیشنهاد من اینه که مدت زمان کوتاهی رو در روز به ولگردی توی اینترنت و پیدا کردن این ابزارها سپری کنید . اصلا هم مهم نیست که کار باهاشون رو یاد بگیرید همین که یه گوشه‌ی مغزتون باشه که این ابزار یا این سرویس برای اینکار وجود داره کافیه . هر وقت واقعا بهش نیاز داشتید برید سراغش و یادش بگیرید .

قدم اول : تورنت و مگنت

اگه پروتکل بیت تورنت رو نمیشناسید و عمری رو در نادانی سپری کردید اینجا رو بخونید: بیت تورنت
یکی از سایت های خیلی مهم برای به اشتراک گذاری فایل توسط تورنت سایت پایرت بی (thepiratebay.se)هست که اگه بهترینشون نباشه قطعا خبر ساز ترینشون هست . در مورد پایرت بی : پایرت بی در ویکی پدیا

داک داک گو هم که دیگه همه میشناسن این روزا . موتور جستجویی که قول داده حریم خصوصی کاربران رو حفظ میکنه و یه قابلیت خیلی جالب هم داره به اسم ! Bang Syntax  که بازدن g! در اول عبارت جستجوتون عبارت رو در سایت گوگل و مثلا با اضافه کردن dpkg! در اول عبارت جستجو عبارت رو در بسته های مربوط به توزیع دبیان جستجو میکنه . لیست کامل رو میتونید اینجا ببینید ، معرکه است : لیست کامل بنگ سینتکس ها
خب همه اینا رو برای این گفتم که تهش بگم با جستجوی عبارت “tpbs big bang theory!” توی داک داک گو به صفحه‌‌ی نتایج جستجوی مربوط به سریال بیگ بنگ تئوری توی پایرت بی هدایت میشید . اون s آخر tpb یعنی با توجه به تعداد seeder نتایج جستجو رو مرتب کن . قبل از اینکه شروع به نوشتن کنم فکر میکردم برای به دست آوردن این نتیجه نیاز به پست کردن ماشینی یک فرم html توی پایرت بی هست اما الان دیدم قضیه ساده تر از این حرفهاست اگر به آدرس براوزرتون دقت کنید شبیه اینه :

https://thepiratebay.se/search/big%20bang%20theory/0/7/0

این یه آدرس ثابته که همیشه آخرین قسمت که طبیعتا پر تقاضا ترین هم هست بالای لیست قرار میگیره . خیلی به اون عکس های دور و ور سایت دقت نکنید . اگه خانواده هم دورتون نشسته سریع ببندینش تا آبروی بر باد ندید .

هدف اول ما فعلا اینه که آدرس مگنت (magnet) رو از توی این لیست در بیاریم تا بعدا یه فکری به حال دانلودش بکنیم :
خب یه صفحه‌ی html داریم که توش یه جدول هست که href اولین تگ a با عنوان “Download this torrent using magnet” چیزیه که من میخوام . برای به دست آوردنش راه های زیادی وجود داره مثل استفاده از sed یا حتی grep یا یه اسکریپت کوچیک پایتون یا پرل اما من دوست دارم ابزار جدیدی رو که تازه باهاش آشنا شدم رو برای این کار استفاده کنم برای این که تستش بکنم و ببینم چطوره . استفاده از این ابزار برای این کار ساده ، احمقانه ترین کار ممکنه ولی همیشه هدف از انجام دادن این جور کارها پیدا کردن راه حل کاملا مناسب نیست . سر و کله زدن با ابزارهای نو و کشف راه های جدید همیشه جذابه :

phantomjs
با استفاده از این پروژه یه وب کیت کامل بدون لایه‌ی نمایش دارید که میتونید یه صفحه رو توش باز کنید ، jquery رو بهش اضافه کنید و روی دکمه ها کلیک کنید یا مقادیر دلخواه رو برگردونید . پروژه‌ی شگفت انگیزیه . با یکم حوصله میتونید صفحه‌ی پرداخت بانک رو اتوماتیک کنید و یه اسکریپت برای خرید اتوماتیک کارت شارژ بنویسید که خودش توی بانک با استفاده از اطلاعات کارتتون پول رو پرداخت کنه  . نگران اون captcha هم نباشید ، توی هند و خیلی از کشور های آسیای شرقی یه عده هستند که نشستن دائم captcha تایپ میکنن و یه سری سایت هم هستن که با API شما رو به اونا وصل میکنن مثل : deathbycaptcha.com که قیمت هاش هم خیلی ارزونه .

خب . با استفاده از این ابزار اون صفحه رو توی سایت پایرت بی باز میکنم ، jquery رو اضافه میکنم و مقدار دلخواه که آدرس magnet بالاترین سطر باشه رو برمیگردونم . (تا یادم نرفته در مورد اون قضیه‌ی اتوماتیک کردن صفحه‌ی پرداخت بانک بگم که این کار یعنی ماشینی کردن فرآیند پرداخت از نظر قوانین خود بانکها جرم محسوب میشه ولی اگه دوست داشتید انجام بدید کی به کیه نهایتا میگید با کرومیوم رفتم )
خوشبختانه بسته‌ی phantomjs توی مدیر بسته های اوبونتو موجود بود و راحت نصب شد اگر دیستروی شما بسته‌ی آماده رو نداشت میتونید از سایت پروژه دانلود و نصبش کنید :
http://phantomjs.org/download.html
خب بعد از خوندن داکیومنت و دیدن مثال ها نتیجه شد این کد که کار میکنه :

#!/usr/bin/phantomjs
var page = require('webpage').create();
page.open('https://thepiratebay.se/search/big%20bang%20theory/0/7/0', function() {
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
        var magnet = page.evaluate(function() {
	    firstMagnet= $('a[title="Download this torrent using magnet"]').first().attr("href");
	    return firstMagnet;
        });
	console.log(magnet);
        phantom.exit()
    });
});

بلد بودن یه مقدار برنامه نویسی در این حد که بتونید چیزها رو خوب به هم وصله پینه کنید کارتون رو راه میندازه اما اگه واقعا بخواید کارهای جالبی انجام بدید باید برنامه نویسی رو بیشتر یاد بگیرید .

قدم دوم : سناریو

خب وقتش رسیده که با توجه به امکانات و ابزارهایی که دارم سناریو یا ساختار اصلی کاری که میخوام بکنم رو مشخص کنم . این قسمت بخش خیلی مهمیه و به قول اریک ریموند ساختار خوب و کد احمقانه بهتر از ساختار احمقانه و کد خوب کار میکنه . من به یه سرور راه دور دسترسی دارم که اوبونتو روش نصب شده . کاری که میخوام انجام بدم اینه که هر ساعت یکبار یک اسکریپت روی سرور اجرا بشه که با استفاده از کد بالا آدرس مگنت آخرین قسمت سریال رو بده به Transmission که دانلود کنه اینطوری همیشه تمام قسمت های سریال رو با حداکثر تاخیر ۱ ساعت و ۱۰ دقیقه (یک ساعت حداکثر تاخیر و ۱۰ دقیقه برای دانلود حدودا ) روی سرور دارم .

بعد از اون به یه اسکریپت نیاز دارم که روی کامپیوتر خودم اجرا بشه و هرقسمتی که روی سرور دانلود شده باشه رو دانلود کنه . دلیل اینکه مستقیم با همون Transmission روی کامپیوتر خودم دانلود نمیکنم اینه که بتونم با استفاده از شتاب دهنده ها با سرعت بیشتری دانلود کنم و یه چند وقتی هم قسمت ها رو seed کنم روی سرور که seed کردن کار بزرگان است .

قدم سوم : سرور
خیلی سریع بگم که روی سرور یه Transmission نصب میکنم و تنظیمش میکنم که فایلهای دانلود شده رو انتقال بده به شاخه done و شاخه‌ی downloading هم برای فایل های در حال دانلود . اینترفیس وب رو هم تنظیم میکنم و یه سری تنظیمات دیگه مثل پورت و پسورد و اینجور چیزا ، فایل تنظیمات رو هم بعدا میذارم اینجا اگه کسی خواست .

فایل magnet.js رو که قبلا ساختم آپلود میکنم توی مسیر bin/~ روی سرور بعد یه فایل توی همون مسیر میسازم به اسم bigbang بعد با دستور chmod +x اجراییش میکنم و کد زیر رو توش قرار میدم :

#!/bin/bash
var=`magnet.js`
/usr/bin/transmission-remote myserver.com:9899 -n user:pass --add "$var"

بعد با دستور crontab -e وارد محیط ویرایش cron میشم و این خط رو توی اون فایل اضافه میکنم :

 0 * * * * /home/mahdy/bin/bigbang

این خط باعث میشه هر یک ساعت یک بار کدمون اجرا بشه و محبوب ترین تورنت به Transmission اضافه بشه . خوشبختانه خود Transmission مانع اضافه شدن تورنت های تکراری میشه و این خیلی کمک میکنه به کارمون .
برسام یه پست در مورد کار با cron نوشته بود که اگه براتون سوال پیش اومده که این cron چطوری کار میکنه میتونید بخونیدش : پست برسام در مورد Cron
خب روی سرور دیگه کاری نداریم فعلا

قدم چهارم : کلاینت

خب اینجا هم یه اسکریپت میخوایم که با استفاده از ssh به سرور وصل بشه و فایل هایی که روی سرور دانلود شدن و توی پوشه‌ی دانلود ما نیستن رو با استفاده از یه شتاب دهنده‌ دانلود کنه . برای مقاصد معمولی بهترین گزینه استفاده از دستور rsync هست ولی متاسفانه به عنوان شتاب دهنده عمل نمیکنه اگه کسی بتونه این قابلیت رو بهش اضافه کنه کار بزرگی کرده . خب مجبورم خودم یه چیزی بنویسم :

#!/bin/bash
cd /home/mahdy/BigBang
CMD_OUT=`rsync -n -av -e ssh mahdy@myserver.com:/var/www/done/ . | grep Bang | tail -n 1`
if [ "$CMD_OUT" != "" ]; then
	killall -9 axel
	CMD_OUT="http://myserver.com/done/"$CMD_OUT
	axel -n 20 "$CMD_OUT"
fi

خب توضیح مختصرش میشه این که با استفاده از rsync و سوییچ n لیست فایل هایی که اونور دارم و اینور ندارم رو در میارم بعد توشون دنبال Bang میگردم (چون احتمالا میخوام روی سرور چیزهای دیگه هم دانلود کنم) و آخریشون رو با استفاده از نرم افزار axel دانلود میکنم (اگر میخواید از حداکثر پهنای باندتون استفاده نشه و به کارای دیگه هم برسید از سوییچ های خود axel یا از برنامه‌ی trickle استفاده کنید) . البته قبل از همه‌ی این کار ها با استفاده از ssh-keygen و ssh-copy-id یه جفت کلید درست میکنم و کلید عمومی رو به سرور میفرستم که برای ssh نیازی به وارد کردن پسورد نباشه . این اسکریپت رو هم با همون cron میذارم هر نیم ساعت یه بار روی کلاینت اجرا بشه .

داستان زیر نویس :

خیلی هم خوب . تا اینجا برای کسی که به زبان انگلیسی مسلط باشه و بتونه گوشه کنایه های توی سریال رو متوجه بشه و بخنده کافیه . آخرین قسمت سریال همیشه توی شاخه‌ی BigBang وجود داره و میتونه بره ببینه اما متاسفانه من اون طوری نیستم . تا زیرنویس نباشه چیزی از سریال حالیم نمیشه به اون شکل و حالا که همه چیز اتوماتیک شده یه جورایی حیفه که این یه قسمت دستی انجام بشه . مزه‌ی کار به اینه که کل روند ماشینی باشه .

این صفحه زیر نویس های فصل ۶ این سریال رو نشون میده :

http://subscene.com/subtitles/the-big-bang-theory-sixth-season

با کلیک روی قسمت مورد نظر به یه صفحه‌ی دیگه میره که اونجا یه دکمه هست که با کلیک روی اون یه فایل زیپ دانلود میشه ، اون phantomjs رو که اول کار معرفی کردم و باهاش لینک مگنت رو از صفحه‌ی پایرت بی بیرون کشیدیم رو یادتونه ؟ با استفاده از همون یه اسکریپت نوشتم که با گرفتن شماره‌ی قسمت لینک دانلود زیرنویس فارسی رو میده بهمون ، کدش یه مقدار بزرگ شد متاسفانه :

#!/usr/bin/phantomjs
var page = require('webpage').create(),
    system = require('system'),
    t, episode;
episode= system.args[1];
subtitle='';
page.open('http://subscene.com/subtitles/the-big-bang-theory-sixth-season', function() {
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
        var subtitle = page.evaluate(function(episode) {	    
	var episode=''+episode;
		while (episode.length < length) { 			episode = '0' + episode; 		} 		link='0'; 		$('td.a1 a').each(function() { 			if($(this).children().first().children().first().html().indexOf("Farsi")>0)
	   		{
				if($(this).children().first().children().first().next().html().toLowerCase().indexOf("e"+episode)>0)
				{
				        link="http://subscene.com"+$(this).attr("href");
				}
				if($(this).children().first().children().first().next().html().toLowerCase().indexOf("x"+episode)>0)
				{
				        link="http://subscene.com"+$(this).attr("href");
				}
		 	}
		});
		return link;
        });
	var page2 = require('webpage').create();
	page2.open(subtitle, function() {
		page2.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
	        var dlLink = page2.evaluate(function() {	
			return "http://subscene.com"+$("#downloadButton").attr("href");
	        });
	console.log(dlLink);
        phantom.exit();
	});
	});
    });
});

سایت subscene به دلیل کاملا موجه میزبانی کردن از زیرنویس توی ایران سانسور شده ولی خب چون روی سرور اجرا میکنم مشکلی ندارم اما شما اگه میخواید کل روند رو روی کامپیوتر خودتون اجرا کنید میتونید از ابزارهایی مثل torify که ترافیک یه نرم افزار دلخواه رو از tor عبور میده استفاده کنید یا از راه های مختلف دیگه ای که خودتون احتمالا بهتر بلدید استفاده کنید . این کد رو توی همون مسیر bin/~ روی سرور آپلود میکنم ، و یک کد مکمل دیگه هم مینویسم که قراره هر نیم ساعت یک بار اجرا بشه و کارش هم اینه که اگر قسمتی از سریال دانلود شده بود که زیر نویس نداشت سعی کنه با استفاده از خروجی اسکریپت بالا زیرنویسش رو دانلود کنه ، از حالت زیپ خارج کنه و تغییر نام بده که همنام با فایل ویدئو باشه :

#!/bin/bash
cd /var/www/done
for file in $(ls -1 | grep mp4);
do
fname=$(basename $file)
fname=${fname%.*}
if [ ! -f $fname".srt" ];
then
   echo "subtitle not exist"
   episode=`echo "$fname" | sed -n 's/.*S..E\(..\).*/\1/p'`
   echo $episode
   link=`/home/mahdy/bin/subtitle.js $episode`
if [ "$link" != "" ]; then
	torify wget -O subtitle.zip $link
	mkdir tmp
	unzip subtitle.zip -d tmp/
	mv tmp/*.srt $fname.srt
	rm -r -f tmp
	rm subtitle.zip
	#fix subtitle using aliva's script
	subtitlefixer $fname.srt
fi

fi
done

وقتی داشتم کد رو مینوشتم گفتم بد نیست که با ابزاری که دوست خوبمون علی وکیل زاده برای اصلاح زیرنویس های فارسی درست کرده زیر نویس رو اصلاح کنم (دنیای گنو/لینوکس با اعتبار اداره میشه سعی کنید همیشه با بردن اسم افرادی که میشناسید و یادکردن از کار خوبشون به اونها اعتبار بدید) این ابزار encoding فایل رو به utf-8 تغییر میده ، ی و ک عربی رو با معادل فارسیش جایگزین میکنه و یه سری خورده کاری دیگه . میتونید از اینجا دانلودش کنید : اصلاحگر زیر نویس فارسی در گیت هاب

حالا که زیرنویس رو هم داریم چه خوبه که فایل رو پخش کنم ! چه کاری مهمتر از دیدن یه سریال طنز ؟ پس کد قبلی که مربوط به دانلود کردن بود رو تغییر میدم تا در حالتی که ویدئو و فایل زیرنویس هر دو تا وجود داشتن شروع به پخش سریال بکنه :

#!/bin/bash
cd /home/mahdy/BigBang
CMD_OUT=`rsync -n -av -e ssh mahdy@myserver.com:/var/www/done/ . | grep Bang | tail -n 1`
if [ "$CMD_OUT" != "" ]; then
	killall -9 axel
	CMD_OUT="http://myserver.com/done/"$CMD_OUT
	axel -n 20 "$CMD_OUT"
	fname=$(basename $CMD_OUT)
	fname=${fname%.*}
	if [ -f $fname".srt" ] & [ -f $fname".mp4" ];then
		xdg-open $fname.mp4;
	fi
fi

بعد از دانلود ، فایل با Player محبوبتون باز میشه . دستور xdg-open فایل مورد نظر رو با نرم افزار پیش فرضی که قبلا توی محیط دسکتاپ انتخاب کردید اجرا میکنه برای من Smplayer باز میشه و سریال شروع به پخش شدن میکنه و چون فایل زیرنویس هم نام با فایل اصلی هست خود به خود زیرنویس رو هم اضافه میکنه برای شما ممکنه VLC یا هر چیز دیگه ای که پیش فرض شماست باز بشه .
نتیجه‌ی نهایی کل این کارها یه چیزی شبیه این میشه :
یه روز بعد از ظهر پشت سیستم نشستید و دارید به کارهاتون میرسید که یه دفعه آخرین قسمت سریال مورد علاقتون با زیرنویس فارسی و بدون حروف عربی شروع به پخش میکنه یه چیزی مثل این  :

bigbang

خیلی راحت میتونید این کدها رو برای سریال مورد نظر خودتون تغییر بدید ، بعضی قسمت هاش رو مثل قسمت سرور حذف کنید و تمام مراحل رو روی کامپیوتر خودتون انجام بدید یا امکانات بیشتری بهش اضافه کنید . مثلا با استفاده از این بُرد های آماده چراغ های اتاق رو قبل از پخش خاموش کنید که مثل سینما بشه یا کلی کار باحال دیگه

حرف آخر :

تمام این کدهای مزخرف و وراجی ها رو بریزید دور ، این دلیلی نیست که من گنو/لینوکس رو دوست دارم . با یکم تلاش توی ویندوز یا هر سیستم عامل دیگه ای میشه همچین کارایی کرد ، شاید به این راحتی و قشنگی و سادگی نباشه و نشه توی مدت زمان خیلی کوتاه کار رو تموم کرد ولی در نهایت میشه .
من گنو/لینوکس رو دوست دارم چون وقتی داشتم این رو مینوشتم آدمای مهربونی بودند که هرجا مشکل داشتم بهم کمک کنن  ، دوستش دارم چون شغلی که دارم رو به خاطر گنو/لینوکس دارم ، دوستش دارم چون بهترین دوستانم کسایی هستن که توی جوامع مربوط به گنو/لینوکس باهاشون آشنا شدم ، گنو/لینوکس رو دوست دارم چون اگر نبود احتمالا باید الان تنهایی این سریال رو نگاه میکردم . وقتشه برم کد رو عوض کنم تا ۱ دقیقه قبل از پخش فیلم یه sms بده تا از اتاق بغل پاشه بیاد