├── LICENSE
├── README.md
├── accounts
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ ├── admin.cpython-36.pyc
│ ├── forms.cpython-36.pyc
│ ├── models.cpython-36.pyc
│ ├── urls.cpython-36.pyc
│ └── views.cpython-36.pyc
├── admin.py
├── api
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ ├── permissions.cpython-36.pyc
│ │ ├── serializers.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ ├── utils.cpython-36.pyc
│ │ └── views.cpython-36.pyc
│ ├── permissions.py
│ ├── serializers.py
│ ├── urls.py
│ ├── utils.py
│ └── views.py
├── apps.py
├── forms.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_auto_20191127_1345.py
│ ├── 0003_myuser_spam_count.py
│ ├── 0004_auto_20191127_2121.py
│ ├── __init__.py
│ └── __pycache__
│ │ ├── 0001_initial.cpython-36.pyc
│ │ ├── 0002_auto_20191127_1345.cpython-36.pyc
│ │ ├── 0003_myuser_spam_count.cpython-36.pyc
│ │ ├── 0004_auto_20191127_2121.cpython-36.pyc
│ │ └── __init__.cpython-36.pyc
├── models.py
├── tests.py
├── urls.py
└── views.py
├── data
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ ├── admin.cpython-36.pyc
│ ├── models.cpython-36.pyc
│ ├── urls.cpython-36.pyc
│ └── views.cpython-36.pyc
├── admin.py
├── api
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ ├── serializers.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ └── views.cpython-36.pyc
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── apps.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_auto_20191127_2150.py
│ ├── __init__.py
│ └── __pycache__
│ │ ├── 0001_initial.cpython-36.pyc
│ │ ├── 0002_auto_20191127_2150.cpython-36.pyc
│ │ └── __init__.cpython-36.pyc
├── models.py
├── templates
│ └── home.html
├── tests.py
├── urls.py
└── views.py
├── db.sqlite3
├── manage.py
├── requirements.txt
└── truecaller
├── __init__.py
├── __pycache__
├── __init__.cpython-36.pyc
├── putdata.cpython-36.pyc
├── settings.cpython-36.pyc
├── urls.cpython-36.pyc
└── wsgi.cpython-36.pyc
├── data.csv
├── putdata.py
├── restconf
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ └── main.cpython-36.pyc
└── main.py
├── settings.py
├── urls.py
└── wsgi.py
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Naveen Arora
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Truecaller-APIs
2 |
3 | This is a brief description of what this app does and how these apis work
4 | As specified, this app is just like truecaller and works on same principle
5 |
6 | To start the project, one needs to run the server first using the specified virtual environment.
7 | On Linux,
8 | Enter following commands once you are in this directory
9 |
10 | source venv/bin/activate
11 | cd truecaller
12 | python manage.py runserver
13 |
14 | Now the application server has started,
15 |
16 | Every Functionality implemented in the code could have been implemented using various other methods. I have used methods which I felt would be appropriate
17 | To access anything in the api , one needs to be logged in otherwise it will raise Authentication errors.
18 |
19 | To register using the API: -
20 |
21 | ENDPOINT - http://localhost:8000/api/auth/register/
22 |
23 | data = {
24 | "name": "",
25 | "phone_number": "",
26 | "email": "",
27 | "password": "",
28 | "password2": ""
29 | }
30 |
31 | To login and authenticate into the API :
32 |
33 | ENDPOINT - http://localhost:8000/api/auth/login/
34 |
35 | data = {
36 | "phone_number/email": "",
37 | "password": "",
38 | }
39 |
40 | Note :- I have used JWT Authentication and implicitly logging into django using login function, but for third party devices and apps, we can use token based system to verify and it has also been implemented here only
41 | After logging in you can use below ENDPOINTS
42 |
43 | Search using the API
44 | ENDPOINT - http://localhost:8000/api/data/
45 |
46 | To search using a phone number -
47 | ENDPOINT - http://localhost:8000/api/data/?p={phone_number}
48 |
49 | Replace {phone_number} with phone number and make a get request
50 |
51 | To search using a name -
52 | ENDPOINT - http://localhost:8000/api/data/?name={name}
53 |
54 | Replace {phone_number} with phone number and make a get request
55 |
56 | Detail View of Users
57 | ENDPOINT - http://localhost:8000/api/data/{user_id}
58 |
59 | Replace {user_id} with respective id of user to display.
60 | It has been keeping in mind to show the Email if Requested User has logged in user's phone number as a contact
61 |
62 | To mark spam
63 | Make a POST request to the ENDPOINT
64 |
65 | Detail View of Contacts
66 | ENDPOINT - http://localhost:8000/api/data/p/{user_id}/
67 |
68 | Replace {user_id} with respective id of user to display.
69 | It has been keeping in mind to show the Email if Requested User has logged in user's phone number as a contact
70 |
71 | To mark spam
72 | Make a POST request to the ENDPOINT
73 |
74 |
75 | Declaration - This application is intended for educational purposes only. Any use in professional manner or to harm anyone or any organization doesn't relate to me and can be considered as illegal.
76 |
77 |
78 | Promotion - If you are lookingfor best instagram captions for your instagram posts then must check out Instafbcaptions.com
79 |
--------------------------------------------------------------------------------
/accounts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__init__.py
--------------------------------------------------------------------------------
/accounts/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/__pycache__/admin.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/admin.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/__pycache__/forms.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/forms.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/__pycache__/models.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/models.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/__pycache__/urls.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/urls.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/__pycache__/views.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/views.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/admin.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from django.contrib import admin
3 | from django.contrib.auth.models import Group
4 | from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
5 | from django.contrib.auth.forms import ReadOnlyPasswordHashField
6 | from .models import MyUser
7 | from .forms import UserChangeForm, UserCreationForm
8 |
9 |
10 |
11 | class UserAdmin(BaseUserAdmin):
12 | form = UserChangeForm
13 | add_form = UserCreationForm
14 | list_display = ('name', 'phone_number', 'is_admin')
15 | list_filter = ('is_admin',)
16 | fieldsets = (
17 | (None, {'fields': ('name', 'phone_number', 'password')}),
18 | ('Personal info', {'fields': ('email','spam_count')}),
19 | ('Permissions', {'fields': ('is_admin','is_staff')}),
20 | )
21 | # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
22 | # overrides get_fieldsets to use this attribute when creating a user.
23 | add_fieldsets = (
24 | (None, {
25 | 'classes': ('wide',),
26 | 'fields': ('name', 'phone_number', 'email','password1', 'password2')}
27 | ),
28 | )
29 | search_fields = ('phone_number', 'phone_number',)
30 | ordering = ('name', 'phone_number',)
31 | filter_horizontal = ()
32 |
33 |
34 |
35 |
36 |
37 | admin.site.register(MyUser, UserAdmin)
38 | admin.site.unregister(Group)
--------------------------------------------------------------------------------
/accounts/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__init__.py
--------------------------------------------------------------------------------
/accounts/api/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/api/__pycache__/permissions.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/permissions.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/api/__pycache__/serializers.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/serializers.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/api/__pycache__/urls.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/urls.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/api/__pycache__/utils.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/utils.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/api/__pycache__/views.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/views.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/api/permissions.py:
--------------------------------------------------------------------------------
1 | from rest_framework import permissions
2 |
3 | class AnonPermissionOnly(permissions.BasePermission):
4 | def has_permission(self,request,view):
5 | return not request.user.is_authenticated
--------------------------------------------------------------------------------
/accounts/api/serializers.py:
--------------------------------------------------------------------------------
1 | from rest_framework import serializers
2 | from django.contrib.auth import get_user_model
3 | import datetime
4 | from django.conf import settings
5 | from django.utils import timezone
6 |
7 |
8 | # token expires after a period of EXPIRATION_DELTA
9 | expire_delta = settings.JWT_AUTH['JWT_REFRESH_EXPIRATION_DELTA']
10 |
11 | # JWT configuration to use
12 | from rest_framework_jwt.settings import api_settings
13 | jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
14 | jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
15 | jwt_response_payload_handler = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER
16 |
17 | # instance of user model
18 | User = get_user_model()
19 |
20 | # Registeration Serializer
21 | class UserRegisterSerializer(serializers.ModelSerializer):
22 | password = serializers.CharField(style={'input_type':'password'},write_only=True)
23 | password2 = serializers.CharField(style={'input_type':'password'},write_only=True)
24 | token = serializers.SerializerMethodField(read_only=True)
25 | expires = serializers.SerializerMethodField(read_only=True)
26 | message = serializers.SerializerMethodField(read_only=True)
27 |
28 | class Meta:
29 | model=User
30 | fields=[
31 | 'name',
32 | 'phone_number',
33 | 'email',
34 | 'password',
35 | 'password2',
36 | 'token',
37 | 'expires',
38 | 'message'
39 | ]
40 | def validate_phone_number(self,value):
41 | qs = User.objects.filter(phone_number__iexact=value)
42 | import re
43 | if not re.match("\d{10}",value):
44 | raise serializers.ValidationError("Enter a valid phone number")
45 | if qs.exists():
46 | raise serializers.ValidationError("User with this phone number already exists")
47 | return value
48 | def get_message(self,obj):
49 | return "Registeration Successfull. To login go to /api/auth/"
50 | def get_expires(self,obj):
51 | return timezone.now() + expire_delta - datetime.timedelta(seconds=200)
52 |
53 | def get_token(self, obj):
54 | payload=jwt_payload_handler(obj)
55 | token=jwt_encode_handler(payload)
56 | return token
57 | def validate(self,data):
58 | pw = data.get("password")
59 | pw2 = data.pop("password2")
60 | if pw!= pw2:
61 | raise serializers.ValidationError("Passwords must match")
62 | return data
63 |
64 |
--------------------------------------------------------------------------------
/accounts/api/urls.py:
--------------------------------------------------------------------------------
1 | from rest_framework_jwt.views import obtain_jwt_token,refresh_jwt_token
2 | from django.urls import path
3 | from .views import AuthView,RegisterAPIView,LogoutAPIView
4 |
5 | urlpatterns = [
6 | path('login/', AuthView.as_view()),
7 | path('register/', RegisterAPIView.as_view()),
8 | path('logout/', LogoutAPIView.as_view()),
9 | path('jwt/', obtain_jwt_token),
10 | path('refresh/', refresh_jwt_token),
11 | ]
12 |
13 |
--------------------------------------------------------------------------------
/accounts/api/utils.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | from django.conf import settings
3 | from django.utils import timezone
4 | from rest_framework_jwt.settings import api_settings
5 | expire_delta = settings.JWT_AUTH['JWT_REFRESH_EXPIRATION_DELTA']
6 |
7 | def jwt_response_payload_handler(token,user=None,request=None):
8 | return {
9 | 'token':token,
10 | 'user':user.name,
11 | 'phone_number':user.phone_number,
12 | 'expires': timezone.now() + expire_delta - datetime.timedelta(seconds=200)
13 | }
--------------------------------------------------------------------------------
/accounts/api/views.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth import authenticate, get_user_model
2 | from django.db.models import Q
3 | from django.contrib.auth import logout,login
4 |
5 | # rest_framework
6 | from rest_framework import permissions, generics
7 | from rest_framework.views import APIView
8 | from rest_framework.response import Response
9 |
10 | # relative imports
11 | from .serializers import UserRegisterSerializer
12 | from .permissions import AnonPermissionOnly
13 |
14 | # jwt handlers
15 | from rest_framework_jwt.settings import api_settings
16 | jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
17 | jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
18 | jwt_response_payload_handler = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER
19 |
20 | # User model
21 | User=get_user_model()
22 |
23 | # Login ENDPOINT Handler
24 | class AuthView(APIView):
25 | permission_classes = [permissions.AllowAny]
26 | def post(self, request, *args, **kwargs):
27 | if request.user.is_authenticated:
28 | return Response({"data":"You are already authenticated"})
29 | data=request.data
30 | query=data.get("phone_number")
31 | password=data.get("password")
32 | qs=User.objects.filter(
33 | Q(phone_number__iexact=query)|
34 | Q(email__iexact=query)
35 | ).distinct()
36 | if qs.count()==1:
37 | user_obj=qs.first()
38 | if user_obj.check_password(password):
39 | user=user_obj
40 | login(request,user)
41 | payload=jwt_payload_handler(user)
42 | token=jwt_encode_handler(payload)
43 | response=jwt_response_payload_handler(token,user,request=request)
44 | return Response(response)
45 | return Response({"data":"Invalid Credentials"},status=401).add_post_render_callback
46 |
47 | # Register ENDPOINT Handler
48 | class RegisterAPIView(generics.CreateAPIView):
49 | queryset = User.objects.all()
50 | serializer_class = UserRegisterSerializer
51 | permission_classes = [AnonPermissionOnly]
52 |
53 | def get_serializer_context(self, *args,**kwargs):
54 | return {"request": self.request}
55 |
56 | # Logout ENDPOINT Handler
57 | class LogoutAPIView(APIView):
58 | def post(self,request,*args,**kwargs):
59 | logout(request)
60 | return Response({"Message":"Successfully Logged out"},status=200)
--------------------------------------------------------------------------------
/accounts/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class AccountsConfig(AppConfig):
5 | name = 'accounts'
6 |
--------------------------------------------------------------------------------
/accounts/forms.py:
--------------------------------------------------------------------------------
1 | # imports from django
2 | from django.db.models import Q
3 | from django import forms
4 | from django.contrib.auth.forms import ReadOnlyPasswordHashField
5 | from django.contrib.auth import get_user_model, authenticate
6 | from django.core.validators import RegexValidator
7 |
8 | # instance of User model
9 | User=get_user_model()
10 |
11 | # creating login form for user
12 | class UserLoginForm(forms.Form):
13 | phone_number=forms.CharField(label='Phone Number/Email',widget=forms.TextInput(attrs=
14 | {
15 | 'class':'form-control',
16 | 'placeholder' : 'User Name',
17 | }))
18 | password = forms.CharField(label='Password', widget=forms.PasswordInput(attrs=
19 | {
20 | 'class':'form-control',
21 | 'placeholder' : 'Password',
22 | }))
23 | # overriding default clean method for validating whether user and password are appropriate
24 | def clean(self, *args,**kwargs):
25 | query =self.cleaned_data.get('query')
26 | password =self.cleaned_data.get('password')
27 | user_qs_final=User.objects.filter(
28 | Q(phone_number__iexact=query)|
29 | Q(email__iexact=query)
30 | ).distinct()
31 | if not user_qs_final.exists() and user_qs_final.count() !=1:
32 | raise forms.ValidationError("Invalid Phone Number or Email")
33 | else:
34 | user_obj =user_qs_final.first()
35 | if not user_obj.check_password(password):
36 | raise forms.ValidationError("Invalid Password for {}".format(query))
37 | self.cleaned_data['user_obj']=user_obj
38 | return super(UserLoginForm, self).clean(*args,**kwargs)
39 |
40 | #user creation form or in specific registeration form
41 | class UserCreationForm(forms.ModelForm):
42 | """A form for creating new users. Includes all the required
43 | fields, plus a repeated password."""
44 | name = forms.CharField(label='Full Name')
45 | phone_number = forms.CharField()
46 | email = forms.EmailField(required=False)
47 | password1 = forms.CharField(label='Password', widget=forms.PasswordInput(attrs=
48 | {
49 | 'class':'form-control',
50 | 'placeholder' : 'Password',
51 | }))
52 | password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput(attrs=
53 | {
54 | 'class':'form-control',
55 | 'placeholder' : 'Confirm Password',
56 | }))
57 |
58 | class Meta:
59 | model = User
60 | fields = ('name','phone_number','email',)
61 |
62 | def clean_password2(self):
63 | # Check that the two password entries match
64 | password1 = self.cleaned_data.get("password1")
65 | password2 = self.cleaned_data.get("password2")
66 | if len(password1)<7:
67 | raise forms.ValidationError("Password must be of at least 8 digits")
68 |
69 | if password1 and password2 and password1 != password2:
70 | raise forms.ValidationError("Passwords don't match")
71 | return password2
72 |
73 | def save(self, commit=True):
74 | # Save the provided password in hashed format
75 | user = super().save(commit=False)
76 | user.set_password(self.cleaned_data["password1"])
77 | if commit:
78 | user.save()
79 | return user
80 |
81 | # changing the user from admin panel itself
82 | class UserChangeForm(forms.ModelForm):
83 | password = ReadOnlyPasswordHashField()
84 |
85 | class Meta:
86 | model = User
87 | fields = ('name', 'phone_number', 'email', 'spam_count','is_staff', 'is_admin','password')
88 |
89 | def clean_password(self):
90 | # Regardless of what the user provides, return the initial value.
91 | # This is done here, rather than on the field, because the
92 | # field does not have access to the initial value
93 | return self.initial["password"]
--------------------------------------------------------------------------------
/accounts/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.7 on 2019-11-27 13:41
2 |
3 | import django.core.validators
4 | from django.db import migrations, models
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | initial = True
10 |
11 | dependencies = [
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='MyUser',
17 | fields=[
18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('password', models.CharField(max_length=128, verbose_name='password')),
20 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
21 | ('name', models.CharField(max_length=120)),
22 | ('phone_number', models.CharField(max_length=20, unique=True, validators=[django.core.validators.RegexValidator(code='invalid_username', message='Phone Number must be of 10 digits', regex='^[0-9]*{10}$')])),
23 | ('email', models.EmailField(blank=True, max_length=255, null=True, unique=True, verbose_name='email address')),
24 | ('is_admin', models.BooleanField(default=False)),
25 | ('is_staff', models.BooleanField(default=False)),
26 | ],
27 | options={
28 | 'abstract': False,
29 | },
30 | ),
31 | ]
32 |
--------------------------------------------------------------------------------
/accounts/migrations/0002_auto_20191127_1345.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.7 on 2019-11-27 13:45
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('accounts', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='myuser',
15 | name='email',
16 | field=models.EmailField(blank=True, max_length=255, null=True, verbose_name='email address'),
17 | ),
18 | migrations.AlterField(
19 | model_name='myuser',
20 | name='phone_number',
21 | field=models.CharField(max_length=20, unique=True),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/accounts/migrations/0003_myuser_spam_count.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.7 on 2019-11-27 21:20
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('accounts', '0002_auto_20191127_1345'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='myuser',
15 | name='spam_count',
16 | field=models.IntegerField(default=0),
17 | preserve_default=False,
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/accounts/migrations/0004_auto_20191127_2121.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.7 on 2019-11-27 21:21
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('accounts', '0003_myuser_spam_count'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='myuser',
15 | name='spam_count',
16 | field=models.IntegerField(default=0),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/accounts/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__init__.py
--------------------------------------------------------------------------------
/accounts/migrations/__pycache__/0001_initial.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/0001_initial.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/migrations/__pycache__/0002_auto_20191127_1345.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/0002_auto_20191127_1345.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/migrations/__pycache__/0003_myuser_spam_count.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/0003_myuser_spam_count.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/migrations/__pycache__/0004_auto_20191127_2121.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/0004_auto_20191127_2121.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/migrations/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/accounts/models.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.db import models
3 | from django.db.models.signals import post_save
4 | from django.contrib.auth.models import (
5 | BaseUserManager, AbstractBaseUser
6 | )
7 | from django.core.validators import RegexValidator
8 |
9 |
10 | class MyUserManager(BaseUserManager):
11 | def create_user(self, name, phone_number, email, password=None):
12 | """
13 | Creates and saves a User with the given phone number, name and password
14 | """
15 | if not phone_number:
16 | raise ValueError('User must have a Phone Number')
17 | if not email:
18 | email=""
19 | else:
20 | email=self.normalize_email(email),
21 |
22 | user = self.model(
23 | name=name,
24 | phone_number=phone_number,
25 | email=email,
26 | )
27 |
28 | user.set_password(password)
29 | user.save(using=self._db)
30 | return user
31 |
32 | def create_superuser(self, name, phone_number, password):
33 | """
34 | Creates and saves a superuser with the given email, date of
35 | birth and password.
36 | """
37 | email=""
38 | user = self.create_user(
39 | name,
40 | phone_number,
41 | email,
42 | password=password,
43 | )
44 | user.is_admin = True
45 | user.is_staff = True
46 | user.save(using=self._db)
47 | return user
48 |
49 | NAME_REGEX='^[a-zA-Z]*$'
50 | PHONENO_REGEX='^[0-9]*{10}$'
51 |
52 | # overriding default USER MODEL
53 | class MyUser(AbstractBaseUser):
54 | name=models.CharField(max_length=120)
55 | phone_number = models.CharField(max_length=20,
56 | unique=True)
57 | email = models.EmailField(
58 | verbose_name='email address',
59 | max_length=255,
60 | null=True,
61 | blank=True
62 | )
63 | spam_count = models.IntegerField(default=0)
64 | is_admin = models.BooleanField(default=False)
65 | is_staff = models.BooleanField(default=False)
66 | objects = MyUserManager()
67 | USERNAME_FIELD = 'phone_number'
68 | REQUIRED_FIELDS = ['name']
69 |
70 | def __str__(self):
71 | return self.name
72 |
73 | def has_perm(self, perm, obj=None):
74 | "Does the user have a specific permission?"
75 | # Simplest possible answer: Yes, always
76 | return True
77 | def has_module_perms(self, app_label):
78 | "Does the user have permissions to view the app `app_label`?"
79 | # Simplest possible answer: Yes, always
80 | return True
--------------------------------------------------------------------------------
/accounts/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/accounts/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path,include
2 |
3 |
4 | urlpatterns = [
5 | path('', include("accounts.api.urls")),
6 | ]
7 |
--------------------------------------------------------------------------------
/accounts/views.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/views.py
--------------------------------------------------------------------------------
/data/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__init__.py
--------------------------------------------------------------------------------
/data/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/data/__pycache__/admin.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/admin.cpython-36.pyc
--------------------------------------------------------------------------------
/data/__pycache__/models.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/models.cpython-36.pyc
--------------------------------------------------------------------------------
/data/__pycache__/urls.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/urls.cpython-36.pyc
--------------------------------------------------------------------------------
/data/__pycache__/views.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/views.cpython-36.pyc
--------------------------------------------------------------------------------
/data/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 | from .models import PersonalContacts
5 |
6 | admin.site.register(PersonalContacts)
--------------------------------------------------------------------------------
/data/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__init__.py
--------------------------------------------------------------------------------
/data/api/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/data/api/__pycache__/serializers.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__pycache__/serializers.cpython-36.pyc
--------------------------------------------------------------------------------
/data/api/__pycache__/urls.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__pycache__/urls.cpython-36.pyc
--------------------------------------------------------------------------------
/data/api/__pycache__/views.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__pycache__/views.cpython-36.pyc
--------------------------------------------------------------------------------
/data/api/serializers.py:
--------------------------------------------------------------------------------
1 | from rest_framework import serializers
2 | from django.contrib.auth import get_user_model
3 | from data.models import PersonalContacts
4 | User = get_user_model()
5 |
6 | # To display user model search results
7 | class UserModelSerializer(serializers.ModelSerializer):
8 | uri = serializers.SerializerMethodField(read_only=True)
9 | class Meta:
10 | model=User
11 | fields=[
12 | 'uri',
13 | 'name',
14 | 'phone_number',
15 | 'spam_count'
16 | ]
17 | def get_uri(self,obj):
18 | return "http://localhost:8000/api/data/{}/".format(obj.id)
19 |
20 | # To display personal_contacts model search results
21 | class PersonalContactsSerializer(serializers.ModelSerializer):
22 | uri = serializers.SerializerMethodField(read_only=True)
23 | class Meta:
24 | model=PersonalContacts
25 | fields=[
26 | 'uri',
27 | 'name',
28 | 'phone_number',
29 | 'spam_count'
30 | ]
31 | def get_uri(self,obj):
32 | return "http://localhost:8000/api/data/p/{}/".format(obj.id)
33 |
34 |
--------------------------------------------------------------------------------
/data/api/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from .views import (
3 | DataListSearchAPIView,
4 | UserDetailAPIView,
5 | PersonalContactsDetailAPIView
6 | # UserMarkSpamAPIView
7 |
8 | )
9 |
10 | urlpatterns = [
11 | path('', DataListSearchAPIView.as_view()),
12 | path('/', UserDetailAPIView.as_view()),
13 | path('p//', PersonalContactsDetailAPIView.as_view()),
14 |
15 | # path('/spam', UserMarkSpamAPIView.as_view()),
16 |
17 | ]
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/data/api/views.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth import get_user_model
2 | from django.db.models import Q
3 | User=get_user_model()
4 |
5 | # rest_framework
6 | from rest_framework import permissions, generics, mixins
7 | from rest_framework.views import APIView
8 | from rest_framework.response import Response
9 |
10 | # relative import of serializer
11 | from .serializers import UserModelSerializer, PersonalContactsSerializer
12 |
13 | # importing Model
14 | from data.models import PersonalContacts
15 |
16 | # Search View Handler API ENDPOINT
17 | class DataListSearchAPIView(APIView):
18 | def get(self,request,*args, **kwargs):
19 | if 'p' in request.GET:
20 | search_phone_number = request.GET['p']
21 | qs = User.objects.filter(phone_number__iexact=search_phone_number)
22 | if qs.count()==1:
23 | serializer = UserModelSerializer(qs, many=True)
24 | return Response(serializer.data)
25 | else:
26 | qs = PersonalContacts.objects.filter(phone_number__iexact=search_phone_number)
27 | print(qs)
28 | if qs.count() > 0:
29 | serializer = PersonalContactsSerializer(qs, many=True)
30 | data={
31 | "message":"Number is not registered",
32 | "data":serializer.data
33 | }
34 | return Response(data)
35 | if 'name' in request.GET:
36 | search_name = request.GET['name']
37 | user_qs = User.objects.filter(
38 | Q(name__startswith=search_name)|
39 | Q(name__icontains = search_name)
40 | ).distinct()
41 | p_qs = PersonalContacts.objects.filter(
42 | Q(name__startswith=search_name)|
43 | Q(name__icontains = search_name)
44 | ).distinct()
45 | serializer1 = UserModelSerializer(user_qs,many=True)
46 | serializer2 = PersonalContactsSerializer(p_qs, many=True)
47 | data={
48 | 'registered_users':serializer1.data,
49 | 'personal_contacts':serializer2.data
50 | }
51 | return Response(data)
52 | return Response({"data":"Search something by name (?name=) or phone_number (?p=)"},status=200)
53 |
54 | # detail view of User model
55 | class UserDetailAPIView(APIView):
56 |
57 | def get(self,request,pk,*args,**kwargs):
58 | qs=User.objects.get(id=pk)
59 | serializer = UserModelSerializer(qs)
60 |
61 | # to display email or not
62 | # user is already registered
63 | # now check whether searching user is in this user's contact list
64 | check_qs = PersonalContacts.objects.filter(
65 | Q(user=qs) &
66 | Q(phone_number__icontains=request.user.phone_number)
67 | )
68 | if check_qs.count()>0:
69 | data={
70 | "data":serializer.data,
71 | "email":qs.email
72 | }
73 | else:
74 | data=serializer.data
75 | return Response(data)
76 |
77 | def post(self,request,pk,*args,**kwargs):
78 | q=User.objects.get(id=pk)
79 | q.spam_count+=1
80 | q.save()
81 | serializer = UserModelSerializer(q)
82 | data={
83 | "data":serializer.data,
84 | "message":"{} marked as spam.".format(q.name)
85 | }
86 | return Response(data,status=200)
87 |
88 |
89 | # detail view of Personal contacts model
90 | class PersonalContactsDetailAPIView(APIView):
91 |
92 | def get(self,request,pk,*args,**kwargs):
93 | qs=PersonalContacts.objects.get(id=pk)
94 | serializer = PersonalContactsSerializer(qs)
95 | return Response(serializer.data)
96 |
97 | def post(self,request,pk,*args,**kwargs):
98 | q=PersonalContacts.objects.get(id=pk)
99 | q.spam_count+=1
100 | q.save()
101 | serializer = PersonalContactsSerializer(q)
102 | data={
103 | "data":serializer.data,
104 | "message":"{} marked as spam.".format(q.name)
105 | }
106 | return Response(data,status=200)
107 |
--------------------------------------------------------------------------------
/data/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class DataConfig(AppConfig):
5 | name = 'data'
6 |
--------------------------------------------------------------------------------
/data/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.7 on 2019-11-27 21:22
2 |
3 | from django.conf import settings
4 | import django.core.validators
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | initial = True
12 |
13 | dependencies = [
14 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15 | ]
16 |
17 | operations = [
18 | migrations.CreateModel(
19 | name='PersonalContacts',
20 | fields=[
21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22 | ('name', models.CharField(max_length=200)),
23 | ('phone_number', models.CharField(max_length=200, validators=[django.core.validators.RegexValidator(code='invalid_username', message='Phone Number must be of 10 digits', regex='^[0-9]*$')])),
24 | ('email_address', models.EmailField(max_length=254)),
25 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
26 | ],
27 | ),
28 | ]
29 |
--------------------------------------------------------------------------------
/data/migrations/0002_auto_20191127_2150.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.7 on 2019-11-27 21:50
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('data', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='personalcontacts',
15 | name='spam_count',
16 | field=models.IntegerField(default=0),
17 | ),
18 | migrations.AlterField(
19 | model_name='personalcontacts',
20 | name='email_address',
21 | field=models.EmailField(blank=True, max_length=254, null=True),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/data/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/migrations/__init__.py
--------------------------------------------------------------------------------
/data/migrations/__pycache__/0001_initial.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/migrations/__pycache__/0001_initial.cpython-36.pyc
--------------------------------------------------------------------------------
/data/migrations/__pycache__/0002_auto_20191127_2150.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/migrations/__pycache__/0002_auto_20191127_2150.cpython-36.pyc
--------------------------------------------------------------------------------
/data/migrations/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/migrations/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/data/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.core.validators import RegexValidator
3 | from django.conf import settings
4 | # Create your models here.
5 |
6 | PHONENO_REGEX='^[0-9]{10}$'
7 |
8 | class PersonalContacts(models.Model):
9 | user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
10 | name = models.CharField(max_length=200)
11 | phone_number = models.CharField(max_length=200,validators=[RegexValidator(
12 | regex=PHONENO_REGEX,
13 | message="Phone Number must be of 10 digits",
14 | code='invalid_username'
15 | )])
16 | email_address = models.EmailField(null=True, blank=True)
17 | spam_count = models.IntegerField(default=0)
18 | def __str__(self):
19 | return self.name
--------------------------------------------------------------------------------
/data/templates/home.html:
--------------------------------------------------------------------------------
1 | This is a brief description of what this app does and how these apis work
2 | As specified, this app is just like truecaller and works on same principle
3 |
4 | To start the project, one needs to run the server first using the specified virtual environment.
5 | On Linux,
6 | Enter following commands once you are in this directory
7 |
8 | source venv/bin/activate
9 | cd truecaller
10 | python manage.py runserver
11 |
12 | Now the application server has started,
13 |
14 | Every Functionality implemented in the code could have been implemented using various other methods. I have used methods which I felt would be appropriate
15 | To access anything in the api , one needs to be logged in otherwise it will raise Authentication errors.
16 |
17 | To register using the API: -
18 |
19 | ENDPOINT - http://localhost:8000/api/auth/register/
20 |
21 | data = {
22 | "name": "",
23 | "phone_number": "",
24 | "email": "",
25 | "password": "",
26 | "password2": ""
27 | }
28 |
29 | To login and authenticate into the API :
30 |
31 | ENDPOINT - http://localhost:8000/api/auth/login/
32 |
33 | data = {
34 | "phone_number/email": "",
35 | "password": "",
36 | }
37 |
38 | Note :- I have used JWT Authentication and implicitly logging into django using login function, but for third party devices and apps, we can use token based system to verify and it has also been implemented here only
39 | After logging in you can use below ENDPOINTS
40 |
41 | Search using the API
42 | ENDPOINT - http://localhost:8000/api/data/
43 |
44 | To search using a phone number -
45 | ENDPOINT - http://localhost:8000/api/data/?p={phone_number}
46 |
47 | Replace {phone_number} with phone number and make a get request
48 |
49 | To search using a name -
50 | ENDPOINT - http://localhost:8000/api/data/?name={name}
51 |
52 | Replace {phone_number} with phone number and make a get request
53 |
54 | Detail View of Users
55 | ENDPOINT - http://localhost:8000/api/data/{user_id}
56 |
57 | Replace {user_id} with respective id of user to display.
58 | It has been keeping in mind to show the Email if Requested User has logged in user's phone number as a contact
59 |
60 | To mark spam
61 | Make a POST request to the ENDPOINT
62 |
63 | Detail View of Contacts
64 | ENDPOINT - http://localhost:8000/api/data/p/{user_id}/
65 |
66 | Replace {user_id} with respective id of user to display.
67 | It has been keeping in mind to show the Email if Requested User has logged in user's phone number as a contact
68 |
69 | To mark spam
70 | Make a POST request to the ENDPOINT
71 |
72 |
73 | Declaration - This application is intended for use by reciepent only. Any use in professional manner or to harm anyone or any organization doesn't relate to me and can be considered as illegal.
--------------------------------------------------------------------------------
/data/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/data/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path, include
2 | from .views import home_view
3 | urlpatterns = [
4 | path('', home_view),
5 | path('api/data/', include("data.api.urls")),
6 |
7 | ]
8 |
--------------------------------------------------------------------------------
/data/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 | # Create your views here.
4 | def home_view(request):
5 | return render(request,"home.html")
--------------------------------------------------------------------------------
/db.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/db.sqlite3
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'truecaller.settings')
9 | try:
10 | from django.core.management import execute_from_command_line
11 | except ImportError as exc:
12 | raise ImportError(
13 | "Couldn't import Django. Are you sure it's installed and "
14 | "available on your PYTHONPATH environment variable? Did you "
15 | "forget to activate a virtual environment?"
16 | ) from exc
17 | execute_from_command_line(sys.argv)
18 |
19 |
20 | if __name__ == '__main__':
21 | main()
22 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | certifi==2019.9.11
2 | chardet==3.0.4
3 | Django==2.2.8
4 | django-filter==2.2.0
5 | djangorestframework==3.10.3
6 | djangorestframework-jwt==1.11.0
7 | idna==2.8
8 | Markdown==3.1.1
9 | PyJWT==1.7.1
10 | pytz==2019.3
11 | requests==2.22.0
12 | sqlparse==0.3.0
13 | urllib3==1.25.7
14 |
--------------------------------------------------------------------------------
/truecaller/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__init__.py
--------------------------------------------------------------------------------
/truecaller/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/truecaller/__pycache__/putdata.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/putdata.cpython-36.pyc
--------------------------------------------------------------------------------
/truecaller/__pycache__/settings.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/settings.cpython-36.pyc
--------------------------------------------------------------------------------
/truecaller/__pycache__/urls.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/urls.cpython-36.pyc
--------------------------------------------------------------------------------
/truecaller/__pycache__/wsgi.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/wsgi.cpython-36.pyc
--------------------------------------------------------------------------------
/truecaller/data.csv:
--------------------------------------------------------------------------------
1 | Mobile_Number,Name,Email
2 | 917053000273,Sunita,
3 | 917053001487,Shobhit,
4 | 917053001479,Govind Govind,singhgovind01420@gmail.com
5 | 917053001460,Arman Khan,
6 | 917053001433,Sandhya Sharma,
7 | 917053001432,Rahul Sharma,rahul.sharma.71.rs@gmail.com
8 | 917053001422,Manoj Kumar,manojprajapati7053@gmail.com
9 | 917053001413,Ail Abid,aliabid47422@gmail.com
10 | 917053001410,Preeti Sain,preetisain241996@gmail.com
11 | 917053001378,Abhishek Verma,abhishek.nature16@gmail.com
12 | 917053001347,Chulbul Pandey,
13 | 917053001343,Armaan Ali,manjeetroy7867@gmail.com
14 | 917053001334,Anuj Rai Spice Jet,
15 | 917053001333,Kishan Singh,
16 | 917053001319,Mamtesh Sharma,uditupadhyay29@gmail.com
17 | 917053001314,Ajay K,ajayk.kumar91@gmail.com
18 | 917053001312,Alok Singh,
19 | 917053001300,Abhishek Sharma (kush Pandit),
20 | 917053001298,Cma Neeraj,
21 | 917053001297,Suresh Pal,suresh.pal0707@gmail.com
22 | 917053001268,Shailendra Singh,shailendrasbscet@gmail.com
23 | 917053001250,Rohit,
24 | 917053001244,Vipin Shop,
25 | 917053001209,Keshav Jha,keshavkrjha149@gmail.com
26 | 917053001207,Nidhi,
27 | 917053001199,Sachin Sanjay Enclave,
28 | 917053001193,Pradeep Das,pradeepdas180@gmail.com
29 | 917053001170,Cma Shalini,
30 | 917053001153,Soma Raj,
31 | 917053001147,Rajeev Kumar,rbrajeevkumar005@gmail.com
32 | 917053001139,Indu,
33 | 917053001133,Abhay Singh,abhay28singh@gmail.com
34 | 917053001128,Golu Kk,
35 | 917053001113,Dayaram Choraai,
36 | 917053001109,Roshan,
37 | 917053001101,Kapil,
38 | 917053001069,Naina Ranjna,
39 | 917053001064,Vishal Chaturvedi,
40 | 917053001045,Rishi Trolley,
41 | 917053001037,Sudhirkumar Sudhirkumar,
42 | 917053001019,Sumit Kumar,sumitkumard1671985@gmail.com
43 | 917053001008,Aniket,
44 | 917053001003,Basant Kumar,
45 | 917053001002,Papa G,yoginderkmr18@gmail.com
46 | 917053000980,Kamal Kashyap,kamalkashyap4000@gmail.com
47 | 917053000976,Aircel977 Delm977,
48 | 917053000942,Pankaj Office Larka,
49 | 917053000938,Preeti Singh,
50 | 917053000936,Satya Parkash Prasad,iipl.satyaparkash@gmail.com
51 | 917053000912,Vidhi,
52 | 917053000909,Sikka Pardhan,
53 | 917053000908,Dagar Shab,
54 | 917053000894,Miister Potterhead,
55 | 917053000888,Kamal Kamal,
56 | 917053000879,Ruby,
57 | 917053000868,India Gurgaon,
58 | 917053000858,Anand Driver,
59 | 917053000857,Barkte Hr,
60 | 917053000850,Mukesh,
61 | 917053000849,Salman Syed,mohdsksalman@gmail.com
62 | 917053000845,Ramkesh Gurjar Bainsla,
63 | 917053000840,Shweta Amarjeet Bhabhiji,
64 | 917053000836,Kundan Kumar,kumarkundan7053@gmail.com
65 | 917053000833,Gurucharan Singh,
66 | 917053000821,Rinki Bkp,
67 | 917053000819,Jagram Singh,jagramsingh63487@gmail.com
68 | 917053000808,Vijay Mcd,
69 | 917053000806,Samrat Guru,
70 | 917053000786,Gurgaon Airtel,
71 | 917053000780,Raju 2,
72 | 917053000777,Kamal Kamal,kamalkamalkamalkamal087@gmail.com
73 | 917053000768,Mr. Siddiqui,
74 | 917053000756,Pardeep Gujjar,
75 | 917053000751,Rakesh,
76 | 917053000750,Sumit Mama,
77 | 917053000743,Sameer Sameer,
78 | 917053000736,Sunder Khandiya,sunderkhandiyas@gmail.com
79 | 917053000727,Riya,
80 | 917053000702,Shadab Rangrezz,
81 | 917053000700,Aircel701 Delm701,
82 | 917053000688,Shruti 2,
83 | 917053000680,Nnnn. Khaan,
84 | 917053000678,Amrik Singh,amriks841@gmail.com
85 | 917053000672,Vaseem,
86 | 917053000666,Rishab Singh,6525jatin@gmail.com
87 | 917053000656,Rajender 3,
88 | 917053000648,Tinku,
89 | 917053000645,No Naah!!,
90 | 917053000619,Rajbala Mami,
91 | 917053000618,Tarun Ahuja,pals9992@gmail.com
92 | 917053000600,Aircel601 Delm601,
93 | 917053000594,Neetesh Kumar Raj,
94 | 917053000593,Chandra Ji Airport,
95 |
--------------------------------------------------------------------------------
/truecaller/putdata.py:
--------------------------------------------------------------------------------
1 |
2 | def get_data():
3 | import csv
4 | # csv file name
5 | filename = "data.csv"
6 |
7 | # initializing the titles and rows list
8 | fields = []
9 | rows = []
10 |
11 | # reading csv file
12 | with open(filename, 'r') as csvfile:
13 | # creating a csv reader object
14 | csvreader = csv.reader(csvfile)
15 |
16 | # extracting field names through first row
17 | fields = next(csvreader)
18 |
19 | # extracting each data row one by one
20 | for row in csvreader:
21 | rows.append(row)
22 | return fields,rows
23 | # printing first 5 rows
24 | print('\nFirst 5 rows are:\n')
25 | for row in rows[:5]:
26 | # parsing each column of a row
27 | for col in row:
28 | print("%10s"%col),
29 | print('\n')
--------------------------------------------------------------------------------
/truecaller/restconf/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/restconf/__init__.py
--------------------------------------------------------------------------------
/truecaller/restconf/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/restconf/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/truecaller/restconf/__pycache__/main.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/restconf/__pycache__/main.cpython-36.pyc
--------------------------------------------------------------------------------
/truecaller/restconf/main.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | REST_FRAMEWORK = {
3 | 'DEFAULT_AUTHENTICATION_CLASSES': (
4 | 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
5 | 'rest_framework.authentication.SessionAuthentication',
6 | ),
7 | 'DEFAULT_PERMISSION_CLASSES':(
8 | 'rest_framework.permissions.IsAuthenticated',
9 | )
10 | }
11 |
12 | JWT_AUTH = {
13 | 'JWT_ENCODE_HANDLER':
14 | 'rest_framework_jwt.utils.jwt_encode_handler',
15 |
16 | 'JWT_DECODE_HANDLER':
17 | 'rest_framework_jwt.utils.jwt_decode_handler',
18 |
19 | 'JWT_PAYLOAD_HANDLER':
20 | 'rest_framework_jwt.utils.jwt_payload_handler',
21 |
22 | 'JWT_PAYLOAD_GET_USER_ID_HANDLER':
23 | 'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
24 |
25 | 'JWT_RESPONSE_PAYLOAD_HANDLER':
26 | # 'rest_framework_jwt.utils.jwt_response_payload_handler',
27 | 'accounts.api.utils.jwt_response_payload_handler',
28 |
29 | 'JWT_ALLOW_REFRESH': True,
30 | 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
31 |
32 | 'JWT_AUTH_HEADER_PREFIX': 'JWT',
33 | 'JWT_AUTH_COOKIE': None,
34 |
35 | }
--------------------------------------------------------------------------------
/truecaller/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for truecaller project.
3 |
4 | Generated by 'django-admin startproject' using Django 2.2.7.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.2/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/2.2/ref/settings/
11 | """
12 |
13 | import os
14 |
15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'hrpuk=3vgiqi=it*x+(g$fu7o%p%mjmpsg!_x$s$bnl7y7n22b'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 | AUTH_USER_MODEL = 'accounts.MyUser'
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | # third-party
41 | 'rest_framework',
42 |
43 | # local
44 | 'data',
45 | 'accounts'
46 | ]
47 |
48 | MIDDLEWARE = [
49 | 'django.middleware.security.SecurityMiddleware',
50 | 'django.contrib.sessions.middleware.SessionMiddleware',
51 | 'django.middleware.common.CommonMiddleware',
52 | 'django.middleware.csrf.CsrfViewMiddleware',
53 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
54 | 'django.contrib.messages.middleware.MessageMiddleware',
55 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
56 | ]
57 |
58 | ROOT_URLCONF = 'truecaller.urls'
59 |
60 | TEMPLATES = [
61 | {
62 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
63 | 'DIRS': [],
64 | 'APP_DIRS': True,
65 | 'OPTIONS': {
66 | 'context_processors': [
67 | 'django.template.context_processors.debug',
68 | 'django.template.context_processors.request',
69 | 'django.contrib.auth.context_processors.auth',
70 | 'django.contrib.messages.context_processors.messages',
71 | ],
72 | },
73 | },
74 | ]
75 |
76 | WSGI_APPLICATION = 'truecaller.wsgi.application'
77 |
78 |
79 | # Database
80 | # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
81 |
82 | DATABASES = {
83 | 'default': {
84 | 'ENGINE': 'django.db.backends.sqlite3',
85 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
86 | }
87 | }
88 |
89 |
90 | # Password validation
91 | # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
92 |
93 | AUTH_PASSWORD_VALIDATORS = [
94 | {
95 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
96 | },
97 | {
98 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
99 | },
100 | {
101 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
102 | },
103 | {
104 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
105 | },
106 | ]
107 |
108 |
109 | # Internationalization
110 | # https://docs.djangoproject.com/en/2.2/topics/i18n/
111 |
112 | LANGUAGE_CODE = 'en-us'
113 |
114 | TIME_ZONE = 'UTC'
115 |
116 | USE_I18N = True
117 |
118 | USE_L10N = True
119 |
120 | USE_TZ = True
121 |
122 |
123 | # Static files (CSS, JavaScript, Images)
124 | # https://docs.djangoproject.com/en/2.2/howto/static-files/
125 |
126 | STATIC_URL = '/static/'
127 |
128 | from truecaller.restconf.main import *
--------------------------------------------------------------------------------
/truecaller/urls.py:
--------------------------------------------------------------------------------
1 | """truecaller URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/2.2/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path, include
18 |
19 | urlpatterns = [
20 | path('admin/', admin.site.urls),
21 | path('api/auth/', include("accounts.urls")),
22 | path('', include("data.urls")),
23 |
24 | ]
25 |
--------------------------------------------------------------------------------
/truecaller/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for truecaller project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'truecaller.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------