Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

posting to blue sky working #3004

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ DATABASE_URL=postgres://user:password@localhost:5432/dbname

#Sentry DSN
SENTRY_DSN=https://[email protected]/0


#BlueSky User Details
BLUESKY_USERNAME=example.bsky.social
BLUESKY_PASSWORD='example#123'
1 change: 1 addition & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ jobs:
with:
python-version: 3.11.2
- run: pip install poetry
- run: poetry lock --no-update
DonnieBLT marked this conversation as resolved.
Show resolved Hide resolved
- run: poetry install
- run: poetry run python manage.py collectstatic --noinput
- name: Run tests
Expand Down
3 changes: 2 additions & 1 deletion blt/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@
"tz_detect.middleware.TimezoneMiddleware",
"blt.middleware.ip_restrict.IPRestrictMiddleware",
)

BLUESKY_USERNAME = env("BLUESKY_USERNAME", default="default_username")
BLUESKY_PASSWORD = env("BLUESKY_PASSWORD", default="default_password")
TESTING = len(sys.argv) > 1 and sys.argv[1] == "test"

if DEBUG and not TESTING:
Expand Down
6 changes: 6 additions & 0 deletions blt/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,18 @@
add_role,
admin_company_dashboard,
admin_company_dashboard_detail,
approve_activity,
company_dashboard,
company_dashboard_domain_detail,
company_dashboard_hunt_detail,
company_dashboard_hunt_edit,
company_hunt_results,
delete_time_entry,
dislike_activity,
feed,
get_scoreboard,
hunt_results,
like_activity,
sizzle,
sizzle_daily_log,
sizzle_docs,
Expand Down Expand Up @@ -581,6 +584,9 @@
distribute_bacon,
name="distribute_bacon",
),
path("activity/like/<int:id>/", like_activity, name="like_activity"),
path("activity/dislike/<int:id>/", dislike_activity, name="dislike_activity"),
path("activity/approve/<int:id>/", approve_activity, name="approve_activity"),
re_path(r"^tz_detect/", include("tz_detect.urls")),
# re_path(r"^tellme/", include("tellme.urls")),
re_path(r"^ratings/", include("star_ratings.urls", namespace="ratings")),
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ python-bitcoinrpc = "^1.0"
sendgrid = "^6.11.0"
matplotlib = "^3.9.2"
openpyxl = "^3.1.5"
atproto = "^0.0.55"

[tool.poetry.group.dev.dependencies]
black = "^24.8.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Generated by Django 5.1.3 on 2024-11-28 19:23

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("website", "0159_merge_20241128_0439"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.AddField(
model_name="activity",
name="dislike_count",
field=models.PositiveIntegerField(default=0),
),
migrations.AddField(
model_name="activity",
name="dislikes",
field=models.ManyToManyField(
blank=True,
related_name="disliked_activities",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="activity",
name="is_approved",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="activity",
name="is_posted_to_bluesky",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="activity",
name="like_count",
field=models.PositiveIntegerField(default=0),
),
migrations.AddField(
model_name="activity",
name="likes",
field=models.ManyToManyField(
blank=True, related_name="liked_activities", to=settings.AUTH_USER_MODEL
),
),
migrations.AlterField(
model_name="badge",
name="icon",
field=models.ImageField(blank=True, null=True, upload_to="badges/"),
),
]
12 changes: 12 additions & 0 deletions website/migrations/0161_merge_20241130_0224.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Generated by Django 5.1.3 on 2024-11-30 02:24

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("website", "0160_activity_dislike_count_activity_dislikes_and_more"),
("website", "0160_merge_20241129_0712"),
]

operations = []
41 changes: 40 additions & 1 deletion website/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -942,20 +942,59 @@ class Activity(models.Model):
title = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
image = models.ImageField(null=True, blank=True, upload_to="activity_images/")
timestamp = models.DateTimeField(auto_now_add=True)
url = models.URLField(null=True, blank=True)
timestamp = models.DateTimeField(auto_now_add=True)

# Approval and Posting
like_count = models.PositiveIntegerField(default=0)
dislike_count = models.PositiveIntegerField(default=0)
is_approved = models.BooleanField(default=False) # Whether activity is approved
is_posted_to_bluesky = models.BooleanField(default=False) # Whether posted to BlueSky

# Generic foreign key fields
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
related_object = GenericForeignKey("content_type", "object_id")

# New fields for likes and dislikes
likes = models.ManyToManyField(User, related_name="liked_activities", blank=True)
dislikes = models.ManyToManyField(User, related_name="disliked_activities", blank=True)

def __str__(self):
return f"{self.title} by {self.user.username} at {self.timestamp}"

class Meta:
ordering = ["-timestamp"]

# Approve the activity
def approve_activity(self):
# Check auto-approval criteria
if self.like_count >= 3 and self.dislike_count < 3:
self.is_approved = True
self.save()

# Post to BlueSky
def post_to_bluesky(self, bluesky_service):
if not self.is_approved:
raise ValueError("Activity must be approved before posting to BlueSky.")

try:
post_data = f"{self.title}\n\n{self.description}"
# If image exists, include it
if self.image:
print("image = " + self.image.path)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please remove the print statements?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure on it.

bluesky_service.post_with_image(text=post_data, image_path=self.image.path)
else:
bluesky_service.post_text(text=post_data)

# Mark activity as posted
self.is_posted_to_bluesky = True
self.save()
return True
except Exception as e:
print(f"Error posting to BlueSky: {e}")
raise


class Badge(models.Model):
BADGE_TYPES = [
Expand Down
46 changes: 46 additions & 0 deletions website/services/blue_sky_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# services/bluesky_service.py
from atproto import Client, models
from django.conf import settings


class BlueSkyService:
def __init__(self):
self.client = Client()
self.client.login(settings.BLUESKY_USERNAME, settings.BLUESKY_PASSWORD)

def post_text(self, text):
"""Post plain text to BlueSky."""
post = self.client.send_post(text=text)
return post.uri # Assuming the response includes a post ID

def post_with_image(self, text, image_path):
"""Post text with an image to BlueSky."""
try:
# Read the image as binary
with open(image_path, "rb") as img_file:
img_data = img_file.read()

# Debug: Confirm image data size, not raw binary
print(f"Uploading image to BlueSky... Size: {len(img_data)} bytes")

# Upload the image to BlueSky
upload = self.client.upload_blob(img_data)
print(f"Upload response: Blob ID = {upload.blob}")

# Create the embedded image structure
images = [models.AppBskyEmbedImages.Image(alt="Activity Image", image=upload.blob)]
embed = models.AppBskyEmbedImages.Main(images=images)
print(f"Embed object: {embed}")

# Create the post record
post_record = models.AppBskyFeedPost.Record(
text=text, embed=embed, created_at=self.client.get_current_time_iso()
)

# Post to BlueSky
post = self.client.app.bsky.feed.post.create(self.client.me.did, post_record)
print(f"Post created successfully. URI: {post.uri}")
return post.uri
except Exception as e:
print(f"Error in post_with_image: {e}")
raise
Loading
Loading