Skip to content

Commit faccf2e

Browse files
committed
Chat with self for free account getstream.io
1 parent 018ae4e commit faccf2e

38 files changed

+505
-42
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ npx prisma migrate dev (rails db:migrate)
7474
rails db:seed (prisma introspect && npx prisma db pull && npx prisma db push)
7575
cd ..
7676
rails s -p 3001
77+
(git checkout 1242dc57c527178d6bffd6980c884ba4478bafd4 -- db/migrate)
78+
(rails status code symbol: https://gist.github.com/mlanett/a31c340b132ddefa9cca)
7779
```
7880

7981
## Links

app/controllers/api/users_controller.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
class Api::UsersController < Api::ApiController
2-
before_action :authenticate!, except: %i[create, update]
2+
before_action :authenticate!, except: %i[create, update, index]
33
before_action :set_user, except: %i[index create]
44
before_action :correct_user, only: %i[destroy]
55
before_action :admin_user, only: %i[destroy]
66

77
def index
8+
# @users = User.all.page(params[:page])
89
@users = User.all.page(params[:page])
910
@total, users = pager(User.all.order(id: :asc))
1011
end

app/views/api/users/index.json.jbuilder

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ json.users do
22
json.array!(@users) do |u|
33
json.id u.id
44
json.name u.name
5-
json.email u.email
6-
json.gravatar_id Digest::MD5::hexdigest(u.email.downcase)
7-
json.size 50
8-
json.admin u.admin
5+
json.username u.username
6+
json.displayName u.displayName
7+
json.avatarUrl u.avatarUrl
98
end
109
end
1110
json.total_count @total

client/src/app/(auth)/signup/actions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export async function signUp(
6565
passwordHash,
6666
},
6767
});
68+
// stream upsertUser
6869
await streamServerClient.upsertUser({
6970
id: userId,
7071
username,

client/src/app/(main)/messages/NewChatDialog.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export default function NewChatDialog({
4444
client.queryUsers(
4545
{
4646
id: { $ne: loggedInUser.id },
47-
role: { $ne: "admin" },
47+
// role: { $ne: "user" },
4848
...(searchInputDebounced
4949
? {
5050
$or: [
@@ -61,16 +61,20 @@ export default function NewChatDialog({
6161

6262
const mutation = useMutation({
6363
mutationFn: async () => {
64-
const channel = client.channel("messaging", {
65-
members: [loggedInUser.id, ...selectedUsers.map((u) => u.id)],
66-
name:
67-
selectedUsers.length > 1
68-
? loggedInUser.displayName +
69-
", " +
70-
selectedUsers.map((u) => u.name).join(", ")
71-
: undefined,
64+
const channelId = `self-chat-${loggedInUser.id}`;
65+
const channel = client.channel("messaging", channelId, {
66+
members: [loggedInUser.id],
67+
name: loggedInUser.displayName
7268
});
73-
await channel.create();
69+
try {
70+
const response = await channel.create();
71+
console.log('Channel created:', response);
72+
} catch (error) {
73+
console.error('Error creating channel:', error);
74+
}
75+
const result = await channel.addMembers([{user_id: "00cffeed-248f-4fc5-92ff-b99ebbad7e8d"}]);
76+
// const result1 = await channel.addMembers([{user_id: "0649d146-060c-4c8e-86c1-b975947c49b4"}]);
77+
console.log(result.members[0].channel_role) // "channel_member"
7478
return channel;
7579
},
7680
onSuccess: (channel) => {

client/src/app/(main)/messages/useInitializeChatClient.ts

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,84 @@
11
import kyInstance from "@/lib/ky";
22
import { useEffect, useState } from "react";
3-
import { StreamChat } from "stream-chat";
3+
import { StreamChat, UserResponse } from "stream-chat";
44
import { useSession } from "../SessionProvider";
5+
import { index } from "@/components/shared/api/userApi";
56

67
export default function useInitializeChatClient() {
78
const { user } = useSession();
89
const [chatClient, setChatClient] = useState<StreamChat | null>(null);
910

1011
useEffect(() => {
11-
const client = StreamChat.getInstance(process.env.NEXT_PUBLIC_STREAM_KEY!);
12-
13-
client
14-
.connectUser(
15-
{
16-
id: user.id,
17-
username: user.username,
18-
name: user.displayName,
19-
image: user.avatarUrl,
20-
},
21-
async () =>
22-
kyInstance
23-
.get("/api/get-token")
24-
// .get("/api/sessions")
25-
.json<{ token: string }>()
26-
.then((data) => data.token),
27-
)
28-
.catch((error) => console.error("Failed to connect user", error))
29-
.then(() => setChatClient(client));
12+
const initializeChatClient = async () => {
13+
try {
14+
// Khởi tạo client Stream Chat
15+
const client = StreamChat.getInstance(process.env.NEXT_PUBLIC_STREAM_KEY!);
3016

17+
// Upsert người dùng lên Stream Chat
18+
19+
try {
20+
const usersResponse = await index({ page: 1 });
21+
const users = usersResponse.users;
22+
const transformedUsers: UserResponse[] = users.map(user => ({
23+
id: user.id,
24+
username: user.username,
25+
name: user.name,
26+
image: user.avatarUrl,
27+
}));
28+
await client.upsertUsers(transformedUsers)
29+
// client.partialUpdateUser({...users[0], set: {role: "admin"}})
30+
await client.partialUpdateUser({id: "00cffeed-248f-4fc5-92ff-b99ebbad7e8d", set: {role: "admin"}})
31+
} catch (error) {
32+
console.error("Failed to upsert users", error);
33+
}
34+
35+
36+
37+
// const batchSize = 100; // Kích thước của mỗi batch
38+
// const upsertUsersInBatches = async (users: any[]) => {
39+
// for (let i = 0; i < users.length; i += batchSize) {
40+
// const batch = users.slice(i, i + batchSize);
41+
// await client.partialUpdateUsers(batch);
42+
// }
43+
// };
44+
45+
// await upsertUsersInBatches(users);
46+
47+
// Kết nối người dùng với Stream Chat
48+
await client.connectUser(
49+
{
50+
id: user.id,
51+
username: user.username,
52+
name: user.displayName,
53+
image: user.avatarUrl,
54+
},
55+
async () => {
56+
const response = await kyInstance.get("/api/get-token").json<{ token: string }>();
57+
return response.token;
58+
}
59+
);
60+
61+
62+
63+
// Cập nhật state với client đã kết nối
64+
setChatClient(client);
65+
} catch (error) {
66+
console.error("Failed to initialize chat client", error);
67+
}
68+
69+
// Cleanup khi component bị unmount
70+
return () => {
71+
if (chatClient) {
72+
chatClient.disconnectUser().catch((error) => console.error("Failed to disconnect user", error));
73+
}
74+
};
75+
};
76+
77+
initializeChatClient();
78+
79+
// Cleanup khi component bị unmount
3180
return () => {
3281
setChatClient(null);
33-
client
34-
.disconnectUser()
35-
.catch((error) => console.error("Failed to disconnect user", error))
36-
.then(() => console.log("Connection closed"));
3782
};
3883
}, [user.id, user.username, user.displayName, user.avatarUrl]);
3984

client/src/app/api/auth/callback/google/route.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export async function GET(req: NextRequest) {
7474
googleId: googleUser.id,
7575
},
7676
});
77+
// stream upsertUser
7778
await streamServerClient.upsertUser({
7879
id: userId,
7980
username,

client/src/components/shared/api/userApi.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ export interface ListResponse<User> {
1313
}
1414

1515
export interface User {
16-
readonly id: number
16+
readonly id: string
1717
name: string
18-
gravatar_id: string
19-
size: number
18+
username: string
19+
displayName: string
20+
avatarUrl: string
21+
// gravatar_id: string
22+
// size: number
2023
}
2124

2225
export interface CreateParams {
@@ -140,6 +143,7 @@ const userApi = {
140143
export default userApi;
141144
export const { create } = userApi;
142145
export const { update } = userApi;
146+
export const { index } = userApi;
143147

144148
export interface UserFollow {
145149
readonly id: number
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# This migration comes from active_storage (originally 20170806125915)
2+
class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
3+
def change
4+
# Use Active Record's configured type for primary and foreign keys
5+
primary_key_type, foreign_key_type = primary_and_foreign_key_types
6+
7+
create_table :active_storage_blobs, id: primary_key_type do |t|
8+
t.string :key, null: false
9+
t.string :filename, null: false
10+
t.string :content_type
11+
t.text :metadata
12+
t.string :service_name, null: false
13+
t.bigint :byte_size, null: false
14+
t.string :checksum
15+
16+
if connection.supports_datetime_with_precision?
17+
t.datetime :created_at, precision: 6, null: false
18+
else
19+
t.datetime :created_at, null: false
20+
end
21+
22+
t.index [ :key ], unique: true
23+
end
24+
25+
create_table :active_storage_attachments, id: primary_key_type do |t|
26+
t.string :name, null: false
27+
t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
28+
t.references :blob, null: false, type: foreign_key_type
29+
30+
if connection.supports_datetime_with_precision?
31+
t.datetime :created_at, precision: 6, null: false
32+
else
33+
t.datetime :created_at, null: false
34+
end
35+
36+
t.index [ :record_type, :record_id, :name, :blob_id ], name: :index_active_storage_attachments_uniqueness, unique: true
37+
t.foreign_key :active_storage_blobs, column: :blob_id
38+
end
39+
40+
create_table :active_storage_variant_records, id: primary_key_type do |t|
41+
t.belongs_to :blob, null: false, index: false, type: foreign_key_type
42+
t.string :variation_digest, null: false
43+
44+
t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true
45+
t.foreign_key :active_storage_blobs, column: :blob_id
46+
end
47+
end
48+
49+
private
50+
def primary_and_foreign_key_types
51+
config = Rails.configuration.generators
52+
setting = config.options[config.orm][:primary_key_type]
53+
primary_key_type = setting || :primary_key
54+
foreign_key_type = setting || :bigint
55+
[primary_key_type, foreign_key_type]
56+
end
57+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class CreateUsers < ActiveRecord::Migration[7.0]
2+
def change
3+
create_table :users do |t|
4+
t.string :name
5+
t.string :email
6+
t.string "refresh_token"
7+
t.datetime "refresh_token_expiration_at"
8+
9+
t.timestamps
10+
11+
t.index %i[email], unique: true, name: 'index_admin_users_email_uniqueness'
12+
t.index %i[refresh_token], unique: true, name: 'index_admin_users_refresh_token_uniqueness'
13+
end
14+
end
15+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddIndexToUsersEmail < ActiveRecord::Migration[7.0]
2+
def change
3+
add_index :users, :email, unique: true
4+
end
5+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddPasswordDigestToUsers < ActiveRecord::Migration[7.0]
2+
def change
3+
add_column :users, :password_digest, :string
4+
end
5+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddRememberDigestToUsers < ActiveRecord::Migration[7.0]
2+
def change
3+
add_column :users, :remember_digest, :string
4+
end
5+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddAdminToUsers < ActiveRecord::Migration[7.0]
2+
def change
3+
add_column :users, :admin, :boolean, default: false
4+
end
5+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class AddActivationToUsers < ActiveRecord::Migration[7.0]
2+
def change
3+
add_column :users, :activation_digest, :string
4+
add_column :users, :activated, :boolean, default: false
5+
add_column :users, :activated_at, :datetime
6+
end
7+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class AddResetToUsers < ActiveRecord::Migration[7.0]
2+
def change
3+
add_column :users, :reset_digest, :string
4+
add_column :users, :reset_sent_at, :datetime
5+
end
6+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class CreateMicroposts < ActiveRecord::Migration[7.0]
2+
def change
3+
create_table :microposts do |t|
4+
t.text :content
5+
t.references :user, null: false, foreign_key: true
6+
7+
t.timestamps
8+
end
9+
add_index :microposts, [:user_id, :created_at]
10+
end
11+
end
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class CreateRelationships < ActiveRecord::Migration[7.0]
2+
def change
3+
create_table :relationships do |t|
4+
t.integer :follower_id
5+
t.integer :followed_id
6+
7+
t.timestamps
8+
end
9+
add_index :relationships, :follower_id
10+
add_index :relationships, :followed_id
11+
add_index :relationships, [:follower_id, :followed_id], unique: true
12+
end
13+
end
14+
15+
# class CreateRelationships < ActiveRecord::Migration[7.0]
16+
# def change
17+
# create_table :relationships do |t|
18+
# t.integer :follower_id
19+
# t.integer :followed_id
20+
21+
# t.timestamps
22+
# end
23+
# end
24+
# end
25+
26+
# 20190827030205_create_relationships
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class CreateProducts < ActiveRecord::Migration[6.0]
2+
def change
3+
create_table :products do |t|
4+
t.string :name
5+
t.string :jan_code
6+
t.string :gender
7+
t.string :franchise
8+
t.string :producttype
9+
t.string :brand
10+
t.string :category
11+
t.string :sport
12+
t.text :description_h5
13+
t.text :description_p
14+
t.text :specifications
15+
t.text :care
16+
17+
t.timestamps
18+
end
19+
end
20+
end

0 commit comments

Comments
 (0)