Pattern: All services use the singleton pattern and export a single instance. Import using import serviceName from '@/src/services/serviceName'

Authentication Services

Firebase authentication operations

authService

Handles all authentication operations including email/password and Google Sign-In. Automatically sends verification emails on signup.

Methods

signUp(email: string, password: string, displayName: string): Promise<User>
signIn(email: string, password: string): Promise<User>
signInWithGoogle(): Promise<User>
sendVerificationEmail(): Promise<void>
resetPassword(email: string): Promise<void>
signOut(): Promise<void>
getCurrentUser(): User | null
deleteAccount(): Promise<void>

Usage Example

import authService from '@/src/services/authService';

// Sign up new user
const user = await authService.signUp(
  'student@college.edu',
  'password123',
  'John Doe'
);

// Sign in existing user
const user = await authService.signIn(email, password);

// Google Sign-In
const user = await authService.signInWithGoogle();

// Password reset
await authService.resetPassword('student@college.edu');

Data Services

Firestore database operations

firestoreService

Core database service for user profiles, timetables, and attendance tracking.

User Profile Methods

createUserProfile(uid: string, data: UserProfile): Promise<void>
getUserProfile(uid: string): Promise<UserProfile | null>
updateUserProfile(uid: string, data: Partial<UserProfile>): Promise<void>
deleteUserProfile(uid: string): Promise<void>

Timetable Methods (Manual Entry CRUD)

These methods support the manual timetable entry feature where users add/edit/delete entries one by one:

saveTimetable(uid: string, entries: TimetableEntry[]): Promise<void>
getTimetable(uid: string): Promise<TimetableEntry[]>
addTimetableEntry(uid: string, entry: TimetableEntry): Promise<string>
updateTimetableEntry(uid: string, entryId: string, data: Partial<TimetableEntry>): Promise<void>
deleteTimetableEntry(uid: string, entryId: string): Promise<void>

Subjects & Attendance Methods

getSubjects(uid: string): Promise<Subject[]>
addSubject(uid: string, subject: Subject): Promise<string>
updateSubject(uid: string, subjectId: string, data: Partial<Subject>): Promise<void>
deleteSubject(uid: string, subjectId: string): Promise<void>
updateSubjectAttendance(uid: string, subjectId: string, attended: number, total: number): Promise<void>
markAttendance(uid: string, subjectId: string, present: boolean): Promise<void>

notesService

Notes creation, editing, and feed generation for the collaborative notes feature.

CRUD Methods

createNote(authorId: string, data: CreateNoteInput): Promise<Note>
updateNote(noteId: string, data: Partial<Note>): Promise<void>
deleteNote(noteId: string, authorId: string): Promise<void>
getNoteById(noteId: string): Promise<Note | null>
getNoteWithContext(noteId: string, userId: string): Promise<FeedNote>

Feed & Discovery Methods

getFeedNotes(userId: string, followingIds: string[], lastDoc?: any): Promise<PaginatedResult<FeedNote>>
getExploreNotes(userId: string, filters?: NoteFilters, lastDoc?: any): Promise<PaginatedResult<FeedNote>>
getUserNotes(authorId: string, viewerId: string, lastDoc?: any): Promise<PaginatedResult<FeedNote>>
searchNotes(userId: string, query: string, filters?: NoteFilters): Promise<FeedNote[]>

Usage Example

import notesService from '@/src/services/notesService';

// Create a new note
const note = await notesService.createNote(userId, {
  title: 'Physics Chapter 5 Notes',
  description: 'Complete notes on thermodynamics',
  contentType: 'text',
  content: '# Thermodynamics...',
  subject: 'Physics',
  tags: ['physics', 'thermodynamics'],
  isPublic: true
});

// Get feed (notes from followed users)
const feed = await notesService.getFeedNotes(userId, followingIds);
console.log(feed.items, feed.hasMore);

groupsService

Study groups with real-time messaging, member management, and notifications.

Group Operations

createGroup(name, description, category, isPrivate, userId, userName, photoURL?, college?, course?, department?): Promise<string>
getGroup(groupId: string): Promise<Group | null>
getPublicGroups(limit?: number): Promise<Group[]>
getUserGroups(userId: string): Promise<Group[]>
updateGroup(groupId: string, updates: Partial<Group>): Promise<void>
deleteGroup(groupId: string): Promise<void>

Member Operations

joinGroup(groupId, userId, userName, photoURL?): Promise<void>
leaveGroup(groupId: string, userId: string): Promise<void>
addMember(groupId, userId, userName, photoURL?, role?): Promise<void>
removeMember(groupId: string, userId: string): Promise<void>
updateMemberRole(groupId, userId, newRole): Promise<void>
getGroupMembers(groupId: string): Promise<GroupMember[]>
isMember(groupId: string, userId: string): Promise<boolean>

Messaging Operations

sendMessage(groupId, userId, userName, photoURL?, message, fileUrl?, fileName?, fileType?): Promise<string>
getMessages(groupId: string, limit?: number): Promise<GroupMessage[]>
subscribeToMessages(groupId, callback, limit?): Unsubscribe
deleteMessage(groupId: string, messageId: string): Promise<void>
editMessage(groupId, messageId, newMessage): Promise<void>

Real-time Subscriptions

subscribeToMyGroups(userId: string, callback: (groups: Group[]) => void): Unsubscribe

Usage Example

import groupsService from '@/src/services/groupsService';

// Create a study group
const groupId = await groupsService.createGroup(
  'Physics Study Group',
  'Preparing for finals',
  'study',
  false, // public
  userId,
  'John Doe'
);

// Subscribe to real-time messages
const unsubscribe = groupsService.subscribeToMessages(
  groupId,
  (messages) => {
    console.log('New messages:', messages);
  }
);

// Send a message
await groupsService.sendMessage(
  groupId,
  userId,
  'John Doe',
  photoURL,
  'Hello everyone!'
);

// Cleanup
unsubscribe();

Social Services

Social interactions and following system

socialService

Handles likes, comments, saves, and download tracking for notes.

Like Operations

likeNote(noteId: string, userId: string): Promise<void>
unlikeNote(noteId: string, userId: string): Promise<void>
toggleLike(noteId: string, userId: string): Promise<boolean>
isNoteLiked(noteId: string, userId: string): Promise<boolean>
getNoteLikes(noteId: string): Promise<string[]>

Comment Operations

addComment(noteId: string, comment: Omit<NoteComment, 'id' | 'createdAt'>): Promise<NoteComment>
updateComment(noteId: string, commentId: string, content: string): Promise<void>
deleteComment(noteId: string, commentId: string): Promise<void>
getNoteComments(noteId: string): Promise<NoteComment[]>

Save Operations

saveNote(noteId: string, userId: string): Promise<void>
unsaveNote(noteId: string, userId: string): Promise<void>
toggleSave(noteId: string, userId: string): Promise<boolean>
isNoteSaved(noteId: string, userId: string): Promise<boolean>
getSavedNotes(userId: string, lastDoc?: any): Promise<PaginatedResult<Note>>

followService

User following system with suggestions.

Methods

followUser(followerId: string, followingId: string): Promise<void>
unfollowUser(followerId: string, followingId: string): Promise<void>
toggleFollow(followerId: string, followingId: string): Promise<boolean>
isFollowing(followerId: string, followingId: string): Promise<boolean>
getFollowing(userId: string): Promise<string[]>
getFollowers(userId: string): Promise<string[]>
getFollowingCount(userId: string): Promise<number>
getFollowersCount(userId: string): Promise<number>
getSuggestedUsers(userId: string, college: string, course: string): Promise<PublicUserProfile[]>

Usage Example

import followService from '@/src/services/followService';

// Follow a user
await followService.followUser(myUserId, targetUserId);

// Get suggestions from same college
const suggestions = await followService.getSuggestedUsers(
  myUserId,
  'MIT College',
  'Computer Science'
);

// Check if following
const isFollowing = await followService.isFollowing(myUserId, targetUserId);

OCR & Timetable Extraction Services

Alternative to manual entry: Extract timetable from images using OCR and AI parsing

Two ways to set up timetable:
1. Manual Entry (Default): Use firestoreService methods above to add/edit/delete entries with UI
2. OCR Extraction (Optional): Upload image → OCR extracts text → AI parses to entries → Review in manual entry screen

ocrService

OCR (Optical Character Recognition) service using OCR.space API to extract text from images. Supports multiple image formats and both web and native platforms.

Configuration

SettingValue
API ProviderOCR.space
OCR EngineEngine 2 (advanced)
Supported FormatsJPG, PNG, GIF, WebP, BMP, TIFF
Table DetectionEnabled
Auto ScaleEnabled

Methods

extractTextFromImage(imageUri: string): Promise<OCRResult>

OCRResult Interface

interface OCRResult {
  success: boolean;
  text: string;
  error?: string;
}

Supported Input Types

Input TypeExamplePlatform
Base64 Data URIdata:image/png;base64,...Web & Native
File URIfile:///path/to/image.jpgNative only
Content URIcontent://...Android only
HTTP URLhttps://example.com/image.pngWeb & Native

Usage Example

import { extractTextFromImage } from '@/src/services/ocrService';

// Extract text from image
const result = await extractTextFromImage('file:///path/to/timetable.jpg');

if (result.success) {
  console.log('Extracted text:', result.text);
} else {
  console.error('OCR failed:', result.error);
}

timetableParserService

AI-powered service that parses OCR-extracted text into structured TimetableEntry objects using Groq API (Llama 4 Maverick model).

Configuration

SettingValue
Modelmeta-llama/llama-4-maverick-17b-128e-instruct
Temperature0.1 (low for structured output)
Max Tokens4096
APIGroq Cloud API

Methods

parseTimetableFromText(ocrText: string): Promise<ParseResult>

ParseResult Interface

interface ParseResult {
  success: boolean;
  entries: TimetableEntry[];
  error?: string;
}

interface TimetableEntry {
  id: string;
  day: string;           // Monday, Tuesday, etc.
  subject: string;       // Subject name
  subjectCode?: string;  // Subject code (if detected)
  startTime: string;     // HH:MM format
  endTime: string;       // HH:MM format
  type?: string;         // lecture, lab, tutorial
  faculty?: string;      // Teacher name (if detected)
  room?: string;         // Room/Location (if detected)
}

Usage Example

import { extractTextFromImage } from '@/src/services/ocrService';
import { parseTimetableFromText } from '@/src/services/timetableParserService';

// Step 1: Extract text from image
const ocrResult = await extractTextFromImage(imageUri);

if (ocrResult.success) {
  // Step 2: Parse extracted text into timetable entries
  const parseResult = await parseTimetableFromText(ocrResult.text);

  if (parseResult.success) {
    console.log('Parsed entries:', parseResult.entries);
    // entries can be used to populate timetable
  }
}

AI Services

AI-powered chat and assistance

chatService

Groq API integration for BunkBot AI assistant with context-aware responses.

Configuration

SettingValue
Modelmeta-llama/llama-4-maverick-17b-128e-instruct
Temperature0.7
Max Tokens2048
APIGroq Cloud API

Methods

sendMessage(
  message: string,
  history: ChatMessage[],
  attendanceContext: AttendanceContext | null,
  imageBase64?: string
): Promise<string>

quickPrompts: Array<{ label: string; prompt: string }>

Attendance Context Interface

interface AttendanceContext {
  subjects: Subject[];
  timetable: TimetableEntry[];
  minimumAttendance: number;
  userName: string;
}

Usage Example

import { sendMessage, quickPrompts } from '@/src/services/chatService';

// Send message with attendance context
const response = await sendMessage(
  'Can I bunk physics class tomorrow?',
  chatHistory,
  {
    subjects: userSubjects,
    timetable: userTimetable,
    minimumAttendance: 75,
    userName: 'John'
  }
);

// Use with image
const response = await sendMessage(
  'Please analyze this timetable image',
  chatHistory,
  attendanceContext,
  base64ImageData
);

Infrastructure Services

Caching, offline support, and notifications

cacheService

AsyncStorage-based local caching for offline access.

Methods

cacheUserProfile(uid: string, profile: UserProfile): Promise<void>
getCachedUserProfile(uid: string): Promise<UserProfile | null>
cacheSubjects(uid: string, subjects: Subject[]): Promise<void>
getCachedSubjects(uid: string): Promise<Subject[] | null>
cacheTimetable(uid: string, timetable: TimetableEntry[]): Promise<void>
getCachedTimetable(uid: string): Promise<TimetableEntry[] | null>
clearCache(uid: string): Promise<void>
clearAllCache(): Promise<void>

offlineQueueService

Queue-based offline operation handling with auto-sync.

Methods

queueOperation(operation: OfflineOperation): Promise<void>
processQueue(): Promise<void>
getQueueLength(): Promise<number>
clearQueue(): Promise<void>

Operation Types

type OfflineOperation = {
  id: string;
  type: 'create' | 'update' | 'delete';
  collection: string;
  documentId?: string;
  data?: any;
  timestamp: Date;
}

notificationService

Push notification registration and handling.

Methods

registerForPushNotificationsAsync(): Promise<string | null>
savePushToken(userId: string, token: string): Promise<void>
deletePushToken(userId: string): Promise<void>
setupNotificationListeners(): void

Note

Push notifications require a development build (EAS). They are not available in Expo Go for SDK 53+.

File Upload Services

Cloud storage integration

imageUploadService

Uploads images to Catbox.moe (CORS-friendly for avatars).

Methods

uploadImage(imageUri: string): Promise<string> // Returns URL
uploadImageBase64(base64: string, fileName: string): Promise<string>

googleDriveService

Google Drive API for note attachments (PDFs, images).

Methods

uploadFile(file: File): Promise<UploadResult>
deleteFile(fileId: string): Promise<void>
getFileUrl(fileId: string): string
getThumbnailUrl(fileId: string): string

Upload Result

interface UploadResult {
  fileId: string;
  fileName: string;
  mimeType: string;
  size: number;
  webViewLink: string;
  webContentLink: string;
  thumbnailLink?: string;
}

chatStorageService

Persists chat conversations locally using AsyncStorage.

Methods

createChat(): Promise<Chat>
getAllChats(): Promise<Chat[]>
updateChatMessages(chatId: string, messages: ChatMessage[]): Promise<void>
deleteChat(chatId: string): Promise<void>
getActiveChatId(): Promise<string | null>
setActiveChatId(chatId: string): Promise<void>

Chat Interface

interface Chat {
  id: string;
  title: string;
  messages: ChatMessage[];
  createdAt: Date;
  updatedAt: Date;
}

interface ChatMessage {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  image?: string; // Base64
  timestamp: Date;
}