|
@@ -0,0 +1,298 @@
|
|
|
|
+<?php
|
|
|
|
+
|
|
|
|
+namespace App\Http\Controllers;
|
|
|
|
+
|
|
|
|
+use Illuminate\Http\Request;
|
|
|
|
+use App\Models\ImportPost;
|
|
|
|
+use App\Services\ImportService;
|
|
|
|
+use App\Services\StatusService;
|
|
|
|
+use App\Http\Resources\ImportStatus;
|
|
|
|
+use App\Follower;
|
|
|
|
+use App\User;
|
|
|
|
+
|
|
|
|
+class ImportPostController extends Controller
|
|
|
|
+{
|
|
|
|
+ public function __construct()
|
|
|
|
+ {
|
|
|
|
+ $this->middleware('auth');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public function getConfig(Request $request)
|
|
|
|
+ {
|
|
|
|
+ return [
|
|
|
|
+ 'enabled' => config('import.instagram.enabled'),
|
|
|
|
+
|
|
|
|
+ 'limits' => [
|
|
|
|
+ 'max_posts' => config('import.instagram.limits.max_posts'),
|
|
|
|
+ 'max_attempts' => config('import.instagram.limits.max_attempts'),
|
|
|
|
+ ],
|
|
|
|
+
|
|
|
|
+ 'allow_video_posts' => config('import.instagram.allow_video_posts'),
|
|
|
|
+
|
|
|
|
+ 'permissions' => [
|
|
|
|
+ 'admins_only' => config('import.instagram.permissions.admins_only'),
|
|
|
|
+ 'admin_follows_only' => config('import.instagram.permissions.admin_follows_only'),
|
|
|
|
+ 'min_account_age' => config('import.instagram.permissions.min_account_age'),
|
|
|
|
+ 'min_follower_count' => config('import.instagram.permissions.min_follower_count'),
|
|
|
|
+ ],
|
|
|
|
+
|
|
|
|
+ 'allowed' => $this->checkPermissions($request, false)
|
|
|
|
+ ];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public function getProcessingCount(Request $request)
|
|
|
|
+ {
|
|
|
|
+ abort_unless(config('import.instagram.enabled'), 404);
|
|
|
|
+
|
|
|
|
+ $processing = ImportPost::whereProfileId($request->user()->profile_id)
|
|
|
|
+ ->whereNull('status_id')
|
|
|
|
+ ->whereSkipMissingMedia(false)
|
|
|
|
+ ->count();
|
|
|
|
+
|
|
|
|
+ $finished = ImportPost::whereProfileId($request->user()->profile_id)
|
|
|
|
+ ->whereNotNull('status_id')
|
|
|
|
+ ->whereSkipMissingMedia(false)
|
|
|
|
+ ->count();
|
|
|
|
+
|
|
|
|
+ return response()->json([
|
|
|
|
+ 'processing_count' => $processing,
|
|
|
|
+ 'finished_count' => $finished,
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public function getImportedFiles(Request $request)
|
|
|
|
+ {
|
|
|
|
+ abort_unless(config('import.instagram.enabled'), 404);
|
|
|
|
+
|
|
|
|
+ return response()->json(
|
|
|
|
+ ImportService::getImportedFiles($request->user()->profile_id),
|
|
|
|
+ 200,
|
|
|
|
+ [],
|
|
|
|
+ JSON_UNESCAPED_SLASHES
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public function getImportedPosts(Request $request)
|
|
|
|
+ {
|
|
|
|
+ abort_unless(config('import.instagram.enabled'), 404);
|
|
|
|
+
|
|
|
|
+ return ImportStatus::collection(
|
|
|
|
+ ImportPost::whereProfileId($request->user()->profile_id)
|
|
|
|
+ ->whereNotNull('status_id')
|
|
|
|
+ ->cursorPaginate(9)
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public function store(Request $request)
|
|
|
|
+ {
|
|
|
|
+ abort_unless(config('import.instagram.enabled'), 404);
|
|
|
|
+ $this->checkPermissions($request);
|
|
|
|
+
|
|
|
|
+ $uid = $request->user()->id;
|
|
|
|
+ $pid = $request->user()->profile_id;
|
|
|
|
+ foreach($request->input('files') as $file) {
|
|
|
|
+ $media = $file['media'];
|
|
|
|
+ $c = collect($media);
|
|
|
|
+ $postHash = hash('sha256', $c->toJson());
|
|
|
|
+ $exts = $c->map(function($m) {
|
|
|
|
+ $fn = last(explode('/', $m['uri']));
|
|
|
|
+ return last(explode('.', $fn));
|
|
|
|
+ });
|
|
|
|
+ $postType = 'photo';
|
|
|
|
+
|
|
|
|
+ if($exts->count() > 1) {
|
|
|
|
+ if($exts->contains('mp4')) {
|
|
|
|
+ if($exts->contains('jpg', 'png')) {
|
|
|
|
+ $postType = 'photo:video:album';
|
|
|
|
+ } else {
|
|
|
|
+ $postType = 'video:album';
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ $postType = 'photo:album';
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if(in_array($exts[0], ['jpg', 'png'])) {
|
|
|
|
+ $postType = 'photo';
|
|
|
|
+ } else if(in_array($exts[0], ['mp4'])) {
|
|
|
|
+ $postType = 'video';
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $ip = new ImportPost;
|
|
|
|
+ $ip->user_id = $uid;
|
|
|
|
+ $ip->profile_id = $pid;
|
|
|
|
+ $ip->post_hash = $postHash;
|
|
|
|
+ $ip->service = 'instagram';
|
|
|
|
+ $ip->post_type = $postType;
|
|
|
|
+ $ip->media_count = $c->count();
|
|
|
|
+ $ip->media = $c->map(function($m) {
|
|
|
|
+ return [
|
|
|
|
+ 'uri' => $m['uri'],
|
|
|
|
+ 'title' => $m['title'],
|
|
|
|
+ 'creation_timestamp' => $m['creation_timestamp']
|
|
|
|
+ ];
|
|
|
|
+ })->toArray();
|
|
|
|
+ $ip->caption = $c->count() > 1 ? $file['title'] : $ip->media[0]['title'];
|
|
|
|
+ $ip->filename = last(explode('/', $ip->media[0]['uri']));
|
|
|
|
+ $ip->metadata = $c->map(function($m) {
|
|
|
|
+ return [
|
|
|
|
+ 'uri' => $m['uri'],
|
|
|
|
+ 'media_metadata' => isset($m['media_metadata']) ? $m['media_metadata'] : null
|
|
|
|
+ ];
|
|
|
|
+ })->toArray();
|
|
|
|
+ $ip->creation_date = $c->count() > 1 ? now()->parse($file['creation_timestamp']) : now()->parse($media[0]['creation_timestamp']);
|
|
|
|
+ $ip->creation_year = now()->parse($ip->creation_date)->format('y');
|
|
|
|
+ $ip->creation_month = now()->parse($ip->creation_date)->format('m');
|
|
|
|
+ $ip->creation_day = now()->parse($ip->creation_date)->format('d');
|
|
|
|
+ $ip->save();
|
|
|
|
+
|
|
|
|
+ ImportService::getImportedFiles($pid, true);
|
|
|
|
+ ImportService::getPostCount($pid, true);
|
|
|
|
+ }
|
|
|
|
+ return [
|
|
|
|
+ 'msg' => 'Success'
|
|
|
|
+ ];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public function storeMedia(Request $request)
|
|
|
|
+ {
|
|
|
|
+ abort_unless(config('import.instagram.enabled'), 404);
|
|
|
|
+
|
|
|
|
+ $this->checkPermissions($request);
|
|
|
|
+
|
|
|
|
+ $mimes = config('import.allow_video_posts') ? 'mimetypes:image/png,image/jpeg,video/mp4' : 'mimetypes:image/png,image/jpeg';
|
|
|
|
+
|
|
|
|
+ $this->validate($request, [
|
|
|
|
+ 'file' => 'required|array|max:10',
|
|
|
|
+ 'file.*' => [
|
|
|
|
+ 'required',
|
|
|
|
+ 'file',
|
|
|
|
+ $mimes,
|
|
|
|
+ 'max:' . config('pixelfed.max_photo_size')
|
|
|
|
+ ]
|
|
|
|
+ ]);
|
|
|
|
+
|
|
|
|
+ foreach($request->file('file') as $file) {
|
|
|
|
+ $fileName = $file->getClientOriginalName();
|
|
|
|
+ $file->storeAs('imports/' . $request->user()->id . '/', $fileName);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ImportService::getImportedFiles($request->user()->profile_id, true);
|
|
|
|
+
|
|
|
|
+ return [
|
|
|
|
+ 'msg' => 'Success'
|
|
|
|
+ ];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ protected function checkPermissions($request, $abortOnFail = true)
|
|
|
|
+ {
|
|
|
|
+ $user = $request->user();
|
|
|
|
+
|
|
|
|
+ if($abortOnFail) {
|
|
|
|
+ abort_unless(config('import.instagram.enabled'), 404);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if($user->is_admin) {
|
|
|
|
+ if(!$abortOnFail) {
|
|
|
|
+ return true;
|
|
|
|
+ } else {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $admin = User::whereIsAdmin(true)->first();
|
|
|
|
+
|
|
|
|
+ if(config('import.instagram.permissions.admins_only')) {
|
|
|
|
+ if($abortOnFail) {
|
|
|
|
+ abort_unless($user->is_admin, 404, 'Only admins can use this feature.');
|
|
|
|
+ } else {
|
|
|
|
+ if(!$user->is_admin) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(config('import.instagram.permissions.admin_follows_only')) {
|
|
|
|
+ $exists = Follower::whereProfileId($admin->profile_id)
|
|
|
|
+ ->whereFollowingId($user->profile_id)
|
|
|
|
+ ->exists();
|
|
|
|
+ if($abortOnFail) {
|
|
|
|
+ abort_unless(
|
|
|
|
+ $exists,
|
|
|
|
+ 404,
|
|
|
|
+ 'Only admins, and accounts they follow can use this feature'
|
|
|
|
+ );
|
|
|
|
+ } else {
|
|
|
|
+ if(!$exists) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(config('import.instagram.permissions.min_account_age')) {
|
|
|
|
+ $res = $user->created_at->lt(
|
|
|
|
+ now()->subDays(config('import.instagram.permissions.min_account_age'))
|
|
|
|
+ );
|
|
|
|
+ if($abortOnFail) {
|
|
|
|
+ abort_unless(
|
|
|
|
+ $res,
|
|
|
|
+ 404,
|
|
|
|
+ 'Your account is too new to use this feature'
|
|
|
|
+ );
|
|
|
|
+ } else {
|
|
|
|
+ if(!$res) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(config('import.instagram.permissions.min_follower_count')) {
|
|
|
|
+ $res = Follower::whereFollowingId($user->profile_id)->count() >= config('import.instagram.permissions.min_follower_count');
|
|
|
|
+ if($abortOnFail) {
|
|
|
|
+ abort_unless(
|
|
|
|
+ $res,
|
|
|
|
+ 404,
|
|
|
|
+ 'You don\'t have enough followers to use this feature'
|
|
|
|
+ );
|
|
|
|
+ } else {
|
|
|
|
+ if(!$res) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(intval(config('import.instagram.limits.max_posts')) > 0) {
|
|
|
|
+ $res = ImportService::getPostCount($user->profile_id) >= intval(config('import.instagram.limits.max_posts'));
|
|
|
|
+ if($abortOnFail) {
|
|
|
|
+ abort_if(
|
|
|
|
+ $res,
|
|
|
|
+ 404,
|
|
|
|
+ 'You have reached the limit of post imports and cannot import any more posts'
|
|
|
|
+ );
|
|
|
|
+ } else {
|
|
|
|
+ if($res) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(intval(config('import.instagram.limits.max_attempts')) > 0) {
|
|
|
|
+ $res = ImportService::getAttempts($user->profile_id) >= intval(config('import.instagram.limits.max_attempts'));
|
|
|
|
+ if($abortOnFail) {
|
|
|
|
+ abort_if(
|
|
|
|
+ $res,
|
|
|
|
+ 404,
|
|
|
|
+ 'You have reached the limit of post import attempts and cannot import any more posts'
|
|
|
|
+ );
|
|
|
|
+ } else {
|
|
|
|
+ if($res) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(!$abortOnFail) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|