ফেসবুক পোস্ট থেকে ওয়ার্ডপ্রেস ব্লগ

সম্ভবত ২০০৯ থেকে আমি ফেসবুকে নিয়মিত টুকটাক লেখালিখি করি। ফেসবুকের বাহিরে এখানে (jakir.me) লিখছি মূলত টেকনিক্যাল লেখা গুলো। নন-টেকনিক্যাল লেখা গুলো ফেসবুকের টাইমলাইনে হারিয়ে যায়। নিজেও খুঁজে পাই না সহজে। সহজে খুঁজে পাওয়ার জন্য ভাবলাম অন্য এক যায়গায় সব গুলো লেখা রাখি। ফ্রিতে কোথাও হোস্ট করতে চাচ্ছি যেনো রিনিউ এর ঝামেলায় পোস্ট গুলো হারিয়ে না যায়। এগুলোর মধ্যে সবচেয়ে রিলায়েবল হচ্ছে blogger.com এবং wordpress.com। ব্লগার থেকে ওয়ার্ডপ্রেসে ফিচার বেশি। তাই আমি ওয়ার্ডপ্রেসেই ফেসবুকের পোস্ট গুলো হোস্ট করার প্ল্যান করেছি।

এর আগে ম্যানুয়ালি এক অনেক গুলো পোস্ট নিয়েছি। পরে দেখলাম এত পোস্ট। ম্যানুয়ালি না নিয়ে একটা স্ক্রিপ্ট লিখে নেই। তবে যাদের পোস্ট কম, এবং সব পোস্ট ওয়ার্ডপ্রেসে নিতে চান, তারা চাইলে Jetpack ব্যবহার করেই ইম্পোর্ট করতে পারেন। ওয়ার্ডপ্রেসের ফ্রি স্টোরেজ মাত্র 1GB। এর বেশি হলে ম্যানুয়ালি নিজের মত করে ইম্পোর্ট করাই ভালো হবে।

এখানে আমি একাধিক সলিউশন সম্পর্কে বলছি। যেটা আপনার ভালো এবং সহজ মনে হয়, তাই ব্যবহার করতে পারেন।

ফেসবুক থেকে ওয়ার্ডপ্রেসে অটোমেটিক ট্রান্সফার

Import from Facebook লেখায় স্টেপ গুলো লেখা রয়েছে। এরপরও আমি এখানে লিখছিঃ

  • ফেসবুকের একাউন্ট সেন্টার থেকে ডেটা ট্রান্সফার অথবা ডাউনলোড করা যাবে. সরাসরি https://facebook.com/dtp লিঙ্ক ভিজিট করলে ঐ পেইজে নিয়ে যাবে। এখানে ইউজারনেম এবং পাসওয়ার্ড চাইতে পারে। একাউন্ট সেন্টার থেকে Transser a copy of your information সিলেক্ট করতে হবে।
  • প্রোফাইল: ফেসবুক, ইন্সট্রাগ্রাম ইত্যাদি একাধিক প্রোফাইল থাকলে তা দেখাবে। সেখান থেকে ফেসবুক সিলেক্ট করব।
  • Select information: সিলেক্ট ইনফরমেশন থেকে “Create custom transfer” এ ক্লিক করতে হবে। এরপর “Next” ক্লিক করব।
  • কোথায় এবং কখন: এখানে দুইটা অপশন পাবো। Where to থেকে “WordPress.com/Jetpack” সিলেক্ট করে “Save” বাটনে ক্লিক করব। এবং “Next” বাটনে ক্লিক করব।
  • Choose what to transfer: এখান থেকে আমরা কি কি ট্রান্সফার করতে চাই, তা সিলেক্ট করতে পারব। আমরা কাস্টম ডেট রেঞ্জও সিলেক্ট করতে পারব। সিলেক্ট করার পর “Next” এ ক্লিক করব।
  • Connect with WordPress.com/ Jetpack: এবার WordPress.com সাইটের সাথে কানেক্ট করতে হবে। “Connect” বাটনে ক্লিক করে যে সাইটে ডেটা ট্রান্সফার করতে চাচ্ছেন, তা সিলেক্ট করুন।
  • Start transfer: এরপর “Start transfer” এ ক্লিক করে ট্রান্সফার কনফার্ম করুন। ফেসবুক থেকে ওয়ার্ডপ্রেসে ডেটা ট্রান্সফার শুরু হবে। এই স্টেপে ফেসবুক পাসওয়ার্ড চাইবে। পোস্ট সংখ্যা এর উপর নির্ভর করে সময় লাগবে। কয়েক ঘণ্টাও লেগে যেতে পারে।

ট্রান্সফারের পর করণীয়

ডেটা ট্রান্সফার করলে লেখা গুলো ড্রাফটে জমা হয়। পাবলিশ হয় না অটোমেটিক। পরে সেগুলো সব গুলো সিলেক্ট করে পাবলিশ করে নেওয়া যাবে। আর পোস্টের টাইটেল হয় এমন Facebook Post: 2024-04-23T05:32:21। সরাসরি পাবলিশ করতে চাইলে কাস্টম স্ক্রিপ্ট ব্যবহার করতে হবে। ঐটা নিয়ে জানা যাবে এর পরের সেকশনে।

সেলফ হোস্টেড ওয়ার্ডপ্রেসে ডেটা ট্রান্সফার

সম্ভবত সেলফ হোস্টেড ওয়েব সাইটে জেটপ্যাক ব্যবহার করে ফেসবুক ডেটা ট্রান্সফার করা যায় না। আমার দুইটা সাইটে ট্রাই করেছি। হয়নি। তো নিজে সহজে একটা স্ক্রিপ্ট লিখে ফেসবুক ডেটা গুলো ব্লগে পাবলিশ করা যাবে। আমি এখানে দেখাবো কিভাবে ফেসবুকের ডেটা JSON ফরমেটে ডাউনলোড করে এরপর ওয়ার্ডপ্রেস ব্লগে পাবলিশ করা যায়।

ফেসবুকের ডেটা ডাউনলোড

১। ফেসবুক একাউন্ট সেন্টার থেকে Download your information এ ক্লিক করব।

বিদ্রঃ ফেসবুক রেগুলার নিজেদের ওয়েবসাইটের ইন্টারফেস পরিবর্তন করে। তাই হয়তো নিচের ধাপ গুলো নাও মিলতে পারে। আশা করি এখান থেকে আপনি আইডিয়া পাবেন কিভাবে ডেটা ডাউনলোড করতে হবে।

২। এরপর Download or transfer information এ ক্লিক করব।

৩। এর পরের স্টেপে কোন প্রোফাইল এর ডেটা আমরা ডাউনলোড করব, তা সিলেক্ট করব। এরপর নেক্সট এ ক্লিক করব।

৪। এখান থেকে Specific types of information এ ক্লিক করব। এরপর নেক্সট এ ক্লিক করব।

৫। এখান থেকে সব ধরণের ডেটা ডাউনলোড করা যাবে। আমি শুধু Post গুলো ডাউনলোড করব। তাই এখান থেকে Posts সিলেক্ট করলাম।

এরপর নেক্সট এ ক্লিক করব।

৬। পরের ধাপে Download to device এ ক্লিক করব। এরপর নেক্সট এ ক্লিক করব।

৭। এখান থেকে ফরমেট হিসেবে JSON সিলেক্ট করব। মিডিয়া কোয়ালিটি যদি ভালো চাই, তাহলে High সিলেক্ট করব। এবং ডেট রেঞ্জ সিলেক্ট করব। সব গুলো ডেটা ডাউনলোড করতে চাইলে All time সিলেক্ট করব। এরপর Create files এ ক্লিক করব।

ফেসবুক কিছু সময় নিবে এই ডেটা গুলো জেনারেট করতে। জেনারেট হয়ে গেলে আপনাকে ইমেইল করবে। অথবা একাউন্ট সেন্টারে গিয়েও আপডেট দেখা যাবে।

ডেটা তৈরি হলে ডাউনলোড করতে পারবেন। your_facebook_activity নামক একটা ফোল্ডারের ভেতর posts ফোল্ডারে আপনার সকল পোস্ট দেখতে পাবেন। কিছুটা এমনঃ

এখানে অনেক গুলো ফাইল এবং ফোল্ডার পাবেন। media ফোল্ডারে সকল ইমেজ এবং ভিডিও পাবেন। এছাড়া your_posts__check_ins__photos_and_videos_.json নামক JSON ফাইলে আপনার সকল পোস্ট এই ফরমেটে থাকবেঃ

[
    {
      "timestamp": 1722342460,
      "data": [
        {
          "post": ""
        },
        {
          
        }
      ]
    },
    {
      "timestamp": 1722182695,
      "attachments": [
        {
          "data": [
            {
              "media": {
                "uri": "",
                "creation_timestamp": 1722182683,
                "media_metadata": {
                  "photo_metadata": {
                    "exif_data": [
                      {
                        "upload_ip": "",
                        "taken_timestamp": 1722182695
                      }
                    ]
                  }
                },
                "title": "Timeline photos",
                "description": " ",
                "backup_uri": ""
              }
            }
          ]
        }
      ],
      "data": [
        {
          "post": " "
        },
        {
        }
      ]
    }
  ]

মূলত দুই টাইপের ডেটা এখানে। attachments এবং রেগুলার post। ডেটা গুলো ল্যাটিনে এনকোড করা। নিচের পাইথন স্ক্রিপ্ট ব্যবহার করে ডিকোড করে নিতে পারেনঃ

import json

# Function to decode Latin-encoded data to UTF-8
def decode_latin_encoded_text(text):
    try:
        return text.encode('latin1').decode('utf-8')
    except UnicodeEncodeError:
        return text  # Return the original text if encoding/decoding fails

# Load JSON data from the input file
input_file_path = 'your_facebook_post.json'  # Replace with the path to your input JSON file
output_file_path = 'output.json'  # Path to save the new JSON file

with open(input_file_path, 'r', encoding='utf-8') as f:
    data = json.load(f)

# Iterate through the JSON data and decode Latin-encoded fields
for item in data:
    if 'data' in item:
        for entry in item['data']:
            if 'post' in entry:
                entry['post'] = decode_latin_encoded_text(entry['post'])
    
    if 'attachments' in item:
        for attachment in item['attachments']:
            for media_data in attachment.get('data', []):
                if 'media' in media_data:
                    if 'description' in media_data['media']:
                        media_data['media']['description'] = decode_latin_encoded_text(media_data['media']['description'])

# Save the modified data to a new JSON file
with open(output_file_path, 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)

print(f"New JSON file with decoded text saved to {output_file_path}")

JSON ফাইল গুলোর ভেতরের টেক্সট তাহলে পড়তে পারবেন।

আমরা JSON ফাইল থেকে ডেটা গুলো নিয়ে সেলফ হোস্টেড ওয়েব সাইটে পাবলিশ করব। তা অটোম্যাটিক্যালি করব। আর তা করব ওয়ার্ডপ্রেস রেস্ট এপিআই ব্যবহার করে। ওয়ার্ডপ্রেস রেস্ট এপিআই লেখাটা পড়লে অনেক কিছু ক্লিয়ার হবে। এখানে ব্যাসিক কিছু আবারও রিপিট করছি।

যে কোন সেলফ হোস্টেড ওয়েব সাইটে ডিফল্ট ভাবে REST API এনাবল থাকে। কোন ডেটা ওয়েব সাইটে পোস্ট করার জন্য অথেনটিকেশনের দরকার পড়ে। ডিফল্ট ব্যাসিক অথেনটিকেশনই আমরা ব্যবহার করতে পারব। উপরের ওয়ার্ডপ্রেস রেস্ট এপিআই লেখাতে যা বিস্তারিত লিখেছি। তার জন্য আমাদের শুধু মাত্র একটা এপ্লিকেশন পাসওয়ার্ড তৈরি করে নিতে হবে।

ওয়ার্ডপ্রেসের এক্সেস টোকেন বা অ্যাপলিকেশন পাসওয়ার্ডঃ এপ্লিকেশন পাসওয়ার্ড তৈরি করা যাবে ওয়ার্ডপ্রেস ড্যাসবোর্ড থেকে। ওয়ার্ডপ্রেস এডমিন > Users > All Users এ গিয়ে এডমিন ইউজার এডিট করোলে নিচের দিকে এপ্লিকেশন পাসওয়ার্ড তৈরির অপশন পাবো। এখানে এই পাসওয়ার্ডের একটা নাম দেওয়ার পর আমাদের একটা পাসওয়ার্ড তৈরি করে দিবে।

আমাদের ইউজারনেম এবং এই অ্যাপলিকেশন পাসওয়ার্ড লাগবে। অ্যাপলিকেশন পাসওয়ার্ড একবারই দেখা যাবে। যদি কপি করতে ভুলে গিয়ে থাকেন, আগেরটা ডিলিট করে আবার নতুন করে তৈরি করে নেওয়া যাবে। ওয়ার্ডপ্রেস থেকে আমাদের এতটুকুই লাগবে। এবার স্ক্রিপ্ট তৈরি।

পাইথন স্ক্রিপ্ট ব্যবহার করে ডাউনলোড করা ফেসবুক পোস্ট ওয়ার্ডপ্রেসে পোস্ট করা

যে ফোল্ডারে ডাউনলোডকৃত your_facebook_activity ফোল্ডার রেখেছেন, একই ফোল্ডারে নিচের স্ক্রিপ্ট সেভ করুন। যেমন upload.py।

import json
import base64
import requests
import os
from datetime import datetime

# Replace these with your WordPress site URL and user credentials
WORDPRESS_API_URL = 'http://hello.local/wp-json/wp/v2'
USERNAME = 'admin'
PASSWORD = 'cYQE 4rqwr 0VOq 344 Mq3O P7Ug'  # Generated from WordPress

# Load JSON data from the file
with open('your_facebook_data.json', 'r', encoding='utf-8') as f:
    data = json.load(f)


# File to store processed post titles
processed_posts_file = 'processed_posts.txt'
processed_media_file = 'processed_media.txt'

# Load processed items into sets
if os.path.exists(processed_posts_file):
    with open(processed_posts_file, 'r', encoding='utf-8') as f:
        processed_posts = set(f.read().splitlines())
else:
    processed_posts = set()

if os.path.exists(processed_media_file):
    with open(processed_media_file, 'r', encoding='utf-8') as f:
        processed_media = set(f.read().splitlines())
else:
    processed_media = set()


# Function to log processed post titles
def log_processed_post(title):
    with open(processed_posts_file, 'a', encoding='utf-8') as f:
        f.write(title + '\n')
    processed_posts.add(title)


# Function to log processed media
def log_processed_media(filename):
    with open(processed_media_file, 'a', encoding='utf-8') as f:
        f.write(filename + '\n')
    processed_media.add(filename)


# Check if a post or media file has already been processed
def is_post_processed(title):
    return title in processed_posts


def is_media_processed(filename):
    return filename in processed_media


# Encode the username and password for Basic Auth
auth_str = f"{USERNAME}:{PASSWORD}"
auth_bytes = base64.b64encode(auth_str.encode('utf-8'))
auth_header = f"Basic {auth_bytes.decode('utf-8')}"

# Counter for the number of posts created
post_counter = 0


# Function to check if the file is an image (skip video files)
def is_image_file(filename):
    image_extensions = ['.jpg', '.jpeg', '.png', '.gif']
    return any(filename.lower().endswith(ext) for ext in image_extensions)

# Function to convert a Unix timestamp to the WordPress REST API date format
def convert_timestamp_to_wp_date(timestamp):
    dt_object = datetime.fromtimestamp(timestamp)
    return dt_object.strftime('%Y-%m-%dT%H:%M:%S')


# Function to upload an image from a local directory and get its URL
def upload_image_from_local_path(file_path, media_description):
    # Skip the file if it's not an image
    if not is_image_file(file_path):
        print(f"Skipping non-image file: {file_path}")
        return None

    headers = {
        'Authorization': auth_header
    }

    # Ensure the file exists
    if os.path.exists(file_path):
        with open(file_path, 'rb') as image_file:
            files = {
                'file': (os.path.basename(file_path), image_file, 'image/jpeg'),  # Adjust MIME type if necessary
                'description': (None, media_description),
            }

            # Upload the image to WordPress
            response = requests.post(f'{WORDPRESS_API_URL}/media', headers=headers, files=files)

            if response.status_code == 201:
                print(f"Uploaded {file_path} successfully.")
                return response.json().get('source_url')
            else:
                print(f"Failed to upload {file_path}: {response.status_code}, {response.text}")
                return None
    else:
        print(f"File not found: {file_path}")
        return None


# Function to create a post on WordPress
def create_post(title, content, timestamp=None, image_url=None):
    title.replace("\n", " ")

    if title in processed_posts:
        print(f"Post '{title}' already processed. Skipping.")
        return  # Skip if the post was already processed

    global post_counter
    headers = {
        'Authorization': auth_header,
        'Content-Type': 'application/json'
    }
    post_data = {
        'title': title,
        'content': content,
        'status': 'publish'  # Change to 'draft' if you want to review before publishing
    }

    if timestamp:
        post_date = convert_timestamp_to_wp_date(timestamp)
        post_data['date'] = post_date  # Publish with a specific date

    if image_url:
        post_data['content'] += f'<img src="{image_url}" alt="{title}" />'

    response = requests.post(f'{WORDPRESS_API_URL}/posts', headers=headers, json=post_data)

    if response.status_code == 201:
        post_counter += 1
        print(f"[{post_counter}] Post '{title}' created successfully.")
        log_processed_post(title)  # log the title  
    else:
        print(f"Failed to create post '{title}': {response.status_code}, {response.text}")


# Iterate through the JSON data and handle posts and media
local_media_directory = ''  # Replace with the path to your local directory

for item in data:

    if 'attachments' in item:
        for attachment in item['attachments']:
            for media_data in attachment.get('data', []):
                if 'media' in media_data:
                    media_filename = media_data['media'].get('uri', '')

                    if media_filename in processed_media:
                        print(f"Media '{media_filename}' already processed media list. Skipping.")
                        continue  # Skip if the media was already processed

                    file_path = os.path.join(local_media_directory, media_filename)
                    media_description = media_data['media'].get('description', 'Media Post').encode('latin1').decode(
                        'utf-8')

                    # skip the post if it is smaller than 20 word
                    if len(media_description.split()) < 20:
                        continue

                    post_title = media_description[:40] + "..." if len(media_description) > 40 else media_description
                    post_timestamp = item.get('timestamp')  # Get the timestamp for media posts

                    # Upload image from local path and create a post with the uploaded image URL
                    uploaded_image_url = upload_image_from_local_path(file_path, media_description)

                    if uploaded_image_url:
                        create_post(post_title, media_description, post_timestamp, uploaded_image_url)
                        # log the media name 
                        log_processed_media(media_filename)
                        break  # Break to prevent creating multiple posts from the same item
                else:
                    # Continue the outer loop if no media post was created
                    continue

                break  # Exit 'attachments' processing if a post was created        
    elif 'data' in item:
        for entry in item['data']:
            if 'post' in entry:
                post_text = entry['post'].encode('latin1').decode('utf-8')

                # skip the post if it is smaller than 20 word
                if len(post_text.split()) < 20:
                    continue
                post_title = post_text[:40] + "..." if len(post_text) > 40 else post_text
                post_timestamp = item.get('timestamp')  # Get the timestamp from the item
                create_post(post_title, post_text, post_timestamp)
                break  # Exit 'data' processing after creating a post               

print("Script execution completed.")

আপনার সাইট অনুযায়ী নিচের ডেটা গুলো পরিবর্তন করুনঃ

WORDPRESS_API_URL = 'http://hello.local/wp-json/wp/v2'
USERNAME = 'admin'
PASSWORD = 'cYQE 4rqwr 0VOq 344 Mq3O P7Ug'  # Generated from WordPress

ভালো হয় প্রথমে লোকাল মেশিনে একটা ওয়ার্ডপ্রেস ইন্সটল করে নিয়ে টেস্ট করা। তার জন্য localwp.com ব্যবহার করতে পারেন।

এরপর কমান্ডলাইন বা টার্মিনালে গিয়ে স্ক্রিপ্টটি রান করুন। যেমনঃ

python upload.py

    পোস্ট গুলো ওয়ার্ডপ্রেসে ওয়েব সাইটে আস্তে আস্তে পাবলিশ হবে।

    JSON ফাইল লোকেশন নিচের লাইনে পরিবর্তন করা যাবেঃ

    with open('your_facebook_data.json', 'r', encoding='utf-8') as f:
        data = json.load(f)
    

    বিদ্রঃ আপনার ব্লগে আগের কোন ডেটা থাকলে অবশ্যই প্রথমে ডেটার ব্যাকআপ নিয়ে নিবেন।

    উপরের স্ক্রিপ্টের কিছু বৈশিষ্ট্য

    • ভিডিও আপলোড করবে না। শুধু ইমেজ আপলোড করবে।
    • ফেসবুক স্ট্যাটাস যদি ২০ শব্দের নিচে হয়, তাহলে তা ব্লগে প্রকাশ করবে না। এই লজিক হচ্ছে নিচের লাইন গুলোতেঃ
    if len(media_description.split()) < 20:
        continue
    

    এবং

    if len(post_text.split()) < 20:
        continue
    

    ছোট বড় সব স্ট্যাটাস পাবলিশ করতে চাইলে এই দুইটা লাইন রিমুভ করে দিতে পারেন। এমনকি ওয়ার্ড কাউন্ট বাড়িয়ে দিতে পারেন।

    • পোস্ট থেকে প্রথম ৪০ ক্যারেক্টার নিয়ে টাইটেল জেনারেট করবে। আপনি চাইলে ক্যারেক্টারের সংখ্যা কমাতে বাড়াতে পারেন।
    • ফেসবুক স্ট্যাটাস যে তারিখে পোস্ট করা হয়েছে, ব্লগে ঐ তারিখ অনুযায়ী পোস্ট হবে।
    • কোন কারণে কম্পিউটার বন্ধ হয়ে গেলে স্ক্রিপ্ট যদি পুনরায় রান করতে হয়, তাহলে দেখা যাবে শুরু থেকে আবার সব পোস্ট করবে। এর সমাধান হিসেবে একটা লগ রেখেছি। মিডিয়া ফাইল যেগুলো ওয়েব সাইটে আপলোড হবে, সেগুলোর লগও রাখা হয়েছে।
    • কয়টা পোস্ট পাবলিশ করা হয়েছে, তার একটা কাউন্টারও রাখা হয়েছে। এই তো!

    যদি আপনি ভিডিও বা যে কোন মিডিয়া টাইপ আপলোড করতে চান, তাহলে upload_image_from_local_path ফাংশন থেকে নিচের কোড রিমুভ বা কমেন্টআউট করে দিবেন।

        # Skip the file if it's not an image
        if not is_image_file(file_path):
            print(f"Skipping non-image file: {file_path}")
            return None
    

    এই কয়েকটা জিনিস আমার দরকার ছিল, তাই এভাবে লিখে নিয়েছি। আপনি চাইলে আপনার মত করে সাজিয়ে নিতে পারেন। কোন সমস্যা ফেইস করলে কমেন্টে জানাতে পারেন।

    WordPress.com ব্লগে ডাউনলোডকৃত ফেসবুক স্ট্যাটাস ট্রান্সফার

    শুরুতেই আমরা দেখেছি কিভাবে Jetpack এর মাধ্যমে wordpress.com ব্লগ সাইটে ফেসবুক পোস্ট ট্রান্সফার করা যায়। যা সব কিছু ট্রান্সফার করবে। আমি সব ডেটা ট্রান্সফার করতে চাচ্ছিলাম না। কিছুটা কাস্টোমাইজ চাচ্ছিলাম। তাই উপরের স্ক্রিপ্ট লিখি। কিন্তু উপরের স্ক্রিপ্ট wordress.com ব্লগে সরাসরি সাপোর্ট করবে না। অথেনটিকেশন ভিন্ন ভাবে কাজ করে WordPress.com ব্লগে। আর যার জন্য কিছু স্টেপ ফলো করতে হবে।

    প্রথম ধাপঃ WordPress.com Developer App তৈরি

    • https://developer.wordpress.com/apps সাইটে গিয়ে আমাদের একটা অ্যাপ তৈরি করতে হবে।
    • Create New Application এ ক্লিক করলে নতুন অ্যাপ তৈরি ফরম আসবে। যেখানে নিচের ইনফরমেশন গুলো দিয়ে একটা অ্যাপ তৈরি করে নিব।

    নিচের তথ্য গুলো অবশ্যই দিতে হবেঃ

    • App Name: এখানে অ্যাপের একটা নাম দিতে হবে। যেমন Facebook to WordPress Automation।
    • Description: এখানে অ্যাপ সম্পর্কে লিখতে হবে। যে কোন কিছুই লিখতে পারেন।
    • Website URL: এখানে এই অ্যাপ রিলেটেড তথ্য দেখানোর ওয়েবসাইট লিঙ্ক দিতে হবে। যে কোন কিছুই দিতে পারেন।
    • Redirect URLs: রিডারেক্ট ইউআরএলটা গুরুত্বপূর্ণ। এখানে অ্যাপ অথেনটিকেশন করার পর যেখানে রিডাইরেক্ট করবে, সেই URL দিতে হবে। একাধিক URL দিতে পারব। যেমন http://localhost অথবা https://example.com। আমি WP Local ব্যবহার করে hello নামে একটা ওয়েবসাইট তৈরি করেছি। তাই আমি রিডাইরেক্ট URL দিয়েছি http://hello.local
    • Javascript Origins: আমরা যদিও জাভাস্ক্রিপ্ট ব্যবহার করব না। তারপরও এখানে একটা URL দিতে হবে। লোকাল হোস্ট URL দিতে পারেন বা যে কোন URL দিতে পারেন।
    • Type: Native সিলেক্ট করতে পারেন।

    এরপর Create বাটনে ক্লিক করলে অ্যাপ আইকন সিলেক্ট করতে বলবে। সব ঠিক থাকলে অ্যাপ তৈরি হবে। অ্যাপ তৈরি করলে একটা Client ID এবং একটা Client Secreat পাবেন। এগুলো দরকার হবে।

    এই অ্যাপ তৈরি করেছি ওয়ার্ডপ্রেস ব্লগের এক্সেস টোকেন নেওয়ার জন্য। যে এক্সেস টোকেন ব্যবহার করে আমরা ব্লগে POST রিকোয়েস্ট করতে পারব।

    দ্বিতীয় ধাপঃ অথোরাইজেশন কোড

    নিচের URL দেখিঃ

    https://public-api.wordpress.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=YOUR_SCOPES
    
    

    এই URL এ তিনটা তথ্য দিতে হবে। যেমনঃ

    • YOUR_CLIENT_ID: এখানে ওয়ার্ডপ্রেস অ্যাপের Client ID দিতে হবে।
    • YOUR_REDIRECT_URI: এখানে আমরা অ্যাপ তৈরির সময় যে রিডাইরেক্ট URL দিয়েছি, সেগুলো থেকে একটা ব্যবহার করতে পারব। যেমন http://localhost অথবা http://hello.local অথবা যে কোন ওয়েব সাইট।
    • YOUR_SCOPES: যে কোড জেনারেট করবে, তার কি কি এক্সেস পাবে, তাই এখানে বলে দিব। REST API ব্যবহার করে POST করতে আমাদের global স্কোপ ব্যবহার করতে হবে।

      যেমনঃ

      https://public-api.wordpress.com/oauth2/authorize?client_id=12345&redirect_uri=http://hello.local&response_type=code&scope=global
      
      

      উপরের লিঙ্ক ভিজিট করলে অ্যাপ এপ্রুভাল চাইবেঃ

      এপ্রুভ করার পর রিডাইরেক্ট URL এ রিডাইরেক্ট করবে। রিডাইরেক্ট URL এর সাথে একটা অথেনটিকেশন কোড থাকবে এমনঃ http://localhost/?code=AUTH_CODE। যে কোডটা আমরা কপি করে নিব। কোডটা Rty6D2334RTYu9 এর মত হবে।

      এই কোড ব্যবহার করে আমরা এক্সেস টোকেন জেনারেট করব। কত কিছু যে লাগে!

      ধাপ তিনঃ এক্সেস টোকেন তৈরি

      নিচের স্ক্রিপ্ট দেখিঃ

      import requests
      
      # Replace these values with your actual credentials
      client_id = '12345'
      client_secret = 'App Client Secret'
      auth_code = 'Rty6D2334RTYu9'
      redirect_uri = 'http://hello.local'
      
      # Prepare the data for the token request
      data = {
          'client_id': client_id,
          'client_secret': client_secret,
          'code': auth_code,
          'redirect_uri': redirect_uri,
          'grant_type': 'authorization_code'
      }
      
      # Send the POST request
      response = requests.post('https://public-api.wordpress.com/oauth2/token', data=data)
      
      # Print the response
      if response.status_code == 200:
          token_info = response.json()
          access_token = token_info['access_token']
          print("Access Token:", access_token)
      else:
          print("Failed to get access token:", response.status_code, response.text)
      

      উপরের স্ক্রিপ্টে client_id, client_secret (ওয়ার্ডপ্রেস ডেভেলপার অ্যাপ তৈরির সময় প্রাপ্ত) এবং পরবর্তীতে তৈরি করা auth_code ব্যবহার করে রান করলে একটা এক্সেস টোকেন তৈরি করে দিবে। কিছুটা এমনঃ 2AdfayI!m7kS#8CylBasdfgWSrXmA866A$KS1K#$x%IOboUks)Gq435sfdgNDfa

      এই এক্সেস টোকেন পাওয়ার জন্যই এত কিছু! এখন বাকি কাজ সহজ। সেলফ হোস্টেড ওয়েব সাইটের মত করে স্ক্রিপ্ট রান করে দিব।

      ধাপ চারঃ WordPress.com ব্লগ সাইটে REST API ব্যবহার করে পোস্ট

      WordPress.com এর REST API এন্ডপয়েন্ট এমনঃ

      https://public-api.wordpress.com/wp/v2/sites/example.wordpress.com
      

      example.wordpress.com এর যায়গায় আপনার ওয়ার্ডপ্রেস ব্লগ সাইটের url ব্যবহার করবেন। টেস্ট করার জন্য ব্রাউজারে উপরের মত করে ভিজিট করে দেখুন। যেমন https://public-api.wordpress.com/wp/v2/sites/example.wordpress.com/posts ব্রাউজারে ভিজিট করলেই পাবলিক পোস্টের JSON ফরমেত দেখতে পারবেন।

      সেলফ হোস্টেড ওয়ার্ডপ্রেসে আমরা বেসিক অথেনটিকেশন ব্যবহার করেছি। এবার এক্সেস টোকেন ব্যবহার করে রিকোয়েস্ট করব। তাই স্ক্রিপ্ট সামান্য পরিবর্তন করতে হবে। নিচের স্ক্রিপ্ট ব্যবহার করে আপনি ডাউনলোডকৃত ফেসবুক স্ট্যাটাস ওয়ার্ডপ্রেসে ট্রান্সফার করতে পারবেনঃ

      import json
      import base64
      import requests
      import os
      from datetime import datetime
      
      # Replace these with your WordPress site URL and user credentials
      WORDPRESS_API_URL = 'https://public-api.wordpress.com/wp/v2/sites/example.wordpress.com'
      access_token = "YOUR_ACCESS_TOKEN"
      
      # Load JSON data from the file
      with open('facebook_post_data.json', 'r', encoding='utf-8') as f:
          data = json.load(f)
      
      # File to store processed post titles
      processed_posts_file = 'processed_posts.txt'
      processed_media_file = 'processed_media.txt'
      
      # Load processed items into sets
      if os.path.exists(processed_posts_file):
          with open(processed_posts_file, 'r', encoding='utf-8') as f:
              processed_posts = set(f.read().splitlines())
      else:
          processed_posts = set()
      
      if os.path.exists(processed_media_file):
          with open(processed_media_file, 'r', encoding='utf-8') as f:
              processed_media = set(f.read().splitlines())
      else:
          processed_media = set()
      
      
      # Function to log processed post titles
      def log_processed_post(title):
          with open(processed_posts_file, 'a', encoding='utf-8') as f:
              f.write(title + '\n')
          processed_posts.add(title)
      
      
      # Function to log processed media
      def log_processed_media(filename):
          with open(processed_media_file, 'a', encoding='utf-8') as f:
              f.write(filename + '\n')
          processed_media.add(filename)
      
      
      # Check if a post or media file has already been processed
      def is_post_processed(title):
          return title in processed_posts
      
      
      def is_media_processed(filename):
          return filename in processed_media
      
      
      # Counter for the number of posts created
      post_counter = 0
      
      
      # Function to check if the file is an image (skip video files)
      def is_image_file(filename):
          image_extensions = ['.jpg', '.jpeg', '.png', '.gif']
          return any(filename.lower().endswith(ext) for ext in image_extensions)
      
      
      # Function to convert a Unix timestamp to the WordPress REST API date format
      def convert_timestamp_to_wp_date(timestamp):
          dt_object = datetime.fromtimestamp(timestamp)
          return dt_object.strftime('%Y-%m-%dT%H:%M:%S')
      
      
      # Function to upload an image from a local directory and get its URL
      def upload_image_from_local_path(file_path, media_description):
          # Skip the file if it's not an image
          if not is_image_file(file_path):
              print(f"Skipping non-image file: {file_path}")
              return None
      
          headers = {
              'Authorization': f'Bearer {access_token}'
          }
      
          # Ensure the file exists
          if os.path.exists(file_path):
              with open(file_path, 'rb') as image_file:
                  files = {
                      'file': (os.path.basename(file_path), image_file, 'image/jpeg'),  # Adjust MIME type if necessary
                      'description': (None, media_description),
                  }
      
                  # Upload the image to WordPress
                  response = requests.post(f'{WORDPRESS_API_URL}/media', headers=headers, files=files)
      
                  if response.status_code == 201:
                      print(f"Uploaded {file_path} successfully.")
                      return response.json().get('source_url')
                  else:
                      print(f"Failed to upload {file_path}: {response.status_code}, {response.text}")
                      return None
          else:
              print(f"File not found: {file_path}")
              return None
      
      
      # Function to create a post on WordPress
      def create_post(title, content, timestamp=None, image_url=None):
          headers = {
              'Authorization': f'Bearer {access_token}',
              'Content-Type': 'application/json'
          }
      
          title.replace("\n", " ")
      
          if title in processed_posts:
              print(f"Post '{title}' already processed. Skipping.")
              return  # Skip if the post was already processed
      
          global post_counter
      
          post_data = {
              'title': title,
              'content': content,
              'status': 'publish'  # Change to 'draft' if you want to review before publishing
          }
      
          if timestamp:
              post_date = convert_timestamp_to_wp_date(timestamp)
              post_data['date'] = post_date  # Publish with a specific date
      
          if image_url:
              post_data['content'] += f'<img src="{image_url}" alt="{title}" />'
      
          response = requests.post(f'{WORDPRESS_API_URL}/posts', headers=headers, json=post_data)
      
          if response.status_code == 201:
              post_counter += 1
              print(f"[{post_counter}] Post '{title}' created successfully.")
              log_processed_post(title)  # log the title  
          else:
              print(f"Failed to create post '{title}': {response.status_code}, {response.text}")
      
      
      # Iterate through the JSON data and handle posts and media
      local_media_directory = ''  # Replace with the path to your local directory
      
      for item in data:
      
          if 'attachments' in item:
              for attachment in item['attachments']:
                  for media_data in attachment.get('data', []):
                      if 'media' in media_data:
                          media_filename = media_data['media'].get('uri', '')
      
                          if media_filename in processed_media:
                              print(f"Media '{media_filename}' already processed media list. Skipping.")
                              continue  # Skip if the media was already processed
      
                          file_path = os.path.join(local_media_directory, media_filename)
                          media_description = media_data['media'].get('description', 'Media Post').encode('latin1').decode(
                              'utf-8')
      
                          # skip the post if it is smaller than 20 word
                          if len(media_description.split()) < 20:
                              continue
      
                          post_title = media_description[:40] + "..." if len(media_description) > 40 else media_description
                          post_timestamp = item.get('timestamp')  # Get the timestamp for media posts
      
                          # Upload image from local path and create a post with the uploaded image URL
                          uploaded_image_url = upload_image_from_local_path(file_path, media_description)
      
                          if uploaded_image_url:
                              create_post(post_title, media_description, post_timestamp, uploaded_image_url)
                              # log the media name 
                              log_processed_media(media_filename)
                              break  # Break to prevent creating multiple posts from the same item
                      else:
                          # Continue the outer loop if no media post was created
                          continue
      
                      break  # Exit 'attachments' processing if a post was created        
          elif 'data' in item:
              for entry in item['data']:
                  if 'post' in entry:
                      post_text = entry['post'].encode('latin1').decode('utf-8')
      
                      # skip the post if it is smaller than 20 word
                      if len(post_text.split()) < 20:
                          continue
                      post_title = post_text[:40] + "..." if len(post_text) > 40 else post_text
                      post_timestamp = item.get('timestamp')  # Get the timestamp from the item
                      create_post(post_title, post_text, post_timestamp)
                      break  # Exit 'data' processing after creating a post               
      
      print("Script execution completed.")
      

      বিদ্রঃ আপনার ব্লগে আগের কোন ডেটা থাকলে অবশ্যই প্রথমে ডেটার ব্যাকআপ নিয়ে নিবেন।

      Leave a Reply